293 lines
9.0 KiB
C#
293 lines
9.0 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace NAudio.Dmo.Effect
|
|
{
|
|
internal struct DsFxCompressor
|
|
{
|
|
public float Gain;
|
|
public float Attack;
|
|
public float Release;
|
|
public float Threshold;
|
|
public float Ratio;
|
|
public float PreDelay;
|
|
}
|
|
|
|
[ComImport,
|
|
System.Security.SuppressUnmanagedCodeSecurity,
|
|
Guid("4bbd1154-62f6-4e2c-a15c-d3b6c417f7a0"),
|
|
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
interface IDirectSoundFXCompressor
|
|
{
|
|
[PreserveSig]
|
|
int SetAllParameters([In] ref DsFxCompressor param);
|
|
|
|
[PreserveSig]
|
|
int GetAllParameters(out DsFxCompressor param);
|
|
}
|
|
|
|
/// <summary>
|
|
/// DMO Compressor Effect
|
|
/// </summary>
|
|
public class DmoCompressor : IDmoEffector<DmoCompressor.Params>
|
|
{
|
|
/// <summary>
|
|
/// DMO Compressor Params
|
|
/// </summary>
|
|
public struct Params
|
|
{
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_GAIN_MIN
|
|
/// </summary>
|
|
public const float GainMin = -60.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_GAIN_MAX
|
|
/// </summary>
|
|
public const float GainMax = 60.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_GAIN_DEFAULT
|
|
/// </summary>
|
|
public const float GainDefault = 0.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_ATTACK_MIN
|
|
/// </summary>
|
|
public const float AttackMin = 0.01f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_ATTACK_MAX
|
|
/// </summary>
|
|
public const float AttackMax = 500.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_ATTACK_DEFAULT
|
|
/// </summary>
|
|
public const float AttackDefault = 10.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_RELEASE_MIN
|
|
/// </summary>
|
|
public const float ReleaseMin = 50.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_RELEASE_MAX
|
|
/// </summary>
|
|
public const float ReleaseMax = 3000.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_RELEASE_DEFAULT
|
|
/// </summary>
|
|
public const float ReleaseDefault = 200.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_THRESHOLD_MIN
|
|
/// </summary>
|
|
public const float ThresholdMin = -60.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_THRESHOLD_MAX
|
|
/// </summary>
|
|
public const float ThresholdMax = 0.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_THRESHOLD_DEFAULT
|
|
/// </summary>
|
|
public const float TjresholdDefault = -20.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_RATIO_MIN
|
|
/// </summary>
|
|
public const float RatioMin = 1.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_RATIO_MAX
|
|
/// </summary>
|
|
public const float RatioMax = 100.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_RATIO_DEFAULT
|
|
/// </summary>
|
|
public const float RatioDefault = 3.0f;
|
|
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_PREDELAY_MIN
|
|
/// </summary>
|
|
public const float PreDelayMin = 0.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_PREDELAY_MAX
|
|
/// </summary>
|
|
public const float PreDelayMax = 4.0f;
|
|
/// <summary>
|
|
/// DSFXCOMPRESSOR_PREDELAY_DEFAULT
|
|
/// </summary>
|
|
public const float PreDelayDefault = 4.0f;
|
|
|
|
/// <summary>
|
|
/// Output gain of signal after compression.
|
|
/// </summary>
|
|
public float Gain
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Gain;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Gain = Math.Max(Math.Min(GainMax, value), GainMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Time before compression reaches its full value.
|
|
/// </summary>
|
|
public float Attack
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Attack;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Attack = Math.Max(Math.Min(AttackMax, value), AttackMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Speed at which compression is stopped after input drops below Threshold.
|
|
/// </summary>
|
|
public float Release
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Release;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Release = Math.Max(Math.Min(ReleaseMax, value), ReleaseMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Point at which compression begins, in decibels.
|
|
/// </summary>
|
|
public float Threshold
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Threshold;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Threshold = Math.Max(Math.Min(ThresholdMax, value), ThresholdMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compression ratio
|
|
/// </summary>
|
|
public float Ratio
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.Ratio;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.Ratio = Math.Max(Math.Min(RatioMax, value), RatioMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Time after Threshold is reached before attack phase is started, in milliseconds.
|
|
/// </summary>
|
|
public float PreDelay
|
|
{
|
|
get
|
|
{
|
|
var param = GetAllParameters();
|
|
return param.PreDelay;
|
|
}
|
|
set
|
|
{
|
|
var param = GetAllParameters();
|
|
param.PreDelay = Math.Max(Math.Min(PreDelayMax, value), PreDelayMin);
|
|
SetAllParameters(param);
|
|
}
|
|
}
|
|
|
|
private readonly IDirectSoundFXCompressor fxCompressor;
|
|
|
|
internal Params(IDirectSoundFXCompressor dsFxObject)
|
|
{
|
|
fxCompressor = dsFxObject;
|
|
}
|
|
|
|
private void SetAllParameters(DsFxCompressor param)
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxCompressor.SetAllParameters(ref param));
|
|
}
|
|
|
|
private DsFxCompressor GetAllParameters()
|
|
{
|
|
Marshal.ThrowExceptionForHR(fxCompressor.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 Compressor
|
|
/// </summary>
|
|
public DmoCompressor()
|
|
{
|
|
var guidChorus = new Guid("EF011F79-4000-406D-87AF-BFFB3FC39D57");
|
|
|
|
var targetDescriptor = DmoEnumerator.GetAudioEffectNames().First(descriptor =>
|
|
Equals(descriptor.Clsid, guidChorus));
|
|
|
|
if (targetDescriptor != null)
|
|
{
|
|
var mediaComObject = Activator.CreateInstance(Type.GetTypeFromCLSID(targetDescriptor.Clsid));
|
|
|
|
mediaObject = new MediaObject((IMediaObject)mediaComObject);
|
|
mediaObjectInPlace = new MediaObjectInPlace((IMediaObjectInPlace)mediaComObject);
|
|
effectParams = new Params((IDirectSoundFXCompressor)mediaComObject);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose code
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
mediaObjectInPlace?.Dispose();
|
|
mediaObject?.Dispose();
|
|
}
|
|
}
|
|
} |