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