// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
namespace Win32.Media.Audio.XAudio2;
public static unsafe partial class Apis
{
public static void ReverbConvertI3DL2ToNative(
[NativeTypeName("const XAUDIO2FX_REVERB_I3DL2_PARAMETERS *")] FXReverbI3DL2Parameters* pI3DL2,
[NativeTypeName("XAUDIO2FX_REVERB_PARAMETERS *")] FXReverbParameters* pNative,
[Optional, DefaultParameterValue(1)] Bool32 sevenDotOneReverb)
{
float reflectionsDelay;
float reverbDelay;
if (sevenDotOneReverb != 0)
{
pNative->RearDelay = 20;
}
else
{
pNative->RearDelay = 5;
}
pNative->SideDelay = 5;
pNative->PositionLeft = 6;
pNative->PositionRight = 6;
pNative->PositionMatrixLeft = 27;
pNative->PositionMatrixRight = 27;
pNative->RoomSize = 100.0f;
pNative->LowEQCutoff = 4;
pNative->HighEQCutoff = 6;
pNative->RoomFilterMain = (float)pI3DL2->Room / 100.0f;
pNative->RoomFilterHF = (float)pI3DL2->RoomHF / 100.0f;
if (pI3DL2->DecayHFRatio >= 1.0f)
{
int index = (int)(-4.0 * Math.Log10(pI3DL2->DecayHFRatio));
if (index < -8)
{
index = -8;
}
pNative->LowEQGain = (byte)((index < 0) ? index + 8 : 8);
pNative->HighEQGain = 8;
pNative->DecayTime = pI3DL2->DecayTime * pI3DL2->DecayHFRatio;
}
else
{
int index = (int)(4.0 * Math.Log10(pI3DL2->DecayHFRatio));
if (index < -8)
{
index = -8;
}
pNative->LowEQGain = 8;
pNative->HighEQGain = (byte)((index < 0) ? index + 8 : 8);
pNative->DecayTime = pI3DL2->DecayTime;
}
reflectionsDelay = pI3DL2->ReflectionsDelay * 1000.0f;
if (reflectionsDelay >= 300)
{
reflectionsDelay = (float)(300 - 1);
}
else if (reflectionsDelay <= 1)
{
reflectionsDelay = 1;
}
pNative->ReflectionsDelay = (uint)reflectionsDelay;
reverbDelay = pI3DL2->ReverbDelay * 1000.0f;
if (reverbDelay >= 85)
{
reverbDelay = (float)(85 - 1);
}
pNative->ReverbDelay = (byte)reverbDelay;
pNative->ReflectionsGain = pI3DL2->Reflections / 100.0f;
pNative->ReverbGain = pI3DL2->Reverb / 100.0f;
pNative->EarlyDiffusion = (byte)(15.0f * pI3DL2->Diffusion / 100.0f);
pNative->LateDiffusion = pNative->EarlyDiffusion;
pNative->Density = pI3DL2->Density;
pNative->RoomFilterFreq = pI3DL2->HFReference;
pNative->WetDryMix = pI3DL2->WetDryMix;
pNative->DisableLateField = 0;
}
public static float XAudio2DecibelsToAmplitudeRatio(float Decibels)
{
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return MathF.Pow(10.0f, Decibels / 20.0f);
#else
return (float)Math.Pow(10.0f, Decibels / 20.0f);
#endif
}
public static float XAudio2AmplitudeRatioToDecibels(float Volume)
{
if (Volume == 0)
{
return -3.402823466e+38f;
}
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return 20.0f * MathF.Log10(Volume);
#else
return 20.0f * (float)Math.Log10(Volume);
#endif
}
public static float XAudio2SemitonesToFrequencyRatio(float Semitones)
{
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return MathF.Pow(2.0f, Semitones / 12.0f);
#else
return (float)Math.Pow(2.0f, Semitones / 12.0f);
#endif
}
public static float XAudio2FrequencyRatioToSemitones(float FrequencyRatio)
{
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return 39.86313713864835f * MathF.Log10(FrequencyRatio);
#else
return 39.86313713864835f * (float)Math.Log10(FrequencyRatio);
#endif
}
public static float XAudio2CutoffFrequencyToRadians(float CutoffFrequency, [NativeTypeName("UINT32")] uint SampleRate)
{
if ((uint)(CutoffFrequency * 6.0f) >= SampleRate)
{
return 1.0f;
}
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return 2.0f * MathF.Sin((float)3.14159265358979323846 * CutoffFrequency / SampleRate);
#else
return 2.0f * (float)Math.Sin(3.14159265358979323846 * CutoffFrequency / SampleRate);
#endif
}
public static float XAudio2RadiansToCutoffFrequency(float Radians, float SampleRate)
{
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return SampleRate * MathF.Asin(Radians / 2.0f) / (float)3.14159265358979323846;
#else
return SampleRate * (float)Math.Asin(Radians / 2.0f) / (float)3.14159265358979323846;
#endif
}
public static float XAudio2CutoffFrequencyToOnePoleCoefficient(float CutoffFrequency, [NativeTypeName("UINT32")] uint SampleRate)
{
if ((uint)CutoffFrequency >= SampleRate)
{
return 1.0f;
}
#if NETSTANDARD2_1 || NET6_0_OR_GREATER
return (1.0f - MathF.Pow(1.0f - 2.0f * CutoffFrequency / SampleRate, 2.0f));
#else
return (1.0f - (float)Math.Pow(1.0f - 2.0f * CutoffFrequency / SampleRate, 2.0f));
#endif
}
///
[DllImport("XAudio2_9", ExactSpelling = true)]
public static extern HResult XAudio2Create([NativeTypeName("IXAudio2 **")] IXAudio2** ppXAudio2, [NativeTypeName("UINT32")] uint Flags = 0, [NativeTypeName("XAUDIO2_PROCESSOR")] uint XAudio2Processor = XAUDIO2_DEFAULT_PROCESSOR);
///
public static HResult XAudio2CreateVolumeMeter([NativeTypeName("IUnknown **")] IUnknown** ppApo)
{
return CreateAudioVolumeMeter(ppApo);
}
///
public static HResult XAudio2CreateReverb([NativeTypeName("IUnknown **")] IUnknown** ppApo)
{
return CreateAudioReverb(ppApo);
}
}