/// <summary> /// Initializes an object that reads informations from an mp3 file and stores them into the given database. /// </summary> public Id3SongCreator(ShauniDatabase database) { this.database = database; this.id3v1 = new ID3TagV1(); this.id3v2 = new ID3TagV2(); this.mpegHeader = new MpegHeader(); this.UseNewStandard = false; this.idwav = new IDWav(); }
public MpegFrame(Stream stream, MP3 mp3) { var streamPos = stream.Position; Header = new MpegHeader(stream); Data = new UInt8[0]; mp3.bitrate = 0; if (Header.FrameSync < 0xFFE || Header.LayerId == 0 || Header.BitrateIndex == 0 || Header.BitrateIndex == 15 || Header.FrequencyIndex == 3) { stream.Position = streamPos; throw new Exception("MPEG header is invalid!"); } else { if (Header.MpegId == 1) { mp3.bitrate = (1U << (Int32)(5U + ((UInt32)Header.BitrateIndex - 1U) / 4U)) + (((UInt32)Header.BitrateIndex - 1U & 3U) << (Int32)(3U + ((UInt32)Header.BitrateIndex - 1U) / 4U)); } else // MPEG-2 { Int32 bi = Header.BitrateIndex; Int32 bil = 4 + Header.BitrateIndex / 4; mp3.bitrate = (UInt32)(bi < 4 ? 8 * bi : (1 << bil) + ((bi & 3) == 0 ? 0 : (bi & 3) == 1 ? (1 << bil) : (bi & 3) == 2 ? (1 << bil) + ((1 << bil) >> 1) : (1 << bil) - ((1 << bil) >> 2) )); } } if (mp3.bitrate != 0) { var freq = new UInt16[] { 2205, 2400, 1600 }; mp3.samplingFreq = freq[Header.FrequencyIndex]; if (Header.MpegId == 1) // MPEG-1 { mp3.samplingFreq <<= 1; } mp3.frameSize = (mp3.bitrate * 14400) / mp3.samplingFreq; if (Header.ChannelMode == 3) { mp3.frameSize >>= 1; } mp3.frameSize -= 4U + (Header.ProtectionBit == 0 ? 2U : 0U) - Header.PaddingBit; mp3.frameHeaderOffset = (UInt64)stream.Position - 4UL - (Header.ProtectionBit == 0 ? 2UL : 0UL); if (stream.Position + mp3.frameSize > stream.Length) { throw new Exception("MPEG frame abruptly terminated"); } else { Data = new UInt8[mp3.frameSize]; stream.Read(Data, 0, (Int32)mp3.frameSize); } mp3.sumBitrate += mp3.bitrate; ++mp3.framesCount; } }
////////////////////////////////////////////////////////////////////////// // private methods ////////////////////////////////////////////////////////////////////////// private void Read () { // Since we've likely just looked for the ID3v1 tag, start at the end of the // file where we're least likely to have to have to move the disk head. long last = file.LastFrameOffset; if (last < 0) { TagLibDebugger.Debug ("Mpeg.Properties.Read() -- Could not find a valid last MPEG frame in the stream."); return; } file.Seek (last); MpegHeader last_header = new MpegHeader (file.ReadBlock (4)); long first = file.FirstFrameOffset; if (first < 0) { TagLibDebugger.Debug ("Mpeg.Properties.Read() -- Could not find a valid first MPEG frame in the stream."); return; } if(!last_header.IsValid) { long pos = last; while (pos > first) { pos = file.PreviousFrameOffset (pos); if(pos < 0) break; file.Seek (pos); MpegHeader header = new MpegHeader (file.ReadBlock (4)); if (header.IsValid) { last_header = header; last = pos; break; } } } // Now jump back to the front of the file and read what we need from there. file.Seek (first); MpegHeader first_header = new MpegHeader (file.ReadBlock (4)); if (!first_header.IsValid || !last_header.IsValid) { TagLibDebugger.Debug ("Mpeg.Properties.Read() -- Page headers were invalid."); return; } // Check for a Xing header that will help us in gathering information about a // VBR stream. int xing_header_offset = MpegXingHeader.XingHeaderOffset (first_header.Version, first_header.ChannelMode); file.Seek (first + xing_header_offset); MpegXingHeader xing_header = new MpegXingHeader (file.ReadBlock (16)); // Read the length and the bitrate from the Xing header. if(xing_header.IsValid && first_header.SampleRate > 0 && xing_header.TotalFrames > 0) { int [] block_size = {0, 384, 1152, 1152}; double time_per_frame = block_size [first_header.Layer]; time_per_frame = first_header.SampleRate > 0 ? time_per_frame / first_header.SampleRate : 0; duration = new TimeSpan((int)(time_per_frame * xing_header.TotalFrames) * TimeSpan.TicksPerSecond); bitrate = (int) (duration > TimeSpan.Zero ? ((xing_header.TotalSize * 8L) / duration.TotalSeconds) / 1000 : 0); } // Since there was no valid Xing header found, we hope that we're in a constant // bitrate file. // TODO: Make this more robust with audio property detection for VBR without a // Xing header. else if (first_header.FrameLength > 0 && first_header.Bitrate > 0) { int frames = (int) ((last - first) / first_header.FrameLength + 1); duration = TimeSpan.FromSeconds ((double) (first_header.FrameLength * frames) / (double) (first_header.Bitrate * 125) + 0.5); bitrate = first_header.Bitrate; } sample_rate = first_header.SampleRate; channels = first_header.ChannelMode == MpegChannelMode.SingleChannel ? 1 : 2; version = first_header.Version; layer = first_header.Layer; channel_mode = first_header.ChannelMode; is_copyrighted = first_header.IsCopyrighted; is_original = first_header.IsOriginal; }