private static VBRData getFhGInfo(BufferedBinaryReader source) { VBRData result = new VBRData(); byte[] data = new byte[9]; // Extract FhG VBR info at given position result.Found = true; result.ID = VBR_ID_FHG.ToCharArray(); source.Seek(5, SeekOrigin.Current); source.Read(data, 0, 9); result.Scale = data[0]; result.Bytes = data[1] * 0x1000000 + data[2] * 0x10000 + data[3] * 0x100 + data[4]; result.Frames = data[5] * 0x1000000 + data[6] * 0x10000 + data[7] * 0x100 + data[8]; result.VendorID = ""; return(result); }
private static VBRData findVBR(BufferedBinaryReader source, long position) { VBRData result; byte[] data = new byte[4]; // Check for VBR header at given position source.Seek(position, SeekOrigin.Begin); source.Read(data, 0, 4); string vbrId = Utils.Latin1Encoding.GetString(data); if (VBR_ID_XING.Equals(vbrId)) { result = getXingInfo(source); } else if (VBR_ID_FHG.Equals(vbrId)) { result = getFhGInfo(source); } else { result = new VBRData(); result.Reset(); } return(result); }
// --------------------------------------------------------------------------- private VBRData FindVBR(ushort Index, byte[] Data) { VBRData result = new VBRData(); // Check for VBR header at given position result.Found = false; Array.Clear(result.ID, 0, result.ID.Length); result.Frames = 0; result.Bytes = 0; result.Scale = 0; result.VendorID = ""; char[] tempArray = new char[4] { (char)Data[Index], (char)Data[Index + 1], (char)Data[Index + 2], (char)Data[Index + 3] }; if (Utils.StringEqualsArr(VBR_ID_XING, tempArray)) { result = GetXingInfo(Index, Data); } if (Utils.StringEqualsArr(VBR_ID_FHG, tempArray)) { result = GetFhGInfo(Index, Data); } return(result); }
private static VBRData getXingInfo(BufferedBinaryReader source) { VBRData result = new VBRData(); byte[] data = new byte[8]; result.Found = true; result.ID = VBR_ID_XING.ToCharArray(); source.Seek(4, SeekOrigin.Current); source.Read(data, 0, 8); result.Frames = data[0] * 0x1000000 + data[1] * 0x10000 + data[2] * 0x100 + data[3]; result.Bytes = data[4] * 0x1000000 + data[5] * 0x10000 + data[6] * 0x100 + data[7]; source.Seek(103, SeekOrigin.Current); result.Scale = source.ReadByte(); source.Read(data, 0, 8); result.VendorID = Utils.Latin1Encoding.GetString(data, 0, 8); return(result); }
// --------------------------------------------------------------------------- private VBRData GetFhGInfo(ushort Index, byte[] Data) { VBRData result = new VBRData(); // Extract FhG VBR info at given position result.Found = false; Array.Clear(result.ID, 0, result.ID.Length); result.Frames = 0; result.Bytes = 0; result.Scale = 0; result.VendorID = ""; result.Found = true; result.ID = VBR_ID_FHG.ToCharArray(); result.Scale = Data[Index + 9]; result.Bytes = Data[Index + 10] * 0x1000000 + Data[Index + 11] * 0x10000 + Data[Index + 12] * 0x100 + Data[Index + 13]; result.Frames = Data[Index + 14] * 0x1000000 + Data[Index + 15] * 0x10000 + Data[Index + 16] * 0x100 + Data[Index + 17]; return(result); }
// --------------------------------------------------------------------------- private FrameData FindFrame(byte[] Data, ref VBRData oVBR) { byte[] HeaderData = new byte[4]; FrameData result = new FrameData(); // Search for valid frame //FillChar(result, sizeof(result), 0); result.Found = false; result.Position = 0; result.Size = 0; result.Xing = false; Array.Clear(result.Data, 0, result.Data.Length); result.VersionID = 0; result.LayerID = 0; result.ProtectionBit = false; result.BitRateID = 0; result.SampleRateID = 0; result.PaddingBit = false; result.PrivateBit = false; result.ModeID = 0; result.ModeExtensionID = 0; result.CopyrightBit = false; result.OriginalBit = false; result.EmphasisID = 0; Array.Copy(Data, HeaderData, 4); for (uint iterator = 0; iterator <= Data.Length - MAX_MPEG_FRAME_LENGTH; iterator++) { // Decode data if frame header found if (IsFrameHeader(HeaderData)) { DecodeHeader(HeaderData, ref result); // Check for next frame and try to find VBR header if (ValidFrameAt((ushort)(iterator + GetFrameLength(result)), Data)) { result.Found = true; result.Position = (int)iterator; result.Size = GetFrameLength(result); result.Xing = IsXing((ushort)(iterator + 4), Data); oVBR = FindVBR((ushort)(iterator + GetVBRDeviation(result)), Data); break; } } // Prepare next data block HeaderData[0] = HeaderData[1]; HeaderData[1] = HeaderData[2]; HeaderData[2] = HeaderData[3]; HeaderData[3] = Data[iterator + 4]; } return(result); }
// --------------------------------------------------------------------------- private VBRData GetXingInfo(ushort Index, byte[] Data) { VBRData result = new VBRData(); // Extract Xing VBR info at given position result.Found = false; Array.Clear(result.ID, 0, result.ID.Length); result.Frames = 0; result.Bytes = 0; result.Scale = 0; result.VendorID = ""; result.Found = true; result.ID = VBR_ID_XING.ToCharArray(); result.Frames = Data[Index + 8] * 0x1000000 + Data[Index + 9] * 0x10000 + Data[Index + 10] * 0x100 + Data[Index + 11]; result.Bytes = Data[Index + 12] * 0x1000000 + Data[Index + 13] * 0x10000 + Data[Index + 14] * 0x100 + Data[Index + 15]; result.Scale = Data[Index + 119]; // Vendor ID can be not present char[] tempArray = new char[8] { (char)(Data[Index + 120]), (char)(Data[Index + 121]), (char)(Data[Index + 122]), (char)(Data[Index + 123]), (char)(Data[Index + 124]), (char)(Data[Index + 125]), (char)(Data[Index + 126]), (char)(Data[Index + 127]) }; result.VendorID = new String(tempArray); return(result); }
private static FrameHeader findFrame(BufferedBinaryReader source, ref VBRData oVBR, SizeInfo sizeInfo) { byte[] headerData = new byte[4]; FrameHeader result = new FrameHeader(); source.Read(headerData, 0, 4); result.Found = isValidFrameHeader(headerData); /* * Many things can actually be found before a proper MP3 header : * - Padding with 0x55, 0xAA and even 0xFF bytes * - RIFF header declaring either MP3 or WAVE data * - Xing encoder-specific frame * - One of the above with a few "parasite" bytes before their own header * * The most solid way to deal with all of them is to "scan" the file until proper MP3 header is found. * This method may not the be fastest, but ensures audio data is actually detected, whatever garbage lies before */ if (!result.Found) { // "Quick win" for files starting with padding bytes // 4 identical bytes => MP3 starts with padding bytes => Skip padding if ((headerData[0] == headerData[1]) && (headerData[1] == headerData[2]) && (headerData[2] == headerData[3])) { // Scan the whole padding until it stops while (headerData[0] == source.ReadByte()) { ; } source.Seek(-1, SeekOrigin.Current); // If padding uses 0xFF bytes, take one step back in case MP3 header lies there if (0xFF == headerData[0]) { source.Seek(-1, SeekOrigin.Current); } source.Read(headerData, 0, 4); result.Found = isValidFrameHeader(headerData); } // Blindly look for the MP3 header if (!result.Found) { source.Seek(-4, SeekOrigin.Current); long limit = sizeInfo.ID3v2Size + (long)Math.Round((source.Length - sizeInfo.ID3v2Size) * 0.3); // Look for the beginning of the MP3 header (2nd byte is variable, so it cannot be searched that way) while (!result.Found && source.Position < limit) { while (0xFF != source.ReadByte() && source.Position < limit) { ; } source.Seek(-1, SeekOrigin.Current); source.Read(headerData, 0, 4); result.Found = isValidFrameHeader(headerData); // Valid header candidate found // => let's see if it is a legit MP3 header by using its Size descriptor to find the next header if (result.Found) { result.LoadFromByteArray(headerData); result.Position = source.Position - 4; result.Size = getFrameSize(result); byte[] nextHeaderData = new byte[4]; source.Seek(result.Position + result.Size, SeekOrigin.Begin); source.Read(nextHeaderData, 0, 4); result.Found = isValidFrameHeader(nextHeaderData); if (result.Found) { source.Seek(result.Position + 4, SeekOrigin.Begin); // Go back to header candidate position break; } else { // Restart looking for a candidate source.Seek(result.Position + 1, SeekOrigin.Begin); } } else { source.Seek(-3, SeekOrigin.Current); } } } } if (result.Found) { result.LoadFromByteArray(headerData); result.Position = source.Position - 4; // result.Xing = isXing(i + 4, Data); // Will look into it when encoder ID is needed by upper interfaces // Look for VBR signature oVBR = findVBR(source, result.Position + getVBRDeviation(result)); } return(result); }
// --------------------------------------------------------------------------- private FrameData FindFrame(byte[] Data, ref VBRData oVBR) { byte[] HeaderData = new byte[4]; FrameData result = new FrameData(); // Search for valid frame //FillChar(result, sizeof(result), 0); result.Found = false; result.Position = 0; result.Size = 0; result.Xing = false; Array.Clear(result.Data,0,result.Data.Length); result.VersionID = 0; result.LayerID = 0; result.ProtectionBit = false; result.BitRateID = 0; result.SampleRateID = 0; result.PaddingBit = false; result.PrivateBit = false; result.ModeID = 0; result.ModeExtensionID = 0; result.CopyrightBit = false; result.OriginalBit = false; result.EmphasisID = 0; Array.Copy(Data, HeaderData, 4); for (uint iterator=0; iterator <= Data.Length - MAX_MPEG_FRAME_LENGTH; iterator++) { // Decode data if frame header found if ( IsFrameHeader(HeaderData) ) { DecodeHeader(HeaderData, ref result); // Check for next frame and try to find VBR header if ( ValidFrameAt((ushort)(iterator + GetFrameLength(result)), Data) ) { result.Found = true; result.Position = (int)iterator; result.Size = GetFrameLength(result); result.Xing = IsXing((ushort)(iterator + 4), Data); oVBR = FindVBR((ushort)(iterator + GetVBRDeviation(result)), Data); break; } } // Prepare next data block HeaderData[0] = HeaderData[1]; HeaderData[1] = HeaderData[2]; HeaderData[2] = HeaderData[3]; HeaderData[3] = Data[iterator + 4]; } return result; }
// --------------------------------------------------------------------------- private VBRData FindVBR(ushort Index, byte[] Data) { VBRData result = new VBRData(); // Check for VBR header at given position result.Found = false; Array.Clear(result.ID,0,result.ID.Length); result.Frames = 0; result.Bytes = 0; result.Scale = 0; result.VendorID = ""; char[] tempArray = new char[4] { (char)Data[Index], (char)Data[Index+1], (char)Data[Index+2], (char)Data[Index+3] }; if ( Utils.StringEqualsArr(VBR_ID_XING,tempArray) ) result = GetXingInfo(Index, Data); if ( Utils.StringEqualsArr(VBR_ID_FHG,tempArray) ) result = GetFhGInfo(Index, Data); return result; }
// --------------------------------------------------------------------------- private VBRData GetFhGInfo(ushort Index, byte[] Data) { VBRData result = new VBRData(); // Extract FhG VBR info at given position result.Found = false; Array.Clear(result.ID,0,result.ID.Length); result.Frames = 0; result.Bytes = 0; result.Scale = 0; result.VendorID = ""; result.Found = true; result.ID = VBR_ID_FHG.ToCharArray(); result.Scale = Data[Index + 9]; result.Bytes = Data[Index + 10] * 0x1000000 + Data[Index + 11] * 0x10000 + Data[Index + 12] * 0x100 + Data[Index + 13]; result.Frames = Data[Index + 14] * 0x1000000 + Data[Index + 15] * 0x10000 + Data[Index + 16] * 0x100 + Data[Index + 17]; return result; }
// --------------------------------------------------------------------------- private VBRData GetXingInfo(ushort Index, byte[] Data) { VBRData result = new VBRData(); // Extract Xing VBR info at given position result.Found = false; Array.Clear(result.ID,0,result.ID.Length); result.Frames = 0; result.Bytes = 0; result.Scale = 0; result.VendorID = ""; result.Found = true; result.ID = VBR_ID_XING.ToCharArray(); result.Frames = Data[Index + 8] * 0x1000000 + Data[Index + 9] * 0x10000 + Data[Index + 10] * 0x100 + Data[Index + 11]; result.Bytes = Data[Index + 12] * 0x1000000 + Data[Index + 13] * 0x10000 + Data[Index + 14] * 0x100 + Data[Index + 15]; result.Scale = Data[Index + 119]; // Vendor ID can be not present char[] tempArray = new char[8] { (char)(Data[Index + 120]), (char)(Data[Index + 121]), (char)(Data[Index + 122]), (char)(Data[Index + 123]), (char)(Data[Index + 124]), (char)(Data[Index + 125]), (char)(Data[Index + 126]), (char)(Data[Index + 127]) }; result.VendorID = new String(tempArray); return result; }