diff options
31 files changed, 4211 insertions, 6651 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 52d61ff0..4a3ce192 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -800,9 +800,8 @@ if (ALSOFT_EAX) ${OPENAL_OBJS} al/eax/api.cpp al/eax/api.h - al/eax/eax_call.cpp - al/eax/eax_call.h - al/eax/effect.cpp + al/eax/call.cpp + al/eax/call.h al/eax/effect.h al/eax/exception.cpp al/eax/exception.h @@ -814,7 +813,6 @@ if (ALSOFT_EAX) al/eax/globals.h al/eax/utils.cpp al/eax/utils.h - al/eax/x_ram.cpp al/eax/x_ram.h ) endif () diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 455a1072..d37168e7 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1076,6 +1076,7 @@ public: void ALeffectslot::eax_initialize( + const EaxCall& call, ALCcontext& al_context, EaxFxSlotIndexValue index) { @@ -1090,7 +1091,7 @@ void ALeffectslot::eax_initialize( eax_initialize_eax(); eax_initialize_lock(); - eax_initialize_effects(); + eax_initialize_effects(call); } const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept @@ -1104,8 +1105,7 @@ void ALeffectslot::eax_ensure_is_unlocked() const eax_fail("Locked."); } -void ALeffectslot::eax_validate_fx_slot_effect( - const GUID& eax_effect_id) +void ALeffectslot::eax_validate_fx_slot_effect(const GUID& eax_effect_id) { eax_ensure_is_unlocked(); @@ -1127,8 +1127,7 @@ void ALeffectslot::eax_validate_fx_slot_effect( } } -void ALeffectslot::eax_validate_fx_slot_volume( - long eax_volume) +void ALeffectslot::eax_validate_fx_slot_volume(long eax_volume) { eax_validate_range<EaxFxSlotException>( "Volume", @@ -1137,8 +1136,7 @@ void ALeffectslot::eax_validate_fx_slot_volume( EAXFXSLOT_MAXVOLUME); } -void ALeffectslot::eax_validate_fx_slot_lock( - long eax_lock) +void ALeffectslot::eax_validate_fx_slot_lock(long eax_lock) { eax_ensure_is_unlocked(); @@ -1149,19 +1147,16 @@ void ALeffectslot::eax_validate_fx_slot_lock( EAXFXSLOT_MAXLOCK); } -void ALeffectslot::eax_validate_fx_slot_flags( - unsigned long eax_flags, - int eax_version) +void ALeffectslot::eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags) { eax_validate_range<EaxFxSlotException>( "Flags", eax_flags, 0UL, - ~(eax_version == 4 ? EAX40FXSLOTFLAGS_RESERVED : EAX50FXSLOTFLAGS_RESERVED)); + ~(call.get_version() == 4 ? EAX40FXSLOTFLAGS_RESERVED : EAX50FXSLOTFLAGS_RESERVED)); } -void ALeffectslot::eax_validate_fx_slot_occlusion( - long eax_occlusion) +void ALeffectslot::eax_validate_fx_slot_occlusion(long eax_occlusion) { eax_validate_range<EaxFxSlotException>( "Occlusion", @@ -1170,8 +1165,7 @@ void ALeffectslot::eax_validate_fx_slot_occlusion( EAXFXSLOT_MAXOCCLUSION); } -void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio( - float eax_occlusion_lf_ratio) +void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio) { eax_validate_range<EaxFxSlotException>( "Occlusion LF Ratio", @@ -1180,28 +1174,22 @@ void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio( EAXFXSLOT_MAXOCCLUSIONLFRATIO); } -void ALeffectslot::eax_validate_fx_slot_all( - const EAX40FXSLOTPROPERTIES& fx_slot, - int eax_version) +void ALeffectslot::eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot) { eax_validate_fx_slot_effect(fx_slot.guidLoadEffect); eax_validate_fx_slot_volume(fx_slot.lVolume); eax_validate_fx_slot_lock(fx_slot.lLock); - eax_validate_fx_slot_flags(fx_slot.ulFlags, eax_version); + eax_validate_fx_slot_flags(call, fx_slot.ulFlags); } -void ALeffectslot::eax_validate_fx_slot_all( - const EAX50FXSLOTPROPERTIES& fx_slot, - int eax_version) +void ALeffectslot::eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot) { - eax_validate_fx_slot_all(static_cast<const EAX40FXSLOTPROPERTIES&>(fx_slot), eax_version); - + eax_validate_fx_slot_all(call, static_cast<const EAX40FXSLOTPROPERTIES&>(fx_slot)); eax_validate_fx_slot_occlusion(fx_slot.lOcclusion); eax_validate_fx_slot_occlusion_lf_ratio(fx_slot.flOcclusionLFRatio); } -void ALeffectslot::eax_set_fx_slot_effect( - const GUID& eax_effect_id) +void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id) { if (eax_eax_fx_slot_.guidLoadEffect == eax_effect_id) { @@ -1210,7 +1198,7 @@ void ALeffectslot::eax_set_fx_slot_effect( eax_eax_fx_slot_.guidLoadEffect = eax_effect_id; - eax_set_fx_slot_effect(); + eax_set_fx_slot_effect(call); } void ALeffectslot::eax_set_fx_slot_volume( @@ -1278,20 +1266,18 @@ bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( return true; } -void ALeffectslot::eax_set_fx_slot_all( - const EAX40FXSLOTPROPERTIES& eax_fx_slot) +void ALeffectslot::eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot) { - eax_set_fx_slot_effect(eax_fx_slot.guidLoadEffect); + eax_set_fx_slot_effect(call, eax_fx_slot.guidLoadEffect); eax_set_fx_slot_volume(eax_fx_slot.lVolume); eax_set_fx_slot_lock(eax_fx_slot.lLock); eax_set_fx_slot_flags(eax_fx_slot.ulFlags); } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_all( - const EAX50FXSLOTPROPERTIES& eax_fx_slot) +bool ALeffectslot::eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot) { - eax_set_fx_slot_all(static_cast<const EAX40FXSLOTPROPERTIES&>(eax_fx_slot)); + eax_set_fx_slot_all(call, static_cast<const EAX40FXSLOTPROPERTIES&>(eax_fx_slot)); const auto is_occlusion_modified = eax_set_fx_slot_occlusion(eax_fx_slot.lOcclusion); const auto is_occlusion_lf_ratio_modified = eax_set_fx_slot_occlusion_lf_ratio(eax_fx_slot.flOcclusionLFRatio); @@ -1348,22 +1334,21 @@ void ALeffectslot::eax_initialize_lock() eax_is_locked_ = (eax_fx_slot_index_ < 2); } -void ALeffectslot::eax_initialize_effects() +void ALeffectslot::eax_initialize_effects(const EaxCall& call) { - eax_set_fx_slot_effect(); + eax_set_fx_slot_effect(call); } -void ALeffectslot::eax_get_fx_slot_all( - const EaxEaxCall& eax_call) const +void ALeffectslot::eax_get_fx_slot_all(const EaxCall& call) const { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: - eax_call.set_value<EaxFxSlotException, EAX40FXSLOTPROPERTIES>(eax_eax_fx_slot_); + call.set_value<EaxFxSlotException, EAX40FXSLOTPROPERTIES>(eax_eax_fx_slot_); break; case 5: - eax_call.set_value<EaxFxSlotException, EAX50FXSLOTPROPERTIES>(eax_eax_fx_slot_); + call.set_value<EaxFxSlotException, EAX50FXSLOTPROPERTIES>(eax_eax_fx_slot_); break; default: @@ -1371,37 +1356,36 @@ void ALeffectslot::eax_get_fx_slot_all( } } -void ALeffectslot::eax_get_fx_slot( - const EaxEaxCall& eax_call) const +void ALeffectslot::eax_get_fx_slot(const EaxCall& call) const { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXFXSLOT_ALLPARAMETERS: - eax_get_fx_slot_all(eax_call); + eax_get_fx_slot_all(call); break; case EAXFXSLOT_LOADEFFECT: - eax_call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.guidLoadEffect); + call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.guidLoadEffect); break; case EAXFXSLOT_VOLUME: - eax_call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.lVolume); + call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.lVolume); break; case EAXFXSLOT_LOCK: - eax_call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.lLock); + call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.lLock); break; case EAXFXSLOT_FLAGS: - eax_call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.ulFlags); + call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.ulFlags); break; case EAXFXSLOT_OCCLUSION: - eax_call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.lOcclusion); + call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.lOcclusion); break; case EAXFXSLOT_OCCLUSIONLFRATIO: - eax_call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.flOcclusionLFRatio); + call.set_value<EaxFxSlotException>(eax_eax_fx_slot_.flOcclusionLFRatio); break; default: @@ -1410,17 +1394,16 @@ void ALeffectslot::eax_get_fx_slot( } // [[nodiscard]] -bool ALeffectslot::eax_get( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_get(const EaxCall& call) { - switch (eax_call.get_property_set_id()) + switch (call.get_property_set_id()) { - case EaxEaxCallPropertySetId::fx_slot: - eax_get_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + eax_get_fx_slot(call); break; - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(eax_call); + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(call); break; default: @@ -1430,19 +1413,18 @@ bool ALeffectslot::eax_get( return false; } -void ALeffectslot::eax_set_fx_slot_effect( - ALenum al_effect_type) +void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call, ALenum al_effect_type) { if(!IsValidEffectType(al_effect_type)) eax_fail("Unsupported effect."); eax_effect_ = nullptr; - eax_effect_ = eax_create_eax_effect(al_effect_type); + eax_effect_ = eax_create_eax_effect(al_effect_type, call); eax_set_effect_slot_effect(*eax_effect_); } -void ALeffectslot::eax_set_fx_slot_effect() +void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call) { auto al_effect_type = ALenum{}; @@ -1506,7 +1488,7 @@ void ALeffectslot::eax_set_fx_slot_effect() eax_fail("Unsupported effect."); } - eax_set_fx_slot_effect(al_effect_type); + eax_set_fx_slot_effect(call, al_effect_type); } void ALeffectslot::eax_set_efx_effect_slot_gain() @@ -1535,52 +1517,47 @@ void ALeffectslot::eax_set_fx_slot_flags() eax_set_effect_slot_send_auto(); } -void ALeffectslot::eax_set_fx_slot_effect( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_effect(const EaxCall& call) { const auto& eax_effect_id = - eax_call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::guidLoadEffect)>(); + call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::guidLoadEffect)>(); eax_validate_fx_slot_effect(eax_effect_id); - eax_set_fx_slot_effect(eax_effect_id); + eax_set_fx_slot_effect(call, eax_effect_id); } -void ALeffectslot::eax_set_fx_slot_volume( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_volume(const EaxCall& call) { const auto& eax_volume = - eax_call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::lVolume)>(); + call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::lVolume)>(); eax_validate_fx_slot_volume(eax_volume); eax_set_fx_slot_volume(eax_volume); } -void ALeffectslot::eax_set_fx_slot_lock( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_lock(const EaxCall& call) { const auto& eax_lock = - eax_call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::lLock)>(); + call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::lLock)>(); eax_validate_fx_slot_lock(eax_lock); eax_set_fx_slot_lock(eax_lock); } -void ALeffectslot::eax_set_fx_slot_flags( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_flags(const EaxCall& call) { const auto& eax_flags = - eax_call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::ulFlags)>(); + call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::ulFlags)>(); - eax_validate_fx_slot_flags(eax_flags, eax_call.get_version()); + eax_validate_fx_slot_flags(call, eax_flags); eax_set_fx_slot_flags(eax_flags); } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_occlusion( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_defer_fx_slot_occlusion(const EaxCall& call) { const auto& eax_occlusion = - eax_call.get_value<EaxFxSlotException, const decltype(EAX50FXSLOTPROPERTIES::lOcclusion)>(); + call.get_value<EaxFxSlotException, const decltype(EAX50FXSLOTPROPERTIES::lOcclusion)>(); eax_validate_fx_slot_occlusion(eax_occlusion); @@ -1588,11 +1565,10 @@ bool ALeffectslot::eax_set_fx_slot_occlusion( } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call) { const auto& eax_occlusion_lf_ratio = - eax_call.get_value<EaxFxSlotException, const decltype(EAX50FXSLOTPROPERTIES::flOcclusionLFRatio)>(); + call.get_value<EaxFxSlotException, const decltype(EAX50FXSLOTPROPERTIES::flOcclusionLFRatio)>(); eax_validate_fx_slot_occlusion_lf_ratio(eax_occlusion_lf_ratio); @@ -1600,18 +1576,17 @@ bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_all( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_defer_fx_slot_all(const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: { const auto& eax_all = - eax_call.get_value<EaxFxSlotException, const EAX40FXSLOTPROPERTIES>(); + call.get_value<EaxFxSlotException, const EAX40FXSLOTPROPERTIES>(); - eax_validate_fx_slot_all(eax_all, eax_call.get_version()); - eax_set_fx_slot_all(eax_all); + eax_validate_fx_slot_all(call, eax_all); + eax_set_fx_slot_all(call, eax_all); return false; } @@ -1619,10 +1594,10 @@ bool ALeffectslot::eax_set_fx_slot_all( case 5: { const auto& eax_all = - eax_call.get_value<EaxFxSlotException, const EAX50FXSLOTPROPERTIES>(); + call.get_value<EaxFxSlotException, const EAX50FXSLOTPROPERTIES>(); - eax_validate_fx_slot_all(eax_all, eax_call.get_version()); - return eax_set_fx_slot_all(eax_all); + eax_validate_fx_slot_all(call, eax_all); + return eax_set_fx_slot_all(call, eax_all); } default: @@ -1630,38 +1605,37 @@ bool ALeffectslot::eax_set_fx_slot_all( } } -bool ALeffectslot::eax_set_fx_slot( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_set_fx_slot(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXFXSLOT_NONE: return false; case EAXFXSLOT_ALLPARAMETERS: - return eax_set_fx_slot_all(eax_call); + return eax_defer_fx_slot_all(call); case EAXFXSLOT_LOADEFFECT: - eax_set_fx_slot_effect(eax_call); + eax_defer_fx_slot_effect(call); return false; case EAXFXSLOT_VOLUME: - eax_set_fx_slot_volume(eax_call); + eax_defer_fx_slot_volume(call); return false; case EAXFXSLOT_LOCK: - eax_set_fx_slot_lock(eax_call); + eax_defer_fx_slot_lock(call); return false; case EAXFXSLOT_FLAGS: - eax_set_fx_slot_flags(eax_call); + eax_defer_fx_slot_flags(call); return false; case EAXFXSLOT_OCCLUSION: - return eax_set_fx_slot_occlusion(eax_call); + return eax_defer_fx_slot_occlusion(call); case EAXFXSLOT_OCCLUSIONLFRATIO: - return eax_set_fx_slot_occlusion_lf_ratio(eax_call); + return eax_defer_fx_slot_occlusion_lf_ratio(call); default: @@ -1670,15 +1644,15 @@ bool ALeffectslot::eax_set_fx_slot( } // [[nodiscard]] -bool ALeffectslot::eax_set(const EaxEaxCall& eax_call) +bool ALeffectslot::eax_set(const EaxCall& call) { - switch(eax_call.get_property_set_id()) + switch(call.get_property_set_id()) { - case EaxEaxCallPropertySetId::fx_slot: - return eax_set_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + return eax_set_fx_slot(call); - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(eax_call); + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(call); break; default: @@ -1688,8 +1662,8 @@ bool ALeffectslot::eax_set(const EaxEaxCall& eax_call) return false; } -void ALeffectslot::eax_dispatch_effect(const EaxEaxCall& eax_call) -{ if(eax_effect_) eax_effect_->dispatch(eax_call); } +void ALeffectslot::eax_dispatch_effect(const EaxCall& call) +{ if(eax_effect_) eax_effect_->dispatch(call); } void ALeffectslot::eax_apply_deferred() { @@ -1697,7 +1671,7 @@ void ALeffectslot::eax_apply_deferred() auto is_changed = false; if(eax_effect_) - is_changed = eax_effect_->apply_deferred(); + is_changed = eax_effect_->commit(); if(is_changed) eax_set_effect_slot_effect(*eax_effect_); } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 5336a2a8..83711372 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -18,8 +18,7 @@ #ifdef ALSOFT_EAX #include <memory> - -#include "eax/eax_call.h" +#include "eax/call.h" #include "eax/effect.h" #include "eax/fx_slot_index.h" #endif // ALSOFT_EAX @@ -74,6 +73,7 @@ struct ALeffectslot { #ifdef ALSOFT_EAX public: void eax_initialize( + const EaxCall& call, ALCcontext& al_context, EaxFxSlotIndexValue index); @@ -81,8 +81,8 @@ public: // [[nodiscard]] - bool eax_dispatch(const EaxEaxCall& eax_call) - { return eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); } + bool eax_dispatch(const EaxCall& call) + { return call.is_get() ? eax_get(call) : eax_set(call); } void eax_unlock_legacy() noexcept; @@ -115,24 +115,20 @@ private: void eax_initialize_lock(); - void eax_initialize_effects(); + void eax_initialize_effects(const EaxCall& call); - void eax_get_fx_slot_all( - const EaxEaxCall& eax_call) const; + void eax_get_fx_slot_all(const EaxCall& call) const; - void eax_get_fx_slot( - const EaxEaxCall& eax_call) const; + void eax_get_fx_slot(const EaxCall& call) const; // [[nodiscard]] - bool eax_get( - const EaxEaxCall& eax_call); + bool eax_get(const EaxCall& call); - void eax_set_fx_slot_effect( - ALenum effect_type); + void eax_set_fx_slot_effect(const EaxCall& call, ALenum effect_type); - void eax_set_fx_slot_effect(); + void eax_set_fx_slot_effect(const EaxCall& call); void eax_set_efx_effect_slot_gain(); @@ -147,37 +143,16 @@ private: void eax_ensure_is_unlocked() const; + void eax_validate_fx_slot_effect(const GUID& eax_effect_id); + void eax_validate_fx_slot_volume(long eax_volume); + void eax_validate_fx_slot_lock(long eax_lock); + void eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags); + void eax_validate_fx_slot_occlusion(long eax_occlusion); + void eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio); + void eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot); + void eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot); - void eax_validate_fx_slot_effect( - const GUID& eax_effect_id); - - void eax_validate_fx_slot_volume( - long eax_volume); - - void eax_validate_fx_slot_lock( - long eax_lock); - - void eax_validate_fx_slot_flags( - unsigned long eax_flags, - int eax_version); - - void eax_validate_fx_slot_occlusion( - long eax_occlusion); - - void eax_validate_fx_slot_occlusion_lf_ratio( - float eax_occlusion_lf_ratio); - - void eax_validate_fx_slot_all( - const EAX40FXSLOTPROPERTIES& fx_slot, - int eax_version); - - void eax_validate_fx_slot_all( - const EAX50FXSLOTPROPERTIES& fx_slot, - int eax_version); - - - void eax_set_fx_slot_effect( - const GUID& eax_effect_id); + void eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id); void eax_set_fx_slot_volume( long eax_volume); @@ -196,50 +171,38 @@ private: bool eax_set_fx_slot_occlusion_lf_ratio( float eax_occlusion_lf_ratio); - void eax_set_fx_slot_all( - const EAX40FXSLOTPROPERTIES& eax_fx_slot); + void eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot); // [[nodiscard]] - bool eax_set_fx_slot_all( - const EAX50FXSLOTPROPERTIES& eax_fx_slot); + bool eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot); - void eax_set_fx_slot_effect( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_effect(const EaxCall& call); - void eax_set_fx_slot_volume( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_volume(const EaxCall& call); - void eax_set_fx_slot_lock( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_lock(const EaxCall& call); - void eax_set_fx_slot_flags( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_flags(const EaxCall& call); // [[nodiscard]] - bool eax_set_fx_slot_occlusion( - const EaxEaxCall& eax_call); + bool eax_defer_fx_slot_occlusion(const EaxCall& call); // [[nodiscard]] - bool eax_set_fx_slot_occlusion_lf_ratio( - const EaxEaxCall& eax_call); + bool eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call); // [[nodiscard]] - bool eax_set_fx_slot_all( - const EaxEaxCall& eax_call); + bool eax_defer_fx_slot_all(const EaxCall& call); - bool eax_set_fx_slot( - const EaxEaxCall& eax_call); + bool eax_set_fx_slot(const EaxCall& call); void eax_apply_deferred(); // [[nodiscard]] - bool eax_set( - const EaxEaxCall& eax_call); + bool eax_set(const EaxCall& call); - void eax_dispatch_effect( - const EaxEaxCall& eax_call); + void eax_dispatch_effect(const EaxCall& call); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` diff --git a/al/eax/api.cpp b/al/eax/api.cpp index f859a1c4..34ba554f 100644 --- a/al/eax/api.cpp +++ b/al/eax/api.cpp @@ -393,6 +393,569 @@ bool operator!=( } +// EAX1 ===================================================================== + +namespace { +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; +} // namespace + +const Eax1ReverbPresets EAX1REVERB_PRESETS{{ + EAX1REVERB_PRESET_GENERIC, + EAX1REVERB_PRESET_PADDEDCELL, + EAX1REVERB_PRESET_ROOM, + EAX1REVERB_PRESET_BATHROOM, + EAX1REVERB_PRESET_LIVINGROOM, + EAX1REVERB_PRESET_STONEROOM, + EAX1REVERB_PRESET_AUDITORIUM, + EAX1REVERB_PRESET_CONCERTHALL, + EAX1REVERB_PRESET_CAVE, + EAX1REVERB_PRESET_ARENA, + EAX1REVERB_PRESET_HANGAR, + EAX1REVERB_PRESET_CARPETTEDHALLWAY, + EAX1REVERB_PRESET_HALLWAY, + EAX1REVERB_PRESET_STONECORRIDOR, + EAX1REVERB_PRESET_ALLEY, + EAX1REVERB_PRESET_FOREST, + EAX1REVERB_PRESET_CITY, + EAX1REVERB_PRESET_MOUNTAINS, + EAX1REVERB_PRESET_QUARRY, + EAX1REVERB_PRESET_PLAIN, + EAX1REVERB_PRESET_PARKINGLOT, + EAX1REVERB_PRESET_SEWERPIPE, + EAX1REVERB_PRESET_UNDERWATER, + EAX1REVERB_PRESET_DRUGGED, + EAX1REVERB_PRESET_DIZZY, + EAX1REVERB_PRESET_PSYCHOTIC, +}}; + +// EAX2 ===================================================================== + +namespace { + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_GENERIC{ + EAX2LISTENER_DEFAULTROOM, + EAX2LISTENER_DEFAULTROOMHF, + EAX2LISTENER_DEFAULTROOMROLLOFFFACTOR, + EAX2LISTENER_DEFAULTDECAYTIME, + EAX2LISTENER_DEFAULTDECAYHFRATIO, + EAX2LISTENER_DEFAULTREFLECTIONS, + EAX2LISTENER_DEFAULTREFLECTIONSDELAY, + EAX2LISTENER_DEFAULTREVERB, + EAX2LISTENER_DEFAULTREVERBDELAY, + EAX2LISTENER_DEFAULTENVIRONMENT, + EAX2LISTENER_DEFAULTENVIRONMENTSIZE, + EAX2LISTENER_DEFAULTENVIRONMENTDIFFUSION, + EAX2LISTENER_DEFAULTAIRABSORPTIONHF, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PADDEDCELL{ + -1'000L, + -6'000L, + 0.0F, + 0.17F, + 0.1F, + -1'204L, + 0.001F, + 207L, + 0.002F, + EAX2_ENVIRONMENT_PADDEDCELL, + 1.4F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ROOM{ + -1'000L, + -454L, + 0.0F, + 0.4F, + 0.83F, + -1'646L, + 0.002F, + 53L, + 0.003F, + EAX2_ENVIRONMENT_ROOM, + 1.9F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_BATHROOM{ + -1'000L, + -1'200L, + 0.0F, + 1.49F, + 0.54F, + -370L, + 0.007F, + 1'030L, + 0.011F, + EAX2_ENVIRONMENT_BATHROOM, + 1.4F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_LIVINGROOM{ + -1'000L, + -6'000L, + 0.0F, + 0.5F, + 0.1F, + -1'376L, + 0.003F, + -1'104L, + 0.004F, + EAX2_ENVIRONMENT_LIVINGROOM, + 2.5F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_STONEROOM{ + -1'000L, + -300L, + 0.0F, + 2.31F, + 0.64F, + -711L, + 0.012F, + 83L, + 0.017F, + EAX2_ENVIRONMENT_STONEROOM, + 11.6F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_AUDITORIUM{ + -1'000L, + -476L, + 0.0F, + 4.32F, + 0.59F, + -789L, + 0.02F, + -289L, + 0.03F, + EAX2_ENVIRONMENT_AUDITORIUM, + 21.6F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CONCERTHALL{ + -1'000L, + -500L, + 0.0F, + 3.92F, + 0.7F, + -1'230L, + 0.02F, + -2L, + 0.029F, + EAX2_ENVIRONMENT_CONCERTHALL, + 19.6F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CAVE{ + -1'000L, + 0L, + 0.0F, + 2.91F, + 1.3F, + -602L, + 0.015F, + -302L, + 0.022F, + EAX2_ENVIRONMENT_CAVE, + 14.6F, + 1.0F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ARENA{ + -1'000L, + -698L, + 0.0F, + 7.24F, + 0.33F, + -1'166L, + 0.02F, + 16L, + 0.03F, + EAX2_ENVIRONMENT_ARENA, + 36.2F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_HANGAR{ + -1'000L, + -1'000L, + 0.0F, + 10.05F, + 0.23F, + -602L, + 0.02F, + 198L, + 0.03F, + EAX2_ENVIRONMENT_HANGAR, + 50.3F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CARPETTEDHALLWAY{ + -1'000L, + -4'000L, + 0.0F, + 0.3F, + 0.1F, + -1'831L, + 0.002F, + -1'630L, + 0.03F, + EAX2_ENVIRONMENT_CARPETEDHALLWAY, + 1.9F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_HALLWAY{ + -1'000L, + -300L, + 0.0F, + 1.49F, + 0.59F, + -1'219L, + 0.007F, + 441L, + 0.011F, + EAX2_ENVIRONMENT_HALLWAY, + 1.8F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_STONECORRIDOR{ + -1'000L, + -237L, + 0.0F, + 2.7F, + 0.79F, + -1'214L, + 0.013F, + 395L, + 0.02F, + EAX2_ENVIRONMENT_STONECORRIDOR, + 13.5F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ALLEY{ + -1'000L, + -270L, + 0.0F, + 1.49F, + 0.86F, + -1'204L, + 0.007F, + -4L, + 0.011F, + EAX2_ENVIRONMENT_ALLEY, + 7.5F, + 0.3F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_FOREST{ + -1'000L, + -3'300L, + 0.0F, + 1.49F, + 0.54F, + -2'560L, + 0.162F, + -229L, + 0.088F, + EAX2_ENVIRONMENT_FOREST, + 38.0F, + 0.3F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CITY{ + -1'000L, + -800L, + 0.0F, + 1.49F, + 0.67F, + -2'273L, + 0.007F, + -1'691L, + 0.011F, + EAX2_ENVIRONMENT_CITY, + 7.5F, + 0.5F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_MOUNTAINS{ + -1'000L, + -2'500L, + 0.0F, + 1.49F, + 0.21F, + -2'780L, + 0.3F, + -1'434L, + 0.1F, + EAX2_ENVIRONMENT_MOUNTAINS, + 100.0F, + 0.27F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_QUARRY{ + -1'000L, + -1'000L, + 0.0F, + 1.49F, + 0.83F, + -10'000L, + 0.061F, + 500L, + 0.025F, + EAX2_ENVIRONMENT_QUARRY, + 17.5F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PLAIN{ + -1'000L, + -2'000L, + 0.0F, + 1.49F, + 0.5F, + -2'466L, + 0.179F, + -1'926L, + 0.1F, + EAX2_ENVIRONMENT_PLAIN, + 42.5F, + 0.21F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PARKINGLOT{ + -1'000L, + 0L, + 0.0F, + 1.65F, + 1.5F, + -1'363L, + 0.008F, + -1'153L, + 0.012F, + EAX2_ENVIRONMENT_PARKINGLOT, + 8.3F, + 1.0F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_SEWERPIPE{ + -1'000L, + -1'000L, + 0.0F, + 2.81F, + 0.14F, + 429L, + 0.014F, + 1'023L, + 0.021F, + EAX2_ENVIRONMENT_SEWERPIPE, + 1.7F, + 0.8F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_UNDERWATER{ + -1'000L, + -4'000L, + 0.0F, + 1.49F, + 0.1F, + -449L, + 0.007F, + 1'700L, + 0.011F, + EAX2_ENVIRONMENT_UNDERWATER, + 1.8F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_DRUGGED{ + -1'000L, + 0L, + 0.0F, + 8.39F, + 1.39F, + -115L, + 0.002F, + 985L, + 0.03F, + EAX2_ENVIRONMENT_DRUGGED, + 1.9F, + 0.5F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_DIZZY{ + -1'000L, + -400L, + 0.0F, + 17.23F, + 0.56F, + -1'713L, + 0.02F, + -613L, + 0.03F, + EAX2_ENVIRONMENT_DIZZY, + 1.8F, + 0.6F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PSYCHOTIC{ + -1'000L, + -151L, + 0.0F, + 7.56F, + 0.91F, + -626L, + 0.02F, + 774L, + 0.03F, + EAX2_ENVIRONMENT_PSYCHOTIC, + 1.0F, + 0.5F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +} // namespace + +const Eax2ReverbPresets EAX2REVERB_PRESETS{ + EAX2REVERB_PRESET_GENERIC, + EAX2REVERB_PRESET_PADDEDCELL, + EAX2REVERB_PRESET_ROOM, + EAX2REVERB_PRESET_BATHROOM, + EAX2REVERB_PRESET_LIVINGROOM, + EAX2REVERB_PRESET_STONEROOM, + EAX2REVERB_PRESET_AUDITORIUM, + EAX2REVERB_PRESET_CONCERTHALL, + EAX2REVERB_PRESET_CAVE, + EAX2REVERB_PRESET_ARENA, + EAX2REVERB_PRESET_HANGAR, + EAX2REVERB_PRESET_CARPETTEDHALLWAY, + EAX2REVERB_PRESET_HALLWAY, + EAX2REVERB_PRESET_STONECORRIDOR, + EAX2REVERB_PRESET_ALLEY, + EAX2REVERB_PRESET_FOREST, + EAX2REVERB_PRESET_CITY, + EAX2REVERB_PRESET_MOUNTAINS, + EAX2REVERB_PRESET_QUARRY, + EAX2REVERB_PRESET_PLAIN, + EAX2REVERB_PRESET_PARKINGLOT, + EAX2REVERB_PRESET_SEWERPIPE, + EAX2REVERB_PRESET_UNDERWATER, + EAX2REVERB_PRESET_DRUGGED, + EAX2REVERB_PRESET_DIZZY, + EAX2REVERB_PRESET_PSYCHOTIC, +}; + +// EAX3+ ==================================================================== + namespace { constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC = @@ -1153,61 +1716,3 @@ const EaxReverbPresets EAXREVERB_PRESETS{{ EAXREVERB_PRESET_DIZZY, EAXREVERB_PRESET_PSYCHOTIC, }}; - -namespace { -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; -} // namespace - -const Eax1ReverbPresets EAX1REVERB_PRESETS{{ - EAX1REVERB_PRESET_GENERIC, - EAX1REVERB_PRESET_PADDEDCELL, - EAX1REVERB_PRESET_ROOM, - EAX1REVERB_PRESET_BATHROOM, - EAX1REVERB_PRESET_LIVINGROOM, - EAX1REVERB_PRESET_STONEROOM, - EAX1REVERB_PRESET_AUDITORIUM, - EAX1REVERB_PRESET_CONCERTHALL, - EAX1REVERB_PRESET_CAVE, - EAX1REVERB_PRESET_ARENA, - EAX1REVERB_PRESET_HANGAR, - EAX1REVERB_PRESET_CARPETTEDHALLWAY, - EAX1REVERB_PRESET_HALLWAY, - EAX1REVERB_PRESET_STONECORRIDOR, - EAX1REVERB_PRESET_ALLEY, - EAX1REVERB_PRESET_FOREST, - EAX1REVERB_PRESET_CITY, - EAX1REVERB_PRESET_MOUNTAINS, - EAX1REVERB_PRESET_QUARRY, - EAX1REVERB_PRESET_PLAIN, - EAX1REVERB_PRESET_PARKINGLOT, - EAX1REVERB_PRESET_SEWERPIPE, - EAX1REVERB_PRESET_UNDERWATER, - EAX1REVERB_PRESET_DRUGGED, - EAX1REVERB_PRESET_DIZZY, - EAX1REVERB_PRESET_PSYCHOTIC, -}}; diff --git a/al/eax/api.h b/al/eax/api.h index d0737d1d..f4419ddb 100644 --- a/al/eax/api.h +++ b/al/eax/api.h @@ -129,6 +129,110 @@ struct EAX20LISTENERPROPERTIES unsigned long dwFlags; // modifies the behavior of properties }; // EAX20LISTENERPROPERTIES +inline bool operator==(const EAX20LISTENERPROPERTIES& lhs, const EAX20LISTENERPROPERTIES& rhs) noexcept +{ + return std::memcmp(&lhs, &rhs, sizeof(EAX20LISTENERPROPERTIES)) == 0; +} + +enum : unsigned long +{ + EAX2_ENVIRONMENT_GENERIC, + EAX2_ENVIRONMENT_PADDEDCELL, + EAX2_ENVIRONMENT_ROOM, + EAX2_ENVIRONMENT_BATHROOM, + EAX2_ENVIRONMENT_LIVINGROOM, + EAX2_ENVIRONMENT_STONEROOM, + EAX2_ENVIRONMENT_AUDITORIUM, + EAX2_ENVIRONMENT_CONCERTHALL, + EAX2_ENVIRONMENT_CAVE, + EAX2_ENVIRONMENT_ARENA, + EAX2_ENVIRONMENT_HANGAR, + EAX2_ENVIRONMENT_CARPETEDHALLWAY, + EAX2_ENVIRONMENT_HALLWAY, + EAX2_ENVIRONMENT_STONECORRIDOR, + EAX2_ENVIRONMENT_ALLEY, + EAX2_ENVIRONMENT_FOREST, + EAX2_ENVIRONMENT_CITY, + EAX2_ENVIRONMENT_MOUNTAINS, + EAX2_ENVIRONMENT_QUARRY, + EAX2_ENVIRONMENT_PLAIN, + EAX2_ENVIRONMENT_PARKINGLOT, + EAX2_ENVIRONMENT_SEWERPIPE, + EAX2_ENVIRONMENT_UNDERWATER, + EAX2_ENVIRONMENT_DRUGGED, + EAX2_ENVIRONMENT_DIZZY, + EAX2_ENVIRONMENT_PSYCHOTIC, + + EAX2_ENVIRONMENT_COUNT, +}; + +constexpr auto EAX2LISTENERFLAGS_DECAYTIMESCALE = 0x00000001UL; +constexpr auto EAX2LISTENERFLAGS_REFLECTIONSSCALE = 0x00000002UL; +constexpr auto EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL; +constexpr auto EAX2LISTENERFLAGS_REVERBSCALE = 0x00000008UL; +constexpr auto EAX2LISTENERFLAGS_REVERBDELAYSCALE = 0x00000010UL; +constexpr auto EAX2LISTENERFLAGS_DECAYHFLIMIT = 0x00000020UL; +constexpr auto EAX2LISTENERFLAGS_RESERVED = 0xFFFFFFC0UL; + +constexpr auto EAX2LISTENER_MINROOM = -10'000L; +constexpr auto EAX2LISTENER_MAXROOM = 0L; +constexpr auto EAX2LISTENER_DEFAULTROOM = -1'000L; + +constexpr auto EAX2LISTENER_MINROOMHF = -10'000L; +constexpr auto EAX2LISTENER_MAXROOMHF = 0L; +constexpr auto EAX2LISTENER_DEFAULTROOMHF = -100L; + +constexpr auto EAX2LISTENER_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAX2LISTENER_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAX2LISTENER_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAX2LISTENER_MINDECAYTIME = 0.1F; +constexpr auto EAX2LISTENER_MAXDECAYTIME = 20.0F; +constexpr auto EAX2LISTENER_DEFAULTDECAYTIME = 1.49F; + +constexpr auto EAX2LISTENER_MINDECAYHFRATIO = 0.1F; +constexpr auto EAX2LISTENER_MAXDECAYHFRATIO = 2.0F; +constexpr auto EAX2LISTENER_DEFAULTDECAYHFRATIO = 0.83F; + +constexpr auto EAX2LISTENER_MINREFLECTIONS = -10'000L; +constexpr auto EAX2LISTENER_MAXREFLECTIONS = 1'000L; +constexpr auto EAX2LISTENER_DEFAULTREFLECTIONS = -2'602L; + +constexpr auto EAX2LISTENER_MINREFLECTIONSDELAY = 0.0F; +constexpr auto EAX2LISTENER_MAXREFLECTIONSDELAY = 0.3F; +constexpr auto EAX2LISTENER_DEFAULTREFLECTIONSDELAY = 0.007F; + +constexpr auto EAX2LISTENER_MINREVERB = -10'000L; +constexpr auto EAX2LISTENER_MAXREVERB = 2'000L; +constexpr auto EAX2LISTENER_DEFAULTREVERB = 200L; + +constexpr auto EAX2LISTENER_MINREVERBDELAY = 0.0F; +constexpr auto EAX2LISTENER_MAXREVERBDELAY = 0.1F; +constexpr auto EAX2LISTENER_DEFAULTREVERBDELAY = 0.011F; + +constexpr auto EAX2LISTENER_MINENVIRONMENT = 0UL; +constexpr auto EAX2LISTENER_MAXENVIRONMENT = EAX2_ENVIRONMENT_COUNT - 1; +constexpr auto EAX2LISTENER_DEFAULTENVIRONMENT = EAX2_ENVIRONMENT_GENERIC; + +constexpr auto EAX2LISTENER_MINENVIRONMENTSIZE = 1.0F; +constexpr auto EAX2LISTENER_MAXENVIRONMENTSIZE = 100.0F; +constexpr auto EAX2LISTENER_DEFAULTENVIRONMENTSIZE = 7.5F; + +constexpr auto EAX2LISTENER_MINENVIRONMENTDIFFUSION = 0.0F; +constexpr auto EAX2LISTENER_MAXENVIRONMENTDIFFUSION = 1.0F; +constexpr auto EAX2LISTENER_DEFAULTENVIRONMENTDIFFUSION = 1.0F; + +constexpr auto EAX2LISTENER_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAX2LISTENER_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAX2LISTENER_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAX2LISTENER_DEFAULTFLAGS = + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE | + EAX2LISTENERFLAGS_DECAYHFLIMIT; extern const GUID DSPROPSETID_EAX20_BufferProperties; @@ -957,13 +1061,15 @@ constexpr auto EAXREVERB_DEFAULTFLAGS = EAXREVERBFLAGS_DECAYHFLIMIT; -using EaxReverbPresets = std::array<EAXREVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>; -extern const EaxReverbPresets EAXREVERB_PRESETS; - - using Eax1ReverbPresets = std::array<EAX_REVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>; extern const Eax1ReverbPresets EAX1REVERB_PRESETS; +using Eax2ReverbPresets = std::array<EAX20LISTENERPROPERTIES, EAX2_ENVIRONMENT_COUNT>; +extern const Eax2ReverbPresets EAX2REVERB_PRESETS; + +using EaxReverbPresets = std::array<EAXREVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>; +extern const EaxReverbPresets EAXREVERB_PRESETS; + // AGC Compressor Effect diff --git a/al/eax/call.cpp b/al/eax/call.cpp new file mode 100644 index 00000000..1fd05968 --- /dev/null +++ b/al/eax/call.cpp @@ -0,0 +1,212 @@ +#include "config.h" +#include "call.h" +#include "exception.h" + +namespace { + +constexpr auto deferred_flag = 0x80000000U; + +class EaxCallException : public EaxException { +public: + explicit EaxCallException(const char* message) + : EaxException{"EAX_CALL", message} + {} +}; // EaxCallException + +} // namespace + +EaxCall::EaxCall( + EaxCallType type, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) + : type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none} + , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} + , property_buffer_{property_buffer}, property_size_{property_size} +{ + switch (type_) + { + case EaxCallType::get: + case EaxCallType::set: + break; + + default: + fail("Invalid type."); + } + + if (false) + { + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Context) + { + version_ = 4; + property_set_id_ = EaxCallPropertySetId::context; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Context) + { + version_ = 5; + property_set_id_ = EaxCallPropertySetId::context; + } + else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) + { + version_ = 2; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) + { + version_ = 3; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) + { + version_ = 4; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) + { + version_ = 5; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) + { + version_ = 4; + fx_slot_index_ = 1u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) + { + version_ = 5; + fx_slot_index_ = 1u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) + { + version_ = 4; + fx_slot_index_ = 2u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) + { + version_ = 5; + fx_slot_index_ = 2u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) + { + version_ = 4; + fx_slot_index_ = 3u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) + { + version_ = 5; + fx_slot_index_ = 3u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) + { + version_ = 2; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) + { + version_ = 3; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Source) + { + version_ = 4; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Source) + { + version_ = 5; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) + { + version_ = 1; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) + { + version_ = 1; + property_set_id_ = EaxCallPropertySetId::source; + } + else + { + fail("Unsupported property set id."); + } + + if (version_ < 1 || version_ > 5) + { + fail("EAX version out of range."); + } + + if(!(property_id&deferred_flag)) + { + if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0) + { + if (property_buffer == nullptr) + { + fail("Null property buffer."); + } + + if (property_size == 0) + { + fail("Empty property."); + } + } + } + + if(property_set_id_ == EaxCallPropertySetId::source && property_source_id_ == 0) + { + fail("Null AL source id."); + } + + if (property_set_id_ == EaxCallPropertySetId::fx_slot) + { + if (property_id_ < EAXFXSLOT_NONE) + { + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + } +} + +[[noreturn]] void EaxCall::fail(const char* message) +{ + throw EaxCallException{message}; +} + +[[noreturn]] void EaxCall::fail_too_small() +{ + fail("Property buffer too small."); +} + +EaxCall create_eax_call( + EaxCallType type, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + if(!property_set_id) + throw EaxCallException{"Null property set ID."}; + + return EaxCall{ + type, + *property_set_id, + property_id, + property_source_id, + property_buffer, + property_size + }; +} diff --git a/al/eax/eax_call.h b/al/eax/call.h index 2c90bdc3..d491d6f9 100644 --- a/al/eax/eax_call.h +++ b/al/eax/call.h @@ -1,117 +1,92 @@ #ifndef EAX_EAX_CALL_INCLUDED #define EAX_EAX_CALL_INCLUDED - #include "AL/al.h" - #include "alspan.h" - #include "api.h" #include "fx_slot_index.h" - -enum class EaxEaxCallPropertySetId -{ +enum class EaxCallType { none, + get, + set, +}; // EaxCallType +enum class EaxCallPropertySetId { + none, context, fx_slot, source, fx_slot_effect, -}; // EaxEaxCallPropertySetId - +}; // EaxCallPropertySetId -class EaxEaxCall -{ +class EaxCall { public: - EaxEaxCall( - bool is_get, + EaxCall( + EaxCallType type, const GUID& property_set_guid, ALuint property_id, ALuint property_source_id, ALvoid* property_buffer, ALuint property_size); - bool is_get() const noexcept { return is_get_; } + bool is_get() const noexcept { return type_ == EaxCallType::get; } int get_version() const noexcept { return version_; } - EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } + EaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } ALuint get_property_id() const noexcept { return property_id_; } ALuint get_property_al_name() const noexcept { return property_source_id_; } EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; } - template< - typename TException, - typename TValue - > + template<typename TException, typename TValue> TValue& get_value() const { if (property_size_ < static_cast<ALuint>(sizeof(TValue))) { - throw TException{"Property buffer too small."}; + fail_too_small(); } return *static_cast<TValue*>(property_buffer_); } - template< - typename TException, - typename TValue - > + template<typename TException, typename TValue> al::span<TValue> get_values() const { if (property_size_ < static_cast<ALuint>(sizeof(TValue))) { - throw TException{"Property buffer too small."}; + fail_too_small(); } const auto count = property_size_ / sizeof(TValue); - return al::span<TValue>{static_cast<TValue*>(property_buffer_), count}; } - template< - typename TException, - typename TValue - > - void set_value( - const TValue& value) const + template<typename TException, typename TValue> + void set_value(const TValue& value) const { get_value<TException, TValue>() = value; } - private: - const bool is_get_; + EaxCallType type_; int version_; EaxFxSlotIndex fx_slot_index_; - EaxEaxCallPropertySetId property_set_id_; + EaxCallPropertySetId property_set_id_; ALuint property_id_; - const ALuint property_source_id_; - ALvoid*const property_buffer_; - const ALuint property_size_; - - - [[noreturn]] - static void fail( - const char* message); - + ALuint property_source_id_; + ALvoid*property_buffer_; + ALuint property_size_; - static ALuint convert_eax_v2_0_listener_property_id( - ALuint property_id); + [[noreturn]] static void fail(const char* message); + [[noreturn]] static void fail_too_small(); +}; // EaxCall - static ALuint convert_eax_v2_0_buffer_property_id( - ALuint property_id); -}; // EaxEaxCall - - -EaxEaxCall create_eax_call( - bool is_get, +EaxCall create_eax_call( + EaxCallType type, const GUID* property_set_id, ALuint property_id, ALuint property_source_id, ALvoid* property_buffer, ALuint property_size); - #endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax/eax_call.cpp b/al/eax/eax_call.cpp deleted file mode 100644 index 19565852..00000000 --- a/al/eax/eax_call.cpp +++ /dev/null @@ -1,323 +0,0 @@ -#include "config.h" - -#include "eax_call.h" -#include "exception.h" - - -namespace { - -constexpr auto deferred_flag = 0x80000000U; - -class EaxEaxCallException : - public EaxException -{ -public: - explicit EaxEaxCallException( - const char* message) - : - EaxException{"EAX_EAX_CALL", message} - { - } -}; // EaxEaxCallException - -} // namespace - - -EaxEaxCall::EaxEaxCall( - bool is_get, - const GUID& property_set_guid, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) - : is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none} - , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} - , property_buffer_{property_buffer}, property_size_{property_size} -{ - if (false) - { - } - else if (property_set_guid == EAXPROPERTYID_EAX40_Context) - { - version_ = 4; - property_set_id_ = EaxEaxCallPropertySetId::context; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_Context) - { - version_ = 5; - property_set_id_ = EaxEaxCallPropertySetId::context; - } - else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) - { - version_ = 2; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - property_id_ = convert_eax_v2_0_listener_property_id(property_id_); - } - else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) - { - version_ = 3; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) - { - version_ = 4; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) - { - version_ = 5; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) - { - version_ = 4; - fx_slot_index_ = 1u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) - { - version_ = 5; - fx_slot_index_ = 1u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) - { - version_ = 4; - fx_slot_index_ = 2u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) - { - version_ = 5; - fx_slot_index_ = 2u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) - { - version_ = 4; - fx_slot_index_ = 3u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) - { - version_ = 5; - fx_slot_index_ = 3u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) - { - version_ = 2; - property_set_id_ = EaxEaxCallPropertySetId::source; - property_id_ = convert_eax_v2_0_buffer_property_id(property_id_); - } - else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) - { - version_ = 3; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_Source) - { - version_ = 4; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_Source) - { - version_ = 5; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) - { - version_ = 1; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) - { - version_ = 1; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else - { - fail("Unsupported property set id."); - } - - if (version_ < 1 || version_ > 5) - { - fail("EAX version out of range."); - } - - if(!(property_id&deferred_flag)) - { - if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) - { - if (!property_buffer) - { - fail("Null property buffer."); - } - - if (property_size == 0) - { - fail("Empty property."); - } - } - } - - if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0) - { - fail("Null AL source id."); - } - - if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot) - { - if (property_id_ < EAXFXSLOT_NONE) - { - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - } -} - -[[noreturn]] -void EaxEaxCall::fail( - const char* message) -{ - throw EaxEaxCallException{message}; -} - -ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id( - ALuint property_id) -{ - switch (property_id) - { - case DSPROPERTY_EAX20LISTENER_NONE: - return EAXREVERB_NONE; - - case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: - return EAXREVERB_ALLPARAMETERS; - - case DSPROPERTY_EAX20LISTENER_ROOM: - return EAXREVERB_ROOM; - - case DSPROPERTY_EAX20LISTENER_ROOMHF: - return EAXREVERB_ROOMHF; - - case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: - return EAXREVERB_ROOMROLLOFFFACTOR; - - case DSPROPERTY_EAX20LISTENER_DECAYTIME: - return EAXREVERB_DECAYTIME; - - case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: - return EAXREVERB_DECAYHFRATIO; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONS: - return EAXREVERB_REFLECTIONS; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: - return EAXREVERB_REFLECTIONSDELAY; - - case DSPROPERTY_EAX20LISTENER_REVERB: - return EAXREVERB_REVERB; - - case DSPROPERTY_EAX20LISTENER_REVERBDELAY: - return EAXREVERB_REVERBDELAY; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: - return EAXREVERB_ENVIRONMENT; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: - return EAXREVERB_ENVIRONMENTSIZE; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: - return EAXREVERB_ENVIRONMENTDIFFUSION; - - case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: - return EAXREVERB_AIRABSORPTIONHF; - - case DSPROPERTY_EAX20LISTENER_FLAGS: - return EAXREVERB_FLAGS; - - default: - fail("Unsupported EAX 2.0 listener property id."); - } -} - -ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id( - ALuint property_id) -{ - switch (property_id) - { - case DSPROPERTY_EAX20BUFFER_NONE: - return EAXSOURCE_NONE; - - case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: - return EAXSOURCE_ALLPARAMETERS; - - case DSPROPERTY_EAX20BUFFER_DIRECT: - return EAXSOURCE_DIRECT; - - case DSPROPERTY_EAX20BUFFER_DIRECTHF: - return EAXSOURCE_DIRECTHF; - - case DSPROPERTY_EAX20BUFFER_ROOM: - return EAXSOURCE_ROOM; - - case DSPROPERTY_EAX20BUFFER_ROOMHF: - return EAXSOURCE_ROOMHF; - - case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: - return EAXSOURCE_ROOMROLLOFFFACTOR; - - case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: - return EAXSOURCE_OBSTRUCTION; - - case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: - return EAXSOURCE_OBSTRUCTIONLFRATIO; - - case DSPROPERTY_EAX20BUFFER_OCCLUSION: - return EAXSOURCE_OCCLUSION; - - case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: - return EAXSOURCE_OCCLUSIONLFRATIO; - - case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: - return EAXSOURCE_OCCLUSIONROOMRATIO; - - case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: - return EAXSOURCE_OUTSIDEVOLUMEHF; - - case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: - return EAXSOURCE_AIRABSORPTIONFACTOR; - - case DSPROPERTY_EAX20BUFFER_FLAGS: - return EAXSOURCE_FLAGS; - - default: - fail("Unsupported EAX 2.0 buffer property id."); - } -} - - -EaxEaxCall create_eax_call( - bool is_get, - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) -{ - if(!property_set_id) - throw EaxEaxCallException{"Null property set ID."}; - - return EaxEaxCall{ - is_get, - *property_set_id, - property_id, - property_source_id, - property_buffer, - property_size - }; -} diff --git a/al/eax/effect.cpp b/al/eax/effect.cpp deleted file mode 100644 index 4e8faa73..00000000 --- a/al/eax/effect.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" - -#include "effect.h" diff --git a/al/eax/effect.h b/al/eax/effect.h index 9c9fdef4..b57bf240 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -2,43 +2,172 @@ #define EAX_EFFECT_INCLUDED +#include <cassert> #include <memory> +#include "alnumeric.h" #include "AL/al.h" #include "core/effects/base.h" -#include "eax_call.h" +#include "call.h" -class EaxEffect +struct EaxEffectErrorMessages { + static constexpr auto unknown_property_id() noexcept { return "Unknown property id."; } + static constexpr auto unknown_version() noexcept { return "Unknown version."; } +}; // EaxEffectErrorMessages + +class EaxEffect { public: - EaxEffect(ALenum type) : al_effect_type_{type} { } + EaxEffect(ALenum type) noexcept : al_effect_type_{type} { } virtual ~EaxEffect() = default; const ALenum al_effect_type_; EffectProps al_effect_props_{}; - virtual void dispatch(const EaxEaxCall& eax_call) = 0; + virtual void dispatch(const EaxCall& call) = 0; // Returns "true" if any immediated property was changed. - // [[nodiscard]] - virtual bool apply_deferred() = 0; + /*[[nodiscard]]*/ virtual bool commit() = 0; }; // EaxEffect +// Base class for EAX4+ effects. +template<typename TException, typename TProps> +class EaxEffect4 : public EaxEffect +{ +public: + EaxEffect4(ALenum type, const EaxCall& call) + : EaxEffect{type}, version_{clamp(call.get_version(), 4, 5)} + {} + + void initialize() + { + set_defaults(); + set_efx_defaults(); + } + + void dispatch(const EaxCall& call) override + { + call.is_get() ? get(call) : set(call); + version_ = call.get_version(); + } + + bool commit() final + { + switch (version_) + { + case 4: return commit_state(state4_); + case 5: return commit_state(state5_); + default: fail_unknown_version(); + } + } + +protected: + using Exception = TException; + using Props = TProps; + + struct State { + Props i; // Immediate. + Props d; // Deferred. + }; // State + + int version_; + Props props_; + State state4_; + State state5_; + + 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; + } + + virtual void set_defaults(Props& props) = 0; + virtual void set_efx_defaults() = 0; + + virtual void get(const EaxCall& call, const Props& props) = 0; + virtual void set(const EaxCall& call, Props& props) = 0; + + virtual bool commit_props(const Props& props) = 0; + + [[noreturn]] static void fail(const char* message) + { + throw Exception{message}; + } + + [[noreturn]] static void fail_unknown_property_id() + { + fail(EaxEffectErrorMessages::unknown_property_id()); + } + + [[noreturn]] static void fail_unknown_version() + { + fail(EaxEffectErrorMessages::unknown_version()); + } + +private: + void set_defaults() + { + set_defaults(props_); + state4_.i = props_; + state4_.d = props_; + state5_.i = props_; + state5_.d = props_; + } + + void get(const EaxCall& call) + { + switch (call.get_version()) + { + case 4: get(call, state4_.i); break; + case 5: get(call, state5_.i); break; + default: fail_unknown_version(); + } + } + + void set(const EaxCall& call) + { + switch (call.get_version()) + { + case 4: set(call, state4_.d); break; + case 5: set(call, state5_.d); break; + default: fail_unknown_version(); + } + } + + bool commit_state(State& state) + { + const auto props = props_; + state.i = state.d; + props_ = state.d; + return commit_props(props); + } +}; // EaxEffect4 using EaxEffectUPtr = std::unique_ptr<EaxEffect>; +// Creates EAX4+ effect. +template<typename TEffect> +EaxEffectUPtr eax_create_eax4_effect(const EaxCall& call) +{ + auto effect = std::make_unique<TEffect>(call); + effect->initialize(); + return effect; +} + EaxEffectUPtr eax_create_eax_null_effect(); -EaxEffectUPtr eax_create_eax_chorus_effect(); -EaxEffectUPtr eax_create_eax_distortion_effect(); -EaxEffectUPtr eax_create_eax_echo_effect(); -EaxEffectUPtr eax_create_eax_flanger_effect(); -EaxEffectUPtr eax_create_eax_frequency_shifter_effect(); -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(); -EaxEffectUPtr eax_create_eax_pitch_shifter_effect(); -EaxEffectUPtr eax_create_eax_ring_modulator_effect(); -EaxEffectUPtr eax_create_eax_auto_wah_effect(); -EaxEffectUPtr eax_create_eax_compressor_effect(); -EaxEffectUPtr eax_create_eax_equalizer_effect(); -EaxEffectUPtr eax_create_eax_reverb_effect(); +EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call); #endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax/fx_slots.cpp b/al/eax/fx_slots.cpp index 5897e951..671d2cfb 100644 --- a/al/eax/fx_slots.cpp +++ b/al/eax/fx_slots.cpp @@ -29,9 +29,10 @@ public: void EaxFxSlots::initialize( + const EaxCall& call, ALCcontext& al_context) { - initialize_fx_slots(al_context); + initialize_fx_slots(call, al_context); } void EaxFxSlots::uninitialize() noexcept @@ -70,6 +71,7 @@ void EaxFxSlots::fail( } void EaxFxSlots::initialize_fx_slots( + const EaxCall& call, ALCcontext& al_context) { auto fx_slot_index = EaxFxSlotIndexValue{}; @@ -77,7 +79,7 @@ void EaxFxSlots::initialize_fx_slots( for (auto& fx_slot : fx_slots_) { fx_slot = eax_create_al_effect_slot(al_context); - fx_slot->eax_initialize(al_context, fx_slot_index); + fx_slot->eax_initialize(call, al_context, fx_slot_index); fx_slot_index += 1; } } diff --git a/al/eax/fx_slots.h b/al/eax/fx_slots.h index 49cabd75..e7d1452e 100644 --- a/al/eax/fx_slots.h +++ b/al/eax/fx_slots.h @@ -7,6 +7,7 @@ #include "al/auxeffectslot.h" #include "api.h" +#include "call.h" #include "fx_slot_index.h" @@ -14,6 +15,7 @@ class EaxFxSlots { public: void initialize( + const EaxCall& call, ALCcontext& al_context); void uninitialize() noexcept; @@ -46,6 +48,7 @@ private: const char* message); void initialize_fx_slots( + const EaxCall& call, ALCcontext& al_context); }; // EaxFxSlots diff --git a/al/eax/x_ram.cpp b/al/eax/x_ram.cpp deleted file mode 100644 index 7332c82e..00000000 --- a/al/eax/x_ram.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" - -#include "x_ram.h" 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 diff --git a/al/source.cpp b/al/source.cpp index 604d4566..f2c7e2f8 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -4068,10 +4068,10 @@ void ALsource::eax_update_primary_fx_slot_id() } void ALsource::eax_defer_active_fx_slots( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto active_fx_slots_span = - eax_call.get_values<EaxSourceActiveFxSlotsException, const GUID>(); + call.get_values<EaxSourceActiveFxSlotsException, const GUID>(); const auto fx_slot_count = active_fx_slots_span.size(); @@ -4436,10 +4436,10 @@ void ALsource::eax_defer_send_all( } void ALsource::eax_defer_send( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values<EaxSourceException, const EAXSOURCESENDPROPERTIES>(); + call.get_values<EaxSourceException, const EAXSOURCESENDPROPERTIES>(); const auto count = eax_all_span.size(); @@ -4463,10 +4463,10 @@ void ALsource::eax_defer_send( } void ALsource::eax_defer_send_exclusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values<EaxSourceException, const EAXSOURCEEXCLUSIONSENDPROPERTIES>(); + call.get_values<EaxSourceException, const EAXSOURCEEXCLUSIONSENDPROPERTIES>(); const auto count = eax_all_span.size(); @@ -4490,10 +4490,10 @@ void ALsource::eax_defer_send_exclusion_all( } void ALsource::eax_defer_send_occlusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values<EaxSourceException, const EAXSOURCEOCCLUSIONSENDPROPERTIES>(); + call.get_values<EaxSourceException, const EAXSOURCEOCCLUSIONSENDPROPERTIES>(); const auto count = eax_all_span.size(); @@ -4517,10 +4517,10 @@ void ALsource::eax_defer_send_occlusion_all( } void ALsource::eax_defer_send_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values<EaxSourceException, const EAXSOURCEALLSENDPROPERTIES>(); + call.get_values<EaxSourceException, const EAXSOURCEALLSENDPROPERTIES>(); const auto count = eax_all_span.size(); @@ -5074,6 +5074,29 @@ void ALsource::eax_defer_source_speaker_level_all( } } +ALuint ALsource::eax2_translate_property_id(const EaxCall& call) +{ + switch (call.get_property_id()) + { + case DSPROPERTY_EAX20BUFFER_NONE: return EAXSOURCE_NONE; + case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: return EAXSOURCE_ALLPARAMETERS; + case DSPROPERTY_EAX20BUFFER_DIRECT: return EAXSOURCE_DIRECT; + case DSPROPERTY_EAX20BUFFER_DIRECTHF: return EAXSOURCE_DIRECTHF; + case DSPROPERTY_EAX20BUFFER_ROOM: return EAXSOURCE_ROOM; + case DSPROPERTY_EAX20BUFFER_ROOMHF: return EAXSOURCE_ROOMHF; + case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: return EAXSOURCE_ROOMROLLOFFFACTOR; + case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: return EAXSOURCE_OBSTRUCTION; + case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: return EAXSOURCE_OBSTRUCTIONLFRATIO; + case DSPROPERTY_EAX20BUFFER_OCCLUSION: return EAXSOURCE_OCCLUSION; + case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: return EAXSOURCE_OCCLUSIONLFRATIO; + case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: return EAXSOURCE_OCCLUSIONROOMRATIO; + case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: return EAXSOURCE_OUTSIDEVOLUMEHF; + case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: return EAXSOURCE_AIRABSORPTIONFACTOR; + case DSPROPERTY_EAX20BUFFER_FLAGS: return EAXSOURCE_FLAGS; + default: eax_fail("Unknown property id."); + } +} + void ALsource::eax1_set_efx() { const auto primary_fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index(); @@ -5088,9 +5111,9 @@ void ALsource::eax1_set_efx() mPropsDirty = true; } -void ALsource::eax1_set_reverb_mix(const EaxEaxCall& eax_call) +void ALsource::eax1_set_reverb_mix(const EaxCall& call) { - const auto reverb_mix = eax_call.get_value<EaxSourceException, const decltype(EAXBUFFER_REVERBPROPERTIES::fMix)>(); + const auto reverb_mix = call.get_value<EaxSourceException, const decltype(EAXBUFFER_REVERBPROPERTIES::fMix)>(); eax1_validate_reverb_mix(reverb_mix); if (eax1_.fMix == reverb_mix) @@ -5101,253 +5124,253 @@ void ALsource::eax1_set_reverb_mix(const EaxEaxCall& eax_call) } void ALsource::eax_defer_source_direct( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto direct = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirect)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirect)>(); eax_validate_source_direct(direct); eax_defer_source_direct(direct); } void ALsource::eax_defer_source_direct_hf( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto direct_hf = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirectHF)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirectHF)>(); eax_validate_source_direct_hf(direct_hf); eax_defer_source_direct_hf(direct_hf); } void ALsource::eax_defer_source_room( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto room = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lRoom)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lRoom)>(); eax_validate_source_room(room); eax_defer_source_room(room); } void ALsource::eax_defer_source_room_hf( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto room_hf = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lRoomHF)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lRoomHF)>(); eax_validate_source_room_hf(room_hf); eax_defer_source_room_hf(room_hf); } void ALsource::eax_defer_source_obstruction( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto obstruction = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lObstruction)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lObstruction)>(); eax_validate_source_obstruction(obstruction); eax_defer_source_obstruction(obstruction); } void ALsource::eax_defer_source_obstruction_lf_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto obstruction_lf_ratio = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flObstructionLFRatio)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flObstructionLFRatio)>(); eax_validate_source_obstruction_lf_ratio(obstruction_lf_ratio); eax_defer_source_obstruction_lf_ratio(obstruction_lf_ratio); } void ALsource::eax_defer_source_occlusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lOcclusion)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lOcclusion)>(); eax_validate_source_occlusion(occlusion); eax_defer_source_occlusion(occlusion); } void ALsource::eax_defer_source_occlusion_lf_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion_lf_ratio = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionLFRatio)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionLFRatio)>(); eax_validate_source_occlusion_lf_ratio(occlusion_lf_ratio); eax_defer_source_occlusion_lf_ratio(occlusion_lf_ratio); } void ALsource::eax_defer_source_occlusion_room_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion_room_ratio = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionRoomRatio)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionRoomRatio)>(); eax_validate_source_occlusion_room_ratio(occlusion_room_ratio); eax_defer_source_occlusion_room_ratio(occlusion_room_ratio); } void ALsource::eax_defer_source_occlusion_direct_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion_direct_ratio = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionDirectRatio)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionDirectRatio)>(); eax_validate_source_occlusion_direct_ratio(occlusion_direct_ratio); eax_defer_source_occlusion_direct_ratio(occlusion_direct_ratio); } void ALsource::eax_defer_source_exclusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto exclusion = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lExclusion)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lExclusion)>(); eax_validate_source_exclusion(exclusion); eax_defer_source_exclusion(exclusion); } void ALsource::eax_defer_source_exclusion_lf_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto exclusion_lf_ratio = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flExclusionLFRatio)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flExclusionLFRatio)>(); eax_validate_source_exclusion_lf_ratio(exclusion_lf_ratio); eax_defer_source_exclusion_lf_ratio(exclusion_lf_ratio); } void ALsource::eax_defer_source_outside_volume_hf( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto outside_volume_hf = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lOutsideVolumeHF)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lOutsideVolumeHF)>(); eax_validate_source_outside_volume_hf(outside_volume_hf); eax_defer_source_outside_volume_hf(outside_volume_hf); } void ALsource::eax_defer_source_doppler_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto doppler_factor = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flDopplerFactor)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flDopplerFactor)>(); eax_validate_source_doppler_factor(doppler_factor); eax_defer_source_doppler_factor(doppler_factor); } void ALsource::eax_defer_source_rolloff_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto rolloff_factor = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flRolloffFactor)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flRolloffFactor)>(); eax_validate_source_rolloff_factor(rolloff_factor); eax_defer_source_rolloff_factor(rolloff_factor); } void ALsource::eax_defer_source_room_rolloff_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto room_rolloff_factor = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flRoomRolloffFactor)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flRoomRolloffFactor)>(); eax_validate_source_room_rolloff_factor(room_rolloff_factor); eax_defer_source_room_rolloff_factor(room_rolloff_factor); } void ALsource::eax_defer_source_air_absorption_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto air_absorption_factor = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flAirAbsorptionFactor)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flAirAbsorptionFactor)>(); eax_validate_source_air_absorption_factor(air_absorption_factor); eax_defer_source_air_absorption_factor(air_absorption_factor); } void ALsource::eax_defer_source_flags( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto flags = - eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::ulFlags)>(); + call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::ulFlags)>(); - eax_validate_source_flags(flags, eax_call.get_version()); + eax_validate_source_flags(flags, call.get_version()); eax_defer_source_flags(flags); } void ALsource::eax_defer_source_macro_fx_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto macro_fx_factor = - eax_call.get_value<EaxSourceException, const decltype(EAX50SOURCEPROPERTIES::flMacroFXFactor)>(); + call.get_value<EaxSourceException, const decltype(EAX50SOURCEPROPERTIES::flMacroFXFactor)>(); eax_validate_source_macro_fx_factor(macro_fx_factor); eax_defer_source_macro_fx_factor(macro_fx_factor); } void ALsource::eax_defer_source_2d_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value<EaxSourceException, const EAXSOURCE2DPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAXSOURCE2DPROPERTIES>(); - eax_validate_source_2d_all(all, eax_call.get_version()); + eax_validate_source_2d_all(all, call.get_version()); eax_defer_source_2d_all(all); } void ALsource::eax_defer_source_obstruction_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value<EaxSourceException, const EAXOBSTRUCTIONPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAXOBSTRUCTIONPROPERTIES>(); eax_validate_source_obstruction_all(all); eax_defer_source_obstruction_all(all); } void ALsource::eax_defer_source_exclusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value<EaxSourceException, const EAXEXCLUSIONPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAXEXCLUSIONPROPERTIES>(); eax_validate_source_exclusion_all(all); eax_defer_source_exclusion_all(all); } void ALsource::eax_defer_source_occlusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value<EaxSourceException, const EAXOCCLUSIONPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAXOCCLUSIONPROPERTIES>(); eax_validate_source_occlusion_all(all); eax_defer_source_occlusion_all(all); } void ALsource::eax_defer_source_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto eax_version = eax_call.get_version(); + const auto eax_version = call.get_version(); if (eax_version == 2) { - const auto all = eax_call.get_value<EaxSourceException, const EAX20BUFFERPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAX20BUFFERPROPERTIES>(); eax_validate_source_all(all, eax_version); eax_defer_source_all(all); } else if (eax_version < 5) { - const auto all = eax_call.get_value<EaxSourceException, const EAX30SOURCEPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAX30SOURCEPROPERTIES>(); eax_validate_source_all(all, eax_version); eax_defer_source_all(all); } else { - const auto all = eax_call.get_value<EaxSourceException, const EAX50SOURCEPROPERTIES>(); + const auto all = call.get_value<EaxSourceException, const EAX50SOURCEPROPERTIES>(); eax_validate_source_all(all, eax_version); eax_defer_source_all(all); @@ -5355,9 +5378,9 @@ void ALsource::eax_defer_source_all( } void ALsource::eax_defer_source_speaker_level_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto speaker_level_properties = eax_call.get_value<EaxSourceException, const EAXSPEAKERLEVELPROPERTIES>(); + const auto speaker_level_properties = call.get_value<EaxSourceException, const EAXSPEAKERLEVELPROPERTIES>(); eax_validate_source_speaker_level_all(speaker_level_properties); eax_defer_source_speaker_level_all(speaker_level_properties); @@ -5433,13 +5456,13 @@ void ALsource::eax_set_speaker_levels() // TODO } -void ALsource::eax1_set(const EaxEaxCall& eax_call) +void ALsource::eax1_set(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case DSPROPERTY_EAXBUFFER_ALL: case DSPROPERTY_EAXBUFFER_REVERBMIX: - eax1_set_reverb_mix(eax_call); + eax1_set_reverb_mix(call); break; default: @@ -5534,137 +5557,141 @@ void ALsource::eax_apply_deferred() } void ALsource::eax_set( - const EaxEaxCall& eax_call) + const EaxCall& call) { - if (eax_call.get_version() == 1) + const auto version = call.get_version(); + + if (version == 1) { - eax1_set(eax_call); + eax1_set(call); return; } - switch (eax_call.get_property_id()) + const auto property_id = (version == 2 ? eax2_translate_property_id(call) : call.get_property_id()); + + switch (property_id) { case EAXSOURCE_NONE: break; case EAXSOURCE_ALLPARAMETERS: - eax_defer_source_all(eax_call); + eax_defer_source_all(call); break; case EAXSOURCE_OBSTRUCTIONPARAMETERS: - eax_defer_source_obstruction_all(eax_call); + eax_defer_source_obstruction_all(call); break; case EAXSOURCE_OCCLUSIONPARAMETERS: - eax_defer_source_occlusion_all(eax_call); + eax_defer_source_occlusion_all(call); break; case EAXSOURCE_EXCLUSIONPARAMETERS: - eax_defer_source_exclusion_all(eax_call); + eax_defer_source_exclusion_all(call); break; case EAXSOURCE_DIRECT: - eax_defer_source_direct(eax_call); + eax_defer_source_direct(call); break; case EAXSOURCE_DIRECTHF: - eax_defer_source_direct_hf(eax_call); + eax_defer_source_direct_hf(call); break; case EAXSOURCE_ROOM: - eax_defer_source_room(eax_call); + eax_defer_source_room(call); break; case EAXSOURCE_ROOMHF: - eax_defer_source_room_hf(eax_call); + eax_defer_source_room_hf(call); break; case EAXSOURCE_OBSTRUCTION: - eax_defer_source_obstruction(eax_call); + eax_defer_source_obstruction(call); break; case EAXSOURCE_OBSTRUCTIONLFRATIO: - eax_defer_source_obstruction_lf_ratio(eax_call); + eax_defer_source_obstruction_lf_ratio(call); break; case EAXSOURCE_OCCLUSION: - eax_defer_source_occlusion(eax_call); + eax_defer_source_occlusion(call); break; case EAXSOURCE_OCCLUSIONLFRATIO: - eax_defer_source_occlusion_lf_ratio(eax_call); + eax_defer_source_occlusion_lf_ratio(call); break; case EAXSOURCE_OCCLUSIONROOMRATIO: - eax_defer_source_occlusion_room_ratio(eax_call); + eax_defer_source_occlusion_room_ratio(call); break; case EAXSOURCE_OCCLUSIONDIRECTRATIO: - eax_defer_source_occlusion_direct_ratio(eax_call); + eax_defer_source_occlusion_direct_ratio(call); break; case EAXSOURCE_EXCLUSION: - eax_defer_source_exclusion(eax_call); + eax_defer_source_exclusion(call); break; case EAXSOURCE_EXCLUSIONLFRATIO: - eax_defer_source_exclusion_lf_ratio(eax_call); + eax_defer_source_exclusion_lf_ratio(call); break; case EAXSOURCE_OUTSIDEVOLUMEHF: - eax_defer_source_outside_volume_hf(eax_call); + eax_defer_source_outside_volume_hf(call); break; case EAXSOURCE_DOPPLERFACTOR: - eax_defer_source_doppler_factor(eax_call); + eax_defer_source_doppler_factor(call); break; case EAXSOURCE_ROLLOFFFACTOR: - eax_defer_source_rolloff_factor(eax_call); + eax_defer_source_rolloff_factor(call); break; case EAXSOURCE_ROOMROLLOFFFACTOR: - eax_defer_source_room_rolloff_factor(eax_call); + eax_defer_source_room_rolloff_factor(call); break; case EAXSOURCE_AIRABSORPTIONFACTOR: - eax_defer_source_air_absorption_factor(eax_call); + eax_defer_source_air_absorption_factor(call); break; case EAXSOURCE_FLAGS: - eax_defer_source_flags(eax_call); + eax_defer_source_flags(call); break; case EAXSOURCE_SENDPARAMETERS: - eax_defer_send(eax_call); + eax_defer_send(call); break; case EAXSOURCE_ALLSENDPARAMETERS: - eax_defer_send_all(eax_call); + eax_defer_send_all(call); break; case EAXSOURCE_OCCLUSIONSENDPARAMETERS: - eax_defer_send_occlusion_all(eax_call); + eax_defer_send_occlusion_all(call); break; case EAXSOURCE_EXCLUSIONSENDPARAMETERS: - eax_defer_send_exclusion_all(eax_call); + eax_defer_send_exclusion_all(call); break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_defer_active_fx_slots(eax_call); + eax_defer_active_fx_slots(call); break; case EAXSOURCE_MACROFXFACTOR: - eax_defer_source_macro_fx_factor(eax_call); + eax_defer_source_macro_fx_factor(call); break; case EAXSOURCE_SPEAKERLEVELS: - eax_defer_source_speaker_level_all(eax_call); + eax_defer_source_speaker_level_all(call); break; case EAXSOURCE_ALL2DPARAMETERS: - eax_defer_source_2d_all(eax_call); + eax_defer_source_2d_all(call); break; default: @@ -5754,13 +5781,13 @@ void ALsource::eax_copy_send( dst_send.flExclusionLFRatio = src_send.flExclusionLFRatio; } -void ALsource::eax1_get(const EaxEaxCall& eax_call) +void ALsource::eax1_get(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case DSPROPERTY_EAXBUFFER_ALL: case DSPROPERTY_EAXBUFFER_REVERBMIX: - eax_call.set_value<EaxSourceException>(eax1_); + call.set_value<EaxSourceException>(eax1_); break; default: @@ -5769,7 +5796,7 @@ void ALsource::eax1_get(const EaxEaxCall& eax_call) } void ALsource::eax_api_get_source_all_v2( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_2_all = EAX20BUFFERPROPERTIES{}; eax_2_all.lDirect = eax_.source.lDirect; @@ -5786,37 +5813,37 @@ void ALsource::eax_api_get_source_all_v2( eax_2_all.flAirAbsorptionFactor = eax_.source.flAirAbsorptionFactor; eax_2_all.dwFlags = eax_.source.ulFlags; - eax_call.set_value<EaxSourceException>(eax_2_all); + call.set_value<EaxSourceException>(eax_2_all); } void ALsource::eax_api_get_source_all_v3( - const EaxEaxCall& eax_call) + const EaxCall& call) { - eax_call.set_value<EaxSourceException>(static_cast<const EAX30SOURCEPROPERTIES&>(eax_.source)); + call.set_value<EaxSourceException>(static_cast<const EAX30SOURCEPROPERTIES&>(eax_.source)); } void ALsource::eax_api_get_source_all_v5( - const EaxEaxCall& eax_call) + const EaxCall& call) { - eax_call.set_value<EaxSourceException>(eax_.source); + call.set_value<EaxSourceException>(eax_.source); } void ALsource::eax_api_get_source_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 2: - eax_api_get_source_all_v2(eax_call); + eax_api_get_source_all_v2(call); break; case 3: case 4: - eax_api_get_source_all_v3(eax_call); + eax_api_get_source_all_v3(call); break; case 5: - eax_api_get_source_all_v5(eax_call); + eax_api_get_source_all_v5(call); break; default: @@ -5825,17 +5852,17 @@ void ALsource::eax_api_get_source_all( } void ALsource::eax_api_get_source_all_obstruction( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_obstruction_all = EAXOBSTRUCTIONPROPERTIES{}; eax_obstruction_all.lObstruction = eax_.source.lObstruction; eax_obstruction_all.flObstructionLFRatio = eax_.source.flObstructionLFRatio; - eax_call.set_value<EaxSourceException>(eax_obstruction_all); + call.set_value<EaxSourceException>(eax_obstruction_all); } void ALsource::eax_api_get_source_all_occlusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_occlusion_all = EAXOCCLUSIONPROPERTIES{}; eax_occlusion_all.lOcclusion = eax_.source.lOcclusion; @@ -5843,35 +5870,35 @@ void ALsource::eax_api_get_source_all_occlusion( eax_occlusion_all.flOcclusionRoomRatio = eax_.source.flOcclusionRoomRatio; eax_occlusion_all.flOcclusionDirectRatio = eax_.source.flOcclusionDirectRatio; - eax_call.set_value<EaxSourceException>(eax_occlusion_all); + call.set_value<EaxSourceException>(eax_occlusion_all); } void ALsource::eax_api_get_source_all_exclusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_exclusion_all = EAXEXCLUSIONPROPERTIES{}; eax_exclusion_all.lExclusion = eax_.source.lExclusion; eax_exclusion_all.flExclusionLFRatio = eax_.source.flExclusionLFRatio; - eax_call.set_value<EaxSourceException>(eax_exclusion_all); + call.set_value<EaxSourceException>(eax_exclusion_all); } void ALsource::eax_api_get_source_active_fx_slot_id( - const EaxEaxCall& eax_call) + const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: { const auto& active_fx_slots = reinterpret_cast<const EAX40ACTIVEFXSLOTS&>(eax_.active_fx_slots); - eax_call.set_value<EaxSourceException>(active_fx_slots); + call.set_value<EaxSourceException>(active_fx_slots); } break; case 5: { const auto& active_fx_slots = reinterpret_cast<const EAX50ACTIVEFXSLOTS&>(eax_.active_fx_slots); - eax_call.set_value<EaxSourceException>(active_fx_slots); + call.set_value<EaxSourceException>(active_fx_slots); } break; @@ -5881,7 +5908,7 @@ void ALsource::eax_api_get_source_active_fx_slot_id( } void ALsource::eax_api_get_source_all_2d( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_2d_all = EAXSOURCE2DPROPERTIES{}; eax_2d_all.lDirect = eax_.source.lDirect; @@ -5890,13 +5917,13 @@ void ALsource::eax_api_get_source_all_2d( eax_2d_all.lRoomHF = eax_.source.lRoomHF; eax_2d_all.ulFlags = eax_.source.ulFlags; - eax_call.set_value<EaxSourceException>(eax_2d_all); + call.set_value<EaxSourceException>(eax_2d_all); } void ALsource::eax_api_get_source_speaker_level_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - auto& all = eax_call.get_value<EaxSourceException, EAXSPEAKERLEVELPROPERTIES>(); + auto& all = call.get_value<EaxSourceException, EAXSPEAKERLEVELPROPERTIES>(); eax_validate_source_speaker_id(all.lSpeakerID); const auto speaker_index = static_cast<std::size_t>(all.lSpeakerID - 1); @@ -5904,137 +5931,141 @@ void ALsource::eax_api_get_source_speaker_level_all( } void ALsource::eax_get( - const EaxEaxCall& eax_call) + const EaxCall& call) { - if (eax_call.get_version() == 1) + const auto version = call.get_version(); + + if (version == 1) { - eax1_get(eax_call); + eax1_get(call); return; } - switch (eax_call.get_property_id()) + const auto property_id = (version == 2 ? eax2_translate_property_id(call) : call.get_property_id()); + + switch (property_id) { case EAXSOURCE_NONE: break; case EAXSOURCE_ALLPARAMETERS: - eax_api_get_source_all(eax_call); + eax_api_get_source_all(call); break; case EAXSOURCE_OBSTRUCTIONPARAMETERS: - eax_api_get_source_all_obstruction(eax_call); + eax_api_get_source_all_obstruction(call); break; case EAXSOURCE_OCCLUSIONPARAMETERS: - eax_api_get_source_all_occlusion(eax_call); + eax_api_get_source_all_occlusion(call); break; case EAXSOURCE_EXCLUSIONPARAMETERS: - eax_api_get_source_all_exclusion(eax_call); + eax_api_get_source_all_exclusion(call); break; case EAXSOURCE_DIRECT: - eax_call.set_value<EaxSourceException>(eax_.source.lDirect); + call.set_value<EaxSourceException>(eax_.source.lDirect); break; case EAXSOURCE_DIRECTHF: - eax_call.set_value<EaxSourceException>(eax_.source.lDirectHF); + call.set_value<EaxSourceException>(eax_.source.lDirectHF); break; case EAXSOURCE_ROOM: - eax_call.set_value<EaxSourceException>(eax_.source.lRoom); + call.set_value<EaxSourceException>(eax_.source.lRoom); break; case EAXSOURCE_ROOMHF: - eax_call.set_value<EaxSourceException>(eax_.source.lRoomHF); + call.set_value<EaxSourceException>(eax_.source.lRoomHF); break; case EAXSOURCE_OBSTRUCTION: - eax_call.set_value<EaxSourceException>(eax_.source.lObstruction); + call.set_value<EaxSourceException>(eax_.source.lObstruction); break; case EAXSOURCE_OBSTRUCTIONLFRATIO: - eax_call.set_value<EaxSourceException>(eax_.source.flObstructionLFRatio); + call.set_value<EaxSourceException>(eax_.source.flObstructionLFRatio); break; case EAXSOURCE_OCCLUSION: - eax_call.set_value<EaxSourceException>(eax_.source.lOcclusion); + call.set_value<EaxSourceException>(eax_.source.lOcclusion); break; case EAXSOURCE_OCCLUSIONLFRATIO: - eax_call.set_value<EaxSourceException>(eax_.source.flOcclusionLFRatio); + call.set_value<EaxSourceException>(eax_.source.flOcclusionLFRatio); break; case EAXSOURCE_OCCLUSIONROOMRATIO: - eax_call.set_value<EaxSourceException>(eax_.source.flOcclusionRoomRatio); + call.set_value<EaxSourceException>(eax_.source.flOcclusionRoomRatio); break; case EAXSOURCE_OCCLUSIONDIRECTRATIO: - eax_call.set_value<EaxSourceException>(eax_.source.flOcclusionDirectRatio); + call.set_value<EaxSourceException>(eax_.source.flOcclusionDirectRatio); break; case EAXSOURCE_EXCLUSION: - eax_call.set_value<EaxSourceException>(eax_.source.lExclusion); + call.set_value<EaxSourceException>(eax_.source.lExclusion); break; case EAXSOURCE_EXCLUSIONLFRATIO: - eax_call.set_value<EaxSourceException>(eax_.source.flExclusionLFRatio); + call.set_value<EaxSourceException>(eax_.source.flExclusionLFRatio); break; case EAXSOURCE_OUTSIDEVOLUMEHF: - eax_call.set_value<EaxSourceException>(eax_.source.lOutsideVolumeHF); + call.set_value<EaxSourceException>(eax_.source.lOutsideVolumeHF); break; case EAXSOURCE_DOPPLERFACTOR: - eax_call.set_value<EaxSourceException>(eax_.source.flDopplerFactor); + call.set_value<EaxSourceException>(eax_.source.flDopplerFactor); break; case EAXSOURCE_ROLLOFFFACTOR: - eax_call.set_value<EaxSourceException>(eax_.source.flRolloffFactor); + call.set_value<EaxSourceException>(eax_.source.flRolloffFactor); break; case EAXSOURCE_ROOMROLLOFFFACTOR: - eax_call.set_value<EaxSourceException>(eax_.source.flRoomRolloffFactor); + call.set_value<EaxSourceException>(eax_.source.flRoomRolloffFactor); break; case EAXSOURCE_AIRABSORPTIONFACTOR: - eax_call.set_value<EaxSourceException>(eax_.source.flAirAbsorptionFactor); + call.set_value<EaxSourceException>(eax_.source.flAirAbsorptionFactor); break; case EAXSOURCE_FLAGS: - eax_call.set_value<EaxSourceException>(eax_.source.ulFlags); + call.set_value<EaxSourceException>(eax_.source.ulFlags); break; case EAXSOURCE_SENDPARAMETERS: - eax_api_get_send_properties<EaxSourceException, EAXSOURCESENDPROPERTIES>(eax_call); + eax_api_get_send_properties<EaxSourceException, EAXSOURCESENDPROPERTIES>(call); break; case EAXSOURCE_ALLSENDPARAMETERS: - eax_api_get_send_properties<EaxSourceException, EAXSOURCEALLSENDPROPERTIES>(eax_call); + eax_api_get_send_properties<EaxSourceException, EAXSOURCEALLSENDPROPERTIES>(call); break; case EAXSOURCE_OCCLUSIONSENDPARAMETERS: - eax_api_get_send_properties<EaxSourceException, EAXSOURCEOCCLUSIONSENDPROPERTIES>(eax_call); + eax_api_get_send_properties<EaxSourceException, EAXSOURCEOCCLUSIONSENDPROPERTIES>(call); break; case EAXSOURCE_EXCLUSIONSENDPARAMETERS: - eax_api_get_send_properties<EaxSourceException, EAXSOURCEEXCLUSIONSENDPROPERTIES>(eax_call); + eax_api_get_send_properties<EaxSourceException, EAXSOURCEEXCLUSIONSENDPROPERTIES>(call); break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_api_get_source_active_fx_slot_id(eax_call); + eax_api_get_source_active_fx_slot_id(call); break; case EAXSOURCE_MACROFXFACTOR: - eax_call.set_value<EaxSourceException>(eax_.source.flMacroFXFactor); + call.set_value<EaxSourceException>(eax_.source.flMacroFXFactor); break; case EAXSOURCE_SPEAKERLEVELS: - eax_api_get_source_speaker_level_all(eax_call); + eax_api_get_source_speaker_level_all(call); break; case EAXSOURCE_ALL2DPARAMETERS: - eax_api_get_source_all_2d(eax_call); + eax_api_get_source_all_2d(call); break; default: diff --git a/al/source.h b/al/source.h index 6fc1c1d4..2d93e177 100644 --- a/al/source.h +++ b/al/source.h @@ -22,7 +22,7 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "eax/eax_call.h" +#include "eax/call.h" #include "eax/fx_slot_index.h" #include "eax/utils.h" #endif // ALSOFT_EAX @@ -216,8 +216,8 @@ public: void eax_initialize(ALCcontext *context) noexcept; - void eax_dispatch(const EaxEaxCall& eax_call) - { eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); } + void eax_dispatch(const EaxCall& call) + { call.is_get() ? eax_get(call) : eax_set(call); } void eax_update_filters(); @@ -308,7 +308,7 @@ private: void eax_defer_active_fx_slots( - const EaxEaxCall& eax_call); + const EaxCall& call); static const char* eax_get_exclusion_name() noexcept; @@ -421,16 +421,16 @@ private: void eax_defer_send( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_send_exclusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_send_occlusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_send_all( - const EaxEaxCall& eax_call); + const EaxCall& call); static void eax_validate_source_direct( @@ -609,79 +609,79 @@ private: void eax_defer_source_direct( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_direct_hf( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_room( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_room_hf( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_obstruction( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_obstruction_lf_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_lf_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_room_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_direct_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_exclusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_exclusion_lf_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_outside_volume_hf( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_doppler_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_rolloff_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_room_rolloff_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_air_absorption_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_flags( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_macro_fx_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_2d_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_obstruction_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_exclusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_speaker_level_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_set_outside_volume_hf(); @@ -708,15 +708,16 @@ private: void eax_set_speaker_levels(); + static ALuint eax2_translate_property_id(const EaxCall& call); void eax1_set_efx(); - void eax1_set_reverb_mix(const EaxEaxCall& eax_call); - void eax1_set(const EaxEaxCall& eax_call); + void eax1_set_reverb_mix(const EaxCall& call); + void eax1_set(const EaxCall& call); void eax_apply_deferred(); void eax_set( - const EaxEaxCall& eax_call); + const EaxCall& call); static const GUID& eax_get_send_fx_slot_guid( @@ -744,10 +745,10 @@ private: typename TSrcSend > void eax_api_get_send_properties( - const EaxEaxCall& eax_call) const + const EaxCall& call) const { - const auto eax_version = eax_call.get_version(); - const auto dst_sends = eax_call.get_values<TException, TSrcSend>(); + const auto eax_version = call.get_version(); + const auto dst_sends = call.get_values<TException, TSrcSend>(); const auto send_count = dst_sends.size(); for (auto fx_slot_index = EaxFxSlotIndexValue{}; fx_slot_index < send_count; ++fx_slot_index) @@ -762,40 +763,40 @@ private: } - void eax1_get(const EaxEaxCall& eax_call); + void eax1_get(const EaxCall& call); void eax_api_get_source_all_v2( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_v3( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_v5( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_obstruction( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_occlusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_exclusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_active_fx_slot_id( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_2d( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_speaker_level_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_get( - const EaxEaxCall& eax_call); + const EaxCall& call); // `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)` diff --git a/alc/context.cpp b/alc/context.cpp index 5fe03e78..33c888e7 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -330,32 +330,29 @@ ALenum ALCcontext::eax_eax_set( ALvoid* property_value, ALuint property_value_size) { - eax_initialize(); - - const auto eax_call = create_eax_call( - false, + const auto call = create_eax_call( + EaxCallType::set, property_set_id, property_id, property_source_id, property_value, - property_value_size - ); - - eax_unlock_legacy_fx_slots(eax_call); + property_value_size); + eax_initialize(call); + eax_unlock_legacy_fx_slots(call); - switch (eax_call.get_property_set_id()) + switch (call.get_property_set_id()) { - case EaxEaxCallPropertySetId::context: - eax_set(eax_call); + case EaxCallPropertySetId::context: + eax_set(call); break; - case EaxEaxCallPropertySetId::fx_slot: - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_fx_slot(call); break; - case EaxEaxCallPropertySetId::source: - eax_dispatch_source(eax_call); + case EaxCallPropertySetId::source: + eax_dispatch_source(call); break; default: @@ -376,32 +373,29 @@ ALenum ALCcontext::eax_eax_get( ALvoid* property_value, ALuint property_value_size) { - eax_initialize(); - - const auto eax_call = create_eax_call( - true, + const auto call = create_eax_call( + EaxCallType::get, property_set_id, property_id, property_source_id, property_value, - property_value_size - ); + property_value_size); + eax_initialize(call); + eax_unlock_legacy_fx_slots(call); - eax_unlock_legacy_fx_slots(eax_call); - - switch (eax_call.get_property_set_id()) + switch (call.get_property_set_id()) { - case EaxEaxCallPropertySetId::context: - eax_get(eax_call); + case EaxCallPropertySetId::context: + eax_get(call); break; - case EaxEaxCallPropertySetId::fx_slot: - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_fx_slot(call); break; - case EaxEaxCallPropertySetId::source: - eax_dispatch_source(eax_call); + case EaxCallPropertySetId::source: + eax_dispatch_source(call); break; default: @@ -478,7 +472,7 @@ void ALCcontext::eax_initialize_extensions() mExtensionList = eax_extension_list_.c_str(); } -void ALCcontext::eax_initialize() +void ALCcontext::eax_initialize(const EaxCall& call) { if (eax_is_initialized_) { @@ -501,7 +495,7 @@ void ALCcontext::eax_initialize() eax_set_defaults(); eax_set_air_absorbtion_hf(); eax_update_speaker_configuration(); - eax_initialize_fx_slots(); + eax_initialize_fx_slots(call); eax_initialize_sources(); eax_is_initialized_ = true; @@ -607,34 +601,32 @@ void ALCcontext::eax_set_defaults() noexcept eax_d_ = eax_; } -void ALCcontext::eax_unlock_legacy_fx_slots(const EaxEaxCall& eax_call) noexcept +void ALCcontext::eax_unlock_legacy_fx_slots(const EaxCall& call) noexcept { - if (eax_call.get_version() != 5 || eax_are_legacy_fx_slots_unlocked_) + if (call.get_version() != 5 || eax_are_legacy_fx_slots_unlocked_) return; eax_are_legacy_fx_slots_unlocked_ = true; eax_fx_slots_.unlock_legacy(); } -void ALCcontext::eax_dispatch_fx_slot( - const EaxEaxCall& eax_call) +void ALCcontext::eax_dispatch_fx_slot(const EaxCall& call) { - const auto fx_slot_index = eax_call.get_fx_slot_index(); + const auto fx_slot_index = call.get_fx_slot_index(); if(!fx_slot_index.has_value()) eax_fail("Invalid fx slot index."); auto& fx_slot = eax_get_fx_slot(*fx_slot_index); - if(fx_slot.eax_dispatch(eax_call)) + if(fx_slot.eax_dispatch(call)) { std::lock_guard<std::mutex> source_lock{mSourceLock}; eax_update_filters(); } } -void ALCcontext::eax_dispatch_source( - const EaxEaxCall& eax_call) +void ALCcontext::eax_dispatch_source(const EaxCall& call) { - const auto source_id = eax_call.get_property_al_name(); + const auto source_id = call.get_property_al_name(); std::lock_guard<std::mutex> source_lock{mSourceLock}; @@ -645,70 +637,61 @@ void ALCcontext::eax_dispatch_source( eax_fail("Source not found."); } - source->eax_dispatch(eax_call); + source->eax_dispatch(call); } -void ALCcontext::eax_get_primary_fx_slot_id( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_primary_fx_slot_id(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_.context.guidPrimaryFXSlotID); + call.set_value<ContextException>(eax_.context.guidPrimaryFXSlotID); } -void ALCcontext::eax_get_distance_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_distance_factor(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_.context.flDistanceFactor); + call.set_value<ContextException>(eax_.context.flDistanceFactor); } -void ALCcontext::eax_get_air_absorption_hf( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_air_absorption_hf(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_.context.flAirAbsorptionHF); + call.set_value<ContextException>(eax_.context.flAirAbsorptionHF); } -void ALCcontext::eax_get_hf_reference( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_hf_reference(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_.context.flHFReference); + call.set_value<ContextException>(eax_.context.flHFReference); } -void ALCcontext::eax_get_last_error( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_last_error(const EaxCall& call) { const auto eax_last_error = eax_last_error_; eax_last_error_ = EAX_OK; - eax_call.set_value<ContextException>(eax_last_error); + call.set_value<ContextException>(eax_last_error); } -void ALCcontext::eax_get_speaker_config( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_speaker_config(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_speaker_config_); + call.set_value<ContextException>(eax_speaker_config_); } -void ALCcontext::eax_get_session( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_session(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_session_); + call.set_value<ContextException>(eax_session_); } -void ALCcontext::eax_get_macro_fx_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_macro_fx_factor(const EaxCall& call) { - eax_call.set_value<ContextException>(eax_.context.flMacroFXFactor); + call.set_value<ContextException>(eax_.context.flMacroFXFactor); } -void ALCcontext::eax_get_context_all( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_context_all(const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: - eax_call.set_value<ContextException>(static_cast<const EAX40CONTEXTPROPERTIES&>(eax_.context)); + call.set_value<ContextException>(static_cast<const EAX40CONTEXTPROPERTIES&>(eax_.context)); break; case 5: - eax_call.set_value<ContextException>(static_cast<const EAX50CONTEXTPROPERTIES&>(eax_.context)); + call.set_value<ContextException>(static_cast<const EAX50CONTEXTPROPERTIES&>(eax_.context)); break; default: @@ -716,48 +699,47 @@ void ALCcontext::eax_get_context_all( } } -void ALCcontext::eax_get( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXCONTEXT_NONE: break; case EAXCONTEXT_ALLPARAMETERS: - eax_get_context_all(eax_call); + eax_get_context_all(call); break; case EAXCONTEXT_PRIMARYFXSLOTID: - eax_get_primary_fx_slot_id(eax_call); + eax_get_primary_fx_slot_id(call); break; case EAXCONTEXT_DISTANCEFACTOR: - eax_get_distance_factor(eax_call); + eax_get_distance_factor(call); break; case EAXCONTEXT_AIRABSORPTIONHF: - eax_get_air_absorption_hf(eax_call); + eax_get_air_absorption_hf(call); break; case EAXCONTEXT_HFREFERENCE: - eax_get_hf_reference(eax_call); + eax_get_hf_reference(call); break; case EAXCONTEXT_LASTERROR: - eax_get_last_error(eax_call); + eax_get_last_error(call); break; case EAXCONTEXT_SPEAKERCONFIG: - eax_get_speaker_config(eax_call); + eax_get_speaker_config(call); break; case EAXCONTEXT_EAXSESSION: - eax_get_session(eax_call); + eax_get_session(call); break; case EAXCONTEXT_MACROFXFACTOR: - eax_get_macro_fx_factor(eax_call); + eax_get_macro_fx_factor(call); break; default: @@ -801,9 +783,9 @@ void ALCcontext::eax_set_context() eax_set_hf_reference(); } -void ALCcontext::eax_initialize_fx_slots() +void ALCcontext::eax_initialize_fx_slots(const EaxCall& call) { - eax_fx_slots_.initialize(*this); + eax_fx_slots_.initialize(call, *this); eax_previous_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; eax_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; } @@ -1007,15 +989,14 @@ void ALCcontext::eax_defer_context_all( eax_defer_macro_fx_factor(context_all.flMacroFXFactor); } -void ALCcontext::eax_defer_context_all( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_context_all(const EaxCall& call) { - switch(eax_call.get_version()) + switch(call.get_version()) { case 4: { const auto& context_all = - eax_call.get_value<ContextException, EAX40CONTEXTPROPERTIES>(); + call.get_value<ContextException, EAX40CONTEXTPROPERTIES>(); eax_validate_context_all(context_all); eax_defer_context_all(context_all); @@ -1025,7 +1006,7 @@ void ALCcontext::eax_defer_context_all( case 5: { const auto& context_all = - eax_call.get_value<ContextException, EAX50CONTEXTPROPERTIES>(); + call.get_value<ContextException, EAX50CONTEXTPROPERTIES>(); eax_validate_context_all(context_all); eax_defer_context_all(context_all); @@ -1037,93 +1018,86 @@ void ALCcontext::eax_defer_context_all( } } -void ALCcontext::eax_defer_primary_fx_slot_id( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_primary_fx_slot_id(const EaxCall& call) { const auto& primary_fx_slot_id = - eax_call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID)>(); + call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID)>(); eax_validate_primary_fx_slot_id(primary_fx_slot_id); eax_defer_primary_fx_slot_id(primary_fx_slot_id); } -void ALCcontext::eax_defer_distance_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_distance_factor(const EaxCall& call) { const auto& distance_factor = - eax_call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flDistanceFactor)>(); + call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flDistanceFactor)>(); eax_validate_distance_factor(distance_factor); eax_defer_distance_factor(distance_factor); } -void ALCcontext::eax_defer_air_absorption_hf( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_air_absorption_hf(const EaxCall& call) { const auto& air_absorption_hf = - eax_call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flAirAbsorptionHF)>(); + call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flAirAbsorptionHF)>(); eax_validate_air_absorption_hf(air_absorption_hf); eax_defer_air_absorption_hf(air_absorption_hf); } -void ALCcontext::eax_defer_hf_reference( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_hf_reference(const EaxCall& call) { const auto& hf_reference = - eax_call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flHFReference)>(); + call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flHFReference)>(); eax_validate_hf_reference(hf_reference); eax_defer_hf_reference(hf_reference); } -void ALCcontext::eax_set_session( - const EaxEaxCall& eax_call) +void ALCcontext::eax_set_session(const EaxCall& call) { const auto& eax_session = - eax_call.get_value<ContextException, const EAXSESSIONPROPERTIES>(); + call.get_value<ContextException, const EAXSESSIONPROPERTIES>(); eax_validate_session(eax_session); eax_session_ = eax_session; } -void ALCcontext::eax_defer_macro_fx_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_macro_fx_factor(const EaxCall& call) { const auto& macro_fx_factor = - eax_call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flMacroFXFactor)>(); + call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flMacroFXFactor)>(); eax_validate_macro_fx_factor(macro_fx_factor); eax_defer_macro_fx_factor(macro_fx_factor); } -void ALCcontext::eax_set( - const EaxEaxCall& eax_call) +void ALCcontext::eax_set(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXCONTEXT_NONE: break; case EAXCONTEXT_ALLPARAMETERS: - eax_defer_context_all(eax_call); + eax_defer_context_all(call); break; case EAXCONTEXT_PRIMARYFXSLOTID: - eax_defer_primary_fx_slot_id(eax_call); + eax_defer_primary_fx_slot_id(call); break; case EAXCONTEXT_DISTANCEFACTOR: - eax_defer_distance_factor(eax_call); + eax_defer_distance_factor(call); break; case EAXCONTEXT_AIRABSORPTIONHF: - eax_defer_air_absorption_hf(eax_call); + eax_defer_air_absorption_hf(call); break; case EAXCONTEXT_HFREFERENCE: - eax_defer_hf_reference(eax_call); + eax_defer_hf_reference(call); break; case EAXCONTEXT_LASTERROR: @@ -1133,11 +1107,11 @@ void ALCcontext::eax_set( eax_fail("Speaker configuration is read-only."); case EAXCONTEXT_EAXSESSION: - eax_set_session(eax_call); + eax_set_session(call); break; case EAXCONTEXT_MACROFXFACTOR: - eax_defer_macro_fx_factor(eax_call); + eax_defer_macro_fx_factor(call); break; default: diff --git a/alc/context.h b/alc/context.h index b3f1ea09..a34e3e4b 100644 --- a/alc/context.h +++ b/alc/context.h @@ -20,7 +20,7 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "al/eax/eax_call.h" +#include "al/eax/call.h" #include "al/eax/fx_slot_index.h" #include "al/eax/fx_slots.h" #include "al/eax/utils.h" @@ -297,7 +297,7 @@ private: void eax_initialize_extensions(); - void eax_initialize(); + void eax_initialize(const EaxCall& call); bool eax_has_no_default_effect_slot() const noexcept; @@ -326,45 +326,33 @@ private: void eax_initialize_sources(); - void eax_unlock_legacy_fx_slots(const EaxEaxCall& eax_call) noexcept; + void eax_unlock_legacy_fx_slots(const EaxCall& call) noexcept; - void eax_dispatch_fx_slot( - const EaxEaxCall& eax_call); + void eax_dispatch_fx_slot(const EaxCall& call); - void eax_dispatch_source( - const EaxEaxCall& eax_call); + void eax_dispatch_source(const EaxCall& call); - void eax_get_primary_fx_slot_id( - const EaxEaxCall& eax_call); + void eax_get_primary_fx_slot_id(const EaxCall& call); - void eax_get_distance_factor( - const EaxEaxCall& eax_call); + void eax_get_distance_factor(const EaxCall& call); - void eax_get_air_absorption_hf( - const EaxEaxCall& eax_call); + void eax_get_air_absorption_hf(const EaxCall& call); - void eax_get_hf_reference( - const EaxEaxCall& eax_call); + void eax_get_hf_reference(const EaxCall& call); - void eax_get_last_error( - const EaxEaxCall& eax_call); + void eax_get_last_error(const EaxCall& call); - void eax_get_speaker_config( - const EaxEaxCall& eax_call); + void eax_get_speaker_config(const EaxCall& call); - void eax_get_session( - const EaxEaxCall& eax_call); + void eax_get_session(const EaxCall& call); - void eax_get_macro_fx_factor( - const EaxEaxCall& eax_call); + void eax_get_macro_fx_factor(const EaxCall& call); - void eax_get_context_all( - const EaxEaxCall& eax_call); + void eax_get_context_all(const EaxCall& call); - void eax_get( - const EaxEaxCall& eax_call); + void eax_get(const EaxCall& call); void eax_set_primary_fx_slot_id(); @@ -379,7 +367,7 @@ private: void eax_set_context(); - void eax_initialize_fx_slots(); + void eax_initialize_fx_slots(const EaxCall& call); void eax_update_sources(); @@ -441,29 +429,21 @@ private: const EAX50CONTEXTPROPERTIES& context_all); - void eax_defer_context_all( - const EaxEaxCall& eax_call); + void eax_defer_context_all(const EaxCall& call); - void eax_defer_primary_fx_slot_id( - const EaxEaxCall& eax_call); + void eax_defer_primary_fx_slot_id(const EaxCall& call); - void eax_defer_distance_factor( - const EaxEaxCall& eax_call); + void eax_defer_distance_factor(const EaxCall& call); - void eax_defer_air_absorption_hf( - const EaxEaxCall& eax_call); + void eax_defer_air_absorption_hf(const EaxCall& call); - void eax_defer_hf_reference( - const EaxEaxCall& eax_call); + void eax_defer_hf_reference(const EaxCall& call); - void eax_set_session( - const EaxEaxCall& eax_call); + void eax_set_session(const EaxCall& call); - void eax_defer_macro_fx_factor( - const EaxEaxCall& eax_call); + void eax_defer_macro_fx_factor(const EaxCall& call); - void eax_set( - const EaxEaxCall& eax_call); + void eax_set(const EaxCall& call); void eax_apply_deferred(); #endif // ALSOFT_EAX |