aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects/equalizer.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/equalizer.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/equalizer.cpp')
-rw-r--r--al/effects/equalizer.cpp866
1 files changed, 866 insertions, 0 deletions
diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp
index 3c039688..c052db3e 100644
--- a/al/effects/equalizer.cpp
+++ b/al/effects/equalizer.cpp
@@ -7,6 +7,13 @@
#include "alc/effects/base.h"
#include "effects.h"
+#if ALSOFT_EAX
+#include "alnumeric.h"
+
+#include "al/eax_exception.h"
+#include "al/eax_utils.h"
+#endif // ALSOFT_EAX
+
namespace {
@@ -167,3 +174,862 @@ EffectProps genDefaultProps() noexcept
DEFINE_ALEFFECT_VTABLE(Equalizer);
const EffectProps EqualizerEffectProps{genDefaultProps()};
+
+#if ALSOFT_EAX
+namespace
+{
+
+
+using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t;
+
+struct EaxEqualizerEffectDirtyFlags
+{
+ using EaxIsBitFieldStruct = bool;
+
+ EaxEqualizerEffectDirtyFlagsValue lLowGain : 1;
+ EaxEqualizerEffectDirtyFlagsValue flLowCutOff : 1;
+ EaxEqualizerEffectDirtyFlagsValue lMid1Gain : 1;
+ EaxEqualizerEffectDirtyFlagsValue flMid1Center : 1;
+ EaxEqualizerEffectDirtyFlagsValue flMid1Width : 1;
+ EaxEqualizerEffectDirtyFlagsValue lMid2Gain : 1;
+ EaxEqualizerEffectDirtyFlagsValue flMid2Center : 1;
+ EaxEqualizerEffectDirtyFlagsValue flMid2Width : 1;
+ EaxEqualizerEffectDirtyFlagsValue lHighGain : 1;
+ EaxEqualizerEffectDirtyFlagsValue flHighCutOff : 1;
+}; // EaxEqualizerEffectDirtyFlags
+
+
+class EaxEqualizerEffect final :
+ public EaxEffect
+{
+public:
+ EaxEqualizerEffect(
+ EffectProps& al_effect_props);
+
+
+ // [[nodiscard]]
+ bool dispatch(
+ const EaxEaxCall& eax_call) override;
+
+
+private:
+ EffectProps& al_effect_props_;
+
+ EAXEQUALIZERPROPERTIES eax_{};
+ EAXEQUALIZERPROPERTIES eax_d_{};
+ EaxEqualizerEffectDirtyFlags eax_dirty_flags_{};
+
+
+ void set_eax_defaults();
+
+
+ void set_efx_low_gain();
+
+ void set_efx_low_cutoff();
+
+ void set_efx_mid1_gain();
+
+ void set_efx_mid1_center();
+
+ void set_efx_mid1_width();
+
+ void set_efx_mid2_gain();
+
+ void set_efx_mid2_center();
+
+ void set_efx_mid2_width();
+
+ void set_efx_high_gain();
+
+ void set_efx_high_cutoff();
+
+ void set_efx_defaults();
+
+
+ // [[nodiscard]]
+ bool get(
+ const EaxEaxCall& eax_call);
+
+
+ void validate_low_gain(
+ long lLowGain);
+
+ void validate_low_cutoff(
+ float flLowCutOff);
+
+ void validate_mid1_gain(
+ long lMid1Gain);
+
+ void validate_mid1_center(
+ float flMid1Center);
+
+ void validate_mid1_width(
+ float flMid1Width);
+
+ void validate_mid2_gain(
+ long lMid2Gain);
+
+ void validate_mid2_center(
+ float flMid2Center);
+
+ void validate_mid2_width(
+ float flMid2Width);
+
+ void validate_high_gain(
+ long lHighGain);
+
+ void validate_high_cutoff(
+ float flHighCutOff);
+
+ void validate_all(
+ const EAXEQUALIZERPROPERTIES& all);
+
+
+ void defer_low_gain(
+ long lLowGain);
+
+ void defer_low_cutoff(
+ float flLowCutOff);
+
+ void defer_mid1_gain(
+ long lMid1Gain);
+
+ void defer_mid1_center(
+ float flMid1Center);
+
+ void defer_mid1_width(
+ float flMid1Width);
+
+ void defer_mid2_gain(
+ long lMid2Gain);
+
+ void defer_mid2_center(
+ float flMid2Center);
+
+ void defer_mid2_width(
+ float flMid2Width);
+
+ void defer_high_gain(
+ long lHighGain);
+
+ void defer_high_cutoff(
+ float flHighCutOff);
+
+ void defer_all(
+ const EAXEQUALIZERPROPERTIES& all);
+
+
+ void defer_low_gain(
+ const EaxEaxCall& eax_call);
+
+ void defer_low_cutoff(
+ const EaxEaxCall& eax_call);
+
+ void defer_mid1_gain(
+ const EaxEaxCall& eax_call);
+
+ void defer_mid1_center(
+ const EaxEaxCall& eax_call);
+
+ void defer_mid1_width(
+ const EaxEaxCall& eax_call);
+
+ void defer_mid2_gain(
+ const EaxEaxCall& eax_call);
+
+ void defer_mid2_center(
+ const EaxEaxCall& eax_call);
+
+ void defer_mid2_width(
+ const EaxEaxCall& eax_call);
+
+ void defer_high_gain(
+ const EaxEaxCall& eax_call);
+
+ void defer_high_cutoff(
+ const EaxEaxCall& eax_call);
+
+ void defer_all(
+ const EaxEaxCall& eax_call);
+
+
+ // [[nodiscard]]
+ bool apply_deferred();
+
+ // [[nodiscard]]
+ bool set(
+ const EaxEaxCall& eax_call);
+}; // EaxEqualizerEffect
+
+
+class EaxEqualizerEffectException :
+ public EaxException
+{
+public:
+ explicit EaxEqualizerEffectException(
+ const char* message)
+ :
+ EaxException{"EAX_EQUALIZER_EFFECT", message}
+ {
+ }
+}; // EaxEqualizerEffectException
+
+
+EaxEqualizerEffect::EaxEqualizerEffect(
+ EffectProps& al_effect_props)
+ :
+ al_effect_props_{al_effect_props}
+{
+ set_eax_defaults();
+ set_efx_defaults();
+}
+
+// [[nodiscard]]
+bool EaxEqualizerEffect::dispatch(
+ const EaxEaxCall& eax_call)
+{
+ return eax_call.is_get() ? get(eax_call) : set(eax_call);
+}
+
+void EaxEqualizerEffect::set_eax_defaults()
+{
+ eax_.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
+ eax_.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
+ eax_.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
+ eax_.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
+ eax_.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
+ eax_.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
+ eax_.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
+ eax_.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
+ eax_.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
+ eax_.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
+
+ eax_d_ = eax_;
+}
+
+void EaxEqualizerEffect::set_efx_low_gain()
+{
+ const auto low_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lLowGain)),
+ AL_EQUALIZER_MIN_LOW_GAIN,
+ AL_EQUALIZER_MAX_LOW_GAIN);
+
+ al_effect_props_.Equalizer.LowGain = low_gain;
+}
+
+void EaxEqualizerEffect::set_efx_low_cutoff()
+{
+ const auto low_cutoff = clamp(
+ eax_.flLowCutOff,
+ AL_EQUALIZER_MIN_LOW_CUTOFF,
+ AL_EQUALIZER_MAX_LOW_CUTOFF);
+
+ al_effect_props_.Equalizer.LowCutoff = low_cutoff;
+}
+
+void EaxEqualizerEffect::set_efx_mid1_gain()
+{
+ const auto mid1_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lMid1Gain)),
+ AL_EQUALIZER_MIN_MID1_GAIN,
+ AL_EQUALIZER_MAX_MID1_GAIN);
+
+ al_effect_props_.Equalizer.Mid1Gain = mid1_gain;
+}
+
+void EaxEqualizerEffect::set_efx_mid1_center()
+{
+ const auto mid1_center = clamp(
+ eax_.flMid1Center,
+ AL_EQUALIZER_MIN_MID1_CENTER,
+ AL_EQUALIZER_MAX_MID1_CENTER);
+
+ al_effect_props_.Equalizer.Mid1Center = mid1_center;
+}
+
+void EaxEqualizerEffect::set_efx_mid1_width()
+{
+ const auto mid1_width = clamp(
+ eax_.flMid1Width,
+ AL_EQUALIZER_MIN_MID1_WIDTH,
+ AL_EQUALIZER_MAX_MID1_WIDTH);
+
+ al_effect_props_.Equalizer.Mid1Width = mid1_width;
+}
+
+void EaxEqualizerEffect::set_efx_mid2_gain()
+{
+ const auto mid2_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lMid2Gain)),
+ AL_EQUALIZER_MIN_MID2_GAIN,
+ AL_EQUALIZER_MAX_MID2_GAIN);
+
+ al_effect_props_.Equalizer.Mid2Gain = mid2_gain;
+}
+
+void EaxEqualizerEffect::set_efx_mid2_center()
+{
+ const auto mid2_center = clamp(
+ eax_.flMid2Center,
+ AL_EQUALIZER_MIN_MID2_CENTER,
+ AL_EQUALIZER_MAX_MID2_CENTER);
+
+ al_effect_props_.Equalizer.Mid2Center = mid2_center;
+}
+
+void EaxEqualizerEffect::set_efx_mid2_width()
+{
+ const auto mid2_width = clamp(
+ eax_.flMid2Width,
+ AL_EQUALIZER_MIN_MID2_WIDTH,
+ AL_EQUALIZER_MAX_MID2_WIDTH);
+
+ al_effect_props_.Equalizer.Mid2Width = mid2_width;
+}
+
+void EaxEqualizerEffect::set_efx_high_gain()
+{
+ const auto high_gain = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.lHighGain)),
+ AL_EQUALIZER_MIN_HIGH_GAIN,
+ AL_EQUALIZER_MAX_HIGH_GAIN);
+
+ al_effect_props_.Equalizer.HighGain = high_gain;
+}
+
+void EaxEqualizerEffect::set_efx_high_cutoff()
+{
+ const auto high_cutoff = clamp(
+ eax_.flHighCutOff,
+ AL_EQUALIZER_MIN_HIGH_CUTOFF,
+ AL_EQUALIZER_MAX_HIGH_CUTOFF);
+
+ al_effect_props_.Equalizer.HighCutoff = high_cutoff;
+}
+
+void EaxEqualizerEffect::set_efx_defaults()
+{
+ set_efx_low_gain();
+ set_efx_low_cutoff();
+ set_efx_mid1_gain();
+ set_efx_mid1_center();
+ set_efx_mid1_width();
+ set_efx_mid2_gain();
+ set_efx_mid2_center();
+ set_efx_mid2_width();
+ set_efx_high_gain();
+ set_efx_high_cutoff();
+}
+
+// [[nodiscard]]
+bool EaxEqualizerEffect::get(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_property_id())
+ {
+ case EAXEQUALIZER_NONE:
+ break;
+
+ case EAXEQUALIZER_ALLPARAMETERS:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_);
+ break;
+
+ case EAXEQUALIZER_LOWGAIN:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.lLowGain);
+ break;
+
+ case EAXEQUALIZER_LOWCUTOFF:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.flLowCutOff);
+ break;
+
+ case EAXEQUALIZER_MID1GAIN:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid1Gain);
+ break;
+
+ case EAXEQUALIZER_MID1CENTER:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Center);
+ break;
+
+ case EAXEQUALIZER_MID1WIDTH:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Width);
+ break;
+
+ case EAXEQUALIZER_MID2GAIN:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid2Gain);
+ break;
+
+ case EAXEQUALIZER_MID2CENTER:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Center);
+ break;
+
+ case EAXEQUALIZER_MID2WIDTH:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Width);
+ break;
+
+ case EAXEQUALIZER_HIGHGAIN:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.lHighGain);
+ break;
+
+ case EAXEQUALIZER_HIGHCUTOFF:
+ eax_call.set_value<EaxEqualizerEffectException>(eax_.flHighCutOff);
+ break;
+
+ default:
+ throw EaxEqualizerEffectException{"Unsupported property id."};
+ }
+
+ return false;
+}
+
+void EaxEqualizerEffect::validate_low_gain(
+ long lLowGain)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Low Gain",
+ lLowGain,
+ EAXEQUALIZER_MINLOWGAIN,
+ EAXEQUALIZER_MAXLOWGAIN);
+}
+
+void EaxEqualizerEffect::validate_low_cutoff(
+ float flLowCutOff)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Low Cutoff",
+ flLowCutOff,
+ EAXEQUALIZER_MINLOWCUTOFF,
+ EAXEQUALIZER_MAXLOWCUTOFF);
+}
+
+void EaxEqualizerEffect::validate_mid1_gain(
+ long lMid1Gain)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Mid1 Gain",
+ lMid1Gain,
+ EAXEQUALIZER_MINMID1GAIN,
+ EAXEQUALIZER_MAXMID1GAIN);
+}
+
+void EaxEqualizerEffect::validate_mid1_center(
+ float flMid1Center)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Mid1 Center",
+ flMid1Center,
+ EAXEQUALIZER_MINMID1CENTER,
+ EAXEQUALIZER_MAXMID1CENTER);
+}
+
+void EaxEqualizerEffect::validate_mid1_width(
+ float flMid1Width)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Mid1 Width",
+ flMid1Width,
+ EAXEQUALIZER_MINMID1WIDTH,
+ EAXEQUALIZER_MAXMID1WIDTH);
+}
+
+void EaxEqualizerEffect::validate_mid2_gain(
+ long lMid2Gain)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Mid2 Gain",
+ lMid2Gain,
+ EAXEQUALIZER_MINMID2GAIN,
+ EAXEQUALIZER_MAXMID2GAIN);
+}
+
+void EaxEqualizerEffect::validate_mid2_center(
+ float flMid2Center)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Mid2 Center",
+ flMid2Center,
+ EAXEQUALIZER_MINMID2CENTER,
+ EAXEQUALIZER_MAXMID2CENTER);
+}
+
+void EaxEqualizerEffect::validate_mid2_width(
+ float flMid2Width)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "Mid2 Width",
+ flMid2Width,
+ EAXEQUALIZER_MINMID2WIDTH,
+ EAXEQUALIZER_MAXMID2WIDTH);
+}
+
+void EaxEqualizerEffect::validate_high_gain(
+ long lHighGain)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "High Gain",
+ lHighGain,
+ EAXEQUALIZER_MINHIGHGAIN,
+ EAXEQUALIZER_MAXHIGHGAIN);
+}
+
+void EaxEqualizerEffect::validate_high_cutoff(
+ float flHighCutOff)
+{
+ eax_validate_range<EaxEqualizerEffectException>(
+ "High Cutoff",
+ flHighCutOff,
+ EAXEQUALIZER_MINHIGHCUTOFF,
+ EAXEQUALIZER_MAXHIGHCUTOFF);
+}
+
+void EaxEqualizerEffect::validate_all(
+ const EAXEQUALIZERPROPERTIES& all)
+{
+ validate_low_gain(all.lLowGain);
+ validate_low_cutoff(all.flLowCutOff);
+ validate_mid1_gain(all.lMid1Gain);
+ validate_mid1_center(all.flMid1Center);
+ validate_mid1_width(all.flMid1Width);
+ validate_mid2_gain(all.lMid2Gain);
+ validate_mid2_center(all.flMid2Center);
+ validate_mid2_width(all.flMid2Width);
+ validate_high_gain(all.lHighGain);
+ validate_high_cutoff(all.flHighCutOff);
+}
+
+void EaxEqualizerEffect::defer_low_gain(
+ long lLowGain)
+{
+ eax_d_.lLowGain = lLowGain;
+ eax_dirty_flags_.lLowGain = (eax_.lLowGain != eax_d_.lLowGain);
+}
+
+void EaxEqualizerEffect::defer_low_cutoff(
+ float flLowCutOff)
+{
+ eax_d_.flLowCutOff = flLowCutOff;
+ eax_dirty_flags_.flLowCutOff = (eax_.flLowCutOff != eax_d_.flLowCutOff);
+}
+
+void EaxEqualizerEffect::defer_mid1_gain(
+ long lMid1Gain)
+{
+ eax_d_.lMid1Gain = lMid1Gain;
+ eax_dirty_flags_.lMid1Gain = (eax_.lMid1Gain != eax_d_.lMid1Gain);
+}
+
+void EaxEqualizerEffect::defer_mid1_center(
+ float flMid1Center)
+{
+ eax_d_.flMid1Center = flMid1Center;
+ eax_dirty_flags_.flMid1Center = (eax_.flMid1Center != eax_d_.flMid1Center);
+}
+
+void EaxEqualizerEffect::defer_mid1_width(
+ float flMid1Width)
+{
+ eax_d_.flMid1Width = flMid1Width;
+ eax_dirty_flags_.flMid1Width = (eax_.flMid1Width != eax_d_.flMid1Width);
+}
+
+void EaxEqualizerEffect::defer_mid2_gain(
+ long lMid2Gain)
+{
+ eax_d_.lMid2Gain = lMid2Gain;
+ eax_dirty_flags_.lMid2Gain = (eax_.lMid2Gain != eax_d_.lMid2Gain);
+}
+
+void EaxEqualizerEffect::defer_mid2_center(
+ float flMid2Center)
+{
+ eax_d_.flMid2Center = flMid2Center;
+ eax_dirty_flags_.flMid2Center = (eax_.flMid2Center != eax_d_.flMid2Center);
+}
+
+void EaxEqualizerEffect::defer_mid2_width(
+ float flMid2Width)
+{
+ eax_d_.flMid2Width = flMid2Width;
+ eax_dirty_flags_.flMid2Width = (eax_.flMid2Width != eax_d_.flMid2Width);
+}
+
+void EaxEqualizerEffect::defer_high_gain(
+ long lHighGain)
+{
+ eax_d_.lHighGain = lHighGain;
+ eax_dirty_flags_.lHighGain = (eax_.lHighGain != eax_d_.lHighGain);
+}
+
+void EaxEqualizerEffect::defer_high_cutoff(
+ float flHighCutOff)
+{
+ eax_d_.flHighCutOff = flHighCutOff;
+ eax_dirty_flags_.flHighCutOff = (eax_.flHighCutOff != eax_d_.flHighCutOff);
+}
+
+void EaxEqualizerEffect::defer_all(
+ const EAXEQUALIZERPROPERTIES& all)
+{
+ defer_low_gain(all.lLowGain);
+ defer_low_cutoff(all.flLowCutOff);
+ defer_mid1_gain(all.lMid1Gain);
+ defer_mid1_center(all.flMid1Center);
+ defer_mid1_width(all.flMid1Width);
+ defer_mid2_gain(all.lMid2Gain);
+ defer_mid2_center(all.flMid2Center);
+ defer_mid2_width(all.flMid2Width);
+ defer_high_gain(all.lHighGain);
+ defer_high_cutoff(all.flHighCutOff);
+}
+
+void EaxEqualizerEffect::defer_low_gain(
+ const EaxEaxCall& eax_call)
+{
+ const auto& low_gain =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lLowGain)>();
+
+ validate_low_gain(low_gain);
+ defer_low_gain(low_gain);
+}
+
+void EaxEqualizerEffect::defer_low_cutoff(
+ const EaxEaxCall& eax_call)
+{
+ const auto& low_cutoff =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flLowCutOff)>();
+
+ validate_low_cutoff(low_cutoff);
+ defer_low_cutoff(low_cutoff);
+}
+
+void EaxEqualizerEffect::defer_mid1_gain(
+ const EaxEaxCall& eax_call)
+{
+ const auto& mid1_gain =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid1Gain)>();
+
+ validate_mid1_gain(mid1_gain);
+ defer_mid1_gain(mid1_gain);
+}
+
+void EaxEqualizerEffect::defer_mid1_center(
+ const EaxEaxCall& eax_call)
+{
+ const auto& mid1_center =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Center)>();
+
+ validate_mid1_center(mid1_center);
+ defer_mid1_center(mid1_center);
+}
+
+void EaxEqualizerEffect::defer_mid1_width(
+ const EaxEaxCall& eax_call)
+{
+ const auto& mid1_width =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Width)>();
+
+ validate_mid1_width(mid1_width);
+ defer_mid1_width(mid1_width);
+}
+
+void EaxEqualizerEffect::defer_mid2_gain(
+ const EaxEaxCall& eax_call)
+{
+ const auto& mid2_gain =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid2Gain)>();
+
+ validate_mid2_gain(mid2_gain);
+ defer_mid2_gain(mid2_gain);
+}
+
+void EaxEqualizerEffect::defer_mid2_center(
+ const EaxEaxCall& eax_call)
+{
+ const auto& mid2_center =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Center)>();
+
+ validate_mid2_center(mid2_center);
+ defer_mid2_center(mid2_center);
+}
+
+void EaxEqualizerEffect::defer_mid2_width(
+ const EaxEaxCall& eax_call)
+{
+ const auto& mid2_width =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Width)>();
+
+ validate_mid2_width(mid2_width);
+ defer_mid2_width(mid2_width);
+}
+
+void EaxEqualizerEffect::defer_high_gain(
+ const EaxEaxCall& eax_call)
+{
+ const auto& high_gain =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lHighGain)>();
+
+ validate_high_gain(high_gain);
+ defer_high_gain(high_gain);
+}
+
+void EaxEqualizerEffect::defer_high_cutoff(
+ const EaxEaxCall& eax_call)
+{
+ const auto& high_cutoff =
+ eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flHighCutOff)>();
+
+ validate_high_cutoff(high_cutoff);
+ defer_high_cutoff(high_cutoff);
+}
+
+void EaxEqualizerEffect::defer_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto& all =
+ eax_call.get_value<EaxEqualizerEffectException, const EAXEQUALIZERPROPERTIES>();
+
+ validate_all(all);
+ defer_all(all);
+}
+
+// [[nodiscard]]
+bool EaxEqualizerEffect::apply_deferred()
+{
+ if (eax_dirty_flags_ == EaxEqualizerEffectDirtyFlags{})
+ {
+ return false;
+ }
+
+ eax_ = eax_d_;
+
+ if (eax_dirty_flags_.lLowGain)
+ {
+ set_efx_low_gain();
+ }
+
+ if (eax_dirty_flags_.flLowCutOff)
+ {
+ set_efx_low_cutoff();
+ }
+
+ if (eax_dirty_flags_.lMid1Gain)
+ {
+ set_efx_mid1_gain();
+ }
+
+ if (eax_dirty_flags_.flMid1Center)
+ {
+ set_efx_mid1_center();
+ }
+
+ if (eax_dirty_flags_.flMid1Width)
+ {
+ set_efx_mid1_width();
+ }
+
+ if (eax_dirty_flags_.lMid2Gain)
+ {
+ set_efx_mid2_gain();
+ }
+
+ if (eax_dirty_flags_.flMid2Center)
+ {
+ set_efx_mid2_center();
+ }
+
+ if (eax_dirty_flags_.flMid2Width)
+ {
+ set_efx_mid2_width();
+ }
+
+ if (eax_dirty_flags_.lHighGain)
+ {
+ set_efx_high_gain();
+ }
+
+ if (eax_dirty_flags_.flHighCutOff)
+ {
+ set_efx_high_cutoff();
+ }
+
+ eax_dirty_flags_ = EaxEqualizerEffectDirtyFlags{};
+
+ return true;
+}
+
+// [[nodiscard]]
+bool EaxEqualizerEffect::set(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_property_id())
+ {
+ case EAXEQUALIZER_NONE:
+ break;
+
+ case EAXEQUALIZER_ALLPARAMETERS:
+ defer_all(eax_call);
+ break;
+
+ case EAXEQUALIZER_LOWGAIN:
+ defer_low_gain(eax_call);
+ break;
+
+ case EAXEQUALIZER_LOWCUTOFF:
+ defer_low_cutoff(eax_call);
+ break;
+
+ case EAXEQUALIZER_MID1GAIN:
+ defer_mid1_gain(eax_call);
+ break;
+
+ case EAXEQUALIZER_MID1CENTER:
+ defer_mid1_center(eax_call);
+ break;
+
+ case EAXEQUALIZER_MID1WIDTH:
+ defer_mid1_width(eax_call);
+ break;
+
+ case EAXEQUALIZER_MID2GAIN:
+ defer_mid2_gain(eax_call);
+ break;
+
+ case EAXEQUALIZER_MID2CENTER:
+ defer_mid2_center(eax_call);
+ break;
+
+ case EAXEQUALIZER_MID2WIDTH:
+ defer_mid2_width(eax_call);
+ break;
+
+ case EAXEQUALIZER_HIGHGAIN:
+ defer_high_gain(eax_call);
+ break;
+
+ case EAXEQUALIZER_HIGHCUTOFF:
+ defer_high_cutoff(eax_call);
+ break;
+
+ default:
+ throw EaxEqualizerEffectException{"Unsupported property id."};
+ }
+
+ if (!eax_call.is_deferred())
+ {
+ return apply_deferred();
+ }
+
+ return false;
+}
+
+
+} // namespace
+
+
+EaxEffectUPtr eax_create_eax_equalizer_effect(
+ EffectProps& al_effect_props)
+{
+ return std::make_unique<EaxEqualizerEffect>(al_effect_props);
+}
+
+
+#endif // ALSOFT_EAX