using System; using System.Collections.Generic; using System.Text; using NAudio.Dmo; using NAudio.Wave; using System.Diagnostics; namespace NAudio.FileFormats.Mp3 { /// /// MP3 Frame decompressor using the Windows Media MP3 Decoder DMO object /// public class DmoMp3FrameDecompressor : IMp3FrameDecompressor { private WindowsMediaMp3Decoder mp3Decoder; private WaveFormat pcmFormat; private MediaBuffer inputMediaBuffer; private DmoOutputDataBuffer outputBuffer; private bool reposition; /// /// Initializes a new instance of the DMO MP3 Frame decompressor /// /// public DmoMp3FrameDecompressor(WaveFormat sourceFormat) { this.mp3Decoder = new WindowsMediaMp3Decoder(); if (!mp3Decoder.MediaObject.SupportsInputWaveFormat(0, sourceFormat)) { throw new ArgumentException("Unsupported input format"); } mp3Decoder.MediaObject.SetInputWaveFormat(0, sourceFormat); pcmFormat = new WaveFormat(sourceFormat.SampleRate, sourceFormat.Channels); // 16 bit if (!mp3Decoder.MediaObject.SupportsOutputWaveFormat(0, pcmFormat)) { throw new ArgumentException(String.Format("Unsupported output format {0}", pcmFormat)); } mp3Decoder.MediaObject.SetOutputWaveFormat(0, pcmFormat); // a second is more than enough to decompress a frame at a time inputMediaBuffer = new MediaBuffer(sourceFormat.AverageBytesPerSecond); outputBuffer = new DmoOutputDataBuffer(pcmFormat.AverageBytesPerSecond); } /// /// Converted PCM WaveFormat /// public WaveFormat OutputFormat { get { return pcmFormat; } } /// /// Decompress a single frame of MP3 /// public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset) { // 1. copy into our DMO's input buffer inputMediaBuffer.LoadData(frame.RawData, frame.FrameLength); if (reposition) { mp3Decoder.MediaObject.Flush(); reposition = false; } // 2. Give the input buffer to the DMO to process mp3Decoder.MediaObject.ProcessInput(0, inputMediaBuffer, DmoInputDataBufferFlags.None, 0, 0); outputBuffer.MediaBuffer.SetLength(0); outputBuffer.StatusFlags = DmoOutputDataBufferFlags.None; // 3. Now ask the DMO for some output data mp3Decoder.MediaObject.ProcessOutput(DmoProcessOutputFlags.None, 1, new[] { outputBuffer }); if (outputBuffer.Length == 0) { Debug.WriteLine("ResamplerDmoStream.Read: No output data available"); return 0; } // 5. Now get the data out of the output buffer outputBuffer.RetrieveData(dest, destOffset); Debug.Assert(!outputBuffer.MoreDataAvailable, "have not implemented more data available yet"); return outputBuffer.Length; } /// /// Alerts us that a reposition has occured so the MP3 decoder needs to reset its state /// public void Reset() { reposition = true; } /// /// Dispose of this obejct and clean up resources /// public void Dispose() { if (inputMediaBuffer != null) { inputMediaBuffer.Dispose(); inputMediaBuffer = null; } outputBuffer.Dispose(); if (mp3Decoder!= null) { mp3Decoder.Dispose(); mp3Decoder = null; } } } }