Beispiel #1
0
 public void AddFrame(
     MpegVersion version,
     MpegLayer layer,
     bool hasCRC,
     int frameSizeOffset,
     int frameSize)
 {
     Add(new Mp3Frame(BuildFrame(
         version,
         layer,
         hasCRC,
         frameSizeOffset,
         frameSize)));
 }
Beispiel #2
0
        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));
        }
Beispiel #3
0
 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;
     }
 }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        /// <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);

        }
Beispiel #6
0
        /// <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);
                    }
                }
            }
        }
Beispiel #7
0
        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;
        }
Beispiel #8
0
 private static int GetBitrate(MpegVersion mpegVersion, MpegLayer mpegLayer, int bitrateIndex)
 {
     return BitrateTable[(int)mpegVersion][(int)mpegLayer - 1][bitrateIndex - 1];
 }
Beispiel #9
0
        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;
        }
Beispiel #10
0
 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);
 }
Beispiel #11
0
        /// <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;
        }
Beispiel #12
0
        /// <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);
        }
Beispiel #13
0
        /// <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);
                    }
                }
            }
        }
Beispiel #14
0
 private static int GetBitrate(MpegVersion mpegVersion, MpegLayer mpegLayer, int bitrateIndex)
 {
     return(BitrateTable[(int)mpegVersion][(int)mpegLayer - 1][bitrateIndex - 1]);
 }
Beispiel #15
0
        /// <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);
        }
Beispiel #16
0
 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;
 }