MVH/NAudio-2.2.1/NAudio.Wasapi/DmoMp3FrameDecompressor.cs
2024-06-07 00:47:07 +02:00

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