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; }