diff options
author | Boris I. Bendovsky <[email protected]> | 2022-05-24 12:19:14 +0300 |
---|---|---|
committer | GitHub <[email protected]> | 2022-05-24 02:19:14 -0700 |
commit | 074dbef2e3129e9f7ee4895c44721c2a0a4b045b (patch) | |
tree | 72087ad2df3a5293d6aec82e762797b69de64111 /al/effects/distortion.cpp | |
parent | 54d72d17ad64809aeaf7a840447e398b2d38cbc9 (diff) |
[EAX] Add separate effect state for each version (#705)
* [EAX] Add separate effect state for each version
* [EAX] Don't use EAX call as data member
Diffstat (limited to 'al/effects/distortion.cpp')
-rw-r--r-- | al/effects/distortion.cpp | 510 |
1 files changed, 147 insertions, 363 deletions
diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 441b89a0..b58412b9 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -9,7 +9,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -123,156 +122,151 @@ const EffectProps DistortionEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxDistortionEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxDistortionEffectDirtyFlags +class EaxDistortionEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxDistortionEffectDirtyFlagsValue flEdge : 1; - EaxDistortionEffectDirtyFlagsValue lGain : 1; - EaxDistortionEffectDirtyFlagsValue flLowPassCutOff : 1; - EaxDistortionEffectDirtyFlagsValue flEQCenter : 1; - EaxDistortionEffectDirtyFlagsValue flEQBandwidth : 1; -}; // EaxDistortionEffectDirtyFlags - +public: + explicit EaxDistortionEffectException(const char* message) + : EaxException{"EAX_DISTORTION_EFFECT", message} + {} +}; // EaxDistortionEffectException -class EaxDistortionEffect final : - public EaxEffect +class EaxDistortionEffect final : public EaxEffect4<EaxDistortionEffectException, EAXDISTORTIONPROPERTIES> { public: - EaxDistortionEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; + EaxDistortionEffect(const EaxCall& call); private: - EAXDISTORTIONPROPERTIES eax_{}; - EAXDISTORTIONPROPERTIES eax_d_{}; - EaxDistortionEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_edge(); - void set_efx_gain(); - void set_efx_lowpass_cutoff(); - void set_efx_eq_center(); - void set_efx_eq_bandwidth(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_edge(float flEdge); - void validate_gain(long lGain); - void validate_lowpass_cutoff(float flLowPassCutOff); - void validate_eq_center(float flEQCenter); - void validate_eq_bandwidth(float flEQBandwidth); - void validate_all(const EAXDISTORTIONPROPERTIES& eax_all); - - void defer_edge(float flEdge); - void defer_gain(long lGain); - void defer_low_pass_cutoff(float flLowPassCutOff); - void defer_eq_center(float flEQCenter); - void defer_eq_bandwidth(float flEQBandwidth); - void defer_all(const EAXDISTORTIONPROPERTIES& eax_all); - - void defer_edge(const EaxEaxCall& eax_call); - void defer_gain(const EaxEaxCall& eax_call); - void defer_low_pass_cutoff(const EaxEaxCall& eax_call); - void defer_eq_center(const EaxEaxCall& eax_call); - void defer_eq_bandwidth(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + struct EdgeValidator { + void operator()(float flEdge) const + { + eax_validate_range<Exception>( + "Edge", + flEdge, + EAXDISTORTION_MINEDGE, + EAXDISTORTION_MAXEDGE); + } + }; // EdgeValidator + + struct GainValidator { + void operator()(long lGain) const + { + eax_validate_range<Exception>( + "Gain", + lGain, + EAXDISTORTION_MINGAIN, + EAXDISTORTION_MAXGAIN); + } + }; // GainValidator + + struct LowPassCutOffValidator { + void operator()(float flLowPassCutOff) const + { + eax_validate_range<Exception>( + "Low-pass Cut-off", + flLowPassCutOff, + EAXDISTORTION_MINLOWPASSCUTOFF, + EAXDISTORTION_MAXLOWPASSCUTOFF); + } + }; // LowPassCutOffValidator + + struct EqCenterValidator { + void operator()(float flEQCenter) const + { + eax_validate_range<Exception>( + "EQ Center", + flEQCenter, + EAXDISTORTION_MINEQCENTER, + EAXDISTORTION_MAXEQCENTER); + } + }; // EqCenterValidator + + struct EqBandwidthValidator { + void operator()(float flEQBandwidth) const + { + eax_validate_range<Exception>( + "EQ Bandwidth", + flEQBandwidth, + EAXDISTORTION_MINEQBANDWIDTH, + EAXDISTORTION_MAXEQBANDWIDTH); + } + }; // EqBandwidthValidator + + struct AllValidator { + void operator()(const Props& all) const + { + EdgeValidator{}(all.flEdge); + GainValidator{}(all.lGain); + LowPassCutOffValidator{}(all.flLowPassCutOff); + EqCenterValidator{}(all.flEQCenter); + EqBandwidthValidator{}(all.flEQBandwidth); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_edge() noexcept; + void set_efx_gain() noexcept; + void set_efx_lowpass_cutoff() noexcept; + void set_efx_eq_center() noexcept; + void set_efx_eq_bandwidth() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxDistortionEffect +EaxDistortionEffect::EaxDistortionEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_DISTORTION, call} +{} -class EaxDistortionEffectException : - public EaxException -{ -public: - explicit EaxDistortionEffectException( - const char* message) - : - EaxException{"EAX_DISTORTION_EFFECT", message} - { - } -}; // EaxDistortionEffectException - - -EaxDistortionEffect::EaxDistortionEffect() - : EaxEffect{AL_EFFECT_DISTORTION} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxDistortionEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxDistortionEffect::set_eax_defaults() +void EaxDistortionEffect::set_defaults(Props& props) { - eax_.flEdge = EAXDISTORTION_DEFAULTEDGE; - eax_.lGain = EAXDISTORTION_DEFAULTGAIN; - eax_.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; - eax_.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; - eax_.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; - - eax_d_ = eax_; + props.flEdge = EAXDISTORTION_DEFAULTEDGE; + props.lGain = EAXDISTORTION_DEFAULTGAIN; + props.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; + props.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; + props.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; } -void EaxDistortionEffect::set_efx_edge() +void EaxDistortionEffect::set_efx_edge() noexcept { - const auto edge = clamp( - eax_.flEdge, + al_effect_props_.Distortion.Edge = clamp( + props_.flEdge, AL_DISTORTION_MIN_EDGE, AL_DISTORTION_MAX_EDGE); - - al_effect_props_.Distortion.Edge = edge; } -void EaxDistortionEffect::set_efx_gain() +void EaxDistortionEffect::set_efx_gain() noexcept { - const auto gain = clamp( - level_mb_to_gain(static_cast<float>(eax_.lGain)), + al_effect_props_.Distortion.Gain = clamp( + level_mb_to_gain(static_cast<float>(props_.lGain)), AL_DISTORTION_MIN_GAIN, AL_DISTORTION_MAX_GAIN); - - al_effect_props_.Distortion.Gain = gain; } -void EaxDistortionEffect::set_efx_lowpass_cutoff() +void EaxDistortionEffect::set_efx_lowpass_cutoff() noexcept { - const auto lowpass_cutoff = clamp( - eax_.flLowPassCutOff, + al_effect_props_.Distortion.LowpassCutoff = clamp( + props_.flLowPassCutOff, AL_DISTORTION_MIN_LOWPASS_CUTOFF, AL_DISTORTION_MAX_LOWPASS_CUTOFF); - - al_effect_props_.Distortion.LowpassCutoff = lowpass_cutoff; } -void EaxDistortionEffect::set_efx_eq_center() +void EaxDistortionEffect::set_efx_eq_center() noexcept { - const auto eq_center = clamp( - eax_.flEQCenter, + al_effect_props_.Distortion.EQCenter = clamp( + props_.flEQCenter, AL_DISTORTION_MIN_EQCENTER, AL_DISTORTION_MAX_EQCENTER); - - al_effect_props_.Distortion.EQCenter = eq_center; } -void EaxDistortionEffect::set_efx_eq_bandwidth() +void EaxDistortionEffect::set_efx_eq_bandwidth() noexcept { - const auto eq_bandwidth = clamp( - eax_.flEdge, + al_effect_props_.Distortion.EQBandwidth = clamp( + props_.flEdge, AL_DISTORTION_MIN_EQBANDWIDTH, AL_DISTORTION_MAX_EQBANDWIDTH); - - al_effect_props_.Distortion.EQBandwidth = eq_bandwidth; } void EaxDistortionEffect::set_efx_defaults() @@ -284,288 +278,78 @@ void EaxDistortionEffect::set_efx_defaults() set_efx_eq_bandwidth(); } -void EaxDistortionEffect::get(const EaxEaxCall& eax_call) +void EaxDistortionEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXDISTORTION_NONE: - break; - - case EAXDISTORTION_ALLPARAMETERS: - eax_call.set_value<EaxDistortionEffectException>(eax_); - break; - - case EAXDISTORTION_EDGE: - eax_call.set_value<EaxDistortionEffectException>(eax_.flEdge); - break; - - case EAXDISTORTION_GAIN: - eax_call.set_value<EaxDistortionEffectException>(eax_.lGain); - break; - - case EAXDISTORTION_LOWPASSCUTOFF: - eax_call.set_value<EaxDistortionEffectException>(eax_.flLowPassCutOff); - break; - - case EAXDISTORTION_EQCENTER: - eax_call.set_value<EaxDistortionEffectException>(eax_.flEQCenter); - break; - - case EAXDISTORTION_EQBANDWIDTH: - eax_call.set_value<EaxDistortionEffectException>(eax_.flEQBandwidth); - break; - - default: - throw EaxDistortionEffectException{"Unsupported property id."}; + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props); break; + case EAXDISTORTION_EDGE: call.set_value<Exception>(props.flEdge); break; + case EAXDISTORTION_GAIN: call.set_value<Exception>(props.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.flEQBandwidth); break; + default: fail_unknown_property_id(); } } -void EaxDistortionEffect::validate_edge( - float flEdge) -{ - eax_validate_range<EaxDistortionEffectException>( - "Edge", - flEdge, - EAXDISTORTION_MINEDGE, - EAXDISTORTION_MAXEDGE); -} - -void EaxDistortionEffect::validate_gain( - long lGain) -{ - eax_validate_range<EaxDistortionEffectException>( - "Gain", - lGain, - EAXDISTORTION_MINGAIN, - EAXDISTORTION_MAXGAIN); -} - -void EaxDistortionEffect::validate_lowpass_cutoff( - float flLowPassCutOff) -{ - eax_validate_range<EaxDistortionEffectException>( - "Low-pass Cut-off", - flLowPassCutOff, - EAXDISTORTION_MINLOWPASSCUTOFF, - EAXDISTORTION_MAXLOWPASSCUTOFF); -} - -void EaxDistortionEffect::validate_eq_center( - float flEQCenter) -{ - eax_validate_range<EaxDistortionEffectException>( - "EQ Center", - flEQCenter, - EAXDISTORTION_MINEQCENTER, - EAXDISTORTION_MAXEQCENTER); -} - -void EaxDistortionEffect::validate_eq_bandwidth( - float flEQBandwidth) -{ - eax_validate_range<EaxDistortionEffectException>( - "EQ Bandwidth", - flEQBandwidth, - EAXDISTORTION_MINEQBANDWIDTH, - EAXDISTORTION_MAXEQBANDWIDTH); -} - -void EaxDistortionEffect::validate_all( - const EAXDISTORTIONPROPERTIES& eax_all) -{ - validate_edge(eax_all.flEdge); - validate_gain(eax_all.lGain); - validate_lowpass_cutoff(eax_all.flLowPassCutOff); - validate_eq_center(eax_all.flEQCenter); - validate_eq_bandwidth(eax_all.flEQBandwidth); -} - -void EaxDistortionEffect::defer_edge( - float flEdge) -{ - eax_d_.flEdge = flEdge; - eax_dirty_flags_.flEdge = (eax_.flEdge != eax_d_.flEdge); -} - -void EaxDistortionEffect::defer_gain( - long lGain) +void EaxDistortionEffect::set(const EaxCall& call, Props& props) { - eax_d_.lGain = lGain; - eax_dirty_flags_.lGain = (eax_.lGain != eax_d_.lGain); -} - -void EaxDistortionEffect::defer_low_pass_cutoff( - float flLowPassCutOff) -{ - eax_d_.flLowPassCutOff = flLowPassCutOff; - eax_dirty_flags_.flLowPassCutOff = (eax_.flLowPassCutOff != eax_d_.flLowPassCutOff); -} - -void EaxDistortionEffect::defer_eq_center( - float flEQCenter) -{ - eax_d_.flEQCenter = flEQCenter; - eax_dirty_flags_.flEQCenter = (eax_.flEQCenter != eax_d_.flEQCenter); -} - -void EaxDistortionEffect::defer_eq_bandwidth( - float flEQBandwidth) -{ - eax_d_.flEQBandwidth = flEQBandwidth; - eax_dirty_flags_.flEQBandwidth = (eax_.flEQBandwidth != eax_d_.flEQBandwidth); -} - -void EaxDistortionEffect::defer_all( - const EAXDISTORTIONPROPERTIES& eax_all) -{ - defer_edge(eax_all.flEdge); - defer_gain(eax_all.lGain); - defer_low_pass_cutoff(eax_all.flLowPassCutOff); - defer_eq_center(eax_all.flEQCenter); - defer_eq_bandwidth(eax_all.flEQBandwidth); -} - -void EaxDistortionEffect::defer_edge( - const EaxEaxCall& eax_call) -{ - const auto& edge = - eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flEdge)>(); - - validate_edge(edge); - defer_edge(edge); -} - -void EaxDistortionEffect::defer_gain( - const EaxEaxCall& eax_call) -{ - const auto& gain = - eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::lGain)>(); - - validate_gain(gain); - defer_gain(gain); -} - -void EaxDistortionEffect::defer_low_pass_cutoff( - const EaxEaxCall& eax_call) -{ - const auto& lowpass_cutoff = - eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flLowPassCutOff)>(); - - validate_lowpass_cutoff(lowpass_cutoff); - defer_low_pass_cutoff(lowpass_cutoff); -} - -void EaxDistortionEffect::defer_eq_center( - const EaxEaxCall& eax_call) -{ - const auto& eq_center = - eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flEQCenter)>(); - - validate_eq_center(eq_center); - defer_eq_center(eq_center); -} - -void EaxDistortionEffect::defer_eq_bandwidth( - const EaxEaxCall& eax_call) -{ - const auto& eq_bandwidth = - eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flEQBandwidth)>(); - - validate_eq_bandwidth(eq_bandwidth); - defer_eq_bandwidth(eq_bandwidth); -} - -void EaxDistortionEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value<EaxDistortionEffectException, const EAXDISTORTIONPROPERTIES>(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxDistortionEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxDistortionEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props); break; + case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.flEdge); break; + case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.flEQBandwidth); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxDistortionEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flEdge) + if (props_.flEdge != props.flEdge) { + is_dirty = true; set_efx_edge(); } - if (eax_dirty_flags_.lGain) + if (props_.lGain != props.lGain) { + is_dirty = true; set_efx_gain(); } - if (eax_dirty_flags_.flLowPassCutOff) + if (props_.flLowPassCutOff != props.flLowPassCutOff) { + is_dirty = true; set_efx_lowpass_cutoff(); } - if (eax_dirty_flags_.flEQCenter) + if (props_.flEQCenter != props.flEQCenter) { + is_dirty = true; set_efx_eq_center(); } - if (eax_dirty_flags_.flEQBandwidth) + if (props_.flEQBandwidth != props.flEQBandwidth) { + is_dirty = true; set_efx_eq_bandwidth(); } - eax_dirty_flags_ = EaxDistortionEffectDirtyFlags{}; - - return true; -} - -void EaxDistortionEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXDISTORTION_NONE: - break; - - case EAXDISTORTION_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXDISTORTION_EDGE: - defer_edge(eax_call); - break; - - case EAXDISTORTION_GAIN: - defer_gain(eax_call); - break; - - case EAXDISTORTION_LOWPASSCUTOFF: - defer_low_pass_cutoff(eax_call); - break; - - case EAXDISTORTION_EQCENTER: - defer_eq_center(eax_call); - break; - - case EAXDISTORTION_EQBANDWIDTH: - defer_eq_bandwidth(eax_call); - break; - - default: - throw EaxDistortionEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_distortion_effect() +EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call) { - return std::make_unique<EaxDistortionEffect>(); + return eax_create_eax4_effect<EaxDistortionEffect>(call); } #endif // ALSOFT_EAX |