aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects/echo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'al/effects/echo.cpp')
-rw-r--r--al/effects/echo.cpp511
1 files changed, 147 insertions, 364 deletions
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