using System;
using NAudio.Dmo;
using NAudio.Dmo.Effect;
// ReSharper disable once CheckNamespace
namespace NAudio.Wave
{
///
/// Provide WaveProvider that can apply effects in real time using DMO.
///
/// If the audio thread is running on the STA thread, please generate and operate from the same thread.
/// If the audio thread is running on the MTA thread, please operate on any MTA thread.
///
/// Types of DMO effectors to use
/// Parameters of the effect to be used
public class DmoEffectWaveProvider : IWaveProvider, IDisposable
where TDmoEffector : IDmoEffector, new()
{
private readonly IWaveProvider inputProvider;
private readonly IDmoEffector effector;
///
/// Create a new DmoEffectWaveProvider
///
/// Input Stream
public DmoEffectWaveProvider(IWaveProvider inputProvider)
{
this.inputProvider = inputProvider;
effector = new TDmoEffector();
var mediaObject = effector.MediaObject;
if (mediaObject == null)
{
throw new NotSupportedException(@"Dmo Effector Not Supported: " + nameof(TDmoEffector));
}
if (!mediaObject.SupportsInputWaveFormat(0, inputProvider.WaveFormat))
{
throw new ArgumentException(@"Unsupported Input Stream format", nameof(inputProvider));
}
mediaObject.AllocateStreamingResources();
mediaObject.SetInputWaveFormat(0, this.inputProvider.WaveFormat);
mediaObject.SetOutputWaveFormat(0, this.inputProvider.WaveFormat);
}
///
/// Stream Wave Format
///
public WaveFormat WaveFormat => inputProvider.WaveFormat;
///
/// Reads data from input stream
///
/// buffer
/// offset into buffer
/// Bytes required
/// Number of bytes read
public int Read(byte[] buffer, int offset, int count)
{
var readNum = inputProvider.Read(buffer, offset, count);
if (effector == null)
{
return readNum;
}
if (effector.MediaObjectInPlace.Process(readNum, offset, buffer, 0, DmoInPlaceProcessFlags.Normal)
== DmoInPlaceProcessReturn.HasEffectTail)
{
var effectTail = new byte[readNum];
while (effector.MediaObjectInPlace.Process(readNum, 0, effectTail, 0, DmoInPlaceProcessFlags.Zero) ==
DmoInPlaceProcessReturn.HasEffectTail)
{
}
}
return readNum;
}
///
/// Get Effector Parameters
///
public TEffectorParam EffectParams => effector.EffectParams;
///
/// Dispose
///
public void Dispose()
{
if (effector != null)
{
effector.MediaObject.FreeStreamingResources();
effector.Dispose();
}
}
}
}