public static CMp3Frame LoadFromBytes(BufferedData input) { var frame = new CMp3Frame(); byte[] headerBytes = new byte[4]; int bytesRead = input.Read(headerBytes, 0, headerBytes.Length); if (bytesRead == 0) { return(null); } while (!IsValidHeader(headerBytes, frame)) { headerBytes[0] = headerBytes[1]; headerBytes[1] = headerBytes[2]; headerBytes[2] = headerBytes[3]; bytesRead = input.Read(headerBytes, 3, 1); if (bytesRead == 0) { return(null); } } int bytesRequired = frame.FrameLength - 4; frame.RawData = new byte[frame.FrameLength]; Array.Copy(headerBytes, frame.RawData, 4); bytesRead = input.Read(frame.RawData, 4, bytesRequired); if (bytesRead == 0) { return(null); } return(frame); }
private static CAcmMp3FrameDecompressor CreateFrameDecompressor(CMp3Frame frame) { WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); return(new CAcmMp3FrameDecompressor(waveFormat)); }
/// <summary>Reads an CMp3Frame 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 CMp3Frame LoadFromStream(Stream input, bool readData) { var frame = new CMp3Frame(); 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) { return(null); } } else { // n.b. readData should not be false if input stream does not support seeking input.Position += bytesRequired; } return(frame); }
/// <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(CMp3Frame 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); }
private void Mp3Running(object state) { CAcmMp3FrameDecompressor decompressor = null; try { do { CMp3Frame frame = CMp3Frame.LoadFromBytes(_bufferedData); if (frame == null) { continue; } if (decompressor == null) { decompressor = CreateFrameDecompressor(frame); bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat); bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); } int decompressed = decompressor.DecompressFrame(frame, buffer, 0); bufferedWaveProvider.AddSamples(buffer, 0, decompressed); }while (playbackState != StreamingPlaybackState.Stopped); } catch (Exception) { } finally { StopPlayback(); if (decompressor != null) { decompressor.Dispose(); } } }
/// <summary> /// checks if the four bytes represent a valid header, /// if they are, will parse the values into CMp3Frame /// </summary> private static bool IsValidHeader(byte[] headerBytes, CMp3Frame 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 == NAudio.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); }