public void AddFrame( MpegVersion version, MpegLayer layer, bool hasCRC, int frameSizeOffset, int frameSize) { Add(new Mp3Frame(BuildFrame( version, layer, hasCRC, frameSizeOffset, frameSize))); }
public void AddFreeFrame( MpegVersion version, MpegLayer layer, bool hasCRC, int frameSizeOffset, int frameSize) { byte[] buf = BuildFrame( version, layer, hasCRC, frameSizeOffset, frameSize); buf[2] &= 0x0F; Add(new Mp3Frame(buf)); }
private void GetLayer(params bool[] twoBits) { if (twoBits[0] && twoBits[1]) { this.mpegLayer = MpegLayer.I; } else if (twoBits[0] && !twoBits[1]) { this.mpegLayer = MpegLayer.II; } else if (!twoBits[0] && twoBits[1]) { this.mpegLayer = MpegLayer.III; } else if (!twoBits[0] && !twoBits[1]) { this.mpegLayer = MpegLayer.Reserved; } }
private static int GetSamplesPerFrame(MpegVersion mpegVersion, MpegLayer mpegLayer) { int tmpSamplesPerFrame = 0; switch (mpegVersion) { // MPEG-1 case MpegVersion.Mpeg1: if (mpegLayer == MpegLayer.Layer1) { tmpSamplesPerFrame = 384; } else if (mpegLayer == MpegLayer.Layer2 || mpegLayer == MpegLayer.Layer3) { tmpSamplesPerFrame = 1152; } break; // MPEG-2/2.5 case MpegVersion.Mpeg2: case MpegVersion.Mpeg25: if (mpegLayer == MpegLayer.Layer1) { tmpSamplesPerFrame = 384; } else if (mpegLayer == MpegLayer.Layer2) { tmpSamplesPerFrame = 1152; } else if (mpegLayer == MpegLayer.Layer3) { tmpSamplesPerFrame = 576; } break; } // end switch (ID) return(tmpSamplesPerFrame); }
/// <summary>Reads an MP3Frame from a stream</summary> /// <remarks>http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm /// has some good info</remarks> public Mp3Frame(Stream input) { BinaryReader reader = new BinaryReader(input); // try for a header long headerStartPosition = input.Position; byte[] headerBytes = reader.ReadBytes(4); // Added -jam to play wrapped mp3 files via RIFF headerBytes = CheckForRiff(input, reader, headerBytes); if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0)) { // TODO: could do with a bitstream class here mpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3); if (mpegVersion == MpegVersion.Reserved) { throw new FormatException("Unsupported MPEG Version"); } layer = (MpegLayer)((headerBytes[1] & 0x06) >> 1); if (layer != MpegLayer.Layer3) { throw new FormatException("Not an MP3"); } crcPresent = (headerBytes[1] & 0x01) == 0x00; int bitRateIndex = (headerBytes[2] & 0xF0) >> 4; bitRate = (mpegVersion == MpegVersion.Version1) ? bitRatesLayer3Version1[bitRateIndex] : bitRatesLayer3Version2[bitRateIndex]; int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2; if (mpegVersion == MpegVersion.Version1) sampleRate = sampleRatesVersion1[sampleFrequencyIndex]; else if (mpegVersion == MpegVersion.Version2) sampleRate = sampleRatesVersion2[sampleFrequencyIndex]; else // mpegVersion == MpegVersion.Version25 sampleRate = sampleRatesVersion25[sampleFrequencyIndex]; bool padding = (headerBytes[2] & 0x02) == 0x02; bool privateBit = (headerBytes[2] & 0x01) == 0x01; channelMode = (ChannelMode) ((headerBytes[3] & 0xC0) >> 6); int channelExtension = (headerBytes[3] & 0x30) >> 4; bool copyright = (headerBytes[3] & 0x08) == 0x80; bool original = (headerBytes[3] & 0x04) == 0x80; int emphasis = (headerBytes[3] & 0x03); frameLengthInBytes = (144 * 1000 * bitRate) / sampleRate + ((padding) ? 1 : 0); } else { input.Position = headerStartPosition; throw new FormatException("Not a recognised MP3 block"); } if (crcPresent) crc = reader.ReadInt16(); long dataStartPosition = input.Position; input.Position = headerStartPosition; rawData = reader.ReadBytes(frameLengthInBytes); }
/// <summary> /// Initializes a new instance of the <see cref="Mpeg"/> class. /// </summary> /// <param name="path">The full path of the file.</param> /// <param name="calculateBitrate">if set to <c>true</c> the bitrate will be calculated before the constructor returns.</param> public Mpeg(string path, bool calculateBitrate) { _fileName = path; using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { int tmpID3v2TagSize = ID3v2.GetTagSize(stream); stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); byte[] tmpFrameHeader = new byte[4]; bool acceptNullSamples = false; while (true) { int tmpByte = stream.ReadByte(); // keep as ReadByte while (tmpByte != 0xFF && tmpByte != -1) { tmpByte = stream.ReadByte(); // keep as ReadByte } if (tmpByte == -1) { if (acceptNullSamples) { throw new InvalidDataException(string.Format("'{0}': Can't find frame sync", path)); } stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); acceptNullSamples = true; continue; } tmpFrameHeader[0] = (byte)tmpByte; // Get frame header if (stream.Read(tmpFrameHeader, 1, 3) != 3) { throw new InvalidDataException(string.Format("'{0}': Invalid MPEG file; end of stream reached", path)); } // No sync if ((tmpFrameHeader[1] >> 5) != 0x07 || ((tmpFrameHeader[1] >> 1) & 0x03) == 0) // 2/18/05 - ignore reserved layer { stream.Seek(-3, SeekOrigin.Current); } else if (tmpFrameHeader[1] == 0xFF || ((tmpFrameHeader[1] >> 3) & 0x03) == 1) // 2/19/05 - more bad data { stream.Seek(-3, SeekOrigin.Current); } else { int tmpMpegID = (tmpFrameHeader[1] >> 3) & 0x03; int tmpLayerNum = (tmpFrameHeader[1] >> 1) & 0x03; int tmpFrequency = GetFrequency((MpegVersion)tmpMpegID, (tmpFrameHeader[2] >> 2) & 0x03); // Check for invalid frequency if (tmpFrequency == 0) { stream.Seek(-3, SeekOrigin.Current); continue; } int tmpSamplesPerFrame = GetSamplesPerFrame((MpegVersion)tmpMpegID, (MpegLayer)tmpLayerNum); int tmpUsesPadding = (tmpFrameHeader[2] >> 1) & 0x01; double tmpFrameSizeConst = 125.0 * tmpSamplesPerFrame / tmpFrequency; int tmpPaddingSize = (tmpLayerNum == 3 ? 4 : 1); int tmpBitrateIndex = tmpFrameHeader[2] >> 4; // Check for invalid values if (tmpBitrateIndex < 1 || tmpBitrateIndex > 14 || tmpLayerNum == 0) { stream.Seek(-3, SeekOrigin.Current); continue; } int tmpFrameBitrate = GetBitrate((MpegVersion)tmpMpegID, (MpegLayer)tmpLayerNum, tmpBitrateIndex); int tmpFrameSize = (int)(tmpFrameBitrate * tmpFrameSizeConst) + (tmpUsesPadding * tmpPaddingSize); _headerOffset = stream.Position - 4; if (tmpFrameSize < 8) { stream.Seek(-3, SeekOrigin.Current); continue; } // 7/21/05 - Check for 0x00 or 0xFF at end of last frame // this sucks for tracks that start with silence if (_headerOffset >= 1 && !acceptNullSamples) // if (ftell(fp) >= 5) { stream.Seek(-5, SeekOrigin.Current); byte tmpLastByte = stream.Read1(); stream.Seek(4, SeekOrigin.Current); if (tmpFrameBitrate != 320 && (tmpLastByte == 0x00 || tmpLastByte == 0xFF)) { // 7/31/05 // may be a valid frame - skip its contents to prevent false sync long tmpNewPosition = _headerOffset + tmpFrameSize; if (tmpFrameSize == 0) tmpNewPosition++; stream.Seek(tmpNewPosition, SeekOrigin.Begin); continue; } } /*if (BR == 0 || FrameSizeConst == 0) { startpos = HeaderOffset+1; fseek(fp, startpos, SEEK_SET); continue; }*/ stream.Seek(_headerOffset + tmpFrameSize, SeekOrigin.Begin); if (stream.Read1() == 0xFF) { fh1 = stream.Read1(); fh2 = stream.Read1(); if (tmpFrameHeader[1] == fh1 && (tmpFrameHeader[2] & 0x0D) == (fh2 & 0x0D)) { // header found break; } } stream.Seek(_headerOffset + 1, SeekOrigin.Begin); continue; } } _mpegVersion = (MpegVersion)((tmpFrameHeader[1] >> 3) & 0x03); _mpegLayer = (MpegLayer)((tmpFrameHeader[1] >> 1) & 0x03); _frequency = GetFrequency(_mpegVersion, (tmpFrameHeader[2] >> 2) & 0x03); if (_frequency == 0) { throw new InvalidDataException(String.Format("'{0}'; cannot determine frequency", path)); } _isPrivate = ((tmpFrameHeader[2] & 0x01) == 0x01); _samplesPerFrame = GetSamplesPerFrame(_mpegVersion, _mpegLayer); _frameSizeConst = 125.0 * _samplesPerFrame / _frequency; _paddingSizeConst = (_mpegLayer == MpegLayer.Layer1 ? 4 : 1); _isCopyright = (((tmpFrameHeader[3] >> 3) & 0x01) == 0x01); _isOriginal = (((tmpFrameHeader[3] >> 2) & 0x01) == 0x01); //tmpModeExtension = (FH[3] >> 4) & 0x03; // not interested, only used in joint-stereo //_mpegEmphasis = (MpegEmphasis)(tmpFrameHeader[3] & 0x03); if ((tmpFrameHeader[3] >> 6) == 3) _channels = 1; // Single Channel else _channels = 2; // Read LAME Info Tag bool tmpHasLameInfoTag = false; stream.Seek(tmpID3v2TagSize + 36, SeekOrigin.Begin); Byte[] buf = stream.Read(4); if (ByteUtils.Compare(buf, INFO_MARKER)) // CBR { tmpHasLameInfoTag = true; _isVBR = false; } else if (ByteUtils.Compare(buf, XING_MARKER)) // VBR { tmpHasLameInfoTag = true; _isVBR = true; } if (tmpHasLameInfoTag) { stream.Seek(4, SeekOrigin.Current); int tmpFrames = stream.ReadInt32(); uint tmpBytes = (uint)stream.ReadInt32(); if (tmpFrames > 256 && tmpBytes > 50000) { decimal tmpBitrate = tmpBytes / 125.0m / (tmpFrames * _samplesPerFrame / (decimal)_frequency); if (tmpBitrate <= 320 && tmpBitrate >= 32) { _frames = tmpFrames; _bitrate = tmpBitrate; _totalSeconds = (tmpBytes / 125.0m) / _bitrate; } } } // TODO: Take these 2 lines out /*fs.Position = 0; CalculateBitrate(fs, null);*/ if (calculateBitrate) { if (_bitrate == 0 || _isVBR == null || _frames == 0 || _totalSeconds == 0) { stream.Position = 0; CalculateBitrate(stream, null); } } } }
private static int GetSamplesPerFrame(MpegVersion mpegVersion, MpegLayer mpegLayer) { int tmpSamplesPerFrame = 0; switch (mpegVersion) { // MPEG-1 case MpegVersion.Mpeg1: if (mpegLayer == MpegLayer.Layer1) tmpSamplesPerFrame = 384; else if (mpegLayer == MpegLayer.Layer2 || mpegLayer == MpegLayer.Layer3) tmpSamplesPerFrame = 1152; break; // MPEG-2/2.5 case MpegVersion.Mpeg2: case MpegVersion.Mpeg25: if (mpegLayer == MpegLayer.Layer1) tmpSamplesPerFrame = 384; else if (mpegLayer == MpegLayer.Layer2) tmpSamplesPerFrame = 1152; else if (mpegLayer == MpegLayer.Layer3) tmpSamplesPerFrame = 576; break; } // end switch (ID) return tmpSamplesPerFrame; }
private static int GetBitrate(MpegVersion mpegVersion, MpegLayer mpegLayer, int bitrateIndex) { return BitrateTable[(int)mpegVersion][(int)mpegLayer - 1][bitrateIndex - 1]; }
public byte[] BuildFrame( MpegVersion version, MpegLayer layer, bool hasCRC, int frameSizeOffset, int frameSize) { byte[] buf = Slush.DomainObjects.Mp3.Test.Mp3FrameTest.BuildFrame( version, layer, hasCRC, frameSizeOffset, frameSize); if (UseRandom) { for (int i = 6; i < buf.Length; i++) { buf[i] = (byte)random.Next(); } } return buf; }
private static int?GetBitrate(byte three, MpegVersion version, MpegLayer layer) { if (version == MpegVersion.MPEG1) { if (layer == MpegLayer.Layer1) { if (CompBit(three, 1, 4, false, false, false, false)) { return(null); } if (CompBit(three, 1, 4, false, false, false, true)) { return(32); } if (CompBit(three, 1, 4, false, false, true, false)) { return(64); } if (CompBit(three, 1, 4, false, false, true, true)) { return(96); } if (CompBit(three, 1, 4, false, true, false, false)) { return(128); } if (CompBit(three, 1, 4, false, true, false, true)) { return(160); } if (CompBit(three, 1, 4, false, true, true, false)) { return(192); } if (CompBit(three, 1, 4, false, true, true, true)) { return(224); } if (CompBit(three, 1, 4, true, false, false, false)) { return(256); } if (CompBit(three, 1, 4, true, false, false, true)) { return(288); } if (CompBit(three, 1, 4, true, false, true, false)) { return(320); } if (CompBit(three, 1, 4, true, false, true, true)) { return(352); } if (CompBit(three, 1, 4, true, true, false, false)) { return(384); } if (CompBit(three, 1, 4, true, true, false, true)) { return(416); } if (CompBit(three, 1, 4, true, true, true, false)) { return(448); } if (CompBit(three, 1, 4, true, true, true, true)) { return(null); } } else if (layer == MpegLayer.Layer2) { if (CompBit(three, 1, 4, false, false, false, false)) { return(null); } if (CompBit(three, 1, 4, false, false, false, true)) { return(32); } if (CompBit(three, 1, 4, false, false, true, false)) { return(45); } if (CompBit(three, 1, 4, false, false, true, true)) { return(56); } if (CompBit(three, 1, 4, false, true, false, false)) { return(64); } if (CompBit(three, 1, 4, false, true, false, true)) { return(80); } if (CompBit(three, 1, 4, false, true, true, false)) { return(96); } if (CompBit(three, 1, 4, false, true, true, true)) { return(112); } if (CompBit(three, 1, 4, true, false, false, false)) { return(128); } if (CompBit(three, 1, 4, true, false, false, true)) { return(160); } if (CompBit(three, 1, 4, true, false, true, false)) { return(192); } if (CompBit(three, 1, 4, true, false, true, true)) { return(224); } if (CompBit(three, 1, 4, true, true, false, false)) { return(256); } if (CompBit(three, 1, 4, true, true, false, true)) { return(320); } if (CompBit(three, 1, 4, true, true, true, false)) { return(384); } if (CompBit(three, 1, 4, true, true, true, true)) { return(null); } } else if (layer == MpegLayer.Layer3) { if (CompBit(three, 1, 4, false, false, false, false)) { return(null); } if (CompBit(three, 1, 4, false, false, false, true)) { return(32); } if (CompBit(three, 1, 4, false, false, true, false)) { return(40); } if (CompBit(three, 1, 4, false, false, true, true)) { return(45); } if (CompBit(three, 1, 4, false, true, false, false)) { return(56); } if (CompBit(three, 1, 4, false, true, false, true)) { return(64); } if (CompBit(three, 1, 4, false, true, true, false)) { return(80); } if (CompBit(three, 1, 4, false, true, true, true)) { return(96); } if (CompBit(three, 1, 4, true, false, false, false)) { return(112); } if (CompBit(three, 1, 4, true, false, false, true)) { return(128); } if (CompBit(three, 1, 4, true, false, true, false)) { return(160); } if (CompBit(three, 1, 4, true, false, true, true)) { return(192); } if (CompBit(three, 1, 4, true, true, false, false)) { return(224); } if (CompBit(three, 1, 4, true, true, false, true)) { return(256); } if (CompBit(three, 1, 4, true, true, true, false)) { return(320); } if (CompBit(three, 1, 4, true, true, true, true)) { return(null); } } } return(null); }
/// <summary>checks if the four bytes represent a valid header, /// if they are, will parse the values into local properties /// </summary> private bool IsValidHeader(byte[] headerBytes) { if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0)) { // TODO: could do with a bitstream class here mpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3); if (mpegVersion == MpegVersion.Reserved) { //throw new FormatException("Unsupported MPEG Version"); return false; } layer = (MpegLayer)((headerBytes[1] & 0x06) >> 1); if (layer == MpegLayer.Reserved) { return false; } int layerIndex = this.layer == MpegLayer.Layer1 ? 0 : this.layer == MpegLayer.Layer2 ? 1: 2; crcPresent = (headerBytes[1] & 0x01) == 0x00; int bitRateIndex = (headerBytes[2] & 0xF0) >> 4; if (bitRateIndex == 15) { // invalid index return false; } int versionIndex = this.mpegVersion == Wave.MpegVersion.Version1 ? 0 : 1; this.bitRate = bitRates[versionIndex, layerIndex, bitRateIndex] * 1000; if (bitRate == 0) { return false; } int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2; if (sampleFrequencyIndex == 3) { return false; } if (mpegVersion == MpegVersion.Version1) sampleRate = sampleRatesVersion1[sampleFrequencyIndex]; else if (mpegVersion == MpegVersion.Version2) sampleRate = sampleRatesVersion2[sampleFrequencyIndex]; else // mpegVersion == MpegVersion.Version25 sampleRate = sampleRatesVersion25[sampleFrequencyIndex]; bool padding = (headerBytes[2] & 0x02) == 0x02; bool privateBit = (headerBytes[2] & 0x01) == 0x01; channelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6); int channelExtension = (headerBytes[3] & 0x30) >> 4; bool copyright = (headerBytes[3] & 0x08) == 0x08; bool original = (headerBytes[3] & 0x04) == 0x04; int emphasis = (headerBytes[3] & 0x03); int nPadding = padding ? 1 : 0; this.samplesInFrame = samplesPerFrame[versionIndex, layerIndex]; int coefficient = this.samplesInFrame / 8; if (this.layer == MpegLayer.Layer1) { this.frameLengthInBytes = (coefficient * bitRate / sampleRate + nPadding) * 4; } else { frameLengthInBytes = (coefficient * bitRate) / sampleRate + nPadding; } if (this.frameLengthInBytes > MaxFrameLength) { return false; } return true; } return false; }
/// <summary>Reads an MP3Frame from a stream</summary> /// <remarks>http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm /// has some good info</remarks> public Mp3Frame(Stream input) { BinaryReader reader = new BinaryReader(input); // try for a header long headerStartPosition = input.Position; byte[] headerBytes = reader.ReadBytes(4); if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0)) { // TODO: could do with a bitstream class here mpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3); if (mpegVersion == MpegVersion.Reserved) { throw new FormatException("Unsupported MPEG Version"); } layer = (MpegLayer)((headerBytes[1] & 0x06) >> 1); if (layer != MpegLayer.Layer3) { throw new FormatException("Not an MP3"); } crcPresent = (headerBytes[1] & 0x01) == 0x00; int bitRateIndex = (headerBytes[2] & 0xF0) >> 4; bitRate = (mpegVersion == MpegVersion.Version1) ? bitRatesLayer3Version1[bitRateIndex] : bitRatesLayer3Version2[bitRateIndex]; int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2; if (mpegVersion == MpegVersion.Version1) { sampleRate = sampleRatesVersion1[sampleFrequencyIndex]; } else if (mpegVersion == MpegVersion.Version2) { sampleRate = sampleRatesVersion2[sampleFrequencyIndex]; } else // mpegVersion == MpegVersion.Version25 { sampleRate = sampleRatesVersion25[sampleFrequencyIndex]; } bool padding = (headerBytes[2] & 0x02) == 0x02; bool privateBit = (headerBytes[2] & 0x01) == 0x01; channelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6); int channelExtension = (headerBytes[3] & 0x30) >> 4; bool copyright = (headerBytes[3] & 0x08) == 0x80; bool original = (headerBytes[3] & 0x04) == 0x80; int emphasis = (headerBytes[3] & 0x03); frameLengthInBytes = (144 * 1000 * bitRate) / sampleRate + ((padding) ? 1 : 0); } else { input.Position = headerStartPosition; throw new FormatException("Not a recognised MP3 block"); } if (crcPresent) { crc = reader.ReadInt16(); } long dataStartPosition = input.Position; input.Position = headerStartPosition; rawData = reader.ReadBytes(frameLengthInBytes); }
/// <summary> /// Initializes a new instance of the <see cref="Mpeg"/> class. /// </summary> /// <param name="path">The full path of the file.</param> /// <param name="calculateBitrate">if set to <c>true</c> the bitrate will be calculated before the constructor returns.</param> public Mpeg(string path, bool calculateBitrate) { _fileName = path; using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { int tmpID3v2TagSize = ID3v2.GetTagSize(stream); stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); byte[] tmpFrameHeader = new byte[4]; bool acceptNullSamples = false; while (true) { int tmpByte = stream.ReadByte(); // keep as ReadByte while (tmpByte != 0xFF && tmpByte != -1) { tmpByte = stream.ReadByte(); // keep as ReadByte } if (tmpByte == -1) { if (acceptNullSamples) { throw new InvalidDataException(string.Format("'{0}': Can't find frame sync", path)); } stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); acceptNullSamples = true; continue; } tmpFrameHeader[0] = (byte)tmpByte; // Get frame header if (stream.Read(tmpFrameHeader, 1, 3) != 3) { throw new InvalidDataException(string.Format("'{0}': Invalid MPEG file; end of stream reached", path)); } // No sync if ((tmpFrameHeader[1] >> 5) != 0x07 || ((tmpFrameHeader[1] >> 1) & 0x03) == 0) // 2/18/05 - ignore reserved layer { stream.Seek(-3, SeekOrigin.Current); } else if (tmpFrameHeader[1] == 0xFF || ((tmpFrameHeader[1] >> 3) & 0x03) == 1) // 2/19/05 - more bad data { stream.Seek(-3, SeekOrigin.Current); } else { int tmpMpegID = (tmpFrameHeader[1] >> 3) & 0x03; int tmpLayerNum = (tmpFrameHeader[1] >> 1) & 0x03; int tmpFrequency = GetFrequency((MpegVersion)tmpMpegID, (tmpFrameHeader[2] >> 2) & 0x03); // Check for invalid frequency if (tmpFrequency == 0) { stream.Seek(-3, SeekOrigin.Current); continue; } int tmpSamplesPerFrame = GetSamplesPerFrame((MpegVersion)tmpMpegID, (MpegLayer)tmpLayerNum); int tmpUsesPadding = (tmpFrameHeader[2] >> 1) & 0x01; double tmpFrameSizeConst = 125.0 * tmpSamplesPerFrame / tmpFrequency; int tmpPaddingSize = (tmpLayerNum == 3 ? 4 : 1); int tmpBitrateIndex = tmpFrameHeader[2] >> 4; // Check for invalid values if (tmpBitrateIndex < 1 || tmpBitrateIndex > 14 || tmpLayerNum == 0) { stream.Seek(-3, SeekOrigin.Current); continue; } int tmpFrameBitrate = GetBitrate((MpegVersion)tmpMpegID, (MpegLayer)tmpLayerNum, tmpBitrateIndex); int tmpFrameSize = (int)(tmpFrameBitrate * tmpFrameSizeConst) + (tmpUsesPadding * tmpPaddingSize); _headerOffset = stream.Position - 4; if (tmpFrameSize < 8) { stream.Seek(-3, SeekOrigin.Current); continue; } // 7/21/05 - Check for 0x00 or 0xFF at end of last frame // this sucks for tracks that start with silence if (_headerOffset >= 1 && !acceptNullSamples) // if (ftell(fp) >= 5) { stream.Seek(-5, SeekOrigin.Current); byte tmpLastByte = stream.Read1(); stream.Seek(4, SeekOrigin.Current); if (tmpFrameBitrate != 320 && (tmpLastByte == 0x00 || tmpLastByte == 0xFF)) { // 7/31/05 // may be a valid frame - skip its contents to prevent false sync long tmpNewPosition = _headerOffset + tmpFrameSize; if (tmpFrameSize == 0) { tmpNewPosition++; } stream.Seek(tmpNewPosition, SeekOrigin.Begin); continue; } } /*if (BR == 0 || FrameSizeConst == 0) * { * startpos = HeaderOffset+1; * fseek(fp, startpos, SEEK_SET); * continue; * }*/ stream.Seek(_headerOffset + tmpFrameSize, SeekOrigin.Begin); if (stream.Read1() == 0xFF) { fh1 = stream.Read1(); fh2 = stream.Read1(); if (tmpFrameHeader[1] == fh1 && (tmpFrameHeader[2] & 0x0D) == (fh2 & 0x0D)) { // header found break; } } stream.Seek(_headerOffset + 1, SeekOrigin.Begin); continue; } } _mpegVersion = (MpegVersion)((tmpFrameHeader[1] >> 3) & 0x03); _mpegLayer = (MpegLayer)((tmpFrameHeader[1] >> 1) & 0x03); _frequency = GetFrequency(_mpegVersion, (tmpFrameHeader[2] >> 2) & 0x03); if (_frequency == 0) { throw new InvalidDataException(String.Format("'{0}'; cannot determine frequency", path)); } _isPrivate = ((tmpFrameHeader[2] & 0x01) == 0x01); _samplesPerFrame = GetSamplesPerFrame(_mpegVersion, _mpegLayer); _frameSizeConst = 125.0 * _samplesPerFrame / _frequency; _paddingSizeConst = (_mpegLayer == MpegLayer.Layer1 ? 4 : 1); _isCopyright = (((tmpFrameHeader[3] >> 3) & 0x01) == 0x01); _isOriginal = (((tmpFrameHeader[3] >> 2) & 0x01) == 0x01); //tmpModeExtension = (FH[3] >> 4) & 0x03; // not interested, only used in joint-stereo //_mpegEmphasis = (MpegEmphasis)(tmpFrameHeader[3] & 0x03); if ((tmpFrameHeader[3] >> 6) == 3) { _channels = 1; // Single Channel } else { _channels = 2; } // Read LAME Info Tag bool tmpHasLameInfoTag = false; stream.Seek(tmpID3v2TagSize + 36, SeekOrigin.Begin); Byte[] buf = stream.Read(4); if (ByteUtils.Compare(buf, INFO_MARKER)) // CBR { tmpHasLameInfoTag = true; _isVBR = false; } else if (ByteUtils.Compare(buf, XING_MARKER)) // VBR { tmpHasLameInfoTag = true; _isVBR = true; } if (tmpHasLameInfoTag) { stream.Seek(4, SeekOrigin.Current); int tmpFrames = stream.ReadInt32(); uint tmpBytes = (uint)stream.ReadInt32(); if (tmpFrames > 256 && tmpBytes > 50000) { decimal tmpBitrate = tmpBytes / 125.0m / (tmpFrames * _samplesPerFrame / (decimal)_frequency); if (tmpBitrate <= 320 && tmpBitrate >= 32) { _frames = tmpFrames; _bitrate = tmpBitrate; _totalSeconds = (tmpBytes / 125.0m) / _bitrate; } } } // TODO: Take these 2 lines out /*fs.Position = 0; * CalculateBitrate(fs, null);*/ if (calculateBitrate) { if (_bitrate == 0 || _isVBR == null || _frames == 0 || _totalSeconds == 0) { stream.Position = 0; CalculateBitrate(stream, null); } } } }
private static int GetBitrate(MpegVersion mpegVersion, MpegLayer mpegLayer, int bitrateIndex) { return(BitrateTable[(int)mpegVersion][(int)mpegLayer - 1][bitrateIndex - 1]); }
/// <summary>checks if the four bytes represent a valid header, /// if they are, will parse the values into local properties /// </summary> private bool IsValidHeader(byte[] headerBytes) { if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0)) { // TODO: could do with a bitstream class here mpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3); if (mpegVersion == MpegVersion.Reserved) { //throw new FormatException("Unsupported MPEG Version"); return(false); } layer = (MpegLayer)((headerBytes[1] & 0x06) >> 1); if (layer == MpegLayer.Reserved) { return(false); } int layerIndex = this.layer == MpegLayer.Layer1 ? 0 : this.layer == MpegLayer.Layer2 ? 1: 2; crcPresent = (headerBytes[1] & 0x01) == 0x00; int bitRateIndex = (headerBytes[2] & 0xF0) >> 4; if (bitRateIndex == 15) { // invalid index return(false); } int versionIndex = this.mpegVersion == Wave.MpegVersion.Version1 ? 0 : 1; this.bitRate = bitRates[versionIndex, layerIndex, bitRateIndex] * 1000; if (bitRate == 0) { return(false); } int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2; if (sampleFrequencyIndex == 3) { return(false); } if (mpegVersion == MpegVersion.Version1) { sampleRate = sampleRatesVersion1[sampleFrequencyIndex]; } else if (mpegVersion == MpegVersion.Version2) { sampleRate = sampleRatesVersion2[sampleFrequencyIndex]; } else // mpegVersion == MpegVersion.Version25 { sampleRate = sampleRatesVersion25[sampleFrequencyIndex]; } bool padding = (headerBytes[2] & 0x02) == 0x02; bool privateBit = (headerBytes[2] & 0x01) == 0x01; channelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6); int channelExtension = (headerBytes[3] & 0x30) >> 4; bool copyright = (headerBytes[3] & 0x08) == 0x08; bool original = (headerBytes[3] & 0x04) == 0x04; int emphasis = (headerBytes[3] & 0x03); int nPadding = padding ? 1 : 0; this.samplesInFrame = samplesPerFrame[versionIndex, layerIndex]; int coefficient = this.samplesInFrame / 8; if (this.layer == MpegLayer.Layer1) { this.frameLengthInBytes = (coefficient * bitRate / sampleRate + nPadding) * 4; } else { frameLengthInBytes = (coefficient * bitRate) / sampleRate + nPadding; } if (this.frameLengthInBytes > MaxFrameLength) { return(false); } return(true); } return(false); }
private void GetLayer(params bool[] twoBits) { if (twoBits[0] && twoBits[1]) this.mpegLayer = MpegLayer.I; else if (twoBits[0] && !twoBits[1]) this.mpegLayer = MpegLayer.II; else if (!twoBits[0] && twoBits[1]) this.mpegLayer = MpegLayer.III; else if (!twoBits[0] && !twoBits[1]) this.mpegLayer = MpegLayer.Reserved; }