113 lines
3.9 KiB
C#
113 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using NAudio.Dmo;
|
|
using NAudio.Wave;
|
|
using System.Diagnostics;
|
|
|
|
namespace NAudio.FileFormats.Mp3
|
|
{
|
|
/// <summary>
|
|
/// MP3 Frame decompressor using the Windows Media MP3 Decoder DMO object
|
|
/// </summary>
|
|
public class DmoMp3FrameDecompressor : IMp3FrameDecompressor
|
|
{
|
|
private WindowsMediaMp3Decoder mp3Decoder;
|
|
private WaveFormat pcmFormat;
|
|
private MediaBuffer inputMediaBuffer;
|
|
private DmoOutputDataBuffer outputBuffer;
|
|
private bool reposition;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the DMO MP3 Frame decompressor
|
|
/// </summary>
|
|
/// <param name="sourceFormat"></param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converted PCM WaveFormat
|
|
/// </summary>
|
|
public WaveFormat OutputFormat { get { return pcmFormat; } }
|
|
|
|
/// <summary>
|
|
/// Decompress a single frame of MP3
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Alerts us that a reposition has occured so the MP3 decoder needs to reset its state
|
|
/// </summary>
|
|
public void Reset()
|
|
{
|
|
reposition = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose of this obejct and clean up resources
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
if (inputMediaBuffer != null)
|
|
{
|
|
inputMediaBuffer.Dispose();
|
|
inputMediaBuffer = null;
|
|
}
|
|
outputBuffer.Dispose();
|
|
if (mp3Decoder!= null)
|
|
{
|
|
mp3Decoder.Dispose();
|
|
mp3Decoder = null;
|
|
}
|
|
}
|
|
}
|
|
}
|