aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects/pshifter.cpp
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-01-30 14:47:32 +0200
committerGitHub <[email protected]>2022-01-30 04:47:32 -0800
commit19ed994dc30ed84ea7cbbb5152577669fc25caf6 (patch)
treef68933bf8f778806618bd6c0b1bf9ced1b0ccf08 /al/effects/pshifter.cpp
parent619249371a40f03cf988d1f5750d643df797c485 (diff)
Add EAX extensions (EAX 2.0-5.0, X-RAM) (#632)
* Add EAX extensions (EAX 2.0-5.0, X-RAM) * Comment out C++17 leftovers * Remove everything related to patching * Update alsoftrc.sample * Rewrite integration * Fix GCC compilation under Linux * Always reset EAX effect properties when loading it into FX slot
Diffstat (limited to 'al/effects/pshifter.cpp')
-rw-r--r--al/effects/pshifter.cpp338
1 files changed, 338 insertions, 0 deletions
diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp
index 56059a3c..03f9a139 100644
--- a/al/effects/pshifter.cpp
+++ b/al/effects/pshifter.cpp
@@ -7,6 +7,13 @@
#include "alc/effects/base.h"
#include "effects.h"
+#if ALSOFT_EAX
+#include "alnumeric.h"
+
+#include "al/eax_exception.h"
+#include "al/eax_utils.h"
+#endif // ALSOFT_EAX
+
namespace {
@@ -82,3 +89,334 @@ EffectProps genDefaultProps() noexcept
DEFINE_ALEFFECT_VTABLE(Pshifter);
const EffectProps PshifterEffectProps{genDefaultProps()};
+
+#if 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
+{
+public:
+ EaxPitchShifterEffect(
+ EffectProps& al_effect_props);
+
+
+ // [[nodiscard]]
+ bool dispatch(
+ const EaxEaxCall& eax_call) override;
+
+
+private:
+ EffectProps& al_effect_props_;
+
+ 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();
+
+
+ // [[nodiscard]]
+ bool 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);
+
+
+ // [[nodiscard]]
+ bool apply_deferred();
+
+ // [[nodiscard]]
+ bool set(
+ const EaxEaxCall& eax_call);
+}; // EaxPitchShifterEffect
+
+
+class EaxPitchShifterEffectException :
+ public EaxException
+{
+public:
+ explicit EaxPitchShifterEffectException(
+ const char* message)
+ :
+ EaxException{"EAX_PITCH_SHIFTER_EFFECT", message}
+ {
+ }
+}; // EaxPitchShifterEffectException
+
+
+EaxPitchShifterEffect::EaxPitchShifterEffect(
+ EffectProps& al_effect_props)
+ :
+ al_effect_props_{al_effect_props}
+{
+ set_eax_defaults();
+ set_efx_defaults();
+}
+
+// [[nodiscard]]
+bool EaxPitchShifterEffect::dispatch(
+ const EaxEaxCall& eax_call)
+{
+ return 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_;
+}
+
+void EaxPitchShifterEffect::set_efx_coarse_tune()
+{
+ const auto coarse_tune = clamp(
+ static_cast<ALint>(eax_.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()
+{
+ const auto fine_tune = clamp(
+ static_cast<ALint>(eax_.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()
+{
+ set_efx_coarse_tune();
+ set_efx_fine_tune();
+}
+
+// [[nodiscard]]
+bool EaxPitchShifterEffect::get(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_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."};
+ }
+
+ return false;
+}
+
+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)
+{
+ 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{})
+ {
+ return false;
+ }
+
+ eax_ = eax_d_;
+
+ if (eax_dirty_flags_.lCoarseTune)
+ {
+ set_efx_coarse_tune();
+ }
+
+ if (eax_dirty_flags_.lFineTune)
+ {
+ set_efx_fine_tune();
+ }
+
+ eax_dirty_flags_ = EaxPitchShifterEffectDirtyFlags{};
+
+ return true;
+}
+
+// [[nodiscard]]
+bool 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."};
+ }
+
+ if (!eax_call.is_deferred())
+ {
+ return apply_deferred();
+ }
+
+ return false;
+}
+
+
+} // namespace
+
+
+EaxEffectUPtr eax_create_eax_pitch_shifter_effect(
+ EffectProps& al_effect_props)
+{
+ return std::make_unique<EaxPitchShifterEffect>(al_effect_props);
+}
+
+
+#endif // ALSOFT_EAX