2024-06-07 00:47:07 +02:00

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