internal XingHeader ReadXingHeader() { var result = new XingHeader(); var headerId = new string(ReadChars(4)); if (headerId != "Xing" && headerId != "Info") { return(result); } // The flags DWORD indicates whether the frame and byte counts are present: uint flags = ReadUInt32BigEndian(); if ((flags & 0x1) == 1) { result.FrameCount = ReadUInt32BigEndian(); } if ((flags >> 1 & 0x1) == 1) { result.ByteCount = ReadUInt32BigEndian(); } return(result); }
public AudioInfo ReadAudioInfo(Stream stream) { Contract.Ensures(Contract.Result <AudioInfo>() != null); using (var reader = new FrameReader(stream)) { // Seek to the first valid frame header: FrameHeader frameHeader; do { reader.SeekToNextFrame(); frameHeader = new FrameHeader(reader.ReadBytes(4)); } while (!reader.VerifyFrameSync(frameHeader)); if (frameHeader.Layer != "III") { throw new UnsupportedAudioException(string.Format(CultureInfo.InvariantCulture, Resources.AudioInfoDecoderLayerError, frameHeader.Layer)); } // Seek past the CRC, if present: if (frameHeader.HasCrc) { reader.BaseStream.Seek(2, SeekOrigin.Current); } // Seek past the side information: reader.BaseStream.Seek(GetSideInfoLength(frameHeader.ChannelMode, frameHeader.MpegVersion), SeekOrigin.Current); // Read the XING header (if present): XingHeader xingHeader = reader.ReadXingHeader(); // If the byte count isn't present in the Xing header, use the file length: if (xingHeader.ByteCount == 0) { xingHeader.ByteCount = (uint)reader.BaseStream.Length; } // Calculate the (approximate) sample count: uint sampleCount = frameHeader.MpegVersion == "1" ? xingHeader.FrameCount * 1152 : xingHeader.FrameCount * 576; // Calculate the bitrate from the VBR header, or use the information from the first frame: int bitRate = sampleCount > 0 ? CalculateBitRate(xingHeader.ByteCount, sampleCount, frameHeader.SampleRate) : frameHeader.BitRate; var format = new StringBuilder(bitRate.ToString(CultureInfo.CurrentCulture)); format.Append("kbps MPEG "); format.Append(frameHeader.MpegVersion); format.Append(" Layer "); format.Append(frameHeader.Layer); return(new AudioInfo(format.ToString(), frameHeader.ChannelMode == "Mono" ? 1 : 2, 0, frameHeader.SampleRate, sampleCount)); } }