public MpegHeader(MpegHeader header) { if (header != null) { isValid = header.IsValid; version = header.Version; layer = header.Layer; protectionEnabled = header.ProtectionEnabled; bitrate = header.Bitrate; sampleRate = header.SampleRate; isPadded = header.IsPadded; channelMode = header.ChannelMode; isCopyrighted = header.IsCopyrighted; isOriginal = header.IsOriginal; frameLength = header.FrameLength; } }
////////////////////////////////////////////////////////////////////////// // 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; }