diff options
author | Chris Robinson <[email protected]> | 2023-03-11 00:47:22 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-03-11 00:47:22 -0800 |
commit | 64ead7d36de7dc748414530121b69876a0c84e05 (patch) | |
tree | 91fcacc64d03b0db131b961a8d4d2d457f36343b /al/effects | |
parent | 1d112eee0fb5bfe358dc9a7627a64679292a3df5 (diff) |
Convert the EAX Echo and Equalizer effects
Diffstat (limited to 'al/effects')
-rw-r--r-- | al/effects/echo.cpp | 329 | ||||
-rw-r--r-- | al/effects/equalizer.cpp | 563 |
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 |