Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OggVorbis"/> class.
        /// </summary>
        /// <param name="path">The path.</param>
        public OggVorbis(string path)
        {
            using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                try
                {
                    int tmpID3v2Size = ID3v2.GetTagSize(stream);
                    stream.Seek(tmpID3v2Size, SeekOrigin.Begin);

                    byte[] oggMarker = stream.Read(4);
                    if (ByteUtils.Compare(oggMarker, OGG_MARKER) == false)
                    {
                        throw new InvalidDataException("OggS marker not found");
                    }

                    // Skip through Ogg page header to page_segments position
                    stream.Seek(22, SeekOrigin.Current);

                    // Skip segment_table
                    int pageSegments = stream.Read1();
                    stream.Seek(pageSegments, SeekOrigin.Current);

                    // Read vorbis header
                    int packetType = stream.Read1();
                    if (packetType != 0x01)
                    {
                        throw new InvalidDataException("Vorbis identification header not found");
                    }

                    byte[] vorbisMarker = stream.Read(6);
                    if (ByteUtils.Compare(vorbisMarker, VORBIS_MARKER) == false)
                    {
                        throw new InvalidDataException("Vorbis marker not found");
                    }

                    // Skip vorbis_version
                    stream.Seek(4, SeekOrigin.Current);

                    _channels  = stream.Read1();
                    _frequency = stream.ReadInt32LittleEndian();

                    byte[] buf  = new byte[251];
                    long   size = stream.Length;

                    // Get total number of samples
                    _samples = 0;
                    for (int index = 1; index <= 50 && _samples == 0; index++)
                    {
                        long dataIndex = size - ((251 - 10) * index) - 10;
                        stream.Seek(dataIndex, SeekOrigin.Begin);
                        stream.Read(buf, 0, 251);

                        // Get number of PCM samples from last Ogg packet header
                        for (int i = 251 - 10; i >= 0; i--)
                        {
                            bool headerFound = true;
                            for (int j = 0; j < 4; j++)
                            {
                                if (buf[i + j] != OGG_MARKER[j])
                                {
                                    headerFound = false;
                                    break;
                                }
                            }

                            if (headerFound)
                            {
                                stream.Seek(dataIndex + i + 6, SeekOrigin.Begin);
                                stream.Read(buf, 0, 8);
                                for (i = 0; i < 8; i++)
                                {
                                    _samples += buf[i] << (8 * i);
                                }
                                break;
                            }
                        }
                    }

                    if (_samples == 0)
                    {
                        throw new InvalidDataException("Could not position to last frame");
                    }

                    _totalSeconds = _samples / (decimal)_frequency;
                    _bitrate      = (size - tmpID3v2Size) / _totalSeconds / 125.0m;
                }
                catch (Exception ex)
                {
                    throw new Exception("Invalid Ogg-Vorbis file; stream may be corrupt", ex);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MonkeysAudio"/> class.
        /// </summary>
        /// <param name="path">The path.</param>
        public MonkeysAudio(string path)
        {
            using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // Skip ID3v2 tag
                int tmpID3v2TagSize = ID3v2.GetTagSize(stream);
                int tmpID3v1TagSize = ID3v1.GetTagSize(stream);
                int tmpAPEv2TagSize = APEv2.GetTagSize(stream);
                stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin);

                byte[] identifier = stream.Read(4);
                if (ByteUtils.Compare(identifier, MAC_IDENTIFIER, 4) == false)
                {
                    throw new InvalidDataException("Invalid Monkey's Audio file");
                }

                byte[] buf = stream.Read(4);

                _version = buf[0] + (buf[1] << 8);
                int blocksPerFrame;
                int finalBlocks;

                if (_version >= 3980 && _version <= 3990)
                {
                    buf = stream.Read(4);
                    int descriptorLength = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
                    stream.Seek(descriptorLength - 12, SeekOrigin.Current); // skip DESCRIPTOR

                    buf = stream.Read(4);
                    _compressionLevel = buf[0] + (buf[1] << 8);

                    blocksPerFrame = stream.ReadInt32LittleEndian();
                    finalBlocks    = stream.ReadInt32LittleEndian();
                    _frames        = stream.ReadInt32LittleEndian();

                    buf = stream.Read(4);
                    // skip bits per sample
                    _channels = buf[2] + (buf[3] << 8);

                    _frequency = stream.ReadInt32LittleEndian();
                }
                else if (_version <= 3970)
                {
                    // TODO: This section needs work

                    _compressionLevel = buf[2] + (buf[3] << 8);

                    buf = stream.Read(24);

                    // skip format flags
                    _channels = buf[2] + (buf[3] << 8);

                    _frequency = buf[4] + (buf[5] << 8) + (buf[6] << 16) + (buf[7] << 32);

                    if (_version >= 3950)
                    {
                        blocksPerFrame = 73728 * 4;
                    }
                    else if (_version >= 3900 || (_version >= 3800 && _compressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH))
                    {
                        blocksPerFrame = 73728;
                    }
                    else
                    {
                        blocksPerFrame = 9216;
                    }

                    // TODO: This is definitely f****d up
                    finalBlocks = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
                    _frames     = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
                }
                else
                {
                    throw new NotImplementedException(string.Format("MAC {0:0.00} not supported", _version / 1000.0));
                }

                long totalBlocks = ((_frames - 1) * blocksPerFrame) + finalBlocks;

                long totalSize = stream.Length - stream.Position - tmpAPEv2TagSize - tmpID3v1TagSize;

                _totalSeconds = totalBlocks / (decimal)_frequency;
                _bitrate      = totalSize / (_totalSeconds * 125.0m);
            }
        }
Пример #3
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);
                    }
                }
            }
        }
Пример #4
0
        private void CalculateBitrate(Stream stream, CInterestedFrames InterestedFrames)
        {
            int totalTagSize = ID3v2.GetTagSize(stream);

            totalTagSize += ID3v1.GetTagSize(stream);
            totalTagSize += APEv2.GetTagSize(stream);

            Int64 audioLength = stream.Length - totalTagSize;

            _bitrate      = 0;
            _isVBR        = null;
            _frames       = 0;
            _totalSeconds = 0;

            String step = "";

            try
            {
                int BR, Padding;
                int FrameSize;

                int TotalBR     = 0;
                int FrameOffset = 0;
                //Int64 TagOffset = 0;
                bool   bTrusting = true;
                bool   ignoreall = false;
                Byte[] FH        = new Byte[4];
                bool   mPerfect  = true;

                stream.Position = _headerOffset;

                //                if (_headerOffset > 0)
                //                {
                //                    TagOffset = _headerOffset;
                //                }

                int offset     = 0;
                int frameCount = 0;
                int FirstBR    = 0;

                int    audioDataSize = (int)(stream.Length - _headerOffset);
                Byte[] audioData     = new Byte[audioDataSize];
                //Int64 startoffset = stream.Position;
                int BufLen = stream.Read(audioData, 0, audioDataSize);
                while (offset < BufLen - 16 && !ignoreall)
                {
                    bool reservedlayer = false;

                    // Find FrameSync
                    if (FindFrameSync(FH, audioData, BufLen, ref FrameOffset, ref offset, ref mPerfect, ref ignoreall, ref bTrusting, ref reservedlayer))
                    {
                        FrameOffset = 0;

                        int bitrateIndex = FH[2] >> 4;
                        if (bitrateIndex <= 0 || bitrateIndex >= 15)
                        {
                            offset -= 3;
                            continue;
                        }

                        Padding = (FH[2] >> 1) & 0x01;
                        BR      = GetBitrate(_mpegVersion, _mpegLayer, bitrateIndex);

                        if (BR == 0 || BR % 8 != 0)
                        {
                            offset -= 3;
                            continue;
                        }

                        //step = "last good frame @ " + String(startoffset + offset - 4) + ", frame " +
                        //       String(_frames + 1);

                        // todo: put back later

                        /*if (InterestedFrames != NULL)
                         * {
                         *  if (((_frames + 1) * _samplesperframe / (float)_Frequency) * 75.0 >= InterestedFrames->CurrentFrame())
                         *  {
                         *      if (_frames == 0 || InterestedFrames->NoAccomodation)
                         *      {
                         *          InterestedFrames->SetCurrentByteOffset(startoffset + offset - 4);
                         *          InterestedFrames->SetCurrentFrameOffset(_frames);
                         *      }
                         *      InterestedFrames->SetCurrentByteEndOffset(startoffset + offset - 4);
                         *      InterestedFrames->Cur += 1;
                         *  }
                         *  else
                         *  {
                         *      InterestedFrames->SetCurrentByteOffset(startoffset + offset - 4);
                         *      InterestedFrames->SetCurrentFrameOffset(_frames);
                         *  }
                         * }*/

                        if (_isVBR != true)
                        {
                            if (TotalBR == 0)
                            {
                                FirstBR = BR;
                            }
                            else if (BR != FirstBR)
                            {
                                _isVBR = true;
                            }
                        }

                        TotalBR += BR;

                        FrameSize = (int)(BR * _frameSizeConst + Padding * _paddingSizeConst);

                        offset += FrameSize - 4;
                        frameCount++;
                    }
                }// end while

                if (frameCount == 0)
                {
                    throw new InvalidDataException(String.Format("No frames found in {0}", _fileName));
                }

                _frames = frameCount;
                if (_isVBR == null)
                {
                    _bitrate = FirstBR;
                    _isVBR   = false;
                }
                else
                {
                    _bitrate = TotalBR / _frames;
                }

                if (_bitrate == 0)
                {
                    throw new InvalidDataException(String.Format("Error determining bitrate: {0}", _fileName));
                }

                _totalSeconds = (audioLength / 125.0m) / _bitrate;
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Error calculating bitrate; {0}", step), ex);
            }
        }
Пример #5
0
        private readonly int _channels = 2; // TODO

        /// <summary>
        /// Initializes a new instance of the <see cref="Musepack"/> class.
        /// </summary>
        /// <param name="path">The path of the file.</param>
        public Musepack(string path)
        {
            using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // Skip ID3v2 tag
                int tmpID3v2TagSize = ID3v2.GetTagSize(stream);
                int tmpID3v1TagSize = ID3v1.GetTagSize(stream);
                int tmpAPEv2TagSize = APEv2.GetTagSize(stream);
                stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin);

                _streamVersion = 0;

                byte[] byteArray    = stream.Read(32);
                int[]  integerArray = new int[8];
                for (int i = 0; i < 8; i++)
                {
                    integerArray[i] = (byteArray[i * 4]) +
                                      (byteArray[i * 4 + 1] << 8) +
                                      (byteArray[i * 4 + 2] << 16) +
                                      (byteArray[i * 4 + 3] << 24);
                }

                // Size TODO - ignore Lyrics3
                long audioDataLength = stream.Length - tmpID3v2TagSize - tmpID3v1TagSize - tmpAPEv2TagSize;

                // Stream version
                if (integerArray[0] == STREAM_VERSION_70_ID)
                {
                    _streamVersion = 7;
                }
                else if (integerArray[0] == STREAM_VERSION_71_ID)
                {
                    _streamVersion = 7.1m;
                }
                else
                {
                    switch ((byteArray[1] % 32) / 2)
                    {
                    case 3:
                        _streamVersion = 4;
                        break;

                    case 7:
                        _streamVersion = 5;
                        break;

                    case 11:
                        _streamVersion = 6;
                        break;
                    }
                }

                if (_streamVersion == 0)
                {
                    throw new InvalidDataException("Unrecognized MPC stream");
                }

                // Sample rate
                _frequency = _sampleRates[byteArray[10] & 0x03];

                // Channels
                if (_streamVersion == 7 || _streamVersion == 7.1m)
                {
                    if ((byteArray[11] % 128) < 64)
                    {
                        _mode = "Stereo";
                    }
                    else
                    {
                        _mode = "Joint Stereo";
                    }
                }
                else
                {
                    if ((byteArray[2] % 128) == 0)
                    {
                        _mode = "Stereo";
                    }
                    else
                    {
                        _mode = "Joint Stereo";
                    }
                }

                // Frames
                if (_streamVersion == 4)
                {
                    _frames = integerArray[1] >> 16;
                }
                else
                {
                    _frames = integerArray[1];
                }

                _totalSeconds = _frames * 1152 / (decimal)_frequency;
                _bitrate      = (audioDataLength / _totalSeconds) / 125.0m;
            }
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Flac"/> class.
        /// </summary>
        /// <param name="path">The path of the file.</param>
        public Flac(string path)
        {
            try
            {
                using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    // Skip ID3v2 tag
                    int tmpID3v2TagSize = ID3v2.GetTagSize(stream);
                    int tmpID3v1TagSize = ID3v1.GetTagSize(stream);
                    int tmpAPEv2TagSize = APEv2.GetTagSize(stream);
                    stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin);

                    // Read flac marker
                    byte[] flacMarker = new Byte[4];
                    stream.Read(flacMarker, 0, 4);
                    if (ByteUtils.Compare(flacMarker, FLAC_MARKER) == false)
                    {
                        throw new InvalidDataException("No header found");
                    }

                    // skip frame header and stuff we're not interested in
                    stream.Seek(14, SeekOrigin.Current);

                    byte[] buf = stream.Read(8);

                    _frequency = (buf[0] << 12) + (buf[1] << 4) + (buf[2] >> 4);
                    _channels  = ((buf[2] >> 1) & 0x03) + 1;
                    _samples   = ((buf[3] & 0x0F) << 32) + (buf[4] << 24) +
                                 (buf[5] << 16) + (buf[6] << 8) + buf[7];

                    _totalSeconds = _samples / (decimal)_frequency;

                    // Find first sync
                    // TODO: There's probably a better way to do this.. also an embedded PICTURE might
                    // cause a false sync. Not high priority since it will only cause a slight error
                    // in bitrate calculation if a false sync is found.
                    int c = stream.ReadByte(); // keep as ReadByte
                    while (c != -1)
                    {
                        if (c == 0xFF)
                        {
                            c = stream.ReadByte(); // keep as ReadByte
                            if (c >= 0xF8 && c <= 0xFB)
                            {
                                break;
                            }
                        }
                        else
                        {
                            c = stream.ReadByte(); // keep as ReadByte
                        }
                    }

                    if (c == -1)
                    {
                        throw new InvalidDataException("No sync found");
                    }

                    long startaudio = stream.Position;
                    long totalsize  = stream.Length - startaudio - tmpAPEv2TagSize - tmpID3v1TagSize;
                    _bitrate = totalsize / (_totalSeconds * 125);
                }
            }
            catch (InvalidDataException ex)
            {
                throw new InvalidDataException(String.Format("Cannot read FLAC file '{0}'", path), ex);
            }
        }