Пример #1
0
		// ---------------------------------------------------------------------------

		// No explicit destructors in C#

		// ---------------------------------------------------------------------------

		public bool ReadFromFile(String FileName)
		{
   
			APE_HEADER APE = new APE_HEADER();				// common header
			APE_HEADER_OLD APE_OLD = new APE_HEADER_OLD();	// old header   <= 3.97
			APE_HEADER_NEW APE_NEW = new APE_HEADER_NEW();	// new header   >= 3.98
			APE_DESCRIPTOR APE_DESC = new APE_DESCRIPTOR(); // extra header >= 3.98

			FileStream fs = null;
			BinaryReader SourceFile = null;

			int BlocksPerFrame;
			bool LoadSuccess;
			int TagSize;
			bool result = false;
   
			FResetData();
   
			// load tags first
			FID3v2.ReadFromFile(FileName);
			FID3v1.ReadFromFile(FileName);
			FAPEtag.ReadFromFile(FileName);
   
			// calculate total tag size
			TagSize = 0;
			if (FID3v1.Exists) TagSize += 128;
			if (FID3v2.Exists) TagSize += FID3v2.Size;
			if (FAPEtag.Exists) TagSize += FAPEtag.Size;
   
			// reading data from file
			LoadSuccess = false;

			try
			{
				try
				{         
					fs = new FileStream(FileName, FileMode.Open, FileAccess.Read);
					fs.Lock(0,fs.Length);
					SourceFile = new BinaryReader(fs);
					FFileSize = fs.Length;

					// seek past id3v2-tag
					if (FID3v2.Exists)
					{
						fs.Seek(FID3v2.Size, SeekOrigin.Begin);
					}
					// Read APE Format Header         
					Array.Clear(APE.cID,0,APE.cID.Length);
					APE.nVersion = 0;
	  
					APE.cID = SourceFile.ReadChars(4);
					APE.nVersion = SourceFile.ReadUInt16();

					if ( Utils.StringEqualsArr("MAC ",APE.cID) )
					{            
						FVersion = APE.nVersion;

						FVersionStr = ((double)FVersion / 1000).ToString().Substring(0,4); //Str(FVersion / 1000 : 4 : 2, FVersionStr);
            
						// Load New Monkey's Audio Header for version >= 3.98
						if (APE.nVersion >= 3980) 
						{
							APE_DESC.padded = 0;
							APE_DESC.nDescriptorBytes = 0;
							APE_DESC.nHeaderBytes = 0;
							APE_DESC.nSeekTableBytes = 0;
							APE_DESC.nHeaderDataBytes = 0;
							APE_DESC.nAPEFrameDataBytes = 0;
							APE_DESC.nAPEFrameDataBytesHigh = 0;
							APE_DESC.nTerminatingDataBytes = 0;
							Array.Clear(APE_DESC.cFileMD5,0,APE_DESC.cFileMD5.Length);

							APE_DESC.padded = SourceFile.ReadUInt16();
							APE_DESC.nDescriptorBytes = SourceFile.ReadUInt32();
							APE_DESC.nHeaderBytes = SourceFile.ReadUInt32();
							APE_DESC.nSeekTableBytes = SourceFile.ReadUInt32();
							APE_DESC.nHeaderDataBytes = SourceFile.ReadUInt32();
							APE_DESC.nAPEFrameDataBytes = SourceFile.ReadUInt32();
							APE_DESC.nAPEFrameDataBytesHigh = SourceFile.ReadUInt32();
							APE_DESC.nTerminatingDataBytes = SourceFile.ReadUInt32();
							APE_DESC.cFileMD5 = SourceFile.ReadBytes(16);

							// seek past description header
							if (APE_DESC.nDescriptorBytes != 52) fs.Seek(APE_DESC.nDescriptorBytes - 52, SeekOrigin.Current);
							// load new ape_header
							if (APE_DESC.nHeaderBytes > 24/*sizeof(APE_NEW)*/) APE_DESC.nHeaderBytes = 24/*sizeof(APE_NEW)*/;
                  				
							APE_NEW.nCompressionLevel = 0;
							APE_NEW.nFormatFlags = 0;
							APE_NEW.nBlocksPerFrame = 0;
							APE_NEW.nFinalFrameBlocks = 0;
							APE_NEW.nTotalFrames = 0;
							APE_NEW.nBitsPerSample = 0;
							APE_NEW.nChannels = 0;
							APE_NEW.nSampleRate = 0;

							APE_NEW.nCompressionLevel = SourceFile.ReadUInt16();
							APE_NEW.nFormatFlags = SourceFile.ReadUInt16();
							APE_NEW.nBlocksPerFrame = SourceFile.ReadUInt32();
							APE_NEW.nFinalFrameBlocks = SourceFile.ReadUInt32();
							APE_NEW.nTotalFrames = SourceFile.ReadUInt32();
							APE_NEW.nBitsPerSample = SourceFile.ReadUInt16();
							APE_NEW.nChannels = SourceFile.ReadUInt16();
							APE_NEW.nSampleRate = SourceFile.ReadUInt32();
				
							// based on MAC SDK 3.98a1 (APEinfo.h)
							FSampleRate       = (int)APE_NEW.nSampleRate;
							FChannels         = APE_NEW.nChannels;
							FFormatFlags      = APE_NEW.nFormatFlags;
							FBits             = APE_NEW.nBitsPerSample;
							FCompressionMode  = APE_NEW.nCompressionLevel;
							// calculate total uncompressed samples
							if (APE_NEW.nTotalFrames > 0)
							{
								FTotalSamples     = (long)(APE_NEW.nBlocksPerFrame) *
									(long)(APE_NEW.nTotalFrames-1) +
									(long)(APE_NEW.nFinalFrameBlocks);
							}
							LoadSuccess = true;
						}
						else 
						{
							// Old Monkey <= 3.97               

							APE_OLD.nCompressionLevel = 0;
							APE_OLD.nFormatFlags = 0;
							APE_OLD.nChannels = 0;
							APE_OLD.nSampleRate = 0;
							APE_OLD.nHeaderBytes = 0;
							APE_OLD.nTerminatingBytes = 0;
							APE_OLD.nTotalFrames = 0;
							APE_OLD.nFinalFrameBlocks = 0;
							APE_OLD.nInt = 0;

							APE_OLD.nCompressionLevel = SourceFile.ReadUInt16();
							APE_OLD.nFormatFlags = SourceFile.ReadUInt16();
							APE_OLD.nChannels = SourceFile.ReadUInt16();
							APE_OLD.nSampleRate = SourceFile.ReadUInt32();
							APE_OLD.nHeaderBytes = SourceFile.ReadUInt32();
							APE_OLD.nTerminatingBytes = SourceFile.ReadUInt32();
							APE_OLD.nTotalFrames = SourceFile.ReadUInt32();
							APE_OLD.nFinalFrameBlocks = SourceFile.ReadUInt32();
							APE_OLD.nInt = SourceFile.ReadInt32();				

							FCompressionMode  = APE_OLD.nCompressionLevel;
							FSampleRate       = (int)APE_OLD.nSampleRate;
							FChannels         = APE_OLD.nChannels;
							FFormatFlags      = APE_OLD.nFormatFlags;
							FBits = 16;
							if ( (APE_OLD.nFormatFlags & MONKEY_FLAG_8_BIT ) != 0) FBits =  8;
							if ( (APE_OLD.nFormatFlags & MONKEY_FLAG_24_BIT) != 0) FBits = 24;

							FHasSeekElements  = ( (APE_OLD.nFormatFlags & MONKEY_FLAG_PEAK_LEVEL   )  != 0);
							FWavNotStored     = ( (APE_OLD.nFormatFlags & MONKEY_FLAG_SEEK_ELEMENTS) != 0);
							FHasPeakLevel     = ( (APE_OLD.nFormatFlags & MONKEY_FLAG_WAV_NOT_STORED) != 0);
                  
							if (FHasPeakLevel)
							{
								FPeakLevel        = (uint)APE_OLD.nInt;
								FPeakLevelRatio   = (FPeakLevel / (1 << FBits) / 2.0) * 100.0;
							}

							// based on MAC_SDK_397 (APEinfo.cpp)
							if (FVersion >= 3950) 
								BlocksPerFrame = 73728 * 4;
							else if ( (FVersion >= 3900) || ((FVersion >= 3800) && (MONKEY_COMPRESSION_EXTRA_HIGH == APE_OLD.nCompressionLevel)) )
								BlocksPerFrame = 73728;
							else
								BlocksPerFrame = 9216;

							// calculate total uncompressed samples
							if (APE_OLD.nTotalFrames>0)
							{
								FTotalSamples =  (long)(APE_OLD.nTotalFrames-1) *
									(long)(BlocksPerFrame) +
									(long)(APE_OLD.nFinalFrameBlocks);
							}
							LoadSuccess = true;
               
						}
						if (LoadSuccess) 
						{
							// compression profile name
							if ( (0 == (FCompressionMode % 1000)) && (FCompressionMode<=6000) )
							{
								FCompressionModeStr = MONKEY_COMPRESSION[FCompressionMode / 1000]; // int division
							}
							else 
							{
								FCompressionModeStr = FCompressionMode.ToString();
							}
							// length
							if (FSampleRate>0) FDuration = ((double)FTotalSamples / FSampleRate);
							// average bitrate
							if (FDuration>0) FBitrate = 8*(FFileSize - (long)(TagSize)) / (FDuration*1000);
							// some extra sanity checks
							FValid   = ((FBits>0) && (FSampleRate>0) && (FTotalSamples>0) && (FChannels>0));
							result   = FValid;
						}
					}
				}
				finally
				{
					if (fs != null)
					{
						fs.Unlock(0,fs.Length);
						if (SourceFile != null) SourceFile.Close();
					}
				}
			}
			catch (Exception e)
			{
				System.Console.WriteLine(e.StackTrace);
				result = false;
			}
			return result;
		}