aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects/reverb.cpp
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-01-30 14:47:32 +0200
committerGitHub <[email protected]>2022-01-30 04:47:32 -0800
commit19ed994dc30ed84ea7cbbb5152577669fc25caf6 (patch)
treef68933bf8f778806618bd6c0b1bf9ced1b0ccf08 /al/effects/reverb.cpp
parent619249371a40f03cf988d1f5750d643df797c485 (diff)
Add EAX extensions (EAX 2.0-5.0, X-RAM) (#632)
* Add EAX extensions (EAX 2.0-5.0, X-RAM) * Comment out C++17 leftovers * Remove everything related to patching * Update alsoftrc.sample * Rewrite integration * Fix GCC compilation under Linux * Always reset EAX effect properties when loading it into FX slot
Diffstat (limited to 'al/effects/reverb.cpp')
-rw-r--r--al/effects/reverb.cpp1922
1 files changed, 1922 insertions, 0 deletions
diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp
index 3f234b93..8012450d 100644
--- a/al/effects/reverb.cpp
+++ b/al/effects/reverb.cpp
@@ -9,6 +9,15 @@
#include "alc/effects/base.h"
#include "effects.h"
+#if ALSOFT_EAX
+#include <tuple>
+
+#include "alnumeric.h"
+
+#include "al/eax_exception.h"
+#include "al/eax_utils.h"
+#endif // ALSOFT_EAX
+
namespace {
@@ -554,3 +563,1916 @@ const EffectProps ReverbEffectProps{genDefaultProps()};
DEFINE_ALEFFECT_VTABLE(StdReverb);
const EffectProps StdReverbEffectProps{genDefaultStdProps()};
+
+#if ALSOFT_EAX
+namespace
+{
+
+
+using EaxReverbEffectDirtyFlagsValue = std::uint_least32_t;
+
+struct EaxReverbEffectDirtyFlags
+{
+ using EaxIsBitFieldStruct = bool;
+
+ EaxReverbEffectDirtyFlagsValue ulEnvironment : 1;
+ EaxReverbEffectDirtyFlagsValue flEnvironmentSize : 1;
+ EaxReverbEffectDirtyFlagsValue flEnvironmentDiffusion : 1;
+ EaxReverbEffectDirtyFlagsValue lRoom : 1;
+ EaxReverbEffectDirtyFlagsValue lRoomHF : 1;
+ EaxReverbEffectDirtyFlagsValue lRoomLF : 1;
+ EaxReverbEffectDirtyFlagsValue flDecayTime : 1;
+ EaxReverbEffectDirtyFlagsValue flDecayHFRatio : 1;
+ EaxReverbEffectDirtyFlagsValue flDecayLFRatio : 1;
+ EaxReverbEffectDirtyFlagsValue lReflections : 1;
+ EaxReverbEffectDirtyFlagsValue flReflectionsDelay : 1;
+ EaxReverbEffectDirtyFlagsValue vReflectionsPan : 1;
+ EaxReverbEffectDirtyFlagsValue lReverb : 1;
+ EaxReverbEffectDirtyFlagsValue flReverbDelay : 1;
+ EaxReverbEffectDirtyFlagsValue vReverbPan : 1;
+ EaxReverbEffectDirtyFlagsValue flEchoTime : 1;
+ EaxReverbEffectDirtyFlagsValue flEchoDepth : 1;
+ EaxReverbEffectDirtyFlagsValue flModulationTime : 1;
+ EaxReverbEffectDirtyFlagsValue flModulationDepth : 1;
+ EaxReverbEffectDirtyFlagsValue flAirAbsorptionHF : 1;
+ EaxReverbEffectDirtyFlagsValue flHFReference : 1;
+ EaxReverbEffectDirtyFlagsValue flLFReference : 1;
+ EaxReverbEffectDirtyFlagsValue flRoomRolloffFactor : 1;
+ EaxReverbEffectDirtyFlagsValue ulFlags : 1;
+}; // EaxReverbEffectDirtyFlags
+
+
+class EaxReverbEffect final :
+ public EaxEffect
+{
+public:
+ EaxReverbEffect(
+ EffectProps& al_effect_props);
+
+
+ // [[nodiscard]]
+ bool dispatch(
+ const EaxEaxCall& eax_call) override;
+
+
+private:
+ EffectProps& al_effect_props_;
+
+ EAXREVERBPROPERTIES eax_{};
+ EAXREVERBPROPERTIES eax_d_{};
+ EaxReverbEffectDirtyFlags eax_dirty_flags_{};
+
+
+ void set_eax_defaults();
+
+
+ void set_efx_density();
+
+ void set_efx_diffusion();
+
+ void set_efx_gain();
+
+ void set_efx_gain_hf();
+
+ void set_efx_gain_lf();
+
+ void set_efx_decay_time();
+
+ void set_efx_decay_hf_ratio();
+
+ void set_efx_decay_lf_ratio();
+
+ void set_efx_reflections_gain();
+
+ void set_efx_reflections_delay();
+
+ void set_efx_reflections_pan();
+
+ void set_efx_late_reverb_gain();
+
+ void set_efx_late_reverb_delay();
+
+ void set_efx_late_reverb_pan();
+
+ void set_efx_echo_time();
+
+ void set_efx_echo_depth();
+
+ void set_efx_modulation_time();
+
+ void set_efx_modulation_depth();
+
+ void set_efx_air_absorption_gain_hf();
+
+ void set_efx_hf_reference();
+
+ void set_efx_lf_reference();
+
+ void set_efx_room_rolloff_factor();
+
+ void set_efx_flags();
+
+ void set_efx_defaults();
+
+
+ void get_all(
+ const EaxEaxCall& eax_call) const;
+
+ // [[nodiscard]]
+ bool get(
+ const EaxEaxCall& eax_call) const;
+
+
+ void validate_environment(
+ unsigned long ulEnvironment,
+ int version,
+ bool is_standalone);
+
+ void validate_environment_size(
+ float flEnvironmentSize);
+
+ void validate_environment_diffusion(
+ float flEnvironmentDiffusion);
+
+ void validate_room(
+ long lRoom);
+
+ void validate_room_hf(
+ long lRoomHF);
+
+ void validate_room_lf(
+ long lRoomLF);
+
+ void validate_decay_time(
+ float flDecayTime);
+
+ void validate_decay_hf_ratio(
+ float flDecayHFRatio);
+
+ void validate_decay_lf_ratio(
+ float flDecayLFRatio);
+
+ void validate_reflections(
+ long lReflections);
+
+ void validate_reflections_delay(
+ float flReflectionsDelay);
+
+ void validate_reflections_pan(
+ const EAXVECTOR& vReflectionsPan);
+
+ void validate_reverb(
+ long lReverb);
+
+ void validate_reverb_delay(
+ float flReverbDelay);
+
+ void validate_reverb_pan(
+ const EAXVECTOR& vReverbPan);
+
+ void validate_echo_time(
+ float flEchoTime);
+
+ void validate_echo_depth(
+ float flEchoDepth);
+
+ void validate_modulation_time(
+ float flModulationTime);
+
+ void validate_modulation_depth(
+ float flModulationDepth);
+
+ void validate_air_absorbtion_hf(
+ float air_absorbtion_hf);
+
+ void validate_hf_reference(
+ float flHFReference);
+
+ void validate_lf_reference(
+ float flLFReference);
+
+ void validate_room_rolloff_factor(
+ float flRoomRolloffFactor);
+
+ void validate_flags(
+ unsigned long ulFlags);
+
+ void validate_all(
+ const EAX20LISTENERPROPERTIES& all,
+ int version);
+
+ void validate_all(
+ const EAXREVERBPROPERTIES& all,
+ int version);
+
+
+ void defer_environment(
+ unsigned long ulEnvironment);
+
+ void defer_environment_size(
+ float flEnvironmentSize);
+
+ void defer_environment_diffusion(
+ float flEnvironmentDiffusion);
+
+ void defer_room(
+ long lRoom);
+
+ void defer_room_hf(
+ long lRoomHF);
+
+ void defer_room_lf(
+ long lRoomLF);
+
+ void defer_decay_time(
+ float flDecayTime);
+
+ void defer_decay_hf_ratio(
+ float flDecayHFRatio);
+
+ void defer_decay_lf_ratio(
+ float flDecayLFRatio);
+
+ void defer_reflections(
+ long lReflections);
+
+ void defer_reflections_delay(
+ float flReflectionsDelay);
+
+ void defer_reflections_pan(
+ const EAXVECTOR& vReflectionsPan);
+
+ void defer_reverb(
+ long lReverb);
+
+ void defer_reverb_delay(
+ float flReverbDelay);
+
+ void defer_reverb_pan(
+ const EAXVECTOR& vReverbPan);
+
+ void defer_echo_time(
+ float flEchoTime);
+
+ void defer_echo_depth(
+ float flEchoDepth);
+
+ void defer_modulation_time(
+ float flModulationTime);
+
+ void defer_modulation_depth(
+ float flModulationDepth);
+
+ void defer_air_absorbtion_hf(
+ float flAirAbsorptionHF);
+
+ void defer_hf_reference(
+ float flHFReference);
+
+ void defer_lf_reference(
+ float flLFReference);
+
+ void defer_room_rolloff_factor(
+ float flRoomRolloffFactor);
+
+ void defer_flags(
+ unsigned long ulFlags);
+
+ void defer_all(
+ const EAX20LISTENERPROPERTIES& all);
+
+ void defer_all(
+ const EAXREVERBPROPERTIES& all);
+
+
+ void defer_environment(
+ const EaxEaxCall& eax_call);
+
+ void defer_environment_size(
+ const EaxEaxCall& eax_call);
+
+ void defer_environment_diffusion(
+ const EaxEaxCall& eax_call);
+
+ void defer_room(
+ const EaxEaxCall& eax_call);
+
+ void defer_room_hf(
+ const EaxEaxCall& eax_call);
+
+ void defer_room_lf(
+ const EaxEaxCall& eax_call);
+
+ void defer_decay_time(
+ const EaxEaxCall& eax_call);
+
+ void defer_decay_hf_ratio(
+ const EaxEaxCall& eax_call);
+
+ void defer_decay_lf_ratio(
+ const EaxEaxCall& eax_call);
+
+ void defer_reflections(
+ const EaxEaxCall& eax_call);
+
+ void defer_reflections_delay(
+ const EaxEaxCall& eax_call);
+
+ void defer_reflections_pan(
+ const EaxEaxCall& eax_call);
+
+ void defer_reverb(
+ const EaxEaxCall& eax_call);
+
+ void defer_reverb_delay(
+ const EaxEaxCall& eax_call);
+
+ void defer_reverb_pan(
+ const EaxEaxCall& eax_call);
+
+ void defer_echo_time(
+ const EaxEaxCall& eax_call);
+
+ void defer_echo_depth(
+ const EaxEaxCall& eax_call);
+
+ void defer_modulation_time(
+ const EaxEaxCall& eax_call);
+
+ void defer_modulation_depth(
+ const EaxEaxCall& eax_call);
+
+ void defer_air_absorbtion_hf(
+ const EaxEaxCall& eax_call);
+
+ void defer_hf_reference(
+ const EaxEaxCall& eax_call);
+
+ void defer_lf_reference(
+ const EaxEaxCall& eax_call);
+
+ void defer_room_rolloff_factor(
+ const EaxEaxCall& eax_call);
+
+ void defer_flags(
+ const EaxEaxCall& eax_call);
+
+ void defer_all(
+ const EaxEaxCall& eax_call);
+
+
+ // [[nodiscard]]
+ bool apply_deferred();
+
+ // [[nodiscard]]
+ bool set(
+ const EaxEaxCall& eax_call);
+}; // EaxReverbEffect
+
+
+class EaxReverbEffectException :
+ public EaxException
+{
+public:
+ explicit EaxReverbEffectException(
+ const char* message)
+ :
+ EaxException{"EAX_REVERB_EFFECT", message}
+ {
+ }
+}; // EaxReverbEffectException
+
+
+EaxReverbEffect::EaxReverbEffect(
+ EffectProps& al_effect_props)
+ :
+ al_effect_props_{al_effect_props}
+{
+ set_eax_defaults();
+ set_efx_defaults();
+}
+
+// [[nodiscard]]
+bool EaxReverbEffect::dispatch(
+ const EaxEaxCall& eax_call)
+{
+ return eax_call.is_get() ? get(eax_call) : set(eax_call);
+}
+
+void EaxReverbEffect::set_eax_defaults()
+{
+ eax_ = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
+
+ eax_d_ = eax_;
+}
+
+void EaxReverbEffect::set_efx_density()
+{
+ const auto eax_environment_size = eax_.flEnvironmentSize;
+
+ const auto efx_density = clamp(
+ (eax_environment_size * eax_environment_size * eax_environment_size) / 16.0F,
+ AL_EAXREVERB_MIN_DENSITY,
+ AL_EAXREVERB_MAX_DENSITY);
+
+ al_effect_props_.Reverb.Density = efx_density;
+}
+
+void EaxReverbEffect::set_efx_diffusion()
+{
+ const auto efx_diffusion = clamp(
+ eax_.flEnvironmentDiffusion,
+ AL_EAXREVERB_MIN_DIFFUSION,
+ AL_EAXREVERB_MAX_DIFFUSION);
+
+ al_effect_props_.Reverb.Diffusion = efx_diffusion;
+}
+
+void EaxReverbEffect::set_efx_gain()
+{
+ const auto efx_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lRoom)),
+ AL_EAXREVERB_MIN_GAIN,
+ AL_EAXREVERB_MAX_GAIN);
+
+ al_effect_props_.Reverb.Gain = efx_gain;
+}
+
+void EaxReverbEffect::set_efx_gain_hf()
+{
+ const auto efx_gain_hf = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lRoomHF)),
+ AL_EAXREVERB_MIN_GAINHF,
+ AL_EAXREVERB_MAX_GAINHF);
+
+ al_effect_props_.Reverb.GainHF = efx_gain_hf;
+}
+
+void EaxReverbEffect::set_efx_gain_lf()
+{
+ const auto efx_gain_lf = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lRoomLF)),
+ AL_EAXREVERB_MIN_GAINLF,
+ AL_EAXREVERB_MAX_GAINLF);
+
+ al_effect_props_.Reverb.GainLF = efx_gain_lf;
+}
+
+void EaxReverbEffect::set_efx_decay_time()
+{
+ const auto efx_decay_time = clamp(
+ eax_.flDecayTime,
+ AL_EAXREVERB_MIN_DECAY_TIME,
+ AL_EAXREVERB_MAX_DECAY_TIME);
+
+ al_effect_props_.Reverb.DecayTime = efx_decay_time;
+}
+
+void EaxReverbEffect::set_efx_decay_hf_ratio()
+{
+ const auto efx_decay_hf_ratio = clamp(
+ eax_.flDecayHFRatio,
+ AL_EAXREVERB_MIN_DECAY_HFRATIO,
+ AL_EAXREVERB_MAX_DECAY_HFRATIO);
+
+ al_effect_props_.Reverb.DecayHFRatio = efx_decay_hf_ratio;
+}
+
+void EaxReverbEffect::set_efx_decay_lf_ratio()
+{
+ const auto efx_decay_lf_ratio = clamp(
+ eax_.flDecayLFRatio,
+ AL_EAXREVERB_MIN_DECAY_LFRATIO,
+ AL_EAXREVERB_MAX_DECAY_LFRATIO);
+
+ al_effect_props_.Reverb.DecayLFRatio = efx_decay_lf_ratio;
+}
+
+void EaxReverbEffect::set_efx_reflections_gain()
+{
+ const auto efx_reflections_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lReflections)),
+ AL_EAXREVERB_MIN_REFLECTIONS_GAIN,
+ AL_EAXREVERB_MAX_REFLECTIONS_GAIN);
+
+ al_effect_props_.Reverb.ReflectionsGain = efx_reflections_gain;
+}
+
+void EaxReverbEffect::set_efx_reflections_delay()
+{
+ const auto efx_reflections_delay = clamp(
+ eax_.flReflectionsDelay,
+ AL_EAXREVERB_MIN_REFLECTIONS_DELAY,
+ AL_EAXREVERB_MAX_REFLECTIONS_DELAY);
+
+ al_effect_props_.Reverb.ReflectionsDelay = efx_reflections_delay;
+}
+
+void EaxReverbEffect::set_efx_reflections_pan()
+{
+ al_effect_props_.Reverb.ReflectionsPan[0] = eax_.vReflectionsPan.x;
+ al_effect_props_.Reverb.ReflectionsPan[1] = eax_.vReflectionsPan.y;
+ al_effect_props_.Reverb.ReflectionsPan[2] = eax_.vReflectionsPan.z;
+}
+
+void EaxReverbEffect::set_efx_late_reverb_gain()
+{
+ const auto efx_late_reverb_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lReverb)),
+ AL_EAXREVERB_MIN_LATE_REVERB_GAIN,
+ AL_EAXREVERB_MAX_LATE_REVERB_GAIN);
+
+ al_effect_props_.Reverb.LateReverbGain = efx_late_reverb_gain;
+}
+
+void EaxReverbEffect::set_efx_late_reverb_delay()
+{
+ const auto efx_late_reverb_delay = clamp(
+ eax_.flReverbDelay,
+ AL_EAXREVERB_MIN_LATE_REVERB_DELAY,
+ AL_EAXREVERB_MAX_LATE_REVERB_DELAY);
+
+ al_effect_props_.Reverb.LateReverbDelay = efx_late_reverb_delay;
+}
+
+void EaxReverbEffect::set_efx_late_reverb_pan()
+{
+ al_effect_props_.Reverb.LateReverbPan[0] = eax_.vReverbPan.x;
+ al_effect_props_.Reverb.LateReverbPan[1] = eax_.vReverbPan.y;
+ al_effect_props_.Reverb.LateReverbPan[2] = eax_.vReverbPan.z;
+}
+
+void EaxReverbEffect::set_efx_echo_time()
+{
+ const auto efx_echo_time = clamp(
+ eax_.flEchoTime,
+ AL_EAXREVERB_MIN_ECHO_TIME,
+ AL_EAXREVERB_MAX_ECHO_TIME);
+
+ al_effect_props_.Reverb.EchoTime = efx_echo_time;
+}
+
+void EaxReverbEffect::set_efx_echo_depth()
+{
+ const auto efx_echo_depth = clamp(
+ eax_.flEchoDepth,
+ AL_EAXREVERB_MIN_ECHO_DEPTH,
+ AL_EAXREVERB_MAX_ECHO_DEPTH);
+
+ al_effect_props_.Reverb.EchoDepth = efx_echo_depth;
+}
+
+void EaxReverbEffect::set_efx_modulation_time()
+{
+ const auto efx_modulation_time = clamp(
+ eax_.flModulationTime,
+ AL_EAXREVERB_MIN_MODULATION_TIME,
+ AL_EAXREVERB_MAX_MODULATION_TIME);
+
+ al_effect_props_.Reverb.ModulationTime = efx_modulation_time;
+}
+
+void EaxReverbEffect::set_efx_modulation_depth()
+{
+ const auto efx_modulation_depth = clamp(
+ eax_.flModulationDepth,
+ AL_EAXREVERB_MIN_MODULATION_DEPTH,
+ AL_EAXREVERB_MAX_MODULATION_DEPTH);
+
+ al_effect_props_.Reverb.ModulationDepth = efx_modulation_depth;
+}
+
+void EaxReverbEffect::set_efx_air_absorption_gain_hf()
+{
+ const auto efx_air_absorption_hf = clamp(
+ level_mb_to_gain(eax_.flAirAbsorptionHF),
+ AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF,
+ AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF);
+
+ al_effect_props_.Reverb.AirAbsorptionGainHF = efx_air_absorption_hf;
+}
+
+void EaxReverbEffect::set_efx_hf_reference()
+{
+ const auto efx_hf_reference = clamp(
+ eax_.flHFReference,
+ AL_EAXREVERB_MIN_HFREFERENCE,
+ AL_EAXREVERB_MAX_HFREFERENCE);
+
+ al_effect_props_.Reverb.HFReference = efx_hf_reference;
+}
+
+void EaxReverbEffect::set_efx_lf_reference()
+{
+ const auto efx_lf_reference = clamp(
+ eax_.flLFReference,
+ AL_EAXREVERB_MIN_LFREFERENCE,
+ AL_EAXREVERB_MAX_LFREFERENCE);
+
+ al_effect_props_.Reverb.LFReference = efx_lf_reference;
+}
+
+void EaxReverbEffect::set_efx_room_rolloff_factor()
+{
+ const auto efx_room_rolloff_factor = clamp(
+ eax_.flRoomRolloffFactor,
+ AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR,
+ AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR);
+
+ al_effect_props_.Reverb.RoomRolloffFactor = efx_room_rolloff_factor;
+}
+
+void EaxReverbEffect::set_efx_flags()
+{
+ al_effect_props_.Reverb.DecayHFLimit = ((eax_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
+}
+
+void EaxReverbEffect::set_efx_defaults()
+{
+ set_efx_density();
+ set_efx_diffusion();
+ set_efx_gain();
+ set_efx_gain_hf();
+ set_efx_gain_lf();
+ set_efx_decay_time();
+ set_efx_decay_hf_ratio();
+ set_efx_decay_lf_ratio();
+ set_efx_reflections_gain();
+ set_efx_reflections_delay();
+ set_efx_reflections_pan();
+ set_efx_late_reverb_gain();
+ set_efx_late_reverb_delay();
+ set_efx_late_reverb_pan();
+ set_efx_echo_time();
+ set_efx_echo_depth();
+ set_efx_modulation_time();
+ set_efx_modulation_depth();
+ set_efx_air_absorption_gain_hf();
+ set_efx_hf_reference();
+ set_efx_lf_reference();
+ set_efx_room_rolloff_factor();
+ set_efx_flags();
+}
+
+void EaxReverbEffect::get_all(
+ const EaxEaxCall& eax_call) const
+{
+ if (eax_call.get_version() == 2)
+ {
+ auto& eax_reverb = eax_call.get_value<EaxReverbEffectException, EAX20LISTENERPROPERTIES>();
+ eax_reverb.lRoom = eax_.lRoom;
+ eax_reverb.lRoomHF = eax_.lRoomHF;
+ eax_reverb.flRoomRolloffFactor = eax_.flRoomRolloffFactor;
+ eax_reverb.flDecayTime = eax_.flDecayTime;
+ eax_reverb.flDecayHFRatio = eax_.flDecayHFRatio;
+ eax_reverb.lReflections = eax_.lReflections;
+ eax_reverb.flReflectionsDelay = eax_.flReflectionsDelay;
+ eax_reverb.lReverb = eax_.lReverb;
+ eax_reverb.flReverbDelay = eax_.flReverbDelay;
+ eax_reverb.dwEnvironment = eax_.ulEnvironment;
+ eax_reverb.flEnvironmentSize = eax_.flEnvironmentSize;
+ eax_reverb.flEnvironmentDiffusion = eax_.flEnvironmentDiffusion;
+ eax_reverb.flAirAbsorptionHF = eax_.flAirAbsorptionHF;
+ eax_reverb.dwFlags = eax_.ulFlags;
+ }
+ else
+ {
+ eax_call.set_value<EaxReverbEffectException>(eax_);
+ }
+}
+
+// [[nodiscard]]
+bool EaxReverbEffect::get(
+ const EaxEaxCall& eax_call) const
+{
+ switch (eax_call.get_property_id())
+ {
+ case EAXREVERB_NONE:
+ break;
+
+ case EAXREVERB_ALLPARAMETERS:
+ get_all(eax_call);
+ break;
+
+ case EAXREVERB_ENVIRONMENT:
+ eax_call.set_value<EaxReverbEffectException>(eax_.ulEnvironment);
+ break;
+
+ case EAXREVERB_ENVIRONMENTSIZE:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flEnvironmentSize);
+ break;
+
+ case EAXREVERB_ENVIRONMENTDIFFUSION:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flEnvironmentDiffusion);
+ break;
+
+ case EAXREVERB_ROOM:
+ eax_call.set_value<EaxReverbEffectException>(eax_.lRoom);
+ break;
+
+ case EAXREVERB_ROOMHF:
+ eax_call.set_value<EaxReverbEffectException>(eax_.lRoomHF);
+ break;
+
+ case EAXREVERB_ROOMLF:
+ eax_call.set_value<EaxReverbEffectException>(eax_.lRoomLF);
+ break;
+
+ case EAXREVERB_DECAYTIME:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flDecayTime);
+ break;
+
+ case EAXREVERB_DECAYHFRATIO:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flDecayHFRatio);
+ break;
+
+ case EAXREVERB_DECAYLFRATIO:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flDecayLFRatio);
+ break;
+
+ case EAXREVERB_REFLECTIONS:
+ eax_call.set_value<EaxReverbEffectException>(eax_.lReflections);
+ break;
+
+ case EAXREVERB_REFLECTIONSDELAY:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flReflectionsDelay);
+ break;
+
+ case EAXREVERB_REFLECTIONSPAN:
+ eax_call.set_value<EaxReverbEffectException>(eax_.vReflectionsPan);
+ break;
+
+ case EAXREVERB_REVERB:
+ eax_call.set_value<EaxReverbEffectException>(eax_.lReverb);
+ break;
+
+ case EAXREVERB_REVERBDELAY:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flReverbDelay);
+ break;
+
+ case EAXREVERB_REVERBPAN:
+ eax_call.set_value<EaxReverbEffectException>(eax_.vReverbPan);
+ break;
+
+ case EAXREVERB_ECHOTIME:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flEchoTime);
+ break;
+
+ case EAXREVERB_ECHODEPTH:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flEchoDepth);
+ break;
+
+ case EAXREVERB_MODULATIONTIME:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flModulationTime);
+ break;
+
+ case EAXREVERB_MODULATIONDEPTH:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flModulationDepth);
+ break;
+
+ case EAXREVERB_AIRABSORPTIONHF:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flAirAbsorptionHF);
+ break;
+
+ case EAXREVERB_HFREFERENCE:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flHFReference);
+ break;
+
+ case EAXREVERB_LFREFERENCE:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flLFReference);
+ break;
+
+ case EAXREVERB_ROOMROLLOFFFACTOR:
+ eax_call.set_value<EaxReverbEffectException>(eax_.flRoomRolloffFactor);
+ break;
+
+ case EAXREVERB_FLAGS:
+ eax_call.set_value<EaxReverbEffectException>(eax_.ulFlags);
+ break;
+
+ default:
+ throw EaxReverbEffectException{"Unsupported property id."};
+ }
+
+ return false;
+}
+
+void EaxReverbEffect::validate_environment(
+ unsigned long ulEnvironment,
+ int version,
+ bool is_standalone)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Environment",
+ ulEnvironment,
+ EAXREVERB_MINENVIRONMENT,
+ (version == 2 || is_standalone) ? EAX20REVERB_MAXENVIRONMENT : EAX30REVERB_MAXENVIRONMENT);
+}
+
+void EaxReverbEffect::validate_environment_size(
+ float flEnvironmentSize)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Environment Size",
+ flEnvironmentSize,
+ EAXREVERB_MINENVIRONMENTSIZE,
+ EAXREVERB_MAXENVIRONMENTSIZE);
+}
+
+void EaxReverbEffect::validate_environment_diffusion(
+ float flEnvironmentDiffusion)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Environment Diffusion",
+ flEnvironmentDiffusion,
+ EAXREVERB_MINENVIRONMENTDIFFUSION,
+ EAXREVERB_MAXENVIRONMENTDIFFUSION);
+}
+
+void EaxReverbEffect::validate_room(
+ long lRoom)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Room",
+ lRoom,
+ EAXREVERB_MINROOM,
+ EAXREVERB_MAXROOM);
+}
+
+void EaxReverbEffect::validate_room_hf(
+ long lRoomHF)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Room HF",
+ lRoomHF,
+ EAXREVERB_MINROOMHF,
+ EAXREVERB_MAXROOMHF);
+}
+
+void EaxReverbEffect::validate_room_lf(
+ long lRoomLF)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Room LF",
+ lRoomLF,
+ EAXREVERB_MINROOMLF,
+ EAXREVERB_MAXROOMLF);
+}
+
+void EaxReverbEffect::validate_decay_time(
+ float flDecayTime)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Decay Time",
+ flDecayTime,
+ EAXREVERB_MINDECAYTIME,
+ EAXREVERB_MAXDECAYTIME);
+}
+
+void EaxReverbEffect::validate_decay_hf_ratio(
+ float flDecayHFRatio)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Decay HF Ratio",
+ flDecayHFRatio,
+ EAXREVERB_MINDECAYHFRATIO,
+ EAXREVERB_MAXDECAYHFRATIO);
+}
+
+void EaxReverbEffect::validate_decay_lf_ratio(
+ float flDecayLFRatio)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Decay LF Ratio",
+ flDecayLFRatio,
+ EAXREVERB_MINDECAYLFRATIO,
+ EAXREVERB_MAXDECAYLFRATIO);
+}
+
+void EaxReverbEffect::validate_reflections(
+ long lReflections)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Reflections",
+ lReflections,
+ EAXREVERB_MINREFLECTIONS,
+ EAXREVERB_MAXREFLECTIONS);
+}
+
+void EaxReverbEffect::validate_reflections_delay(
+ float flReflectionsDelay)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Reflections Delay",
+ flReflectionsDelay,
+ EAXREVERB_MINREFLECTIONSDELAY,
+ EAXREVERB_MAXREFLECTIONSDELAY);
+}
+
+void EaxReverbEffect::validate_reflections_pan(
+ const EAXVECTOR& vReflectionsPan)
+{
+ std::ignore = vReflectionsPan;
+}
+
+void EaxReverbEffect::validate_reverb(
+ long lReverb)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Reverb",
+ lReverb,
+ EAXREVERB_MINREVERB,
+ EAXREVERB_MAXREVERB);
+}
+
+void EaxReverbEffect::validate_reverb_delay(
+ float flReverbDelay)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Reverb Delay",
+ flReverbDelay,
+ EAXREVERB_MINREVERBDELAY,
+ EAXREVERB_MAXREVERBDELAY);
+}
+
+void EaxReverbEffect::validate_reverb_pan(
+ const EAXVECTOR& vReverbPan)
+{
+ std::ignore = vReverbPan;
+}
+
+void EaxReverbEffect::validate_echo_time(
+ float flEchoTime)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Echo Time",
+ flEchoTime,
+ EAXREVERB_MINECHOTIME,
+ EAXREVERB_MAXECHOTIME);
+}
+
+void EaxReverbEffect::validate_echo_depth(
+ float flEchoDepth)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Echo Depth",
+ flEchoDepth,
+ EAXREVERB_MINECHODEPTH,
+ EAXREVERB_MAXECHODEPTH);
+}
+
+void EaxReverbEffect::validate_modulation_time(
+ float flModulationTime)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Modulation Time",
+ flModulationTime,
+ EAXREVERB_MINMODULATIONTIME,
+ EAXREVERB_MAXMODULATIONTIME);
+}
+
+void EaxReverbEffect::validate_modulation_depth(
+ float flModulationDepth)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Modulation Depth",
+ flModulationDepth,
+ EAXREVERB_MINMODULATIONDEPTH,
+ EAXREVERB_MAXMODULATIONDEPTH);
+}
+
+void EaxReverbEffect::validate_air_absorbtion_hf(
+ float air_absorbtion_hf)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Air Absorbtion HF",
+ air_absorbtion_hf,
+ EAXREVERB_MINAIRABSORPTIONHF,
+ EAXREVERB_MAXAIRABSORPTIONHF);
+}
+
+void EaxReverbEffect::validate_hf_reference(
+ float flHFReference)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "HF Reference",
+ flHFReference,
+ EAXREVERB_MINHFREFERENCE,
+ EAXREVERB_MAXHFREFERENCE);
+}
+
+void EaxReverbEffect::validate_lf_reference(
+ float flLFReference)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "LF Reference",
+ flLFReference,
+ EAXREVERB_MINLFREFERENCE,
+ EAXREVERB_MAXLFREFERENCE);
+}
+
+void EaxReverbEffect::validate_room_rolloff_factor(
+ float flRoomRolloffFactor)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Room Rolloff Factor",
+ flRoomRolloffFactor,
+ EAXREVERB_MINROOMROLLOFFFACTOR,
+ EAXREVERB_MAXROOMROLLOFFFACTOR);
+}
+
+void EaxReverbEffect::validate_flags(
+ unsigned long ulFlags)
+{
+ eax_validate_range<EaxReverbEffectException>(
+ "Flags",
+ ulFlags,
+ 0UL,
+ ~EAXREVERBFLAGS_RESERVED);
+}
+
+void EaxReverbEffect::validate_all(
+ const EAX20LISTENERPROPERTIES& listener,
+ int version)
+{
+ validate_room(listener.lRoom);
+ validate_room_hf(listener.lRoomHF);
+ validate_room_rolloff_factor(listener.flRoomRolloffFactor);
+ validate_decay_time(listener.flDecayTime);
+ validate_decay_hf_ratio(listener.flDecayHFRatio);
+ validate_reflections(listener.lReflections);
+ validate_reflections_delay(listener.flReflectionsDelay);
+ validate_reverb(listener.lReverb);
+ validate_reverb_delay(listener.flReverbDelay);
+ validate_environment(listener.dwEnvironment, version, false);
+ validate_environment_size(listener.flEnvironmentSize);
+ validate_environment_diffusion(listener.flEnvironmentDiffusion);
+ validate_air_absorbtion_hf(listener.flAirAbsorptionHF);
+ validate_flags(listener.dwFlags);
+}
+
+void EaxReverbEffect::validate_all(
+ const EAXREVERBPROPERTIES& lReverb,
+ int version)
+{
+ validate_environment(lReverb.ulEnvironment, version, false);
+ validate_environment_size(lReverb.flEnvironmentSize);
+ validate_environment_diffusion(lReverb.flEnvironmentDiffusion);
+ validate_room(lReverb.lRoom);
+ validate_room_hf(lReverb.lRoomHF);
+ validate_room_lf(lReverb.lRoomLF);
+ validate_decay_time(lReverb.flDecayTime);
+ validate_decay_hf_ratio(lReverb.flDecayHFRatio);
+ validate_decay_lf_ratio(lReverb.flDecayLFRatio);
+ validate_reflections(lReverb.lReflections);
+ validate_reflections_delay(lReverb.flReflectionsDelay);
+ validate_reverb(lReverb.lReverb);
+ validate_reverb_delay(lReverb.flReverbDelay);
+ validate_echo_time(lReverb.flEchoTime);
+ validate_echo_depth(lReverb.flEchoDepth);
+ validate_modulation_time(lReverb.flModulationTime);
+ validate_modulation_depth(lReverb.flModulationDepth);
+ validate_air_absorbtion_hf(lReverb.flAirAbsorptionHF);
+ validate_hf_reference(lReverb.flHFReference);
+ validate_lf_reference(lReverb.flLFReference);
+ validate_room_rolloff_factor(lReverb.flRoomRolloffFactor);
+ validate_flags(lReverb.ulFlags);
+}
+
+void EaxReverbEffect::defer_environment(
+ unsigned long ulEnvironment)
+{
+ eax_d_.ulEnvironment = ulEnvironment;
+ eax_dirty_flags_.ulEnvironment = (eax_.ulEnvironment != eax_d_.ulEnvironment);
+}
+
+void EaxReverbEffect::defer_environment_size(
+ float flEnvironmentSize)
+{
+ eax_d_.flEnvironmentSize = flEnvironmentSize;
+ eax_dirty_flags_.flEnvironmentSize = (eax_.flEnvironmentSize != eax_d_.flEnvironmentSize);
+}
+
+void EaxReverbEffect::defer_environment_diffusion(
+ float flEnvironmentDiffusion)
+{
+ eax_d_.flEnvironmentDiffusion = flEnvironmentDiffusion;
+ eax_dirty_flags_.flEnvironmentDiffusion = (eax_.flEnvironmentDiffusion != eax_d_.flEnvironmentDiffusion);
+}
+
+void EaxReverbEffect::defer_room(
+ long lRoom)
+{
+ eax_d_.lRoom = lRoom;
+ eax_dirty_flags_.lRoom = (eax_.lRoom != eax_d_.lRoom);
+}
+
+void EaxReverbEffect::defer_room_hf(
+ long lRoomHF)
+{
+ eax_d_.lRoomHF = lRoomHF;
+ eax_dirty_flags_.lRoomHF = (eax_.lRoomHF != eax_d_.lRoomHF);
+}
+
+void EaxReverbEffect::defer_room_lf(
+ long lRoomLF)
+{
+ eax_d_.lRoomLF = lRoomLF;
+ eax_dirty_flags_.lRoomLF = (eax_.lRoomLF != eax_d_.lRoomLF);
+}
+
+void EaxReverbEffect::defer_decay_time(
+ float flDecayTime)
+{
+ eax_d_.flDecayTime = flDecayTime;
+ eax_dirty_flags_.flDecayTime = (eax_.flDecayTime != eax_d_.flDecayTime);
+}
+
+void EaxReverbEffect::defer_decay_hf_ratio(
+ float flDecayHFRatio)
+{
+ eax_d_.flDecayHFRatio = flDecayHFRatio;
+ eax_dirty_flags_.flDecayHFRatio = (eax_.flDecayHFRatio != eax_d_.flDecayHFRatio);
+}
+
+void EaxReverbEffect::defer_decay_lf_ratio(
+ float flDecayLFRatio)
+{
+ eax_d_.flDecayLFRatio = flDecayLFRatio;
+ eax_dirty_flags_.flDecayLFRatio = (eax_.flDecayLFRatio != eax_d_.flDecayLFRatio);
+}
+
+void EaxReverbEffect::defer_reflections(
+ long lReflections)
+{
+ eax_d_.lReflections = lReflections;
+ eax_dirty_flags_.lReflections = (eax_.lReflections != eax_d_.lReflections);
+}
+
+void EaxReverbEffect::defer_reflections_delay(
+ float flReflectionsDelay)
+{
+ eax_d_.flReflectionsDelay = flReflectionsDelay;
+ eax_dirty_flags_.flReflectionsDelay = (eax_.flReflectionsDelay != eax_d_.flReflectionsDelay);
+}
+
+void EaxReverbEffect::defer_reflections_pan(
+ const EAXVECTOR& vReflectionsPan)
+{
+ eax_d_.vReflectionsPan = vReflectionsPan;
+ eax_dirty_flags_.vReflectionsPan = (eax_.vReflectionsPan != eax_d_.vReflectionsPan);
+}
+
+void EaxReverbEffect::defer_reverb(
+ long lReverb)
+{
+ eax_d_.lReverb = lReverb;
+ eax_dirty_flags_.lReverb = (eax_.lReverb != eax_d_.lReverb);
+}
+
+void EaxReverbEffect::defer_reverb_delay(
+ float flReverbDelay)
+{
+ eax_d_.flReverbDelay = flReverbDelay;
+ eax_dirty_flags_.flReverbDelay = (eax_.flReverbDelay != eax_d_.flReverbDelay);
+}
+
+void EaxReverbEffect::defer_reverb_pan(
+ const EAXVECTOR& vReverbPan)
+{
+ eax_d_.vReverbPan = vReverbPan;
+ eax_dirty_flags_.vReverbPan = (eax_.vReverbPan != eax_d_.vReverbPan);
+}
+
+void EaxReverbEffect::defer_echo_time(
+ float flEchoTime)
+{
+ eax_d_.flEchoTime = flEchoTime;
+ eax_dirty_flags_.flEchoTime = (eax_.flEchoTime != eax_d_.flEchoTime);
+}
+
+void EaxReverbEffect::defer_echo_depth(
+ float flEchoDepth)
+{
+ eax_d_.flEchoDepth = flEchoDepth;
+ eax_dirty_flags_.flEchoDepth = (eax_.flEchoDepth != eax_d_.flEchoDepth);
+}
+
+void EaxReverbEffect::defer_modulation_time(
+ float flModulationTime)
+{
+ eax_d_.flModulationTime = flModulationTime;
+ eax_dirty_flags_.flModulationTime = (eax_.flModulationTime != eax_d_.flModulationTime);
+}
+
+void EaxReverbEffect::defer_modulation_depth(
+ float flModulationDepth)
+{
+ eax_d_.flModulationDepth = flModulationDepth;
+ eax_dirty_flags_.flModulationDepth = (eax_.flModulationDepth != eax_d_.flModulationDepth);
+}
+
+void EaxReverbEffect::defer_air_absorbtion_hf(
+ float flAirAbsorptionHF)
+{
+ eax_d_.flAirAbsorptionHF = flAirAbsorptionHF;
+ eax_dirty_flags_.flAirAbsorptionHF = (eax_.flAirAbsorptionHF != eax_d_.flAirAbsorptionHF);
+}
+
+void EaxReverbEffect::defer_hf_reference(
+ float flHFReference)
+{
+ eax_d_.flHFReference = flHFReference;
+ eax_dirty_flags_.flHFReference = (eax_.flHFReference != eax_d_.flHFReference);
+}
+
+void EaxReverbEffect::defer_lf_reference(
+ float flLFReference)
+{
+ eax_d_.flLFReference = flLFReference;
+ eax_dirty_flags_.flLFReference = (eax_.flLFReference != eax_d_.flLFReference);
+}
+
+void EaxReverbEffect::defer_room_rolloff_factor(
+ float flRoomRolloffFactor)
+{
+ eax_d_.flRoomRolloffFactor = flRoomRolloffFactor;
+ eax_dirty_flags_.flRoomRolloffFactor = (eax_.flRoomRolloffFactor != eax_d_.flRoomRolloffFactor);
+}
+
+void EaxReverbEffect::defer_flags(
+ unsigned long ulFlags)
+{
+ eax_d_.ulFlags = ulFlags;
+ eax_dirty_flags_.ulFlags = (eax_.ulFlags != eax_d_.ulFlags);
+}
+
+void EaxReverbEffect::defer_all(
+ const EAX20LISTENERPROPERTIES& listener)
+{
+ defer_room(listener.lRoom);
+ defer_room_hf(listener.lRoomHF);
+ defer_room_rolloff_factor(listener.flRoomRolloffFactor);
+ defer_decay_time(listener.flDecayTime);
+ defer_decay_hf_ratio(listener.flDecayHFRatio);
+ defer_reflections(listener.lReflections);
+ defer_reflections_delay(listener.flReflectionsDelay);
+ defer_reverb(listener.lReverb);
+ defer_reverb_delay(listener.flReverbDelay);
+ defer_environment(listener.dwEnvironment);
+ defer_environment_size(listener.flEnvironmentSize);
+ defer_environment_diffusion(listener.flEnvironmentDiffusion);
+ defer_air_absorbtion_hf(listener.flAirAbsorptionHF);
+ defer_flags(listener.dwFlags);
+}
+
+void EaxReverbEffect::defer_all(
+ const EAXREVERBPROPERTIES& lReverb)
+{
+ defer_environment(lReverb.ulEnvironment);
+ defer_environment_size(lReverb.flEnvironmentSize);
+ defer_environment_diffusion(lReverb.flEnvironmentDiffusion);
+ defer_room(lReverb.lRoom);
+ defer_room_hf(lReverb.lRoomHF);
+ defer_room_lf(lReverb.lRoomLF);
+ defer_decay_time(lReverb.flDecayTime);
+ defer_decay_hf_ratio(lReverb.flDecayHFRatio);
+ defer_decay_lf_ratio(lReverb.flDecayLFRatio);
+ defer_reflections(lReverb.lReflections);
+ defer_reflections_delay(lReverb.flReflectionsDelay);
+ defer_reflections_pan(lReverb.vReflectionsPan);
+ defer_reverb(lReverb.lReverb);
+ defer_reverb_delay(lReverb.flReverbDelay);
+ defer_reverb_pan(lReverb.vReverbPan);
+ defer_echo_time(lReverb.flEchoTime);
+ defer_echo_depth(lReverb.flEchoDepth);
+ defer_modulation_time(lReverb.flModulationTime);
+ defer_modulation_depth(lReverb.flModulationDepth);
+ defer_air_absorbtion_hf(lReverb.flAirAbsorptionHF);
+ defer_hf_reference(lReverb.flHFReference);
+ defer_lf_reference(lReverb.flLFReference);
+ defer_room_rolloff_factor(lReverb.flRoomRolloffFactor);
+ defer_flags(lReverb.ulFlags);
+}
+
+void EaxReverbEffect::defer_environment(
+ const EaxEaxCall& eax_call)
+{
+ const auto& ulEnvironment =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::ulEnvironment)>();
+
+ validate_environment(ulEnvironment, eax_call.get_version(), true);
+
+ if (eax_d_.ulEnvironment == ulEnvironment)
+ {
+ return;
+ }
+
+ const auto& reverb_preset = EAXREVERB_PRESETS[ulEnvironment];
+
+ defer_all(reverb_preset);
+}
+
+void EaxReverbEffect::defer_environment_size(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flEnvironmentSize =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEnvironmentSize)>();
+
+ validate_environment_size(flEnvironmentSize);
+
+ if (eax_d_.flEnvironmentSize == flEnvironmentSize)
+ {
+ return;
+ }
+
+ const auto scale = flEnvironmentSize / eax_d_.flEnvironmentSize;
+
+ defer_environment_size(flEnvironmentSize);
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0)
+ {
+ const auto flDecayTime = clamp(
+ scale * eax_d_.flDecayTime,
+ EAXREVERB_MINDECAYTIME,
+ EAXREVERB_MAXDECAYTIME);
+
+ defer_decay_time(flDecayTime);
+ }
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0)
+ {
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
+ {
+ const auto lReflections = clamp(
+ eax_d_.lReflections - static_cast<long>(gain_to_level_mb(scale)),
+ EAXREVERB_MINREFLECTIONS,
+ EAXREVERB_MAXREFLECTIONS);
+
+ defer_reflections(lReflections);
+ }
+ }
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
+ {
+ const auto flReflectionsDelay = clamp(
+ eax_d_.flReflectionsDelay * scale,
+ EAXREVERB_MINREFLECTIONSDELAY,
+ EAXREVERB_MAXREFLECTIONSDELAY);
+
+ defer_reflections_delay(flReflectionsDelay);
+ }
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0)
+ {
+ const auto log_scalar = ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
+
+ const auto lReverb = clamp(
+ eax_d_.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
+ EAXREVERB_MINREVERB,
+ EAXREVERB_MAXREVERB);
+
+ defer_reverb(lReverb);
+ }
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0)
+ {
+ const auto flReverbDelay = clamp(
+ scale * eax_d_.flReverbDelay,
+ EAXREVERB_MINREVERBDELAY,
+ EAXREVERB_MAXREVERBDELAY);
+
+ defer_reverb_delay(flReverbDelay);
+ }
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0)
+ {
+ const auto flEchoTime = clamp(
+ eax_d_.flEchoTime * scale,
+ EAXREVERB_MINECHOTIME,
+ EAXREVERB_MAXECHOTIME);
+
+ defer_echo_time(flEchoTime);
+ }
+
+ if ((eax_d_.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0)
+ {
+ const auto flModulationTime = clamp(
+ scale * eax_d_.flModulationTime,
+ EAXREVERB_MINMODULATIONTIME,
+ EAXREVERB_MAXMODULATIONTIME);
+
+ defer_modulation_time(flModulationTime);
+ }
+}
+
+void EaxReverbEffect::defer_environment_diffusion(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flEnvironmentDiffusion =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEnvironmentDiffusion)>();
+
+ validate_environment_diffusion(flEnvironmentDiffusion);
+ defer_environment_diffusion(flEnvironmentDiffusion);
+}
+
+void EaxReverbEffect::defer_room(
+ const EaxEaxCall& eax_call)
+{
+ const auto& lRoom =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lRoom)>();
+
+ validate_room(lRoom);
+ defer_room(lRoom);
+}
+
+void EaxReverbEffect::defer_room_hf(
+ const EaxEaxCall& eax_call)
+{
+ const auto& lRoomHF =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lRoomHF)>();
+
+ validate_room_hf(lRoomHF);
+ defer_room_hf(lRoomHF);
+}
+
+void EaxReverbEffect::defer_room_lf(
+ const EaxEaxCall& eax_call)
+{
+ const auto& lRoomLF =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lRoomLF)>();
+
+ validate_room_lf(lRoomLF);
+ defer_room_lf(lRoomLF);
+}
+
+void EaxReverbEffect::defer_decay_time(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flDecayTime =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flDecayTime)>();
+
+ validate_decay_time(flDecayTime);
+ defer_decay_time(flDecayTime);
+}
+
+void EaxReverbEffect::defer_decay_hf_ratio(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flDecayHFRatio =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flDecayHFRatio)>();
+
+ validate_decay_hf_ratio(flDecayHFRatio);
+ defer_decay_hf_ratio(flDecayHFRatio);
+}
+
+void EaxReverbEffect::defer_decay_lf_ratio(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flDecayLFRatio =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flDecayLFRatio)>();
+
+ validate_decay_lf_ratio(flDecayLFRatio);
+ defer_decay_lf_ratio(flDecayLFRatio);
+}
+
+void EaxReverbEffect::defer_reflections(
+ const EaxEaxCall& eax_call)
+{
+ const auto& lReflections =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lReflections)>();
+
+ validate_reflections(lReflections);
+ defer_reflections(lReflections);
+}
+
+void EaxReverbEffect::defer_reflections_delay(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flReflectionsDelay =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flReflectionsDelay)>();
+
+ validate_reflections_delay(flReflectionsDelay);
+ defer_reflections_delay(flReflectionsDelay);
+}
+
+void EaxReverbEffect::defer_reflections_pan(
+ const EaxEaxCall& eax_call)
+{
+ const auto& vReflectionsPan =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::vReflectionsPan)>();
+
+ validate_reflections_pan(vReflectionsPan);
+ defer_reflections_pan(vReflectionsPan);
+}
+
+void EaxReverbEffect::defer_reverb(
+ const EaxEaxCall& eax_call)
+{
+ const auto& lReverb =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lReverb)>();
+
+ validate_reverb(lReverb);
+ defer_reverb(lReverb);
+}
+
+void EaxReverbEffect::defer_reverb_delay(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flReverbDelay =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flReverbDelay)>();
+
+ validate_reverb_delay(flReverbDelay);
+ defer_reverb_delay(flReverbDelay);
+}
+
+void EaxReverbEffect::defer_reverb_pan(
+ const EaxEaxCall& eax_call)
+{
+ const auto& vReverbPan =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::vReverbPan)>();
+
+ validate_reverb_pan(vReverbPan);
+ defer_reverb_pan(vReverbPan);
+}
+
+void EaxReverbEffect::defer_echo_time(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flEchoTime =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEchoTime)>();
+
+ validate_echo_time(flEchoTime);
+ defer_echo_time(flEchoTime);
+}
+
+void EaxReverbEffect::defer_echo_depth(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flEchoDepth =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEchoDepth)>();
+
+ validate_echo_depth(flEchoDepth);
+ defer_echo_depth(flEchoDepth);
+}
+
+void EaxReverbEffect::defer_modulation_time(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flModulationTime =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flModulationTime)>();
+
+ validate_modulation_time(flModulationTime);
+ defer_modulation_time(flModulationTime);
+}
+
+void EaxReverbEffect::defer_modulation_depth(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flModulationDepth =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flModulationDepth)>();
+
+ validate_modulation_depth(flModulationDepth);
+ defer_modulation_depth(flModulationDepth);
+}
+
+void EaxReverbEffect::defer_air_absorbtion_hf(
+ const EaxEaxCall& eax_call)
+{
+ const auto& air_absorbtion_hf =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flAirAbsorptionHF)>();
+
+ validate_air_absorbtion_hf(air_absorbtion_hf);
+ defer_air_absorbtion_hf(air_absorbtion_hf);
+}
+
+void EaxReverbEffect::defer_hf_reference(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flHFReference =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flHFReference)>();
+
+ validate_hf_reference(flHFReference);
+ defer_hf_reference(flHFReference);
+}
+
+void EaxReverbEffect::defer_lf_reference(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flLFReference =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flLFReference)>();
+
+ validate_lf_reference(flLFReference);
+ defer_lf_reference(flLFReference);
+}
+
+void EaxReverbEffect::defer_room_rolloff_factor(
+ const EaxEaxCall& eax_call)
+{
+ const auto& flRoomRolloffFactor =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flRoomRolloffFactor)>();
+
+ validate_room_rolloff_factor(flRoomRolloffFactor);
+ defer_room_rolloff_factor(flRoomRolloffFactor);
+}
+
+void EaxReverbEffect::defer_flags(
+ const EaxEaxCall& eax_call)
+{
+ const auto& ulFlags =
+ eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::ulFlags)>();
+
+ validate_flags(ulFlags);
+ defer_flags(ulFlags);
+}
+
+void EaxReverbEffect::defer_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto eax_version = eax_call.get_version();
+
+ if (eax_version == 2)
+ {
+ const auto& listener =
+ eax_call.get_value<EaxReverbEffectException, const EAX20LISTENERPROPERTIES>();
+
+ validate_all(listener, eax_version);
+ defer_all(listener);
+ }
+ else
+ {
+ const auto& reverb_all =
+ eax_call.get_value<EaxReverbEffectException, const EAXREVERBPROPERTIES>();
+
+ validate_all(reverb_all, eax_version);
+ defer_all(reverb_all);
+ }
+}
+
+// [[nodiscard]]
+bool EaxReverbEffect::apply_deferred()
+{
+ if (eax_dirty_flags_ == EaxReverbEffectDirtyFlags{})
+ {
+ return false;
+ }
+
+ eax_ = eax_d_;
+
+ if (eax_dirty_flags_.ulEnvironment)
+ {
+ }
+
+ if (eax_dirty_flags_.flEnvironmentSize)
+ {
+ set_efx_density();
+ }
+
+ if (eax_dirty_flags_.flEnvironmentDiffusion)
+ {
+ set_efx_diffusion();
+ }
+
+ if (eax_dirty_flags_.lRoom)
+ {
+ set_efx_gain();
+ }
+
+ if (eax_dirty_flags_.lRoomHF)
+ {
+ set_efx_gain_hf();
+ }
+
+ if (eax_dirty_flags_.lRoomLF)
+ {
+ set_efx_gain_lf();
+ }
+
+ if (eax_dirty_flags_.flDecayTime)
+ {
+ set_efx_decay_time();
+ }
+
+ if (eax_dirty_flags_.flDecayHFRatio)
+ {
+ set_efx_decay_hf_ratio();
+ }
+
+ if (eax_dirty_flags_.flDecayLFRatio)
+ {
+ set_efx_decay_lf_ratio();
+ }
+
+ if (eax_dirty_flags_.lReflections)
+ {
+ set_efx_reflections_gain();
+ }
+
+ if (eax_dirty_flags_.flReflectionsDelay)
+ {
+ set_efx_reflections_delay();
+ }
+
+ if (eax_dirty_flags_.vReflectionsPan)
+ {
+ set_efx_reflections_pan();
+ }
+
+ if (eax_dirty_flags_.lReverb)
+ {
+ set_efx_late_reverb_gain();
+ }
+
+ if (eax_dirty_flags_.flReverbDelay)
+ {
+ set_efx_late_reverb_delay();
+ }
+
+ if (eax_dirty_flags_.vReverbPan)
+ {
+ set_efx_late_reverb_pan();
+ }
+
+ if (eax_dirty_flags_.flEchoTime)
+ {
+ set_efx_echo_time();
+ }
+
+ if (eax_dirty_flags_.flEchoDepth)
+ {
+ set_efx_echo_depth();
+ }
+
+ if (eax_dirty_flags_.flModulationTime)
+ {
+ set_efx_modulation_time();
+ }
+
+ if (eax_dirty_flags_.flModulationDepth)
+ {
+ set_efx_modulation_depth();
+ }
+
+ if (eax_dirty_flags_.flAirAbsorptionHF)
+ {
+ set_efx_air_absorption_gain_hf();
+ }
+
+ if (eax_dirty_flags_.flHFReference)
+ {
+ set_efx_hf_reference();
+ }
+
+ if (eax_dirty_flags_.flLFReference)
+ {
+ set_efx_lf_reference();
+ }
+
+ if (eax_dirty_flags_.flRoomRolloffFactor)
+ {
+ set_efx_room_rolloff_factor();
+ }
+
+ if (eax_dirty_flags_.ulFlags)
+ {
+ set_efx_flags();
+ }
+
+ eax_dirty_flags_ = EaxReverbEffectDirtyFlags{};
+
+ return true;
+}
+
+// [[nodiscard]]
+bool EaxReverbEffect::set(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_property_id())
+ {
+ case EAXREVERB_NONE:
+ break;
+
+ case EAXREVERB_ALLPARAMETERS:
+ defer_all(eax_call);
+ break;
+
+ case EAXREVERB_ENVIRONMENT:
+ defer_environment(eax_call);
+ break;
+
+ case EAXREVERB_ENVIRONMENTSIZE:
+ defer_environment_size(eax_call);
+ break;
+
+ case EAXREVERB_ENVIRONMENTDIFFUSION:
+ defer_environment_diffusion(eax_call);
+ break;
+
+ case EAXREVERB_ROOM:
+ defer_room(eax_call);
+ break;
+
+ case EAXREVERB_ROOMHF:
+ defer_room_hf(eax_call);
+ break;
+
+ case EAXREVERB_ROOMLF:
+ defer_room_lf(eax_call);
+ break;
+
+ case EAXREVERB_DECAYTIME:
+ defer_decay_time(eax_call);
+ break;
+
+ case EAXREVERB_DECAYHFRATIO:
+ defer_decay_hf_ratio(eax_call);
+ break;
+
+ case EAXREVERB_DECAYLFRATIO:
+ defer_decay_lf_ratio(eax_call);
+ break;
+
+ case EAXREVERB_REFLECTIONS:
+ defer_reflections(eax_call);
+ break;
+
+ case EAXREVERB_REFLECTIONSDELAY:
+ defer_reflections_delay(eax_call);
+ break;
+
+ case EAXREVERB_REFLECTIONSPAN:
+ defer_reflections_pan(eax_call);
+ break;
+
+ case EAXREVERB_REVERB:
+ defer_reverb(eax_call);
+ break;
+
+ case EAXREVERB_REVERBDELAY:
+ defer_reverb_delay(eax_call);
+ break;
+
+ case EAXREVERB_REVERBPAN:
+ defer_reverb_pan(eax_call);
+ break;
+
+ case EAXREVERB_ECHOTIME:
+ defer_echo_time(eax_call);
+ break;
+
+ case EAXREVERB_ECHODEPTH:
+ defer_echo_depth(eax_call);
+ break;
+
+ case EAXREVERB_MODULATIONTIME:
+ defer_modulation_time(eax_call);
+ break;
+
+ case EAXREVERB_MODULATIONDEPTH:
+ defer_modulation_depth(eax_call);
+ break;
+
+ case EAXREVERB_AIRABSORPTIONHF:
+ defer_air_absorbtion_hf(eax_call);
+ break;
+
+ case EAXREVERB_HFREFERENCE:
+ defer_hf_reference(eax_call);
+ break;
+
+ case EAXREVERB_LFREFERENCE:
+ defer_lf_reference(eax_call);
+ break;
+
+ case EAXREVERB_ROOMROLLOFFFACTOR:
+ defer_room_rolloff_factor(eax_call);
+ break;
+
+ case EAXREVERB_FLAGS:
+ defer_flags(eax_call);
+ break;
+
+ default:
+ throw EaxReverbEffectException{"Unsupported property id."};
+ }
+
+ if (!eax_call.is_deferred())
+ {
+ return apply_deferred();
+ }
+
+ return false;
+}
+
+
+} // namespace
+
+
+EaxEffectUPtr eax_create_eax_reverb_effect(
+ EffectProps& al_effect_props)
+{
+ return std::make_unique<EaxReverbEffect>(al_effect_props);
+}
+
+
+#endif // ALSOFT_EAX