/// <summary> /// checks if the four bytes represent a valid header, /// if they are, will parse the values into Mp3Frame /// </summary> private static bool IsValidHeader(byte[] headerBytes, Mp3Frame frame) { if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0)) { // TODO: could do with a bitstream class here frame.MpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3); if (frame.MpegVersion == MpegVersion.Reserved) { //throw new FormatException("Unsupported MPEG Version"); return(false); } frame.MpegLayer = (MpegLayer)((headerBytes[1] & 0x06) >> 1); if (frame.MpegLayer == MpegLayer.Reserved) { return(false); } int layerIndex = frame.MpegLayer == MpegLayer.Layer1 ? 0 : frame.MpegLayer == MpegLayer.Layer2 ? 1 : 2; frame.CrcPresent = (headerBytes[1] & 0x01) == 0x00; frame.BitRateIndex = (headerBytes[2] & 0xF0) >> 4; if (frame.BitRateIndex == 15) { // invalid index return(false); } int versionIndex = frame.MpegVersion == Wave.MpegVersion.Version1 ? 0 : 1; frame.BitRate = bitRates[versionIndex, layerIndex, frame.BitRateIndex] * 1000; if (frame.BitRate == 0) { return(false); } int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2; if (sampleFrequencyIndex == 3) { return(false); } if (frame.MpegVersion == MpegVersion.Version1) { frame.SampleRate = sampleRatesVersion1[sampleFrequencyIndex]; } else if (frame.MpegVersion == MpegVersion.Version2) { frame.SampleRate = sampleRatesVersion2[sampleFrequencyIndex]; } else { // mpegVersion == MpegVersion.Version25 frame.SampleRate = sampleRatesVersion25[sampleFrequencyIndex]; } bool padding = (headerBytes[2] & 0x02) == 0x02; bool privateBit = (headerBytes[2] & 0x01) == 0x01; frame.ChannelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6); frame.ChannelExtension = (headerBytes[3] & 0x30) >> 4; if (frame.ChannelExtension != 0 && frame.ChannelMode != ChannelMode.JointStereo) { return(false); } frame.Copyright = (headerBytes[3] & 0x08) == 0x08; bool original = (headerBytes[3] & 0x04) == 0x04; int emphasis = (headerBytes[3] & 0x03); int nPadding = padding ? 1 : 0; frame.SampleCount = samplesPerFrame[versionIndex, layerIndex]; int coefficient = frame.SampleCount / 8; if (frame.MpegLayer == MpegLayer.Layer1) { frame.FrameLength = (coefficient * frame.BitRate / frame.SampleRate + nPadding) * 4; } else { frame.FrameLength = (coefficient * frame.BitRate) / frame.SampleRate + nPadding; } if (frame.FrameLength > MaxFrameLength) { return(false); } return(true); } return(false); }
/// <summary> /// Load Xing Header /// </summary> /// <param name="frame">Frame</param> /// <returns>Xing Header</returns> public static XingHeader LoadXingHeader(Mp3Frame frame) { XingHeader xingHeader = new XingHeader(); xingHeader.frame = frame; int offset = 0; if (frame.MpegVersion == MpegVersion.Version1) { if (frame.ChannelMode != ChannelMode.Mono) { offset = 32 + 4; } else { offset = 17 + 4; } } else if (frame.MpegVersion == MpegVersion.Version2) { if (frame.ChannelMode != ChannelMode.Mono) { offset = 17 + 4; } else { offset = 9 + 4; } } else { return(null); // throw new FormatException("Unsupported MPEG Version"); } if ((frame.RawData[offset + 0] == 'X') && (frame.RawData[offset + 1] == 'i') && (frame.RawData[offset + 2] == 'n') && (frame.RawData[offset + 3] == 'g')) { xingHeader.startOffset = offset; offset += 4; } else { return(null); } XingHeaderOptions flags = (XingHeaderOptions)ReadBigEndian(frame.RawData, offset); offset += 4; if ((flags & XingHeaderOptions.Frames) != 0) { xingHeader.framesOffset = offset; offset += 4; } if ((flags & XingHeaderOptions.Bytes) != 0) { xingHeader.bytesOffset = offset; offset += 4; } if ((flags & XingHeaderOptions.Toc) != 0) { xingHeader.tocOffset = offset; offset += 100; } if ((flags & XingHeaderOptions.VbrScale) != 0) { xingHeader.vbrScale = ReadBigEndian(frame.RawData, offset); offset += 4; } xingHeader.endOffset = offset; return(xingHeader); }