// --------------------------------------------------------------------------- // 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; }
// --------------------------------------------------------------------------- // 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); }