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