aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-03-11 00:47:22 -0800
committerChris Robinson <[email protected]>2023-03-11 00:47:22 -0800
commit64ead7d36de7dc748414530121b69876a0c84e05 (patch)
tree91fcacc64d03b0db131b961a8d4d2d457f36343b /al/effects
parent1d112eee0fb5bfe358dc9a7627a64679292a3df5 (diff)
Convert the EAX Echo and Equalizer effects
Diffstat (limited to 'al/effects')
-rw-r--r--al/effects/echo.cpp329
-rw-r--r--al/effects/equalizer.cpp563
2 files changed, 373 insertions, 519 deletions
diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp
index 1a89dffb..98fa5541 100644
--- a/al/effects/echo.cpp
+++ b/al/effects/echo.cpp
@@ -119,235 +119,184 @@ const EffectProps EchoEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-class EaxEchoEffectException : public EaxException
-{
-public:
- explicit EaxEchoEffectException(const char* message)
- : EaxException{"EAX_ECHO_EFFECT", message}
- {}
-}; // EaxEchoEffectException
-
-class EaxEchoEffect final : public EaxEffect4<EaxEchoEffectException>
-{
-public:
- EaxEchoEffect(int eax_version);
-
-private:
- struct DelayValidator {
- void operator()(float flDelay) const
- {
- eax_validate_range<Exception>(
- "Delay",
- flDelay,
- EAXECHO_MINDELAY,
- EAXECHO_MAXDELAY);
- }
- }; // DelayValidator
-
- struct LrDelayValidator {
- void operator()(float flLRDelay) const
- {
- eax_validate_range<Exception>(
- "LR Delay",
- flLRDelay,
- EAXECHO_MINLRDELAY,
- EAXECHO_MAXLRDELAY);
- }
- }; // LrDelayValidator
-
- struct DampingValidator {
- void operator()(float flDamping) const
- {
- eax_validate_range<Exception>(
- "Damping",
- flDamping,
- EAXECHO_MINDAMPING,
- EAXECHO_MAXDAMPING);
- }
- }; // DampingValidator
-
- struct FeedbackValidator {
- void operator()(float flFeedback) const
- {
- eax_validate_range<Exception>(
- "Feedback",
- flFeedback,
- EAXECHO_MINFEEDBACK,
- EAXECHO_MAXFEEDBACK);
- }
- }; // FeedbackValidator
-
- struct SpreadValidator {
- void operator()(float flSpread) const
- {
- eax_validate_range<Exception>(
- "Spread",
- flSpread,
- EAXECHO_MINSPREAD,
- EAXECHO_MAXSPREAD);
- }
- }; // SpreadValidator
-
- struct AllValidator {
- void operator()(const EAXECHOPROPERTIES& all) const
- {
- DelayValidator{}(all.flDelay);
- LrDelayValidator{}(all.flLRDelay);
- DampingValidator{}(all.flDamping);
- FeedbackValidator{}(all.flFeedback);
- SpreadValidator{}(all.flSpread);
- }
- }; // AllValidator
-
- void set_defaults(Props4& props) override;
-
- void set_efx_delay() noexcept;
- void set_efx_lr_delay() noexcept;
- void set_efx_damping() noexcept;
- void set_efx_feedback() noexcept;
- void set_efx_spread() noexcept;
- void set_efx_defaults() override;
-
- void get(const EaxCall& call, const Props4& props) override;
- void set(const EaxCall& call, Props4& props) override;
- bool commit_props(const Props4& props) override;
-}; // EaxEchoEffect
-
-EaxEchoEffect::EaxEchoEffect(int eax_version)
- : EaxEffect4{AL_EFFECT_ECHO, eax_version}
-{}
-
-void EaxEchoEffect::set_defaults(Props4& props)
-{
- props.mType = EaxEffectType::Echo;
- props.mEcho.flDelay = EAXECHO_DEFAULTDELAY;
- props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY;
- props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING;
- props.mEcho.flFeedback = EAXECHO_DEFAULTFEEDBACK;
- props.mEcho.flSpread = EAXECHO_DEFAULTSPREAD;
-}
-
-void EaxEchoEffect::set_efx_delay() noexcept
-{
- al_effect_props_.Echo.Delay = clamp(
- props_.mEcho.flDelay,
- AL_ECHO_MIN_DELAY,
- AL_ECHO_MAX_DELAY);
-}
+using EchoCommitter = EaxCommitter<EaxEchoCommitter>;
-void EaxEchoEffect::set_efx_lr_delay() noexcept
-{
- al_effect_props_.Echo.LRDelay = clamp(
- props_.mEcho.flLRDelay,
- AL_ECHO_MIN_LRDELAY,
- AL_ECHO_MAX_LRDELAY);
-}
-
-void EaxEchoEffect::set_efx_damping() noexcept
-{
- al_effect_props_.Echo.Damping = clamp(
- props_.mEcho.flDamping,
- AL_ECHO_MIN_DAMPING,
- AL_ECHO_MAX_DAMPING);
-}
+struct DelayValidator {
+ void operator()(float flDelay) const
+ {
+ eax_validate_range<EchoCommitter::Exception>(
+ "Delay",
+ flDelay,
+ EAXECHO_MINDELAY,
+ EAXECHO_MAXDELAY);
+ }
+}; // DelayValidator
-void EaxEchoEffect::set_efx_feedback() noexcept
-{
- al_effect_props_.Echo.Feedback = clamp(
- props_.mEcho.flFeedback,
- AL_ECHO_MIN_FEEDBACK,
- AL_ECHO_MAX_FEEDBACK);
-}
+struct LrDelayValidator {
+ void operator()(float flLRDelay) const
+ {
+ eax_validate_range<EchoCommitter::Exception>(
+ "LR Delay",
+ flLRDelay,
+ EAXECHO_MINLRDELAY,
+ EAXECHO_MAXLRDELAY);
+ }
+}; // LrDelayValidator
-void EaxEchoEffect::set_efx_spread() noexcept
-{
- al_effect_props_.Echo.Spread = clamp(
- props_.mEcho.flSpread,
- AL_ECHO_MIN_SPREAD,
- AL_ECHO_MAX_SPREAD);
-}
+struct DampingValidator {
+ void operator()(float flDamping) const
+ {
+ eax_validate_range<EchoCommitter::Exception>(
+ "Damping",
+ flDamping,
+ EAXECHO_MINDAMPING,
+ EAXECHO_MAXDAMPING);
+ }
+}; // DampingValidator
-void EaxEchoEffect::set_efx_defaults()
-{
- set_efx_delay();
- set_efx_lr_delay();
- set_efx_damping();
- set_efx_feedback();
- set_efx_spread();
-}
+struct FeedbackValidator {
+ void operator()(float flFeedback) const
+ {
+ eax_validate_range<EchoCommitter::Exception>(
+ "Feedback",
+ flFeedback,
+ EAXECHO_MINFEEDBACK,
+ EAXECHO_MAXFEEDBACK);
+ }
+}; // FeedbackValidator
-void EaxEchoEffect::get(const EaxCall& call, const Props4& props)
-{
- switch(call.get_property_id())
+struct SpreadValidator {
+ void operator()(float flSpread) const
{
- case EAXECHO_NONE: break;
- case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props.mEcho); break;
- case EAXECHO_DELAY: call.set_value<Exception>(props.mEcho.flDelay); break;
- case EAXECHO_LRDELAY: call.set_value<Exception>(props.mEcho.flLRDelay); break;
- case EAXECHO_DAMPING: call.set_value<Exception>(props.mEcho.flDamping); break;
- case EAXECHO_FEEDBACK: call.set_value<Exception>(props.mEcho.flFeedback); break;
- case EAXECHO_SPREAD: call.set_value<Exception>(props.mEcho.flSpread); break;
- default: fail_unknown_property_id();
+ eax_validate_range<EchoCommitter::Exception>(
+ "Spread",
+ flSpread,
+ EAXECHO_MINSPREAD,
+ EAXECHO_MAXSPREAD);
}
-}
+}; // SpreadValidator
-void EaxEchoEffect::set(const EaxCall& call, Props4& props)
-{
- switch(call.get_property_id())
+struct AllValidator {
+ void operator()(const EAXECHOPROPERTIES& all) const
{
- case EAXECHO_NONE: break;
- case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props.mEcho); break;
- case EAXECHO_DELAY: defer<DelayValidator>(call, props.mEcho.flDelay); break;
- case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.mEcho.flLRDelay); break;
- case EAXECHO_DAMPING: defer<DampingValidator>(call, props.mEcho.flDamping); break;
- case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.mEcho.flFeedback); break;
- case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.mEcho.flSpread); break;
- default: fail_unknown_property_id();
+ DelayValidator{}(all.flDelay);
+ LrDelayValidator{}(all.flLRDelay);
+ DampingValidator{}(all.flDamping);
+ FeedbackValidator{}(all.flFeedback);
+ SpreadValidator{}(all.flSpread);
}
+}; // AllValidator
+
+} // namespace
+
+template<>
+struct EchoCommitter::Exception : public EaxException {
+ explicit Exception(const char* message) : EaxException{"EAX_ECHO_EFFECT", message}
+ { }
+};
+
+template<>
+[[noreturn]] void EchoCommitter::fail(const char *message)
+{
+ throw Exception{message};
}
-bool EaxEchoEffect::commit_props(const Props4& props)
+template<>
+bool EchoCommitter::commit(const EaxEffectProps &props)
{
- auto is_dirty = false;
+ const auto orig = props_;
+ props_ = props;
- if (props_.mEcho.flDelay != props.mEcho.flDelay)
+ auto is_dirty = bool{orig.mType != props_.mType};
+ if(props_.mEcho.flDelay != props.mEcho.flDelay)
{
is_dirty = true;
- set_efx_delay();
+ al_effect_props_.Echo.Delay = clamp(
+ props_.mEcho.flDelay,
+ AL_ECHO_MIN_DELAY,
+ AL_ECHO_MAX_DELAY);
}
- if (props_.mEcho.flLRDelay != props.mEcho.flLRDelay)
+ if(props_.mEcho.flLRDelay != props.mEcho.flLRDelay)
{
is_dirty = true;
- set_efx_lr_delay();
+ al_effect_props_.Echo.LRDelay = clamp(
+ props_.mEcho.flLRDelay,
+ AL_ECHO_MIN_LRDELAY,
+ AL_ECHO_MAX_LRDELAY);
}
- if (props_.mEcho.flDamping != props.mEcho.flDamping)
+ if(props_.mEcho.flDamping != props.mEcho.flDamping)
{
is_dirty = true;
- set_efx_damping();
+ al_effect_props_.Echo.Damping = clamp(
+ props_.mEcho.flDamping,
+ AL_ECHO_MIN_DAMPING,
+ AL_ECHO_MAX_DAMPING);
}
- if (props_.mEcho.flFeedback != props.mEcho.flFeedback)
+ if(props_.mEcho.flFeedback != props.mEcho.flFeedback)
{
is_dirty = true;
- set_efx_feedback();
+ al_effect_props_.Echo.Feedback = clamp(
+ props_.mEcho.flFeedback,
+ AL_ECHO_MIN_FEEDBACK,
+ AL_ECHO_MAX_FEEDBACK);
}
- if (props_.mEcho.flSpread != props.mEcho.flSpread)
+ if(props_.mEcho.flSpread != props.mEcho.flSpread)
{
is_dirty = true;
- set_efx_spread();
+ al_effect_props_.Echo.Spread = clamp(
+ props_.mEcho.flSpread,
+ AL_ECHO_MIN_SPREAD,
+ AL_ECHO_MAX_SPREAD);
}
return is_dirty;
}
-} // namespace
+template<>
+void EchoCommitter::SetDefaults(EaxEffectProps &props)
+{
+ props.mType = EaxEffectType::Echo;
+ props.mEcho.flDelay = EAXECHO_DEFAULTDELAY;
+ props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY;
+ props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING;
+ props.mEcho.flFeedback = EAXECHO_DEFAULTFEEDBACK;
+ props.mEcho.flSpread = EAXECHO_DEFAULTSPREAD;
+}
-EaxEffectUPtr eax_create_eax_echo_effect(int eax_version)
+template<>
+void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
{
- return eax_create_eax4_effect<EaxEchoEffect>(eax_version);
+ switch(call.get_property_id())
+ {
+ case EAXECHO_NONE: break;
+ case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props.mEcho); break;
+ case EAXECHO_DELAY: call.set_value<Exception>(props.mEcho.flDelay); break;
+ case EAXECHO_LRDELAY: call.set_value<Exception>(props.mEcho.flLRDelay); break;
+ case EAXECHO_DAMPING: call.set_value<Exception>(props.mEcho.flDamping); break;
+ case EAXECHO_FEEDBACK: call.set_value<Exception>(props.mEcho.flFeedback); break;
+ case EAXECHO_SPREAD: call.set_value<Exception>(props.mEcho.flSpread); break;
+ default: fail_unknown_property_id();
+ }
+}
+
+template<>
+void EchoCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+{
+ switch(call.get_property_id())
+ {
+ case EAXECHO_NONE: break;
+ case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props.mEcho); break;
+ case EAXECHO_DELAY: defer<DelayValidator>(call, props.mEcho.flDelay); break;
+ case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.mEcho.flLRDelay); break;
+ case EAXECHO_DAMPING: defer<DampingValidator>(call, props.mEcho.flDamping); break;
+ case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.mEcho.flFeedback); break;
+ case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.mEcho.flSpread); break;
+ default: fail_unknown_property_id();
+ }
}
#endif // ALSOFT_EAX
diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp
index fa60d8a1..d9d52e1a 100644
--- a/al/effects/equalizer.cpp
+++ b/al/effects/equalizer.cpp
@@ -177,390 +177,295 @@ const EffectProps EqualizerEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-class EaxEqualizerEffectException : public EaxException
-{
-public:
- explicit EaxEqualizerEffectException(const char* message)
- : EaxException{"EAX_EQUALIZER_EFFECT", message}
- {}
-}; // EaxEqualizerEffectException
+using EqualizerCommitter = EaxCommitter<EaxEqualizerCommitter>;
-class EaxEqualizerEffect final : public EaxEffect4<EaxEqualizerEffectException>
-{
-public:
- EaxEqualizerEffect(int eax_version);
-
-private:
- struct LowGainValidator {
- void operator()(long lLowGain) const
- {
- eax_validate_range<Exception>(
- "Low Gain",
- lLowGain,
- EAXEQUALIZER_MINLOWGAIN,
- EAXEQUALIZER_MAXLOWGAIN);
- }
- }; // LowGainValidator
-
- struct LowCutOffValidator {
- void operator()(float flLowCutOff) const
- {
- eax_validate_range<Exception>(
- "Low Cutoff",
- flLowCutOff,
- EAXEQUALIZER_MINLOWCUTOFF,
- EAXEQUALIZER_MAXLOWCUTOFF);
- }
- }; // LowCutOffValidator
-
- struct Mid1GainValidator {
- void operator()(long lMid1Gain) const
- {
- eax_validate_range<Exception>(
- "Mid1 Gain",
- lMid1Gain,
- EAXEQUALIZER_MINMID1GAIN,
- EAXEQUALIZER_MAXMID1GAIN);
- }
- }; // Mid1GainValidator
-
- struct Mid1CenterValidator {
- void operator()(float flMid1Center) const
- {
- eax_validate_range<Exception>(
- "Mid1 Center",
- flMid1Center,
- EAXEQUALIZER_MINMID1CENTER,
- EAXEQUALIZER_MAXMID1CENTER);
- }
- }; // Mid1CenterValidator
-
- struct Mid1WidthValidator {
- void operator()(float flMid1Width) const
- {
- eax_validate_range<Exception>(
- "Mid1 Width",
- flMid1Width,
- EAXEQUALIZER_MINMID1WIDTH,
- EAXEQUALIZER_MAXMID1WIDTH);
- }
- }; // Mid1WidthValidator
-
- struct Mid2GainValidator {
- void operator()(long lMid2Gain) const
- {
- eax_validate_range<Exception>(
- "Mid2 Gain",
- lMid2Gain,
- EAXEQUALIZER_MINMID2GAIN,
- EAXEQUALIZER_MAXMID2GAIN);
- }
- }; // Mid2GainValidator
-
- struct Mid2CenterValidator {
- void operator()(float flMid2Center) const
- {
- eax_validate_range<Exception>(
- "Mid2 Center",
- flMid2Center,
- EAXEQUALIZER_MINMID2CENTER,
- EAXEQUALIZER_MAXMID2CENTER);
- }
- }; // Mid2CenterValidator
-
- struct Mid2WidthValidator {
- void operator()(float flMid2Width) const
- {
- eax_validate_range<Exception>(
- "Mid2 Width",
- flMid2Width,
- EAXEQUALIZER_MINMID2WIDTH,
- EAXEQUALIZER_MAXMID2WIDTH);
- }
- }; // Mid2WidthValidator
-
- struct HighGainValidator {
- void operator()(long lHighGain) const
- {
- eax_validate_range<Exception>(
- "High Gain",
- lHighGain,
- EAXEQUALIZER_MINHIGHGAIN,
- EAXEQUALIZER_MAXHIGHGAIN);
- }
- }; // HighGainValidator
-
- struct HighCutOffValidator {
- void operator()(float flHighCutOff) const
- {
- eax_validate_range<Exception>(
- "High Cutoff",
- flHighCutOff,
- EAXEQUALIZER_MINHIGHCUTOFF,
- EAXEQUALIZER_MAXHIGHCUTOFF);
- }
- }; // HighCutOffValidator
-
- struct AllValidator {
- void operator()(const EAXEQUALIZERPROPERTIES& all) const
- {
- LowGainValidator{}(all.lLowGain);
- LowCutOffValidator{}(all.flLowCutOff);
- Mid1GainValidator{}(all.lMid1Gain);
- Mid1CenterValidator{}(all.flMid1Center);
- Mid1WidthValidator{}(all.flMid1Width);
- Mid2GainValidator{}(all.lMid2Gain);
- Mid2CenterValidator{}(all.flMid2Center);
- Mid2WidthValidator{}(all.flMid2Width);
- HighGainValidator{}(all.lHighGain);
- HighCutOffValidator{}(all.flHighCutOff);
- }
- }; // AllValidator
-
- void set_defaults(Props4& props) override;
-
- void set_efx_low_gain() noexcept;
- void set_efx_low_cutoff() noexcept;
- void set_efx_mid1_gain() noexcept;
- void set_efx_mid1_center() noexcept;
- void set_efx_mid1_width() noexcept;
- void set_efx_mid2_gain() noexcept;
- void set_efx_mid2_center() noexcept;
- void set_efx_mid2_width() noexcept;
- void set_efx_high_gain() noexcept;
- void set_efx_high_cutoff() noexcept;
- void set_efx_defaults() override;
-
- void get(const EaxCall& call, const Props4& props) override;
- void set(const EaxCall& call, Props4& props) override;
- bool commit_props(const Props4& props) override;
-}; // EaxEqualizerEffect
-
-EaxEqualizerEffect::EaxEqualizerEffect(int eax_version)
- : EaxEffect4{AL_EFFECT_EQUALIZER, eax_version}
-{}
-
-void EaxEqualizerEffect::set_defaults(Props4& props)
-{
- props.mType = EaxEffectType::Equalizer;
- props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
- props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
- props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
- props.mEqualizer.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
- props.mEqualizer.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
- props.mEqualizer.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
- props.mEqualizer.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
- props.mEqualizer.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
- props.mEqualizer.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
- props.mEqualizer.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
-}
-
-void EaxEqualizerEffect::set_efx_low_gain() noexcept
-{
- al_effect_props_.Equalizer.LowGain = clamp(
- level_mb_to_gain(static_cast<float>(props_.mEqualizer.lLowGain)),
- AL_EQUALIZER_MIN_LOW_GAIN,
- AL_EQUALIZER_MAX_LOW_GAIN);
-}
-
-void EaxEqualizerEffect::set_efx_low_cutoff() noexcept
-{
- al_effect_props_.Equalizer.LowCutoff = clamp(
- props_.mEqualizer.flLowCutOff,
- AL_EQUALIZER_MIN_LOW_CUTOFF,
- AL_EQUALIZER_MAX_LOW_CUTOFF);
-}
-
-void EaxEqualizerEffect::set_efx_mid1_gain() noexcept
-{
- al_effect_props_.Equalizer.Mid1Gain = clamp(
- level_mb_to_gain(static_cast<float>(props_.mEqualizer.lMid1Gain)),
- AL_EQUALIZER_MIN_MID1_GAIN,
- AL_EQUALIZER_MAX_MID1_GAIN);
-}
+struct LowGainValidator {
+ void operator()(long lLowGain) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Low Gain",
+ lLowGain,
+ EAXEQUALIZER_MINLOWGAIN,
+ EAXEQUALIZER_MAXLOWGAIN);
+ }
+}; // LowGainValidator
-void EaxEqualizerEffect::set_efx_mid1_center() noexcept
-{
- al_effect_props_.Equalizer.Mid1Center = clamp(
- props_.mEqualizer.flMid1Center,
- AL_EQUALIZER_MIN_MID1_CENTER,
- AL_EQUALIZER_MAX_MID1_CENTER);
-}
+struct LowCutOffValidator {
+ void operator()(float flLowCutOff) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Low Cutoff",
+ flLowCutOff,
+ EAXEQUALIZER_MINLOWCUTOFF,
+ EAXEQUALIZER_MAXLOWCUTOFF);
+ }
+}; // LowCutOffValidator
-void EaxEqualizerEffect::set_efx_mid1_width() noexcept
-{
- al_effect_props_.Equalizer.Mid1Width = clamp(
- props_.mEqualizer.flMid1Width,
- AL_EQUALIZER_MIN_MID1_WIDTH,
- AL_EQUALIZER_MAX_MID1_WIDTH);
-}
+struct Mid1GainValidator {
+ void operator()(long lMid1Gain) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Mid1 Gain",
+ lMid1Gain,
+ EAXEQUALIZER_MINMID1GAIN,
+ EAXEQUALIZER_MAXMID1GAIN);
+ }
+}; // Mid1GainValidator
-void EaxEqualizerEffect::set_efx_mid2_gain() noexcept
-{
- al_effect_props_.Equalizer.Mid2Gain = clamp(
- level_mb_to_gain(static_cast<float>(props_.mEqualizer.lMid2Gain)),
- AL_EQUALIZER_MIN_MID2_GAIN,
- AL_EQUALIZER_MAX_MID2_GAIN);
-}
+struct Mid1CenterValidator {
+ void operator()(float flMid1Center) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Mid1 Center",
+ flMid1Center,
+ EAXEQUALIZER_MINMID1CENTER,
+ EAXEQUALIZER_MAXMID1CENTER);
+ }
+}; // Mid1CenterValidator
-void EaxEqualizerEffect::set_efx_mid2_center() noexcept
-{
- al_effect_props_.Equalizer.Mid2Center = clamp(
- props_.mEqualizer.flMid2Center,
- AL_EQUALIZER_MIN_MID2_CENTER,
- AL_EQUALIZER_MAX_MID2_CENTER);
-}
+struct Mid1WidthValidator {
+ void operator()(float flMid1Width) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Mid1 Width",
+ flMid1Width,
+ EAXEQUALIZER_MINMID1WIDTH,
+ EAXEQUALIZER_MAXMID1WIDTH);
+ }
+}; // Mid1WidthValidator
-void EaxEqualizerEffect::set_efx_mid2_width() noexcept
-{
- al_effect_props_.Equalizer.Mid2Width = clamp(
- props_.mEqualizer.flMid2Width,
- AL_EQUALIZER_MIN_MID2_WIDTH,
- AL_EQUALIZER_MAX_MID2_WIDTH);
-}
+struct Mid2GainValidator {
+ void operator()(long lMid2Gain) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Mid2 Gain",
+ lMid2Gain,
+ EAXEQUALIZER_MINMID2GAIN,
+ EAXEQUALIZER_MAXMID2GAIN);
+ }
+}; // Mid2GainValidator
-void EaxEqualizerEffect::set_efx_high_gain() noexcept
-{
- al_effect_props_.Equalizer.HighGain = clamp(
- level_mb_to_gain(static_cast<float>(props_.mEqualizer.lHighGain)),
- AL_EQUALIZER_MIN_HIGH_GAIN,
- AL_EQUALIZER_MAX_HIGH_GAIN);
-}
+struct Mid2CenterValidator {
+ void operator()(float flMid2Center) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Mid2 Center",
+ flMid2Center,
+ EAXEQUALIZER_MINMID2CENTER,
+ EAXEQUALIZER_MAXMID2CENTER);
+ }
+}; // Mid2CenterValidator
-void EaxEqualizerEffect::set_efx_high_cutoff() noexcept
-{
- al_effect_props_.Equalizer.HighCutoff = clamp(
- props_.mEqualizer.flHighCutOff,
- AL_EQUALIZER_MIN_HIGH_CUTOFF,
- AL_EQUALIZER_MAX_HIGH_CUTOFF);
-}
+struct Mid2WidthValidator {
+ void operator()(float flMid2Width) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "Mid2 Width",
+ flMid2Width,
+ EAXEQUALIZER_MINMID2WIDTH,
+ EAXEQUALIZER_MAXMID2WIDTH);
+ }
+}; // Mid2WidthValidator
-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();
-}
+struct HighGainValidator {
+ void operator()(long lHighGain) const
+ {
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "High Gain",
+ lHighGain,
+ EAXEQUALIZER_MINHIGHGAIN,
+ EAXEQUALIZER_MAXHIGHGAIN);
+ }
+}; // HighGainValidator
-void EaxEqualizerEffect::get(const EaxCall& call, const Props4& props)
-{
- switch(call.get_property_id())
+struct HighCutOffValidator {
+ void operator()(float flHighCutOff) const
{
- case EAXEQUALIZER_NONE: break;
- case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props.mEqualizer); break;
- case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.mEqualizer.lLowGain); break;
- case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.mEqualizer.flLowCutOff); break;
- case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.mEqualizer.lMid1Gain); break;
- case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.mEqualizer.flMid1Center); break;
- case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.mEqualizer.flMid1Width); break;
- case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.mEqualizer.lMid2Gain); break;
- case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.mEqualizer.flMid2Center); break;
- case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.mEqualizer.flMid2Width); break;
- case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.mEqualizer.lHighGain); break;
- case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.mEqualizer.flHighCutOff); break;
- default: fail_unknown_property_id();
+ eax_validate_range<EqualizerCommitter::Exception>(
+ "High Cutoff",
+ flHighCutOff,
+ EAXEQUALIZER_MINHIGHCUTOFF,
+ EAXEQUALIZER_MAXHIGHCUTOFF);
}
-}
+}; // HighCutOffValidator
-void EaxEqualizerEffect::set(const EaxCall& call, Props4& props)
-{
- switch(call.get_property_id())
+struct AllValidator {
+ void operator()(const EAXEQUALIZERPROPERTIES& all) const
{
- case EAXEQUALIZER_NONE: break;
- case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props.mEqualizer); break;
- case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.mEqualizer.lLowGain); break;
- case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.mEqualizer.flLowCutOff); break;
- case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.mEqualizer.lMid1Gain); break;
- case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.mEqualizer.flMid1Center); break;
- case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.mEqualizer.flMid1Width); break;
- case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.mEqualizer.lMid2Gain); break;
- case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.mEqualizer.flMid2Center); break;
- case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.mEqualizer.flMid2Width); break;
- case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.mEqualizer.lHighGain); break;
- case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.mEqualizer.flHighCutOff); break;
- default: fail_unknown_property_id();
+ LowGainValidator{}(all.lLowGain);
+ LowCutOffValidator{}(all.flLowCutOff);
+ Mid1GainValidator{}(all.lMid1Gain);
+ Mid1CenterValidator{}(all.flMid1Center);
+ Mid1WidthValidator{}(all.flMid1Width);
+ Mid2GainValidator{}(all.lMid2Gain);
+ Mid2CenterValidator{}(all.flMid2Center);
+ Mid2WidthValidator{}(all.flMid2Width);
+ HighGainValidator{}(all.lHighGain);
+ HighCutOffValidator{}(all.flHighCutOff);
}
+}; // AllValidator
+
+} // namespace
+
+template<>
+struct EqualizerCommitter::Exception : public EaxException {
+ explicit Exception(const char* message) : EaxException{"EAX_EQUALIZER_EFFECT", message}
+ { }
+};
+
+template<>
+[[noreturn]] void EqualizerCommitter::fail(const char *message)
+{
+ throw Exception{message};
}
-bool EaxEqualizerEffect::commit_props(const Props4& props)
+template<>
+bool EqualizerCommitter::commit(const EaxEffectProps &props)
{
- auto is_dirty = false;
+ const auto orig = props_;
+ props_ = props;
- if (props_.mEqualizer.lLowGain != props.mEqualizer.lLowGain)
+ auto is_dirty = bool{orig.mType != props_.mType};
+ if(props_.mEqualizer.lLowGain != props.mEqualizer.lLowGain)
{
is_dirty = true;
- set_efx_low_gain();
+ al_effect_props_.Equalizer.LowGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.mEqualizer.lLowGain)),
+ AL_EQUALIZER_MIN_LOW_GAIN,
+ AL_EQUALIZER_MAX_LOW_GAIN);
}
-
- if (props_.mEqualizer.flLowCutOff != props.mEqualizer.flLowCutOff)
+ if(props_.mEqualizer.flLowCutOff != props.mEqualizer.flLowCutOff)
{
is_dirty = true;
- set_efx_low_cutoff();
+ al_effect_props_.Equalizer.LowCutoff = clamp(
+ props_.mEqualizer.flLowCutOff,
+ AL_EQUALIZER_MIN_LOW_CUTOFF,
+ AL_EQUALIZER_MAX_LOW_CUTOFF);
}
-
- if (props_.mEqualizer.lMid1Gain != props.mEqualizer.lMid1Gain)
+ if(props_.mEqualizer.lMid1Gain != props.mEqualizer.lMid1Gain)
{
is_dirty = true;
- set_efx_mid1_gain();
+ al_effect_props_.Equalizer.Mid1Gain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.mEqualizer.lMid1Gain)),
+ AL_EQUALIZER_MIN_MID1_GAIN,
+ AL_EQUALIZER_MAX_MID1_GAIN);
}
-
- if (props_.mEqualizer.flMid1Center != props.mEqualizer.flMid1Center)
+ if(props_.mEqualizer.flMid1Center != props.mEqualizer.flMid1Center)
{
is_dirty = true;
- set_efx_mid1_center();
+ al_effect_props_.Equalizer.Mid1Center = clamp(
+ props_.mEqualizer.flMid1Center,
+ AL_EQUALIZER_MIN_MID1_CENTER,
+ AL_EQUALIZER_MAX_MID1_CENTER);
}
-
- if (props_.mEqualizer.flMid1Width != props.mEqualizer.flMid1Width)
+ if(props_.mEqualizer.flMid1Width != props.mEqualizer.flMid1Width)
{
is_dirty = true;
- set_efx_mid1_width();
+ al_effect_props_.Equalizer.Mid1Width = clamp(
+ props_.mEqualizer.flMid1Width,
+ AL_EQUALIZER_MIN_MID1_WIDTH,
+ AL_EQUALIZER_MAX_MID1_WIDTH);
}
-
- if (props_.mEqualizer.lMid2Gain != props.mEqualizer.lMid2Gain)
+ if(props_.mEqualizer.lMid2Gain != props.mEqualizer.lMid2Gain)
{
is_dirty = true;
- set_efx_mid2_gain();
+ al_effect_props_.Equalizer.Mid2Gain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.mEqualizer.lMid2Gain)),
+ AL_EQUALIZER_MIN_MID2_GAIN,
+ AL_EQUALIZER_MAX_MID2_GAIN);
}
-
- if (props_.mEqualizer.flMid2Center != props.mEqualizer.flMid2Center)
+ if(props_.mEqualizer.flMid2Center != props.mEqualizer.flMid2Center)
{
is_dirty = true;
- set_efx_mid2_center();
+ al_effect_props_.Equalizer.Mid2Center = clamp(
+ props_.mEqualizer.flMid2Center,
+ AL_EQUALIZER_MIN_MID2_CENTER,
+ AL_EQUALIZER_MAX_MID2_CENTER);
}
-
- if (props_.mEqualizer.flMid2Width != props.mEqualizer.flMid2Width)
+ if(props_.mEqualizer.flMid2Width != props.mEqualizer.flMid2Width)
{
is_dirty = true;
- set_efx_mid2_width();
+ al_effect_props_.Equalizer.Mid2Width = clamp(
+ props_.mEqualizer.flMid2Width,
+ AL_EQUALIZER_MIN_MID2_WIDTH,
+ AL_EQUALIZER_MAX_MID2_WIDTH);
}
-
- if (props_.mEqualizer.lHighGain != props.mEqualizer.lHighGain)
+ if(props_.mEqualizer.lHighGain != props.mEqualizer.lHighGain)
{
is_dirty = true;
- set_efx_high_gain();
+ al_effect_props_.Equalizer.HighGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.mEqualizer.lHighGain)),
+ AL_EQUALIZER_MIN_HIGH_GAIN,
+ AL_EQUALIZER_MAX_HIGH_GAIN);
}
-
- if (props_.mEqualizer.flHighCutOff != props.mEqualizer.flHighCutOff)
+ if(props_.mEqualizer.flHighCutOff != props.mEqualizer.flHighCutOff)
{
is_dirty = true;
- set_efx_high_cutoff();
+ al_effect_props_.Equalizer.HighCutoff = clamp(
+ props_.mEqualizer.flHighCutOff,
+ AL_EQUALIZER_MIN_HIGH_CUTOFF,
+ AL_EQUALIZER_MAX_HIGH_CUTOFF);
}
return is_dirty;
}
-} // namespace
+template<>
+void EqualizerCommitter::SetDefaults(EaxEffectProps &props)
+{
+ props.mType = EaxEffectType::Equalizer;
+ props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
+ props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
+ props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
+ props.mEqualizer.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
+ props.mEqualizer.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
+ props.mEqualizer.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
+ props.mEqualizer.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
+ props.mEqualizer.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
+ props.mEqualizer.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
+ props.mEqualizer.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
+}
+
+template<>
+void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+{
+ switch(call.get_property_id())
+ {
+ case EAXEQUALIZER_NONE: break;
+ case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props.mEqualizer); break;
+ case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.mEqualizer.lLowGain); break;
+ case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.mEqualizer.flLowCutOff); break;
+ case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.mEqualizer.lMid1Gain); break;
+ case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.mEqualizer.flMid1Center); break;
+ case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.mEqualizer.flMid1Width); break;
+ case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.mEqualizer.lMid2Gain); break;
+ case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.mEqualizer.flMid2Center); break;
+ case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.mEqualizer.flMid2Width); break;
+ case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.mEqualizer.lHighGain); break;
+ case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.mEqualizer.flHighCutOff); break;
+ default: fail_unknown_property_id();
+ }
+}
-EaxEffectUPtr eax_create_eax_equalizer_effect(int eax_version)
+template<>
+void EqualizerCommitter::Set(const EaxCall &call, EaxEffectProps &props)
{
- return eax_create_eax4_effect<EaxEqualizerEffect>(eax_version);
+ switch(call.get_property_id())
+ {
+ case EAXEQUALIZER_NONE: break;
+ case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props.mEqualizer); break;
+ case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.mEqualizer.lLowGain); break;
+ case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.mEqualizer.flLowCutOff); break;
+ case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.mEqualizer.lMid1Gain); break;
+ case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.mEqualizer.flMid1Center); break;
+ case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.mEqualizer.flMid1Width); break;
+ case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.mEqualizer.lMid2Gain); break;
+ case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.mEqualizer.flMid2Center); break;
+ case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.mEqualizer.flMid2Width); break;
+ case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.mEqualizer.lHighGain); break;
+ case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.mEqualizer.flHighCutOff); break;
+ default: fail_unknown_property_id();
+ }
}
#endif // ALSOFT_EAX