From 39066900773e7857faf2d02e7ed51b71d219d97d Mon Sep 17 00:00:00 2001 From: godosa Date: Tue, 6 Oct 2026 23:39:36 +0200 Subject: godosa-engine: initial public history --- src/Godosa.Audio/OpenAlAudio.Reverb.cs | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/Godosa.Audio/OpenAlAudio.Reverb.cs (limited to 'src/Godosa.Audio/OpenAlAudio.Reverb.cs') diff --git a/src/Godosa.Audio/OpenAlAudio.Reverb.cs b/src/Godosa.Audio/OpenAlAudio.Reverb.cs new file mode 100644 index 0000000..b93e74a --- /dev/null +++ b/src/Godosa.Audio/OpenAlAudio.Reverb.cs @@ -0,0 +1,83 @@ +using Silk.NET.OpenAL.Extensions.Creative; + +namespace Godosa.Audio; + +/// One EFX reverb for the region (audio spec ยง2): positioned sources send to it, 2D +/// ones (beds, music, interface) don't. Air absorption dulls distant sounds. +public sealed unsafe partial class OpenAlAudio +{ + private EffectExtension? _efx; + private uint _effect, _effectSlot; + private ReverbPreset? _reverbApplied; + private ReverbPreset? _reverbWanted; + private bool _reverbInitialised; + + /// The current region's reverb, or null for none (UI thread). + public ReverbPreset? Reverb + { + set { lock (_poseLock) _reverbWanted = value; } + } + + private void InitReverb() + { + if (!_al!.TryGetExtension(out _efx)) _efx = null; + if (_efx is null) + { + if (EngineDebug.Audio) EngineDebug.Write("audio", "no EFX: no reverb"); + return; + } + _effect = _efx.GenEffects(1)[0]; + _efx.SetEffectProperty(_effect, EffectInteger.EffectType, (int)EffectType.Reverb); + _effectSlot = _efx.GenAuxiliaryEffectSlots(1)[0]; + _reverbApplied = null; + _reverbInitialised = false; + } + + private void UpdateReverb() + { + if (_efx is null) return; + ReverbPreset? wanted; + lock (_poseLock) wanted = _reverbWanted; + if (_reverbInitialised && _reverbApplied == wanted) return; + _reverbInitialised = true; + _reverbApplied = wanted; + if (wanted is not { } p) + { + // No effect in the slot: sends to it are dropped and the mixer runs no reverb. + _efx.SetAuxiliaryEffectSlotProperty(_effectSlot, EffectSlotInteger.Effect, 0); + if (EngineDebug.Audio) EngineDebug.Write("audio", "reverb off"); + return; + } + _efx.SetEffectProperty(_effect, EffectFloat.ReverbDensity, p.Density); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbDiffusion, p.Diffusion); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbGain, p.Gain); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbGainHF, p.GainHF); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbDecayTime, p.DecayTime); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbDecayHFRatio, p.DecayHFRatio); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbReflectionsGain, p.ReflectionsGain); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbReflectionsDelay, p.ReflectionsDelay); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbLateReverbGain, p.LateReverbGain); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbLateReverbDelay, p.LateReverbDelay); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbAirAbsorptionGainHF, p.AirAbsorptionGainHF); + _efx.SetEffectProperty(_effect, EffectFloat.ReverbRoomRolloffFactor, p.RoomRolloffFactor); + _efx.SetEffectProperty(_effect, EffectInteger.ReverbDecayHFLimit, p.DecayHFLimit ? 1 : 0); + _efx.SetAuxiliaryEffectSlotProperty(_effectSlot, EffectSlotInteger.Effect, (int)_effect); // re-attach applies the change + if (EngineDebug.Audio) EngineDebug.Write("audio", $"reverb {(p == ReverbPreset.Forest ? "forest" : p == ReverbPreset.Cave ? "cave" : "plain")}"); + } + + private void SendToReverb(uint source, bool positioned) + { + if (_efx is null) return; + _efx.SetSourceProperty(source, EFXSourceInteger3.AuxiliarySendFilter, positioned ? (int)_effectSlot : 0, 0, 0); + _efx.SetSourceProperty(source, EFXSourceFloat.AirAbsorptionFactor, positioned ? 1f : 0f); + } + + private void ReleaseReverb() + { + if (_efx is null) return; + _efx.SetAuxiliaryEffectSlotProperty(_effectSlot, EffectSlotInteger.Effect, 0); + _efx.DeleteAuxiliaryEffectSlot(_effectSlot); + _efx.DeleteEffect(_effect); + _efx = null; + } +} -- cgit