aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects/compressor.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/compressor.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/compressor.cpp')
-rw-r--r--al/effects/compressor.cpp272
1 files changed, 272 insertions, 0 deletions
diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp
index f5db2a6f..868c5c1b 100644
--- a/al/effects/compressor.cpp
+++ b/al/effects/compressor.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 {
@@ -70,3 +77,268 @@ EffectProps genDefaultProps() noexcept
DEFINE_ALEFFECT_VTABLE(Compressor);
const EffectProps CompressorEffectProps{genDefaultProps()};
+
+#if ALSOFT_EAX
+namespace
+{
+
+
+using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t;
+
+struct EaxCompressorEffectDirtyFlags
+{
+ using EaxIsBitFieldStruct = bool;
+
+ EaxCompressorEffectDirtyFlagsValue ulOnOff : 1;
+}; // EaxCompressorEffectDirtyFlags
+
+
+class EaxCompressorEffect final :
+ public EaxEffect
+{
+public:
+ EaxCompressorEffect(
+ EffectProps& al_effect_props);
+
+
+ // [[nodiscard]]
+ bool dispatch(
+ const EaxEaxCall& eax_call) override;
+
+
+private:
+ EffectProps& al_effect_props_;
+
+ EAXAGCCOMPRESSORPROPERTIES eax_{};
+ EAXAGCCOMPRESSORPROPERTIES eax_d_{};
+ EaxCompressorEffectDirtyFlags eax_dirty_flags_{};
+
+
+ void set_eax_defaults();
+
+
+ void set_efx_on_off();
+
+ void set_efx_defaults();
+
+
+ // [[nodiscard]]
+ bool 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);
+
+
+ // [[nodiscard]]
+ bool apply_deferred();
+
+ // [[nodiscard]]
+ bool set(
+ const EaxEaxCall& eax_call);
+}; // EaxCompressorEffect
+
+
+class EaxCompressorEffectException :
+ public EaxException
+{
+public:
+ explicit EaxCompressorEffectException(
+ const char* message)
+ :
+ EaxException{"EAX_COMPRESSOR_EFFECT", message}
+ {
+ }
+}; // EaxCompressorEffectException
+
+
+EaxCompressorEffect::EaxCompressorEffect(
+ EffectProps& al_effect_props)
+ :
+ al_effect_props_{al_effect_props}
+{
+ set_eax_defaults();
+ set_efx_defaults();
+}
+
+// [[nodiscard]]
+bool EaxCompressorEffect::dispatch(
+ const EaxEaxCall& eax_call)
+{
+ return eax_call.is_get() ? get(eax_call) : set(eax_call);
+}
+
+void EaxCompressorEffect::set_eax_defaults()
+{
+ eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
+
+ eax_d_ = eax_;
+}
+
+void EaxCompressorEffect::set_efx_on_off()
+{
+ const auto on_off = clamp(
+ static_cast<ALint>(eax_.ulOnOff),
+ AL_COMPRESSOR_MIN_ONOFF,
+ AL_COMPRESSOR_MAX_ONOFF);
+
+ al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE);
+}
+
+void EaxCompressorEffect::set_efx_defaults()
+{
+ set_efx_on_off();
+}
+
+// [[nodiscard]]
+bool EaxCompressorEffect::get(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_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."};
+ }
+
+ return false;
+}
+
+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)
+{
+ 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{})
+ {
+ return false;
+ }
+
+ eax_ = eax_d_;
+
+ if (eax_dirty_flags_.ulOnOff)
+ {
+ set_efx_on_off();
+ }
+
+ eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{};
+
+ return true;
+}
+
+// [[nodiscard]]
+bool 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."};
+ }
+
+ if (!eax_call.is_deferred())
+ {
+ return apply_deferred();
+ }
+
+ return false;
+}
+
+
+} // namespace
+
+
+EaxEffectUPtr eax_create_eax_compressor_effect(
+ EffectProps& al_effect_props)
+{
+ return std::make_unique<EaxCompressorEffect>(al_effect_props);
+}
+
+
+#endif // ALSOFT_EAX