256 lines
7.8 KiB
C#
256 lines
7.8 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace NAudio.Dmo.Effect
|
|
{
|
|
internal struct DsFxEcho
|
|
{
|
|
public float WetDryMix;
|
|
public float FeedBack;
|
|
public float LeftDelay;
|
|
public float RightDelay;
|
|
public EchoPanDelay PanDelay;
|
|
}
|
|
|
|
[ComImport,
|
|
System.Security.SuppressUnmanagedCodeSecurity,
|
|
Guid("8bd28edf-50db-4e92-a2bd-445488d1ed42"),
|
|
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
interface IDirectSoundFXEcho
|
|
{
|
|
[PreserveSig]
|
|
int SetAllParameters([In] ref DsFxEcho param);
|
|
|
|
[PreserveSig]
|
|
int GetAllParameters(out DsFxEcho param);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dmo Echo Effect
|
|
/// </summary>
|
|
public class DmoEcho : IDmoEffector<DmoEcho.Params>
|
|
{
|
|
/// <summary>
|
|
/// DMO Echo Params
|
|
/// </summary>
|
|
public struct Params
|
|
{
|
|
/// <summary>
|
|
/// DSFXECHO_WETDRYMIX_MIN
|
|
/// </summary>
|
|
public const float WetDryMixMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_WETDRYMIX_MAX
|
|
/// </summary>
|
|
public const float WetDryMixMax = 100.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_WETDRYMIX_DEFAULT
|
|
/// </summary>
|
|
public const float WetDeyMixDefault = 50.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXECHO_FEEDBACK_MIN
|
|
/// </summary>
|
|
public const float FeedBackMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_FEEDBACK_MAX
|
|
/// </summary>
|
|
public const float FeedBackMax = 100.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_FEEDBACK_DEFAULT
|
|
/// </summary>
|
|
public const float FeedBackDefault = 50.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXECHO_LEFTDELAY_MIN
|
|
/// </summary>
|
|
public const float LeftDelayMin = 1.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_LEFTDELAY_MAX
|
|
/// </summary>
|
|
public const float LeftDelayMax = 2000.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_LEFTDELAY_DEFAULT
|
|
/// </summary>
|
|
public const float LeftDelayDefault = 500.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXECHO_RIGHTDELAY_MIN
|
|
/// </summary>
|
|
public const float RightDelayMin = 1.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_RIGHTDELAY_MAX
|
|
/// </summary>
|
|
public const float RightDelayMax = 2000.0f;
|
|
/// <summary>
|
|
/// DSFXECHO_RIGHTDELAY_DEFAULT
|
|
/// </summary>
|
|
public const float RightDelayDefault = 500.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXECHO_PANDELAY_DEFAULT
|
|
/// </summary>
|
|
public const EchoPanDelay PanDelayDefault = EchoPanDelay.Off;
|
|
|
|
/// <summary>
|
|
/// Ratio of wet (processed) signal to dry (unprocessed) signal.
|
|
/// </summary>
|
|
public float WetDryMix
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.WetDryMix;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.WetDryMix = Math.Max(Math.Min(WetDryMixMax, value), WetDryMixMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Percentage of output fed back into input.
|
|
/// </summary>
|
|
public float FeedBack
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.FeedBack;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.FeedBack = Math.Max(Math.Min(FeedBackMax, value), FeedBackMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delay for left channel, in milliseconds.
|
|
/// </summary>
|
|
public float LeftDelay
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.LeftDelay;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.LeftDelay = Math.Max(Math.Min(LeftDelayMax, value), LeftDelayMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delay for right channel, in milliseconds.
|
|
/// </summary>
|
|
public float RightDelay
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.RightDelay;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.RightDelay = Math.Max(Math.Min(RightDelayMax, value), RightDelayMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Value that specifies whether to swap left and right delays with each successive echo.
|
|
/// </summary>
|
|
public EchoPanDelay PanDelay
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.PanDelay;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
if (Enum.IsDefined(typeof(EchoPanDelay), value))
|
|
{
|
|
param.PanDelay = value;
|
|
}
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
private readonly IDirectSoundFXEcho fxEcho;
|
|
|
|
internal Params(IDirectSoundFXEcho dsFxObject)
|
|
{
|
|
fxEcho = dsFxObject;
|
|
}
|
|
|
|
private void SetAllParameters(DsFxEcho param)
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxEcho.SetAllParameters(ref param));
|
|
}
|
|
|
|
private DsFxEcho GetAllParameters()
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxEcho.GetAllParameters(out var param));
|
|
return param;
|
|
}
|
|
}
|
|
|
|
private readonly MediaObject mediaObject;
|
|
private readonly MediaObjectInPlace mediaObjectInPlace;
|
|
private readonly Params effectParams;
|
|
|
|
/// <summary>
|
|
/// Media Object
|
|
/// </summary>
|
|
public MediaObject MediaObject => mediaObject;
|
|
|
|
/// <summary>
|
|
/// Media Object InPlace
|
|
/// </summary>
|
|
public MediaObjectInPlace MediaObjectInPlace => mediaObjectInPlace;
|
|
|
|
/// <summary>
|
|
/// Effect Parameter
|
|
/// </summary>
|
|
public Params EffectParams => effectParams;
|
|
|
|
/// <summary>
|
|
/// Create new DMO Echo
|
|
/// </summary>
|
|
public DmoEcho()
|
|
{
|
|
var guidEcho = new Guid("EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D");
|
|
|
|
var targetDescriptor = DmoEnumerator.GetAudioEffectNames().First(descriptor =>
|
|
Equals(descriptor.Clsid, guidEcho));
|
|
|
|
if (targetDescriptor != null)
|
|
{
|
|
var mediaComObject = Activator.CreateInstance(Type.GetTypeFromCLSID(targetDescriptor.Clsid));
|
|
|
|
mediaObject = new MediaObject((IMediaObject) mediaComObject);
|
|
mediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace) mediaComObject);
|
|
effectParams = new Params((IDirectSoundFXEcho) mediaComObject);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose code
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
mediaObjectInPlace?.Dispose();
|
|
mediaObject?.Dispose();
|
|
}
|
|
}
|
|
} |