543 lines
18 KiB
C#
543 lines
18 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace NAudio.Dmo.Effect
|
|
{
|
|
internal struct DsFxI3Dl2Reverb
|
|
{
|
|
public int Room;
|
|
public int RoomHf;
|
|
public float RoomRollOffFactor;
|
|
public float DecayTime;
|
|
public float DecayHfRatio;
|
|
public int Reflections;
|
|
public float ReflectionsDelay;
|
|
public int Reverb;
|
|
public float ReverbDelay;
|
|
public float Diffusion;
|
|
public float Density;
|
|
public float HfReference;
|
|
}
|
|
|
|
[ComImport,
|
|
System.Security.SuppressUnmanagedCodeSecurity,
|
|
Guid("4b166a6a-0d66-43f3-80e3-ee6280dee1a4"),
|
|
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
interface IDirectSoundFXI3DL2Reverb
|
|
{
|
|
[PreserveSig]
|
|
int SetAllParameters([In] ref DsFxI3Dl2Reverb param);
|
|
|
|
[PreserveSig]
|
|
int GetAllParameters(out DsFxI3Dl2Reverb param);
|
|
|
|
[PreserveSig]
|
|
int SetPreset([In] uint preset);
|
|
|
|
[PreserveSig]
|
|
int GetPreset(out uint preset);
|
|
|
|
[PreserveSig]
|
|
int SetQuality([In] int quality);
|
|
|
|
[PreserveSig]
|
|
int GetQuality(out int quality);
|
|
}
|
|
|
|
/// <summary>
|
|
/// DMO I3DL2Reverb Effect
|
|
/// </summary>
|
|
public class DmoI3DL2Reverb : IDmoEffector<DmoI3DL2Reverb.Params>
|
|
{
|
|
/// <summary>
|
|
/// DMO I3DL2Reverb Params
|
|
/// </summary>
|
|
public struct Params
|
|
{
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOM_MIN
|
|
/// </summary>
|
|
public const int RoomMin = -10000;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOM_MAX
|
|
/// </summary>
|
|
public const int RoomMax = 0;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOM_DEFAULT
|
|
/// </summary>
|
|
public const int RoomDefault = -1000;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOMHF_MIN
|
|
/// </summary>
|
|
public const int RoomHfMin = -10000;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOMHF_MAX
|
|
/// </summary>
|
|
public const int RoomHfMax = 0;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOMHF_DEFAULT
|
|
/// </summary>
|
|
public const int RoomHfDefault = -100;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MIN
|
|
/// </summary>
|
|
public const float RoomRollOffFactorMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MAX
|
|
/// </summary>
|
|
public const float RoomRollOffFactorMax = 10.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT
|
|
/// </summary>
|
|
public const float RoomRollOffFactorDefault = 0.0f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DECAYTIME_MIN
|
|
/// </summary>
|
|
public const float DecayTimeMin = 0.1f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DECAYTIME_MAX
|
|
/// </summary>
|
|
public const float DecayTimeMax = 20.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DECAYTIME_DEFAULT
|
|
/// </summary>
|
|
public const float DecayTimeDefault = 1.49f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DECAYHFRATIO_MIN
|
|
/// </summary>
|
|
public const float DecayHfRatioMin = 0.1f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DECAYHFRATIO_MAX
|
|
/// </summary>
|
|
public const float DecayHfRatioMax = 2.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT
|
|
/// </summary>
|
|
public const float DecayHfRatioDefault = 0.83f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REFLECTIONS_MIN
|
|
/// </summary>
|
|
public const int ReflectionsMin = -10000;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REFLECTIONS_MAX
|
|
/// </summary>
|
|
public const int ReflectionsMax = 1000;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT
|
|
/// </summary>
|
|
public const int ReflectionsDefault = -2602;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REFLECTIONSDELAY_MIN
|
|
/// </summary>
|
|
public const float ReflectionsDelayMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REFLECTIONSDELAY_MAX
|
|
/// </summary>
|
|
public const float ReflectionsDelayMax = 0.3f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT
|
|
/// </summary>
|
|
public const float ReflectionsDelayDefault = 0.007f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REVERB_MIN
|
|
/// </summary>
|
|
public const int ReverbMin = -10000;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REVERB_MAX
|
|
/// </summary>
|
|
public const int ReverbMax = 2000;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REVERB_DEFAULT
|
|
/// </summary>
|
|
public const int ReverbDefault = 200;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REVERBDELAY_MIN
|
|
/// </summary>
|
|
public const float ReverbDelayMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REVERBDELAY_MAX
|
|
/// </summary>
|
|
public const float ReverbDelayMax = 0.1f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT
|
|
/// </summary>
|
|
public const float ReverbDelayDefault = 0.011f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DIFFUSION_MIN
|
|
/// </summary>
|
|
public const float DiffusionMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DIFFUSION_MAX
|
|
/// </summary>
|
|
public const float DiffusionMax = 100.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DIFFUSION_DEFAULT
|
|
/// </summary>
|
|
public const float DiffusionDefault = 100.0f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DENSITY_MIN
|
|
/// </summary>
|
|
public const float DensityMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DENSITY_MAX
|
|
/// </summary>
|
|
public const float DensityMax = 100.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_DENSITY_DEFAULT
|
|
/// </summary>
|
|
public const float DensityDefault = 100.0f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_HFREFERENCE_MIN
|
|
/// </summary>
|
|
public const float HfReferenceMin = 20.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_HFREFERENCE_MAX
|
|
/// </summary>
|
|
public const float HfReferenceMax = 20000.0f;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT
|
|
/// </summary>
|
|
public const float HfReferenceDefault = 5000.0f;
|
|
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_QUALITY_MIN
|
|
/// </summary>
|
|
public const int QualityMin = 0;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_QUALITY_MAX
|
|
/// </summary>
|
|
public const int QualityMax = 3;
|
|
/// <summary>
|
|
/// DSFX_I3DL2REVERB_QUALITY_DEFAULT
|
|
/// </summary>
|
|
public const int QualityDefault = 2;
|
|
|
|
/// <summary>
|
|
/// Attenuation of the room effect, in millibels (mB)
|
|
/// </summary>
|
|
public int Room
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Room;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Room = Math.Max(Math.Min(RoomMax, value), RoomMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attenuation of the room high-frequency effect, in mB.
|
|
/// </summary>
|
|
public int RoomHf
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.RoomHf;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.RoomHf = Math.Max(Math.Min(RoomHfMax, value), RoomHfMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rolloff factor for the reflected signals.
|
|
/// </summary>
|
|
public float RoomRollOffFactor
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.RoomRollOffFactor;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.RoomRollOffFactor = Math.Max(Math.Min(RoomRollOffFactorMax, value), RoomRollOffFactorMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Decay time, in seconds.
|
|
/// </summary>
|
|
public float DecayTime
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.DecayTime;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.DecayTime = Math.Max(Math.Min(DecayTimeMax, value), DecayTimeMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ratio of the decay time at high frequencies to the decay time at low frequencies.
|
|
/// </summary>
|
|
public float DecayHfRatio
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.DecayHfRatio;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.DecayHfRatio = Math.Max(Math.Min(DecayHfRatioMax, value), DecayHfRatioMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attenuation of early reflections relative to lRoom, in mB.
|
|
/// </summary>
|
|
public int Reflections
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Reflections;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Reflections = Math.Max(Math.Min(ReflectionsMax, value), ReflectionsMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delay time of the first reflection relative to the direct path, in seconds.
|
|
/// </summary>
|
|
public float ReflectionsDelay
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.ReflectionsDelay;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.ReflectionsDelay = Math.Max(Math.Min(ReflectionsDelayMax, value), ReflectionsDelayMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attenuation of late reverberation relative to lRoom, in mB.
|
|
/// </summary>
|
|
public int Reverb
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Reverb;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Reverb = Math.Max(Math.Min(ReverbMax, value), ReverbMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Time limit between the early reflections and the late reverberation relative to the time of the first reflection.
|
|
/// </summary>
|
|
public float ReverbDelay
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.ReverbDelay;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.ReverbDelay = Math.Max(Math.Min(ReverbDelayMax, value), ReverbDelayMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Echo density in the late reverberation decay, in percent.
|
|
/// </summary>
|
|
public float Diffusion
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Diffusion;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Diffusion = Math.Max(Math.Min(DiffusionMax, value), DiffusionMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Modal density in the late reverberation decay, in percent.
|
|
/// </summary>
|
|
public float Density
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Density;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Density = Math.Max(Math.Min(DensityMax, value), DensityMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reference high frequency, in hertz.
|
|
/// </summary>
|
|
public float HfReference
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.HfReference;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.HfReference = Math.Max(Math.Min(HfReferenceMax, value), HfReferenceMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// the quality of the environmental reverberation effect. Higher values produce better quality at the expense of processing time.
|
|
/// </summary>
|
|
public int Quality
|
|
{
|
|
get
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.GetQuality(out var quality));
|
|
return quality;
|
|
}
|
|
set => Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.SetQuality(value));
|
|
}
|
|
|
|
private readonly IDirectSoundFXI3DL2Reverb fxI3Dl2Reverb;
|
|
|
|
internal Params(IDirectSoundFXI3DL2Reverb dsFxObject)
|
|
{
|
|
fxI3Dl2Reverb = dsFxObject;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets standard reverberation parameters of a buffer.
|
|
/// </summary>
|
|
/// <param name="preset">I3DL2EnvironmentPreset</param>
|
|
public void SetPreset(I3DL2EnvironmentPreset preset)
|
|
{
|
|
var p = (uint)preset;
|
|
Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.SetPreset(p));
|
|
}
|
|
|
|
/// <summary>
|
|
/// retrieves an identifier for standard reverberation parameters of a buffer.
|
|
/// </summary>
|
|
/// <returns>I3DL2EnvironmentPreset</returns>
|
|
public I3DL2EnvironmentPreset GetPreset()
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.GetPreset(out var preset));
|
|
return (I3DL2EnvironmentPreset)preset;
|
|
}
|
|
|
|
private void SetAllParameters(DsFxI3Dl2Reverb param)
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.SetAllParameters(ref param));
|
|
}
|
|
|
|
private DsFxI3Dl2Reverb GetAllParameters()
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxI3Dl2Reverb.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 I3DL2Reverb
|
|
/// </summary>
|
|
public DmoI3DL2Reverb()
|
|
{
|
|
var guidi3Dl2Reverb = new Guid("EF985E71-D5C7-42D4-BA4D-2D073E2E96F4");
|
|
|
|
var targetDescriptor = DmoEnumerator.GetAudioEffectNames().First(descriptor =>
|
|
Equals(descriptor.Clsid, guidi3Dl2Reverb));
|
|
|
|
if (targetDescriptor != null)
|
|
{
|
|
var mediaComObject = Activator.CreateInstance(Type.GetTypeFromCLSID(targetDescriptor.Clsid));
|
|
|
|
mediaObject = new MediaObject((IMediaObject)mediaComObject);
|
|
mediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)mediaComObject);
|
|
effectParams = new Params((IDirectSoundFXI3DL2Reverb)mediaComObject);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose code
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
mediaObjectInPlace?.Dispose();
|
|
mediaObject?.Dispose();
|
|
}
|
|
}
|
|
} |