aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects
diff options
context:
space:
mode:
Diffstat (limited to 'al/effects')
-rw-r--r--al/effects/autowah.cpp482
-rw-r--r--al/effects/chorus.cpp1399
-rw-r--r--al/effects/compressor.cpp230
-rw-r--r--al/effects/distortion.cpp510
-rw-r--r--al/effects/echo.cpp511
-rw-r--r--al/effects/effects.cpp26
-rw-r--r--al/effects/effects.h3
-rw-r--r--al/effects/equalizer.cpp862
-rw-r--r--al/effects/fshifter.cpp359
-rw-r--r--al/effects/modulator.cpp365
-rw-r--r--al/effects/null.cpp36
-rw-r--r--al/effects/pshifter.cpp301
-rw-r--r--al/effects/reverb.cpp2648
-rw-r--r--al/effects/vmorpher.cpp552
14 files changed, 2660 insertions, 5624 deletions
diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp
index 23f43305..7e0e34aa 100644
--- a/al/effects/autowah.cpp
+++ b/al/effects/autowah.cpp
@@ -13,7 +13,6 @@
#ifdef ALSOFT_EAX
#include "alnumeric.h"
-
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -119,178 +118,127 @@ const EffectProps AutowahEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxAutoWahEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxAutoWahEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxAutoWahEffectDirtyFlagsValue flAttackTime : 1;
- EaxAutoWahEffectDirtyFlagsValue flReleaseTime : 1;
- EaxAutoWahEffectDirtyFlagsValue lResonance : 1;
- EaxAutoWahEffectDirtyFlagsValue lPeakLevel : 1;
-}; // EaxAutoWahEffectDirtyFlags
-
-
-class EaxAutoWahEffect final :
- public EaxEffect
-{
+class EaxAutoWahEffectException : public EaxException {
public:
- EaxAutoWahEffect();
-
-
- void dispatch(const EaxEaxCall& eax_call) override;
+ explicit EaxAutoWahEffectException(const char* message)
+ : EaxException{"EAX_AUTO_WAH_EFFECT", message}
+ {}
+}; // EaxAutoWahEffectException
- // [[nodiscard]]
- bool apply_deferred() override;
+class EaxAutoWahEffect final : public EaxEffect4<EaxAutoWahEffectException, EAXAUTOWAHPROPERTIES> {
+public:
+ EaxAutoWahEffect(const EaxCall& call);
private:
- EAXAUTOWAHPROPERTIES eax_{};
- EAXAUTOWAHPROPERTIES eax_d_{};
- EaxAutoWahEffectDirtyFlags eax_dirty_flags_{};
-
-
- void set_eax_defaults();
-
-
- void set_efx_attack_time();
-
- void set_efx_release_time();
-
- void set_efx_resonance();
-
- void set_efx_peak_gain();
-
- void set_efx_defaults();
-
-
- void get(const EaxEaxCall& eax_call);
-
-
- void validate_attack_time(
- float flAttackTime);
-
- void validate_release_time(
- float flReleaseTime);
-
- void validate_resonance(
- long lResonance);
-
- void validate_peak_level(
- long lPeakLevel);
-
- void validate_all(
- const EAXAUTOWAHPROPERTIES& eax_all);
-
-
- void defer_attack_time(
- float flAttackTime);
-
- void defer_release_time(
- float flReleaseTime);
-
- void defer_resonance(
- long lResonance);
-
- void defer_peak_level(
- long lPeakLevel);
-
- void defer_all(
- const EAXAUTOWAHPROPERTIES& eax_all);
-
-
- void defer_attack_time(
- const EaxEaxCall& eax_call);
-
- void defer_release_time(
- const EaxEaxCall& eax_call);
-
- void defer_resonance(
- const EaxEaxCall& eax_call);
-
- void defer_peak_level(
- const EaxEaxCall& eax_call);
-
- void defer_all(
- const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
+ struct AttackTimeValidator {
+ void operator()(float flAttackTime) const
+ {
+ eax_validate_range<Exception>(
+ "Attack Time",
+ flAttackTime,
+ EAXAUTOWAH_MINATTACKTIME,
+ EAXAUTOWAH_MAXATTACKTIME);
+ }
+ }; // AttackTimeValidator
+
+ struct ReleaseTimeValidator {
+ void operator()(float flReleaseTime) const
+ {
+ eax_validate_range<Exception>(
+ "Release Time",
+ flReleaseTime,
+ EAXAUTOWAH_MINRELEASETIME,
+ EAXAUTOWAH_MAXRELEASETIME);
+ }
+ }; // ReleaseTimeValidator
+
+ struct ResonanceValidator {
+ void operator()(long lResonance) const
+ {
+ eax_validate_range<Exception>(
+ "Resonance",
+ lResonance,
+ EAXAUTOWAH_MINRESONANCE,
+ EAXAUTOWAH_MAXRESONANCE);
+ }
+ }; // ResonanceValidator
+
+ struct PeakLevelValidator {
+ void operator()(long lPeakLevel) const
+ {
+ eax_validate_range<Exception>(
+ "Peak Level",
+ lPeakLevel,
+ EAXAUTOWAH_MINPEAKLEVEL,
+ EAXAUTOWAH_MAXPEAKLEVEL);
+ }
+ }; // PeakLevelValidator
+
+ struct AllValidator {
+ void operator()(const Props& all) const
+ {
+ AttackTimeValidator{}(all.flAttackTime);
+ ReleaseTimeValidator{}(all.flReleaseTime);
+ ResonanceValidator{}(all.lResonance);
+ PeakLevelValidator{}(all.lPeakLevel);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& props) override;
+
+ void set_efx_attack_time() noexcept;
+ void set_efx_release_time() noexcept;
+ void set_efx_resonance() noexcept;
+ void set_efx_peak_gain() 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;
}; // EaxAutoWahEffect
+EaxAutoWahEffect::EaxAutoWahEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_AUTOWAH, call}
+{}
-class EaxAutoWahEffectException :
- public EaxException
-{
-public:
- explicit EaxAutoWahEffectException(
- const char* message)
- :
- EaxException{"EAX_AUTO_WAH_EFFECT", message}
- {
- }
-}; // EaxAutoWahEffectException
-
-
-EaxAutoWahEffect::EaxAutoWahEffect()
- : EaxEffect{AL_EFFECT_AUTOWAH}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-void EaxAutoWahEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxAutoWahEffect::set_eax_defaults()
+void EaxAutoWahEffect::set_defaults(Props& props)
{
- eax_.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
- eax_.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
- eax_.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
- eax_.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
-
- eax_d_ = eax_;
+ props.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
+ props.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
+ props.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
+ props.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
}
-void EaxAutoWahEffect::set_efx_attack_time()
+void EaxAutoWahEffect::set_efx_attack_time() noexcept
{
- const auto attack_time = clamp(
- eax_.flAttackTime,
+ al_effect_props_.Autowah.AttackTime = clamp(
+ props_.flAttackTime,
AL_AUTOWAH_MIN_ATTACK_TIME,
AL_AUTOWAH_MAX_ATTACK_TIME);
-
- al_effect_props_.Autowah.AttackTime = attack_time;
}
-void EaxAutoWahEffect::set_efx_release_time()
+void EaxAutoWahEffect::set_efx_release_time() noexcept
{
- const auto release_time = clamp(
- eax_.flReleaseTime,
+ al_effect_props_.Autowah.ReleaseTime = clamp(
+ props_.flReleaseTime,
AL_AUTOWAH_MIN_RELEASE_TIME,
AL_AUTOWAH_MAX_RELEASE_TIME);
-
- al_effect_props_.Autowah.ReleaseTime = release_time;
}
-void EaxAutoWahEffect::set_efx_resonance()
+void EaxAutoWahEffect::set_efx_resonance() noexcept
{
- const auto resonance = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lResonance)),
+ al_effect_props_.Autowah.Resonance = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lResonance)),
AL_AUTOWAH_MIN_RESONANCE,
AL_AUTOWAH_MAX_RESONANCE);
-
- al_effect_props_.Autowah.Resonance = resonance;
}
-void EaxAutoWahEffect::set_efx_peak_gain()
+void EaxAutoWahEffect::set_efx_peak_gain() noexcept
{
- const auto peak_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lPeakLevel)),
+ al_effect_props_.Autowah.PeakGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lPeakLevel)),
AL_AUTOWAH_MIN_PEAK_GAIN,
AL_AUTOWAH_MAX_PEAK_GAIN);
-
- al_effect_props_.Autowah.PeakGain = peak_gain;
}
void EaxAutoWahEffect::set_efx_defaults()
@@ -301,248 +249,70 @@ void EaxAutoWahEffect::set_efx_defaults()
set_efx_peak_gain();
}
-void EaxAutoWahEffect::get(const EaxEaxCall& eax_call)
+void EaxAutoWahEffect::get(const EaxCall& call, const Props& props)
{
- switch (eax_call.get_property_id())
+ switch (call.get_property_id())
{
- case EAXAUTOWAH_NONE:
- break;
-
- case EAXAUTOWAH_ALLPARAMETERS:
- eax_call.set_value<EaxAutoWahEffectException>(eax_);
- break;
-
- case EAXAUTOWAH_ATTACKTIME:
- eax_call.set_value<EaxAutoWahEffectException>(eax_.flAttackTime);
- break;
-
- case EAXAUTOWAH_RELEASETIME:
- eax_call.set_value<EaxAutoWahEffectException>(eax_.flReleaseTime);
- break;
-
- case EAXAUTOWAH_RESONANCE:
- eax_call.set_value<EaxAutoWahEffectException>(eax_.lResonance);
- break;
-
- case EAXAUTOWAH_PEAKLEVEL:
- eax_call.set_value<EaxAutoWahEffectException>(eax_.lPeakLevel);
- break;
-
- default:
- throw EaxAutoWahEffectException{"Unsupported property id."};
+ case EAXAUTOWAH_NONE: break;
+ case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.flAttackTime); break;
+ case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.flReleaseTime); break;
+ case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.lResonance); break;
+ case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.lPeakLevel); break;
+ default: fail_unknown_property_id();
}
}
-void EaxAutoWahEffect::validate_attack_time(
- float flAttackTime)
+void EaxAutoWahEffect::set(const EaxCall& call, Props& props)
{
- eax_validate_range<EaxAutoWahEffectException>(
- "Attack Time",
- flAttackTime,
- EAXAUTOWAH_MINATTACKTIME,
- EAXAUTOWAH_MAXATTACKTIME);
-}
-
-void EaxAutoWahEffect::validate_release_time(
- float flReleaseTime)
-{
- eax_validate_range<EaxAutoWahEffectException>(
- "Release Time",
- flReleaseTime,
- EAXAUTOWAH_MINRELEASETIME,
- EAXAUTOWAH_MAXRELEASETIME);
-}
-
-void EaxAutoWahEffect::validate_resonance(
- long lResonance)
-{
- eax_validate_range<EaxAutoWahEffectException>(
- "Resonance",
- lResonance,
- EAXAUTOWAH_MINRESONANCE,
- EAXAUTOWAH_MAXRESONANCE);
-}
-
-void EaxAutoWahEffect::validate_peak_level(
- long lPeakLevel)
-{
- eax_validate_range<EaxAutoWahEffectException>(
- "Peak Level",
- lPeakLevel,
- EAXAUTOWAH_MINPEAKLEVEL,
- EAXAUTOWAH_MAXPEAKLEVEL);
-}
-
-void EaxAutoWahEffect::validate_all(
- const EAXAUTOWAHPROPERTIES& eax_all)
-{
- validate_attack_time(eax_all.flAttackTime);
- validate_release_time(eax_all.flReleaseTime);
- validate_resonance(eax_all.lResonance);
- validate_peak_level(eax_all.lPeakLevel);
-}
-
-void EaxAutoWahEffect::defer_attack_time(
- float flAttackTime)
-{
- eax_d_.flAttackTime = flAttackTime;
- eax_dirty_flags_.flAttackTime = (eax_.flAttackTime != eax_d_.flAttackTime);
-}
-
-void EaxAutoWahEffect::defer_release_time(
- float flReleaseTime)
-{
- eax_d_.flReleaseTime = flReleaseTime;
- eax_dirty_flags_.flReleaseTime = (eax_.flReleaseTime != eax_d_.flReleaseTime);
-}
-
-void EaxAutoWahEffect::defer_resonance(
- long lResonance)
-{
- eax_d_.lResonance = lResonance;
- eax_dirty_flags_.lResonance = (eax_.lResonance != eax_d_.lResonance);
-}
-
-void EaxAutoWahEffect::defer_peak_level(
- long lPeakLevel)
-{
- eax_d_.lPeakLevel = lPeakLevel;
- eax_dirty_flags_.lPeakLevel = (eax_.lPeakLevel != eax_d_.lPeakLevel);
-}
-
-void EaxAutoWahEffect::defer_all(
- const EAXAUTOWAHPROPERTIES& eax_all)
-{
- validate_all(eax_all);
-
- defer_attack_time(eax_all.flAttackTime);
- defer_release_time(eax_all.flReleaseTime);
- defer_resonance(eax_all.lResonance);
- defer_peak_level(eax_all.lPeakLevel);
-}
-
-void EaxAutoWahEffect::defer_attack_time(
- const EaxEaxCall& eax_call)
-{
- const auto& attack_time =
- eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::flAttackTime)>();
-
- validate_attack_time(attack_time);
- defer_attack_time(attack_time);
-}
-
-void EaxAutoWahEffect::defer_release_time(
- const EaxEaxCall& eax_call)
-{
- const auto& release_time =
- eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::flReleaseTime)>();
-
- validate_release_time(release_time);
- defer_release_time(release_time);
-}
-
-void EaxAutoWahEffect::defer_resonance(
- const EaxEaxCall& eax_call)
-{
- const auto& resonance =
- eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::lResonance)>();
-
- validate_resonance(resonance);
- defer_resonance(resonance);
-}
-
-void EaxAutoWahEffect::defer_peak_level(
- const EaxEaxCall& eax_call)
-{
- const auto& peak_level =
- eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::lPeakLevel)>();
-
- validate_peak_level(peak_level);
- defer_peak_level(peak_level);
-}
-
-void EaxAutoWahEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxAutoWahEffectException, const EAXAUTOWAHPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxAutoWahEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxAutoWahEffectDirtyFlags{})
+ switch (call.get_property_id())
{
- return false;
+ case EAXAUTOWAH_NONE: break;
+ case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.flAttackTime); break;
+ case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.flReleaseTime); break;
+ case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.lResonance); break;
+ case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.lPeakLevel); break;
+ default: fail_unknown_property_id();
}
+}
- eax_ = eax_d_;
+bool EaxAutoWahEffect::commit_props(const Props& props)
+{
+ auto is_dirty = false;
- if (eax_dirty_flags_.flAttackTime)
+ if (props_.flAttackTime != props.flAttackTime)
{
+ is_dirty = true;
set_efx_attack_time();
}
- if (eax_dirty_flags_.flReleaseTime)
+ if (props_.flReleaseTime != props.flReleaseTime)
{
+ is_dirty = true;
set_efx_release_time();
}
- if (eax_dirty_flags_.lResonance)
+ if (props_.lResonance != props.lResonance)
{
+ is_dirty = true;
set_efx_resonance();
}
- if (eax_dirty_flags_.lPeakLevel)
+ if (props_.lPeakLevel != props.lPeakLevel)
{
+ is_dirty = true;
set_efx_peak_gain();
}
- eax_dirty_flags_ = EaxAutoWahEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxAutoWahEffect::set(const EaxEaxCall& eax_call)
-{
- switch (eax_call.get_property_id())
- {
- case EAXAUTOWAH_NONE:
- break;
-
- case EAXAUTOWAH_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXAUTOWAH_ATTACKTIME:
- defer_attack_time(eax_call);
- break;
-
- case EAXAUTOWAH_RELEASETIME:
- defer_release_time(eax_call);
- break;
-
- case EAXAUTOWAH_RESONANCE:
- defer_resonance(eax_call);
- break;
-
- case EAXAUTOWAH_PEAKLEVEL:
- defer_peak_level(eax_call);
- break;
-
- default:
- throw EaxAutoWahEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-EaxEffectUPtr eax_create_eax_auto_wah_effect()
+EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call)
{
- return std::make_unique<::EaxAutoWahEffect>();
+ return eax_create_eax4_effect<EaxAutoWahEffect>(call);
}
#endif // ALSOFT_EAX
diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp
index b612a6c1..0d4283c9 100644
--- a/al/effects/chorus.cpp
+++ b/al/effects/chorus.cpp
@@ -13,9 +13,7 @@
#ifdef ALSOFT_EAX
#include <cassert>
-
#include "alnumeric.h"
-
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -293,1065 +291,444 @@ const EffectProps FlangerEffectProps{genDefaultFlangerProps()};
#ifdef ALSOFT_EAX
namespace {
-void eax_set_efx_waveform(
- ALenum waveform,
- EffectProps& al_effect_props)
-{
- const auto efx_waveform = WaveformFromEnum(waveform);
- assert(efx_waveform.has_value());
- al_effect_props.Chorus.Waveform = *efx_waveform;
-}
-
-void eax_set_efx_phase(
- ALint phase,
- EffectProps& al_effect_props)
-{
- al_effect_props.Chorus.Phase = phase;
-}
-
-void eax_set_efx_rate(
- ALfloat rate,
- EffectProps& al_effect_props)
-{
- al_effect_props.Chorus.Rate = rate;
-}
-
-void eax_set_efx_depth(
- ALfloat depth,
- EffectProps& al_effect_props)
-{
- al_effect_props.Chorus.Depth = depth;
-}
-
-void eax_set_efx_feedback(
- ALfloat feedback,
- EffectProps& al_effect_props)
-{
- al_effect_props.Chorus.Feedback = feedback;
-}
-
-void eax_set_efx_delay(
- ALfloat delay,
- EffectProps& al_effect_props)
-{
- al_effect_props.Chorus.Delay = delay;
-}
-
-
-using EaxChorusEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxChorusEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxChorusEffectDirtyFlagsValue ulWaveform : 1;
- EaxChorusEffectDirtyFlagsValue lPhase : 1;
- EaxChorusEffectDirtyFlagsValue flRate : 1;
- EaxChorusEffectDirtyFlagsValue flDepth : 1;
- EaxChorusEffectDirtyFlagsValue flFeedback : 1;
- EaxChorusEffectDirtyFlagsValue flDelay : 1;
-}; // EaxChorusEffectDirtyFlags
-
+class EaxChorusEffectException : public EaxException {
+public:
+ explicit EaxChorusEffectException(const char* message)
+ : EaxException{"EAX_CHORUS_EFFECT", message}
+ {}
+}; // EaxChorusEffectException
-class EaxChorusEffect final :
- public EaxEffect
-{
+class EaxFlangerEffectException : public EaxException {
public:
- EaxChorusEffect();
+ explicit EaxFlangerEffectException(const char* message)
+ : EaxException{"EAX_FLANGER_EFFECT", message}
+ {}
+}; // EaxFlangerEffectException
- void dispatch(const EaxEaxCall& eax_call) override;
+struct EaxChorusTraits
+{
+ using Exception = EaxChorusEffectException;
+ using Props = EAXCHORUSPROPERTIES;
+
+ static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; }
+
+ static constexpr auto eax_none_param_id() { return EAXCHORUS_NONE; }
+ static constexpr auto eax_allparameters_param_id() { return EAXCHORUS_ALLPARAMETERS; }
+ static constexpr auto eax_waveform_param_id() { return EAXCHORUS_WAVEFORM; }
+ static constexpr auto eax_phase_param_id() { return EAXCHORUS_PHASE; }
+ static constexpr auto eax_rate_param_id() { return EAXCHORUS_RATE; }
+ static constexpr auto eax_depth_param_id() { return EAXCHORUS_DEPTH; }
+ static constexpr auto eax_feedback_param_id() { return EAXCHORUS_FEEDBACK; }
+ static constexpr auto eax_delay_param_id() { return EAXCHORUS_DELAY; }
+
+ static constexpr auto eax_min_waveform() { return EAXCHORUS_MINWAVEFORM; }
+ static constexpr auto eax_min_phase() { return EAXCHORUS_MINPHASE; }
+ static constexpr auto eax_min_rate() { return EAXCHORUS_MINRATE; }
+ static constexpr auto eax_min_depth() { return EAXCHORUS_MINDEPTH; }
+ static constexpr auto eax_min_feedback() { return EAXCHORUS_MINFEEDBACK; }
+ static constexpr auto eax_min_delay() { return EAXCHORUS_MINDELAY; }
+
+ static constexpr auto eax_max_waveform() { return EAXCHORUS_MAXWAVEFORM; }
+ static constexpr auto eax_max_phase() { return EAXCHORUS_MAXPHASE; }
+ static constexpr auto eax_max_rate() { return EAXCHORUS_MAXRATE; }
+ static constexpr auto eax_max_depth() { return EAXCHORUS_MAXDEPTH; }
+ static constexpr auto eax_max_feedback() { return EAXCHORUS_MAXFEEDBACK; }
+ static constexpr auto eax_max_delay() { return EAXCHORUS_MAXDELAY; }
+
+ static constexpr auto eax_default_waveform() { return EAXCHORUS_DEFAULTWAVEFORM; }
+ static constexpr auto eax_default_phase() { return EAXCHORUS_DEFAULTPHASE; }
+ static constexpr auto eax_default_rate() { return EAXCHORUS_DEFAULTRATE; }
+ static constexpr auto eax_default_depth() { return EAXCHORUS_DEFAULTDEPTH; }
+ static constexpr auto eax_default_feedback() { return EAXCHORUS_DEFAULTFEEDBACK; }
+ static constexpr auto eax_default_delay() { return EAXCHORUS_DEFAULTDELAY; }
+
+ static constexpr auto efx_min_waveform() { return AL_CHORUS_MIN_WAVEFORM; }
+ static constexpr auto efx_min_phase() { return AL_CHORUS_MIN_PHASE; }
+ static constexpr auto efx_min_rate() { return AL_CHORUS_MIN_RATE; }
+ static constexpr auto efx_min_depth() { return AL_CHORUS_MIN_DEPTH; }
+ static constexpr auto efx_min_feedback() { return AL_CHORUS_MIN_FEEDBACK; }
+ static constexpr auto efx_min_delay() { return AL_CHORUS_MIN_DELAY; }
+
+ static constexpr auto efx_max_waveform() { return AL_CHORUS_MAX_WAVEFORM; }
+ static constexpr auto efx_max_phase() { return AL_CHORUS_MAX_PHASE; }
+ static constexpr auto efx_max_rate() { return AL_CHORUS_MAX_RATE; }
+ static constexpr auto efx_max_depth() { return AL_CHORUS_MAX_DEPTH; }
+ static constexpr auto efx_max_feedback() { return AL_CHORUS_MAX_FEEDBACK; }
+ static constexpr auto efx_max_delay() { return AL_CHORUS_MAX_DELAY; }
+
+ static constexpr auto efx_default_waveform() { return AL_CHORUS_DEFAULT_WAVEFORM; }
+ static constexpr auto efx_default_phase() { return AL_CHORUS_DEFAULT_PHASE; }
+ static constexpr auto efx_default_rate() { return AL_CHORUS_DEFAULT_RATE; }
+ static constexpr auto efx_default_depth() { return AL_CHORUS_DEFAULT_DEPTH; }
+ static constexpr auto efx_default_feedback() { return AL_CHORUS_DEFAULT_FEEDBACK; }
+ static constexpr auto efx_default_delay() { return AL_CHORUS_DEFAULT_DELAY; }
+}; // EaxChorusTraits
+
+struct EaxFlangerTraits
+{
+ using Exception = EaxFlangerEffectException;
+ using Props = EAXFLANGERPROPERTIES;
+
+ static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; }
+
+ static constexpr auto eax_none_param_id() { return EAXFLANGER_NONE; }
+ static constexpr auto eax_allparameters_param_id() { return EAXFLANGER_ALLPARAMETERS; }
+ static constexpr auto eax_waveform_param_id() { return EAXFLANGER_WAVEFORM; }
+ static constexpr auto eax_phase_param_id() { return EAXFLANGER_PHASE; }
+ static constexpr auto eax_rate_param_id() { return EAXFLANGER_RATE; }
+ static constexpr auto eax_depth_param_id() { return EAXFLANGER_DEPTH; }
+ static constexpr auto eax_feedback_param_id() { return EAXFLANGER_FEEDBACK; }
+ static constexpr auto eax_delay_param_id() { return EAXFLANGER_DELAY; }
+
+ static constexpr auto eax_min_waveform() { return EAXFLANGER_MINWAVEFORM; }
+ static constexpr auto eax_min_phase() { return EAXFLANGER_MINPHASE; }
+ static constexpr auto eax_min_rate() { return EAXFLANGER_MINRATE; }
+ static constexpr auto eax_min_depth() { return EAXFLANGER_MINDEPTH; }
+ static constexpr auto eax_min_feedback() { return EAXFLANGER_MINFEEDBACK; }
+ static constexpr auto eax_min_delay() { return EAXFLANGER_MINDELAY; }
+
+ static constexpr auto eax_max_waveform() { return EAXFLANGER_MAXWAVEFORM; }
+ static constexpr auto eax_max_phase() { return EAXFLANGER_MAXPHASE; }
+ static constexpr auto eax_max_rate() { return EAXFLANGER_MAXRATE; }
+ static constexpr auto eax_max_depth() { return EAXFLANGER_MAXDEPTH; }
+ static constexpr auto eax_max_feedback() { return EAXFLANGER_MAXFEEDBACK; }
+ static constexpr auto eax_max_delay() { return EAXFLANGER_MAXDELAY; }
+
+ static constexpr auto eax_default_waveform() { return EAXFLANGER_DEFAULTWAVEFORM; }
+ static constexpr auto eax_default_phase() { return EAXFLANGER_DEFAULTPHASE; }
+ static constexpr auto eax_default_rate() { return EAXFLANGER_DEFAULTRATE; }
+ static constexpr auto eax_default_depth() { return EAXFLANGER_DEFAULTDEPTH; }
+ static constexpr auto eax_default_feedback() { return EAXFLANGER_DEFAULTFEEDBACK; }
+ static constexpr auto eax_default_delay() { return EAXFLANGER_DEFAULTDELAY; }
+
+ static constexpr auto efx_min_waveform() { return AL_FLANGER_MIN_WAVEFORM; }
+ static constexpr auto efx_min_phase() { return AL_FLANGER_MIN_PHASE; }
+ static constexpr auto efx_min_rate() { return AL_FLANGER_MIN_RATE; }
+ static constexpr auto efx_min_depth() { return AL_FLANGER_MIN_DEPTH; }
+ static constexpr auto efx_min_feedback() { return AL_FLANGER_MIN_FEEDBACK; }
+ static constexpr auto efx_min_delay() { return AL_FLANGER_MIN_DELAY; }
+
+ static constexpr auto efx_max_waveform() { return AL_FLANGER_MAX_WAVEFORM; }
+ static constexpr auto efx_max_phase() { return AL_FLANGER_MAX_PHASE; }
+ static constexpr auto efx_max_rate() { return AL_FLANGER_MAX_RATE; }
+ static constexpr auto efx_max_depth() { return AL_FLANGER_MAX_DEPTH; }
+ static constexpr auto efx_max_feedback() { return AL_FLANGER_MAX_FEEDBACK; }
+ static constexpr auto efx_max_delay() { return AL_FLANGER_MAX_DELAY; }
+
+ static constexpr auto efx_default_waveform() { return AL_FLANGER_DEFAULT_WAVEFORM; }
+ static constexpr auto efx_default_phase() { return AL_FLANGER_DEFAULT_PHASE; }
+ static constexpr auto efx_default_rate() { return AL_FLANGER_DEFAULT_RATE; }
+ static constexpr auto efx_default_depth() { return AL_FLANGER_DEFAULT_DEPTH; }
+ static constexpr auto efx_default_feedback() { return AL_FLANGER_DEFAULT_FEEDBACK; }
+ static constexpr auto efx_default_delay() { return AL_FLANGER_DEFAULT_DELAY; }
+}; // EaxFlangerTraits
+
+template<typename TTraits>
+class EaxChorusFlangerEffect final : public EaxEffect4<typename TTraits::Exception, typename TTraits::Props> {
+public:
+ using Traits = TTraits;
+ using Base = EaxEffect4<typename Traits::Exception, typename Traits::Props>;
+ using typename Base::Exception;
+ using typename Base::Props;
+ using typename Base::State;
+ using Base::defer;
- // [[nodiscard]]
- bool apply_deferred() override;
+ EaxChorusFlangerEffect(const EaxCall& call)
+ : Base{Traits::efx_effect(), call}
+ {}
private:
- EAXCHORUSPROPERTIES eax_{};
- EAXCHORUSPROPERTIES eax_d_{};
- EaxChorusEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults() noexcept;
-
- void set_efx_waveform();
- void set_efx_phase();
- void set_efx_rate();
- void set_efx_depth();
- void set_efx_feedback();
- void set_efx_delay();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_waveform(unsigned long ulWaveform);
- void validate_phase(long lPhase);
- void validate_rate(float flRate);
- void validate_depth(float flDepth);
- void validate_feedback(float flFeedback);
- void validate_delay(float flDelay);
- void validate_all(const EAXCHORUSPROPERTIES& eax_all);
-
- void defer_waveform(unsigned long ulWaveform);
- void defer_phase(long lPhase);
- void defer_rate(float flRate);
- void defer_depth(float flDepth);
- void defer_feedback(float flFeedback);
- void defer_delay(float flDelay);
- void defer_all(const EAXCHORUSPROPERTIES& eax_all);
-
- void defer_waveform(const EaxEaxCall& eax_call);
- void defer_phase(const EaxEaxCall& eax_call);
- void defer_rate(const EaxEaxCall& eax_call);
- void defer_depth(const EaxEaxCall& eax_call);
- void defer_feedback(const EaxEaxCall& eax_call);
- void defer_delay(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
-}; // EaxChorusEffect
-
-
-class EaxChorusEffectException :
- public EaxException
-{
-public:
- explicit EaxChorusEffectException(
- const char* message)
- :
- EaxException{"EAX_CHORUS_EFFECT", message}
+ struct WaveformValidator {
+ void operator()(unsigned long ulWaveform) const
+ {
+ eax_validate_range<Exception>(
+ "Waveform",
+ ulWaveform,
+ Traits::eax_min_waveform(),
+ Traits::eax_max_waveform());
+ }
+ }; // WaveformValidator
+
+ struct PhaseValidator {
+ void operator()(long lPhase) const
+ {
+ eax_validate_range<Exception>(
+ "Phase",
+ lPhase,
+ Traits::eax_min_phase(),
+ Traits::eax_max_phase());
+ }
+ }; // PhaseValidator
+
+ struct RateValidator {
+ void operator()(float flRate) const
+ {
+ eax_validate_range<Exception>(
+ "Rate",
+ flRate,
+ Traits::eax_min_rate(),
+ Traits::eax_max_rate());
+ }
+ }; // RateValidator
+
+ struct DepthValidator {
+ void operator()(float flDepth) const
+ {
+ eax_validate_range<Exception>(
+ "Depth",
+ flDepth,
+ Traits::eax_min_depth(),
+ Traits::eax_max_depth());
+ }
+ }; // DepthValidator
+
+ struct FeedbackValidator {
+ void operator()(float flFeedback) const
+ {
+ eax_validate_range<Exception>(
+ "Feedback",
+ flFeedback,
+ Traits::eax_min_feedback(),
+ Traits::eax_max_feedback());
+ }
+ }; // FeedbackValidator
+
+ struct DelayValidator {
+ void operator()(float flDelay) const
+ {
+ eax_validate_range<Exception>(
+ "Delay",
+ flDelay,
+ Traits::eax_min_delay(),
+ Traits::eax_max_delay());
+ }
+ }; // DelayValidator
+
+ struct AllValidator {
+ void operator()(const Props& all) const
+ {
+ WaveformValidator{}(all.ulWaveform);
+ PhaseValidator{}(all.lPhase);
+ RateValidator{}(all.flRate);
+ DepthValidator{}(all.flDepth);
+ FeedbackValidator{}(all.flFeedback);
+ DelayValidator{}(all.flDelay);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& props) override
{
+ props.ulWaveform = Traits::eax_default_waveform();
+ props.lPhase = Traits::eax_default_phase();
+ props.flRate = Traits::eax_default_rate();
+ props.flDepth = Traits::eax_default_depth();
+ props.flFeedback = Traits::eax_default_feedback();
+ props.flDelay = Traits::eax_default_delay();
}
-}; // EaxChorusEffectException
-
-
-EaxChorusEffect::EaxChorusEffect()
- : EaxEffect{AL_EFFECT_CHORUS}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-void EaxChorusEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxChorusEffect::set_eax_defaults() noexcept
-{
- eax_.ulWaveform = EAXCHORUS_DEFAULTWAVEFORM;
- eax_.lPhase = EAXCHORUS_DEFAULTPHASE;
- eax_.flRate = EAXCHORUS_DEFAULTRATE;
- eax_.flDepth = EAXCHORUS_DEFAULTDEPTH;
- eax_.flFeedback = EAXCHORUS_DEFAULTFEEDBACK;
- eax_.flDelay = EAXCHORUS_DEFAULTDELAY;
-
- eax_d_ = eax_;
-}
-
-void EaxChorusEffect::set_efx_waveform()
-{
- const auto waveform = clamp(
- static_cast<ALint>(eax_.ulWaveform),
- AL_CHORUS_MIN_WAVEFORM,
- AL_CHORUS_MAX_WAVEFORM);
- eax_set_efx_waveform(waveform, al_effect_props_);
-}
-
-void EaxChorusEffect::set_efx_phase()
-{
- const auto phase = clamp(
- static_cast<ALint>(eax_.lPhase),
- AL_CHORUS_MIN_PHASE,
- AL_CHORUS_MAX_PHASE);
-
- eax_set_efx_phase(phase, al_effect_props_);
-}
-
-void EaxChorusEffect::set_efx_rate()
-{
- const auto rate = clamp(
- eax_.flRate,
- AL_CHORUS_MIN_RATE,
- AL_CHORUS_MAX_RATE);
-
- eax_set_efx_rate(rate, al_effect_props_);
-}
-
-void EaxChorusEffect::set_efx_depth()
-{
- const auto depth = clamp(
- eax_.flDepth,
- AL_CHORUS_MIN_DEPTH,
- AL_CHORUS_MAX_DEPTH);
-
- eax_set_efx_depth(depth, al_effect_props_);
-}
-
-void EaxChorusEffect::set_efx_feedback()
-{
- const auto feedback = clamp(
- eax_.flFeedback,
- AL_CHORUS_MIN_FEEDBACK,
- AL_CHORUS_MAX_FEEDBACK);
-
- eax_set_efx_feedback(feedback, al_effect_props_);
-}
-
-void EaxChorusEffect::set_efx_delay()
-{
- const auto delay = clamp(
- eax_.flDelay,
- AL_CHORUS_MIN_DELAY,
- AL_CHORUS_MAX_DELAY);
-
- eax_set_efx_delay(delay, al_effect_props_);
-}
-
-void EaxChorusEffect::set_efx_defaults()
-{
- set_efx_waveform();
- set_efx_phase();
- set_efx_rate();
- set_efx_depth();
- set_efx_feedback();
- set_efx_delay();
-}
-
-void EaxChorusEffect::get(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
+ void set_efx_waveform()
{
- case EAXCHORUS_NONE:
- break;
-
- case EAXCHORUS_ALLPARAMETERS:
- eax_call.set_value<EaxChorusEffectException>(eax_);
- break;
-
- case EAXCHORUS_WAVEFORM:
- eax_call.set_value<EaxChorusEffectException>(eax_.ulWaveform);
- break;
-
- case EAXCHORUS_PHASE:
- eax_call.set_value<EaxChorusEffectException>(eax_.lPhase);
- break;
-
- case EAXCHORUS_RATE:
- eax_call.set_value<EaxChorusEffectException>(eax_.flRate);
- break;
-
- case EAXCHORUS_DEPTH:
- eax_call.set_value<EaxChorusEffectException>(eax_.flDepth);
- break;
-
- case EAXCHORUS_FEEDBACK:
- eax_call.set_value<EaxChorusEffectException>(eax_.flFeedback);
- break;
-
- case EAXCHORUS_DELAY:
- eax_call.set_value<EaxChorusEffectException>(eax_.flDelay);
- break;
-
- default:
- throw EaxChorusEffectException{"Unsupported property id."};
+ const auto waveform = clamp(
+ static_cast<ALint>(Base::props_.ulWaveform),
+ Traits::efx_min_waveform(),
+ Traits::efx_max_waveform());
+ const auto efx_waveform = WaveformFromEnum(waveform);
+ assert(efx_waveform.has_value());
+ Base::al_effect_props_.Chorus.Waveform = *efx_waveform;
}
-}
-
-void EaxChorusEffect::validate_waveform(
- unsigned long ulWaveform)
-{
- eax_validate_range<EaxChorusEffectException>(
- "Waveform",
- ulWaveform,
- EAXCHORUS_MINWAVEFORM,
- EAXCHORUS_MAXWAVEFORM);
-}
-
-void EaxChorusEffect::validate_phase(
- long lPhase)
-{
- eax_validate_range<EaxChorusEffectException>(
- "Phase",
- lPhase,
- EAXCHORUS_MINPHASE,
- EAXCHORUS_MAXPHASE);
-}
-
-void EaxChorusEffect::validate_rate(
- float flRate)
-{
- eax_validate_range<EaxChorusEffectException>(
- "Rate",
- flRate,
- EAXCHORUS_MINRATE,
- EAXCHORUS_MAXRATE);
-}
-
-void EaxChorusEffect::validate_depth(
- float flDepth)
-{
- eax_validate_range<EaxChorusEffectException>(
- "Depth",
- flDepth,
- EAXCHORUS_MINDEPTH,
- EAXCHORUS_MAXDEPTH);
-}
-
-void EaxChorusEffect::validate_feedback(
- float flFeedback)
-{
- eax_validate_range<EaxChorusEffectException>(
- "Feedback",
- flFeedback,
- EAXCHORUS_MINFEEDBACK,
- EAXCHORUS_MAXFEEDBACK);
-}
-
-void EaxChorusEffect::validate_delay(
- float flDelay)
-{
- eax_validate_range<EaxChorusEffectException>(
- "Delay",
- flDelay,
- EAXCHORUS_MINDELAY,
- EAXCHORUS_MAXDELAY);
-}
-
-void EaxChorusEffect::validate_all(
- const EAXCHORUSPROPERTIES& eax_all)
-{
- validate_waveform(eax_all.ulWaveform);
- validate_phase(eax_all.lPhase);
- validate_rate(eax_all.flRate);
- validate_depth(eax_all.flDepth);
- validate_feedback(eax_all.flFeedback);
- validate_delay(eax_all.flDelay);
-}
-
-void EaxChorusEffect::defer_waveform(
- unsigned long ulWaveform)
-{
- eax_d_.ulWaveform = ulWaveform;
- eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
-}
-
-void EaxChorusEffect::defer_phase(
- long lPhase)
-{
- eax_d_.lPhase = lPhase;
- eax_dirty_flags_.lPhase = (eax_.lPhase != eax_d_.lPhase);
-}
-
-void EaxChorusEffect::defer_rate(
- float flRate)
-{
- eax_d_.flRate = flRate;
- eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate);
-}
-
-void EaxChorusEffect::defer_depth(
- float flDepth)
-{
- eax_d_.flDepth = flDepth;
- eax_dirty_flags_.flDepth = (eax_.flDepth != eax_d_.flDepth);
-}
-
-void EaxChorusEffect::defer_feedback(
- float flFeedback)
-{
- eax_d_.flFeedback = flFeedback;
- eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback);
-}
-
-void EaxChorusEffect::defer_delay(
- float flDelay)
-{
- eax_d_.flDelay = flDelay;
- eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay);
-}
-
-void EaxChorusEffect::defer_all(
- const EAXCHORUSPROPERTIES& eax_all)
-{
- defer_waveform(eax_all.ulWaveform);
- defer_phase(eax_all.lPhase);
- defer_rate(eax_all.flRate);
- defer_depth(eax_all.flDepth);
- defer_feedback(eax_all.flFeedback);
- defer_delay(eax_all.flDelay);
-}
-
-void EaxChorusEffect::defer_waveform(
- const EaxEaxCall& eax_call)
-{
- const auto& waveform =
- eax_call.get_value<EaxChorusEffectException, const decltype(EAXCHORUSPROPERTIES::ulWaveform)>();
-
- validate_waveform(waveform);
- defer_waveform(waveform);
-}
-
-void EaxChorusEffect::defer_phase(
- const EaxEaxCall& eax_call)
-{
- const auto& phase =
- eax_call.get_value<EaxChorusEffectException, const decltype(EAXCHORUSPROPERTIES::lPhase)>();
-
- validate_phase(phase);
- defer_phase(phase);
-}
-
-void EaxChorusEffect::defer_rate(
- const EaxEaxCall& eax_call)
-{
- const auto& rate =
- eax_call.get_value<EaxChorusEffectException, const decltype(EAXCHORUSPROPERTIES::flRate)>();
-
- validate_rate(rate);
- defer_rate(rate);
-}
-
-void EaxChorusEffect::defer_depth(
- const EaxEaxCall& eax_call)
-{
- const auto& depth =
- eax_call.get_value<EaxChorusEffectException, const decltype(EAXCHORUSPROPERTIES::flDepth)>();
-
- validate_depth(depth);
- defer_depth(depth);
-}
-
-void EaxChorusEffect::defer_feedback(
- const EaxEaxCall& eax_call)
-{
- const auto& feedback =
- eax_call.get_value<EaxChorusEffectException, const decltype(EAXCHORUSPROPERTIES::flFeedback)>();
-
- validate_feedback(feedback);
- defer_feedback(feedback);
-}
-
-void EaxChorusEffect::defer_delay(
- const EaxEaxCall& eax_call)
-{
- const auto& delay =
- eax_call.get_value<EaxChorusEffectException, const decltype(EAXCHORUSPROPERTIES::flDelay)>();
- validate_delay(delay);
- defer_delay(delay);
-}
-
-void EaxChorusEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxChorusEffectException, const EAXCHORUSPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxChorusEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxChorusEffectDirtyFlags{})
+ void set_efx_phase() noexcept
{
- return false;
+ Base::al_effect_props_.Chorus.Phase = clamp(
+ static_cast<ALint>(Base::props_.lPhase),
+ Traits::efx_min_phase(),
+ Traits::efx_max_phase());
}
- eax_ = eax_d_;
-
- if (eax_dirty_flags_.ulWaveform)
+ void set_efx_rate() noexcept
{
- set_efx_waveform();
+ Base::al_effect_props_.Chorus.Rate = clamp(
+ Base::props_.flRate,
+ Traits::efx_min_rate(),
+ Traits::efx_max_rate());
}
- if (eax_dirty_flags_.lPhase)
+ void set_efx_depth() noexcept
{
- set_efx_phase();
+ Base::al_effect_props_.Chorus.Depth = clamp(
+ Base::props_.flDepth,
+ Traits::efx_min_depth(),
+ Traits::efx_max_depth());
}
- if (eax_dirty_flags_.flRate)
+ void set_efx_feedback() noexcept
{
- set_efx_rate();
+ Base::al_effect_props_.Chorus.Feedback = clamp(
+ Base::props_.flFeedback,
+ Traits::efx_min_feedback(),
+ Traits::efx_max_feedback());
}
- if (eax_dirty_flags_.flDepth)
+ void set_efx_delay() noexcept
{
- set_efx_depth();
+ Base::al_effect_props_.Chorus.Delay = clamp(
+ Base::props_.flDelay,
+ Traits::efx_min_delay(),
+ Traits::efx_max_delay());
}
- if (eax_dirty_flags_.flFeedback)
+ void set_efx_defaults() override
{
+ set_efx_waveform();
+ set_efx_phase();
+ set_efx_rate();
+ set_efx_depth();
set_efx_feedback();
- }
-
- if (eax_dirty_flags_.flDelay)
- {
set_efx_delay();
}
- eax_dirty_flags_ = EaxChorusEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxChorusEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
+ void get(const EaxCall& call, const Props& props) override
{
- case EAXCHORUS_NONE:
- break;
-
- case EAXCHORUS_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXCHORUS_WAVEFORM:
- defer_waveform(eax_call);
- break;
-
- case EAXCHORUS_PHASE:
- defer_phase(eax_call);
- break;
-
- case EAXCHORUS_RATE:
- defer_rate(eax_call);
- break;
-
- case EAXCHORUS_DEPTH:
- defer_depth(eax_call);
- break;
-
- case EAXCHORUS_FEEDBACK:
- defer_feedback(eax_call);
- break;
-
- case EAXCHORUS_DELAY:
- defer_delay(eax_call);
- break;
-
- default:
- throw EaxChorusEffectException{"Unsupported property id."};
+ switch(call.get_property_id())
+ {
+ case Traits::eax_none_param_id():
+ break;
+
+ case Traits::eax_allparameters_param_id():
+ call.template set_value<Exception>(props);
+ break;
+
+ case Traits::eax_waveform_param_id():
+ call.template set_value<Exception>(props.ulWaveform);
+ break;
+
+ case Traits::eax_phase_param_id():
+ call.template set_value<Exception>(props.lPhase);
+ break;
+
+ case Traits::eax_rate_param_id():
+ call.template set_value<Exception>(props.flRate);
+ break;
+
+ case Traits::eax_depth_param_id():
+ call.template set_value<Exception>(props.flDepth);
+ break;
+
+ case Traits::eax_feedback_param_id():
+ call.template set_value<Exception>(props.flFeedback);
+ break;
+
+ case Traits::eax_delay_param_id():
+ call.template set_value<Exception>(props.flDelay);
+ break;
+
+ default:
+ Base::fail_unknown_property_id();
+ }
}
-}
-
-
-} // namespace
-
-EaxEffectUPtr eax_create_eax_chorus_effect()
-{
- return std::make_unique<::EaxChorusEffect>();
-}
-
-
-namespace
-{
-
-
-using EaxFlangerEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxFlangerEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxFlangerEffectDirtyFlagsValue ulWaveform : 1;
- EaxFlangerEffectDirtyFlagsValue lPhase : 1;
- EaxFlangerEffectDirtyFlagsValue flRate : 1;
- EaxFlangerEffectDirtyFlagsValue flDepth : 1;
- EaxFlangerEffectDirtyFlagsValue flFeedback : 1;
- EaxFlangerEffectDirtyFlagsValue flDelay : 1;
-}; // EaxFlangerEffectDirtyFlags
-
-
-class EaxFlangerEffect final :
- public EaxEffect
-{
-public:
- EaxFlangerEffect();
-
-
- void dispatch(const EaxEaxCall& eax_call) override;
-
- // [[nodiscard]]
- bool apply_deferred() override;
-
-private:
- EAXFLANGERPROPERTIES eax_{};
- EAXFLANGERPROPERTIES eax_d_{};
- EaxFlangerEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults();
-
- void set_efx_waveform();
- void set_efx_phase();
- void set_efx_rate();
- void set_efx_depth();
- void set_efx_feedback();
- void set_efx_delay();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_waveform(unsigned long ulWaveform);
- void validate_phase(long lPhase);
- void validate_rate(float flRate);
- void validate_depth(float flDepth);
- void validate_feedback(float flFeedback);
- void validate_delay(float flDelay);
- void validate_all(const EAXFLANGERPROPERTIES& all);
-
- void defer_waveform(unsigned long ulWaveform);
- void defer_phase(long lPhase);
- void defer_rate(float flRate);
- void defer_depth(float flDepth);
- void defer_feedback(float flFeedback);
- void defer_delay(float flDelay);
- void defer_all(const EAXFLANGERPROPERTIES& all);
-
- void defer_waveform(const EaxEaxCall& eax_call);
- void defer_phase(const EaxEaxCall& eax_call);
- void defer_rate(const EaxEaxCall& eax_call);
- void defer_depth(const EaxEaxCall& eax_call);
- void defer_feedback(const EaxEaxCall& eax_call);
- void defer_delay(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
-}; // EaxFlangerEffect
-
-
-class EaxFlangerEffectException :
- public EaxException
-{
-public:
- explicit EaxFlangerEffectException(
- const char* message)
- :
- EaxException{"EAX_FLANGER_EFFECT", message}
+ void set(const EaxCall& call, Props& props) override
{
+ switch(call.get_property_id())
+ {
+ case Traits::eax_none_param_id():
+ break;
+
+ case Traits::eax_allparameters_param_id():
+ Base::template defer<AllValidator>(call, props);
+ break;
+
+ case Traits::eax_waveform_param_id():
+ Base::template defer<WaveformValidator>(call, props.ulWaveform);
+ break;
+
+ case Traits::eax_phase_param_id():
+ Base::template defer<PhaseValidator>(call, props.lPhase);
+ break;
+
+ case Traits::eax_rate_param_id():
+ Base::template defer<RateValidator>(call, props.flRate);
+ break;
+
+ case Traits::eax_depth_param_id():
+ Base::template defer<DepthValidator>(call, props.flDepth);
+ break;
+
+ case Traits::eax_feedback_param_id():
+ Base::template defer<FeedbackValidator>(call, props.flFeedback);
+ break;
+
+ case Traits::eax_delay_param_id():
+ Base::template defer<DelayValidator>(call, props.flDelay);
+ break;
+
+ default:
+ Base::fail_unknown_property_id();
+ }
}
-}; // EaxFlangerEffectException
-
-
-EaxFlangerEffect::EaxFlangerEffect()
- : EaxEffect{AL_EFFECT_FLANGER}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-void EaxFlangerEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxFlangerEffect::set_eax_defaults()
-{
- eax_.ulWaveform = EAXFLANGER_DEFAULTWAVEFORM;
- eax_.lPhase = EAXFLANGER_DEFAULTPHASE;
- eax_.flRate = EAXFLANGER_DEFAULTRATE;
- eax_.flDepth = EAXFLANGER_DEFAULTDEPTH;
- eax_.flFeedback = EAXFLANGER_DEFAULTFEEDBACK;
- eax_.flDelay = EAXFLANGER_DEFAULTDELAY;
-
- eax_d_ = eax_;
-}
-
-void EaxFlangerEffect::set_efx_waveform()
-{
- const auto waveform = clamp(
- static_cast<ALint>(eax_.ulWaveform),
- AL_FLANGER_MIN_WAVEFORM,
- AL_FLANGER_MAX_WAVEFORM);
-
- eax_set_efx_waveform(waveform, al_effect_props_);
-}
-
-void EaxFlangerEffect::set_efx_phase()
-{
- const auto phase = clamp(
- static_cast<ALint>(eax_.lPhase),
- AL_FLANGER_MIN_PHASE,
- AL_FLANGER_MAX_PHASE);
-
- eax_set_efx_phase(phase, al_effect_props_);
-}
-
-void EaxFlangerEffect::set_efx_rate()
-{
- const auto rate = clamp(
- eax_.flRate,
- AL_FLANGER_MIN_RATE,
- AL_FLANGER_MAX_RATE);
-
- eax_set_efx_rate(rate, al_effect_props_);
-}
-
-void EaxFlangerEffect::set_efx_depth()
-{
- const auto depth = clamp(
- eax_.flDepth,
- AL_FLANGER_MIN_DEPTH,
- AL_FLANGER_MAX_DEPTH);
-
- eax_set_efx_depth(depth, al_effect_props_);
-}
-
-void EaxFlangerEffect::set_efx_feedback()
-{
- const auto feedback = clamp(
- eax_.flFeedback,
- AL_FLANGER_MIN_FEEDBACK,
- AL_FLANGER_MAX_FEEDBACK);
-
- eax_set_efx_feedback(feedback, al_effect_props_);
-}
-
-void EaxFlangerEffect::set_efx_delay()
-{
- const auto delay = clamp(
- eax_.flDelay,
- AL_FLANGER_MIN_DELAY,
- AL_FLANGER_MAX_DELAY);
- eax_set_efx_delay(delay, al_effect_props_);
-}
-
-void EaxFlangerEffect::set_efx_defaults()
-{
- set_efx_waveform();
- set_efx_phase();
- set_efx_rate();
- set_efx_depth();
- set_efx_feedback();
- set_efx_delay();
-}
-
-void EaxFlangerEffect::get(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
+ bool commit_props(const Props& props) override
{
- case EAXFLANGER_NONE:
- break;
-
- case EAXFLANGER_ALLPARAMETERS:
- eax_call.set_value<EaxFlangerEffectException>(eax_);
- break;
-
- case EAXFLANGER_WAVEFORM:
- eax_call.set_value<EaxFlangerEffectException>(eax_.ulWaveform);
- break;
-
- case EAXFLANGER_PHASE:
- eax_call.set_value<EaxFlangerEffectException>(eax_.lPhase);
- break;
-
- case EAXFLANGER_RATE:
- eax_call.set_value<EaxFlangerEffectException>(eax_.flRate);
- break;
-
- case EAXFLANGER_DEPTH:
- eax_call.set_value<EaxFlangerEffectException>(eax_.flDepth);
- break;
-
- case EAXFLANGER_FEEDBACK:
- eax_call.set_value<EaxFlangerEffectException>(eax_.flFeedback);
- break;
-
- case EAXFLANGER_DELAY:
- eax_call.set_value<EaxFlangerEffectException>(eax_.flDelay);
- break;
-
- default:
- throw EaxFlangerEffectException{"Unsupported property id."};
+ auto is_dirty = false;
+
+ if (Base::props_.ulWaveform != props.ulWaveform)
+ {
+ is_dirty = true;
+ set_efx_waveform();
+ }
+
+ if (Base::props_.lPhase != props.lPhase)
+ {
+ is_dirty = true;
+ set_efx_phase();
+ }
+
+ if (Base::props_.flRate != props.flRate)
+ {
+ is_dirty = true;
+ set_efx_rate();
+ }
+
+ if (Base::props_.flDepth != props.flDepth)
+ {
+ is_dirty = true;
+ set_efx_depth();
+ }
+
+ if (Base::props_.flFeedback != props.flFeedback)
+ {
+ is_dirty = true;
+ set_efx_feedback();
+ }
+
+ if (Base::props_.flDelay != props.flDelay)
+ {
+ is_dirty = true;
+ set_efx_delay();
+ }
+
+ return is_dirty;
}
-}
-
-void EaxFlangerEffect::validate_waveform(
- unsigned long ulWaveform)
-{
- eax_validate_range<EaxFlangerEffectException>(
- "Waveform",
- ulWaveform,
- EAXFLANGER_MINWAVEFORM,
- EAXFLANGER_MAXWAVEFORM);
-}
-
-void EaxFlangerEffect::validate_phase(
- long lPhase)
-{
- eax_validate_range<EaxFlangerEffectException>(
- "Phase",
- lPhase,
- EAXFLANGER_MINPHASE,
- EAXFLANGER_MAXPHASE);
-}
-
-void EaxFlangerEffect::validate_rate(
- float flRate)
-{
- eax_validate_range<EaxFlangerEffectException>(
- "Rate",
- flRate,
- EAXFLANGER_MINRATE,
- EAXFLANGER_MAXRATE);
-}
-
-void EaxFlangerEffect::validate_depth(
- float flDepth)
-{
- eax_validate_range<EaxFlangerEffectException>(
- "Depth",
- flDepth,
- EAXFLANGER_MINDEPTH,
- EAXFLANGER_MAXDEPTH);
-}
-
-void EaxFlangerEffect::validate_feedback(
- float flFeedback)
-{
- eax_validate_range<EaxFlangerEffectException>(
- "Feedback",
- flFeedback,
- EAXFLANGER_MINFEEDBACK,
- EAXFLANGER_MAXFEEDBACK);
-}
-
-void EaxFlangerEffect::validate_delay(
- float flDelay)
-{
- eax_validate_range<EaxFlangerEffectException>(
- "Delay",
- flDelay,
- EAXFLANGER_MINDELAY,
- EAXFLANGER_MAXDELAY);
-}
-
-void EaxFlangerEffect::validate_all(
- const EAXFLANGERPROPERTIES& all)
-{
- validate_waveform(all.ulWaveform);
- validate_phase(all.lPhase);
- validate_rate(all.flRate);
- validate_depth(all.flDepth);
- validate_feedback(all.flDelay);
- validate_delay(all.flDelay);
-}
+}; // EaxChorusFlangerEffect
-void EaxFlangerEffect::defer_waveform(
- unsigned long ulWaveform)
+template<typename TTraits>
+EaxEffectUPtr eax_create_eax_chorus_flanger_effect(const EaxCall& call)
{
- eax_d_.ulWaveform = ulWaveform;
- eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
+ return eax_create_eax4_effect<EaxChorusFlangerEffect<TTraits>>(call);
}
-void EaxFlangerEffect::defer_phase(
- long lPhase)
-{
- eax_d_.lPhase = lPhase;
- eax_dirty_flags_.lPhase = (eax_.lPhase != eax_d_.lPhase);
-}
-
-void EaxFlangerEffect::defer_rate(
- float flRate)
-{
- eax_d_.flRate = flRate;
- eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate);
-}
-
-void EaxFlangerEffect::defer_depth(
- float flDepth)
-{
- eax_d_.flDepth = flDepth;
- eax_dirty_flags_.flDepth = (eax_.flDepth != eax_d_.flDepth);
-}
-
-void EaxFlangerEffect::defer_feedback(
- float flFeedback)
-{
- eax_d_.flFeedback = flFeedback;
- eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback);
-}
-
-void EaxFlangerEffect::defer_delay(
- float flDelay)
-{
- eax_d_.flDelay = flDelay;
- eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay);
-}
-
-void EaxFlangerEffect::defer_all(
- const EAXFLANGERPROPERTIES& all)
-{
- defer_waveform(all.ulWaveform);
- defer_phase(all.lPhase);
- defer_rate(all.flRate);
- defer_depth(all.flDepth);
- defer_feedback(all.flDelay);
- defer_delay(all.flDelay);
-}
-
-void EaxFlangerEffect::defer_waveform(
- const EaxEaxCall& eax_call)
-{
- const auto& waveform =
- eax_call.get_value<EaxFlangerEffectException, const decltype(EAXFLANGERPROPERTIES::ulWaveform)>();
-
- validate_waveform(waveform);
- defer_waveform(waveform);
-}
-
-void EaxFlangerEffect::defer_phase(
- const EaxEaxCall& eax_call)
-{
- const auto& phase =
- eax_call.get_value<EaxFlangerEffectException, const decltype(EAXFLANGERPROPERTIES::lPhase)>();
-
- validate_phase(phase);
- defer_phase(phase);
-}
-
-void EaxFlangerEffect::defer_rate(
- const EaxEaxCall& eax_call)
-{
- const auto& rate =
- eax_call.get_value<EaxFlangerEffectException, const decltype(EAXFLANGERPROPERTIES::flRate)>();
-
- validate_rate(rate);
- defer_rate(rate);
-}
-
-void EaxFlangerEffect::defer_depth(
- const EaxEaxCall& eax_call)
-{
- const auto& depth =
- eax_call.get_value<EaxFlangerEffectException, const decltype(EAXFLANGERPROPERTIES::flDepth)>();
-
- validate_depth(depth);
- defer_depth(depth);
-}
-
-void EaxFlangerEffect::defer_feedback(
- const EaxEaxCall& eax_call)
-{
- const auto& feedback =
- eax_call.get_value<EaxFlangerEffectException, const decltype(EAXFLANGERPROPERTIES::flFeedback)>();
-
- validate_feedback(feedback);
- defer_feedback(feedback);
-}
-
-void EaxFlangerEffect::defer_delay(
- const EaxEaxCall& eax_call)
-{
- const auto& delay =
- eax_call.get_value<EaxFlangerEffectException, const decltype(EAXFLANGERPROPERTIES::flDelay)>();
-
- validate_delay(delay);
- defer_delay(delay);
-}
-
-void EaxFlangerEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxFlangerEffectException, const EAXFLANGERPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxFlangerEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxFlangerEffectDirtyFlags{})
- {
- return false;
- }
-
- eax_ = eax_d_;
-
- if (eax_dirty_flags_.ulWaveform)
- {
- set_efx_waveform();
- }
-
- if (eax_dirty_flags_.lPhase)
- {
- set_efx_phase();
- }
-
- if (eax_dirty_flags_.flRate)
- {
- set_efx_rate();
- }
-
- if (eax_dirty_flags_.flDepth)
- {
- set_efx_depth();
- }
-
- if (eax_dirty_flags_.flFeedback)
- {
- set_efx_feedback();
- }
-
- if (eax_dirty_flags_.flDelay)
- {
- set_efx_delay();
- }
+} // namespace
- eax_dirty_flags_ = EaxFlangerEffectDirtyFlags{};
+// ==========================================================================
- return true;
-}
-
-void EaxFlangerEffect::set(const EaxEaxCall& eax_call)
+EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call)
{
- switch(eax_call.get_property_id())
- {
- case EAXFLANGER_NONE:
- break;
-
- case EAXFLANGER_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXFLANGER_WAVEFORM:
- defer_waveform(eax_call);
- break;
-
- case EAXFLANGER_PHASE:
- defer_phase(eax_call);
- break;
-
- case EAXFLANGER_RATE:
- defer_rate(eax_call);
- break;
-
- case EAXFLANGER_DEPTH:
- defer_depth(eax_call);
- break;
-
- case EAXFLANGER_FEEDBACK:
- defer_feedback(eax_call);
- break;
-
- case EAXFLANGER_DELAY:
- defer_delay(eax_call);
- break;
-
- default:
- throw EaxFlangerEffectException{"Unsupported property id."};
- }
+ return eax_create_eax_chorus_flanger_effect<EaxChorusTraits>(call);
}
-} // namespace
-
-EaxEffectUPtr eax_create_eax_flanger_effect()
+EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call)
{
- return std::make_unique<EaxFlangerEffect>();
+ return eax_create_eax_chorus_flanger_effect<EaxFlangerTraits>(call);
}
#endif // ALSOFT_EAX
diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp
index a18609ca..9824d11b 100644
--- a/al/effects/compressor.cpp
+++ b/al/effects/compressor.cpp
@@ -9,7 +9,6 @@
#ifdef ALSOFT_EAX
#include "alnumeric.h"
-
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -81,94 +80,63 @@ const EffectProps CompressorEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxCompressorEffectDirtyFlags
+class EaxCompressorEffectException : public EaxException
{
- using EaxIsBitFieldStruct = bool;
-
- EaxCompressorEffectDirtyFlagsValue ulOnOff : 1;
-}; // EaxCompressorEffectDirtyFlags
-
+public:
+ explicit EaxCompressorEffectException(const char* message)
+ : EaxException{"EAX_COMPRESSOR_EFFECT", message}
+ {}
+}; // EaxCompressorEffectException
-class EaxCompressorEffect final :
- public EaxEffect
+class EaxCompressorEffect final : public EaxEffect4<EaxCompressorEffectException, EAXAGCCOMPRESSORPROPERTIES>
{
public:
- EaxCompressorEffect();
-
-
- void dispatch(const EaxEaxCall& eax_call) override;
-
- // [[nodiscard]]
- bool apply_deferred() override;
+ EaxCompressorEffect(const EaxCall& call);
private:
- EAXAGCCOMPRESSORPROPERTIES eax_{};
- EAXAGCCOMPRESSORPROPERTIES eax_d_{};
- EaxCompressorEffectDirtyFlags eax_dirty_flags_{};
-
-
- void set_eax_defaults();
-
- void set_efx_on_off();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_on_off(unsigned long ulOnOff);
- void validate_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
-
- void defer_on_off(unsigned long ulOnOff);
- void defer_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
-
- void defer_on_off(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
+ struct OnOffValidator {
+ void operator()(unsigned long ulOnOff) const
+ {
+ eax_validate_range<Exception>(
+ "On-Off",
+ ulOnOff,
+ EAXAGCCOMPRESSOR_MINONOFF,
+ EAXAGCCOMPRESSOR_MAXONOFF);
+ }
+ }; // OnOffValidator
+
+ struct AllValidator {
+ void operator()(const Props& all) const
+ {
+ OnOffValidator{}(all.ulOnOff);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& props) override;
+
+ void set_efx_on_off() 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;
}; // EaxCompressorEffect
+EaxCompressorEffect::EaxCompressorEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_COMPRESSOR, call}
+{}
-class EaxCompressorEffectException :
- public EaxException
+void EaxCompressorEffect::set_defaults(Props& props)
{
-public:
- explicit EaxCompressorEffectException(
- const char* message)
- :
- EaxException{"EAX_COMPRESSOR_EFFECT", message}
- {
- }
-}; // EaxCompressorEffectException
-
-
-EaxCompressorEffect::EaxCompressorEffect()
- : EaxEffect{AL_EFFECT_COMPRESSOR}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-// [[nodiscard]]
-void EaxCompressorEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxCompressorEffect::set_eax_defaults()
-{
- eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
-
- eax_d_ = eax_;
+ props.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
}
-void EaxCompressorEffect::set_efx_on_off()
+void EaxCompressorEffect::set_efx_on_off() noexcept
{
const auto on_off = clamp(
- static_cast<ALint>(eax_.ulOnOff),
+ static_cast<ALint>(props_.ulOnOff),
AL_COMPRESSOR_MIN_ONOFF,
AL_COMPRESSOR_MAX_ONOFF);
-
al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE);
}
@@ -177,120 +145,46 @@ void EaxCompressorEffect::set_efx_defaults()
set_efx_on_off();
}
-void EaxCompressorEffect::get(const EaxEaxCall& eax_call)
+void EaxCompressorEffect::get(const EaxCall& call, const Props& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case EAXAGCCOMPRESSOR_NONE:
- break;
-
- case EAXAGCCOMPRESSOR_ALLPARAMETERS:
- eax_call.set_value<EaxCompressorEffectException>(eax_);
- break;
-
- case EAXAGCCOMPRESSOR_ONOFF:
- eax_call.set_value<EaxCompressorEffectException>(eax_.ulOnOff);
- break;
-
- default:
- throw EaxCompressorEffectException{"Unsupported property id."};
+ case EAXAGCCOMPRESSOR_NONE: break;
+ case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXAGCCOMPRESSOR_ONOFF: call.set_value<Exception>(props.ulOnOff); break;
+ default: fail_unknown_property_id();
}
}
-void EaxCompressorEffect::validate_on_off(
- unsigned long ulOnOff)
-{
- eax_validate_range<EaxCompressorEffectException>(
- "On-Off",
- ulOnOff,
- EAXAGCCOMPRESSOR_MINONOFF,
- EAXAGCCOMPRESSOR_MAXONOFF);
-}
-
-void EaxCompressorEffect::validate_all(
- const EAXAGCCOMPRESSORPROPERTIES& eax_all)
+void EaxCompressorEffect::set(const EaxCall& call, Props& props)
{
- validate_on_off(eax_all.ulOnOff);
-}
-
-void EaxCompressorEffect::defer_on_off(
- unsigned long ulOnOff)
-{
- eax_d_.ulOnOff = ulOnOff;
- eax_dirty_flags_.ulOnOff = (eax_.ulOnOff != eax_d_.ulOnOff);
-}
-
-void EaxCompressorEffect::defer_all(
- const EAXAGCCOMPRESSORPROPERTIES& eax_all)
-{
- defer_on_off(eax_all.ulOnOff);
-}
-
-void EaxCompressorEffect::defer_on_off(
- const EaxEaxCall& eax_call)
-{
- const auto& on_off =
- eax_call.get_value<EaxCompressorEffectException, const decltype(EAXAGCCOMPRESSORPROPERTIES::ulOnOff)>();
-
- validate_on_off(on_off);
- defer_on_off(on_off);
-}
-
-void EaxCompressorEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxCompressorEffectException, const EAXAGCCOMPRESSORPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxCompressorEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxCompressorEffectDirtyFlags{})
+ switch(call.get_property_id())
{
- return false;
+ case EAXAGCCOMPRESSOR_NONE: break;
+ case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXAGCCOMPRESSOR_ONOFF: defer<OnOffValidator>(call, props.ulOnOff); break;
+ default: fail_unknown_property_id();
}
+}
- eax_ = eax_d_;
+bool EaxCompressorEffect::commit_props(const Props& props)
+{
+ auto is_dirty = false;
- if (eax_dirty_flags_.ulOnOff)
+ if (props_.ulOnOff != props.ulOnOff)
{
+ is_dirty = true;
set_efx_on_off();
}
- eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxCompressorEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
- {
- case EAXAGCCOMPRESSOR_NONE:
- break;
-
- case EAXAGCCOMPRESSOR_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXAGCCOMPRESSOR_ONOFF:
- defer_on_off(eax_call);
- break;
-
- default:
- throw EaxCompressorEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-EaxEffectUPtr eax_create_eax_compressor_effect()
+EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call)
{
- return std::make_unique<EaxCompressorEffect>();
+ return eax_create_eax4_effect<EaxCompressorEffect>(call);
}
#endif // ALSOFT_EAX
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
diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp
index 56849b9d..f25c94bf 100644
--- a/al/effects/echo.cpp
+++ b/al/effects/echo.cpp
@@ -9,7 +9,6 @@
#ifdef ALSOFT_EAX
#include "alnumeric.h"
-
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -120,157 +119,151 @@ const EffectProps EchoEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxEchoEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxEchoEffectDirtyFlags
+class EaxEchoEffectException : public EaxException
{
- using EaxIsBitFieldStruct = bool;
-
- EaxEchoEffectDirtyFlagsValue flDelay : 1;
- EaxEchoEffectDirtyFlagsValue flLRDelay : 1;
- EaxEchoEffectDirtyFlagsValue flDamping : 1;
- EaxEchoEffectDirtyFlagsValue flFeedback : 1;
- EaxEchoEffectDirtyFlagsValue flSpread : 1;
-}; // EaxEchoEffectDirtyFlags
-
+public:
+ explicit EaxEchoEffectException(const char* message)
+ : EaxException{"EAX_ECHO_EFFECT", message}
+ {}
+}; // EaxEchoEffectException
-class EaxEchoEffect final :
- public EaxEffect
+class EaxEchoEffect final : public EaxEffect4<EaxEchoEffectException, EAXECHOPROPERTIES>
{
public:
- EaxEchoEffect();
-
- void dispatch(const EaxEaxCall& eax_call) override;
-
- // [[nodiscard]]
- bool apply_deferred() override;
+ EaxEchoEffect(const EaxCall& call);
private:
- EAXECHOPROPERTIES eax_{};
- EAXECHOPROPERTIES eax_d_{};
- EaxEchoEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults();
-
- void set_efx_delay();
- void set_efx_lr_delay();
- void set_efx_damping();
- void set_efx_feedback();
- void set_efx_spread();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_delay(float flDelay);
- void validate_lr_delay(float flLRDelay);
- void validate_damping(float flDamping);
- void validate_feedback(float flFeedback);
- void validate_spread(float flSpread);
- void validate_all(const EAXECHOPROPERTIES& all);
-
- void defer_delay(float flDelay);
- void defer_lr_delay(float flLRDelay);
- void defer_damping(float flDamping);
- void defer_feedback(float flFeedback);
- void defer_spread(float flSpread);
- void defer_all(const EAXECHOPROPERTIES& all);
-
- void defer_delay(const EaxEaxCall& eax_call);
- void defer_lr_delay(const EaxEaxCall& eax_call);
- void defer_damping(const EaxEaxCall& eax_call);
- void defer_feedback(const EaxEaxCall& eax_call);
- void defer_spread(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
+ 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 Props& all) const
+ {
+ DelayValidator{}(all.flDelay);
+ LrDelayValidator{}(all.flLRDelay);
+ DampingValidator{}(all.flDamping);
+ FeedbackValidator{}(all.flFeedback);
+ SpreadValidator{}(all.flSpread);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& 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 Props& props) override;
+ void set(const EaxCall& call, Props& props) override;
+ bool commit_props(const Props& props) override;
}; // EaxEchoEffect
+EaxEchoEffect::EaxEchoEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_ECHO, call}
+{}
-class EaxEchoEffectException :
- public EaxException
-{
-public:
- explicit EaxEchoEffectException(
- const char* message)
- :
- EaxException{"EAX_ECHO_EFFECT", message}
- {
- }
-}; // EaxEchoEffectException
-
-
-EaxEchoEffect::EaxEchoEffect()
- : EaxEffect{AL_EFFECT_ECHO}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-void EaxEchoEffect::dispatch(
- const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxEchoEffect::set_eax_defaults()
+void EaxEchoEffect::set_defaults(Props& props)
{
- eax_.flDelay = EAXECHO_DEFAULTDELAY;
- eax_.flLRDelay = EAXECHO_DEFAULTLRDELAY;
- eax_.flDamping = EAXECHO_DEFAULTDAMPING;
- eax_.flFeedback = EAXECHO_DEFAULTFEEDBACK;
- eax_.flSpread = EAXECHO_DEFAULTSPREAD;
-
- eax_d_ = eax_;
+ props.flDelay = EAXECHO_DEFAULTDELAY;
+ props.flLRDelay = EAXECHO_DEFAULTLRDELAY;
+ props.flDamping = EAXECHO_DEFAULTDAMPING;
+ props.flFeedback = EAXECHO_DEFAULTFEEDBACK;
+ props.flSpread = EAXECHO_DEFAULTSPREAD;
}
-void EaxEchoEffect::set_efx_delay()
+void EaxEchoEffect::set_efx_delay() noexcept
{
- const auto delay = clamp(
- eax_.flDelay,
+ al_effect_props_.Echo.Delay = clamp(
+ props_.flDelay,
AL_ECHO_MIN_DELAY,
AL_ECHO_MAX_DELAY);
-
- al_effect_props_.Echo.Delay = delay;
}
-void EaxEchoEffect::set_efx_lr_delay()
+void EaxEchoEffect::set_efx_lr_delay() noexcept
{
- const auto lr_delay = clamp(
- eax_.flLRDelay,
+ al_effect_props_.Echo.LRDelay = clamp(
+ props_.flLRDelay,
AL_ECHO_MIN_LRDELAY,
AL_ECHO_MAX_LRDELAY);
-
- al_effect_props_.Echo.LRDelay = lr_delay;
}
-void EaxEchoEffect::set_efx_damping()
+void EaxEchoEffect::set_efx_damping() noexcept
{
- const auto damping = clamp(
- eax_.flDamping,
+ al_effect_props_.Echo.Damping = clamp(
+ props_.flDamping,
AL_ECHO_MIN_DAMPING,
AL_ECHO_MAX_DAMPING);
-
- al_effect_props_.Echo.Damping = damping;
}
-void EaxEchoEffect::set_efx_feedback()
+void EaxEchoEffect::set_efx_feedback() noexcept
{
- const auto feedback = clamp(
- eax_.flFeedback,
+ al_effect_props_.Echo.Feedback = clamp(
+ props_.flFeedback,
AL_ECHO_MIN_FEEDBACK,
AL_ECHO_MAX_FEEDBACK);
-
- al_effect_props_.Echo.Feedback = feedback;
}
-void EaxEchoEffect::set_efx_spread()
+void EaxEchoEffect::set_efx_spread() noexcept
{
- const auto spread = clamp(
- eax_.flSpread,
+ al_effect_props_.Echo.Spread = clamp(
+ props_.flSpread,
AL_ECHO_MIN_SPREAD,
AL_ECHO_MAX_SPREAD);
-
- al_effect_props_.Echo.Spread = spread;
}
void EaxEchoEffect::set_efx_defaults()
@@ -282,288 +275,78 @@ void EaxEchoEffect::set_efx_defaults()
set_efx_spread();
}
-void EaxEchoEffect::get(const EaxEaxCall& eax_call)
+void EaxEchoEffect::get(const EaxCall& call, const Props& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case EAXECHO_NONE:
- break;
-
- case EAXECHO_ALLPARAMETERS:
- eax_call.set_value<EaxEchoEffectException>(eax_);
- break;
-
- case EAXECHO_DELAY:
- eax_call.set_value<EaxEchoEffectException>(eax_.flDelay);
- break;
-
- case EAXECHO_LRDELAY:
- eax_call.set_value<EaxEchoEffectException>(eax_.flLRDelay);
- break;
-
- case EAXECHO_DAMPING:
- eax_call.set_value<EaxEchoEffectException>(eax_.flDamping);
- break;
-
- case EAXECHO_FEEDBACK:
- eax_call.set_value<EaxEchoEffectException>(eax_.flFeedback);
- break;
-
- case EAXECHO_SPREAD:
- eax_call.set_value<EaxEchoEffectException>(eax_.flSpread);
- break;
-
- default:
- throw EaxEchoEffectException{"Unsupported property id."};
+ case EAXECHO_NONE: break;
+ case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXECHO_DELAY: call.set_value<Exception>(props.flDelay); break;
+ case EAXECHO_LRDELAY: call.set_value<Exception>(props.flLRDelay); break;
+ case EAXECHO_DAMPING: call.set_value<Exception>(props.flDamping); break;
+ case EAXECHO_FEEDBACK: call.set_value<Exception>(props.flFeedback); break;
+ case EAXECHO_SPREAD: call.set_value<Exception>(props.flSpread); break;
+ default: fail_unknown_property_id();
}
}
-void EaxEchoEffect::validate_delay(
- float flDelay)
-{
- eax_validate_range<EaxEchoEffectException>(
- "Delay",
- flDelay,
- EAXECHO_MINDELAY,
- EAXECHO_MAXDELAY);
-}
-
-void EaxEchoEffect::validate_lr_delay(
- float flLRDelay)
-{
- eax_validate_range<EaxEchoEffectException>(
- "LR Delay",
- flLRDelay,
- EAXECHO_MINLRDELAY,
- EAXECHO_MAXLRDELAY);
-}
-
-void EaxEchoEffect::validate_damping(
- float flDamping)
-{
- eax_validate_range<EaxEchoEffectException>(
- "Damping",
- flDamping,
- EAXECHO_MINDAMPING,
- EAXECHO_MAXDAMPING);
-}
-
-void EaxEchoEffect::validate_feedback(
- float flFeedback)
-{
- eax_validate_range<EaxEchoEffectException>(
- "Feedback",
- flFeedback,
- EAXECHO_MINFEEDBACK,
- EAXECHO_MAXFEEDBACK);
-}
-
-void EaxEchoEffect::validate_spread(
- float flSpread)
-{
- eax_validate_range<EaxEchoEffectException>(
- "Spread",
- flSpread,
- EAXECHO_MINSPREAD,
- EAXECHO_MAXSPREAD);
-}
-
-void EaxEchoEffect::validate_all(
- const EAXECHOPROPERTIES& all)
-{
- validate_delay(all.flDelay);
- validate_lr_delay(all.flLRDelay);
- validate_damping(all.flDamping);
- validate_feedback(all.flFeedback);
- validate_spread(all.flSpread);
-}
-
-void EaxEchoEffect::defer_delay(
- float flDelay)
-{
- eax_d_.flDelay = flDelay;
- eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay);
-}
-
-void EaxEchoEffect::defer_lr_delay(
- float flLRDelay)
+void EaxEchoEffect::set(const EaxCall& call, Props& props)
{
- eax_d_.flLRDelay = flLRDelay;
- eax_dirty_flags_.flLRDelay = (eax_.flLRDelay != eax_d_.flLRDelay);
-}
-
-void EaxEchoEffect::defer_damping(
- float flDamping)
-{
- eax_d_.flDamping = flDamping;
- eax_dirty_flags_.flDamping = (eax_.flDamping != eax_d_.flDamping);
-}
-
-void EaxEchoEffect::defer_feedback(
- float flFeedback)
-{
- eax_d_.flFeedback = flFeedback;
- eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback);
-}
-
-void EaxEchoEffect::defer_spread(
- float flSpread)
-{
- eax_d_.flSpread = flSpread;
- eax_dirty_flags_.flSpread = (eax_.flSpread != eax_d_.flSpread);
-}
-
-void EaxEchoEffect::defer_all(
- const EAXECHOPROPERTIES& all)
-{
- defer_delay(all.flDelay);
- defer_lr_delay(all.flLRDelay);
- defer_damping(all.flDamping);
- defer_feedback(all.flFeedback);
- defer_spread(all.flSpread);
-}
-
-void EaxEchoEffect::defer_delay(
- const EaxEaxCall& eax_call)
-{
- const auto& delay =
- eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flDelay)>();
-
- validate_delay(delay);
- defer_delay(delay);
-}
-
-void EaxEchoEffect::defer_lr_delay(
- const EaxEaxCall& eax_call)
-{
- const auto& lr_delay =
- eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flLRDelay)>();
-
- validate_lr_delay(lr_delay);
- defer_lr_delay(lr_delay);
-}
-
-void EaxEchoEffect::defer_damping(
- const EaxEaxCall& eax_call)
-{
- const auto& damping =
- eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flDamping)>();
-
- validate_damping(damping);
- defer_damping(damping);
-}
-
-void EaxEchoEffect::defer_feedback(
- const EaxEaxCall& eax_call)
-{
- const auto& feedback =
- eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flFeedback)>();
-
- validate_feedback(feedback);
- defer_feedback(feedback);
-}
-
-void EaxEchoEffect::defer_spread(
- const EaxEaxCall& eax_call)
-{
- const auto& spread =
- eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flSpread)>();
-
- validate_spread(spread);
- defer_spread(spread);
-}
-
-void EaxEchoEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxEchoEffectException, const EAXECHOPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxEchoEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxEchoEffectDirtyFlags{})
+ switch(call.get_property_id())
{
- return false;
+ case EAXECHO_NONE: break;
+ case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXECHO_DELAY: defer<DelayValidator>(call, props.flDelay); break;
+ case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.flLRDelay); break;
+ case EAXECHO_DAMPING: defer<DampingValidator>(call, props.flDamping); break;
+ case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.flFeedback); break;
+ case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.flSpread); break;
+ default: fail_unknown_property_id();
}
+}
- eax_ = eax_d_;
+bool EaxEchoEffect::commit_props(const Props& props)
+{
+ auto is_dirty = false;
- if (eax_dirty_flags_.flDelay)
+ if (props_.flDelay != props.flDelay)
{
+ is_dirty = true;
set_efx_delay();
}
- if (eax_dirty_flags_.flLRDelay)
+ if (props_.flLRDelay != props.flLRDelay)
{
+ is_dirty = true;
set_efx_lr_delay();
}
- if (eax_dirty_flags_.flDamping)
+ if (props_.flDamping != props.flDamping)
{
+ is_dirty = true;
set_efx_damping();
}
- if (eax_dirty_flags_.flFeedback)
+ if (props_.flFeedback != props.flFeedback)
{
+ is_dirty = true;
set_efx_feedback();
}
- if (eax_dirty_flags_.flSpread)
+ if (props_.flSpread != props.flSpread)
{
+ is_dirty = true;
set_efx_spread();
}
- eax_dirty_flags_ = EaxEchoEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxEchoEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
- {
- case EAXECHO_NONE:
- break;
-
- case EAXECHO_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXECHO_DELAY:
- defer_delay(eax_call);
- break;
-
- case EAXECHO_LRDELAY:
- defer_lr_delay(eax_call);
- break;
-
- case EAXECHO_DAMPING:
- defer_damping(eax_call);
- break;
-
- case EAXECHO_FEEDBACK:
- defer_feedback(eax_call);
- break;
-
- case EAXECHO_SPREAD:
- defer_spread(eax_call);
- break;
-
- default:
- throw EaxEchoEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-EaxEffectUPtr eax_create_eax_echo_effect()
+EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call)
{
- return std::make_unique<EaxEchoEffect>();
+ return eax_create_eax4_effect<EaxEchoEffect>(call);
}
#endif // ALSOFT_EAX
diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp
index faf322d2..e4e61231 100644
--- a/al/effects/effects.cpp
+++ b/al/effects/effects.cpp
@@ -10,7 +10,7 @@
#include "AL/efx.h"
-EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type)
+EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call)
{
#define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] "
@@ -20,40 +20,40 @@ EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type)
return eax_create_eax_null_effect();
case AL_EFFECT_CHORUS:
- return eax_create_eax_chorus_effect();
+ return eax_create_eax_chorus_effect(call);
case AL_EFFECT_DISTORTION:
- return eax_create_eax_distortion_effect();
+ return eax_create_eax_distortion_effect(call);
case AL_EFFECT_ECHO:
- return eax_create_eax_echo_effect();
+ return eax_create_eax_echo_effect(call);
case AL_EFFECT_FLANGER:
- return eax_create_eax_flanger_effect();
+ return eax_create_eax_flanger_effect(call);
case AL_EFFECT_FREQUENCY_SHIFTER:
- return eax_create_eax_frequency_shifter_effect();
+ return eax_create_eax_frequency_shifter_effect(call);
case AL_EFFECT_VOCAL_MORPHER:
- return eax_create_eax_vocal_morpher_effect();
+ return eax_create_eax_vocal_morpher_effect(call);
case AL_EFFECT_PITCH_SHIFTER:
- return eax_create_eax_pitch_shifter_effect();
+ return eax_create_eax_pitch_shifter_effect(call);
case AL_EFFECT_RING_MODULATOR:
- return eax_create_eax_ring_modulator_effect();
+ return eax_create_eax_ring_modulator_effect(call);
case AL_EFFECT_AUTOWAH:
- return eax_create_eax_auto_wah_effect();
+ return eax_create_eax_auto_wah_effect(call);
case AL_EFFECT_COMPRESSOR:
- return eax_create_eax_compressor_effect();
+ return eax_create_eax_compressor_effect(call);
case AL_EFFECT_EQUALIZER:
- return eax_create_eax_equalizer_effect();
+ return eax_create_eax_equalizer_effect(call);
case AL_EFFECT_EAXREVERB:
- return eax_create_eax_reverb_effect();
+ return eax_create_eax_reverb_effect(call);
default:
assert(false && "Unsupported AL effect type.");
diff --git a/al/effects/effects.h b/al/effects/effects.h
index f8b97eeb..164c0d19 100644
--- a/al/effects/effects.h
+++ b/al/effects/effects.h
@@ -6,6 +6,7 @@
#include "core/except.h"
#ifdef ALSOFT_EAX
+#include "al/eax/call.h"
#include "al/eax/effect.h"
#endif // ALSOFT_EAX
@@ -86,7 +87,7 @@ extern const EffectVtable ConvolutionEffectVtable;
#ifdef ALSOFT_EAX
-EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type);
+EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call);
#endif // ALSOFT_EAX
#endif /* AL_EFFECTS_EFFECTS_H */
diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp
index ccc00f67..80dd1c4b 100644
--- a/al/effects/equalizer.cpp
+++ b/al/effects/equalizer.cpp
@@ -9,7 +9,6 @@
#ifdef ALSOFT_EAX
#include "alnumeric.h"
-
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -178,236 +177,261 @@ const EffectProps EqualizerEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t;
-
-struct EaxEqualizerEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxEqualizerEffectDirtyFlagsValue lLowGain : 1;
- EaxEqualizerEffectDirtyFlagsValue flLowCutOff : 1;
- EaxEqualizerEffectDirtyFlagsValue lMid1Gain : 1;
- EaxEqualizerEffectDirtyFlagsValue flMid1Center : 1;
- EaxEqualizerEffectDirtyFlagsValue flMid1Width : 1;
- EaxEqualizerEffectDirtyFlagsValue lMid2Gain : 1;
- EaxEqualizerEffectDirtyFlagsValue flMid2Center : 1;
- EaxEqualizerEffectDirtyFlagsValue flMid2Width : 1;
- EaxEqualizerEffectDirtyFlagsValue lHighGain : 1;
- EaxEqualizerEffectDirtyFlagsValue flHighCutOff : 1;
-}; // EaxEqualizerEffectDirtyFlags
-
-
-class EaxEqualizerEffect final :
- public EaxEffect
+class EaxEqualizerEffectException : public EaxException
{
public:
- EaxEqualizerEffect();
-
- void dispatch(const EaxEaxCall& eax_call) override;
-
- // [[nodiscard]]
- bool apply_deferred() override;
-
-private:
- EAXEQUALIZERPROPERTIES eax_{};
- EAXEQUALIZERPROPERTIES eax_d_{};
- EaxEqualizerEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults();
-
- void set_efx_low_gain();
- void set_efx_low_cutoff();
- void set_efx_mid1_gain();
- void set_efx_mid1_center();
- void set_efx_mid1_width();
- void set_efx_mid2_gain();
- void set_efx_mid2_center();
- void set_efx_mid2_width();
- void set_efx_high_gain();
- void set_efx_high_cutoff();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_low_gain(long lLowGain);
- void validate_low_cutoff(float flLowCutOff);
- void validate_mid1_gain(long lMid1Gain);
- void validate_mid1_center(float flMid1Center);
- void validate_mid1_width(float flMid1Width);
- void validate_mid2_gain(long lMid2Gain);
- void validate_mid2_center(float flMid2Center);
- void validate_mid2_width(float flMid2Width);
- void validate_high_gain(long lHighGain);
- void validate_high_cutoff(float flHighCutOff);
- void validate_all(const EAXEQUALIZERPROPERTIES& all);
-
- void defer_low_gain(long lLowGain);
- void defer_low_cutoff(float flLowCutOff);
- void defer_mid1_gain(long lMid1Gain);
- void defer_mid1_center(float flMid1Center);
- void defer_mid1_width(float flMid1Width);
- void defer_mid2_gain(long lMid2Gain);
- void defer_mid2_center(float flMid2Center);
- void defer_mid2_width(float flMid2Width);
- void defer_high_gain(long lHighGain);
- void defer_high_cutoff(float flHighCutOff);
- void defer_all(const EAXEQUALIZERPROPERTIES& all);
-
- void defer_low_gain(const EaxEaxCall& eax_call);
- void defer_low_cutoff(const EaxEaxCall& eax_call);
- void defer_mid1_gain(const EaxEaxCall& eax_call);
- void defer_mid1_center(const EaxEaxCall& eax_call);
- void defer_mid1_width(const EaxEaxCall& eax_call);
- void defer_mid2_gain(const EaxEaxCall& eax_call);
- void defer_mid2_center(const EaxEaxCall& eax_call);
- void defer_mid2_width(const EaxEaxCall& eax_call);
- void defer_high_gain(const EaxEaxCall& eax_call);
- void defer_high_cutoff(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
-}; // EaxEqualizerEffect
-
+ explicit EaxEqualizerEffectException(const char* message)
+ : EaxException{"EAX_EQUALIZER_EFFECT", message}
+ {}
+}; // EaxEqualizerEffectException
-class EaxEqualizerEffectException :
- public EaxException
+class EaxEqualizerEffect final : public EaxEffect4<EaxEqualizerEffectException, EAXEQUALIZERPROPERTIES>
{
public:
- explicit EaxEqualizerEffectException(
- const char* message)
- :
- EaxException{"EAX_EQUALIZER_EFFECT", message}
- {
- }
-}; // EaxEqualizerEffectException
-
+ EaxEqualizerEffect(const EaxCall& call);
-EaxEqualizerEffect::EaxEqualizerEffect()
- : EaxEffect{AL_EFFECT_EQUALIZER}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
+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 Props& 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(Props& 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 Props& props) override;
+ void set(const EaxCall& call, Props& props) override;
+ bool commit_props(const Props& props) override;
+}; // EaxEqualizerEffect
-void EaxEqualizerEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
+EaxEqualizerEffect::EaxEqualizerEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_EQUALIZER, call}
+{}
-void EaxEqualizerEffect::set_eax_defaults()
+void EaxEqualizerEffect::set_defaults(Props& props)
{
- eax_.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
- eax_.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
- eax_.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
- eax_.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
- eax_.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
- eax_.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
- eax_.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
- eax_.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
- eax_.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
- eax_.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
-
- eax_d_ = eax_;
+ props.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
+ props.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
+ props.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
+ props.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
+ props.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
+ props.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
+ props.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
+ props.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
+ props.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
+ props.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
}
-void EaxEqualizerEffect::set_efx_low_gain()
+void EaxEqualizerEffect::set_efx_low_gain() noexcept
{
- const auto low_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lLowGain)),
+ al_effect_props_.Equalizer.LowGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lLowGain)),
AL_EQUALIZER_MIN_LOW_GAIN,
AL_EQUALIZER_MAX_LOW_GAIN);
-
- al_effect_props_.Equalizer.LowGain = low_gain;
}
-void EaxEqualizerEffect::set_efx_low_cutoff()
+void EaxEqualizerEffect::set_efx_low_cutoff() noexcept
{
- const auto low_cutoff = clamp(
- eax_.flLowCutOff,
+ al_effect_props_.Equalizer.LowCutoff = clamp(
+ props_.flLowCutOff,
AL_EQUALIZER_MIN_LOW_CUTOFF,
AL_EQUALIZER_MAX_LOW_CUTOFF);
-
- al_effect_props_.Equalizer.LowCutoff = low_cutoff;
}
-void EaxEqualizerEffect::set_efx_mid1_gain()
+void EaxEqualizerEffect::set_efx_mid1_gain() noexcept
{
- const auto mid1_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lMid1Gain)),
+ al_effect_props_.Equalizer.Mid1Gain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lMid1Gain)),
AL_EQUALIZER_MIN_MID1_GAIN,
AL_EQUALIZER_MAX_MID1_GAIN);
-
- al_effect_props_.Equalizer.Mid1Gain = mid1_gain;
}
-void EaxEqualizerEffect::set_efx_mid1_center()
+void EaxEqualizerEffect::set_efx_mid1_center() noexcept
{
- const auto mid1_center = clamp(
- eax_.flMid1Center,
+ al_effect_props_.Equalizer.Mid1Center = clamp(
+ props_.flMid1Center,
AL_EQUALIZER_MIN_MID1_CENTER,
AL_EQUALIZER_MAX_MID1_CENTER);
-
- al_effect_props_.Equalizer.Mid1Center = mid1_center;
}
-void EaxEqualizerEffect::set_efx_mid1_width()
+void EaxEqualizerEffect::set_efx_mid1_width() noexcept
{
- const auto mid1_width = clamp(
- eax_.flMid1Width,
+ al_effect_props_.Equalizer.Mid1Width = clamp(
+ props_.flMid1Width,
AL_EQUALIZER_MIN_MID1_WIDTH,
AL_EQUALIZER_MAX_MID1_WIDTH);
-
- al_effect_props_.Equalizer.Mid1Width = mid1_width;
}
-void EaxEqualizerEffect::set_efx_mid2_gain()
+void EaxEqualizerEffect::set_efx_mid2_gain() noexcept
{
- const auto mid2_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lMid2Gain)),
+ al_effect_props_.Equalizer.Mid2Gain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lMid2Gain)),
AL_EQUALIZER_MIN_MID2_GAIN,
AL_EQUALIZER_MAX_MID2_GAIN);
-
- al_effect_props_.Equalizer.Mid2Gain = mid2_gain;
}
-void EaxEqualizerEffect::set_efx_mid2_center()
+void EaxEqualizerEffect::set_efx_mid2_center() noexcept
{
- const auto mid2_center = clamp(
- eax_.flMid2Center,
+ al_effect_props_.Equalizer.Mid2Center = clamp(
+ props_.flMid2Center,
AL_EQUALIZER_MIN_MID2_CENTER,
AL_EQUALIZER_MAX_MID2_CENTER);
-
- al_effect_props_.Equalizer.Mid2Center = mid2_center;
}
-void EaxEqualizerEffect::set_efx_mid2_width()
+void EaxEqualizerEffect::set_efx_mid2_width() noexcept
{
- const auto mid2_width = clamp(
- eax_.flMid2Width,
+ al_effect_props_.Equalizer.Mid2Width = clamp(
+ props_.flMid2Width,
AL_EQUALIZER_MIN_MID2_WIDTH,
AL_EQUALIZER_MAX_MID2_WIDTH);
-
- al_effect_props_.Equalizer.Mid2Width = mid2_width;
}
-void EaxEqualizerEffect::set_efx_high_gain()
+void EaxEqualizerEffect::set_efx_high_gain() noexcept
{
- const auto high_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lHighGain)),
+ al_effect_props_.Equalizer.HighGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lHighGain)),
AL_EQUALIZER_MIN_HIGH_GAIN,
AL_EQUALIZER_MAX_HIGH_GAIN);
-
- al_effect_props_.Equalizer.HighGain = high_gain;
}
-void EaxEqualizerEffect::set_efx_high_cutoff()
+void EaxEqualizerEffect::set_efx_high_cutoff() noexcept
{
- const auto high_cutoff = clamp(
- eax_.flHighCutOff,
+ al_effect_props_.Equalizer.HighCutoff = clamp(
+ props_.flHighCutOff,
AL_EQUALIZER_MIN_HIGH_CUTOFF,
AL_EQUALIZER_MAX_HIGH_CUTOFF);
-
- al_effect_props_.Equalizer.HighCutoff = high_cutoff;
}
void EaxEqualizerEffect::set_efx_defaults()
@@ -424,498 +448,118 @@ void EaxEqualizerEffect::set_efx_defaults()
set_efx_high_cutoff();
}
-void EaxEqualizerEffect::get(const EaxEaxCall& eax_call)
+void EaxEqualizerEffect::get(const EaxCall& call, const Props& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case EAXEQUALIZER_NONE:
- break;
-
- case EAXEQUALIZER_ALLPARAMETERS:
- eax_call.set_value<EaxEqualizerEffectException>(eax_);
- break;
-
- case EAXEQUALIZER_LOWGAIN:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.lLowGain);
- break;
-
- case EAXEQUALIZER_LOWCUTOFF:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.flLowCutOff);
- break;
-
- case EAXEQUALIZER_MID1GAIN:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid1Gain);
- break;
-
- case EAXEQUALIZER_MID1CENTER:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Center);
- break;
-
- case EAXEQUALIZER_MID1WIDTH:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Width);
- break;
-
- case EAXEQUALIZER_MID2GAIN:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid2Gain);
- break;
-
- case EAXEQUALIZER_MID2CENTER:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Center);
- break;
-
- case EAXEQUALIZER_MID2WIDTH:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Width);
- break;
-
- case EAXEQUALIZER_HIGHGAIN:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.lHighGain);
- break;
-
- case EAXEQUALIZER_HIGHCUTOFF:
- eax_call.set_value<EaxEqualizerEffectException>(eax_.flHighCutOff);
- break;
-
- default:
- throw EaxEqualizerEffectException{"Unsupported property id."};
+ case EAXEQUALIZER_NONE: break;
+ case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.lLowGain); break;
+ case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.flLowCutOff); break;
+ case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.lMid1Gain); break;
+ case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.flMid1Center); break;
+ case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.flMid1Width); break;
+ case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.lMid2Gain); break;
+ case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.flMid2Center); break;
+ case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.flMid2Width); break;
+ case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.lHighGain); break;
+ case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.flHighCutOff); break;
+ default: fail_unknown_property_id();
}
}
-void EaxEqualizerEffect::validate_low_gain(
- long lLowGain)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Low Gain",
- lLowGain,
- EAXEQUALIZER_MINLOWGAIN,
- EAXEQUALIZER_MAXLOWGAIN);
-}
-
-void EaxEqualizerEffect::validate_low_cutoff(
- float flLowCutOff)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Low Cutoff",
- flLowCutOff,
- EAXEQUALIZER_MINLOWCUTOFF,
- EAXEQUALIZER_MAXLOWCUTOFF);
-}
-
-void EaxEqualizerEffect::validate_mid1_gain(
- long lMid1Gain)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Mid1 Gain",
- lMid1Gain,
- EAXEQUALIZER_MINMID1GAIN,
- EAXEQUALIZER_MAXMID1GAIN);
-}
-
-void EaxEqualizerEffect::validate_mid1_center(
- float flMid1Center)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Mid1 Center",
- flMid1Center,
- EAXEQUALIZER_MINMID1CENTER,
- EAXEQUALIZER_MAXMID1CENTER);
-}
-
-void EaxEqualizerEffect::validate_mid1_width(
- float flMid1Width)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Mid1 Width",
- flMid1Width,
- EAXEQUALIZER_MINMID1WIDTH,
- EAXEQUALIZER_MAXMID1WIDTH);
-}
-
-void EaxEqualizerEffect::validate_mid2_gain(
- long lMid2Gain)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Mid2 Gain",
- lMid2Gain,
- EAXEQUALIZER_MINMID2GAIN,
- EAXEQUALIZER_MAXMID2GAIN);
-}
-
-void EaxEqualizerEffect::validate_mid2_center(
- float flMid2Center)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Mid2 Center",
- flMid2Center,
- EAXEQUALIZER_MINMID2CENTER,
- EAXEQUALIZER_MAXMID2CENTER);
-}
-
-void EaxEqualizerEffect::validate_mid2_width(
- float flMid2Width)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "Mid2 Width",
- flMid2Width,
- EAXEQUALIZER_MINMID2WIDTH,
- EAXEQUALIZER_MAXMID2WIDTH);
-}
-
-void EaxEqualizerEffect::validate_high_gain(
- long lHighGain)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "High Gain",
- lHighGain,
- EAXEQUALIZER_MINHIGHGAIN,
- EAXEQUALIZER_MAXHIGHGAIN);
-}
-
-void EaxEqualizerEffect::validate_high_cutoff(
- float flHighCutOff)
-{
- eax_validate_range<EaxEqualizerEffectException>(
- "High Cutoff",
- flHighCutOff,
- EAXEQUALIZER_MINHIGHCUTOFF,
- EAXEQUALIZER_MAXHIGHCUTOFF);
-}
-
-void EaxEqualizerEffect::validate_all(
- const EAXEQUALIZERPROPERTIES& all)
-{
- validate_low_gain(all.lLowGain);
- validate_low_cutoff(all.flLowCutOff);
- validate_mid1_gain(all.lMid1Gain);
- validate_mid1_center(all.flMid1Center);
- validate_mid1_width(all.flMid1Width);
- validate_mid2_gain(all.lMid2Gain);
- validate_mid2_center(all.flMid2Center);
- validate_mid2_width(all.flMid2Width);
- validate_high_gain(all.lHighGain);
- validate_high_cutoff(all.flHighCutOff);
-}
-
-void EaxEqualizerEffect::defer_low_gain(
- long lLowGain)
-{
- eax_d_.lLowGain = lLowGain;
- eax_dirty_flags_.lLowGain = (eax_.lLowGain != eax_d_.lLowGain);
-}
-
-void EaxEqualizerEffect::defer_low_cutoff(
- float flLowCutOff)
-{
- eax_d_.flLowCutOff = flLowCutOff;
- eax_dirty_flags_.flLowCutOff = (eax_.flLowCutOff != eax_d_.flLowCutOff);
-}
-
-void EaxEqualizerEffect::defer_mid1_gain(
- long lMid1Gain)
-{
- eax_d_.lMid1Gain = lMid1Gain;
- eax_dirty_flags_.lMid1Gain = (eax_.lMid1Gain != eax_d_.lMid1Gain);
-}
-
-void EaxEqualizerEffect::defer_mid1_center(
- float flMid1Center)
-{
- eax_d_.flMid1Center = flMid1Center;
- eax_dirty_flags_.flMid1Center = (eax_.flMid1Center != eax_d_.flMid1Center);
-}
-
-void EaxEqualizerEffect::defer_mid1_width(
- float flMid1Width)
-{
- eax_d_.flMid1Width = flMid1Width;
- eax_dirty_flags_.flMid1Width = (eax_.flMid1Width != eax_d_.flMid1Width);
-}
-
-void EaxEqualizerEffect::defer_mid2_gain(
- long lMid2Gain)
-{
- eax_d_.lMid2Gain = lMid2Gain;
- eax_dirty_flags_.lMid2Gain = (eax_.lMid2Gain != eax_d_.lMid2Gain);
-}
-
-void EaxEqualizerEffect::defer_mid2_center(
- float flMid2Center)
-{
- eax_d_.flMid2Center = flMid2Center;
- eax_dirty_flags_.flMid2Center = (eax_.flMid2Center != eax_d_.flMid2Center);
-}
-
-void EaxEqualizerEffect::defer_mid2_width(
- float flMid2Width)
-{
- eax_d_.flMid2Width = flMid2Width;
- eax_dirty_flags_.flMid2Width = (eax_.flMid2Width != eax_d_.flMid2Width);
-}
-
-void EaxEqualizerEffect::defer_high_gain(
- long lHighGain)
-{
- eax_d_.lHighGain = lHighGain;
- eax_dirty_flags_.lHighGain = (eax_.lHighGain != eax_d_.lHighGain);
-}
-
-void EaxEqualizerEffect::defer_high_cutoff(
- float flHighCutOff)
-{
- eax_d_.flHighCutOff = flHighCutOff;
- eax_dirty_flags_.flHighCutOff = (eax_.flHighCutOff != eax_d_.flHighCutOff);
-}
-
-void EaxEqualizerEffect::defer_all(
- const EAXEQUALIZERPROPERTIES& all)
-{
- defer_low_gain(all.lLowGain);
- defer_low_cutoff(all.flLowCutOff);
- defer_mid1_gain(all.lMid1Gain);
- defer_mid1_center(all.flMid1Center);
- defer_mid1_width(all.flMid1Width);
- defer_mid2_gain(all.lMid2Gain);
- defer_mid2_center(all.flMid2Center);
- defer_mid2_width(all.flMid2Width);
- defer_high_gain(all.lHighGain);
- defer_high_cutoff(all.flHighCutOff);
-}
-
-void EaxEqualizerEffect::defer_low_gain(
- const EaxEaxCall& eax_call)
-{
- const auto& low_gain =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lLowGain)>();
-
- validate_low_gain(low_gain);
- defer_low_gain(low_gain);
-}
-
-void EaxEqualizerEffect::defer_low_cutoff(
- const EaxEaxCall& eax_call)
-{
- const auto& low_cutoff =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flLowCutOff)>();
-
- validate_low_cutoff(low_cutoff);
- defer_low_cutoff(low_cutoff);
-}
-
-void EaxEqualizerEffect::defer_mid1_gain(
- const EaxEaxCall& eax_call)
-{
- const auto& mid1_gain =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid1Gain)>();
-
- validate_mid1_gain(mid1_gain);
- defer_mid1_gain(mid1_gain);
-}
-
-void EaxEqualizerEffect::defer_mid1_center(
- const EaxEaxCall& eax_call)
-{
- const auto& mid1_center =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Center)>();
-
- validate_mid1_center(mid1_center);
- defer_mid1_center(mid1_center);
-}
-
-void EaxEqualizerEffect::defer_mid1_width(
- const EaxEaxCall& eax_call)
-{
- const auto& mid1_width =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Width)>();
-
- validate_mid1_width(mid1_width);
- defer_mid1_width(mid1_width);
-}
-
-void EaxEqualizerEffect::defer_mid2_gain(
- const EaxEaxCall& eax_call)
-{
- const auto& mid2_gain =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid2Gain)>();
-
- validate_mid2_gain(mid2_gain);
- defer_mid2_gain(mid2_gain);
-}
-
-void EaxEqualizerEffect::defer_mid2_center(
- const EaxEaxCall& eax_call)
-{
- const auto& mid2_center =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Center)>();
-
- validate_mid2_center(mid2_center);
- defer_mid2_center(mid2_center);
-}
-
-void EaxEqualizerEffect::defer_mid2_width(
- const EaxEaxCall& eax_call)
-{
- const auto& mid2_width =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Width)>();
-
- validate_mid2_width(mid2_width);
- defer_mid2_width(mid2_width);
-}
-
-void EaxEqualizerEffect::defer_high_gain(
- const EaxEaxCall& eax_call)
+void EaxEqualizerEffect::set(const EaxCall& call, Props& props)
{
- const auto& high_gain =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lHighGain)>();
-
- validate_high_gain(high_gain);
- defer_high_gain(high_gain);
-}
-
-void EaxEqualizerEffect::defer_high_cutoff(
- const EaxEaxCall& eax_call)
-{
- const auto& high_cutoff =
- eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flHighCutOff)>();
-
- validate_high_cutoff(high_cutoff);
- defer_high_cutoff(high_cutoff);
-}
-
-void EaxEqualizerEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxEqualizerEffectException, const EAXEQUALIZERPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxEqualizerEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxEqualizerEffectDirtyFlags{})
+ switch(call.get_property_id())
{
- return false;
+ case EAXEQUALIZER_NONE: break;
+ case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.lLowGain); break;
+ case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.flLowCutOff); break;
+ case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.lMid1Gain); break;
+ case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.flMid1Center); break;
+ case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.flMid1Width); break;
+ case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.lMid2Gain); break;
+ case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.flMid2Center); break;
+ case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.flMid2Width); break;
+ case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.lHighGain); break;
+ case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.flHighCutOff); break;
+ default: fail_unknown_property_id();
}
+}
- eax_ = eax_d_;
+bool EaxEqualizerEffect::commit_props(const Props& props)
+{
+ auto is_dirty = false;
- if (eax_dirty_flags_.lLowGain)
+ if (props_.lLowGain != props.lLowGain)
{
+ is_dirty = true;
set_efx_low_gain();
}
- if (eax_dirty_flags_.flLowCutOff)
+ if (props_.flLowCutOff != props.flLowCutOff)
{
+ is_dirty = true;
set_efx_low_cutoff();
}
- if (eax_dirty_flags_.lMid1Gain)
+ if (props_.lMid1Gain != props.lMid1Gain)
{
+ is_dirty = true;
set_efx_mid1_gain();
}
- if (eax_dirty_flags_.flMid1Center)
+ if (props_.flMid1Center != props.flMid1Center)
{
+ is_dirty = true;
set_efx_mid1_center();
}
- if (eax_dirty_flags_.flMid1Width)
+ if (props_.flMid1Width != props.flMid1Width)
{
+ is_dirty = true;
set_efx_mid1_width();
}
- if (eax_dirty_flags_.lMid2Gain)
+ if (props_.lMid2Gain != props.lMid2Gain)
{
+ is_dirty = true;
set_efx_mid2_gain();
}
- if (eax_dirty_flags_.flMid2Center)
+ if (props_.flMid2Center != props.flMid2Center)
{
+ is_dirty = true;
set_efx_mid2_center();
}
- if (eax_dirty_flags_.flMid2Width)
+ if (props_.flMid2Width != props.flMid2Width)
{
+ is_dirty = true;
set_efx_mid2_width();
}
- if (eax_dirty_flags_.lHighGain)
+ if (props_.lHighGain != props.lHighGain)
{
+ is_dirty = true;
set_efx_high_gain();
}
- if (eax_dirty_flags_.flHighCutOff)
+ if (props_.flHighCutOff != props.flHighCutOff)
{
+ is_dirty = true;
set_efx_high_cutoff();
}
- eax_dirty_flags_ = EaxEqualizerEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxEqualizerEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
- {
- case EAXEQUALIZER_NONE:
- break;
-
- case EAXEQUALIZER_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXEQUALIZER_LOWGAIN:
- defer_low_gain(eax_call);
- break;
-
- case EAXEQUALIZER_LOWCUTOFF:
- defer_low_cutoff(eax_call);
- break;
-
- case EAXEQUALIZER_MID1GAIN:
- defer_mid1_gain(eax_call);
- break;
-
- case EAXEQUALIZER_MID1CENTER:
- defer_mid1_center(eax_call);
- break;
-
- case EAXEQUALIZER_MID1WIDTH:
- defer_mid1_width(eax_call);
- break;
-
- case EAXEQUALIZER_MID2GAIN:
- defer_mid2_gain(eax_call);
- break;
-
- case EAXEQUALIZER_MID2CENTER:
- defer_mid2_center(eax_call);
- break;
-
- case EAXEQUALIZER_MID2WIDTH:
- defer_mid2_width(eax_call);
- break;
-
- case EAXEQUALIZER_HIGHGAIN:
- defer_high_gain(eax_call);
- break;
-
- case EAXEQUALIZER_HIGHCUTOFF:
- defer_high_cutoff(eax_call);
- break;
-
- default:
- throw EaxEqualizerEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-EaxEffectUPtr eax_create_eax_equalizer_effect()
+EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call)
{
- return std::make_unique<EaxEqualizerEffect>();
+ return eax_create_eax4_effect<EaxEqualizerEffect>(call);
}
#endif // ALSOFT_EAX
diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp
index 1ca97ecb..2b1710ad 100644
--- a/al/effects/fshifter.cpp
+++ b/al/effects/fshifter.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
@@ -141,113 +139,99 @@ const EffectProps FshifterEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxFrequencyShifterEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxFrequencyShifterEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxFrequencyShifterEffectDirtyFlagsValue flFrequency : 1;
- EaxFrequencyShifterEffectDirtyFlagsValue ulLeftDirection : 1;
- EaxFrequencyShifterEffectDirtyFlagsValue ulRightDirection : 1;
-}; // EaxFrequencyShifterEffectDirtyFlags
-
-
-class EaxFrequencyShifterEffect final :
- public EaxEffect
+class EaxFrequencyShifterEffectException : public EaxException
{
public:
- EaxFrequencyShifterEffect();
-
- void dispatch(const EaxEaxCall& eax_call) override;
+ explicit EaxFrequencyShifterEffectException(const char* message)
+ : EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
+ {}
+}; // EaxFrequencyShifterEffectException
- // [[nodiscard]]
- bool apply_deferred() override;
+class EaxFrequencyShifterEffect final : public EaxEffect4<EaxFrequencyShifterEffectException, EAXFREQUENCYSHIFTERPROPERTIES> {
+public:
+ EaxFrequencyShifterEffect(const EaxCall& call);
private:
- EAXFREQUENCYSHIFTERPROPERTIES eax_{};
- EAXFREQUENCYSHIFTERPROPERTIES eax_d_{};
- EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults();
-
- void set_efx_frequency();
+ struct FrequencyValidator {
+ void operator()(float flFrequency) const
+ {
+ eax_validate_range<Exception>(
+ "Frequency",
+ flFrequency,
+ EAXFREQUENCYSHIFTER_MINFREQUENCY,
+ EAXFREQUENCYSHIFTER_MAXFREQUENCY);
+ }
+ }; // FrequencyValidator
+
+ struct LeftDirectionValidator {
+ void operator()(unsigned long ulLeftDirection) const
+ {
+ eax_validate_range<Exception>(
+ "Left Direction",
+ ulLeftDirection,
+ EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
+ EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
+ }
+ }; // LeftDirectionValidator
+
+ struct RightDirectionValidator {
+ void operator()(unsigned long ulRightDirection) const
+ {
+ eax_validate_range<Exception>(
+ "Right Direction",
+ ulRightDirection,
+ EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
+ EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
+ }
+ }; // RightDirectionValidator
+
+ struct AllValidator {
+ void operator()(const Props& all) const
+ {
+ FrequencyValidator{}(all.flFrequency);
+ LeftDirectionValidator{}(all.ulLeftDirection);
+ RightDirectionValidator{}(all.ulRightDirection);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& props) override;
+
+ void set_efx_frequency() noexcept;
void set_efx_left_direction();
void set_efx_right_direction();
- void set_efx_defaults();
+ void set_efx_defaults() override;
- void get(const EaxEaxCall& eax_call);
-
- void validate_frequency(float flFrequency);
- void validate_left_direction(unsigned long ulLeftDirection);
- void validate_right_direction(unsigned long ulRightDirection);
- void validate_all(const EAXFREQUENCYSHIFTERPROPERTIES& all);
-
- void defer_frequency(float flFrequency);
- void defer_left_direction(unsigned long ulLeftDirection);
- void defer_right_direction(unsigned long ulRightDirection);
- void defer_all(const EAXFREQUENCYSHIFTERPROPERTIES& all);
-
- void defer_frequency(const EaxEaxCall& eax_call);
- void defer_left_direction(const EaxEaxCall& eax_call);
- void defer_right_direction(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;
}; // EaxFrequencyShifterEffect
-class EaxFrequencyShifterEffectException :
- public EaxException
-{
-public:
- explicit EaxFrequencyShifterEffectException(
- const char* message)
- :
- EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
- {
- }
-}; // EaxFrequencyShifterEffectException
+EaxFrequencyShifterEffect::EaxFrequencyShifterEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_FREQUENCY_SHIFTER, call}
+{}
-
-EaxFrequencyShifterEffect::EaxFrequencyShifterEffect()
- : EaxEffect{AL_EFFECT_FREQUENCY_SHIFTER}
+void EaxFrequencyShifterEffect::set_defaults(Props& props)
{
- set_eax_defaults();
- set_efx_defaults();
+ props.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
+ props.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
+ props.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
}
-void EaxFrequencyShifterEffect::dispatch(const EaxEaxCall& eax_call)
+void EaxFrequencyShifterEffect::set_efx_frequency() noexcept
{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxFrequencyShifterEffect::set_eax_defaults()
-{
- eax_.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
- eax_.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
- eax_.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
-
- eax_d_ = eax_;
-}
-
-void EaxFrequencyShifterEffect::set_efx_frequency()
-{
- const auto frequency = clamp(
- eax_.flFrequency,
+ al_effect_props_.Fshifter.Frequency = clamp(
+ props_.flFrequency,
AL_FREQUENCY_SHIFTER_MIN_FREQUENCY,
AL_FREQUENCY_SHIFTER_MAX_FREQUENCY);
-
- al_effect_props_.Fshifter.Frequency = frequency;
}
void EaxFrequencyShifterEffect::set_efx_left_direction()
{
const auto left_direction = clamp(
- static_cast<ALint>(eax_.ulLeftDirection),
+ static_cast<ALint>(props_.ulLeftDirection),
AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION,
AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION);
-
const auto efx_left_direction = DirectionFromEmum(left_direction);
assert(efx_left_direction.has_value());
al_effect_props_.Fshifter.LeftDirection = *efx_left_direction;
@@ -256,10 +240,9 @@ void EaxFrequencyShifterEffect::set_efx_left_direction()
void EaxFrequencyShifterEffect::set_efx_right_direction()
{
const auto right_direction = clamp(
- static_cast<ALint>(eax_.ulRightDirection),
+ static_cast<ALint>(props_.ulRightDirection),
AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION,
AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION);
-
const auto efx_right_direction = DirectionFromEmum(right_direction);
assert(efx_right_direction.has_value());
al_effect_props_.Fshifter.RightDirection = *efx_right_direction;
@@ -272,208 +255,62 @@ void EaxFrequencyShifterEffect::set_efx_defaults()
set_efx_right_direction();
}
-void EaxFrequencyShifterEffect::get(const EaxEaxCall& eax_call)
+void EaxFrequencyShifterEffect::get(const EaxCall& call, const Props& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case EAXFREQUENCYSHIFTER_NONE:
- break;
-
- case EAXFREQUENCYSHIFTER_ALLPARAMETERS:
- eax_call.set_value<EaxFrequencyShifterEffectException>(eax_);
- break;
-
- case EAXFREQUENCYSHIFTER_FREQUENCY:
- eax_call.set_value<EaxFrequencyShifterEffectException>(eax_.flFrequency);
- break;
-
- case EAXFREQUENCYSHIFTER_LEFTDIRECTION:
- eax_call.set_value<EaxFrequencyShifterEffectException>(eax_.ulLeftDirection);
- break;
-
- case EAXFREQUENCYSHIFTER_RIGHTDIRECTION:
- eax_call.set_value<EaxFrequencyShifterEffectException>(eax_.ulRightDirection);
- break;
-
- default:
- throw EaxFrequencyShifterEffectException{"Unsupported property id."};
+ case EAXFREQUENCYSHIFTER_NONE: break;
+ case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value<Exception>(props.flFrequency); break;
+ case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value<Exception>(props.ulLeftDirection); break;
+ case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value<Exception>(props.ulRightDirection); break;
+ default: fail_unknown_property_id();
}
}
-void EaxFrequencyShifterEffect::validate_frequency(
- float flFrequency)
-{
- eax_validate_range<EaxFrequencyShifterEffectException>(
- "Frequency",
- flFrequency,
- EAXFREQUENCYSHIFTER_MINFREQUENCY,
- EAXFREQUENCYSHIFTER_MAXFREQUENCY);
-}
-
-void EaxFrequencyShifterEffect::validate_left_direction(
- unsigned long ulLeftDirection)
-{
- eax_validate_range<EaxFrequencyShifterEffectException>(
- "Left Direction",
- ulLeftDirection,
- EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
- EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
-}
-
-void EaxFrequencyShifterEffect::validate_right_direction(
- unsigned long ulRightDirection)
-{
- eax_validate_range<EaxFrequencyShifterEffectException>(
- "Right Direction",
- ulRightDirection,
- EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
- EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
-}
-
-void EaxFrequencyShifterEffect::validate_all(
- const EAXFREQUENCYSHIFTERPROPERTIES& all)
-{
- validate_frequency(all.flFrequency);
- validate_left_direction(all.ulLeftDirection);
- validate_right_direction(all.ulRightDirection);
-}
-
-void EaxFrequencyShifterEffect::defer_frequency(
- float flFrequency)
-{
- eax_d_.flFrequency = flFrequency;
- eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency);
-}
-
-void EaxFrequencyShifterEffect::defer_left_direction(
- unsigned long ulLeftDirection)
-{
- eax_d_.ulLeftDirection = ulLeftDirection;
- eax_dirty_flags_.ulLeftDirection = (eax_.ulLeftDirection != eax_d_.ulLeftDirection);
-}
-
-void EaxFrequencyShifterEffect::defer_right_direction(
- unsigned long ulRightDirection)
+void EaxFrequencyShifterEffect::set(const EaxCall& call, Props& props)
{
- eax_d_.ulRightDirection = ulRightDirection;
- eax_dirty_flags_.ulRightDirection = (eax_.ulRightDirection != eax_d_.ulRightDirection);
-}
-
-void EaxFrequencyShifterEffect::defer_all(
- const EAXFREQUENCYSHIFTERPROPERTIES& all)
-{
- defer_frequency(all.flFrequency);
- defer_left_direction(all.ulLeftDirection);
- defer_right_direction(all.ulRightDirection);
-}
-
-void EaxFrequencyShifterEffect::defer_frequency(
- const EaxEaxCall& eax_call)
-{
- const auto& frequency =
- eax_call.get_value<
- EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::flFrequency)>();
-
- validate_frequency(frequency);
- defer_frequency(frequency);
-}
-
-void EaxFrequencyShifterEffect::defer_left_direction(
- const EaxEaxCall& eax_call)
-{
- const auto& left_direction =
- eax_call.get_value<
- EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulLeftDirection)>();
-
- validate_left_direction(left_direction);
- defer_left_direction(left_direction);
-}
-
-void EaxFrequencyShifterEffect::defer_right_direction(
- const EaxEaxCall& eax_call)
-{
- const auto& right_direction =
- eax_call.get_value<
- EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulRightDirection)>();
-
- validate_right_direction(right_direction);
- defer_right_direction(right_direction);
-}
-
-void EaxFrequencyShifterEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<
- EaxFrequencyShifterEffectException, const EAXFREQUENCYSHIFTERPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxFrequencyShifterEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxFrequencyShifterEffectDirtyFlags{})
+ switch(call.get_property_id())
{
- return false;
+ case EAXFREQUENCYSHIFTER_NONE: break;
+ case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXFREQUENCYSHIFTER_FREQUENCY: defer<FrequencyValidator>(call, props.flFrequency); break;
+ case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer<LeftDirectionValidator>(call, props.ulLeftDirection); break;
+ case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer<RightDirectionValidator>(call, props.ulRightDirection); break;
+ default: fail_unknown_property_id();
}
+}
- eax_ = eax_d_;
+bool EaxFrequencyShifterEffect::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_.ulLeftDirection)
+ if (props_.ulLeftDirection != props.ulLeftDirection)
{
+ is_dirty = true;
set_efx_left_direction();
}
- if (eax_dirty_flags_.ulRightDirection)
+ if (props_.ulRightDirection != props.ulRightDirection)
{
+ is_dirty = true;
set_efx_right_direction();
}
- eax_dirty_flags_ = EaxFrequencyShifterEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxFrequencyShifterEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
- {
- case EAXFREQUENCYSHIFTER_NONE:
- break;
-
- case EAXFREQUENCYSHIFTER_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXFREQUENCYSHIFTER_FREQUENCY:
- defer_frequency(eax_call);
- break;
-
- case EAXFREQUENCYSHIFTER_LEFTDIRECTION:
- defer_left_direction(eax_call);
- break;
-
- case EAXFREQUENCYSHIFTER_RIGHTDIRECTION:
- defer_right_direction(eax_call);
- break;
-
- default:
- throw EaxFrequencyShifterEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-EaxEffectUPtr eax_create_eax_frequency_shifter_effect()
+EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call)
{
- return std::make_unique<EaxFrequencyShifterEffect>();
+ return eax_create_eax4_effect<EaxFrequencyShifterEffect>(call);
}
#endif // ALSOFT_EAX
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
diff --git a/al/effects/null.cpp b/al/effects/null.cpp
index 0ec387d4..2243dfe1 100644
--- a/al/effects/null.cpp
+++ b/al/effects/null.cpp
@@ -100,44 +100,34 @@ const EffectProps NullEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-class EaxNullEffect final :
- public EaxEffect
-{
+class EaxNullEffect final : public EaxEffect {
public:
- EaxNullEffect();
-
- void dispatch(const EaxEaxCall& eax_call) override;
+ EaxNullEffect() noexcept;
- // [[nodiscard]]
- bool apply_deferred() override;
+ void dispatch(const EaxCall& call) override;
+ /*[[nodiscard]]*/ bool commit() override;
}; // EaxNullEffect
-class EaxNullEffectException :
- public EaxException
+class EaxNullEffectException : public EaxException
{
public:
- explicit EaxNullEffectException(
- const char* message)
- :
- EaxException{"EAX_NULL_EFFECT", message}
- {
- }
+ explicit EaxNullEffectException(const char* message)
+ : EaxException{"EAX_NULL_EFFECT", message}
+ {}
}; // EaxNullEffectException
-
-EaxNullEffect::EaxNullEffect()
+EaxNullEffect::EaxNullEffect() noexcept
: EaxEffect{AL_EFFECT_NULL}
-{
-}
+{}
-void EaxNullEffect::dispatch(const EaxEaxCall& eax_call)
+void EaxNullEffect::dispatch(const EaxCall& call)
{
- if(eax_call.get_property_id() != 0)
+ if(call.get_property_id() != 0)
throw EaxNullEffectException{"Unsupported property id."};
}
-bool EaxNullEffect::apply_deferred()
+bool EaxNullEffect::commit()
{
return false;
}
diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp
index cb81d831..51dbdd8f 100644
--- a/al/effects/pshifter.cpp
+++ b/al/effects/pshifter.cpp
@@ -9,7 +9,6 @@
#ifdef ALSOFT_EAX
#include "alnumeric.h"
-
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -93,108 +92,84 @@ const EffectProps PshifterEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxPitchShifterEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxPitchShifterEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxPitchShifterEffectDirtyFlagsValue lCoarseTune : 1;
- EaxPitchShifterEffectDirtyFlagsValue lFineTune : 1;
-}; // EaxPitchShifterEffectDirtyFlags
-
-
-class EaxPitchShifterEffect final :
- public EaxEffect
+class EaxPitchShifterEffectException : public EaxException
{
public:
- EaxPitchShifterEffect();
-
- void dispatch(const EaxEaxCall& eax_call) override;
+ explicit EaxPitchShifterEffectException(const char* message)
+ : EaxException{"EAX_PITCH_SHIFTER_EFFECT", message}
+ {}
+}; // EaxPitchShifterEffectException
- // [[nodiscard]]
- bool apply_deferred() override;
+class EaxPitchShifterEffect final : public EaxEffect4<EaxPitchShifterEffectException, EAXPITCHSHIFTERPROPERTIES> {
+public:
+ EaxPitchShifterEffect(const EaxCall& call);
private:
- EAXPITCHSHIFTERPROPERTIES eax_{};
- EAXPITCHSHIFTERPROPERTIES eax_d_{};
- EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults();
-
- void set_efx_coarse_tune();
- void set_efx_fine_tune();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_coarse_tune(long lCoarseTune);
- void validate_fine_tune(long lFineTune);
- void validate_all(const EAXPITCHSHIFTERPROPERTIES& all);
-
- void defer_coarse_tune(long lCoarseTune);
- void defer_fine_tune(long lFineTune);
- void defer_all(const EAXPITCHSHIFTERPROPERTIES& all);
-
- void defer_coarse_tune(const EaxEaxCall& eax_call);
- void defer_fine_tune(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
+ struct CoarseTuneValidator {
+ void operator()(long lCoarseTune) const
+ {
+ eax_validate_range<Exception>(
+ "Coarse Tune",
+ lCoarseTune,
+ EAXPITCHSHIFTER_MINCOARSETUNE,
+ EAXPITCHSHIFTER_MAXCOARSETUNE);
+ }
+ }; // CoarseTuneValidator
+
+ struct FineTuneValidator {
+ void operator()(long lFineTune) const
+ {
+ eax_validate_range<Exception>(
+ "Fine Tune",
+ lFineTune,
+ EAXPITCHSHIFTER_MINFINETUNE,
+ EAXPITCHSHIFTER_MAXFINETUNE);
+ }
+ }; // FineTuneValidator
+
+ struct AllValidator {
+ void operator()(const Props& all) const
+ {
+ CoarseTuneValidator{}(all.lCoarseTune);
+ FineTuneValidator{}(all.lFineTune);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& props) override;
+
+ void set_efx_coarse_tune() noexcept;
+ void set_efx_fine_tune() 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& old_i) override;
}; // EaxPitchShifterEffect
+EaxPitchShifterEffect::EaxPitchShifterEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_PITCH_SHIFTER, call}
+{}
-class EaxPitchShifterEffectException :
- public EaxException
+void EaxPitchShifterEffect::set_defaults(Props& props)
{
-public:
- explicit EaxPitchShifterEffectException(
- const char* message)
- :
- EaxException{"EAX_PITCH_SHIFTER_EFFECT", message}
- {
- }
-}; // EaxPitchShifterEffectException
-
-
-EaxPitchShifterEffect::EaxPitchShifterEffect()
- : EaxEffect{AL_EFFECT_PITCH_SHIFTER}
-{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-void EaxPitchShifterEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxPitchShifterEffect::set_eax_defaults()
-{
- eax_.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE;
- eax_.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE;
-
- eax_d_ = eax_;
+ props.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE;
+ props.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE;
}
-void EaxPitchShifterEffect::set_efx_coarse_tune()
+void EaxPitchShifterEffect::set_efx_coarse_tune() noexcept
{
- const auto coarse_tune = clamp(
- static_cast<ALint>(eax_.lCoarseTune),
+ al_effect_props_.Pshifter.CoarseTune = clamp(
+ static_cast<ALint>(props_.lCoarseTune),
AL_PITCH_SHIFTER_MIN_COARSE_TUNE,
AL_PITCH_SHIFTER_MAX_COARSE_TUNE);
-
- al_effect_props_.Pshifter.CoarseTune = coarse_tune;
}
-void EaxPitchShifterEffect::set_efx_fine_tune()
+void EaxPitchShifterEffect::set_efx_fine_tune() noexcept
{
- const auto fine_tune = clamp(
- static_cast<ALint>(eax_.lFineTune),
+ al_effect_props_.Pshifter.FineTune = clamp(
+ static_cast<ALint>(props_.lFineTune),
AL_PITCH_SHIFTER_MIN_FINE_TUNE,
AL_PITCH_SHIFTER_MAX_FINE_TUNE);
-
- al_effect_props_.Pshifter.FineTune = fine_tune;
}
void EaxPitchShifterEffect::set_efx_defaults()
@@ -203,162 +178,54 @@ void EaxPitchShifterEffect::set_efx_defaults()
set_efx_fine_tune();
}
-void EaxPitchShifterEffect::get(const EaxEaxCall& eax_call)
+void EaxPitchShifterEffect::get(const EaxCall& call, const Props& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case EAXPITCHSHIFTER_NONE:
- break;
-
- case EAXPITCHSHIFTER_ALLPARAMETERS:
- eax_call.set_value<EaxPitchShifterEffectException>(eax_);
- break;
-
- case EAXPITCHSHIFTER_COARSETUNE:
- eax_call.set_value<EaxPitchShifterEffectException>(eax_.lCoarseTune);
- break;
-
- case EAXPITCHSHIFTER_FINETUNE:
- eax_call.set_value<EaxPitchShifterEffectException>(eax_.lFineTune);
- break;
-
- default:
- throw EaxPitchShifterEffectException{"Unsupported property id."};
+ case EAXPITCHSHIFTER_NONE: break;
+ case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXPITCHSHIFTER_COARSETUNE: call.set_value<Exception>(props.lCoarseTune); break;
+ case EAXPITCHSHIFTER_FINETUNE: call.set_value<Exception>(props.lFineTune); break;
+ default: fail_unknown_property_id();
}
}
-void EaxPitchShifterEffect::validate_coarse_tune(
- long lCoarseTune)
-{
- eax_validate_range<EaxPitchShifterEffectException>(
- "Coarse Tune",
- lCoarseTune,
- EAXPITCHSHIFTER_MINCOARSETUNE,
- EAXPITCHSHIFTER_MAXCOARSETUNE);
-}
-
-void EaxPitchShifterEffect::validate_fine_tune(
- long lFineTune)
+void EaxPitchShifterEffect::set(const EaxCall& call, Props& props)
{
- eax_validate_range<EaxPitchShifterEffectException>(
- "Fine Tune",
- lFineTune,
- EAXPITCHSHIFTER_MINFINETUNE,
- EAXPITCHSHIFTER_MAXFINETUNE);
-}
-
-void EaxPitchShifterEffect::validate_all(
- const EAXPITCHSHIFTERPROPERTIES& all)
-{
- validate_coarse_tune(all.lCoarseTune);
- validate_fine_tune(all.lFineTune);
-}
-
-void EaxPitchShifterEffect::defer_coarse_tune(
- long lCoarseTune)
-{
- eax_d_.lCoarseTune = lCoarseTune;
- eax_dirty_flags_.lCoarseTune = (eax_.lCoarseTune != eax_d_.lCoarseTune);
-}
-
-void EaxPitchShifterEffect::defer_fine_tune(
- long lFineTune)
-{
- eax_d_.lFineTune = lFineTune;
- eax_dirty_flags_.lFineTune = (eax_.lFineTune != eax_d_.lFineTune);
-}
-
-void EaxPitchShifterEffect::defer_all(
- const EAXPITCHSHIFTERPROPERTIES& all)
-{
- defer_coarse_tune(all.lCoarseTune);
- defer_fine_tune(all.lFineTune);
-}
-
-void EaxPitchShifterEffect::defer_coarse_tune(
- const EaxEaxCall& eax_call)
-{
- const auto& coarse_tune =
- eax_call.get_value<EaxPitchShifterEffectException, const decltype(EAXPITCHSHIFTERPROPERTIES::lCoarseTune)>();
-
- validate_coarse_tune(coarse_tune);
- defer_coarse_tune(coarse_tune);
-}
-
-void EaxPitchShifterEffect::defer_fine_tune(
- const EaxEaxCall& eax_call)
-{
- const auto& fine_tune =
- eax_call.get_value<EaxPitchShifterEffectException, const decltype(EAXPITCHSHIFTERPROPERTIES::lFineTune)>();
-
- validate_fine_tune(fine_tune);
- defer_fine_tune(fine_tune);
-}
-
-void EaxPitchShifterEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all =
- eax_call.get_value<EaxPitchShifterEffectException, const EAXPITCHSHIFTERPROPERTIES>();
-
- validate_all(all);
- defer_all(all);
-}
-
-// [[nodiscard]]
-bool EaxPitchShifterEffect::apply_deferred()
-{
- if (eax_dirty_flags_ == EaxPitchShifterEffectDirtyFlags{})
+ switch(call.get_property_id())
{
- return false;
+ case EAXPITCHSHIFTER_NONE: break;
+ case EAXPITCHSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXPITCHSHIFTER_COARSETUNE: defer<CoarseTuneValidator>(call, props.lCoarseTune); break;
+ case EAXPITCHSHIFTER_FINETUNE: defer<FineTuneValidator>(call, props.lFineTune); break;
+ default: fail_unknown_property_id();
}
+}
- eax_ = eax_d_;
+bool EaxPitchShifterEffect::commit_props(const Props& props)
+{
+ auto is_dirty = false;
- if (eax_dirty_flags_.lCoarseTune)
+ if (props_.lCoarseTune != props.lCoarseTune)
{
+ is_dirty = true;
set_efx_coarse_tune();
}
- if (eax_dirty_flags_.lFineTune)
+ if (props_.lFineTune != props.lFineTune)
{
+ is_dirty = true;
set_efx_fine_tune();
}
- eax_dirty_flags_ = EaxPitchShifterEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxPitchShifterEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
- {
- case EAXPITCHSHIFTER_NONE:
- break;
-
- case EAXPITCHSHIFTER_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXPITCHSHIFTER_COARSETUNE:
- defer_coarse_tune(eax_call);
- break;
-
- case EAXPITCHSHIFTER_FINETUNE:
- defer_fine_tune(eax_call);
- break;
-
- default:
- throw EaxPitchShifterEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-EaxEffectUPtr eax_create_eax_pitch_shifter_effect()
+EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call)
{
- return std::make_unique<EaxPitchShifterEffect>();
+ return eax_create_eax4_effect<EaxPitchShifterEffect>(call);
}
#endif // ALSOFT_EAX
diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp
index 4184eda0..da4c3fb4 100644
--- a/al/effects/reverb.cpp
+++ b/al/effects/reverb.cpp
@@ -10,12 +10,9 @@
#include "effects.h"
#ifdef ALSOFT_EAX
-#include <tuple>
-
-#include "AL/efx-presets.h"
-
+#include <cassert>
#include "alnumeric.h"
-
+#include "AL/efx-presets.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
#endif // ALSOFT_EAX
@@ -569,475 +566,884 @@ const EffectProps StdReverbEffectProps{genDefaultStdProps()};
#ifdef ALSOFT_EAX
namespace {
-extern const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[];
-
-using EaxReverbEffectDirtyFlagsValue = std::uint_least32_t;
-
-struct EaxReverbEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxReverbEffectDirtyFlagsValue ulEnvironment : 1;
- EaxReverbEffectDirtyFlagsValue flEnvironmentSize : 1;
- EaxReverbEffectDirtyFlagsValue flEnvironmentDiffusion : 1;
- EaxReverbEffectDirtyFlagsValue lRoom : 1;
- EaxReverbEffectDirtyFlagsValue lRoomHF : 1;
- EaxReverbEffectDirtyFlagsValue lRoomLF : 1;
- EaxReverbEffectDirtyFlagsValue flDecayTime : 1;
- EaxReverbEffectDirtyFlagsValue flDecayHFRatio : 1;
- EaxReverbEffectDirtyFlagsValue flDecayLFRatio : 1;
- EaxReverbEffectDirtyFlagsValue lReflections : 1;
- EaxReverbEffectDirtyFlagsValue flReflectionsDelay : 1;
- EaxReverbEffectDirtyFlagsValue vReflectionsPan : 1;
- EaxReverbEffectDirtyFlagsValue lReverb : 1;
- EaxReverbEffectDirtyFlagsValue flReverbDelay : 1;
- EaxReverbEffectDirtyFlagsValue vReverbPan : 1;
- EaxReverbEffectDirtyFlagsValue flEchoTime : 1;
- EaxReverbEffectDirtyFlagsValue flEchoDepth : 1;
- EaxReverbEffectDirtyFlagsValue flModulationTime : 1;
- EaxReverbEffectDirtyFlagsValue flModulationDepth : 1;
- EaxReverbEffectDirtyFlagsValue flAirAbsorptionHF : 1;
- EaxReverbEffectDirtyFlagsValue flHFReference : 1;
- EaxReverbEffectDirtyFlagsValue flLFReference : 1;
- EaxReverbEffectDirtyFlagsValue flRoomRolloffFactor : 1;
- EaxReverbEffectDirtyFlagsValue ulFlags : 1;
-}; // EaxReverbEffectDirtyFlags
-
-struct Eax1ReverbEffectDirtyFlags
+class EaxReverbEffectException : public EaxException
{
- using EaxIsBitFieldStruct = bool;
-
- EaxReverbEffectDirtyFlagsValue ulEnvironment : 1;
- EaxReverbEffectDirtyFlagsValue flVolume : 1;
- EaxReverbEffectDirtyFlagsValue flDecayTime : 1;
- EaxReverbEffectDirtyFlagsValue flDamping : 1;
-}; // Eax1ReverbEffectDirtyFlags
+public:
+ explicit EaxReverbEffectException(const char* message)
+ : EaxException{"EAX_REVERB_EFFECT", message}
+ {}
+}; // EaxReverbEffectException
-class EaxReverbEffect final :
- public EaxEffect
+class EaxReverbEffect final : public EaxEffect
{
public:
- EaxReverbEffect();
+ EaxReverbEffect(const EaxCall& call) noexcept;
- void dispatch(const EaxEaxCall& eax_call) override;
-
- // [[nodiscard]]
- bool apply_deferred() override;
+ void dispatch(const EaxCall& call) override;
+ /*[[nodiscard]]*/ bool commit() override;
private:
- EAX_REVERBPROPERTIES eax1_{};
- EAX_REVERBPROPERTIES eax1_d_{};
- Eax1ReverbEffectDirtyFlags eax1_dirty_flags_{};
- EAXREVERBPROPERTIES eax_{};
- EAXREVERBPROPERTIES eax_d_{};
- EaxReverbEffectDirtyFlags eax_dirty_flags_{};
-
- [[noreturn]] static void eax_fail(const char* message);
-
- void set_eax_defaults();
-
- void set_efx_density_from_environment_size();
- void set_efx_diffusion();
- void set_efx_gain();
- void set_efx_gain_hf();
- void set_efx_gain_lf();
- void set_efx_decay_time();
- void set_efx_decay_hf_ratio();
- void set_efx_decay_lf_ratio();
- void set_efx_reflections_gain();
- void set_efx_reflections_delay();
- void set_efx_reflections_pan();
- void set_efx_late_reverb_gain();
- void set_efx_late_reverb_delay();
- void set_efx_late_reverb_pan();
- void set_efx_echo_time();
- void set_efx_echo_depth();
- void set_efx_modulation_time();
- void set_efx_modulation_depth();
- void set_efx_air_absorption_gain_hf();
- void set_efx_hf_reference();
- void set_efx_lf_reference();
- void set_efx_room_rolloff_factor();
- void set_efx_flags();
- void set_efx_defaults();
-
- void v1_get(const EaxEaxCall& eax_call) const;
-
- void get_all(const EaxEaxCall& eax_call) const;
-
- void get(const EaxEaxCall& eax_call) const;
-
- static void v1_validate_environment(unsigned long environment);
- static void v1_validate_volume(float volume);
- static void v1_validate_decay_time(float decay_time);
- static void v1_validate_damping(float damping);
- static void v1_validate_all(const EAX_REVERBPROPERTIES& all);
-
- void v1_defer_environment(unsigned long environment);
- void v1_defer_volume(float volume);
- void v1_defer_decay_time(float decay_time);
- void v1_defer_damping(float damping);
- void v1_defer_all(const EAX_REVERBPROPERTIES& all);
-
- void v1_defer_environment(const EaxEaxCall& eax_call);
- void v1_defer_volume(const EaxEaxCall& eax_call);
- void v1_defer_decay_time(const EaxEaxCall& eax_call);
- void v1_defer_damping(const EaxEaxCall& eax_call);
- void v1_defer_all(const EaxEaxCall& eax_call);
- void v1_defer(const EaxEaxCall& eax_call);
-
- void v1_set_efx();
-
- static void validate_environment(unsigned long ulEnvironment, int version, bool is_standalone);
- static void validate_environment_size(float flEnvironmentSize);
- static void validate_environment_diffusion(float flEnvironmentDiffusion);
- static void validate_room(long lRoom);
- static void validate_room_hf(long lRoomHF);
- static void validate_room_lf(long lRoomLF);
- static void validate_decay_time(float flDecayTime);
- static void validate_decay_hf_ratio(float flDecayHFRatio);
- static void validate_decay_lf_ratio(float flDecayLFRatio);
- static void validate_reflections(long lReflections);
- static void validate_reflections_delay(float flReflectionsDelay);
- static void validate_reflections_pan(const EAXVECTOR& vReflectionsPan);
- static void validate_reverb(long lReverb);
- static void validate_reverb_delay(float flReverbDelay);
- static void validate_reverb_pan(const EAXVECTOR& vReverbPan);
- static void validate_echo_time(float flEchoTime);
- static void validate_echo_depth(float flEchoDepth);
- static void validate_modulation_time(float flModulationTime);
- static void validate_modulation_depth(float flModulationDepth);
- static void validate_air_absorbtion_hf(float air_absorbtion_hf);
- static void validate_hf_reference(float flHFReference);
- static void validate_lf_reference(float flLFReference);
- static void validate_room_rolloff_factor(float flRoomRolloffFactor);
- static void validate_flags(unsigned long ulFlags);
- static void validate_all(const EAX20LISTENERPROPERTIES& all, int version);
- static void validate_all(const EAXREVERBPROPERTIES& all, int version);
-
- void defer_environment(unsigned long ulEnvironment);
- void defer_environment_size(float flEnvironmentSize);
- void defer_environment_diffusion(float flEnvironmentDiffusion);
- void defer_room(long lRoom);
- void defer_room_hf(long lRoomHF);
- void defer_room_lf(long lRoomLF);
- void defer_decay_time(float flDecayTime);
- void defer_decay_hf_ratio(float flDecayHFRatio);
- void defer_decay_lf_ratio(float flDecayLFRatio);
- void defer_reflections(long lReflections);
- void defer_reflections_delay(float flReflectionsDelay);
- void defer_reflections_pan(const EAXVECTOR& vReflectionsPan);
- void defer_reverb(long lReverb);
- void defer_reverb_delay(float flReverbDelay);
- void defer_reverb_pan(const EAXVECTOR& vReverbPan);
- void defer_echo_time(float flEchoTime);
- void defer_echo_depth(float flEchoDepth);
- void defer_modulation_time(float flModulationTime);
- void defer_modulation_depth(float flModulationDepth);
- void defer_air_absorbtion_hf(float flAirAbsorptionHF);
- void defer_hf_reference(float flHFReference);
- void defer_lf_reference(float flLFReference);
- void defer_room_rolloff_factor(float flRoomRolloffFactor);
- void defer_flags(unsigned long ulFlags);
- void defer_all(const EAX20LISTENERPROPERTIES& all);
- void defer_all(const EAXREVERBPROPERTIES& all);
-
- void defer_environment(const EaxEaxCall& eax_call);
- void defer_environment_size(const EaxEaxCall& eax_call);
- void defer_environment_diffusion(const EaxEaxCall& eax_call);
- void defer_room(const EaxEaxCall& eax_call);
- void defer_room_hf(const EaxEaxCall& eax_call);
- void defer_room_lf(const EaxEaxCall& eax_call);
- void defer_decay_time(const EaxEaxCall& eax_call);
- void defer_decay_hf_ratio(const EaxEaxCall& eax_call);
- void defer_decay_lf_ratio(const EaxEaxCall& eax_call);
- void defer_reflections(const EaxEaxCall& eax_call);
- void defer_reflections_delay(const EaxEaxCall& eax_call);
- void defer_reflections_pan(const EaxEaxCall& eax_call);
- void defer_reverb(const EaxEaxCall& eax_call);
- void defer_reverb_delay(const EaxEaxCall& eax_call);
- void defer_reverb_pan(const EaxEaxCall& eax_call);
- void defer_echo_time(const EaxEaxCall& eax_call);
- void defer_echo_depth(const EaxEaxCall& eax_call);
- void defer_modulation_time(const EaxEaxCall& eax_call);
- void defer_modulation_depth(const EaxEaxCall& eax_call);
- void defer_air_absorbtion_hf(const EaxEaxCall& eax_call);
- void defer_hf_reference(const EaxEaxCall& eax_call);
- void defer_lf_reference(const EaxEaxCall& eax_call);
- void defer_room_rolloff_factor(const EaxEaxCall& eax_call);
- void defer_flags(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
-}; // EaxReverbEffect
+ static constexpr auto initial_room2 = -10'000L;
+ using Exception = EaxReverbEffectException;
-class EaxReverbEffectException :
- public EaxException
-{
-public:
- explicit EaxReverbEffectException(
- const char* message)
- :
- EaxException{"EAX_REVERB_EFFECT", message}
+ using Props1 = EAX_REVERBPROPERTIES;
+ using Props2 = EAX20LISTENERPROPERTIES;
+ using Props3 = EAXREVERBPROPERTIES;
+
+ struct State1
+ {
+ Props1 i; // Immediate.
+ Props1 d; // Deferred.
+ }; // State1
+
+ struct State2
+ {
+ Props2 i; // Immediate.
+ Props2 d; // Deferred.
+ }; // State2
+
+ struct State3
+ {
+ Props3 i; // Immediate.
+ Props3 d; // Deferred.
+ }; // State3
+
+ struct EnvironmentValidator1 {
+ void operator()(unsigned long ulEnvironment) const
+ {
+ eax_validate_range<Exception>(
+ "Environment",
+ ulEnvironment,
+ EAXREVERB_MINENVIRONMENT,
+ EAX1REVERB_MAXENVIRONMENT);
+ }
+ }; // EnvironmentValidator1
+
+ struct VolumeValidator {
+ void operator()(float volume) const
+ {
+ eax_validate_range<Exception>(
+ "Volume",
+ volume,
+ EAX1REVERB_MINVOLUME,
+ EAX1REVERB_MAXVOLUME);
+ }
+ }; // VolumeValidator
+
+ struct DecayTimeValidator {
+ void operator()(float flDecayTime) const
+ {
+ eax_validate_range<Exception>(
+ "Decay Time",
+ flDecayTime,
+ EAXREVERB_MINDECAYTIME,
+ EAXREVERB_MAXDECAYTIME);
+ }
+ }; // DecayTimeValidator
+
+ struct DampingValidator {
+ void operator()(float damping) const
+ {
+ eax_validate_range<Exception>(
+ "Damping",
+ damping,
+ EAX1REVERB_MINDAMPING,
+ EAX1REVERB_MAXDAMPING);
+ }
+ }; // DampingValidator
+
+ struct AllValidator1 {
+ void operator()(const Props1& all) const
+ {
+ EnvironmentValidator1{}(all.environment);
+ VolumeValidator{}(all.fVolume);
+ DecayTimeValidator{}(all.fDecayTime_sec);
+ DampingValidator{}(all.fDamping);
+ }
+ }; // AllValidator1
+
+ struct RoomValidator {
+ void operator()(long lRoom) const
+ {
+ eax_validate_range<Exception>(
+ "Room",
+ lRoom,
+ EAXREVERB_MINROOM,
+ EAXREVERB_MAXROOM);
+ }
+ }; // RoomValidator
+
+ struct RoomHFValidator {
+ void operator()(long lRoomHF) const
+ {
+ eax_validate_range<Exception>(
+ "Room HF",
+ lRoomHF,
+ EAXREVERB_MINROOMHF,
+ EAXREVERB_MAXROOMHF);
+ }
+ }; // RoomHFValidator
+
+ struct RoomRolloffFactorValidator {
+ void operator()(float flRoomRolloffFactor) const
+ {
+ eax_validate_range<Exception>(
+ "Room Rolloff Factor",
+ flRoomRolloffFactor,
+ EAXREVERB_MINROOMROLLOFFFACTOR,
+ EAXREVERB_MAXROOMROLLOFFFACTOR);
+ }
+ }; // RoomRolloffFactorValidator
+
+ struct DecayHFRatioValidator {
+ void operator()(float flDecayHFRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Decay HF Ratio",
+ flDecayHFRatio,
+ EAXREVERB_MINDECAYHFRATIO,
+ EAXREVERB_MAXDECAYHFRATIO);
+ }
+ }; // DecayHFRatioValidator
+
+ struct ReflectionsValidator {
+ void operator()(long lReflections) const
+ {
+ eax_validate_range<Exception>(
+ "Reflections",
+ lReflections,
+ EAXREVERB_MINREFLECTIONS,
+ EAXREVERB_MAXREFLECTIONS);
+ }
+ }; // ReflectionsValidator
+
+ struct ReflectionsDelayValidator {
+ void operator()(float flReflectionsDelay) const
+ {
+ eax_validate_range<Exception>(
+ "Reflections Delay",
+ flReflectionsDelay,
+ EAXREVERB_MINREFLECTIONSDELAY,
+ EAXREVERB_MAXREFLECTIONSDELAY);
+ }
+ }; // ReflectionsDelayValidator
+
+ struct ReverbValidator {
+ void operator()(long lReverb) const
+ {
+ eax_validate_range<Exception>(
+ "Reverb",
+ lReverb,
+ EAXREVERB_MINREVERB,
+ EAXREVERB_MAXREVERB);
+ }
+ }; // ReverbValidator
+
+ struct ReverbDelayValidator {
+ void operator()(float flReverbDelay) const
+ {
+ eax_validate_range<Exception>(
+ "Reverb Delay",
+ flReverbDelay,
+ EAXREVERB_MINREVERBDELAY,
+ EAXREVERB_MAXREVERBDELAY);
+ }
+ }; // ReverbDelayValidator
+
+ struct EnvironmentSizeValidator {
+ void operator()(float flEnvironmentSize) const
+ {
+ eax_validate_range<Exception>(
+ "Environment Size",
+ flEnvironmentSize,
+ EAXREVERB_MINENVIRONMENTSIZE,
+ EAXREVERB_MAXENVIRONMENTSIZE);
+ }
+ }; // EnvironmentSizeValidator
+
+ struct EnvironmentDiffusionValidator {
+ void operator()(float flEnvironmentDiffusion) const
+ {
+ eax_validate_range<Exception>(
+ "Environment Diffusion",
+ flEnvironmentDiffusion,
+ EAXREVERB_MINENVIRONMENTDIFFUSION,
+ EAXREVERB_MAXENVIRONMENTDIFFUSION);
+ }
+ }; // EnvironmentDiffusionValidator
+
+ struct AirAbsorptionHFValidator {
+ void operator()(float flAirAbsorptionHF) const
+ {
+ eax_validate_range<Exception>(
+ "Air Absorbtion HF",
+ flAirAbsorptionHF,
+ EAXREVERB_MINAIRABSORPTIONHF,
+ EAXREVERB_MAXAIRABSORPTIONHF);
+ }
+ }; // AirAbsorptionHFValidator
+
+ struct FlagsValidator2 {
+ void operator()(unsigned long ulFlags) const
+ {
+ eax_validate_range<Exception>(
+ "Flags",
+ ulFlags,
+ 0UL,
+ ~EAX2LISTENERFLAGS_RESERVED);
+ }
+ }; // FlagsValidator2
+
+ struct AllValidator2 {
+ void operator()(const Props2& all) const
+ {
+ RoomValidator{}(all.lRoom);
+ RoomHFValidator{}(all.lRoomHF);
+ RoomRolloffFactorValidator{}(all.flRoomRolloffFactor);
+ DecayTimeValidator{}(all.flDecayTime);
+ DecayHFRatioValidator{}(all.flDecayHFRatio);
+ ReflectionsValidator{}(all.lReflections);
+ ReflectionsDelayValidator{}(all.flReflectionsDelay);
+ ReverbValidator{}(all.lReverb);
+ ReverbDelayValidator{}(all.flReverbDelay);
+ EnvironmentValidator1{}(all.dwEnvironment);
+ EnvironmentSizeValidator{}(all.flEnvironmentSize);
+ EnvironmentDiffusionValidator{}(all.flEnvironmentDiffusion);
+ AirAbsorptionHFValidator{}(all.flAirAbsorptionHF);
+ FlagsValidator2{}(all.dwFlags);
+ }
+ }; // AllValidator2
+
+ struct EnvironmentValidator3 {
+ void operator()(unsigned long ulEnvironment) const
+ {
+ eax_validate_range<Exception>(
+ "Environment",
+ ulEnvironment,
+ EAXREVERB_MINENVIRONMENT,
+ EAX30REVERB_MAXENVIRONMENT);
+ }
+ }; // EnvironmentValidator1
+
+ struct RoomLFValidator {
+ void operator()(long lRoomLF) const
+ {
+ eax_validate_range<Exception>(
+ "Room LF",
+ lRoomLF,
+ EAXREVERB_MINROOMLF,
+ EAXREVERB_MAXROOMLF);
+ }
+ }; // RoomLFValidator
+
+ struct DecayLFRatioValidator {
+ void operator()(float flDecayLFRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Decay LF Ratio",
+ flDecayLFRatio,
+ EAXREVERB_MINDECAYLFRATIO,
+ EAXREVERB_MAXDECAYLFRATIO);
+ }
+ }; // DecayLFRatioValidator
+
+ struct VectorValidator {
+ void operator()(const EAXVECTOR&) const
+ {}
+ }; // VectorValidator
+
+ struct EchoTimeValidator {
+ void operator()(float flEchoTime) const
+ {
+ eax_validate_range<Exception>(
+ "Echo Time",
+ flEchoTime,
+ EAXREVERB_MINECHOTIME,
+ EAXREVERB_MAXECHOTIME);
+ }
+ }; // EchoTimeValidator
+
+ struct EchoDepthValidator {
+ void operator()(float flEchoDepth) const
+ {
+ eax_validate_range<Exception>(
+ "Echo Depth",
+ flEchoDepth,
+ EAXREVERB_MINECHODEPTH,
+ EAXREVERB_MAXECHODEPTH);
+ }
+ }; // EchoDepthValidator
+
+ struct ModulationTimeValidator {
+ void operator()(float flModulationTime) const
+ {
+ eax_validate_range<Exception>(
+ "Modulation Time",
+ flModulationTime,
+ EAXREVERB_MINMODULATIONTIME,
+ EAXREVERB_MAXMODULATIONTIME);
+ }
+ }; // ModulationTimeValidator
+
+ struct ModulationDepthValidator {
+ void operator()(float flModulationDepth) const
+ {
+ eax_validate_range<Exception>(
+ "Modulation Depth",
+ flModulationDepth,
+ EAXREVERB_MINMODULATIONDEPTH,
+ EAXREVERB_MAXMODULATIONDEPTH);
+ }
+ }; // ModulationDepthValidator
+
+ struct HFReferenceValidator {
+ void operator()(float flHFReference) const
+ {
+ eax_validate_range<Exception>(
+ "HF Reference",
+ flHFReference,
+ EAXREVERB_MINHFREFERENCE,
+ EAXREVERB_MAXHFREFERENCE);
+ }
+ }; // HFReferenceValidator
+
+ struct LFReferenceValidator {
+ void operator()(float flLFReference) const
+ {
+ eax_validate_range<Exception>(
+ "LF Reference",
+ flLFReference,
+ EAXREVERB_MINLFREFERENCE,
+ EAXREVERB_MAXLFREFERENCE);
+ }
+ }; // LFReferenceValidator
+
+ struct FlagsValidator3 {
+ void operator()(unsigned long ulFlags) const
+ {
+ eax_validate_range<Exception>(
+ "Flags",
+ ulFlags,
+ 0UL,
+ ~EAXREVERBFLAGS_RESERVED);
+ }
+ }; // FlagsValidator3
+
+ struct AllValidator3 {
+ void operator()(const Props3& all) const
+ {
+ EnvironmentValidator3{}(all.ulEnvironment);
+ EnvironmentSizeValidator{}(all.flEnvironmentSize);
+ EnvironmentDiffusionValidator{}(all.flEnvironmentDiffusion);
+ RoomValidator{}(all.lRoom);
+ RoomHFValidator{}(all.lRoomHF);
+ RoomLFValidator{}(all.lRoomLF);
+ DecayTimeValidator{}(all.flDecayTime);
+ DecayHFRatioValidator{}(all.flDecayHFRatio);
+ DecayLFRatioValidator{}(all.flDecayLFRatio);
+ ReflectionsValidator{}(all.lReflections);
+ ReflectionsDelayValidator{}(all.flReflectionsDelay);
+ VectorValidator{}(all.vReflectionsPan);
+ ReverbValidator{}(all.lReverb);
+ ReverbDelayValidator{}(all.flReverbDelay);
+ VectorValidator{}(all.vReverbPan);
+ EchoTimeValidator{}(all.flEchoTime);
+ EchoDepthValidator{}(all.flEchoDepth);
+ ModulationTimeValidator{}(all.flModulationTime);
+ ModulationDepthValidator{}(all.flModulationDepth);
+ AirAbsorptionHFValidator{}(all.flAirAbsorptionHF);
+ HFReferenceValidator{}(all.flHFReference);
+ LFReferenceValidator{}(all.flLFReference);
+ RoomRolloffFactorValidator{}(all.flRoomRolloffFactor);
+ FlagsValidator3{}(all.ulFlags);
+ }
+ }; // AllValidator3
+
+ struct EnvironmentDeferrer2 {
+ void operator()(Props2& props, unsigned long dwEnvironment) const
+ {
+ props = EAX2REVERB_PRESETS[dwEnvironment];
+ }
+ }; // EnvironmentDeferrer2
+
+ struct EnvironmentSizeDeferrer2 {
+ void operator()(Props2& props, float flEnvironmentSize) const
+ {
+ if (props.flEnvironmentSize == flEnvironmentSize)
+ {
+ return;
+ }
+
+ const auto scale = flEnvironmentSize / props.flEnvironmentSize;
+ props.flEnvironmentSize = flEnvironmentSize;
+
+ if ((props.dwFlags & EAX2LISTENERFLAGS_DECAYTIMESCALE) != 0)
+ {
+ props.flDecayTime = clamp(
+ props.flDecayTime * scale,
+ EAXREVERB_MINDECAYTIME,
+ EAXREVERB_MAXDECAYTIME);
+ }
+
+ if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSSCALE) != 0 &&
+ (props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0)
+ {
+ props.lReflections = clamp(
+ props.lReflections - static_cast<long>(gain_to_level_mb(scale)),
+ EAXREVERB_MINREFLECTIONS,
+ EAXREVERB_MAXREFLECTIONS);
+ }
+
+ if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0)
+ {
+ props.flReflectionsDelay = clamp(
+ props.flReflectionsDelay * scale,
+ EAXREVERB_MINREFLECTIONSDELAY,
+ EAXREVERB_MAXREFLECTIONSDELAY);
+ }
+
+ if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBSCALE) != 0)
+ {
+ const auto log_scalar = ((props.dwFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
+
+ props.lReverb = clamp(
+ props.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
+ EAXREVERB_MINREVERB,
+ EAXREVERB_MAXREVERB);
+ }
+
+ if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBDELAYSCALE) != 0)
+ {
+ props.flReverbDelay = clamp(
+ props.flReverbDelay * scale,
+ EAXREVERB_MINREVERBDELAY,
+ EAXREVERB_MAXREVERBDELAY);
+ }
+ }
+ }; // EnvironmentSizeDeferrer2
+
+ struct EnvironmentDeferrer3 {
+ void operator()(Props3& props, unsigned long ulEnvironment) const
+ {
+ if (ulEnvironment == EAX_ENVIRONMENT_UNDEFINED)
+ {
+ props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
+ return;
+ }
+
+ props = EAXREVERB_PRESETS[ulEnvironment];
+ }
+ }; // EnvironmentDeferrer3
+
+ struct EnvironmentSizeDeferrer3 {
+ void operator()(Props3& props, float flEnvironmentSize) const
+ {
+ if (props.flEnvironmentSize == flEnvironmentSize)
+ {
+ return;
+ }
+
+ const auto scale = flEnvironmentSize / props.flEnvironmentSize;
+ props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
+ props.flEnvironmentSize = flEnvironmentSize;
+
+ if ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0)
+ {
+ props.flDecayTime = clamp(
+ props.flDecayTime * scale,
+ EAXREVERB_MINDECAYTIME,
+ EAXREVERB_MAXDECAYTIME);
+ }
+
+ if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0 &&
+ (props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
+ {
+ props.lReflections = clamp(
+ props.lReflections - static_cast<long>(gain_to_level_mb(scale)),
+ EAXREVERB_MINREFLECTIONS,
+ EAXREVERB_MAXREFLECTIONS);
+ }
+
+ if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
+ {
+ props.flReflectionsDelay = clamp(
+ props.flReflectionsDelay * scale,
+ EAXREVERB_MINREFLECTIONSDELAY,
+ EAXREVERB_MAXREFLECTIONSDELAY);
+ }
+
+ if ((props.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0)
+ {
+ const auto log_scalar = ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
+ props.lReverb = clamp(
+ props.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
+ EAXREVERB_MINREVERB,
+ EAXREVERB_MAXREVERB);
+ }
+
+ if ((props.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0)
+ {
+ props.flReverbDelay = clamp(
+ props.flReverbDelay * scale,
+ EAXREVERB_MINREVERBDELAY,
+ EAXREVERB_MAXREVERBDELAY);
+ }
+
+ if ((props.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0)
+ {
+ props.flEchoTime = clamp(
+ props.flEchoTime * scale,
+ EAXREVERB_MINECHOTIME,
+ EAXREVERB_MAXECHOTIME);
+ }
+
+ if ((props.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0)
+ {
+ props.flModulationTime = clamp(
+ props.flModulationTime * scale,
+ EAXREVERB_MINMODULATIONTIME,
+ EAXREVERB_MAXMODULATIONTIME);
+ }
+ }
+ }; // EnvironmentSizeDeferrer3
+
+ int version_;
+ Props3 props_{};
+ State1 state1_{};
+ State2 state2_{};
+ State3 state3_{};
+ State3 state4_{};
+ State3 state5_{};
+
+ [[noreturn]] static void fail(const char* message);
+ [[noreturn]] static void fail_unknown_property_id();
+ [[noreturn]] static void fail_unknown_version();
+
+ static void set_defaults(State1& state) noexcept;
+ static void set_defaults(State2& state) noexcept;
+ static void set_defaults(State3& state) noexcept;
+ void set_defaults() noexcept;
+
+ void set_current_defaults();
+
+ void set_efx_density_from_environment_size() noexcept;
+ void set_efx_diffusion() noexcept;
+ void set_efx_gain() noexcept;
+ void set_efx_gain_hf() noexcept;
+ void set_efx_gain_lf() noexcept;
+ void set_efx_decay_time() noexcept;
+ void set_efx_decay_hf_ratio() noexcept;
+ void set_efx_decay_lf_ratio() noexcept;
+ void set_efx_reflections_gain() noexcept;
+ void set_efx_reflections_delay() noexcept;
+ void set_efx_reflections_pan() noexcept;
+ void set_efx_late_reverb_gain() noexcept;
+ void set_efx_late_reverb_delay() noexcept;
+ void set_efx_late_reverb_pan() noexcept;
+ void set_efx_echo_time() noexcept;
+ void set_efx_echo_depth() noexcept;
+ void set_efx_modulation_time() noexcept;
+ void set_efx_modulation_depth() noexcept;
+ void set_efx_air_absorption_gain_hf() noexcept;
+ void set_efx_hf_reference() noexcept;
+ void set_efx_lf_reference() noexcept;
+ void set_efx_room_rolloff_factor() noexcept;
+ void set_efx_flags() noexcept;
+ void set_efx_defaults() noexcept;
+
+ static void get1(const EaxCall& call, const Props1& props);
+ static void get2(const EaxCall& call, const Props2& props);
+ static void get3(const EaxCall& call, const Props3& props);
+ void get(const EaxCall& call);
+
+ template<typename TValidator, typename TProperty>
+ static void defer(const EaxCall& call, TProperty& property)
{
+ const auto& value = call.get_value<Exception, const TProperty>();
+ TValidator{}(value);
+ property = value;
}
-}; // EaxReverbEffectException
+ template<typename TValidator, typename TDeferrer, typename TProperties, typename TProperty>
+ static void defer(const EaxCall& call, TProperties& properties, TProperty&)
+ {
+ const auto& value = call.get_value<Exception, const TProperty>();
+ TValidator{}(value);
+ TDeferrer{}(properties, value);
+ }
-EaxReverbEffect::EaxReverbEffect()
- : EaxEffect{AL_EFFECT_EAXREVERB}
+ template<typename TValidator, typename TProperty>
+ static void defer3(const EaxCall& call, Props3& properties, TProperty& property)
+ {
+ const auto& value = call.get_value<Exception, const TProperty>();
+ TValidator{}(value);
+ if (value == property)
+ return;
+ property = value;
+ properties.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
+ }
+
+ static void set1(const EaxCall& call, Props1& props);
+ static void set2(const EaxCall& call, Props2& props);
+ static void set3(const EaxCall& call, Props3& props);
+ void set(const EaxCall& call);
+
+ static void translate(const Props1& src, Props3& dst) noexcept;
+ static void translate(const Props2& src, Props3& dst) noexcept;
+}; // EaxReverbEffect
+
+EaxReverbEffect::EaxReverbEffect(const EaxCall& call) noexcept
+ : EaxEffect{AL_EFFECT_EAXREVERB}, version_{call.get_version()}
{
- set_eax_defaults();
+ set_defaults();
+ set_current_defaults();
set_efx_defaults();
}
-void EaxReverbEffect::dispatch(const EaxEaxCall& eax_call)
+void EaxReverbEffect::dispatch(const EaxCall& call)
+{
+ call.is_get() ? get(call) : set(call);
+}
+
+[[noreturn]] void EaxReverbEffect::fail(const char* message)
+{
+ throw Exception{message};
+}
+
+[[noreturn]] void EaxReverbEffect::fail_unknown_property_id()
{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
+ fail(EaxEffectErrorMessages::unknown_property_id());
}
-[[noreturn]] void EaxReverbEffect::eax_fail(const char* message)
+[[noreturn]] void EaxReverbEffect::fail_unknown_version()
{
- throw EaxReverbEffectException{message};
+ fail(EaxEffectErrorMessages::unknown_version());
}
-void EaxReverbEffect::set_eax_defaults()
+void EaxReverbEffect::set_defaults(State1& state) noexcept
{
- eax1_ = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
- eax1_d_ = eax1_;
- eax_ = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
- /* HACK: EAX2 has a default room volume of -10,000dB (silence), although
- * newer versions use -1,000dB. What should be happening is properties for
- * each EAX version is tracked separately, with the last version used for
- * the properties to apply (presumably v2 or nothing being the default).
- */
- eax_.lRoom = EAXREVERB_MINROOM;
- eax_d_ = eax_;
+ state.i = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
+ state.d = state.i;
}
-void EaxReverbEffect::set_efx_density_from_environment_size()
+void EaxReverbEffect::set_defaults(State2& state) noexcept
{
- const auto eax_environment_size = eax_.flEnvironmentSize;
+ state.i = EAX2REVERB_PRESETS[EAX2_ENVIRONMENT_GENERIC];
+ state.i.lRoom = initial_room2;
+ state.d = state.i;
+}
+
+void EaxReverbEffect::set_defaults(State3& state) noexcept
+{
+ state.i = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
+ state.d = state.i;
+}
+
+void EaxReverbEffect::set_defaults() noexcept
+{
+ set_defaults(state1_);
+ set_defaults(state2_);
+ set_defaults(state3_);
+ state4_ = state3_;
+ state5_ = state3_;
+}
+
+void EaxReverbEffect::set_current_defaults()
+{
+ switch (version_)
+ {
+ case 1: translate(state1_.i, props_); break;
+ case 2: translate(state2_.i, props_); break;
+ case 3: props_ = state3_.i; break;
+ case 4: props_ = state4_.i; break;
+ case 5: props_ = state5_.i; break;
+ default: fail_unknown_version();
+ }
+}
- const auto efx_density = clamp(
- (eax_environment_size * eax_environment_size * eax_environment_size) / 16.0F,
+void EaxReverbEffect::set_efx_density_from_environment_size() noexcept
+{
+ const auto size = props_.flEnvironmentSize;
+ const auto density = (size * size * size) / 16.0F;
+ al_effect_props_.Reverb.Density = clamp(
+ density,
AL_EAXREVERB_MIN_DENSITY,
AL_EAXREVERB_MAX_DENSITY);
-
- al_effect_props_.Reverb.Density = efx_density;
}
-void EaxReverbEffect::set_efx_diffusion()
+void EaxReverbEffect::set_efx_diffusion() noexcept
{
- const auto efx_diffusion = clamp(
- eax_.flEnvironmentDiffusion,
+ al_effect_props_.Reverb.Diffusion = clamp(
+ props_.flEnvironmentDiffusion,
AL_EAXREVERB_MIN_DIFFUSION,
AL_EAXREVERB_MAX_DIFFUSION);
-
- al_effect_props_.Reverb.Diffusion = efx_diffusion;
}
-void EaxReverbEffect::set_efx_gain()
+void EaxReverbEffect::set_efx_gain() noexcept
{
- const auto efx_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lRoom)),
+ al_effect_props_.Reverb.Gain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lRoom)),
AL_EAXREVERB_MIN_GAIN,
AL_EAXREVERB_MAX_GAIN);
-
- al_effect_props_.Reverb.Gain = efx_gain;
}
-void EaxReverbEffect::set_efx_gain_hf()
+void EaxReverbEffect::set_efx_gain_hf() noexcept
{
- const auto efx_gain_hf = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lRoomHF)),
+ al_effect_props_.Reverb.GainHF = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lRoomHF)),
AL_EAXREVERB_MIN_GAINHF,
AL_EAXREVERB_MAX_GAINHF);
-
- al_effect_props_.Reverb.GainHF = efx_gain_hf;
}
-void EaxReverbEffect::set_efx_gain_lf()
+void EaxReverbEffect::set_efx_gain_lf() noexcept
{
- const auto efx_gain_lf = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lRoomLF)),
+ al_effect_props_.Reverb.GainLF = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lRoomLF)),
AL_EAXREVERB_MIN_GAINLF,
AL_EAXREVERB_MAX_GAINLF);
-
- al_effect_props_.Reverb.GainLF = efx_gain_lf;
}
-void EaxReverbEffect::set_efx_decay_time()
+void EaxReverbEffect::set_efx_decay_time() noexcept
{
- const auto efx_decay_time = clamp(
- eax_.flDecayTime,
+ al_effect_props_.Reverb.DecayTime = clamp(
+ props_.flDecayTime,
AL_EAXREVERB_MIN_DECAY_TIME,
AL_EAXREVERB_MAX_DECAY_TIME);
-
- al_effect_props_.Reverb.DecayTime = efx_decay_time;
}
-void EaxReverbEffect::set_efx_decay_hf_ratio()
+void EaxReverbEffect::set_efx_decay_hf_ratio() noexcept
{
- const auto efx_decay_hf_ratio = clamp(
- eax_.flDecayHFRatio,
+ al_effect_props_.Reverb.DecayHFRatio = clamp(
+ props_.flDecayHFRatio,
AL_EAXREVERB_MIN_DECAY_HFRATIO,
AL_EAXREVERB_MAX_DECAY_HFRATIO);
-
- al_effect_props_.Reverb.DecayHFRatio = efx_decay_hf_ratio;
}
-void EaxReverbEffect::set_efx_decay_lf_ratio()
+void EaxReverbEffect::set_efx_decay_lf_ratio() noexcept
{
- const auto efx_decay_lf_ratio = clamp(
- eax_.flDecayLFRatio,
+ al_effect_props_.Reverb.DecayLFRatio = clamp(
+ props_.flDecayLFRatio,
AL_EAXREVERB_MIN_DECAY_LFRATIO,
AL_EAXREVERB_MAX_DECAY_LFRATIO);
-
- al_effect_props_.Reverb.DecayLFRatio = efx_decay_lf_ratio;
}
-void EaxReverbEffect::set_efx_reflections_gain()
+void EaxReverbEffect::set_efx_reflections_gain() noexcept
{
- const auto efx_reflections_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lReflections)),
+ al_effect_props_.Reverb.ReflectionsGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lReflections)),
AL_EAXREVERB_MIN_REFLECTIONS_GAIN,
AL_EAXREVERB_MAX_REFLECTIONS_GAIN);
-
- al_effect_props_.Reverb.ReflectionsGain = efx_reflections_gain;
}
-void EaxReverbEffect::set_efx_reflections_delay()
+void EaxReverbEffect::set_efx_reflections_delay() noexcept
{
- const auto efx_reflections_delay = clamp(
- eax_.flReflectionsDelay,
+ al_effect_props_.Reverb.ReflectionsDelay = clamp(
+ props_.flReflectionsDelay,
AL_EAXREVERB_MIN_REFLECTIONS_DELAY,
AL_EAXREVERB_MAX_REFLECTIONS_DELAY);
-
- al_effect_props_.Reverb.ReflectionsDelay = efx_reflections_delay;
}
-void EaxReverbEffect::set_efx_reflections_pan()
+void EaxReverbEffect::set_efx_reflections_pan() noexcept
{
- al_effect_props_.Reverb.ReflectionsPan[0] = eax_.vReflectionsPan.x;
- al_effect_props_.Reverb.ReflectionsPan[1] = eax_.vReflectionsPan.y;
- al_effect_props_.Reverb.ReflectionsPan[2] = eax_.vReflectionsPan.z;
+ al_effect_props_.Reverb.ReflectionsPan[0] = props_.vReflectionsPan.x;
+ al_effect_props_.Reverb.ReflectionsPan[1] = props_.vReflectionsPan.y;
+ al_effect_props_.Reverb.ReflectionsPan[2] = props_.vReflectionsPan.z;
}
-void EaxReverbEffect::set_efx_late_reverb_gain()
+void EaxReverbEffect::set_efx_late_reverb_gain() noexcept
{
- const auto efx_late_reverb_gain = clamp(
- level_mb_to_gain(static_cast<float>(eax_.lReverb)),
+ al_effect_props_.Reverb.LateReverbGain = clamp(
+ level_mb_to_gain(static_cast<float>(props_.lReverb)),
AL_EAXREVERB_MIN_LATE_REVERB_GAIN,
AL_EAXREVERB_MAX_LATE_REVERB_GAIN);
-
- al_effect_props_.Reverb.LateReverbGain = efx_late_reverb_gain;
}
-void EaxReverbEffect::set_efx_late_reverb_delay()
+void EaxReverbEffect::set_efx_late_reverb_delay() noexcept
{
- const auto efx_late_reverb_delay = clamp(
- eax_.flReverbDelay,
+ al_effect_props_.Reverb.LateReverbDelay = clamp(
+ props_.flReverbDelay,
AL_EAXREVERB_MIN_LATE_REVERB_DELAY,
AL_EAXREVERB_MAX_LATE_REVERB_DELAY);
-
- al_effect_props_.Reverb.LateReverbDelay = efx_late_reverb_delay;
}
-void EaxReverbEffect::set_efx_late_reverb_pan()
+void EaxReverbEffect::set_efx_late_reverb_pan() noexcept
{
- al_effect_props_.Reverb.LateReverbPan[0] = eax_.vReverbPan.x;
- al_effect_props_.Reverb.LateReverbPan[1] = eax_.vReverbPan.y;
- al_effect_props_.Reverb.LateReverbPan[2] = eax_.vReverbPan.z;
+ al_effect_props_.Reverb.LateReverbPan[0] = props_.vReverbPan.x;
+ al_effect_props_.Reverb.LateReverbPan[1] = props_.vReverbPan.y;
+ al_effect_props_.Reverb.LateReverbPan[2] = props_.vReverbPan.z;
}
-void EaxReverbEffect::set_efx_echo_time()
+void EaxReverbEffect::set_efx_echo_time() noexcept
{
- const auto efx_echo_time = clamp(
- eax_.flEchoTime,
+ al_effect_props_.Reverb.EchoTime = clamp(
+ props_.flEchoTime,
AL_EAXREVERB_MIN_ECHO_TIME,
AL_EAXREVERB_MAX_ECHO_TIME);
-
- al_effect_props_.Reverb.EchoTime = efx_echo_time;
}
-void EaxReverbEffect::set_efx_echo_depth()
+void EaxReverbEffect::set_efx_echo_depth() noexcept
{
- const auto efx_echo_depth = clamp(
- eax_.flEchoDepth,
+ al_effect_props_.Reverb.EchoDepth = clamp(
+ props_.flEchoDepth,
AL_EAXREVERB_MIN_ECHO_DEPTH,
AL_EAXREVERB_MAX_ECHO_DEPTH);
-
- al_effect_props_.Reverb.EchoDepth = efx_echo_depth;
}
-void EaxReverbEffect::set_efx_modulation_time()
+void EaxReverbEffect::set_efx_modulation_time() noexcept
{
- const auto efx_modulation_time = clamp(
- eax_.flModulationTime,
+ al_effect_props_.Reverb.ModulationTime = clamp(
+ props_.flModulationTime,
AL_EAXREVERB_MIN_MODULATION_TIME,
AL_EAXREVERB_MAX_MODULATION_TIME);
-
- al_effect_props_.Reverb.ModulationTime = efx_modulation_time;
}
-void EaxReverbEffect::set_efx_modulation_depth()
+void EaxReverbEffect::set_efx_modulation_depth() noexcept
{
- const auto efx_modulation_depth = clamp(
- eax_.flModulationDepth,
+ al_effect_props_.Reverb.ModulationDepth = clamp(
+ props_.flModulationDepth,
AL_EAXREVERB_MIN_MODULATION_DEPTH,
AL_EAXREVERB_MAX_MODULATION_DEPTH);
-
- al_effect_props_.Reverb.ModulationDepth = efx_modulation_depth;
}
-void EaxReverbEffect::set_efx_air_absorption_gain_hf()
+void EaxReverbEffect::set_efx_air_absorption_gain_hf() noexcept
{
- const auto efx_air_absorption_hf = clamp(
- level_mb_to_gain(eax_.flAirAbsorptionHF),
+ al_effect_props_.Reverb.AirAbsorptionGainHF = clamp(
+ level_mb_to_gain(props_.flAirAbsorptionHF),
AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF,
AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF);
-
- al_effect_props_.Reverb.AirAbsorptionGainHF = efx_air_absorption_hf;
}
-void EaxReverbEffect::set_efx_hf_reference()
+void EaxReverbEffect::set_efx_hf_reference() noexcept
{
- const auto efx_hf_reference = clamp(
- eax_.flHFReference,
+ al_effect_props_.Reverb.HFReference = clamp(
+ props_.flHFReference,
AL_EAXREVERB_MIN_HFREFERENCE,
AL_EAXREVERB_MAX_HFREFERENCE);
-
- al_effect_props_.Reverb.HFReference = efx_hf_reference;
}
-void EaxReverbEffect::set_efx_lf_reference()
+void EaxReverbEffect::set_efx_lf_reference() noexcept
{
- const auto efx_lf_reference = clamp(
- eax_.flLFReference,
+ al_effect_props_.Reverb.LFReference = clamp(
+ props_.flLFReference,
AL_EAXREVERB_MIN_LFREFERENCE,
AL_EAXREVERB_MAX_LFREFERENCE);
-
- al_effect_props_.Reverb.LFReference = efx_lf_reference;
}
-void EaxReverbEffect::set_efx_room_rolloff_factor()
+void EaxReverbEffect::set_efx_room_rolloff_factor() noexcept
{
- const auto efx_room_rolloff_factor = clamp(
- eax_.flRoomRolloffFactor,
+ al_effect_props_.Reverb.RoomRolloffFactor = clamp(
+ props_.flRoomRolloffFactor,
AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR,
AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR);
-
- al_effect_props_.Reverb.RoomRolloffFactor = efx_room_rolloff_factor;
}
-void EaxReverbEffect::set_efx_flags()
+void EaxReverbEffect::set_efx_flags() noexcept
{
- al_effect_props_.Reverb.DecayHFLimit = ((eax_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
+ al_effect_props_.Reverb.DecayHFLimit = ((props_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
}
-void EaxReverbEffect::set_efx_defaults()
+void EaxReverbEffect::set_efx_defaults() noexcept
{
set_efx_density_from_environment_size();
set_efx_diffusion();
@@ -1064,1482 +1470,536 @@ void EaxReverbEffect::set_efx_defaults()
set_efx_flags();
}
-void EaxReverbEffect::v1_get(const EaxEaxCall& eax_call) const
+void EaxReverbEffect::get1(const EaxCall& call, const Props1& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case DSPROPERTY_EAX_ALL:
- eax_call.set_value<EaxReverbEffectException>(eax1_);
- break;
-
- case DSPROPERTY_EAX_ENVIRONMENT:
- eax_call.set_value<EaxReverbEffectException>(eax1_.environment);
- break;
-
- case DSPROPERTY_EAX_VOLUME:
- eax_call.set_value<EaxReverbEffectException>(eax1_.fVolume);
- break;
-
- case DSPROPERTY_EAX_DECAYTIME:
- eax_call.set_value<EaxReverbEffectException>(eax1_.fDecayTime_sec);
- break;
-
- case DSPROPERTY_EAX_DAMPING:
- eax_call.set_value<EaxReverbEffectException>(eax1_.fDamping);
- break;
-
- default:
- eax_fail("Unsupported property id.");
+ case DSPROPERTY_EAX_ALL: call.set_value<Exception>(props); break;
+ case DSPROPERTY_EAX_ENVIRONMENT: call.set_value<Exception>(props.environment); break;
+ case DSPROPERTY_EAX_VOLUME: call.set_value<Exception>(props.fVolume); break;
+ case DSPROPERTY_EAX_DECAYTIME: call.set_value<Exception>(props.fDecayTime_sec); break;
+ case DSPROPERTY_EAX_DAMPING: call.set_value<Exception>(props.fDamping); break;
+ default: fail_unknown_property_id();
}
}
-void EaxReverbEffect::get_all(
- const EaxEaxCall& eax_call) const
+void EaxReverbEffect::get2(const EaxCall& call, const Props2& props)
{
- if (eax_call.get_version() == 2)
- {
- auto& eax_reverb = eax_call.get_value<EaxReverbEffectException, EAX20LISTENERPROPERTIES>();
- eax_reverb.lRoom = eax_.lRoom;
- eax_reverb.lRoomHF = eax_.lRoomHF;
- eax_reverb.flRoomRolloffFactor = eax_.flRoomRolloffFactor;
- eax_reverb.flDecayTime = eax_.flDecayTime;
- eax_reverb.flDecayHFRatio = eax_.flDecayHFRatio;
- eax_reverb.lReflections = eax_.lReflections;
- eax_reverb.flReflectionsDelay = eax_.flReflectionsDelay;
- eax_reverb.lReverb = eax_.lReverb;
- eax_reverb.flReverbDelay = eax_.flReverbDelay;
- eax_reverb.dwEnvironment = eax_.ulEnvironment;
- eax_reverb.flEnvironmentSize = eax_.flEnvironmentSize;
- eax_reverb.flEnvironmentDiffusion = eax_.flEnvironmentDiffusion;
- eax_reverb.flAirAbsorptionHF = eax_.flAirAbsorptionHF;
- eax_reverb.dwFlags = eax_.ulFlags;
- }
- else
+ switch(call.get_property_id())
{
- eax_call.set_value<EaxReverbEffectException>(eax_);
+ case DSPROPERTY_EAX20LISTENER_NONE: break;
+ case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case DSPROPERTY_EAX20LISTENER_ROOM: call.set_value<Exception>(props.lRoom); break;
+ case DSPROPERTY_EAX20LISTENER_ROOMHF: call.set_value<Exception>(props.lRoomHF); break;
+ case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: call.set_value<Exception>(props.flRoomRolloffFactor); break;
+ case DSPROPERTY_EAX20LISTENER_DECAYTIME: call.set_value<Exception>(props.flDecayTime); break;
+ case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: call.set_value<Exception>(props.flDecayHFRatio); break;
+ case DSPROPERTY_EAX20LISTENER_REFLECTIONS: call.set_value<Exception>(props.lReflections); break;
+ case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: call.set_value<Exception>(props.flReverbDelay); break;
+ case DSPROPERTY_EAX20LISTENER_REVERB: call.set_value<Exception>(props.lReverb); break;
+ case DSPROPERTY_EAX20LISTENER_REVERBDELAY: call.set_value<Exception>(props.flReverbDelay); break;
+ case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: call.set_value<Exception>(props.dwEnvironment); break;
+ case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: call.set_value<Exception>(props.flEnvironmentSize); break;
+ case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: call.set_value<Exception>(props.flEnvironmentDiffusion); break;
+ case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: call.set_value<Exception>(props.flAirAbsorptionHF); break;
+ case DSPROPERTY_EAX20LISTENER_FLAGS: call.set_value<Exception>(props.dwFlags); break;
+ default: fail_unknown_property_id();
}
}
-void EaxReverbEffect::get(const EaxEaxCall& eax_call) const
+void EaxReverbEffect::get3(const EaxCall& call, const Props3& props)
{
- if(eax_call.get_version() == 1)
- v1_get(eax_call);
- else switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
- case EAXREVERB_NONE:
- break;
-
- case EAXREVERB_ALLPARAMETERS:
- get_all(eax_call);
- break;
-
- case EAXREVERB_ENVIRONMENT:
- eax_call.set_value<EaxReverbEffectException>(eax_.ulEnvironment);
- break;
-
- case EAXREVERB_ENVIRONMENTSIZE:
- eax_call.set_value<EaxReverbEffectException>(eax_.flEnvironmentSize);
- break;
-
- case EAXREVERB_ENVIRONMENTDIFFUSION:
- eax_call.set_value<EaxReverbEffectException>(eax_.flEnvironmentDiffusion);
- break;
-
- case EAXREVERB_ROOM:
- eax_call.set_value<EaxReverbEffectException>(eax_.lRoom);
- break;
-
- case EAXREVERB_ROOMHF:
- eax_call.set_value<EaxReverbEffectException>(eax_.lRoomHF);
- break;
-
- case EAXREVERB_ROOMLF:
- eax_call.set_value<EaxReverbEffectException>(eax_.lRoomLF);
- break;
-
- case EAXREVERB_DECAYTIME:
- eax_call.set_value<EaxReverbEffectException>(eax_.flDecayTime);
- break;
-
- case EAXREVERB_DECAYHFRATIO:
- eax_call.set_value<EaxReverbEffectException>(eax_.flDecayHFRatio);
- break;
-
- case EAXREVERB_DECAYLFRATIO:
- eax_call.set_value<EaxReverbEffectException>(eax_.flDecayLFRatio);
- break;
-
- case EAXREVERB_REFLECTIONS:
- eax_call.set_value<EaxReverbEffectException>(eax_.lReflections);
- break;
-
- case EAXREVERB_REFLECTIONSDELAY:
- eax_call.set_value<EaxReverbEffectException>(eax_.flReflectionsDelay);
- break;
-
- case EAXREVERB_REFLECTIONSPAN:
- eax_call.set_value<EaxReverbEffectException>(eax_.vReflectionsPan);
- break;
-
- case EAXREVERB_REVERB:
- eax_call.set_value<EaxReverbEffectException>(eax_.lReverb);
- break;
-
- case EAXREVERB_REVERBDELAY:
- eax_call.set_value<EaxReverbEffectException>(eax_.flReverbDelay);
- break;
-
- case EAXREVERB_REVERBPAN:
- eax_call.set_value<EaxReverbEffectException>(eax_.vReverbPan);
- break;
-
- case EAXREVERB_ECHOTIME:
- eax_call.set_value<EaxReverbEffectException>(eax_.flEchoTime);
- break;
-
- case EAXREVERB_ECHODEPTH:
- eax_call.set_value<EaxReverbEffectException>(eax_.flEchoDepth);
- break;
-
- case EAXREVERB_MODULATIONTIME:
- eax_call.set_value<EaxReverbEffectException>(eax_.flModulationTime);
- break;
-
- case EAXREVERB_MODULATIONDEPTH:
- eax_call.set_value<EaxReverbEffectException>(eax_.flModulationDepth);
- break;
-
- case EAXREVERB_AIRABSORPTIONHF:
- eax_call.set_value<EaxReverbEffectException>(eax_.flAirAbsorptionHF);
- break;
-
- case EAXREVERB_HFREFERENCE:
- eax_call.set_value<EaxReverbEffectException>(eax_.flHFReference);
- break;
-
- case EAXREVERB_LFREFERENCE:
- eax_call.set_value<EaxReverbEffectException>(eax_.flLFReference);
- break;
-
- case EAXREVERB_ROOMROLLOFFFACTOR:
- eax_call.set_value<EaxReverbEffectException>(eax_.flRoomRolloffFactor);
- break;
-
- case EAXREVERB_FLAGS:
- eax_call.set_value<EaxReverbEffectException>(eax_.ulFlags);
- break;
-
- default:
- eax_fail("Unsupported property id.");
+ case EAXREVERB_NONE: break;
+ case EAXREVERB_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXREVERB_ENVIRONMENT: call.set_value<Exception>(props.ulEnvironment); break;
+ case EAXREVERB_ENVIRONMENTSIZE: call.set_value<Exception>(props.flEnvironmentSize); break;
+ case EAXREVERB_ENVIRONMENTDIFFUSION: call.set_value<Exception>(props.flEnvironmentDiffusion); break;
+ case EAXREVERB_ROOM: call.set_value<Exception>(props.lRoom); break;
+ case EAXREVERB_ROOMHF: call.set_value<Exception>(props.lRoomHF); break;
+ case EAXREVERB_ROOMLF: call.set_value<Exception>(props.lRoomLF); break;
+ case EAXREVERB_DECAYTIME: call.set_value<Exception>(props.flDecayTime); break;
+ case EAXREVERB_DECAYHFRATIO: call.set_value<Exception>(props.flDecayHFRatio); break;
+ case EAXREVERB_DECAYLFRATIO: call.set_value<Exception>(props.flDecayLFRatio); break;
+ case EAXREVERB_REFLECTIONS: call.set_value<Exception>(props.lReflections); break;
+ case EAXREVERB_REFLECTIONSDELAY: call.set_value<Exception>(props.flReflectionsDelay); break;
+ case EAXREVERB_REFLECTIONSPAN: call.set_value<Exception>(props.vReflectionsPan); break;
+ case EAXREVERB_REVERB: call.set_value<Exception>(props.lReverb); break;
+ case EAXREVERB_REVERBDELAY: call.set_value<Exception>(props.flReverbDelay); break;
+ case EAXREVERB_REVERBPAN: call.set_value<Exception>(props.vReverbPan); break;
+ case EAXREVERB_ECHOTIME: call.set_value<Exception>(props.flEchoTime); break;
+ case EAXREVERB_ECHODEPTH: call.set_value<Exception>(props.flEchoDepth); break;
+ case EAXREVERB_MODULATIONTIME: call.set_value<Exception>(props.flModulationTime); break;
+ case EAXREVERB_MODULATIONDEPTH: call.set_value<Exception>(props.flModulationDepth); break;
+ case EAXREVERB_AIRABSORPTIONHF: call.set_value<Exception>(props.flAirAbsorptionHF); break;
+ case EAXREVERB_HFREFERENCE: call.set_value<Exception>(props.flHFReference); break;
+ case EAXREVERB_LFREFERENCE: call.set_value<Exception>(props.flLFReference); break;
+ case EAXREVERB_ROOMROLLOFFFACTOR: call.set_value<Exception>(props.flRoomRolloffFactor); break;
+ case EAXREVERB_FLAGS: call.set_value<Exception>(props.ulFlags); break;
+ default: fail_unknown_property_id();
}
}
-void EaxReverbEffect::v1_validate_environment(unsigned long environment)
-{
- validate_environment(environment, 1, true);
-}
-
-void EaxReverbEffect::v1_validate_volume(float volume)
-{
- eax_validate_range<EaxReverbEffectException>("Volume", volume, EAX1REVERB_MINVOLUME, EAX1REVERB_MAXVOLUME);
-}
-
-void EaxReverbEffect::v1_validate_decay_time(float decay_time)
-{
- validate_decay_time(decay_time);
-}
-
-void EaxReverbEffect::v1_validate_damping(float damping)
-{
- eax_validate_range<EaxReverbEffectException>("Damping", damping, EAX1REVERB_MINDAMPING, EAX1REVERB_MAXDAMPING);
-}
-
-void EaxReverbEffect::v1_validate_all(const EAX_REVERBPROPERTIES& all)
-{
- v1_validate_environment(all.environment);
- v1_validate_volume(all.fVolume);
- v1_validate_decay_time(all.fDecayTime_sec);
- v1_validate_damping(all.fDamping);
-}
-
-void EaxReverbEffect::validate_environment(
- unsigned long ulEnvironment,
- int version,
- bool is_standalone)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Environment",
- ulEnvironment,
- EAXREVERB_MINENVIRONMENT,
- (version <= 2 || is_standalone) ? EAX1REVERB_MAXENVIRONMENT : EAX30REVERB_MAXENVIRONMENT);
-}
-
-void EaxReverbEffect::validate_environment_size(
- float flEnvironmentSize)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Environment Size",
- flEnvironmentSize,
- EAXREVERB_MINENVIRONMENTSIZE,
- EAXREVERB_MAXENVIRONMENTSIZE);
-}
-
-void EaxReverbEffect::validate_environment_diffusion(
- float flEnvironmentDiffusion)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Environment Diffusion",
- flEnvironmentDiffusion,
- EAXREVERB_MINENVIRONMENTDIFFUSION,
- EAXREVERB_MAXENVIRONMENTDIFFUSION);
-}
-
-void EaxReverbEffect::validate_room(
- long lRoom)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Room",
- lRoom,
- EAXREVERB_MINROOM,
- EAXREVERB_MAXROOM);
-}
-
-void EaxReverbEffect::validate_room_hf(
- long lRoomHF)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Room HF",
- lRoomHF,
- EAXREVERB_MINROOMHF,
- EAXREVERB_MAXROOMHF);
-}
-
-void EaxReverbEffect::validate_room_lf(
- long lRoomLF)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Room LF",
- lRoomLF,
- EAXREVERB_MINROOMLF,
- EAXREVERB_MAXROOMLF);
-}
-
-void EaxReverbEffect::validate_decay_time(
- float flDecayTime)
+void EaxReverbEffect::get(const EaxCall& call)
{
- eax_validate_range<EaxReverbEffectException>(
- "Decay Time",
- flDecayTime,
- EAXREVERB_MINDECAYTIME,
- EAXREVERB_MAXDECAYTIME);
-}
-
-void EaxReverbEffect::validate_decay_hf_ratio(
- float flDecayHFRatio)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Decay HF Ratio",
- flDecayHFRatio,
- EAXREVERB_MINDECAYHFRATIO,
- EAXREVERB_MAXDECAYHFRATIO);
-}
-
-void EaxReverbEffect::validate_decay_lf_ratio(
- float flDecayLFRatio)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Decay LF Ratio",
- flDecayLFRatio,
- EAXREVERB_MINDECAYLFRATIO,
- EAXREVERB_MAXDECAYLFRATIO);
-}
-
-void EaxReverbEffect::validate_reflections(
- long lReflections)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Reflections",
- lReflections,
- EAXREVERB_MINREFLECTIONS,
- EAXREVERB_MAXREFLECTIONS);
-}
-
-void EaxReverbEffect::validate_reflections_delay(
- float flReflectionsDelay)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Reflections Delay",
- flReflectionsDelay,
- EAXREVERB_MINREFLECTIONSDELAY,
- EAXREVERB_MAXREFLECTIONSDELAY);
-}
-
-void EaxReverbEffect::validate_reflections_pan(
- const EAXVECTOR& vReflectionsPan)
-{
- std::ignore = vReflectionsPan;
-}
-
-void EaxReverbEffect::validate_reverb(
- long lReverb)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Reverb",
- lReverb,
- EAXREVERB_MINREVERB,
- EAXREVERB_MAXREVERB);
-}
-
-void EaxReverbEffect::validate_reverb_delay(
- float flReverbDelay)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Reverb Delay",
- flReverbDelay,
- EAXREVERB_MINREVERBDELAY,
- EAXREVERB_MAXREVERBDELAY);
-}
-
-void EaxReverbEffect::validate_reverb_pan(
- const EAXVECTOR& vReverbPan)
-{
- std::ignore = vReverbPan;
-}
+ const auto version = call.get_version();
-void EaxReverbEffect::validate_echo_time(
- float flEchoTime)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Echo Time",
- flEchoTime,
- EAXREVERB_MINECHOTIME,
- EAXREVERB_MAXECHOTIME);
-}
-
-void EaxReverbEffect::validate_echo_depth(
- float flEchoDepth)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Echo Depth",
- flEchoDepth,
- EAXREVERB_MINECHODEPTH,
- EAXREVERB_MAXECHODEPTH);
-}
-
-void EaxReverbEffect::validate_modulation_time(
- float flModulationTime)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Modulation Time",
- flModulationTime,
- EAXREVERB_MINMODULATIONTIME,
- EAXREVERB_MAXMODULATIONTIME);
-}
-
-void EaxReverbEffect::validate_modulation_depth(
- float flModulationDepth)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Modulation Depth",
- flModulationDepth,
- EAXREVERB_MINMODULATIONDEPTH,
- EAXREVERB_MAXMODULATIONDEPTH);
-}
-
-void EaxReverbEffect::validate_air_absorbtion_hf(
- float air_absorbtion_hf)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Air Absorbtion HF",
- air_absorbtion_hf,
- EAXREVERB_MINAIRABSORPTIONHF,
- EAXREVERB_MAXAIRABSORPTIONHF);
-}
-
-void EaxReverbEffect::validate_hf_reference(
- float flHFReference)
-{
- eax_validate_range<EaxReverbEffectException>(
- "HF Reference",
- flHFReference,
- EAXREVERB_MINHFREFERENCE,
- EAXREVERB_MAXHFREFERENCE);
-}
-
-void EaxReverbEffect::validate_lf_reference(
- float flLFReference)
-{
- eax_validate_range<EaxReverbEffectException>(
- "LF Reference",
- flLFReference,
- EAXREVERB_MINLFREFERENCE,
- EAXREVERB_MAXLFREFERENCE);
-}
-
-void EaxReverbEffect::validate_room_rolloff_factor(
- float flRoomRolloffFactor)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Room Rolloff Factor",
- flRoomRolloffFactor,
- EAXREVERB_MINROOMROLLOFFFACTOR,
- EAXREVERB_MAXROOMROLLOFFFACTOR);
-}
-
-void EaxReverbEffect::validate_flags(
- unsigned long ulFlags)
-{
- eax_validate_range<EaxReverbEffectException>(
- "Flags",
- ulFlags,
- 0UL,
- ~EAXREVERBFLAGS_RESERVED);
-}
-
-void EaxReverbEffect::validate_all(
- const EAX20LISTENERPROPERTIES& listener,
- int version)
-{
- validate_room(listener.lRoom);
- validate_room_hf(listener.lRoomHF);
- validate_room_rolloff_factor(listener.flRoomRolloffFactor);
- validate_decay_time(listener.flDecayTime);
- validate_decay_hf_ratio(listener.flDecayHFRatio);
- validate_reflections(listener.lReflections);
- validate_reflections_delay(listener.flReflectionsDelay);
- validate_reverb(listener.lReverb);
- validate_reverb_delay(listener.flReverbDelay);
- validate_environment(listener.dwEnvironment, version, false);
- validate_environment_size(listener.flEnvironmentSize);
- validate_environment_diffusion(listener.flEnvironmentDiffusion);
- validate_air_absorbtion_hf(listener.flAirAbsorptionHF);
- validate_flags(listener.dwFlags);
-}
-
-void EaxReverbEffect::validate_all(
- const EAXREVERBPROPERTIES& lReverb,
- int version)
-{
- validate_environment(lReverb.ulEnvironment, version, false);
- validate_environment_size(lReverb.flEnvironmentSize);
- validate_environment_diffusion(lReverb.flEnvironmentDiffusion);
- validate_room(lReverb.lRoom);
- validate_room_hf(lReverb.lRoomHF);
- validate_room_lf(lReverb.lRoomLF);
- validate_decay_time(lReverb.flDecayTime);
- validate_decay_hf_ratio(lReverb.flDecayHFRatio);
- validate_decay_lf_ratio(lReverb.flDecayLFRatio);
- validate_reflections(lReverb.lReflections);
- validate_reflections_delay(lReverb.flReflectionsDelay);
- validate_reverb(lReverb.lReverb);
- validate_reverb_delay(lReverb.flReverbDelay);
- validate_echo_time(lReverb.flEchoTime);
- validate_echo_depth(lReverb.flEchoDepth);
- validate_modulation_time(lReverb.flModulationTime);
- validate_modulation_depth(lReverb.flModulationDepth);
- validate_air_absorbtion_hf(lReverb.flAirAbsorptionHF);
- validate_hf_reference(lReverb.flHFReference);
- validate_lf_reference(lReverb.flLFReference);
- validate_room_rolloff_factor(lReverb.flRoomRolloffFactor);
- validate_flags(lReverb.ulFlags);
-}
-
-void EaxReverbEffect::v1_defer_environment(unsigned long environment)
-{
- eax1_d_ = EAX1REVERB_PRESETS[environment];
- eax1_dirty_flags_.ulEnvironment = true;
-}
-
-void EaxReverbEffect::v1_defer_volume(float volume)
-{
- eax1_d_.fVolume = volume;
- eax1_dirty_flags_.flVolume = (eax1_.fVolume != eax1_d_.fVolume);
-}
-
-void EaxReverbEffect::v1_defer_decay_time(float decay_time)
-{
- eax1_d_.fDecayTime_sec = decay_time;
- eax1_dirty_flags_.flDecayTime = (eax1_.fDecayTime_sec != eax1_d_.fDecayTime_sec);
-}
-
-void EaxReverbEffect::v1_defer_damping(float damping)
-{
- eax1_d_.fDamping = damping;
- eax1_dirty_flags_.flDamping = (eax1_.fDamping != eax1_d_.fDamping);
-}
-
-void EaxReverbEffect::v1_defer_all(const EAX_REVERBPROPERTIES& lReverb)
-{
- v1_defer_environment(lReverb.environment);
- v1_defer_volume(lReverb.fVolume);
- v1_defer_decay_time(lReverb.fDecayTime_sec);
- v1_defer_damping(lReverb.fDamping);
-}
-
-
-void EaxReverbEffect::v1_set_efx()
-{
- auto efx_props = eax_efx_reverb_presets[eax1_.environment];
- efx_props.flGain = eax1_.fVolume;
- efx_props.flDecayTime = eax1_.fDecayTime_sec;
- efx_props.flDecayHFRatio = clamp(eax1_.fDamping, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO);
-
- al_effect_props_.Reverb.Density = efx_props.flDensity;
- al_effect_props_.Reverb.Diffusion = efx_props.flDiffusion;
- al_effect_props_.Reverb.Gain = efx_props.flGain;
- al_effect_props_.Reverb.GainHF = efx_props.flGainHF;
- al_effect_props_.Reverb.GainLF = efx_props.flGainLF;
- al_effect_props_.Reverb.DecayTime = efx_props.flDecayTime;
- al_effect_props_.Reverb.DecayHFRatio = efx_props.flDecayHFRatio;
- al_effect_props_.Reverb.DecayLFRatio = efx_props.flDecayLFRatio;
- al_effect_props_.Reverb.ReflectionsGain = efx_props.flReflectionsGain;
- al_effect_props_.Reverb.ReflectionsDelay = efx_props.flReflectionsDelay;
- al_effect_props_.Reverb.ReflectionsPan[0] = efx_props.flReflectionsPan[0];
- al_effect_props_.Reverb.ReflectionsPan[1] = efx_props.flReflectionsPan[1];
- al_effect_props_.Reverb.ReflectionsPan[2] = efx_props.flReflectionsPan[2];
- al_effect_props_.Reverb.LateReverbGain = efx_props.flLateReverbGain;
- al_effect_props_.Reverb.LateReverbDelay = efx_props.flLateReverbDelay;
- al_effect_props_.Reverb.LateReverbPan[0] = efx_props.flLateReverbPan[0];
- al_effect_props_.Reverb.LateReverbPan[1] = efx_props.flLateReverbPan[1];
- al_effect_props_.Reverb.LateReverbPan[2] = efx_props.flLateReverbPan[2];
- al_effect_props_.Reverb.EchoTime = efx_props.flEchoTime;
- al_effect_props_.Reverb.EchoDepth = efx_props.flEchoDepth;
- al_effect_props_.Reverb.ModulationTime = efx_props.flModulationTime;
- al_effect_props_.Reverb.ModulationDepth = efx_props.flModulationDepth;
- al_effect_props_.Reverb.HFReference = efx_props.flHFReference;
- al_effect_props_.Reverb.LFReference = efx_props.flLFReference;
- al_effect_props_.Reverb.RoomRolloffFactor = efx_props.flRoomRolloffFactor;
- al_effect_props_.Reverb.AirAbsorptionGainHF = efx_props.flAirAbsorptionGainHF;
- al_effect_props_.Reverb.DecayHFLimit = false;
-}
-
-void EaxReverbEffect::defer_environment(
- unsigned long ulEnvironment)
-{
- eax_d_.ulEnvironment = ulEnvironment;
- eax_dirty_flags_.ulEnvironment = (eax_.ulEnvironment != eax_d_.ulEnvironment);
-}
-
-void EaxReverbEffect::defer_environment_size(
- float flEnvironmentSize)
-{
- eax_d_.flEnvironmentSize = flEnvironmentSize;
- eax_dirty_flags_.flEnvironmentSize = (eax_.flEnvironmentSize != eax_d_.flEnvironmentSize);
-}
-
-void EaxReverbEffect::defer_environment_diffusion(
- float flEnvironmentDiffusion)
-{
- eax_d_.flEnvironmentDiffusion = flEnvironmentDiffusion;
- eax_dirty_flags_.flEnvironmentDiffusion = (eax_.flEnvironmentDiffusion != eax_d_.flEnvironmentDiffusion);
-}
-
-void EaxReverbEffect::defer_room(
- long lRoom)
-{
- eax_d_.lRoom = lRoom;
- eax_dirty_flags_.lRoom = (eax_.lRoom != eax_d_.lRoom);
-}
-
-void EaxReverbEffect::defer_room_hf(
- long lRoomHF)
-{
- eax_d_.lRoomHF = lRoomHF;
- eax_dirty_flags_.lRoomHF = (eax_.lRoomHF != eax_d_.lRoomHF);
-}
-
-void EaxReverbEffect::defer_room_lf(
- long lRoomLF)
-{
- eax_d_.lRoomLF = lRoomLF;
- eax_dirty_flags_.lRoomLF = (eax_.lRoomLF != eax_d_.lRoomLF);
-}
-
-void EaxReverbEffect::defer_decay_time(
- float flDecayTime)
-{
- eax_d_.flDecayTime = flDecayTime;
- eax_dirty_flags_.flDecayTime = (eax_.flDecayTime != eax_d_.flDecayTime);
-}
-
-void EaxReverbEffect::defer_decay_hf_ratio(
- float flDecayHFRatio)
-{
- eax_d_.flDecayHFRatio = flDecayHFRatio;
- eax_dirty_flags_.flDecayHFRatio = (eax_.flDecayHFRatio != eax_d_.flDecayHFRatio);
-}
-
-void EaxReverbEffect::defer_decay_lf_ratio(
- float flDecayLFRatio)
-{
- eax_d_.flDecayLFRatio = flDecayLFRatio;
- eax_dirty_flags_.flDecayLFRatio = (eax_.flDecayLFRatio != eax_d_.flDecayLFRatio);
-}
-
-void EaxReverbEffect::defer_reflections(
- long lReflections)
-{
- eax_d_.lReflections = lReflections;
- eax_dirty_flags_.lReflections = (eax_.lReflections != eax_d_.lReflections);
-}
-
-void EaxReverbEffect::defer_reflections_delay(
- float flReflectionsDelay)
-{
- eax_d_.flReflectionsDelay = flReflectionsDelay;
- eax_dirty_flags_.flReflectionsDelay = (eax_.flReflectionsDelay != eax_d_.flReflectionsDelay);
-}
-
-void EaxReverbEffect::defer_reflections_pan(
- const EAXVECTOR& vReflectionsPan)
-{
- eax_d_.vReflectionsPan = vReflectionsPan;
- eax_dirty_flags_.vReflectionsPan = (eax_.vReflectionsPan != eax_d_.vReflectionsPan);
-}
-
-void EaxReverbEffect::defer_reverb(
- long lReverb)
-{
- eax_d_.lReverb = lReverb;
- eax_dirty_flags_.lReverb = (eax_.lReverb != eax_d_.lReverb);
-}
-
-void EaxReverbEffect::defer_reverb_delay(
- float flReverbDelay)
-{
- eax_d_.flReverbDelay = flReverbDelay;
- eax_dirty_flags_.flReverbDelay = (eax_.flReverbDelay != eax_d_.flReverbDelay);
-}
-
-void EaxReverbEffect::defer_reverb_pan(
- const EAXVECTOR& vReverbPan)
-{
- eax_d_.vReverbPan = vReverbPan;
- eax_dirty_flags_.vReverbPan = (eax_.vReverbPan != eax_d_.vReverbPan);
-}
-
-void EaxReverbEffect::defer_echo_time(
- float flEchoTime)
-{
- eax_d_.flEchoTime = flEchoTime;
- eax_dirty_flags_.flEchoTime = (eax_.flEchoTime != eax_d_.flEchoTime);
-}
-
-void EaxReverbEffect::defer_echo_depth(
- float flEchoDepth)
-{
- eax_d_.flEchoDepth = flEchoDepth;
- eax_dirty_flags_.flEchoDepth = (eax_.flEchoDepth != eax_d_.flEchoDepth);
-}
-
-void EaxReverbEffect::defer_modulation_time(
- float flModulationTime)
-{
- eax_d_.flModulationTime = flModulationTime;
- eax_dirty_flags_.flModulationTime = (eax_.flModulationTime != eax_d_.flModulationTime);
-}
-
-void EaxReverbEffect::defer_modulation_depth(
- float flModulationDepth)
-{
- eax_d_.flModulationDepth = flModulationDepth;
- eax_dirty_flags_.flModulationDepth = (eax_.flModulationDepth != eax_d_.flModulationDepth);
-}
-
-void EaxReverbEffect::defer_air_absorbtion_hf(
- float flAirAbsorptionHF)
-{
- eax_d_.flAirAbsorptionHF = flAirAbsorptionHF;
- eax_dirty_flags_.flAirAbsorptionHF = (eax_.flAirAbsorptionHF != eax_d_.flAirAbsorptionHF);
-}
-
-void EaxReverbEffect::defer_hf_reference(
- float flHFReference)
-{
- eax_d_.flHFReference = flHFReference;
- eax_dirty_flags_.flHFReference = (eax_.flHFReference != eax_d_.flHFReference);
-}
-
-void EaxReverbEffect::defer_lf_reference(
- float flLFReference)
-{
- eax_d_.flLFReference = flLFReference;
- eax_dirty_flags_.flLFReference = (eax_.flLFReference != eax_d_.flLFReference);
-}
-
-void EaxReverbEffect::defer_room_rolloff_factor(
- float flRoomRolloffFactor)
-{
- eax_d_.flRoomRolloffFactor = flRoomRolloffFactor;
- eax_dirty_flags_.flRoomRolloffFactor = (eax_.flRoomRolloffFactor != eax_d_.flRoomRolloffFactor);
-}
-
-void EaxReverbEffect::defer_flags(
- unsigned long ulFlags)
-{
- eax_d_.ulFlags = ulFlags;
- eax_dirty_flags_.ulFlags = (eax_.ulFlags != eax_d_.ulFlags);
-}
-
-void EaxReverbEffect::defer_all(
- const EAX20LISTENERPROPERTIES& listener)
-{
- defer_room(listener.lRoom);
- defer_room_hf(listener.lRoomHF);
- defer_room_rolloff_factor(listener.flRoomRolloffFactor);
- defer_decay_time(listener.flDecayTime);
- defer_decay_hf_ratio(listener.flDecayHFRatio);
- defer_reflections(listener.lReflections);
- defer_reflections_delay(listener.flReflectionsDelay);
- defer_reverb(listener.lReverb);
- defer_reverb_delay(listener.flReverbDelay);
- defer_environment(listener.dwEnvironment);
- defer_environment_size(listener.flEnvironmentSize);
- defer_environment_diffusion(listener.flEnvironmentDiffusion);
- defer_air_absorbtion_hf(listener.flAirAbsorptionHF);
- defer_flags(listener.dwFlags);
-}
-
-void EaxReverbEffect::defer_all(
- const EAXREVERBPROPERTIES& lReverb)
-{
- defer_environment(lReverb.ulEnvironment);
- defer_environment_size(lReverb.flEnvironmentSize);
- defer_environment_diffusion(lReverb.flEnvironmentDiffusion);
- defer_room(lReverb.lRoom);
- defer_room_hf(lReverb.lRoomHF);
- defer_room_lf(lReverb.lRoomLF);
- defer_decay_time(lReverb.flDecayTime);
- defer_decay_hf_ratio(lReverb.flDecayHFRatio);
- defer_decay_lf_ratio(lReverb.flDecayLFRatio);
- defer_reflections(lReverb.lReflections);
- defer_reflections_delay(lReverb.flReflectionsDelay);
- defer_reflections_pan(lReverb.vReflectionsPan);
- defer_reverb(lReverb.lReverb);
- defer_reverb_delay(lReverb.flReverbDelay);
- defer_reverb_pan(lReverb.vReverbPan);
- defer_echo_time(lReverb.flEchoTime);
- defer_echo_depth(lReverb.flEchoDepth);
- defer_modulation_time(lReverb.flModulationTime);
- defer_modulation_depth(lReverb.flModulationDepth);
- defer_air_absorbtion_hf(lReverb.flAirAbsorptionHF);
- defer_hf_reference(lReverb.flHFReference);
- defer_lf_reference(lReverb.flLFReference);
- defer_room_rolloff_factor(lReverb.flRoomRolloffFactor);
- defer_flags(lReverb.ulFlags);
-}
-
-
-void EaxReverbEffect::v1_defer_environment(const EaxEaxCall& eax_call)
-{
- const auto& environment = eax_call.get_value<EaxReverbEffectException,
- const decltype(EAX_REVERBPROPERTIES::environment)>();
-
- validate_environment(environment, 1, true);
-
- const auto& reverb_preset = EAX1REVERB_PRESETS[environment];
- v1_defer_all(reverb_preset);
-}
-
-void EaxReverbEffect::v1_defer_volume(const EaxEaxCall& eax_call)
-{
- const auto& volume = eax_call.get_value<EaxReverbEffectException,
- const decltype(EAX_REVERBPROPERTIES::fVolume)>();
-
- v1_validate_volume(volume);
- v1_defer_volume(volume);
-}
-
-void EaxReverbEffect::v1_defer_decay_time(const EaxEaxCall& eax_call)
-{
- const auto& decay_time = eax_call.get_value<EaxReverbEffectException,
- const decltype(EAX_REVERBPROPERTIES::fDecayTime_sec)>();
-
- v1_validate_decay_time(decay_time);
- v1_defer_decay_time(decay_time);
-}
-
-void EaxReverbEffect::v1_defer_damping(const EaxEaxCall& eax_call)
-{
- const auto& damping = eax_call.get_value<EaxReverbEffectException,
- const decltype(EAX_REVERBPROPERTIES::fDamping)>();
-
- v1_validate_damping(damping);
- v1_defer_damping(damping);
-}
-
-void EaxReverbEffect::v1_defer_all(const EaxEaxCall& eax_call)
-{
- const auto& reverb_all = eax_call.get_value<EaxReverbEffectException,
- const EAX_REVERBPROPERTIES>();
-
- v1_validate_all(reverb_all);
- v1_defer_all(reverb_all);
-}
-
-
-void EaxReverbEffect::defer_environment(
- const EaxEaxCall& eax_call)
-{
- const auto& ulEnvironment =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::ulEnvironment)>();
-
- validate_environment(ulEnvironment, eax_call.get_version(), true);
-
- if (eax_d_.ulEnvironment == ulEnvironment)
- {
- return;
- }
-
- const auto& reverb_preset = EAXREVERB_PRESETS[ulEnvironment];
-
- defer_all(reverb_preset);
-}
-
-void EaxReverbEffect::defer_environment_size(
- const EaxEaxCall& eax_call)
-{
- const auto& flEnvironmentSize =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEnvironmentSize)>();
-
- validate_environment_size(flEnvironmentSize);
-
- if (eax_d_.flEnvironmentSize == flEnvironmentSize)
- {
- return;
- }
-
- const auto scale = flEnvironmentSize / eax_d_.flEnvironmentSize;
-
- defer_environment_size(flEnvironmentSize);
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0)
- {
- const auto flDecayTime = clamp(
- scale * eax_d_.flDecayTime,
- EAXREVERB_MINDECAYTIME,
- EAXREVERB_MAXDECAYTIME);
-
- defer_decay_time(flDecayTime);
- }
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0)
- {
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
- {
- const auto lReflections = clamp(
- eax_d_.lReflections - static_cast<long>(gain_to_level_mb(scale)),
- EAXREVERB_MINREFLECTIONS,
- EAXREVERB_MAXREFLECTIONS);
-
- defer_reflections(lReflections);
- }
- }
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
- {
- const auto flReflectionsDelay = clamp(
- eax_d_.flReflectionsDelay * scale,
- EAXREVERB_MINREFLECTIONSDELAY,
- EAXREVERB_MAXREFLECTIONSDELAY);
-
- defer_reflections_delay(flReflectionsDelay);
- }
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0)
+ switch (version)
{
- const auto log_scalar = ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
-
- const auto lReverb = clamp(
- eax_d_.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
- EAXREVERB_MINREVERB,
- EAXREVERB_MAXREVERB);
-
- defer_reverb(lReverb);
- }
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0)
- {
- const auto flReverbDelay = clamp(
- scale * eax_d_.flReverbDelay,
- EAXREVERB_MINREVERBDELAY,
- EAXREVERB_MAXREVERBDELAY);
-
- defer_reverb_delay(flReverbDelay);
- }
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0)
- {
- const auto flEchoTime = clamp(
- eax_d_.flEchoTime * scale,
- EAXREVERB_MINECHOTIME,
- EAXREVERB_MAXECHOTIME);
-
- defer_echo_time(flEchoTime);
- }
-
- if ((eax_d_.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0)
- {
- const auto flModulationTime = clamp(
- scale * eax_d_.flModulationTime,
- EAXREVERB_MINMODULATIONTIME,
- EAXREVERB_MAXMODULATIONTIME);
-
- defer_modulation_time(flModulationTime);
+ case 1: get1(call, state1_.i); break;
+ case 2: get2(call, state2_.i); break;
+ case 3: get3(call, state3_.i); break;
+ case 4: get3(call, state4_.i); break;
+ case 5: get3(call, state5_.i); break;
+ default: fail_unknown_version();
}
-}
-
-void EaxReverbEffect::defer_environment_diffusion(
- const EaxEaxCall& eax_call)
-{
- const auto& flEnvironmentDiffusion =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEnvironmentDiffusion)>();
-
- validate_environment_diffusion(flEnvironmentDiffusion);
- defer_environment_diffusion(flEnvironmentDiffusion);
-}
-
-void EaxReverbEffect::defer_room(
- const EaxEaxCall& eax_call)
-{
- const auto& lRoom =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lRoom)>();
-
- validate_room(lRoom);
- defer_room(lRoom);
-}
-
-void EaxReverbEffect::defer_room_hf(
- const EaxEaxCall& eax_call)
-{
- const auto& lRoomHF =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lRoomHF)>();
-
- validate_room_hf(lRoomHF);
- defer_room_hf(lRoomHF);
-}
-
-void EaxReverbEffect::defer_room_lf(
- const EaxEaxCall& eax_call)
-{
- const auto& lRoomLF =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lRoomLF)>();
-
- validate_room_lf(lRoomLF);
- defer_room_lf(lRoomLF);
-}
-
-void EaxReverbEffect::defer_decay_time(
- const EaxEaxCall& eax_call)
-{
- const auto& flDecayTime =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flDecayTime)>();
-
- validate_decay_time(flDecayTime);
- defer_decay_time(flDecayTime);
-}
-
-void EaxReverbEffect::defer_decay_hf_ratio(
- const EaxEaxCall& eax_call)
-{
- const auto& flDecayHFRatio =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flDecayHFRatio)>();
-
- validate_decay_hf_ratio(flDecayHFRatio);
- defer_decay_hf_ratio(flDecayHFRatio);
-}
-
-void EaxReverbEffect::defer_decay_lf_ratio(
- const EaxEaxCall& eax_call)
-{
- const auto& flDecayLFRatio =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flDecayLFRatio)>();
-
- validate_decay_lf_ratio(flDecayLFRatio);
- defer_decay_lf_ratio(flDecayLFRatio);
-}
-
-void EaxReverbEffect::defer_reflections(
- const EaxEaxCall& eax_call)
-{
- const auto& lReflections =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lReflections)>();
-
- validate_reflections(lReflections);
- defer_reflections(lReflections);
-}
-
-void EaxReverbEffect::defer_reflections_delay(
- const EaxEaxCall& eax_call)
-{
- const auto& flReflectionsDelay =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flReflectionsDelay)>();
-
- validate_reflections_delay(flReflectionsDelay);
- defer_reflections_delay(flReflectionsDelay);
-}
-
-void EaxReverbEffect::defer_reflections_pan(
- const EaxEaxCall& eax_call)
-{
- const auto& vReflectionsPan =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::vReflectionsPan)>();
-
- validate_reflections_pan(vReflectionsPan);
- defer_reflections_pan(vReflectionsPan);
-}
-
-void EaxReverbEffect::defer_reverb(
- const EaxEaxCall& eax_call)
-{
- const auto& lReverb =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::lReverb)>();
-
- validate_reverb(lReverb);
- defer_reverb(lReverb);
-}
-
-void EaxReverbEffect::defer_reverb_delay(
- const EaxEaxCall& eax_call)
-{
- const auto& flReverbDelay =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flReverbDelay)>();
-
- validate_reverb_delay(flReverbDelay);
- defer_reverb_delay(flReverbDelay);
-}
-
-void EaxReverbEffect::defer_reverb_pan(
- const EaxEaxCall& eax_call)
-{
- const auto& vReverbPan =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::vReverbPan)>();
-
- validate_reverb_pan(vReverbPan);
- defer_reverb_pan(vReverbPan);
-}
-
-void EaxReverbEffect::defer_echo_time(
- const EaxEaxCall& eax_call)
-{
- const auto& flEchoTime =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEchoTime)>();
-
- validate_echo_time(flEchoTime);
- defer_echo_time(flEchoTime);
-}
-
-void EaxReverbEffect::defer_echo_depth(
- const EaxEaxCall& eax_call)
-{
- const auto& flEchoDepth =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flEchoDepth)>();
-
- validate_echo_depth(flEchoDepth);
- defer_echo_depth(flEchoDepth);
-}
-
-void EaxReverbEffect::defer_modulation_time(
- const EaxEaxCall& eax_call)
-{
- const auto& flModulationTime =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flModulationTime)>();
-
- validate_modulation_time(flModulationTime);
- defer_modulation_time(flModulationTime);
-}
-
-void EaxReverbEffect::defer_modulation_depth(
- const EaxEaxCall& eax_call)
-{
- const auto& flModulationDepth =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flModulationDepth)>();
-
- validate_modulation_depth(flModulationDepth);
- defer_modulation_depth(flModulationDepth);
-}
-
-void EaxReverbEffect::defer_air_absorbtion_hf(
- const EaxEaxCall& eax_call)
-{
- const auto& air_absorbtion_hf =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flAirAbsorptionHF)>();
- validate_air_absorbtion_hf(air_absorbtion_hf);
- defer_air_absorbtion_hf(air_absorbtion_hf);
+ version_ = version;
}
-void EaxReverbEffect::defer_hf_reference(
- const EaxEaxCall& eax_call)
+/*[[nodiscard]]*/ bool EaxReverbEffect::commit()
{
- const auto& flHFReference =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flHFReference)>();
-
- validate_hf_reference(flHFReference);
- defer_hf_reference(flHFReference);
-}
-
-void EaxReverbEffect::defer_lf_reference(
- const EaxEaxCall& eax_call)
-{
- const auto& flLFReference =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flLFReference)>();
-
- validate_lf_reference(flLFReference);
- defer_lf_reference(flLFReference);
-}
-
-void EaxReverbEffect::defer_room_rolloff_factor(
- const EaxEaxCall& eax_call)
-{
- const auto& flRoomRolloffFactor =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::flRoomRolloffFactor)>();
-
- validate_room_rolloff_factor(flRoomRolloffFactor);
- defer_room_rolloff_factor(flRoomRolloffFactor);
-}
-
-void EaxReverbEffect::defer_flags(
- const EaxEaxCall& eax_call)
-{
- const auto& ulFlags =
- eax_call.get_value<EaxReverbEffectException, const decltype(EAXREVERBPROPERTIES::ulFlags)>();
-
- validate_flags(ulFlags);
- defer_flags(ulFlags);
-}
-
-void EaxReverbEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto eax_version = eax_call.get_version();
-
- if (eax_version == 2)
+ if ((version_ == 1 && state1_.i == state1_.d) ||
+ (version_ == 2 && state2_.i == state2_.d))
{
- const auto& listener =
- eax_call.get_value<EaxReverbEffectException, const EAX20LISTENERPROPERTIES>();
-
- validate_all(listener, eax_version);
- defer_all(listener);
- }
- else
- {
- const auto& reverb_all =
- eax_call.get_value<EaxReverbEffectException, const EAXREVERBPROPERTIES>();
-
- validate_all(reverb_all, eax_version);
- defer_all(reverb_all);
+ return false;
}
-}
+ const auto props = props_;
-void EaxReverbEffect::v1_defer(const EaxEaxCall& eax_call)
-{
- switch (eax_call.get_property_id())
+ switch (version_)
{
- case DSPROPERTY_EAX_ALL: return v1_defer_all(eax_call);
- case DSPROPERTY_EAX_ENVIRONMENT: return v1_defer_environment(eax_call);
- case DSPROPERTY_EAX_VOLUME: return v1_defer_volume(eax_call);
- case DSPROPERTY_EAX_DECAYTIME: return v1_defer_decay_time(eax_call);
- case DSPROPERTY_EAX_DAMPING: return v1_defer_damping(eax_call);
- default: eax_fail("Unsupported property id.");
- }
-}
+ case 1:
+ state1_.i = state1_.d;
+ translate(state1_.d, props_);
+ break;
-// [[nodiscard]]
-bool EaxReverbEffect::apply_deferred()
-{
- bool ret{false};
+ case 2:
+ state2_.i = state2_.d;
+ translate(state2_.d, props_);
+ break;
- if(unlikely(eax1_dirty_flags_ != Eax1ReverbEffectDirtyFlags{}))
- {
- eax1_ = eax1_d_;
+ case 3:
+ state3_.i = state3_.d;
+ props_ = state3_.d;
+ break;
- v1_set_efx();
+ case 4:
+ state4_.i = state4_.d;
+ props_ = state4_.d;
+ break;
- eax1_dirty_flags_ = Eax1ReverbEffectDirtyFlags{};
+ case 5:
+ state5_.i = state5_.d;
+ props_ = state5_.d;
+ break;
- ret = true;
+ default:
+ fail_unknown_version();
}
- if(eax_dirty_flags_ == EaxReverbEffectDirtyFlags{})
- return ret;
-
- eax_ = eax_d_;
-
- if (eax_dirty_flags_.ulEnvironment)
- {
- }
+ auto is_dirty = false;
- if (eax_dirty_flags_.flEnvironmentSize)
+ if (props_.flEnvironmentSize != props.flEnvironmentSize)
{
+ is_dirty = true;
set_efx_density_from_environment_size();
}
- if (eax_dirty_flags_.flEnvironmentDiffusion)
+ if (props_.flEnvironmentDiffusion != props.flEnvironmentDiffusion)
{
+ is_dirty = true;
set_efx_diffusion();
}
- if (eax_dirty_flags_.lRoom)
+ if (props_.lRoom != props.lRoom)
{
+ is_dirty = true;
set_efx_gain();
}
- if (eax_dirty_flags_.lRoomHF)
+ if (props_.lRoomHF != props.lRoomHF)
{
+ is_dirty = true;
set_efx_gain_hf();
}
- if (eax_dirty_flags_.lRoomLF)
+ if (props_.lRoomLF != props.lRoomLF)
{
+ is_dirty = true;
set_efx_gain_lf();
}
- if (eax_dirty_flags_.flDecayTime)
+ if (props_.flDecayTime != props.flDecayTime)
{
+ is_dirty = true;
set_efx_decay_time();
}
- if (eax_dirty_flags_.flDecayHFRatio)
+ if (props_.flDecayHFRatio != props.flDecayHFRatio)
{
+ is_dirty = true;
set_efx_decay_hf_ratio();
}
- if (eax_dirty_flags_.flDecayLFRatio)
+ if (props_.flDecayLFRatio != props.flDecayLFRatio)
{
+ is_dirty = true;
set_efx_decay_lf_ratio();
}
- if (eax_dirty_flags_.lReflections)
+ if (props_.lReflections != props.lReflections)
{
+ is_dirty = true;
set_efx_reflections_gain();
}
- if (eax_dirty_flags_.flReflectionsDelay)
+ if (props_.flReflectionsDelay != props.flReflectionsDelay)
{
+ is_dirty = true;
set_efx_reflections_delay();
}
- if (eax_dirty_flags_.vReflectionsPan)
+ if (props_.vReflectionsPan != props.vReflectionsPan)
{
+ is_dirty = true;
set_efx_reflections_pan();
}
- if (eax_dirty_flags_.lReverb)
+ if (props_.lReverb != props.lReverb)
{
+ is_dirty = true;
set_efx_late_reverb_gain();
}
- if (eax_dirty_flags_.flReverbDelay)
+ if (props_.flReverbDelay != props.flReverbDelay)
{
+ is_dirty = true;
set_efx_late_reverb_delay();
}
- if (eax_dirty_flags_.vReverbPan)
+ if (props_.vReverbPan != props.vReverbPan)
{
+ is_dirty = true;
set_efx_late_reverb_pan();
}
- if (eax_dirty_flags_.flEchoTime)
+ if (props_.flEchoTime != props.flEchoTime)
{
+ is_dirty = true;
set_efx_echo_time();
}
- if (eax_dirty_flags_.flEchoDepth)
+ if (props_.flEchoDepth != props.flEchoDepth)
{
+ is_dirty = true;
set_efx_echo_depth();
}
- if (eax_dirty_flags_.flModulationTime)
+ if (props_.flModulationTime != props.flModulationTime)
{
+ is_dirty = true;
set_efx_modulation_time();
}
- if (eax_dirty_flags_.flModulationDepth)
+ if (props_.flModulationDepth != props.flModulationDepth)
{
+ is_dirty = true;
set_efx_modulation_depth();
}
- if (eax_dirty_flags_.flAirAbsorptionHF)
+ if (props_.flAirAbsorptionHF != props.flAirAbsorptionHF)
{
+ is_dirty = true;
set_efx_air_absorption_gain_hf();
}
- if (eax_dirty_flags_.flHFReference)
+ if (props_.flHFReference != props.flHFReference)
{
+ is_dirty = true;
set_efx_hf_reference();
}
- if (eax_dirty_flags_.flLFReference)
+ if (props_.flLFReference != props.flLFReference)
{
+ is_dirty = true;
set_efx_lf_reference();
}
- if (eax_dirty_flags_.flRoomRolloffFactor)
+ if (props_.flRoomRolloffFactor != props.flRoomRolloffFactor)
{
+ is_dirty = true;
set_efx_room_rolloff_factor();
}
- if (eax_dirty_flags_.ulFlags)
+ if (props_.ulFlags != props.ulFlags)
{
+ is_dirty = true;
set_efx_flags();
}
- eax_dirty_flags_ = EaxReverbEffectDirtyFlags{};
+ return is_dirty;
+}
+
+void EaxReverbEffect::set1(const EaxCall& call, Props1& props)
+{
+ switch (call.get_property_id())
+ {
+ case DSPROPERTY_EAX_ALL: defer<AllValidator1>(call, props); break;
+ case DSPROPERTY_EAX_ENVIRONMENT: defer<EnvironmentValidator1>(call, props.environment); break;
+ case DSPROPERTY_EAX_VOLUME: defer<VolumeValidator>(call, props.fVolume); break;
+ case DSPROPERTY_EAX_DECAYTIME: defer<DecayTimeValidator>(call, props.fDecayTime_sec); break;
+ case DSPROPERTY_EAX_DAMPING: defer<DampingValidator>(call, props.fDamping); break;
+ default: fail_unknown_property_id();
+ }
+}
+
+void EaxReverbEffect::set2(const EaxCall& call, Props2& props)
+{
+ switch (call.get_property_id())
+ {
+ case DSPROPERTY_EAX20LISTENER_NONE:
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS:
+ defer<AllValidator2>(call, props);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_ROOM:
+ defer<RoomValidator>(call, props.lRoom);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_ROOMHF:
+ defer<RoomHFValidator>(call, props.lRoomHF);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR:
+ defer<RoomRolloffFactorValidator>(call, props.flRoomRolloffFactor);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_DECAYTIME:
+ defer<DecayTimeValidator>(call, props.flDecayTime);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO:
+ defer<DecayHFRatioValidator>(call, props.flDecayHFRatio);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_REFLECTIONS:
+ defer<ReflectionsValidator>(call, props.lReflections);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY:
+ defer<ReflectionsDelayValidator>(call, props.flReverbDelay);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_REVERB:
+ defer<ReverbValidator>(call, props.lReverb);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_REVERBDELAY:
+ defer<ReverbDelayValidator>(call, props.flReverbDelay);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_ENVIRONMENT:
+ defer<EnvironmentValidator1, EnvironmentDeferrer2>(call, props, props.dwEnvironment);
+ break;
- return true;
+ case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE:
+ defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer2>(call, props, props.flEnvironmentSize);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION:
+ defer<EnvironmentDiffusionValidator>(call, props.flEnvironmentDiffusion);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF:
+ defer<AirAbsorptionHFValidator>(call, props.flAirAbsorptionHF);
+ break;
+
+ case DSPROPERTY_EAX20LISTENER_FLAGS:
+ defer<FlagsValidator2>(call, props.dwFlags);
+ break;
+
+ default:
+ fail_unknown_property_id();
+ }
}
-void EaxReverbEffect::set(const EaxEaxCall& eax_call)
+void EaxReverbEffect::set3(const EaxCall& call, Props3& props)
{
- if(eax_call.get_version() == 1)
- v1_defer(eax_call);
- else switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
case EAXREVERB_NONE:
break;
case EAXREVERB_ALLPARAMETERS:
- defer_all(eax_call);
+ defer<AllValidator3>(call, props);
break;
case EAXREVERB_ENVIRONMENT:
- defer_environment(eax_call);
+ defer<EnvironmentValidator3, EnvironmentDeferrer3>(call, props, props.ulEnvironment);
break;
case EAXREVERB_ENVIRONMENTSIZE:
- defer_environment_size(eax_call);
+ defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer3>(call, props, props.flEnvironmentSize);
break;
case EAXREVERB_ENVIRONMENTDIFFUSION:
- defer_environment_diffusion(eax_call);
+ defer3<EnvironmentDiffusionValidator>(call, props, props.flEnvironmentDiffusion);
break;
case EAXREVERB_ROOM:
- defer_room(eax_call);
+ defer3<RoomValidator>(call, props, props.lRoom);
break;
case EAXREVERB_ROOMHF:
- defer_room_hf(eax_call);
+ defer3<RoomHFValidator>(call, props, props.lRoomHF);
break;
case EAXREVERB_ROOMLF:
- defer_room_lf(eax_call);
+ defer3<RoomLFValidator>(call, props, props.lRoomLF);
break;
case EAXREVERB_DECAYTIME:
- defer_decay_time(eax_call);
+ defer3<DecayTimeValidator>(call, props, props.flDecayTime);
break;
case EAXREVERB_DECAYHFRATIO:
- defer_decay_hf_ratio(eax_call);
+ defer3<DecayHFRatioValidator>(call, props, props.flDecayHFRatio);
break;
case EAXREVERB_DECAYLFRATIO:
- defer_decay_lf_ratio(eax_call);
+ defer3<DecayLFRatioValidator>(call, props, props.flDecayLFRatio);
break;
case EAXREVERB_REFLECTIONS:
- defer_reflections(eax_call);
+ defer3<ReflectionsValidator>(call, props, props.lReflections);
break;
case EAXREVERB_REFLECTIONSDELAY:
- defer_reflections_delay(eax_call);
+ defer3<ReflectionsDelayValidator>(call, props, props.flReflectionsDelay);
break;
case EAXREVERB_REFLECTIONSPAN:
- defer_reflections_pan(eax_call);
+ defer3<VectorValidator>(call, props, props.vReflectionsPan);
break;
case EAXREVERB_REVERB:
- defer_reverb(eax_call);
+ defer3<ReverbValidator>(call, props, props.lReverb);
break;
case EAXREVERB_REVERBDELAY:
- defer_reverb_delay(eax_call);
+ defer3<ReverbDelayValidator>(call, props, props.flReverbDelay);
break;
case EAXREVERB_REVERBPAN:
- defer_reverb_pan(eax_call);
+ defer3<VectorValidator>(call, props, props.vReverbPan);
break;
case EAXREVERB_ECHOTIME:
- defer_echo_time(eax_call);
+ defer3<EchoTimeValidator>(call, props, props.flEchoTime);
break;
case EAXREVERB_ECHODEPTH:
- defer_echo_depth(eax_call);
+ defer3<EchoDepthValidator>(call, props, props.flEchoDepth);
break;
case EAXREVERB_MODULATIONTIME:
- defer_modulation_time(eax_call);
+ defer3<ModulationTimeValidator>(call, props, props.flModulationTime);
break;
case EAXREVERB_MODULATIONDEPTH:
- defer_modulation_depth(eax_call);
+ defer3<ModulationDepthValidator>(call, props, props.flModulationDepth);
break;
case EAXREVERB_AIRABSORPTIONHF:
- defer_air_absorbtion_hf(eax_call);
+ defer3<AirAbsorptionHFValidator>(call, props, props.flAirAbsorptionHF);
break;
case EAXREVERB_HFREFERENCE:
- defer_hf_reference(eax_call);
+ defer3<HFReferenceValidator>(call, props, props.flHFReference);
break;
case EAXREVERB_LFREFERENCE:
- defer_lf_reference(eax_call);
+ defer3<LFReferenceValidator>(call, props, props.flLFReference);
break;
case EAXREVERB_ROOMROLLOFFFACTOR:
- defer_room_rolloff_factor(eax_call);
+ defer3<RoomRolloffFactorValidator>(call, props, props.flRoomRolloffFactor);
break;
case EAXREVERB_FLAGS:
- defer_flags(eax_call);
+ defer3<FlagsValidator3>(call, props, props.ulFlags);
break;
default:
- eax_fail("Unsupported property id.");
+ fail_unknown_property_id();
}
}
-const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[EAX1_ENVIRONMENT_COUNT] =
+void EaxReverbEffect::set(const EaxCall& call)
{
- EFX_REVERB_PRESET_GENERIC,
- EFX_REVERB_PRESET_PADDEDCELL,
- EFX_REVERB_PRESET_ROOM,
- EFX_REVERB_PRESET_BATHROOM,
- EFX_REVERB_PRESET_LIVINGROOM,
- EFX_REVERB_PRESET_STONEROOM,
- EFX_REVERB_PRESET_AUDITORIUM,
- EFX_REVERB_PRESET_CONCERTHALL,
- EFX_REVERB_PRESET_CAVE,
- EFX_REVERB_PRESET_ARENA,
- EFX_REVERB_PRESET_HANGAR,
- EFX_REVERB_PRESET_CARPETEDHALLWAY,
- EFX_REVERB_PRESET_HALLWAY,
- EFX_REVERB_PRESET_STONECORRIDOR,
- EFX_REVERB_PRESET_ALLEY,
- EFX_REVERB_PRESET_FOREST,
- EFX_REVERB_PRESET_CITY,
- EFX_REVERB_PRESET_MOUNTAINS,
- EFX_REVERB_PRESET_QUARRY,
- EFX_REVERB_PRESET_PLAIN,
- EFX_REVERB_PRESET_PARKINGLOT,
- EFX_REVERB_PRESET_SEWERPIPE,
- EFX_REVERB_PRESET_UNDERWATER,
- EFX_REVERB_PRESET_DRUGGED,
- EFX_REVERB_PRESET_DIZZY,
- EFX_REVERB_PRESET_PSYCHOTIC,
-}; // EFXEAXREVERBPROPERTIES
+ const auto version = call.get_version();
+
+ switch (version)
+ {
+ case 1: set1(call, state1_.d); break;
+ case 2: set2(call, state2_.d); break;
+ case 3: set3(call, state3_.d); break;
+ case 4: set3(call, state4_.d); break;
+ case 5: set3(call, state5_.d); break;
+ default: fail_unknown_version();
+ }
+
+ version_ = version;
+}
+
+void EaxReverbEffect::translate(const Props1& src, Props3& dst) noexcept
+{
+ assert(src.environment <= EAX1REVERB_MAXENVIRONMENT);
+ dst = EAXREVERB_PRESETS[src.environment];
+ dst.flDecayTime = src.fDecayTime_sec;
+ dst.flDecayHFRatio = src.fDamping;
+ dst.lReverb = mini(static_cast<int>(gain_to_level_mb(src.fVolume)), 0);
+}
+
+void EaxReverbEffect::translate(const Props2& src, Props3& dst) noexcept
+{
+ assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT);
+ const auto& env = EAXREVERB_PRESETS[src.dwEnvironment];
+ dst.ulEnvironment = src.dwEnvironment;
+ dst.flEnvironmentSize = src.flEnvironmentSize;
+ dst.flEnvironmentDiffusion = src.flEnvironmentDiffusion;
+ dst.lRoom = src.lRoom;
+ dst.lRoomHF = src.lRoomHF;
+ dst.lRoomLF = env.lRoomLF;
+ dst.flDecayTime = src.flDecayTime;
+ dst.flDecayHFRatio = src.flDecayHFRatio;
+ dst.flDecayLFRatio = env.flDecayLFRatio;
+ dst.lReflections = src.lReflections;
+ dst.flReflectionsDelay = src.flReflectionsDelay;
+ dst.vReflectionsPan = env.vReflectionsPan;
+ dst.lReverb = src.lReverb;
+ dst.flReverbDelay = src.flReverbDelay;
+ dst.vReverbPan = env.vReverbPan;
+ dst.flEchoTime = env.flEchoTime;
+ dst.flEchoDepth = env.flEchoDepth;
+ dst.flModulationTime = env.flModulationTime;
+ dst.flModulationDepth = env.flModulationDepth;
+ dst.flAirAbsorptionHF = src.flAirAbsorptionHF;
+ dst.flHFReference = env.flHFReference;
+ dst.flLFReference = env.flLFReference;
+ dst.flRoomRolloffFactor = src.flRoomRolloffFactor;
+ dst.ulFlags = src.dwFlags;
+}
} // namespace
-EaxEffectUPtr eax_create_eax_reverb_effect()
+EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call)
{
- return std::make_unique<EaxReverbEffect>();
+ return std::make_unique<EaxReverbEffect>(call);
}
#endif // ALSOFT_EAX
diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp
index da513015..95f98db5 100644
--- a/al/effects/vmorpher.cpp
+++ b/al/effects/vmorpher.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
@@ -260,178 +258,181 @@ const EffectProps VmorpherEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
-using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t;
-
-struct EaxVocalMorpherEffectDirtyFlags
-{
- using EaxIsBitFieldStruct = bool;
-
- EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeA : 1;
- EaxVocalMorpherEffectDirtyFlagsValue lPhonemeACoarseTuning : 1;
- EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeB : 1;
- EaxVocalMorpherEffectDirtyFlagsValue lPhonemeBCoarseTuning : 1;
- EaxVocalMorpherEffectDirtyFlagsValue ulWaveform : 1;
- EaxVocalMorpherEffectDirtyFlagsValue flRate : 1;
-}; // EaxPitchShifterEffectDirtyFlags
-
-
-class EaxVocalMorpherEffect final :
- public EaxEffect
-{
+class EaxVocalMorpherEffectException : public EaxException {
public:
- EaxVocalMorpherEffect();
-
- void dispatch(const EaxEaxCall& eax_call) override;
+ explicit EaxVocalMorpherEffectException(const char* message)
+ : EaxException{"EAX_VOCAL_MORPHER_EFFECT", message}
+ {}
+}; // EaxVocalMorpherEffectException
- // [[nodiscard]]
- bool apply_deferred() override;
+class EaxVocalMorpherEffect final : public EaxEffect4<EaxVocalMorpherEffectException, EAXVOCALMORPHERPROPERTIES> {
+public:
+ EaxVocalMorpherEffect(const EaxCall& call);
private:
- EAXVOCALMORPHERPROPERTIES eax_{};
- EAXVOCALMORPHERPROPERTIES eax_d_{};
- EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{};
-
- void set_eax_defaults();
+ struct PhonemeAValidator {
+ void operator()(unsigned long ulPhonemeA) const
+ {
+ eax_validate_range<Exception>(
+ "Phoneme A",
+ ulPhonemeA,
+ EAXVOCALMORPHER_MINPHONEMEA,
+ EAXVOCALMORPHER_MAXPHONEMEA);
+ }
+ }; // PhonemeAValidator
+
+ struct PhonemeACoarseTuningValidator {
+ void operator()(long lPhonemeACoarseTuning) const
+ {
+ eax_validate_range<Exception>(
+ "Phoneme A Coarse Tuning",
+ lPhonemeACoarseTuning,
+ EAXVOCALMORPHER_MINPHONEMEACOARSETUNING,
+ EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING);
+ }
+ }; // PhonemeACoarseTuningValidator
+
+ struct PhonemeBValidator {
+ void operator()(unsigned long ulPhonemeB) const
+ {
+ eax_validate_range<Exception>(
+ "Phoneme B",
+ ulPhonemeB,
+ EAXVOCALMORPHER_MINPHONEMEB,
+ EAXVOCALMORPHER_MAXPHONEMEB);
+ }
+ }; // PhonemeBValidator
+
+ struct PhonemeBCoarseTuningValidator {
+ void operator()(long lPhonemeBCoarseTuning) const
+ {
+ eax_validate_range<Exception>(
+ "Phoneme B Coarse Tuning",
+ lPhonemeBCoarseTuning,
+ EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING,
+ EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING);
+ }
+ }; // PhonemeBCoarseTuningValidator
+
+ struct WaveformValidator {
+ void operator()(unsigned long ulWaveform) const
+ {
+ eax_validate_range<Exception>(
+ "Waveform",
+ ulWaveform,
+ EAXVOCALMORPHER_MINWAVEFORM,
+ EAXVOCALMORPHER_MAXWAVEFORM);
+ }
+ }; // WaveformValidator
+
+ struct RateValidator {
+ void operator()(float flRate) const
+ {
+ eax_validate_range<Exception>(
+ "Rate",
+ flRate,
+ EAXVOCALMORPHER_MINRATE,
+ EAXVOCALMORPHER_MAXRATE);
+ }
+ }; // RateValidator
+
+ struct AllValidator {
+ void operator()(const Props& all) const
+ {
+ PhonemeAValidator{}(all.ulPhonemeA);
+ PhonemeACoarseTuningValidator{}(all.lPhonemeACoarseTuning);
+ PhonemeBValidator{}(all.ulPhonemeB);
+ PhonemeBCoarseTuningValidator{}(all.lPhonemeBCoarseTuning);
+ WaveformValidator{}(all.ulWaveform);
+ RateValidator{}(all.flRate);
+ }
+ }; // AllValidator
+
+ void set_defaults(Props& props) override;
void set_efx_phoneme_a();
- void set_efx_phoneme_a_coarse_tuning();
+ void set_efx_phoneme_a_coarse_tuning() noexcept;
void set_efx_phoneme_b();
- void set_efx_phoneme_b_coarse_tuning();
+ void set_efx_phoneme_b_coarse_tuning() noexcept;
void set_efx_waveform();
- void set_efx_rate();
- void set_efx_defaults();
-
- void get(const EaxEaxCall& eax_call);
-
- void validate_phoneme_a(unsigned long ulPhonemeA);
- void validate_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning);
- void validate_phoneme_b(unsigned long ulPhonemeB);
- void validate_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning);
- void validate_waveform(unsigned long ulWaveform);
- void validate_rate(float flRate);
- void validate_all(const EAXVOCALMORPHERPROPERTIES& all);
-
- void defer_phoneme_a(unsigned long ulPhonemeA);
- void defer_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning);
- void defer_phoneme_b(unsigned long ulPhonemeB);
- void defer_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning);
- void defer_waveform(unsigned long ulWaveform);
- void defer_rate(float flRate);
- void defer_all(const EAXVOCALMORPHERPROPERTIES& all);
-
- void defer_phoneme_a(const EaxEaxCall& eax_call);
- void defer_phoneme_a_coarse_tuning(const EaxEaxCall& eax_call);
- void defer_phoneme_b(const EaxEaxCall& eax_call);
- void defer_phoneme_b_coarse_tuning(const EaxEaxCall& eax_call);
- void defer_waveform(const EaxEaxCall& eax_call);
- void defer_rate(const EaxEaxCall& eax_call);
- void defer_all(const EaxEaxCall& eax_call);
-
- void set(const EaxEaxCall& eax_call);
-}; // EaxVocalMorpherEffect
+ void set_efx_rate() 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;
+}; // EaxVocalMorpherEffect
-class EaxVocalMorpherEffectException :
- public EaxException
-{
-public:
- explicit EaxVocalMorpherEffectException(
- const char* message)
- :
- EaxException{"EAX_VOCAL_MORPHER_EFFECT", message}
- {
- }
-}; // EaxVocalMorpherEffectException
-
+EaxVocalMorpherEffect::EaxVocalMorpherEffect(const EaxCall& call)
+ : EaxEffect4{AL_EFFECT_VOCAL_MORPHER, call}
+{}
-EaxVocalMorpherEffect::EaxVocalMorpherEffect()
- : EaxEffect{AL_EFFECT_VOCAL_MORPHER}
+void EaxVocalMorpherEffect::set_defaults(Props& props)
{
- set_eax_defaults();
- set_efx_defaults();
-}
-
-void EaxVocalMorpherEffect::dispatch(const EaxEaxCall& eax_call)
-{
- eax_call.is_get() ? get(eax_call) : set(eax_call);
-}
-
-void EaxVocalMorpherEffect::set_eax_defaults()
-{
- eax_.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
- eax_.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
- eax_.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
- eax_.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
- eax_.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
- eax_.flRate = EAXVOCALMORPHER_DEFAULTRATE;
-
- eax_d_ = eax_;
+ props.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
+ props.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
+ props.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
+ props.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
+ props.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
+ props.flRate = EAXVOCALMORPHER_DEFAULTRATE;
}
void EaxVocalMorpherEffect::set_efx_phoneme_a()
{
const auto phoneme_a = clamp(
- static_cast<ALint>(eax_.ulPhonemeA),
+ static_cast<ALint>(props_.ulPhonemeA),
AL_VOCAL_MORPHER_MIN_PHONEMEA,
AL_VOCAL_MORPHER_MAX_PHONEMEA);
-
const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a);
assert(efx_phoneme_a.has_value());
al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a;
}
-void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning()
+void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() noexcept
{
const auto phoneme_a_coarse_tuning = clamp(
- static_cast<ALint>(eax_.lPhonemeACoarseTuning),
+ static_cast<ALint>(props_.lPhonemeACoarseTuning),
AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING,
AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING);
-
al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning;
}
void EaxVocalMorpherEffect::set_efx_phoneme_b()
{
const auto phoneme_b = clamp(
- static_cast<ALint>(eax_.ulPhonemeB),
+ static_cast<ALint>(props_.ulPhonemeB),
AL_VOCAL_MORPHER_MIN_PHONEMEB,
AL_VOCAL_MORPHER_MAX_PHONEMEB);
-
const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b);
assert(efx_phoneme_b.has_value());
al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b;
}
-void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning()
+void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() noexcept
{
- const auto phoneme_b_coarse_tuning = clamp(
- static_cast<ALint>(eax_.lPhonemeBCoarseTuning),
+ al_effect_props_.Vmorpher.PhonemeBCoarseTuning = clamp(
+ static_cast<ALint>(props_.lPhonemeBCoarseTuning),
AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING,
AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING);
-
- al_effect_props_.Vmorpher.PhonemeBCoarseTuning = phoneme_b_coarse_tuning;
}
void EaxVocalMorpherEffect::set_efx_waveform()
{
const auto waveform = clamp(
- static_cast<ALint>(eax_.ulWaveform),
+ static_cast<ALint>(props_.ulWaveform),
AL_VOCAL_MORPHER_MIN_WAVEFORM,
AL_VOCAL_MORPHER_MAX_WAVEFORM);
-
const auto wfx_waveform = WaveformFromEmum(waveform);
assert(wfx_waveform.has_value());
al_effect_props_.Vmorpher.Waveform = *wfx_waveform;
}
-void EaxVocalMorpherEffect::set_efx_rate()
+void EaxVocalMorpherEffect::set_efx_rate() noexcept
{
- const auto rate = clamp(
- eax_.flRate,
+ al_effect_props_.Vmorpher.Rate = clamp(
+ props_.flRate,
AL_VOCAL_MORPHER_MIN_RATE,
AL_VOCAL_MORPHER_MAX_RATE);
-
- al_effect_props_.Vmorpher.Rate = rate;
}
void EaxVocalMorpherEffect::set_efx_defaults()
@@ -444,343 +445,134 @@ void EaxVocalMorpherEffect::set_efx_defaults()
set_efx_rate();
}
-void EaxVocalMorpherEffect::get(const EaxEaxCall& eax_call)
+void EaxVocalMorpherEffect::get(const EaxCall& call, const Props& props)
{
- switch(eax_call.get_property_id())
+ switch(call.get_property_id())
{
case EAXVOCALMORPHER_NONE:
break;
case EAXVOCALMORPHER_ALLPARAMETERS:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_);
+ call.set_value<Exception>(props);
break;
case EAXVOCALMORPHER_PHONEMEA:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeA);
+ call.set_value<Exception>(props.ulPhonemeA);
break;
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeACoarseTuning);
+ call.set_value<Exception>(props.lPhonemeACoarseTuning);
break;
case EAXVOCALMORPHER_PHONEMEB:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeB);
+ call.set_value<Exception>(props.ulPhonemeB);
break;
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeBCoarseTuning);
+ call.set_value<Exception>(props.lPhonemeBCoarseTuning);
break;
case EAXVOCALMORPHER_WAVEFORM:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulWaveform);
+ call.set_value<Exception>(props.ulWaveform);
break;
case EAXVOCALMORPHER_RATE:
- eax_call.set_value<EaxVocalMorpherEffectException>(eax_.flRate);
+ call.set_value<Exception>(props.flRate);
break;
default:
- throw EaxVocalMorpherEffectException{"Unsupported property id."};
+ fail_unknown_property_id();
}
}
-void EaxVocalMorpherEffect::validate_phoneme_a(
- unsigned long ulPhonemeA)
+void EaxVocalMorpherEffect::set(const EaxCall& call, Props& props)
{
- eax_validate_range<EaxVocalMorpherEffectException>(
- "Phoneme A",
- ulPhonemeA,
- EAXVOCALMORPHER_MINPHONEMEA,
- EAXVOCALMORPHER_MAXPHONEMEA);
-}
-
-void EaxVocalMorpherEffect::validate_phoneme_a_coarse_tuning(
- long lPhonemeACoarseTuning)
-{
- eax_validate_range<EaxVocalMorpherEffectException>(
- "Phoneme A Coarse Tuning",
- lPhonemeACoarseTuning,
- EAXVOCALMORPHER_MINPHONEMEACOARSETUNING,
- EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING);
-}
-
-void EaxVocalMorpherEffect::validate_phoneme_b(
- unsigned long ulPhonemeB)
-{
- eax_validate_range<EaxVocalMorpherEffectException>(
- "Phoneme B",
- ulPhonemeB,
- EAXVOCALMORPHER_MINPHONEMEB,
- EAXVOCALMORPHER_MAXPHONEMEB);
-}
-
-void EaxVocalMorpherEffect::validate_phoneme_b_coarse_tuning(
- long lPhonemeBCoarseTuning)
-{
- eax_validate_range<EaxVocalMorpherEffectException>(
- "Phoneme B Coarse Tuning",
- lPhonemeBCoarseTuning,
- EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING,
- EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING);
-}
-
-void EaxVocalMorpherEffect::validate_waveform(
- unsigned long ulWaveform)
-{
- eax_validate_range<EaxVocalMorpherEffectException>(
- "Waveform",
- ulWaveform,
- EAXVOCALMORPHER_MINWAVEFORM,
- EAXVOCALMORPHER_MAXWAVEFORM);
-}
-
-void EaxVocalMorpherEffect::validate_rate(
- float flRate)
-{
- eax_validate_range<EaxVocalMorpherEffectException>(
- "Rate",
- flRate,
- EAXVOCALMORPHER_MINRATE,
- EAXVOCALMORPHER_MAXRATE);
-}
-
-void EaxVocalMorpherEffect::validate_all(
- const EAXVOCALMORPHERPROPERTIES& all)
-{
- validate_phoneme_a(all.ulPhonemeA);
- validate_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
- validate_phoneme_b(all.ulPhonemeB);
- validate_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
- validate_waveform(all.ulWaveform);
- validate_rate(all.flRate);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_a(
- unsigned long ulPhonemeA)
-{
- eax_d_.ulPhonemeA = ulPhonemeA;
- eax_dirty_flags_.ulPhonemeA = (eax_.ulPhonemeA != eax_d_.ulPhonemeA);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
- long lPhonemeACoarseTuning)
-{
- eax_d_.lPhonemeACoarseTuning = lPhonemeACoarseTuning;
- eax_dirty_flags_.lPhonemeACoarseTuning = (eax_.lPhonemeACoarseTuning != eax_d_.lPhonemeACoarseTuning);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_b(
- unsigned long ulPhonemeB)
-{
- eax_d_.ulPhonemeB = ulPhonemeB;
- eax_dirty_flags_.ulPhonemeB = (eax_.ulPhonemeB != eax_d_.ulPhonemeB);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
- long lPhonemeBCoarseTuning)
-{
- eax_d_.lPhonemeBCoarseTuning = lPhonemeBCoarseTuning;
- eax_dirty_flags_.lPhonemeBCoarseTuning = (eax_.lPhonemeBCoarseTuning != eax_d_.lPhonemeBCoarseTuning);
-}
-
-void EaxVocalMorpherEffect::defer_waveform(
- unsigned long ulWaveform)
-{
- eax_d_.ulWaveform = ulWaveform;
- eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
-}
-
-void EaxVocalMorpherEffect::defer_rate(
- float flRate)
-{
- eax_d_.flRate = flRate;
- eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate);
-}
-
-void EaxVocalMorpherEffect::defer_all(
- const EAXVOCALMORPHERPROPERTIES& all)
-{
- defer_phoneme_a(all.ulPhonemeA);
- defer_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
- defer_phoneme_b(all.ulPhonemeB);
- defer_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
- defer_waveform(all.ulWaveform);
- defer_rate(all.flRate);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_a(
- const EaxEaxCall& eax_call)
-{
- const auto& phoneme_a = eax_call.get_value<EaxVocalMorpherEffectException,
- const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeA)>();
-
- validate_phoneme_a(phoneme_a);
- defer_phoneme_a(phoneme_a);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
- const EaxEaxCall& eax_call)
-{
- const auto& phoneme_a_coarse_tuning = eax_call.get_value<
- EaxVocalMorpherEffectException,
- const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeACoarseTuning)
- >();
-
- validate_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
- defer_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
-}
-
-void EaxVocalMorpherEffect::defer_phoneme_b(
- const EaxEaxCall& eax_call)
-{
- const auto& phoneme_b = eax_call.get_value<
- EaxVocalMorpherEffectException,
- const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeB)
- >();
-
- validate_phoneme_b(phoneme_b);
- defer_phoneme_b(phoneme_b);
-}
+ switch(call.get_property_id())
+ {
+ case EAXVOCALMORPHER_NONE:
+ break;
-void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
- const EaxEaxCall& eax_call)
-{
- const auto& phoneme_b_coarse_tuning = eax_call.get_value<
- EaxVocalMorpherEffectException,
- const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeBCoarseTuning)
- >();
+ case EAXVOCALMORPHER_ALLPARAMETERS:
+ defer<AllValidator>(call, props);
+ break;
- validate_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
- defer_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
-}
+ case EAXVOCALMORPHER_PHONEMEA:
+ defer<PhonemeAValidator>(call, props.ulPhonemeA);
+ break;
-void EaxVocalMorpherEffect::defer_waveform(
- const EaxEaxCall& eax_call)
-{
- const auto& waveform = eax_call.get_value<
- EaxVocalMorpherEffectException,
- const decltype(EAXVOCALMORPHERPROPERTIES::ulWaveform)
- >();
+ case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
+ defer<PhonemeACoarseTuningValidator>(call, props.lPhonemeACoarseTuning);
+ break;
- validate_waveform(waveform);
- defer_waveform(waveform);
-}
+ case EAXVOCALMORPHER_PHONEMEB:
+ defer<PhonemeBValidator>(call, props.ulPhonemeB);
+ break;
-void EaxVocalMorpherEffect::defer_rate(
- const EaxEaxCall& eax_call)
-{
- const auto& rate = eax_call.get_value<
- EaxVocalMorpherEffectException,
- const decltype(EAXVOCALMORPHERPROPERTIES::flRate)
- >();
+ case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
+ defer<PhonemeBCoarseTuningValidator>(call, props.lPhonemeBCoarseTuning);
+ break;
- validate_rate(rate);
- defer_rate(rate);
-}
+ case EAXVOCALMORPHER_WAVEFORM:
+ defer<WaveformValidator>(call, props.ulWaveform);
+ break;
-void EaxVocalMorpherEffect::defer_all(
- const EaxEaxCall& eax_call)
-{
- const auto& all = eax_call.get_value<
- EaxVocalMorpherEffectException,
- const EAXVOCALMORPHERPROPERTIES
- >();
+ case EAXVOCALMORPHER_RATE:
+ defer<RateValidator>(call, props.flRate);
+ break;
- validate_all(all);
- defer_all(all);
+ default:
+ fail_unknown_property_id();
+ }
}
-// [[nodiscard]]
-bool EaxVocalMorpherEffect::apply_deferred()
+bool EaxVocalMorpherEffect::commit_props(const Props& props)
{
- if (eax_dirty_flags_ == EaxVocalMorpherEffectDirtyFlags{})
- {
- return false;
- }
+ auto is_dirty = false;
- eax_ = eax_d_;
-
- if (eax_dirty_flags_.ulPhonemeA)
+ if (props_.ulPhonemeA != props.ulPhonemeA)
{
+ is_dirty = true;
set_efx_phoneme_a();
}
- if (eax_dirty_flags_.lPhonemeACoarseTuning)
+ if (props_.lPhonemeACoarseTuning != props.lPhonemeACoarseTuning)
{
+ is_dirty = true;
set_efx_phoneme_a_coarse_tuning();
}
- if (eax_dirty_flags_.ulPhonemeB)
+ if (props_.ulPhonemeB != props.ulPhonemeB)
{
+ is_dirty = true;
set_efx_phoneme_b();
}
- if (eax_dirty_flags_.lPhonemeBCoarseTuning)
+ if (props_.lPhonemeBCoarseTuning != props.lPhonemeBCoarseTuning)
{
+ is_dirty = true;
set_efx_phoneme_b_coarse_tuning();
}
- if (eax_dirty_flags_.ulWaveform)
+ if (props_.ulWaveform != props.ulWaveform)
{
+ is_dirty = true;
set_efx_waveform();
}
- if (eax_dirty_flags_.flRate)
+ if (props_.flRate != props.flRate)
{
+ is_dirty = true;
set_efx_rate();
}
- eax_dirty_flags_ = EaxVocalMorpherEffectDirtyFlags{};
-
- return true;
-}
-
-void EaxVocalMorpherEffect::set(const EaxEaxCall& eax_call)
-{
- switch(eax_call.get_property_id())
- {
- case EAXVOCALMORPHER_NONE:
- break;
-
- case EAXVOCALMORPHER_ALLPARAMETERS:
- defer_all(eax_call);
- break;
-
- case EAXVOCALMORPHER_PHONEMEA:
- defer_phoneme_a(eax_call);
- break;
-
- case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
- defer_phoneme_a_coarse_tuning(eax_call);
- break;
-
- case EAXVOCALMORPHER_PHONEMEB:
- defer_phoneme_b(eax_call);
- break;
-
- case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
- defer_phoneme_b_coarse_tuning(eax_call);
- break;
-
- case EAXVOCALMORPHER_WAVEFORM:
- defer_waveform(eax_call);
- break;
-
- case EAXVOCALMORPHER_RATE:
- defer_rate(eax_call);
- break;
-
- default:
- throw EaxVocalMorpherEffectException{"Unsupported property id."};
- }
+ return is_dirty;
}
} // namespace
-
-EaxEffectUPtr eax_create_eax_vocal_morpher_effect()
+EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call)
{
- return std::make_unique<EaxVocalMorpherEffect>();
+ return eax_create_eax4_effect<EaxVocalMorpherEffect>(call);
}
#endif // ALSOFT_EAX