示例#1
0
        private void ParseMp3Frames(byte[] buffer)
        {
            var mpeg1BitRate     = new[] { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 };
            var mpeg2XBitRate    = new[] { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 };
            var mpeg1SampleRate  = new[] { 44100, 48000, 32000, 0 };
            var mpeg20SampleRate = new[] { 22050, 24000, 16000, 0 };
            var mpeg25SampleRate = new[] { 11025, 12000, 8000, 0 };

            int offset = 0;
            int length = buffer.Length;

            while (length >= 4)
            {
                int mpegVersion, sampleRate, channelMode;

                ulong header = (ulong)BigEndianBitConverter.ToUInt32(buffer, offset) << 32;

                if (BitHelper.Read(ref header, 11) != 0x7FF)
                {
                    break;
                }

                mpegVersion = BitHelper.Read(ref header, 2);
                int layer = BitHelper.Read(ref header, 2);
                BitHelper.Read(ref header, 1);
                int bitRate = BitHelper.Read(ref header, 4);
                sampleRate = BitHelper.Read(ref header, 2);
                int padding = BitHelper.Read(ref header, 1);
                BitHelper.Read(ref header, 1);
                channelMode = BitHelper.Read(ref header, 2);

                if (mpegVersion == 1 || layer != 1 || bitRate == 0 || bitRate == 15 || sampleRate == 3)
                {
                    break;
                }

                bitRate = (mpegVersion == 3 ? mpeg1BitRate[bitRate] : mpeg2XBitRate[bitRate]) * 1000;

                switch (mpegVersion)
                {
                case 2:
                    sampleRate = mpeg20SampleRate[sampleRate];
                    break;

                case 3:
                    sampleRate = mpeg1SampleRate[sampleRate];
                    break;

                default:
                    sampleRate = mpeg25SampleRate[sampleRate];
                    break;
                }

                int frameLenght = GetFrameLength(mpegVersion, bitRate, sampleRate, padding);

                if (frameLenght > length)
                {
                    break;
                }

                bool isVbrHeaderFrame = false;

                if (frameOffsets.Count == 0)
                {
                    // Check for an existing VBR header just to be safe (I haven't seen any in FLVs)
                    int o = offset + GetFrameDataOffset(mpegVersion, channelMode);

                    if (BigEndianBitConverter.ToUInt32(buffer, o) == 0x58696E67)
                    {
                        // "Xing"
                        isVbrHeaderFrame  = true;
                        this.delayWrite   = false;
                        this.hasVbrHeader = true;
                    }
                }

                if (!isVbrHeaderFrame)
                {
                    if (this.firstBitRate == 0)
                    {
                        this.firstBitRate     = bitRate;
                        this.mpegVersion      = mpegVersion;
                        this.sampleRate       = sampleRate;
                        this.channelMode      = channelMode;
                        this.firstFrameHeader = BigEndianBitConverter.ToUInt32(buffer, offset);
                    }

                    else if (!this.isVbr && bitRate != this.firstBitRate)
                    {
                        this.isVbr = true;

                        if (!this.hasVbrHeader)
                        {
                            if (this.delayWrite)
                            {
                                this.WriteVbrHeader(true);
                                this.writeVbrHeader = true;
                                this.delayWrite     = false;
                            }

                            else
                            {
                                this.warnings.Add("Detected VBR too late, cannot add VBR header.");
                            }
                        }
                    }
                }

                this.frameOffsets.Add(this.totalFrameLength + (uint)offset);

                offset += frameLenght;
                length -= frameLenght;
            }

            this.totalFrameLength += (uint)buffer.Length;
        }