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/modulator.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/modulator.cpp')
-rw-r--r-- | al/effects/modulator.cpp | 365 |
1 files changed, 101 insertions, 264 deletions
diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 082597cd..774fb767 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -12,9 +12,7 @@ #ifdef ALSOFT_EAX #include <cassert> - #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -147,123 +145,107 @@ const EffectProps ModulatorEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxRingModulatorEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxRingModulatorEffectDirtyFlags +class EaxRingModulatorEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxRingModulatorEffectDirtyFlagsValue flFrequency : 1; - EaxRingModulatorEffectDirtyFlagsValue flHighPassCutOff : 1; - EaxRingModulatorEffectDirtyFlagsValue ulWaveform : 1; -}; // EaxPitchShifterEffectDirtyFlags - +public: + explicit EaxRingModulatorEffectException(const char* message) + : EaxException{"EAX_RING_MODULATOR_EFFECT", message} + {} +}; // EaxRingModulatorEffectException -class EaxRingModulatorEffect final : - public EaxEffect +class EaxRingModulatorEffect final : public EaxEffect4<EaxRingModulatorEffectException, EAXRINGMODULATORPROPERTIES> { public: - EaxRingModulatorEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; + EaxRingModulatorEffect(const EaxCall& call); private: - EAXRINGMODULATORPROPERTIES eax_{}; - EAXRINGMODULATORPROPERTIES eax_d_{}; - EaxRingModulatorEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_frequency(); - void set_efx_high_pass_cutoff(); + struct FrequencyValidator { + void operator()(float flFrequency) const + { + eax_validate_range<EaxRingModulatorEffectException>( + "Frequency", + flFrequency, + EAXRINGMODULATOR_MINFREQUENCY, + EAXRINGMODULATOR_MAXFREQUENCY); + } + }; // FrequencyValidator + + struct HighPassCutOffValidator { + void operator()(float flHighPassCutOff) const + { + eax_validate_range<EaxRingModulatorEffectException>( + "High-Pass Cutoff", + flHighPassCutOff, + EAXRINGMODULATOR_MINHIGHPASSCUTOFF, + EAXRINGMODULATOR_MAXHIGHPASSCUTOFF); + } + }; // HighPassCutOffValidator + + struct WaveformValidator { + void operator()(unsigned long ulWaveform) const + { + eax_validate_range<EaxRingModulatorEffectException>( + "Waveform", + ulWaveform, + EAXRINGMODULATOR_MINWAVEFORM, + EAXRINGMODULATOR_MAXWAVEFORM); + } + }; // WaveformValidator + + struct AllValidator { + void operator()(const Props& all) const + { + FrequencyValidator{}(all.flFrequency); + HighPassCutOffValidator{}(all.flHighPassCutOff); + WaveformValidator{}(all.ulWaveform); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_frequency() noexcept; + void set_efx_high_pass_cutoff() noexcept; void set_efx_waveform(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); + void set_efx_defaults() override; - void validate_frequency(float flFrequency); - void validate_high_pass_cutoff(float flHighPassCutOff); - void validate_waveform(unsigned long ulWaveform); - void validate_all(const EAXRINGMODULATORPROPERTIES& all); - - void defer_frequency(float flFrequency); - void defer_high_pass_cutoff(float flHighPassCutOff); - void defer_waveform(unsigned long ulWaveform); - void defer_all(const EAXRINGMODULATORPROPERTIES& all); - - void defer_frequency(const EaxEaxCall& eax_call); - void defer_high_pass_cutoff(const EaxEaxCall& eax_call); - void defer_waveform(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxRingModulatorEffect +EaxRingModulatorEffect::EaxRingModulatorEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_RING_MODULATOR, call} +{} -class EaxRingModulatorEffectException : - public EaxException +void EaxRingModulatorEffect::set_defaults(Props& props) { -public: - explicit EaxRingModulatorEffectException( - const char* message) - : - EaxException{"EAX_RING_MODULATOR_EFFECT", message} - { - } -}; // EaxRingModulatorEffectException - - -EaxRingModulatorEffect::EaxRingModulatorEffect() - : EaxEffect{AL_EFFECT_RING_MODULATOR} -{ - set_eax_defaults(); - set_efx_defaults(); + props.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; + props.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; + props.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; } -void EaxRingModulatorEffect::dispatch(const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::set_efx_frequency() noexcept { - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxRingModulatorEffect::set_eax_defaults() -{ - eax_.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; - eax_.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; - eax_.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; - - eax_d_ = eax_; -} - -void EaxRingModulatorEffect::set_efx_frequency() -{ - const auto frequency = clamp( - eax_.flFrequency, + al_effect_props_.Modulator.Frequency = clamp( + props_.flFrequency, AL_RING_MODULATOR_MIN_FREQUENCY, AL_RING_MODULATOR_MAX_FREQUENCY); - - al_effect_props_.Modulator.Frequency = frequency; } -void EaxRingModulatorEffect::set_efx_high_pass_cutoff() +void EaxRingModulatorEffect::set_efx_high_pass_cutoff() noexcept { - const auto high_pass_cutoff = clamp( - eax_.flHighPassCutOff, + al_effect_props_.Modulator.HighPassCutoff = clamp( + props_.flHighPassCutOff, AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF, AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF); - - al_effect_props_.Modulator.HighPassCutoff = high_pass_cutoff; } void EaxRingModulatorEffect::set_efx_waveform() { const auto waveform = clamp( - static_cast<ALint>(eax_.ulWaveform), + static_cast<ALint>(props_.ulWaveform), AL_RING_MODULATOR_MIN_WAVEFORM, AL_RING_MODULATOR_MAX_WAVEFORM); - const auto efx_waveform = WaveformFromEmum(waveform); assert(efx_waveform.has_value()); al_effect_props_.Modulator.Waveform = *efx_waveform; @@ -276,207 +258,62 @@ void EaxRingModulatorEffect::set_efx_defaults() set_efx_waveform(); } -void EaxRingModulatorEffect::get(const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXRINGMODULATOR_NONE: - break; - - case EAXRINGMODULATOR_ALLPARAMETERS: - eax_call.set_value<EaxRingModulatorEffectException>(eax_); - break; - - case EAXRINGMODULATOR_FREQUENCY: - eax_call.set_value<EaxRingModulatorEffectException>(eax_.flFrequency); - break; - - case EAXRINGMODULATOR_HIGHPASSCUTOFF: - eax_call.set_value<EaxRingModulatorEffectException>(eax_.flHighPassCutOff); - break; - - case EAXRINGMODULATOR_WAVEFORM: - eax_call.set_value<EaxRingModulatorEffectException>(eax_.ulWaveform); - break; - - default: - throw EaxRingModulatorEffectException{"Unsupported property id."}; + case EAXRINGMODULATOR_NONE: break; + case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value<Exception>(props); break; + case EAXRINGMODULATOR_FREQUENCY: call.set_value<Exception>(props.flFrequency); break; + case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value<Exception>(props.flHighPassCutOff); break; + case EAXRINGMODULATOR_WAVEFORM: call.set_value<Exception>(props.ulWaveform); break; + default: fail_unknown_property_id(); } } -void EaxRingModulatorEffect::validate_frequency( - float flFrequency) -{ - eax_validate_range<EaxRingModulatorEffectException>( - "Frequency", - flFrequency, - EAXRINGMODULATOR_MINFREQUENCY, - EAXRINGMODULATOR_MAXFREQUENCY); -} - -void EaxRingModulatorEffect::validate_high_pass_cutoff( - float flHighPassCutOff) -{ - eax_validate_range<EaxRingModulatorEffectException>( - "High-Pass Cutoff", - flHighPassCutOff, - EAXRINGMODULATOR_MINHIGHPASSCUTOFF, - EAXRINGMODULATOR_MAXHIGHPASSCUTOFF); -} - -void EaxRingModulatorEffect::validate_waveform( - unsigned long ulWaveform) -{ - eax_validate_range<EaxRingModulatorEffectException>( - "Waveform", - ulWaveform, - EAXRINGMODULATOR_MINWAVEFORM, - EAXRINGMODULATOR_MAXWAVEFORM); -} - -void EaxRingModulatorEffect::validate_all( - const EAXRINGMODULATORPROPERTIES& all) -{ - validate_frequency(all.flFrequency); - validate_high_pass_cutoff(all.flHighPassCutOff); - validate_waveform(all.ulWaveform); -} - -void EaxRingModulatorEffect::defer_frequency( - float flFrequency) -{ - eax_d_.flFrequency = flFrequency; - eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency); -} - -void EaxRingModulatorEffect::defer_high_pass_cutoff( - float flHighPassCutOff) -{ - eax_d_.flHighPassCutOff = flHighPassCutOff; - eax_dirty_flags_.flHighPassCutOff = (eax_.flHighPassCutOff != eax_d_.flHighPassCutOff); -} - -void EaxRingModulatorEffect::defer_waveform( - unsigned long ulWaveform) +void EaxRingModulatorEffect::set(const EaxCall& call, Props& props) { - eax_d_.ulWaveform = ulWaveform; - eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); -} - -void EaxRingModulatorEffect::defer_all( - const EAXRINGMODULATORPROPERTIES& all) -{ - defer_frequency(all.flFrequency); - defer_high_pass_cutoff(all.flHighPassCutOff); - defer_waveform(all.ulWaveform); -} - -void EaxRingModulatorEffect::defer_frequency( - const EaxEaxCall& eax_call) -{ - const auto& frequency = - eax_call.get_value< - EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flFrequency)>(); - - validate_frequency(frequency); - defer_frequency(frequency); -} - -void EaxRingModulatorEffect::defer_high_pass_cutoff( - const EaxEaxCall& eax_call) -{ - const auto& high_pass_cutoff = - eax_call.get_value< - EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flHighPassCutOff)>(); - - validate_high_pass_cutoff(high_pass_cutoff); - defer_high_pass_cutoff(high_pass_cutoff); -} - -void EaxRingModulatorEffect::defer_waveform( - const EaxEaxCall& eax_call) -{ - const auto& waveform = - eax_call.get_value< - EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::ulWaveform)>(); - - validate_waveform(waveform); - defer_waveform(waveform); -} - -void EaxRingModulatorEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value<EaxRingModulatorEffectException, const EAXRINGMODULATORPROPERTIES>(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxRingModulatorEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxRingModulatorEffectDirtyFlags{}) + switch (call.get_property_id()) { - return false; + case EAXRINGMODULATOR_NONE: break; + case EAXRINGMODULATOR_ALLPARAMETERS: defer<AllValidator>(call, props); break; + case EAXRINGMODULATOR_FREQUENCY: defer<FrequencyValidator>(call, props.flFrequency); break; + case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer<HighPassCutOffValidator>(call, props.flHighPassCutOff); break; + case EAXRINGMODULATOR_WAVEFORM: defer<WaveformValidator>(call, props.ulWaveform); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxRingModulatorEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flFrequency) + if (props_.flFrequency != props.flFrequency) { + is_dirty = true; set_efx_frequency(); } - if (eax_dirty_flags_.flHighPassCutOff) + if (props_.flHighPassCutOff != props.flHighPassCutOff) { + is_dirty = true; set_efx_high_pass_cutoff(); } - if (eax_dirty_flags_.ulWaveform) + if (props_.ulWaveform != props.ulWaveform) { + is_dirty = true; set_efx_waveform(); } - eax_dirty_flags_ = EaxRingModulatorEffectDirtyFlags{}; - - return true; -} - -void EaxRingModulatorEffect::set(const EaxEaxCall& eax_call) -{ - switch (eax_call.get_property_id()) - { - case EAXRINGMODULATOR_NONE: - break; - - case EAXRINGMODULATOR_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXRINGMODULATOR_FREQUENCY: - defer_frequency(eax_call); - break; - - case EAXRINGMODULATOR_HIGHPASSCUTOFF: - defer_high_pass_cutoff(eax_call); - break; - - case EAXRINGMODULATOR_WAVEFORM: - defer_waveform(eax_call); - break; - - default: - throw EaxRingModulatorEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_ring_modulator_effect() +EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call) { - return std::make_unique<EaxRingModulatorEffect>(); + return eax_create_eax4_effect<EaxRingModulatorEffect>(call); } #endif // ALSOFT_EAX |