aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects/modulator.cpp
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-05-24 12:19:14 +0300
committerGitHub <[email protected]>2022-05-24 02:19:14 -0700
commit074dbef2e3129e9f7ee4895c44721c2a0a4b045b (patch)
tree72087ad2df3a5293d6aec82e762797b69de64111 /al/effects/modulator.cpp
parent54d72d17ad64809aeaf7a840447e398b2d38cbc9 (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.cpp365
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