コード例 #1
0
        /// <summary>
        /// Opens MP3 from a stream rather than a file
        /// Will not dispose of this stream itself
        /// </summary>
        /// <param name="inputStream"></param>
        public Mp3FileReader(Stream inputStream)
        {
            int sampleRate;
            int bitRate;

            mp3Stream = inputStream;
            id3v2Tag = Id3v2Tag.ReadTag(mp3Stream);

            dataStartPosition = mp3Stream.Position;
            Mp3Frame mp3Frame = new Mp3Frame(mp3Stream);
            sampleRate = mp3Frame.SampleRate;
            frameLengthInBytes = mp3Frame.FrameLength;
            bitRate = mp3Frame.BitRate;
            xingHeader = XingHeader.LoadXingHeader(mp3Frame);

            this.length = mp3Stream.Length - dataStartPosition;

            // try for an ID3v1 tag as well
            mp3Stream.Position = mp3Stream.Length - 128;
            byte[] tag = new byte[128];
            mp3Stream.Read(tag, 0, 3);
            if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G')
            {
                id3v1Tag = tag;
                this.length -= 128;
            }

            mp3Stream.Position = dataStartPosition;

            // TODO: choose more appropriately
            waveFormat = new Mp3WaveFormat(sampleRate, 2, frameLengthInBytes, bitRate);
        }
コード例 #2
0
        public bool IsWaveformatEqual(Mp3Frame frame)
        {
            //TODO : fix function. somehow it doesn't work 100% ...
            //hence return false so it always re-inits backend
            return false;

            Mp3WaveFormat new_mp3Format = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
                        frame.FrameLength, frame.BitRate);

            if (waveFormat.GetType() != new_mp3Format.GetType())
                return false;

            Mp3WaveFormat CurrentFormat = (Mp3WaveFormat)waveFormat;
            if(
                CurrentFormat.SampleRate == new_mp3Format.SampleRate &&
                CurrentFormat.Channels == new_mp3Format.Channels &&
                CurrentFormat.BitsPerSample == new_mp3Format.BitsPerSample &&
                CurrentFormat.AverageBytesPerSecond == new_mp3Format.AverageBytesPerSecond &&
                CurrentFormat.blockSize == new_mp3Format.blockSize &&
                CurrentFormat.ExtraSize == new_mp3Format.ExtraSize)
            {

                return true;
            }
            else
            {
                return false;
            }
        }
コード例 #3
0
ファイル: Mp3FrameTests.cs プロジェクト: RasterCode/OtterUI
 public void CanParseMp3FrameOffsetByN(int offset)
 {
     byte[] validMp3Frame = constructValidMp3Frame();
     byte[] offsetBuffer = new byte[offset + validMp3Frame.Length];
     Array.Copy(validMp3Frame, 0, offsetBuffer, offset, validMp3Frame.Length);
     MemoryStream ms = new MemoryStream(validMp3Frame);
     Mp3Frame frame = new Mp3Frame(ms);
 }
コード例 #4
0
ファイル: Tools.cs プロジェクト: yodiwo/plegma
 public static IMp3FrameDecompressor CreateFrameDecompressor(Mp3Frame frame)
 {
     WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate,
                                                 frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
                                                 frame.FrameLength,
                                                 frame.BitRate
                                                 );
     return new AcmMp3FrameDecompressor(waveFormat);
 }
コード例 #5
0
 public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
 {
     Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength);
     int sourceBytesConverted = 0;
     int converted = conversionStream.Convert(frame.FrameLength, out sourceBytesConverted);
     if (sourceBytesConverted != frame.FrameLength)
     {
         throw new InvalidOperationException("Couldn't convert the whole MP3 frame");
     }
     Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, converted);
     return converted;
 }
コード例 #6
0
ファイル: Program.cs プロジェクト: cropotkin/glass
        IEnumerable<float[]> DecompressMp3(Mp3Frame aFrame)
        {
            /*
            WaveFormat waveFormat = new Mp3WaveFormat(aFrame.SampleRate, aFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, aFrame.FrameLength, aFrame.BitRate);

            var decompressor = new AcmMp3FrameDecompressor(waveFormat);

            var bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat);

            int decompressed = decompressor..DecompressFrame(aFrame,, buffer, 0);
            */

            yield return new float[] { 0, 0 };
        }
コード例 #7
0
ファイル: Mp3Frame.cs プロジェクト: ActivePHOENiX/NAudio
        /// <summary>Reads an MP3Frame from a stream</summary>
        /// <remarks>http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm has some good info
        /// also see http://www.codeproject.com/KB/audio-video/mpegaudioinfo.aspx
        /// </remarks>
        /// <returns>A valid MP3 frame, or null if none found</returns>
        public static Mp3Frame LoadFromStream(Stream input, bool readData)
        {
            var frame = new Mp3Frame();
            frame.FileOffset = input.Position;
            byte[] headerBytes = new byte[4];
            int bytesRead = input.Read(headerBytes, 0, headerBytes.Length);
            if (bytesRead < headerBytes.Length)
            {
                // reached end of stream, no more MP3 frames
                return null;
            }
            while (!IsValidHeader(headerBytes, frame))
            {
                // shift down by one and try again
                headerBytes[0] = headerBytes[1];
                headerBytes[1] = headerBytes[2];
                headerBytes[2] = headerBytes[3];
                bytesRead = input.Read(headerBytes, 3, 1);
                if (bytesRead < 1)
                {
                    return null;
                }
                frame.FileOffset++;
            }
            /* no longer read the CRC since we include this in framelengthbytes
            if (this.crcPresent)
                this.crc = reader.ReadInt16();*/

            int bytesRequired = frame.FrameLength - 4;
            if (readData)
            {
                frame.RawData = new byte[frame.FrameLength];
                Array.Copy(headerBytes, frame.RawData, 4);
                bytesRead = input.Read(frame.RawData, 4, bytesRequired);
                if (bytesRead < bytesRequired)
                {
                    // TODO: could have an option to suppress this, although it does indicate a corrupt file
                    // for now, caller should handle this exception
                    throw new EndOfStreamException("Unexpected end of stream before frame complete");
                }
            }
            else
            {
                // n.b. readData should not be false if input stream does not support seeking
                input.Position += bytesRequired;
            }

            return frame;
        }
コード例 #8
0
 /// <summary>
 /// Decompresses a frame
 /// </summary>
 /// <param name="frame">The MP3 frame</param>
 /// <param name="dest">destination buffer</param>
 /// <param name="destOffset">Offset within destination buffer</param>
 /// <returns>Bytes written into destination buffer</returns>
 public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
 {
     if (frame == null)
     {
         throw new ArgumentNullException("frame", "You must provide a non-null Mp3Frame to decompress");
     }
     Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength);
     int sourceBytesConverted = 0;
     int converted = conversionStream.Convert(frame.FrameLength, out sourceBytesConverted);
     if (sourceBytesConverted != frame.FrameLength)
     {
         throw new InvalidOperationException(String.Format("Couldn't convert the whole MP3 frame (converted {0}/{1})",
             sourceBytesConverted, frame.FrameLength));
     }
     Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, converted);
     return converted;
 }
コード例 #9
0
        private Mp3FileReader(Stream inputStream, FrameDecompressorBuilder frameDecompressorBuilder, bool ownInputStream)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException(nameof(inputStream));
            }
            if (frameDecompressorBuilder == null)
            {
                throw new ArgumentNullException(nameof(frameDecompressorBuilder));
            }
            this.ownInputStream = ownInputStream;
            try
            {
                mp3Stream = inputStream;
                Id3v2Tag  = Id3v2Tag.ReadTag(mp3Stream);

                dataStartPosition = mp3Stream.Position;
                var firstFrame = Mp3Frame.LoadFromStream(mp3Stream);
                if (firstFrame == null)
                {
                    throw new InvalidDataException("Invalid MP3 file - no MP3 Frames Detected");
                }
                double bitRate = firstFrame.BitRate;
                xingHeader = XingHeader.LoadXingHeader(firstFrame);
                // If the header exists, we can skip over it when decoding the rest of the file
                if (xingHeader != null)
                {
                    dataStartPosition = mp3Stream.Position;
                }

                // workaround for a longstanding issue with some files failing to load
                // because they report a spurious sample rate change
                var secondFrame = Mp3Frame.LoadFromStream(mp3Stream);
                if (secondFrame != null &&
                    (secondFrame.SampleRate != firstFrame.SampleRate ||
                     secondFrame.ChannelMode != firstFrame.ChannelMode))
                {
                    // assume that the first frame was some kind of VBR/LAME header that we failed to recognise properly
                    dataStartPosition = secondFrame.FileOffset;
                    // forget about the first frame, the second one is the first one we really care about
                    firstFrame = secondFrame;
                }

                mp3DataLength = mp3Stream.Length - dataStartPosition;

                // try for an ID3v1 tag as well
                mp3Stream.Position = mp3Stream.Length - 128;
                byte[] tag = new byte[128];
                mp3Stream.Read(tag, 0, 128);
                if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G')
                {
                    Id3v1Tag       = tag;
                    mp3DataLength -= 128;
                }

                mp3Stream.Position = dataStartPosition;

                // create a temporary MP3 format before we know the real bitrate
                Mp3WaveFormat = new Mp3WaveFormat(firstFrame.SampleRate,
                                                  firstFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, firstFrame.FrameLength, (int)bitRate);

                CreateTableOfContents();
                tocIndex = 0;

                // [Bit rate in Kilobits/sec] = [Length in kbits] / [time in seconds]
                //                            = [Length in bits ] / [time in milliseconds]

                // Note: in audio, 1 kilobit = 1000 bits.
                // Calculated as a double to minimize rounding errors
                bitRate = (mp3DataLength * 8.0 / TotalSeconds());

                mp3Stream.Position = dataStartPosition;

                // now we know the real bitrate we can create an accurate MP3 WaveFormat
                Mp3WaveFormat = new Mp3WaveFormat(firstFrame.SampleRate,
                                                  firstFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, firstFrame.FrameLength, (int)bitRate);
                decompressor   = frameDecompressorBuilder(Mp3WaveFormat);
                waveFormat     = decompressor.OutputFormat;
                bytesPerSample = (decompressor.OutputFormat.BitsPerSample) / 8 * decompressor.OutputFormat.Channels;
                // no MP3 frames have more than 1152 samples in them
                bytesPerDecodedFrame = 1152 * bytesPerSample;
                // some MP3s I seem to get double
                decompressBuffer = new byte[bytesPerDecodedFrame * 2];
            }
            catch (Exception)
            {
                if (ownInputStream)
                {
                    inputStream.Dispose();
                }
                throw;
            }
        }
コード例 #10
0
ファイル: Mp3Frame.cs プロジェクト: asimshah/Music
        /// <summary>
        /// checks if the four bytes represent a valid header,
        /// if they are, will parse the values into Mp3Frame
        /// </summary>
        private static bool IsValidHeader(byte[] headerBytes, Mp3Frame frame)
        {
            if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0))
            {
                // TODO: could do with a bitstream class here
                frame.MpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3);
                if (frame.MpegVersion == MpegVersion.Reserved)
                {
                    //throw new FormatException("Unsupported MPEG Version");
                    return(false);
                }

                frame.MpegLayer = (MpegLayer)((headerBytes[1] & 0x06) >> 1);

                if (frame.MpegLayer == MpegLayer.Reserved)
                {
                    return(false);
                }
                int layerIndex = frame.MpegLayer == MpegLayer.Layer1 ? 0 : frame.MpegLayer == MpegLayer.Layer2 ? 1 : 2;
                frame.CrcPresent   = (headerBytes[1] & 0x01) == 0x00;
                frame.BitRateIndex = (headerBytes[2] & 0xF0) >> 4;
                if (frame.BitRateIndex == 15)
                {
                    // invalid index
                    return(false);
                }
                int versionIndex = frame.MpegVersion == Wave.MpegVersion.Version1 ? 0 : 1;
                frame.BitRate = bitRates[versionIndex, layerIndex, frame.BitRateIndex] * 1000;
                if (frame.BitRate == 0)
                {
                    return(false);
                }
                int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2;
                if (sampleFrequencyIndex == 3)
                {
                    return(false);
                }

                if (frame.MpegVersion == MpegVersion.Version1)
                {
                    frame.SampleRate = sampleRatesVersion1[sampleFrequencyIndex];
                }
                else if (frame.MpegVersion == MpegVersion.Version2)
                {
                    frame.SampleRate = sampleRatesVersion2[sampleFrequencyIndex];
                }
                else
                {
                    // mpegVersion == MpegVersion.Version25
                    frame.SampleRate = sampleRatesVersion25[sampleFrequencyIndex];
                }

                bool padding    = (headerBytes[2] & 0x02) == 0x02;
                bool privateBit = (headerBytes[2] & 0x01) == 0x01;
                frame.ChannelMode      = (ChannelMode)((headerBytes[3] & 0xC0) >> 6);
                frame.ChannelExtension = (headerBytes[3] & 0x30) >> 4;
                if (frame.ChannelExtension != 0 && frame.ChannelMode != ChannelMode.JointStereo)
                {
                    return(false);
                }


                frame.Copyright = (headerBytes[3] & 0x08) == 0x08;
                bool original = (headerBytes[3] & 0x04) == 0x04;
                int  emphasis = (headerBytes[3] & 0x03);

                int nPadding = padding ? 1 : 0;

                frame.SampleCount = samplesPerFrame[versionIndex, layerIndex];
                int coefficient = frame.SampleCount / 8;
                if (frame.MpegLayer == MpegLayer.Layer1)
                {
                    frame.FrameLength = (coefficient * frame.BitRate / frame.SampleRate + nPadding) * 4;
                }
                else
                {
                    frame.FrameLength = (coefficient * frame.BitRate) / frame.SampleRate + nPadding;
                }

                if (frame.FrameLength > MaxFrameLength)
                {
                    return(false);
                }
                return(true);
            }
            return(false);
        }
コード例 #11
0
ファイル: XingHeader.cs プロジェクト: ZhuGongpu/CloudX
        /// <summary>
        /// Load Xing Header
        /// </summary>
        /// <param name="frame">Frame</param>
        /// <returns>Xing Header</returns>
        public static XingHeader LoadXingHeader(Mp3Frame frame)
        {
            XingHeader xingHeader = new XingHeader();
            xingHeader.frame = frame;
            int offset = 0;

            if (frame.MpegVersion == MpegVersion.Version1)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                    offset = 32 + 4;
                else
                    offset = 17 + 4;
            }
            else if (frame.MpegVersion == MpegVersion.Version2)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                    offset = 17 + 4;
                else
                    offset = 9 + 4;
            }
            else
            {
                return null;
                // throw new FormatException("Unsupported MPEG Version");
            }

            if ((frame.RawData[offset + 0] == 'X') &&
                (frame.RawData[offset + 1] == 'i') &&
                (frame.RawData[offset + 2] == 'n') &&
                (frame.RawData[offset + 3] == 'g'))
            {
                xingHeader.startOffset = offset;
                offset += 4;
            }
            else
            {
                return null;
            }

            XingHeaderOptions flags = (XingHeaderOptions)ReadBigEndian(frame.RawData, offset);
            offset += 4;

            if ((flags & XingHeaderOptions.Frames) != 0)
            {
                xingHeader.framesOffset = offset;
                offset += 4;
            }
            if ((flags & XingHeaderOptions.Bytes) != 0)
            {
                xingHeader.bytesOffset = offset;
                offset += 4;
            }
            if ((flags & XingHeaderOptions.Toc) != 0)
            {
                xingHeader.tocOffset = offset;
                offset += 100;
            }
            if ((flags & XingHeaderOptions.VbrScale) != 0)
            {
                xingHeader.vbrScale = ReadBigEndian(frame.RawData, offset);
                offset += 4;
            }
            xingHeader.endOffset = offset;
            return xingHeader;
        }
コード例 #12
0
ファイル: Mp3FileReader.cs プロジェクト: tf2017/toxofone
        /// <summary>
        /// Reads decompressed PCM data from our MP3 file.
        /// </summary>
        public override int Read(byte[] sampleBuffer, int offset, int numBytes)
        {
            int bytesRead = 0;

            lock (repositionLock)
            {
                if (decompressLeftovers != 0)
                {
                    int toCopy = Math.Min(decompressLeftovers, numBytes);
                    Array.Copy(decompressBuffer, decompressBufferOffset, sampleBuffer, offset, toCopy);
                    decompressLeftovers -= toCopy;
                    if (decompressLeftovers == 0)
                    {
                        decompressBufferOffset = 0;
                    }
                    else
                    {
                        decompressBufferOffset += toCopy;
                    }
                    bytesRead += toCopy;
                    offset    += toCopy;
                }

                int targetTocIndex = tocIndex; // the frame index that contains the requested data

                if (repositionedFlag)
                {
                    decompressor.Reset();

                    // Seek back a few frames of the stream to get the reset decoder decode a few
                    // warm-up frames before reading the requested data. Without the warm-up phase,
                    // the first half of the frame after the reset is attenuated and does not resemble
                    // the data as it would be when reading sequentially from the beginning, because
                    // the decoder is missing the required overlap from the previous frame.
                    tocIndex           = Math.Max(0, tocIndex - 3); // no warm-up at the beginning of the stream
                    mp3Stream.Position = tableOfContents[tocIndex].FilePosition;

                    repositionedFlag = false;
                }

                while (bytesRead < numBytes)
                {
                    Mp3Frame frame = ReadNextFrame();
                    if (frame != null)
                    {
                        int decompressed = decompressor.DecompressFrame(frame, decompressBuffer, 0);

                        if (tocIndex <= targetTocIndex || decompressed == 0)
                        {
                            // The first frame after a reset usually does not immediately yield decoded samples.
                            // Because the next instructions will fail if a buffer offset is set and the frame
                            // decoding didn't return data, we skip the part.
                            // We skip the following instructions also after decoding a warm-up frame.
                            continue;
                        }
                        // Two special cases can happen here:
                        // 1. We are interested in the first frame of the stream, but need to read the second frame too
                        //    for the decoder to return decoded data
                        // 2. We are interested in the second frame of the stream, but because reading the first frame
                        //    as warm-up didn't yield any data (because the decoder needs two frames to return data), we
                        //    get data from the first and second frame.
                        //    This case needs special handling, and we have to purge the data of the first frame.
                        else if (tocIndex == targetTocIndex + 1 && decompressed == bytesPerDecodedFrame * 2)
                        {
                            // Purge the first frame's data
                            Array.Copy(decompressBuffer, bytesPerDecodedFrame, decompressBuffer, 0, bytesPerDecodedFrame);
                            decompressed = bytesPerDecodedFrame;
                        }

                        int toCopy = Math.Min(decompressed - decompressBufferOffset, numBytes - bytesRead);
                        Array.Copy(decompressBuffer, decompressBufferOffset, sampleBuffer, offset, toCopy);
                        if ((toCopy + decompressBufferOffset) < decompressed)
                        {
                            decompressBufferOffset = toCopy + decompressBufferOffset;
                            decompressLeftovers    = decompressed - decompressBufferOffset;
                        }
                        else
                        {
                            // no lefovers
                            decompressBufferOffset = 0;
                            decompressLeftovers    = 0;
                        }
                        offset    += toCopy;
                        bytesRead += toCopy;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            Debug.Assert(bytesRead <= numBytes, "MP3 File Reader read too much");
            position += bytesRead;
            return(bytesRead);
        }
コード例 #13
0
ファイル: XingHeader.cs プロジェクト: malebra/Opyum
        /// <summary>
        /// Load Xing Header
        /// </summary>
        /// <param name="frame">Frame</param>
        /// <returns>Xing Header</returns>
        public static XingHeader LoadXingHeader(Mp3Frame frame)
        {
            XingHeader xingHeader = new XingHeader();

            xingHeader.frame = frame;
            int offset = 0;

            if (frame.MpegVersion == MpegVersion.Version1)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                {
                    offset = 32 + 4;
                }
                else
                {
                    offset = 17 + 4;
                }
            }
            else if (frame.MpegVersion == MpegVersion.Version2)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                {
                    offset = 17 + 4;
                }
                else
                {
                    offset = 9 + 4;
                }
            }
            else
            {
                return(null);
                // throw new FormatException("Unsupported MPEG Version");
            }

            if ((frame.RawData[offset + 0] == 'X') &&
                (frame.RawData[offset + 1] == 'i') &&
                (frame.RawData[offset + 2] == 'n') &&
                (frame.RawData[offset + 3] == 'g'))
            {
                xingHeader.startOffset = offset;
                offset += 4;
            }
            else
            {
                return(null);
            }

            XingHeaderOptions flags = (XingHeaderOptions)ReadBigEndian(frame.RawData, offset);

            offset += 4;

            if ((flags & XingHeaderOptions.Frames) != 0)
            {
                xingHeader.framesOffset = offset;
                offset += 4;
            }
            if ((flags & XingHeaderOptions.Bytes) != 0)
            {
                xingHeader.bytesOffset = offset;
                offset += 4;
            }
            if ((flags & XingHeaderOptions.Toc) != 0)
            {
                xingHeader.tocOffset = offset;
                offset += 100;
            }
            if ((flags & XingHeaderOptions.VbrScale) != 0)
            {
                xingHeader.vbrScale = ReadBigEndian(frame.RawData, offset);
                offset += 4;
            }
            xingHeader.endOffset = offset;
            return(xingHeader);
        }
コード例 #14
0
        public void SetupBackend(Mp3Frame frame)
        {
            //first cleanup the the backend. the old MP3 info could be different
            StopPlayer();
            bFileEnding = false;
            //setup the output stream, using the provider & mp3Frame
            waveOut = new NAudio.Wave.DirectSoundOut();

            SetWaveFormat(frame);

            decompressor = new AcmMp3FrameDecompressor(waveFormat);
            out_buffer = new BufferedWaveProvider(decompressor.OutputFormat);
            volumeHandler = new VolumeWaveProvider16(out_buffer);
            //1.0 = full volume, 0.0 = silence
            volumeHandler.Volume = volume;
            waveOut.Init(volumeHandler);

            //signal event we are set up
            if (backendHandler != null)
                backendHandler(this, true);

            waveOut.Play();
        }
コード例 #15
0
        public int AddNextFrame(Mp3Frame frame)
        {
            if (frame == null)
                throw new ArgumentNullException("given frame = null");

            //when receiving data...
            if (out_buffer == null)
            {
                SetupBackend(frame);
            }
            byte[] buffer = new byte[16384 * 50];
            int decompressed = 0;

            if (frame != null)
            {
                decompressed = decompressor.DecompressFrame(frame, buffer, 0);

                if (out_buffer.BufferedBytes + decompressed < out_buffer.BufferLength)
                {
                    out_buffer.AddSamples(buffer, 0, decompressed);//AddSamples(buffer,decompressed);//out_buffer.AddSamples(buffer, 0, decompressed);
                }
            }
            return decompressed;
        }
コード例 #16
0
ファイル: Mp3Frame.cs プロジェクト: hanistory/hasuite
        /// <summary>
        /// checks if the four bytes represent a valid header,
        /// if they are, will parse the values into Mp3Frame
        /// </summary>
        private static bool IsValidHeader(byte[] headerBytes, Mp3Frame frame)
        {
            if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0))
            {
                // TODO: could do with a bitstream class here
                frame.MpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3);
                if (frame.MpegVersion == MpegVersion.Reserved)
                {
                    //throw new FormatException("Unsupported MPEG Version");
                    return false;
                }

                frame.MpegLayer = (MpegLayer)((headerBytes[1] & 0x06) >> 1);

                if (frame.MpegLayer == MpegLayer.Reserved)
                {
                    return false;
                }
                int layerIndex = frame.MpegLayer == MpegLayer.Layer1 ? 0 : frame.MpegLayer == MpegLayer.Layer2 ? 1 : 2;
                frame.crcPresent = (headerBytes[1] & 0x01) == 0x00;
                int bitRateIndex = (headerBytes[2] & 0xF0) >> 4;
                if (bitRateIndex == 15)
                {
                    // invalid index
                    return false;
                }
                int versionIndex = frame.MpegVersion == Wave.MpegVersion.Version1 ? 0 : 1;
                frame.BitRate = bitRates[versionIndex, layerIndex, bitRateIndex] * 1000;
                if (frame.BitRate == 0)
                {
                    return false;
                }
                int sampleFrequencyIndex = (headerBytes[2] & 0x0C) >> 2;
                if (sampleFrequencyIndex == 3)
                {
                    return false;
                }

                if (frame.MpegVersion == MpegVersion.Version1)
                {
                    frame.SampleRate = sampleRatesVersion1[sampleFrequencyIndex];
                }
                else if (frame.MpegVersion == MpegVersion.Version2)
                {
                    frame.SampleRate = sampleRatesVersion2[sampleFrequencyIndex];
                }
                else
                {
                    // mpegVersion == MpegVersion.Version25
                    frame.SampleRate = sampleRatesVersion25[sampleFrequencyIndex];
                }

                bool padding = (headerBytes[2] & 0x02) == 0x02;
                bool privateBit = (headerBytes[2] & 0x01) == 0x01;
                frame.ChannelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6);
                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;

                frame.SampleCount = samplesPerFrame[versionIndex, layerIndex];
                int coefficient = frame.SampleCount / 8;
                if (frame.MpegLayer == MpegLayer.Layer1)
                {
                    frame.FrameLength = (coefficient * frame.BitRate / frame.SampleRate + nPadding) * 4;
                }
                else
                {
                    frame.FrameLength = (coefficient * frame.BitRate) / frame.SampleRate + nPadding;
                }
                
                if (frame.FrameLength > MaxFrameLength)
                {
                    return false;
                }
                return true;
            }
            return false;
        }
コード例 #17
0
        private void _bufferLoop()
        {
            Console.WriteLine("[Buffering thread] Started.");
            _wavebuffer.DiscardOnBufferOverflow = true;

            // Buffering loop
            do
            {
                if (_cancel_buffer.IsCancellationRequested)
                {
                    Console.WriteLine("[Buffering thread] Cancellation requested.");
                    //_cancel_buffer_token.ThrowIfCancellationRequested();
                    //Console.WriteLine("[Buffering thread] WARNING: Cancellation token is not cleanly set!");
                    break;
                }

                // Checking metadata
                if (Metadata != stream.Metadata)
                {
                    this.Metadata = stream.Metadata;
                    Task.Factory.StartNew(() =>
                    {
                        Console.WriteLine("[Buffering thread] Metadata has been changed to \"{0}\"", stream.Metadata);
                        Console.WriteLine("[Buffering thread] Delaying because of the buffering...", stream.Metadata);
                        Thread.Sleep(_wavebuffer.BufferedDuration);
                        Console.WriteLine("[Buffering thread] Exposing metadata NOW.", stream.Metadata);
                        if (MetadataChanged != null)
                            MetadataChanged.Invoke(this, new EventArgs());
                    });
                }

                // Seperated buffer
                long bufferSize = 1024
                    * (Codec == StreamCodec.MP3 ? 128 : 8); // 128 kB for MP3, 8 kB for OGG/AACplus
                byte[] buffer = new byte[bufferSize];
                int decompressedLength = 0;

                switch (Codec)
                {
                    case StreamCodec.MP3:
                        // Decompress the frame
                        decompressedLength = _decoderMp3.DecompressFrame(frame, buffer, 0);

                        // Read next frame
                        frame = Mp3Frame.LoadFromStream(stream);

                        // Add the decompressed frame (samples) into the audio buffer for later playback
                        _wavebuffer.AddSamples(buffer, 0, decompressedLength);
                        break;
                    default:
                        throw new NotSupportedException();
                }

            } while (true);

            _decoderMp3.Dispose();
            stream.Close();
            stream.Dispose();
        }
コード例 #18
0
        private static bool IsValidHeader(byte[] headerBytes, Mp3Frame frame)
        {
            if (headerBytes[0] != 255 || (headerBytes[1] & 224) != 224)
            {
                return(false);
            }
            frame.MpegVersion = (MpegVersion)((headerBytes[1] & 24) >> 3);
            if (frame.MpegVersion == MpegVersion.Reserved)
            {
                return(false);
            }
            frame.MpegLayer = (MpegLayer)((headerBytes[1] & 6) >> 1);
            if (frame.MpegLayer == MpegLayer.Reserved)
            {
                return(false);
            }
            int num = (frame.MpegLayer == MpegLayer.Layer1) ? 0 : ((frame.MpegLayer == MpegLayer.Layer2) ? 1 : 2);

            frame.CrcPresent   = ((headerBytes[1] & 1) == 0);
            frame.BitRateIndex = (headerBytes[2] & 240) >> 4;
            if (frame.BitRateIndex == 15)
            {
                return(false);
            }
            int num2 = (frame.MpegVersion == MpegVersion.Version1) ? 0 : 1;

            frame.BitRate = Mp3Frame.bitRates[num2, num, frame.BitRateIndex] * 1000;
            if (frame.BitRate == 0)
            {
                return(false);
            }
            int num3 = (headerBytes[2] & 12) >> 2;

            if (num3 == 3)
            {
                return(false);
            }
            if (frame.MpegVersion == MpegVersion.Version1)
            {
                frame.SampleRate = Mp3Frame.sampleRatesVersion1[num3];
            }
            else if (frame.MpegVersion == MpegVersion.Version2)
            {
                frame.SampleRate = Mp3Frame.sampleRatesVersion2[num3];
            }
            else
            {
                frame.SampleRate = Mp3Frame.sampleRatesVersion25[num3];
            }
            bool flag = (headerBytes[2] & 2) == 2;
            byte b    = headerBytes[2];

            frame.ChannelMode      = (ChannelMode)((headerBytes[3] & 192) >> 6);
            frame.ChannelExtension = (headerBytes[3] & 48) >> 4;
            if (frame.ChannelExtension != 0 && frame.ChannelMode != ChannelMode.JointStereo)
            {
                return(false);
            }
            frame.Copyright = ((headerBytes[3] & 8) == 8);
            byte b2   = headerBytes[3];
            byte b3   = headerBytes[3];
            int  num4 = flag ? 1 : 0;

            frame.SampleCount = Mp3Frame.samplesPerFrame[num2, num];
            int num5 = frame.SampleCount / 8;

            if (frame.MpegLayer == MpegLayer.Layer1)
            {
                frame.FrameLength = (num5 * frame.BitRate / frame.SampleRate + num4) * 4;
            }
            else
            {
                frame.FrameLength = num5 * frame.BitRate / frame.SampleRate + num4;
            }
            return(frame.FrameLength <= 16384);
        }
コード例 #19
0
 public static Mp3Frame LoadFromStream(Stream input)
 {
     return(Mp3Frame.LoadFromStream(input, true));
 }
コード例 #20
0
        public void SetWaveFormat(Mp3Frame frame)
        {
            if (frame == null)
                return;

            waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
                        frame.FrameLength, frame.BitRate);

            return;
        }
コード例 #21
0
ファイル: XingHeader.cs プロジェクト: h4ltYu/EOS
        public static XingHeader LoadXingHeader(Mp3Frame frame)
        {
            XingHeader xingHeader = new XingHeader();

            xingHeader.frame = frame;
            int num;

            if (frame.MpegVersion == MpegVersion.Version1)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                {
                    num = 36;
                }
                else
                {
                    num = 21;
                }
            }
            else
            {
                if (frame.MpegVersion != MpegVersion.Version2)
                {
                    return(null);
                }
                if (frame.ChannelMode != ChannelMode.Mono)
                {
                    num = 21;
                }
                else
                {
                    num = 13;
                }
            }
            if (frame.RawData[num] == 88 && frame.RawData[num + 1] == 105 && frame.RawData[num + 2] == 110 && frame.RawData[num + 3] == 103)
            {
                xingHeader.startOffset = num;
                num += 4;
                XingHeader.XingHeaderOptions xingHeaderOptions = (XingHeader.XingHeaderOptions)XingHeader.ReadBigEndian(frame.RawData, num);
                num += 4;
                if ((xingHeaderOptions & XingHeader.XingHeaderOptions.Frames) != (XingHeader.XingHeaderOptions) 0)
                {
                    xingHeader.framesOffset = num;
                    num += 4;
                }
                if ((xingHeaderOptions & XingHeader.XingHeaderOptions.Bytes) != (XingHeader.XingHeaderOptions) 0)
                {
                    xingHeader.bytesOffset = num;
                    num += 4;
                }
                if ((xingHeaderOptions & XingHeader.XingHeaderOptions.Toc) != (XingHeader.XingHeaderOptions) 0)
                {
                    xingHeader.tocOffset = num;
                    num += 100;
                }
                if ((xingHeaderOptions & XingHeader.XingHeaderOptions.VbrScale) != (XingHeader.XingHeaderOptions) 0)
                {
                    xingHeader.vbrScale = XingHeader.ReadBigEndian(frame.RawData, num);
                    num += 4;
                }
                xingHeader.endOffset = num;
                return(xingHeader);
            }
            return(null);
        }
コード例 #22
0
        private void _buffer(Stream input)
        {
            Console.WriteLine("[Initial buffering] Meta interval: {0}", this.StationInformation.ContainsKey("icy-metaint") ? long.Parse(this.StationInformation["icy-metaint"]) : -1);

            // Auto-fix the stream and auto-parse metadata
            stream =
                new FixedBufferedStream(
                    input,
                    this.StationInformation.ContainsKey("icy-metaint") ? long.Parse(this.StationInformation["icy-metaint"]) : -1
                );

            // Read first frame
            this.Status = StreamStatus.Buffering;
            switch (Codec)
            {
                case StreamCodec.MP3:
                    // Make a decoder which can decode that (and sequentially following) frames
                    // The decoder will decode to 16-bit samples
                    frame = Mp3Frame.LoadFromStream(stream);
                    _decoderMp3 = new AcmMp3FrameDecompressor(new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate));
                    Console.WriteLine("[Initial buffering] MP3 decoder will encode to {0}-encoded wave format.", _decoderMp3.OutputFormat.Encoding);
                    break;
                default:
                    throw new NotSupportedException();
            }
        }
コード例 #23
0
ファイル: Mp3FrameTests.cs プロジェクト: RasterCode/OtterUI
 public void CanParseValidMp3Frame()
 {
     MemoryStream ms = new MemoryStream(constructValidMp3Frame());
     Mp3Frame frame = new Mp3Frame(ms);
 }
コード例 #24
0
ファイル: Mp3FrameInfo.cs プロジェクト: klad/splitstream
 public Mp3FrameInfo(Mp3Frame frame, double averageVolume)
 {
     this.Frame = frame;
     _averageVolume = averageVolume;
 }
コード例 #25
0
ファイル: Mp3FrameTests.cs プロジェクト: RasterCode/OtterUI
 public void FailsToParseInvalidFrame(int length)
 {
     MemoryStream ms = new MemoryStream(new byte[length]);
     Assert.Throws<EndOfStreamException>(() => { Mp3Frame frame = new Mp3Frame(ms); });
 }
コード例 #26
0
ファイル: Mp3FileReader.cs プロジェクト: ZhuGongpu/CloudX
 private void ValidateFrameFormat(Mp3Frame frame)
 {
     if (frame.SampleRate != Mp3WaveFormat.SampleRate)
     {
         string message =
             String.Format(
                 "Got a frame at sample rate {0}, in an MP3 with sample rate {1}. Mp3FileReader does not support sample rate changes.",
                 frame.SampleRate, Mp3WaveFormat.SampleRate);
         throw new InvalidOperationException(message);
     }
     int channels = frame.ChannelMode == ChannelMode.Mono ? 1 : 2;
     if (channels != Mp3WaveFormat.Channels)
     {
         string message =
             String.Format(
                 "Got a frame with channel mode {0}, in an MP3 with {1} channels. Mp3FileReader does not support changes to channel count.",
                 frame.ChannelMode, Mp3WaveFormat.Channels);
         throw new InvalidOperationException(message);
     }
 }
コード例 #27
0
ファイル: Recorder.cs プロジェクト: klad/splitstream
        private int DecompressFrame(Mp3Frame frame, byte[] buffer)
        {
            // decode frame
            if (_decompressor == null)
            {
                WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
                _decompressor = new AcmMp3FrameDecompressor(waveFormat);

                _waveProvider = new BufferedWaveProvider(_decompressor.OutputFormat);
                _waveProvider.BufferDuration = TimeSpan.FromSeconds(5);

                _channels = _waveProvider.WaveFormat.Channels;
                
                _sampleProvider = _waveProvider.ToSampleProvider();
            }

            return _decompressor.DecompressFrame(frame, buffer, 0);
        }