diff options
Diffstat (limited to 'al')
-rw-r--r-- | al/auxeffectslot.cpp | 142 | ||||
-rw-r--r-- | al/auxeffectslot.h | 8 | ||||
-rw-r--r-- | al/eax/effect.h | 297 | ||||
-rw-r--r-- | al/effects/effects.cpp | 53 | ||||
-rw-r--r-- | al/effects/effects.h | 5 | ||||
-rw-r--r-- | al/effects/null.cpp | 66 | ||||
-rw-r--r-- | al/effects/reverb.cpp | 1913 |
7 files changed, 1078 insertions, 1406 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 81929702..e716beb7 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1052,53 +1052,45 @@ void ALeffectslot::eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue in if(index >= EAX_MAX_FXSLOTS) eax_fail("Index out of range."); - mPropsDirty = true; eax_al_context_ = &al_context; eax_fx_slot_index_ = index; - eax_version_ = eax_al_context_->eax_get_version(); eax_fx_slot_set_defaults(); + + eax_effect_ = std::make_unique<EaxEffect>(); + if(index == 0) eax_effect_->init<EaxReverbCommitter>(); + //else if(index == 1) eax_effect_->init<EaxChorusCommitter>(); + else eax_effect_->init<EaxNullCommitter>(); } void ALeffectslot::eax_commit() { - auto df = EaxDirtyFlags{}; - - switch(eax_version_) + if(eax_df_ != EaxDirtyFlags{}) { - case 1: - case 2: - case 3: - eax5_fx_slot_commit(eax123_, df); - break; - case 4: - eax4_fx_slot_commit(df); - break; - case 5: - eax5_fx_slot_commit(eax5_, df); - break; - default: - eax_fail_unknown_version(); - } - - if(df == EaxDirtyFlags{}) { - if(eax_effect_ != nullptr && eax_effect_->commit()) - eax_set_efx_slot_effect(*eax_effect_); - - return; - } + auto df = EaxDirtyFlags{}; + switch(eax_version_) + { + case 1: + case 2: + case 3: + eax5_fx_slot_commit(eax123_, df); + break; + case 4: + eax4_fx_slot_commit(df); + break; + case 5: + eax5_fx_slot_commit(eax5_, df); + break; + } + eax_df_ = EaxDirtyFlags{}; - if((df & eax_load_effect_dirty_bit) != EaxDirtyFlags{}) - eax_fx_slot_load_effect(); - else { - if(eax_effect_ != nullptr && eax_effect_->commit()) - eax_set_efx_slot_effect(*eax_effect_); + if((df & eax_volume_dirty_bit) != EaxDirtyFlags{}) + eax_fx_slot_set_volume(); + if((df & eax_flags_dirty_bit) != EaxDirtyFlags{}) + eax_fx_slot_set_flags(); } - if((df & eax_volume_dirty_bit) != EaxDirtyFlags{}) - eax_fx_slot_set_volume(); - - if((df & eax_flags_dirty_bit) != EaxDirtyFlags{}) - eax_fx_slot_set_flags(); + if(eax_effect_->do_commit(eax_version_)) + eax_set_efx_slot_effect(*eax_effect_); } [[noreturn]] void ALeffectslot::eax_fail(const char* message) @@ -1192,46 +1184,14 @@ void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) noexcept props.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } -void ALeffectslot::eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept -{ - static_cast<Eax4Props&>(eax_) = props; - eax_.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; - eax_.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; -} - -void ALeffectslot::eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept -{ - eax_ = props; -} - -void ALeffectslot::eax_fx_slot_set_current_defaults() -{ - switch(eax_version_) - { - case 1: - case 2: - case 3: - eax5_fx_slot_set_current_defaults(eax123_.i); - break; - case 4: - eax4_fx_slot_set_current_defaults(eax4_.i); - break; - case 5: - eax5_fx_slot_set_current_defaults(eax5_.i); - break; - default: - eax_fail_unknown_version(); - } - - eax_df_ = ~EaxDirtyFlags{}; -} - void ALeffectslot::eax_fx_slot_set_defaults() { eax5_fx_slot_set_defaults(eax123_.i); eax4_fx_slot_set_defaults(eax4_.i); eax5_fx_slot_set_defaults(eax5_.i); - eax_fx_slot_set_current_defaults(); + eax_ = eax5_.i; + eax_version_ = 5; + eax_df_ = EaxDirtyFlags{}; } void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const @@ -1306,7 +1266,7 @@ bool ALeffectslot::eax_get(const EaxCall& call) eax_fx_slot_get(call); break; case EaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(call); + eax_effect_->get(call); break; default: eax_fail_unknown_property_id(); @@ -1315,16 +1275,11 @@ bool ALeffectslot::eax_get(const EaxCall& call) return false; } -void ALeffectslot::eax_fx_slot_load_effect() +void ALeffectslot::eax_fx_slot_load_effect(int version, ALenum altype) { - eax_effect_ = nullptr; - const auto efx_effect_type = eax_get_efx_effect_type(eax_.guidLoadEffect); - - if(!IsValidEffectType(efx_effect_type)) - eax_fail("Invalid effect type."); - - eax_effect_ = eax_create_eax_effect(efx_effect_type, eax_version_); - eax_set_efx_slot_effect(*eax_effect_); + if(!IsValidEffectType(altype)) + altype = AL_EFFECT_NULL; + eax_effect_->set_defaults(version, altype); } void ALeffectslot::eax_fx_slot_set_volume() @@ -1395,10 +1350,14 @@ bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) break; case EAXFXSLOT_ALLPARAMETERS: eax4_fx_slot_set_all(call); + if((eax_df_ & eax_load_effect_dirty_bit)) + eax_fx_slot_load_effect(4, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_LOADEFFECT: eax4_fx_slot_ensure_unlocked(); eax_fx_slot_set_dirty<Eax4GuidLoadEffectValidator, eax_load_effect_dirty_bit>(call, dst.guidLoadEffect, eax_df_); + if((eax_df_ & eax_load_effect_dirty_bit)) + eax_fx_slot_load_effect(4, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_VOLUME: eax_fx_slot_set<Eax4VolumeValidator, eax_volume_dirty_bit>(call, dst.lVolume, eax_df_); @@ -1428,9 +1387,13 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) break; case EAXFXSLOT_ALLPARAMETERS: eax5_fx_slot_set_all(call); + if((eax_df_ & eax_load_effect_dirty_bit)) + eax_fx_slot_load_effect(5, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_LOADEFFECT: eax_fx_slot_set_dirty<Eax4GuidLoadEffectValidator, eax_load_effect_dirty_bit>(call, dst.guidLoadEffect, eax_df_); + if((eax_df_ & eax_load_effect_dirty_bit)) + eax_fx_slot_load_effect(5, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_VOLUME: eax_fx_slot_set<Eax4VolumeValidator, eax_volume_dirty_bit>(call, dst.lVolume, eax_df_); @@ -1477,16 +1440,13 @@ bool ALeffectslot::eax_set(const EaxCall& call) switch(call.get_property_set_id()) { case EaxCallPropertySetId::fx_slot: return eax_fx_slot_set(call); - case EaxCallPropertySetId::fx_slot_effect: eax_dispatch_effect(call); return false; + case EaxCallPropertySetId::fx_slot_effect: eax_effect_->set(call); return false; default: eax_fail_unknown_property_id(); } } void ALeffectslot::eax4_fx_slot_commit(EaxDirtyFlags& dst_df) { - if(eax_df_ == EaxDirtyFlags{}) - return; - eax_fx_slot_commit_property<eax_load_effect_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::guidLoadEffect); eax_fx_slot_commit_property<eax_volume_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lVolume); eax_fx_slot_commit_property<eax_lock_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lLock); @@ -1503,28 +1463,16 @@ void ALeffectslot::eax4_fx_slot_commit(EaxDirtyFlags& dst_df) dst_df |= eax_occlusion_lf_ratio_dirty_bit; dst_i.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } - - eax_df_ = EaxDirtyFlags{}; } void ALeffectslot::eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df) { - if(eax_df_ == EaxDirtyFlags{}) - return; - eax_fx_slot_commit_property<eax_load_effect_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::guidLoadEffect); eax_fx_slot_commit_property<eax_volume_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::lVolume); eax_fx_slot_commit_property<eax_lock_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::lLock); eax_fx_slot_commit_property<eax_flags_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::ulFlags); eax_fx_slot_commit_property<eax_occlusion_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::lOcclusion); eax_fx_slot_commit_property<eax_occlusion_lf_ratio_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::flOcclusionLFRatio); - eax_df_ = EaxDirtyFlags{}; -} - -void ALeffectslot::eax_dispatch_effect(const EaxCall& call) -{ - if(eax_effect_ != nullptr) - eax_effect_->dispatch(call); } void ALeffectslot::eax_set_efx_slot_effect(EaxEffect &effect) diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 9b6403f4..10f69270 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -132,7 +132,7 @@ private: void operator()(const GUID& guidLoadEffect) const { if (guidLoadEffect != EAX_NULL_GUID && - guidLoadEffect != EAX_REVERB_EFFECT && + guidLoadEffect != EAX_REVERB_EFFECT /*&& guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT && guidLoadEffect != EAX_AUTOWAH_EFFECT && guidLoadEffect != EAX_CHORUS_EFFECT && @@ -143,7 +143,7 @@ private: guidLoadEffect != EAX_FREQUENCYSHIFTER_EFFECT && guidLoadEffect != EAX_VOCALMORPHER_EFFECT && guidLoadEffect != EAX_PITCHSHIFTER_EFFECT && - guidLoadEffect != EAX_RINGMODULATOR_EFFECT) + guidLoadEffect != EAX_RINGMODULATOR_EFFECT*/) { eax_fail_unknown_effect_id(); } @@ -299,7 +299,7 @@ private: // Returns `true` if all sources should be updated, or `false` otherwise. bool eax_get(const EaxCall& call); - void eax_fx_slot_load_effect(); + void eax_fx_slot_load_effect(int version, ALenum altype); void eax_fx_slot_set_volume(); void eax_fx_slot_set_environment_flag(); void eax_fx_slot_set_flags(); @@ -339,8 +339,6 @@ private: void eax4_fx_slot_commit(EaxDirtyFlags& dst_df); void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df); - void eax_dispatch_effect(const EaxCall& call); - // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` void eax_set_efx_slot_effect(EaxEffect &effect); diff --git a/al/eax/effect.h b/al/eax/effect.h index a9dcd14d..15fa34dc 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -39,14 +39,143 @@ struct EaxEffectProps { }; }; +constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props) +{ + switch(props.mType) + { + case EaxEffectType::None: break; + case EaxEffectType::Reverb: return AL_EFFECT_EAXREVERB; + case EaxEffectType::Chorus: return AL_EFFECT_CHORUS; + case EaxEffectType::Autowah: return AL_EFFECT_AUTOWAH; + case EaxEffectType::Compressor: return AL_EFFECT_COMPRESSOR; + case EaxEffectType::Distortion: return AL_EFFECT_DISTORTION; + case EaxEffectType::Echo: return AL_EFFECT_ECHO; + case EaxEffectType::Equalizer: return AL_EFFECT_EQUALIZER; + case EaxEffectType::Flanger: return AL_EFFECT_FLANGER; + case EaxEffectType::FrequencyShifter: return AL_EFFECT_FREQUENCY_SHIFTER; + case EaxEffectType::Modulator: return AL_EFFECT_RING_MODULATOR; + case EaxEffectType::PitchShifter: return AL_EFFECT_PITCH_SHIFTER; + case EaxEffectType::VocalMorpher: return AL_EFFECT_VOCAL_MORPHER; + } + return AL_EFFECT_NULL; +} + +struct EaxReverbCommitter { + struct Exception; + + EaxReverbCommitter(EaxEffectProps &eaxprops, EffectProps &alprops) + : props_{eaxprops}, al_effect_props_{alprops} + { } + + EaxEffectProps &props_; + EffectProps &al_effect_props_; + + [[noreturn]] static void fail(const char* message); + [[noreturn]] static void fail_unknown_property_id() + { fail(EaxEffectErrorMessages::unknown_property_id()); } + + 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; + } + + 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); + } + + template<typename TValidator, typename TProperty> + static void defer3(const EaxCall& call, EAXREVERBPROPERTIES& 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; + } + + + bool commit(const EAX_REVERBPROPERTIES &props); + bool commit(const EAX20LISTENERPROPERTIES &props); + bool commit(const EAXREVERBPROPERTIES &props); + bool commit(const EaxEffectProps &props); + + static void SetDefaults(EAX_REVERBPROPERTIES &props); + static void SetDefaults(EAX20LISTENERPROPERTIES &props); + static void SetDefaults(EAXREVERBPROPERTIES &props); + static void SetDefaults(EaxEffectProps &props); + + static void Get(const EaxCall &call, const EAX_REVERBPROPERTIES &props); + static void Get(const EaxCall &call, const EAX20LISTENERPROPERTIES &props); + static void Get(const EaxCall &call, const EAXREVERBPROPERTIES &props); + static void Get(const EaxCall &call, const EaxEffectProps &props); + + static void Set(const EaxCall &call, EAX_REVERBPROPERTIES &props); + static void Set(const EaxCall &call, EAX20LISTENERPROPERTIES &props); + static void Set(const EaxCall &call, EAXREVERBPROPERTIES &props); + static void Set(const EaxCall &call, EaxEffectProps &props); + + static void translate(const EAX_REVERBPROPERTIES& src, EaxEffectProps& dst) noexcept; + static void translate(const EAX20LISTENERPROPERTIES& src, EaxEffectProps& dst) noexcept; + static void translate(const EAXREVERBPROPERTIES& src, EaxEffectProps& dst) noexcept; +}; + +template<typename T> +struct EaxCommitter { + struct Exception; + + EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops) + : props_{eaxprops}, al_effect_props_{alprops} + { } + + EaxEffectProps &props_; + EffectProps &al_effect_props_; + + 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; + } + + 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); + } + + [[noreturn]] static void fail(const char *message); + [[noreturn]] static void fail_unknown_property_id() + { fail(EaxEffectErrorMessages::unknown_property_id()); } + + bool commit(const EaxEffectProps &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EaxEffectProps &props); + static void Set(const EaxCall &call, EaxEffectProps &props); +}; + +struct EaxNullCommitter : public EaxCommitter<EaxNullCommitter> { + using EaxCommitter<EaxNullCommitter>::EaxCommitter; +}; + + class EaxEffect { public: - EaxEffect(ALenum type, int eax_version) noexcept - : al_effect_type_{type}, version_{eax_version} - { } + EaxEffect() noexcept = default; virtual ~EaxEffect() = default; - const ALenum al_effect_type_; + ALenum al_effect_type_{AL_EFFECT_NULL}; EffectProps al_effect_props_{}; using Props1 = EAX_REVERBPROPERTIES; @@ -74,7 +203,7 @@ public: Props4 d; // Deferred. }; - int version_; + int version_{}; bool changed_{}; Props4 props_{}; State1 state1_{}; @@ -83,10 +212,146 @@ public: State4 state4_{}; State4 state5_{}; - virtual void dispatch(const EaxCall& call) = 0; + [[deprecated]] virtual void dispatch(const EaxCall& /*call*/) { } // Returns "true" if any immediated property was changed. - /*[[nodiscard]]*/ virtual bool commit() = 0; + /*[[nodiscard]]*/ [[deprecated]] virtual bool commit() { return false; } + + template<typename T, typename ...Args> + void call_set_defaults(Args&& ...args) + { return T::SetDefaults(std::forward<Args>(args)...); } + + void call_set_defaults(const ALenum altype, EaxEffectProps &props) + { + if(altype == AL_EFFECT_EAXREVERB) + return call_set_defaults<EaxReverbCommitter>(props); + return call_set_defaults<EaxNullCommitter>(props); + } + + template<typename T> + void init() + { + call_set_defaults<EaxReverbCommitter>(state1_.d); + state1_.i = state1_.d; + call_set_defaults<EaxReverbCommitter>(state2_.d); + state2_.i = state2_.d; + call_set_defaults<EaxReverbCommitter>(state3_.d); + state3_.i = state3_.d; + call_set_defaults<T>(state4_.d); + state4_.i = state4_.d; + call_set_defaults<T>(state5_.d); + state5_.i = state5_.d; + } + + void set_defaults(int eax_version, ALenum altype) + { + switch(eax_version) + { + case 1: call_set_defaults<EaxReverbCommitter>(state1_.d); break; + case 2: call_set_defaults<EaxReverbCommitter>(state2_.d); break; + case 3: call_set_defaults<EaxReverbCommitter>(state3_.d); break; + case 4: call_set_defaults(altype, state4_.d); break; + case 5: call_set_defaults(altype, state5_.d); break; + } + changed_ = true; + } + + + template<typename T, typename ...Args> + void do_set(Args&& ...args) + { return T::Set(std::forward<Args>(args)...); } + + void do_set(const EaxCall &call, EaxEffectProps &props) + { + if(props.mType == EaxEffectType::Reverb) + return do_set<EaxReverbCommitter>(call, props); + return do_set<EaxNullCommitter>(call, props); + } + + void set(const EaxCall &call) + { + switch(call.get_version()) + { + case 1: do_set<EaxReverbCommitter>(call, state1_.d); break; + case 2: do_set<EaxReverbCommitter>(call, state2_.d); break; + case 3: do_set<EaxReverbCommitter>(call, state3_.d); break; + case 4: do_set(call, state4_.d); break; + case 5: do_set(call, state5_.d); break; + } + changed_ = true; + } + + + template<typename T, typename ...Args> + void do_get(Args&& ...args) + { return T::Get(std::forward<Args>(args)...); } + + void do_get(const EaxCall &call, const EaxEffectProps &props) + { + if(props.mType == EaxEffectType::Reverb) + return do_get<EaxReverbCommitter>(call, props); + return do_get<EaxNullCommitter>(call, props); + } + + void get(const EaxCall &call) + { + switch(call.get_version()) + { + case 1: do_get<EaxReverbCommitter>(call, state1_.d); break; + case 2: do_get<EaxReverbCommitter>(call, state2_.d); break; + case 3: do_get<EaxReverbCommitter>(call, state3_.d); break; + case 4: do_get(call, state4_.d); break; + case 5: do_get(call, state5_.d); break; + } + } + + + template<typename T, typename ...Args> + bool call_commit(Args&& ...args) + { return T{props_, al_effect_props_}.commit(std::forward<Args>(args)...); } + + bool call_commit(const EaxEffectProps &props) + { + if(props.mType == EaxEffectType::Reverb) + return call_commit<EaxReverbCommitter>(props); + return call_commit<EaxNullCommitter>(props); + } + + bool do_commit(int eax_version) + { + changed_ |= version_ != eax_version; + if(!changed_) return false; + + bool ret{version_ != eax_version}; + version_ = eax_version; + changed_ = false; + + switch(eax_version) + { + case 1: + state1_.i = state1_.d; + ret |= call_commit<EaxReverbCommitter>(state1_.d); + break; + case 2: + state2_.i = state2_.d; + ret |= call_commit<EaxReverbCommitter>(state2_.d); + break; + case 3: + state3_.i = state3_.d; + ret |= call_commit<EaxReverbCommitter>(state3_.d); + break; + case 4: + state4_.i = state4_.d; + ret |= call_commit(state4_.d); + break; + case 5: + state5_.i = state5_.d; + ret |= call_commit(state5_.d); + break; + } + al_effect_type_ = EnumFromEaxEffectType(props_); + return ret; + } }; // EaxEffect // Base class for EAX4+ effects. @@ -94,9 +359,7 @@ template<typename TException> class EaxEffect4 : public EaxEffect { public: - EaxEffect4(ALenum type, int eax_version) - : EaxEffect{type, clamp(eax_version, 4, 5)} - { } + EaxEffect4(ALenum, int) { } void initialize() { @@ -203,18 +466,4 @@ EaxEffectUPtr eax_create_eax4_effect(int eax_version) return effect; } -EaxEffectUPtr eax_create_eax_null_effect(int eax_version); -EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version); -EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version); -EaxEffectUPtr eax_create_eax_echo_effect(int eax_version); -EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version); -EaxEffectUPtr eax_create_eax_frequency_shifter_effect(int eax_version); -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(int eax_version); -EaxEffectUPtr eax_create_eax_pitch_shifter_effect(int eax_version); -EaxEffectUPtr eax_create_eax_ring_modulator_effect(int eax_version); -EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version); -EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version); -EaxEffectUPtr eax_create_eax_equalizer_effect(int eax_version); -EaxEffectUPtr eax_create_eax_reverb_effect(int eax_version); - #endif // !EAX_EFFECT_INCLUDED diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp index 820f1517..4a67b5ff 100644 --- a/al/effects/effects.cpp +++ b/al/effects/effects.cpp @@ -6,57 +6,4 @@ #include "AL/efx.h" #include "effects.h" -EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, int eax_version) -{ -#define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] " - - switch (al_effect_type) - { - case AL_EFFECT_NULL: - return eax_create_eax_null_effect(eax_version); - - case AL_EFFECT_CHORUS: - return eax_create_eax_chorus_effect(eax_version); - - case AL_EFFECT_DISTORTION: - return eax_create_eax_distortion_effect(eax_version); - - case AL_EFFECT_ECHO: - return eax_create_eax_echo_effect(eax_version); - - case AL_EFFECT_FLANGER: - return eax_create_eax_flanger_effect(eax_version); - - case AL_EFFECT_FREQUENCY_SHIFTER: - return eax_create_eax_frequency_shifter_effect(eax_version); - - case AL_EFFECT_VOCAL_MORPHER: - return eax_create_eax_vocal_morpher_effect(eax_version); - - case AL_EFFECT_PITCH_SHIFTER: - return eax_create_eax_pitch_shifter_effect(eax_version); - - case AL_EFFECT_RING_MODULATOR: - return eax_create_eax_ring_modulator_effect(eax_version); - - case AL_EFFECT_AUTOWAH: - return eax_create_eax_auto_wah_effect(eax_version); - - case AL_EFFECT_COMPRESSOR: - return eax_create_eax_compressor_effect(eax_version); - - case AL_EFFECT_EQUALIZER: - return eax_create_eax_equalizer_effect(eax_version); - - case AL_EFFECT_EAXREVERB: - return eax_create_eax_reverb_effect(eax_version); - - default: - assert(false && "Unsupported AL effect type."); - return nullptr; - } - -#undef EAX_PREFIX -} - #endif // ALSOFT_EAX diff --git a/al/effects/effects.h b/al/effects/effects.h index 70960a7f..9d57dd82 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -85,9 +85,4 @@ extern const EffectVtable VmorpherEffectVtable; extern const EffectVtable DedicatedEffectVtable; extern const EffectVtable ConvolutionEffectVtable; - -#ifdef ALSOFT_EAX -EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, int eax_version); -#endif // ALSOFT_EAX - #endif /* AL_EFFECTS_EFFECTS_H */ diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 8b11f20c..e80ab9f8 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -100,64 +100,50 @@ const EffectProps NullEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxNullEffectException : public EaxException -{ -public: - explicit EaxNullEffectException(const char* message) - : EaxException{"EAX_NULL_EFFECT", message} - {} -}; // EaxNullEffectException - -class EaxNullEffect final : public EaxEffect4<EaxNullEffectException> -{ -public: - EaxNullEffect(int eax_version); - -private: - void set_defaults(Props4& props) override; - - void set_efx_defaults() override; +using NullCommitter = EaxCommitter<EaxNullCommitter>; - void get(const EaxCall& call, const Props4& props) override; - void set(const EaxCall& call, Props4& props) override; - bool commit_props(const Props4& props) override; -}; // EaxCompressorEffect +} // namespace -EaxNullEffect::EaxNullEffect(int eax_version) - : EaxEffect4{AL_EFFECT_NULL, eax_version} -{} +template<> +struct NullCommitter::Exception : public EaxException +{ + explicit Exception(const char *message) : EaxException{"EAX_NULL_EFFECT", message} + { } +}; -void EaxNullEffect::set_defaults(Props4& props) +template<> +[[noreturn]] void NullCommitter::fail(const char *message) { - props.mType = EaxEffectType::None; + throw Exception{message}; } -void EaxNullEffect::set_efx_defaults() +template<> +bool NullCommitter::commit(const EaxEffectProps &props) { + const bool ret{props.mType != props_.mType}; + props_ = props; + return ret; } -void EaxNullEffect::get(const EaxCall& call, const Props4&) +template<> +void NullCommitter::SetDefaults(EaxEffectProps &props) { - if(call.get_property_id() != 0) - fail_unknown_property_id(); + props = EaxEffectProps{}; + props.mType = EaxEffectType::None; } -void EaxNullEffect::set(const EaxCall& call, Props4&) +template<> +void NullCommitter::Get(const EaxCall &call, const EaxEffectProps&) { if(call.get_property_id() != 0) fail_unknown_property_id(); } -bool EaxNullEffect::commit_props(const Props4&) +template<> +void NullCommitter::Set(const EaxCall &call, EaxEffectProps&) { - return false; -} - -} // namespace - -EaxEffectUPtr eax_create_eax_null_effect(int eax_version) -{ - return std::make_unique<EaxNullEffect>(eax_version); + if(call.get_property_id() != 0) + fail_unknown_property_id(); } #endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index acd2fd06..b154e3ff 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -574,1402 +574,951 @@ public: {} }; // EaxReverbEffectException -class EaxReverbEffect final : public EaxEffect -{ -public: - EaxReverbEffect(int eax_version) noexcept; +struct EnvironmentValidator1 { + void operator()(unsigned long ulEnvironment) const + { + eax_validate_range<EaxReverbEffectException>( + "Environment", + ulEnvironment, + EAXREVERB_MINENVIRONMENT, + EAX1REVERB_MAXENVIRONMENT); + } +}; // EnvironmentValidator1 - void dispatch(const EaxCall& call) override; - /*[[nodiscard]]*/ bool commit() override; +struct VolumeValidator { + void operator()(float volume) const + { + eax_validate_range<EaxReverbEffectException>( + "Volume", + volume, + EAX1REVERB_MINVOLUME, + EAX1REVERB_MAXVOLUME); + } +}; // VolumeValidator -private: - static constexpr auto initial_room2 = -10'000L; +struct DecayTimeValidator { + void operator()(float flDecayTime) const + { + eax_validate_range<EaxReverbEffectException>( + "Decay Time", + flDecayTime, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); + } +}; // DecayTimeValidator - using Exception = EaxReverbEffectException; +struct DampingValidator { + void operator()(float damping) const + { + eax_validate_range<EaxReverbEffectException>( + "Damping", + damping, + EAX1REVERB_MINDAMPING, + EAX1REVERB_MAXDAMPING); + } +}; // DampingValidator - struct EnvironmentValidator1 { - void operator()(unsigned long ulEnvironment) const - { - eax_validate_range<Exception>( - "Environment", - ulEnvironment, - EAXREVERB_MINENVIRONMENT, - EAX1REVERB_MAXENVIRONMENT); - } - }; // EnvironmentValidator1 +struct AllValidator1 { + void operator()(const EAX_REVERBPROPERTIES& all) const + { + EnvironmentValidator1{}(all.environment); + VolumeValidator{}(all.fVolume); + DecayTimeValidator{}(all.fDecayTime_sec); + DampingValidator{}(all.fDamping); + } +}; // AllValidator1 - struct VolumeValidator { - void operator()(float volume) const - { - eax_validate_range<Exception>( - "Volume", - volume, - EAX1REVERB_MINVOLUME, - EAX1REVERB_MAXVOLUME); - } - }; // VolumeValidator +struct RoomValidator { + void operator()(long lRoom) const + { + eax_validate_range<EaxReverbEffectException>( + "Room", + lRoom, + EAXREVERB_MINROOM, + EAXREVERB_MAXROOM); + } +}; // RoomValidator - struct DecayTimeValidator { - void operator()(float flDecayTime) const - { - eax_validate_range<Exception>( - "Decay Time", - flDecayTime, - EAXREVERB_MINDECAYTIME, - EAXREVERB_MAXDECAYTIME); - } - }; // DecayTimeValidator +struct RoomHFValidator { + void operator()(long lRoomHF) const + { + eax_validate_range<EaxReverbEffectException>( + "Room HF", + lRoomHF, + EAXREVERB_MINROOMHF, + EAXREVERB_MAXROOMHF); + } +}; // RoomHFValidator - struct DampingValidator { - void operator()(float damping) const - { - eax_validate_range<Exception>( - "Damping", - damping, - EAX1REVERB_MINDAMPING, - EAX1REVERB_MAXDAMPING); - } - }; // DampingValidator +struct RoomRolloffFactorValidator { + void operator()(float flRoomRolloffFactor) const + { + eax_validate_range<EaxReverbEffectException>( + "Room Rolloff Factor", + flRoomRolloffFactor, + EAXREVERB_MINROOMROLLOFFFACTOR, + EAXREVERB_MAXROOMROLLOFFFACTOR); + } +}; // RoomRolloffFactorValidator - struct AllValidator1 { - void operator()(const EAX_REVERBPROPERTIES& all) const - { - EnvironmentValidator1{}(all.environment); - VolumeValidator{}(all.fVolume); - DecayTimeValidator{}(all.fDecayTime_sec); - DampingValidator{}(all.fDamping); - } - }; // AllValidator1 +struct DecayHFRatioValidator { + void operator()(float flDecayHFRatio) const + { + eax_validate_range<EaxReverbEffectException>( + "Decay HF Ratio", + flDecayHFRatio, + EAXREVERB_MINDECAYHFRATIO, + EAXREVERB_MAXDECAYHFRATIO); + } +}; // DecayHFRatioValidator - struct RoomValidator { - void operator()(long lRoom) const - { - eax_validate_range<Exception>( - "Room", - lRoom, - EAXREVERB_MINROOM, - EAXREVERB_MAXROOM); - } - }; // RoomValidator +struct ReflectionsValidator { + void operator()(long lReflections) const + { + eax_validate_range<EaxReverbEffectException>( + "Reflections", + lReflections, + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); + } +}; // ReflectionsValidator - struct RoomHFValidator { - void operator()(long lRoomHF) const - { - eax_validate_range<Exception>( - "Room HF", - lRoomHF, - EAXREVERB_MINROOMHF, - EAXREVERB_MAXROOMHF); - } - }; // RoomHFValidator +struct ReflectionsDelayValidator { + void operator()(float flReflectionsDelay) const + { + eax_validate_range<EaxReverbEffectException>( + "Reflections Delay", + flReflectionsDelay, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); + } +}; // ReflectionsDelayValidator + +struct ReverbValidator { + void operator()(long lReverb) const + { + eax_validate_range<EaxReverbEffectException>( + "Reverb", + lReverb, + EAXREVERB_MINREVERB, + EAXREVERB_MAXREVERB); + } +}; // ReverbValidator + +struct ReverbDelayValidator { + void operator()(float flReverbDelay) const + { + eax_validate_range<EaxReverbEffectException>( + "Reverb Delay", + flReverbDelay, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); + } +}; // ReverbDelayValidator + +struct EnvironmentSizeValidator { + void operator()(float flEnvironmentSize) const + { + eax_validate_range<EaxReverbEffectException>( + "Environment Size", + flEnvironmentSize, + EAXREVERB_MINENVIRONMENTSIZE, + EAXREVERB_MAXENVIRONMENTSIZE); + } +}; // EnvironmentSizeValidator + +struct EnvironmentDiffusionValidator { + void operator()(float flEnvironmentDiffusion) const + { + eax_validate_range<EaxReverbEffectException>( + "Environment Diffusion", + flEnvironmentDiffusion, + EAXREVERB_MINENVIRONMENTDIFFUSION, + EAXREVERB_MAXENVIRONMENTDIFFUSION); + } +}; // EnvironmentDiffusionValidator + +struct AirAbsorptionHFValidator { + void operator()(float flAirAbsorptionHF) const + { + eax_validate_range<EaxReverbEffectException>( + "Air Absorbtion HF", + flAirAbsorptionHF, + EAXREVERB_MINAIRABSORPTIONHF, + EAXREVERB_MAXAIRABSORPTIONHF); + } +}; // AirAbsorptionHFValidator + +struct FlagsValidator2 { + void operator()(unsigned long ulFlags) const + { + eax_validate_range<EaxReverbEffectException>( + "Flags", + ulFlags, + 0UL, + ~EAX2LISTENERFLAGS_RESERVED); + } +}; // FlagsValidator2 + +struct AllValidator2 { + void operator()(const EAX20LISTENERPROPERTIES& 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<EaxReverbEffectException>( + "Environment", + ulEnvironment, + EAXREVERB_MINENVIRONMENT, + EAX30REVERB_MAXENVIRONMENT); + } +}; // EnvironmentValidator1 + +struct RoomLFValidator { + void operator()(long lRoomLF) const + { + eax_validate_range<EaxReverbEffectException>( + "Room LF", + lRoomLF, + EAXREVERB_MINROOMLF, + EAXREVERB_MAXROOMLF); + } +}; // RoomLFValidator + +struct DecayLFRatioValidator { + void operator()(float flDecayLFRatio) const + { + eax_validate_range<EaxReverbEffectException>( + "Decay LF Ratio", + flDecayLFRatio, + EAXREVERB_MINDECAYLFRATIO, + EAXREVERB_MAXDECAYLFRATIO); + } +}; // DecayLFRatioValidator + +struct VectorValidator { + void operator()(const EAXVECTOR&) const + {} +}; // VectorValidator - struct RoomRolloffFactorValidator { - void operator()(float flRoomRolloffFactor) const +struct EchoTimeValidator { + void operator()(float flEchoTime) const + { + eax_validate_range<EaxReverbEffectException>( + "Echo Time", + flEchoTime, + EAXREVERB_MINECHOTIME, + EAXREVERB_MAXECHOTIME); + } +}; // EchoTimeValidator + +struct EchoDepthValidator { + void operator()(float flEchoDepth) const + { + eax_validate_range<EaxReverbEffectException>( + "Echo Depth", + flEchoDepth, + EAXREVERB_MINECHODEPTH, + EAXREVERB_MAXECHODEPTH); + } +}; // EchoDepthValidator + +struct ModulationTimeValidator { + void operator()(float flModulationTime) const + { + eax_validate_range<EaxReverbEffectException>( + "Modulation Time", + flModulationTime, + EAXREVERB_MINMODULATIONTIME, + EAXREVERB_MAXMODULATIONTIME); + } +}; // ModulationTimeValidator + +struct ModulationDepthValidator { + void operator()(float flModulationDepth) const + { + eax_validate_range<EaxReverbEffectException>( + "Modulation Depth", + flModulationDepth, + EAXREVERB_MINMODULATIONDEPTH, + EAXREVERB_MAXMODULATIONDEPTH); + } +}; // ModulationDepthValidator + +struct HFReferenceValidator { + void operator()(float flHFReference) const + { + eax_validate_range<EaxReverbEffectException>( + "HF Reference", + flHFReference, + EAXREVERB_MINHFREFERENCE, + EAXREVERB_MAXHFREFERENCE); + } +}; // HFReferenceValidator + +struct LFReferenceValidator { + void operator()(float flLFReference) const + { + eax_validate_range<EaxReverbEffectException>( + "LF Reference", + flLFReference, + EAXREVERB_MINLFREFERENCE, + EAXREVERB_MAXLFREFERENCE); + } +}; // LFReferenceValidator + +struct FlagsValidator3 { + void operator()(unsigned long ulFlags) const + { + eax_validate_range<EaxReverbEffectException>( + "Flags", + ulFlags, + 0UL, + ~EAXREVERBFLAGS_RESERVED); + } +}; // FlagsValidator3 + +struct AllValidator3 { + void operator()(const EAXREVERBPROPERTIES& 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()(EAX20LISTENERPROPERTIES& props, unsigned long dwEnvironment) const + { + props = EAX2REVERB_PRESETS[dwEnvironment]; + } +}; // EnvironmentDeferrer2 + +struct EnvironmentSizeDeferrer2 { + void operator()(EAX20LISTENERPROPERTIES& props, float flEnvironmentSize) const + { + if (props.flEnvironmentSize == flEnvironmentSize) { - eax_validate_range<Exception>( - "Room Rolloff Factor", - flRoomRolloffFactor, - EAXREVERB_MINROOMROLLOFFFACTOR, - EAXREVERB_MAXROOMROLLOFFFACTOR); + return; } - }; // RoomRolloffFactorValidator - struct DecayHFRatioValidator { - void operator()(float flDecayHFRatio) const + const auto scale = flEnvironmentSize / props.flEnvironmentSize; + props.flEnvironmentSize = flEnvironmentSize; + + if ((props.dwFlags & EAX2LISTENERFLAGS_DECAYTIMESCALE) != 0) { - eax_validate_range<Exception>( - "Decay HF Ratio", - flDecayHFRatio, - EAXREVERB_MINDECAYHFRATIO, - EAXREVERB_MAXDECAYHFRATIO); + props.flDecayTime = clamp( + props.flDecayTime * scale, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); } - }; // DecayHFRatioValidator - struct ReflectionsValidator { - void operator()(long lReflections) const + if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSSCALE) != 0 && + (props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0) { - eax_validate_range<Exception>( - "Reflections", - lReflections, + props.lReflections = clamp( + props.lReflections - static_cast<long>(gain_to_level_mb(scale)), EAXREVERB_MINREFLECTIONS, EAXREVERB_MAXREFLECTIONS); } - }; // ReflectionsValidator - struct ReflectionsDelayValidator { - void operator()(float flReflectionsDelay) const + if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0) { - eax_validate_range<Exception>( - "Reflections Delay", - flReflectionsDelay, + props.flReflectionsDelay = clamp( + props.flReflectionsDelay * scale, EAXREVERB_MINREFLECTIONSDELAY, EAXREVERB_MAXREFLECTIONSDELAY); } - }; // ReflectionsDelayValidator - struct ReverbValidator { - void operator()(long lReverb) const + if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBSCALE) != 0) { - eax_validate_range<Exception>( - "Reverb", - lReverb, + 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); } - }; // ReverbValidator - struct ReverbDelayValidator { - void operator()(float flReverbDelay) const + if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBDELAYSCALE) != 0) { - eax_validate_range<Exception>( - "Reverb Delay", - flReverbDelay, + props.flReverbDelay = clamp( + props.flReverbDelay * scale, EAXREVERB_MINREVERBDELAY, EAXREVERB_MAXREVERBDELAY); } - }; // ReverbDelayValidator + } +}; // EnvironmentSizeDeferrer2 - struct EnvironmentSizeValidator { - void operator()(float flEnvironmentSize) const +struct EnvironmentDeferrer3 { + void operator()(EAXREVERBPROPERTIES& props, unsigned long ulEnvironment) const + { + if (ulEnvironment == EAX_ENVIRONMENT_UNDEFINED) { - eax_validate_range<Exception>( - "Environment Size", - flEnvironmentSize, - EAXREVERB_MINENVIRONMENTSIZE, - EAXREVERB_MAXENVIRONMENTSIZE); + props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED; + return; } - }; // EnvironmentSizeValidator - struct EnvironmentDiffusionValidator { - void operator()(float flEnvironmentDiffusion) const - { - eax_validate_range<Exception>( - "Environment Diffusion", - flEnvironmentDiffusion, - EAXREVERB_MINENVIRONMENTDIFFUSION, - EAXREVERB_MAXENVIRONMENTDIFFUSION); - } - }; // EnvironmentDiffusionValidator + props = EAXREVERB_PRESETS[ulEnvironment]; + } +}; // EnvironmentDeferrer3 - struct AirAbsorptionHFValidator { - void operator()(float flAirAbsorptionHF) const +struct EnvironmentSizeDeferrer3 { + void operator()(EAXREVERBPROPERTIES& props, float flEnvironmentSize) const + { + if (props.flEnvironmentSize == flEnvironmentSize) { - eax_validate_range<Exception>( - "Air Absorbtion HF", - flAirAbsorptionHF, - EAXREVERB_MINAIRABSORPTIONHF, - EAXREVERB_MAXAIRABSORPTIONHF); + return; } - }; // AirAbsorptionHFValidator - struct FlagsValidator2 { - void operator()(unsigned long ulFlags) const + const auto scale = flEnvironmentSize / props.flEnvironmentSize; + props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED; + props.flEnvironmentSize = flEnvironmentSize; + + if ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) { - eax_validate_range<Exception>( - "Flags", - ulFlags, - 0UL, - ~EAX2LISTENERFLAGS_RESERVED); + props.flDecayTime = clamp( + props.flDecayTime * scale, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); } - }; // FlagsValidator2 - struct AllValidator2 { - void operator()(const EAX20LISTENERPROPERTIES& all) const + if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0 && + (props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) { - 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); + props.lReflections = clamp( + props.lReflections - static_cast<long>(gain_to_level_mb(scale)), + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); } - }; // AllValidator2 - struct EnvironmentValidator3 { - void operator()(unsigned long ulEnvironment) const + if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) { - eax_validate_range<Exception>( - "Environment", - ulEnvironment, - EAXREVERB_MINENVIRONMENT, - EAX30REVERB_MAXENVIRONMENT); + props.flReflectionsDelay = clamp( + props.flReflectionsDelay * scale, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); } - }; // EnvironmentValidator1 - struct RoomLFValidator { - void operator()(long lRoomLF) const + if ((props.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0) { - eax_validate_range<Exception>( - "Room LF", - lRoomLF, - EAXREVERB_MINROOMLF, - EAXREVERB_MAXROOMLF); + 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); } - }; // RoomLFValidator - struct DecayLFRatioValidator { - void operator()(float flDecayLFRatio) const + if ((props.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0) { - eax_validate_range<Exception>( - "Decay LF Ratio", - flDecayLFRatio, - EAXREVERB_MINDECAYLFRATIO, - EAXREVERB_MAXDECAYLFRATIO); + props.flReverbDelay = clamp( + props.flReverbDelay * scale, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); } - }; // DecayLFRatioValidator - - struct VectorValidator { - void operator()(const EAXVECTOR&) const - {} - }; // VectorValidator - struct EchoTimeValidator { - void operator()(float flEchoTime) const + if ((props.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0) { - eax_validate_range<Exception>( - "Echo Time", - flEchoTime, + props.flEchoTime = clamp( + props.flEchoTime * scale, 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 + if ((props.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0) { - eax_validate_range<Exception>( - "Modulation Time", - flModulationTime, + props.flModulationTime = clamp( + props.flModulationTime * scale, 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 EAXREVERBPROPERTIES& 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()(EAX20LISTENERPROPERTIES& props, unsigned long dwEnvironment) const - { - props = EAX2REVERB_PRESETS[dwEnvironment]; - } - }; // EnvironmentDeferrer2 - - struct EnvironmentSizeDeferrer2 { - void operator()(EAX20LISTENERPROPERTIES& 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()(EAXREVERBPROPERTIES& 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()(EAXREVERBPROPERTIES& 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 - - - [[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; - } - - 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); - } - - 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; } +}; // EnvironmentSizeDeferrer3 - 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); +} // namespace - static void translate(const Props1& src, Props4& dst) noexcept; - static void translate(const Props2& src, Props4& dst) noexcept; - static void translate(const Props3& src, Props4& dst) noexcept; -}; // EaxReverbEffect -EaxReverbEffect::EaxReverbEffect(int eax_version) noexcept - : EaxEffect{AL_EFFECT_EAXREVERB, eax_version} +struct EaxReverbCommitter::Exception : public EaxReverbEffectException { - set_defaults(); - set_current_defaults(); - set_efx_defaults(); -} + using EaxReverbEffectException::EaxReverbEffectException; +}; -void EaxReverbEffect::dispatch(const EaxCall& call) -{ - call.is_get() ? get(call) : set(call); -} - -[[noreturn]] void EaxReverbEffect::fail(const char* message) +[[noreturn]] void EaxReverbCommitter::fail(const char* message) { throw Exception{message}; } -[[noreturn]] void EaxReverbEffect::fail_unknown_property_id() +void EaxReverbCommitter::translate(const EAX_REVERBPROPERTIES& src, EaxEffectProps& dst) noexcept { - fail(EaxEffectErrorMessages::unknown_property_id()); + assert(src.environment <= EAX1REVERB_MAXENVIRONMENT); + dst.mType = EaxEffectType::Reverb; + dst.mReverb = EAXREVERB_PRESETS[src.environment]; + dst.mReverb.flDecayTime = src.fDecayTime_sec; + dst.mReverb.flDecayHFRatio = src.fDamping; + dst.mReverb.lReverb = mini(static_cast<int>(gain_to_level_mb(src.fVolume)), 0); } -[[noreturn]] void EaxReverbEffect::fail_unknown_version() +void EaxReverbCommitter::translate(const EAX20LISTENERPROPERTIES& src, EaxEffectProps& dst) noexcept { - fail(EaxEffectErrorMessages::unknown_version()); + assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT); + const auto& env = EAXREVERB_PRESETS[src.dwEnvironment]; + dst.mType = EaxEffectType::Reverb; + dst.mReverb.ulEnvironment = src.dwEnvironment; + dst.mReverb.flEnvironmentSize = src.flEnvironmentSize; + dst.mReverb.flEnvironmentDiffusion = src.flEnvironmentDiffusion; + dst.mReverb.lRoom = src.lRoom; + dst.mReverb.lRoomHF = src.lRoomHF; + dst.mReverb.lRoomLF = env.lRoomLF; + dst.mReverb.flDecayTime = src.flDecayTime; + dst.mReverb.flDecayHFRatio = src.flDecayHFRatio; + dst.mReverb.flDecayLFRatio = env.flDecayLFRatio; + dst.mReverb.lReflections = src.lReflections; + dst.mReverb.flReflectionsDelay = src.flReflectionsDelay; + dst.mReverb.vReflectionsPan = env.vReflectionsPan; + dst.mReverb.lReverb = src.lReverb; + dst.mReverb.flReverbDelay = src.flReverbDelay; + dst.mReverb.vReverbPan = env.vReverbPan; + dst.mReverb.flEchoTime = env.flEchoTime; + dst.mReverb.flEchoDepth = env.flEchoDepth; + dst.mReverb.flModulationTime = env.flModulationTime; + dst.mReverb.flModulationDepth = env.flModulationDepth; + dst.mReverb.flAirAbsorptionHF = src.flAirAbsorptionHF; + dst.mReverb.flHFReference = env.flHFReference; + dst.mReverb.flLFReference = env.flLFReference; + dst.mReverb.flRoomRolloffFactor = src.flRoomRolloffFactor; + dst.mReverb.ulFlags = src.dwFlags; } -void EaxReverbEffect::set_defaults(State1& state) noexcept +void EaxReverbCommitter::translate(const EAXREVERBPROPERTIES& src, EaxEffectProps& dst) noexcept { - state.i = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; - state.d = state.i; + dst.mType = EaxEffectType::Reverb; + dst.mReverb = src; } -void EaxReverbEffect::set_defaults(State2& state) noexcept +bool EaxReverbCommitter::commit(const EAX_REVERBPROPERTIES &props) { - state.i = EAX2REVERB_PRESETS[EAX2_ENVIRONMENT_GENERIC]; - state.i.lRoom = initial_room2; - state.d = state.i; + EaxEffectProps dst{}; + translate(props, dst); + return commit(dst); } -void EaxReverbEffect::set_defaults(State3& state) noexcept +bool EaxReverbCommitter::commit(const EAX20LISTENERPROPERTIES &props) { - state.i = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; - state.d = state.i; + EaxEffectProps dst{}; + translate(props, dst); + return commit(dst); } -void EaxReverbEffect::set_defaults() noexcept +bool EaxReverbCommitter::commit(const EAXREVERBPROPERTIES &props) { - set_defaults(state1_); - set_defaults(state2_); - set_defaults(state3_); - translate(state3_.i, state4_.i); - state4_.d = state4_.i; - translate(state3_.i, state5_.i); - state5_.d = state5_.i; + EaxEffectProps dst{}; + translate(props, dst); + return commit(dst); } -void EaxReverbEffect::set_current_defaults() +bool EaxReverbCommitter::commit(const EaxEffectProps &props) { - switch (version_) - { - case 1: translate(state1_.i, props_); break; - case 2: translate(state2_.i, props_); break; - case 3: translate(state3_.i, props_); break; - case 4: props_ = state4_.i; break; - case 5: props_ = state5_.i; break; - default: fail_unknown_version(); - } -} + const auto orig = props_; + props_ = props; + if(orig.mType == props_.mType && memcmp(&orig.mReverb, &props_.mReverb, sizeof(props_.mReverb)) == 0) + return false; -void EaxReverbEffect::set_efx_density_from_environment_size() noexcept -{ const auto size = props_.mReverb.flEnvironmentSize; const auto density = (size * size * size) / 16.0F; - al_effect_props_.Reverb.Density = clamp( - density, - AL_EAXREVERB_MIN_DENSITY, - AL_EAXREVERB_MAX_DENSITY); -} - -void EaxReverbEffect::set_efx_diffusion() noexcept -{ - al_effect_props_.Reverb.Diffusion = clamp( - props_.mReverb.flEnvironmentDiffusion, - AL_EAXREVERB_MIN_DIFFUSION, - AL_EAXREVERB_MAX_DIFFUSION); -} - -void EaxReverbEffect::set_efx_gain() noexcept -{ + al_effect_props_.Reverb.Density = clamp(density, + AL_EAXREVERB_MIN_DENSITY, AL_EAXREVERB_MAX_DENSITY); + al_effect_props_.Reverb.Diffusion = clamp(props_.mReverb.flEnvironmentDiffusion, + AL_EAXREVERB_MIN_DIFFUSION, AL_EAXREVERB_MAX_DIFFUSION); al_effect_props_.Reverb.Gain = clamp( level_mb_to_gain(static_cast<float>(props_.mReverb.lRoom)), - AL_EAXREVERB_MIN_GAIN, - AL_EAXREVERB_MAX_GAIN); -} - -void EaxReverbEffect::set_efx_gain_hf() noexcept -{ + AL_EAXREVERB_MIN_GAIN, AL_EAXREVERB_MAX_GAIN); al_effect_props_.Reverb.GainHF = clamp( level_mb_to_gain(static_cast<float>(props_.mReverb.lRoomHF)), - AL_EAXREVERB_MIN_GAINHF, - AL_EAXREVERB_MAX_GAINHF); -} - -void EaxReverbEffect::set_efx_gain_lf() noexcept -{ + AL_EAXREVERB_MIN_GAINHF, AL_EAXREVERB_MAX_GAINHF); al_effect_props_.Reverb.GainLF = clamp( level_mb_to_gain(static_cast<float>(props_.mReverb.lRoomLF)), - AL_EAXREVERB_MIN_GAINLF, - AL_EAXREVERB_MAX_GAINLF); -} - -void EaxReverbEffect::set_efx_decay_time() noexcept -{ - al_effect_props_.Reverb.DecayTime = clamp( - props_.mReverb.flDecayTime, - AL_EAXREVERB_MIN_DECAY_TIME, - AL_EAXREVERB_MAX_DECAY_TIME); -} - -void EaxReverbEffect::set_efx_decay_hf_ratio() noexcept -{ - al_effect_props_.Reverb.DecayHFRatio = clamp( - props_.mReverb.flDecayHFRatio, - AL_EAXREVERB_MIN_DECAY_HFRATIO, - AL_EAXREVERB_MAX_DECAY_HFRATIO); -} - -void EaxReverbEffect::set_efx_decay_lf_ratio() noexcept -{ - al_effect_props_.Reverb.DecayLFRatio = clamp( - props_.mReverb.flDecayLFRatio, - AL_EAXREVERB_MIN_DECAY_LFRATIO, - AL_EAXREVERB_MAX_DECAY_LFRATIO); -} - -void EaxReverbEffect::set_efx_reflections_gain() noexcept -{ + AL_EAXREVERB_MIN_GAINLF, AL_EAXREVERB_MAX_GAINLF); + al_effect_props_.Reverb.DecayTime = clamp(props_.mReverb.flDecayTime, + AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME); + al_effect_props_.Reverb.DecayHFRatio = clamp(props_.mReverb.flDecayHFRatio, + AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO); + al_effect_props_.Reverb.DecayLFRatio = clamp(props_.mReverb.flDecayLFRatio, + AL_EAXREVERB_MIN_DECAY_LFRATIO, AL_EAXREVERB_MAX_DECAY_LFRATIO); al_effect_props_.Reverb.ReflectionsGain = clamp( level_mb_to_gain(static_cast<float>(props_.mReverb.lReflections)), - AL_EAXREVERB_MIN_REFLECTIONS_GAIN, - AL_EAXREVERB_MAX_REFLECTIONS_GAIN); -} - -void EaxReverbEffect::set_efx_reflections_delay() noexcept -{ - al_effect_props_.Reverb.ReflectionsDelay = clamp( - props_.mReverb.flReflectionsDelay, - AL_EAXREVERB_MIN_REFLECTIONS_DELAY, - AL_EAXREVERB_MAX_REFLECTIONS_DELAY); -} - -void EaxReverbEffect::set_efx_reflections_pan() noexcept -{ + AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN); + al_effect_props_.Reverb.ReflectionsDelay = clamp(props_.mReverb.flReflectionsDelay, + AL_EAXREVERB_MIN_REFLECTIONS_DELAY, AL_EAXREVERB_MAX_REFLECTIONS_DELAY); al_effect_props_.Reverb.ReflectionsPan[0] = props_.mReverb.vReflectionsPan.x; al_effect_props_.Reverb.ReflectionsPan[1] = props_.mReverb.vReflectionsPan.y; al_effect_props_.Reverb.ReflectionsPan[2] = props_.mReverb.vReflectionsPan.z; -} - -void EaxReverbEffect::set_efx_late_reverb_gain() noexcept -{ al_effect_props_.Reverb.LateReverbGain = clamp( level_mb_to_gain(static_cast<float>(props_.mReverb.lReverb)), - AL_EAXREVERB_MIN_LATE_REVERB_GAIN, - AL_EAXREVERB_MAX_LATE_REVERB_GAIN); -} - -void EaxReverbEffect::set_efx_late_reverb_delay() noexcept -{ - al_effect_props_.Reverb.LateReverbDelay = clamp( - props_.mReverb.flReverbDelay, - AL_EAXREVERB_MIN_LATE_REVERB_DELAY, - AL_EAXREVERB_MAX_LATE_REVERB_DELAY); -} - -void EaxReverbEffect::set_efx_late_reverb_pan() noexcept -{ + AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN); + al_effect_props_.Reverb.LateReverbDelay = clamp(props_.mReverb.flReverbDelay, + AL_EAXREVERB_MIN_LATE_REVERB_DELAY, AL_EAXREVERB_MAX_LATE_REVERB_DELAY); al_effect_props_.Reverb.LateReverbPan[0] = props_.mReverb.vReverbPan.x; al_effect_props_.Reverb.LateReverbPan[1] = props_.mReverb.vReverbPan.y; al_effect_props_.Reverb.LateReverbPan[2] = props_.mReverb.vReverbPan.z; -} - -void EaxReverbEffect::set_efx_echo_time() noexcept -{ - al_effect_props_.Reverb.EchoTime = clamp( - props_.mReverb.flEchoTime, - AL_EAXREVERB_MIN_ECHO_TIME, - AL_EAXREVERB_MAX_ECHO_TIME); -} - -void EaxReverbEffect::set_efx_echo_depth() noexcept -{ - al_effect_props_.Reverb.EchoDepth = clamp( - props_.mReverb.flEchoDepth, - AL_EAXREVERB_MIN_ECHO_DEPTH, - AL_EAXREVERB_MAX_ECHO_DEPTH); -} - -void EaxReverbEffect::set_efx_modulation_time() noexcept -{ - al_effect_props_.Reverb.ModulationTime = clamp( - props_.mReverb.flModulationTime, - AL_EAXREVERB_MIN_MODULATION_TIME, - AL_EAXREVERB_MAX_MODULATION_TIME); -} - -void EaxReverbEffect::set_efx_modulation_depth() noexcept -{ - al_effect_props_.Reverb.ModulationDepth = clamp( - props_.mReverb.flModulationDepth, - AL_EAXREVERB_MIN_MODULATION_DEPTH, - AL_EAXREVERB_MAX_MODULATION_DEPTH); -} - -void EaxReverbEffect::set_efx_air_absorption_gain_hf() noexcept -{ + al_effect_props_.Reverb.EchoTime = clamp(props_.mReverb.flEchoTime, + AL_EAXREVERB_MIN_ECHO_TIME, AL_EAXREVERB_MAX_ECHO_TIME); + al_effect_props_.Reverb.EchoDepth = clamp(props_.mReverb.flEchoDepth, + AL_EAXREVERB_MIN_ECHO_DEPTH, AL_EAXREVERB_MAX_ECHO_DEPTH); + al_effect_props_.Reverb.ModulationTime = clamp(props_.mReverb.flModulationTime, + AL_EAXREVERB_MIN_MODULATION_TIME, AL_EAXREVERB_MAX_MODULATION_TIME); + al_effect_props_.Reverb.ModulationDepth = clamp(props_.mReverb.flModulationDepth, + AL_EAXREVERB_MIN_MODULATION_DEPTH, AL_EAXREVERB_MAX_MODULATION_DEPTH); al_effect_props_.Reverb.AirAbsorptionGainHF = clamp( level_mb_to_gain(props_.mReverb.flAirAbsorptionHF), - AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, - AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF); + AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF); + al_effect_props_.Reverb.HFReference = clamp(props_.mReverb.flHFReference, + AL_EAXREVERB_MIN_HFREFERENCE, AL_EAXREVERB_MAX_HFREFERENCE); + al_effect_props_.Reverb.LFReference = clamp(props_.mReverb.flLFReference, + AL_EAXREVERB_MIN_LFREFERENCE, AL_EAXREVERB_MAX_LFREFERENCE); + al_effect_props_.Reverb.RoomRolloffFactor = clamp(props_.mReverb.flRoomRolloffFactor, + AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR, AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR); + al_effect_props_.Reverb.DecayHFLimit = ((props_.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + return true; } -void EaxReverbEffect::set_efx_hf_reference() noexcept +void EaxReverbCommitter::SetDefaults(EAX_REVERBPROPERTIES &props) { - al_effect_props_.Reverb.HFReference = clamp( - props_.mReverb.flHFReference, - AL_EAXREVERB_MIN_HFREFERENCE, - AL_EAXREVERB_MAX_HFREFERENCE); + props = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; } -void EaxReverbEffect::set_efx_lf_reference() noexcept +void EaxReverbCommitter::SetDefaults(EAX20LISTENERPROPERTIES &props) { - al_effect_props_.Reverb.LFReference = clamp( - props_.mReverb.flLFReference, - AL_EAXREVERB_MIN_LFREFERENCE, - AL_EAXREVERB_MAX_LFREFERENCE); + props = EAX2REVERB_PRESETS[EAX2_ENVIRONMENT_GENERIC]; + props.lRoom = -10'000L; } -void EaxReverbEffect::set_efx_room_rolloff_factor() noexcept +void EaxReverbCommitter::SetDefaults(EAXREVERBPROPERTIES &props) { - al_effect_props_.Reverb.RoomRolloffFactor = clamp( - props_.mReverb.flRoomRolloffFactor, - AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR, - AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR); + props = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; } -void EaxReverbEffect::set_efx_flags() noexcept +void EaxReverbCommitter::SetDefaults(EaxEffectProps &props) { - al_effect_props_.Reverb.DecayHFLimit = ((props_.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + props.mType = EaxEffectType::Reverb; + SetDefaults(props.mReverb); } -void EaxReverbEffect::set_efx_defaults() noexcept -{ - set_efx_density_from_environment_size(); - set_efx_diffusion(); - set_efx_gain(); - set_efx_gain_hf(); - set_efx_gain_lf(); - set_efx_decay_time(); - set_efx_decay_hf_ratio(); - set_efx_decay_lf_ratio(); - set_efx_reflections_gain(); - set_efx_reflections_delay(); - set_efx_reflections_pan(); - set_efx_late_reverb_gain(); - set_efx_late_reverb_delay(); - set_efx_late_reverb_pan(); - set_efx_echo_time(); - set_efx_echo_depth(); - set_efx_modulation_time(); - set_efx_modulation_depth(); - set_efx_air_absorption_gain_hf(); - set_efx_hf_reference(); - set_efx_lf_reference(); - set_efx_room_rolloff_factor(); - set_efx_flags(); -} -void EaxReverbEffect::get1(const EaxCall& call, const Props1& props) +void EaxReverbCommitter::Get(const EaxCall &call, const EAX_REVERBPROPERTIES &props) { switch(call.get_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(); + 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::get2(const EaxCall& call, const Props2& props) +void EaxReverbCommitter::Get(const EaxCall &call, const EAX20LISTENERPROPERTIES &props) { switch(call.get_property_id()) { - 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.flReflectionsDelay); 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(); + 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.flReflectionsDelay); 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::get3(const EaxCall& call, const Props3& props) +void EaxReverbCommitter::Get(const EaxCall &call, const EAXREVERBPROPERTIES &props) { switch(call.get_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(); + 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::get(const EaxCall& call) +void EaxReverbCommitter::Get(const EaxCall &call, const EaxEffectProps &props) { - switch(call.get_version()) - { - 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.mReverb); break; - case 5: get3(call, state5_.i.mReverb); break; - default: fail_unknown_version(); - } + Get(call, props.mReverb); } -/*[[nodiscard]]*/ bool EaxReverbEffect::commit() -{ - if(!changed_) - return false; - changed_ = false; - - const auto props = props_; - switch(version_) - { - case 1: - state1_.i = state1_.d; - translate(state1_.d, props_); - break; - case 2: - state2_.i = state2_.d; - translate(state2_.d, props_); - break; - case 3: - state3_.i = state3_.d; - translate(state3_.d, props_); - break; - case 4: - state4_.i = state4_.d; - props_ = state4_.d; - break; - case 5: - state5_.i = state5_.d; - props_ = state5_.d; - break; - - default: - fail_unknown_version(); - } - - auto is_dirty = false; - - if (props_.mReverb.flEnvironmentSize != props.mReverb.flEnvironmentSize) - { - is_dirty = true; - set_efx_density_from_environment_size(); - } - - if (props_.mReverb.flEnvironmentDiffusion != props.mReverb.flEnvironmentDiffusion) - { - is_dirty = true; - set_efx_diffusion(); - } - - if (props_.mReverb.lRoom != props.mReverb.lRoom) - { - is_dirty = true; - set_efx_gain(); - } - - if (props_.mReverb.lRoomHF != props.mReverb.lRoomHF) - { - is_dirty = true; - set_efx_gain_hf(); - } - - if (props_.mReverb.lRoomLF != props.mReverb.lRoomLF) - { - is_dirty = true; - set_efx_gain_lf(); - } - - if (props_.mReverb.flDecayTime != props.mReverb.flDecayTime) - { - is_dirty = true; - set_efx_decay_time(); - } - - if (props_.mReverb.flDecayHFRatio != props.mReverb.flDecayHFRatio) - { - is_dirty = true; - set_efx_decay_hf_ratio(); - } - - if (props_.mReverb.flDecayLFRatio != props.mReverb.flDecayLFRatio) - { - is_dirty = true; - set_efx_decay_lf_ratio(); - } - - if (props_.mReverb.lReflections != props.mReverb.lReflections) - { - is_dirty = true; - set_efx_reflections_gain(); - } - - if (props_.mReverb.flReflectionsDelay != props.mReverb.flReflectionsDelay) - { - is_dirty = true; - set_efx_reflections_delay(); - } - - if (props_.mReverb.vReflectionsPan != props.mReverb.vReflectionsPan) - { - is_dirty = true; - set_efx_reflections_pan(); - } - - if (props_.mReverb.lReverb != props.mReverb.lReverb) - { - is_dirty = true; - set_efx_late_reverb_gain(); - } - - if (props_.mReverb.flReverbDelay != props.mReverb.flReverbDelay) - { - is_dirty = true; - set_efx_late_reverb_delay(); - } - - if (props_.mReverb.vReverbPan != props.mReverb.vReverbPan) - { - is_dirty = true; - set_efx_late_reverb_pan(); - } - - if (props_.mReverb.flEchoTime != props.mReverb.flEchoTime) - { - is_dirty = true; - set_efx_echo_time(); - } - - if (props_.mReverb.flEchoDepth != props.mReverb.flEchoDepth) - { - is_dirty = true; - set_efx_echo_depth(); - } - - if (props_.mReverb.flModulationTime != props.mReverb.flModulationTime) - { - is_dirty = true; - set_efx_modulation_time(); - } - - if (props_.mReverb.flModulationDepth != props.mReverb.flModulationDepth) - { - is_dirty = true; - set_efx_modulation_depth(); - } - - if (props_.mReverb.flAirAbsorptionHF != props.mReverb.flAirAbsorptionHF) - { - is_dirty = true; - set_efx_air_absorption_gain_hf(); - } - - if (props_.mReverb.flHFReference != props.mReverb.flHFReference) - { - is_dirty = true; - set_efx_hf_reference(); - } - - if (props_.mReverb.flLFReference != props.mReverb.flLFReference) - { - is_dirty = true; - set_efx_lf_reference(); - } - if (props_.mReverb.flRoomRolloffFactor != props.mReverb.flRoomRolloffFactor) - { - is_dirty = true; - set_efx_room_rolloff_factor(); - } - - if (props_.mReverb.ulFlags != props.mReverb.ulFlags) - { - is_dirty = true; - set_efx_flags(); - } - - return is_dirty; -} - -void EaxReverbEffect::set1(const EaxCall& call, Props1& props) +void EaxReverbCommitter::Set(const EaxCall &call, EAX_REVERBPROPERTIES &props) { - switch (call.get_property_id()) + 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(); + 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) +void EaxReverbCommitter::Set(const EaxCall &call, EAX20LISTENERPROPERTIES &props) { - switch (call.get_property_id()) + switch(call.get_property_id()) { - case DSPROPERTY_EAX20LISTENER_NONE: - break; + case DSPROPERTY_EAX20LISTENER_NONE: + break; - case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: - defer<AllValidator2>(call, props); - break; + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: + defer<AllValidator2>(call, props); + break; - case DSPROPERTY_EAX20LISTENER_ROOM: - defer<RoomValidator>(call, props.lRoom); - break; + case DSPROPERTY_EAX20LISTENER_ROOM: + defer<RoomValidator>(call, props.lRoom); + break; - case DSPROPERTY_EAX20LISTENER_ROOMHF: - defer<RoomHFValidator>(call, props.lRoomHF); - break; + case DSPROPERTY_EAX20LISTENER_ROOMHF: + defer<RoomHFValidator>(call, props.lRoomHF); + break; - case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: - defer<RoomRolloffFactorValidator>(call, props.flRoomRolloffFactor); - break; + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: + defer<RoomRolloffFactorValidator>(call, props.flRoomRolloffFactor); + break; - case DSPROPERTY_EAX20LISTENER_DECAYTIME: - defer<DecayTimeValidator>(call, props.flDecayTime); - break; + case DSPROPERTY_EAX20LISTENER_DECAYTIME: + defer<DecayTimeValidator>(call, props.flDecayTime); + break; - case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: - defer<DecayHFRatioValidator>(call, props.flDecayHFRatio); - break; + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: + defer<DecayHFRatioValidator>(call, props.flDecayHFRatio); + break; - case DSPROPERTY_EAX20LISTENER_REFLECTIONS: - defer<ReflectionsValidator>(call, props.lReflections); - break; + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: + defer<ReflectionsValidator>(call, props.lReflections); + break; - case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: - defer<ReflectionsDelayValidator>(call, props.flReverbDelay); - break; + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: + defer<ReflectionsDelayValidator>(call, props.flReverbDelay); + break; - case DSPROPERTY_EAX20LISTENER_REVERB: - defer<ReverbValidator>(call, props.lReverb); - break; + case DSPROPERTY_EAX20LISTENER_REVERB: + defer<ReverbValidator>(call, props.lReverb); + break; - case DSPROPERTY_EAX20LISTENER_REVERBDELAY: - defer<ReverbDelayValidator>(call, props.flReverbDelay); - break; + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: + defer<ReverbDelayValidator>(call, props.flReverbDelay); + break; - case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: - defer<EnvironmentValidator1, EnvironmentDeferrer2>(call, props, props.dwEnvironment); - break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: + defer<EnvironmentValidator1, EnvironmentDeferrer2>(call, props, props.dwEnvironment); + break; - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: - defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer2>(call, props, props.flEnvironmentSize); - break; + 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_ENVIRONMENTDIFFUSION: + defer<EnvironmentDiffusionValidator>(call, props.flEnvironmentDiffusion); + break; - case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: - defer<AirAbsorptionHFValidator>(call, props.flAirAbsorptionHF); - break; + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: + defer<AirAbsorptionHFValidator>(call, props.flAirAbsorptionHF); + break; - case DSPROPERTY_EAX20LISTENER_FLAGS: - defer<FlagsValidator2>(call, props.dwFlags); - break; + case DSPROPERTY_EAX20LISTENER_FLAGS: + defer<FlagsValidator2>(call, props.dwFlags); + break; - default: - fail_unknown_property_id(); + default: + fail_unknown_property_id(); } } -void EaxReverbEffect::set3(const EaxCall& call, Props3& props) +void EaxReverbCommitter::Set(const EaxCall &call, EAXREVERBPROPERTIES &props) { switch(call.get_property_id()) { - case EAXREVERB_NONE: - break; - - case EAXREVERB_ALLPARAMETERS: - defer<AllValidator3>(call, props); - break; + case EAXREVERB_NONE: + break; - case EAXREVERB_ENVIRONMENT: - defer<EnvironmentValidator3, EnvironmentDeferrer3>(call, props, props.ulEnvironment); - break; + case EAXREVERB_ALLPARAMETERS: + defer<AllValidator3>(call, props); + break; - case EAXREVERB_ENVIRONMENTSIZE: - defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer3>(call, props, props.flEnvironmentSize); - break; + case EAXREVERB_ENVIRONMENT: + defer<EnvironmentValidator3, EnvironmentDeferrer3>(call, props, props.ulEnvironment); + break; - case EAXREVERB_ENVIRONMENTDIFFUSION: - defer3<EnvironmentDiffusionValidator>(call, props, props.flEnvironmentDiffusion); - break; + case EAXREVERB_ENVIRONMENTSIZE: + defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer3>(call, props, props.flEnvironmentSize); + break; - case EAXREVERB_ROOM: - defer3<RoomValidator>(call, props, props.lRoom); - break; + case EAXREVERB_ENVIRONMENTDIFFUSION: + defer3<EnvironmentDiffusionValidator>(call, props, props.flEnvironmentDiffusion); + break; - case EAXREVERB_ROOMHF: - defer3<RoomHFValidator>(call, props, props.lRoomHF); - break; + case EAXREVERB_ROOM: + defer3<RoomValidator>(call, props, props.lRoom); + break; - case EAXREVERB_ROOMLF: - defer3<RoomLFValidator>(call, props, props.lRoomLF); - break; + case EAXREVERB_ROOMHF: + defer3<RoomHFValidator>(call, props, props.lRoomHF); + break; - case EAXREVERB_DECAYTIME: - defer3<DecayTimeValidator>(call, props, props.flDecayTime); - break; + case EAXREVERB_ROOMLF: + defer3<RoomLFValidator>(call, props, props.lRoomLF); + break; - case EAXREVERB_DECAYHFRATIO: - defer3<DecayHFRatioValidator>(call, props, props.flDecayHFRatio); - break; + case EAXREVERB_DECAYTIME: + defer3<DecayTimeValidator>(call, props, props.flDecayTime); + break; - case EAXREVERB_DECAYLFRATIO: - defer3<DecayLFRatioValidator>(call, props, props.flDecayLFRatio); - break; + case EAXREVERB_DECAYHFRATIO: + defer3<DecayHFRatioValidator>(call, props, props.flDecayHFRatio); + break; - case EAXREVERB_REFLECTIONS: - defer3<ReflectionsValidator>(call, props, props.lReflections); - break; + case EAXREVERB_DECAYLFRATIO: + defer3<DecayLFRatioValidator>(call, props, props.flDecayLFRatio); + break; - case EAXREVERB_REFLECTIONSDELAY: - defer3<ReflectionsDelayValidator>(call, props, props.flReflectionsDelay); - break; + case EAXREVERB_REFLECTIONS: + defer3<ReflectionsValidator>(call, props, props.lReflections); + break; - case EAXREVERB_REFLECTIONSPAN: - defer3<VectorValidator>(call, props, props.vReflectionsPan); - break; + case EAXREVERB_REFLECTIONSDELAY: + defer3<ReflectionsDelayValidator>(call, props, props.flReflectionsDelay); + break; - case EAXREVERB_REVERB: - defer3<ReverbValidator>(call, props, props.lReverb); - break; + case EAXREVERB_REFLECTIONSPAN: + defer3<VectorValidator>(call, props, props.vReflectionsPan); + break; - case EAXREVERB_REVERBDELAY: - defer3<ReverbDelayValidator>(call, props, props.flReverbDelay); - break; + case EAXREVERB_REVERB: + defer3<ReverbValidator>(call, props, props.lReverb); + break; - case EAXREVERB_REVERBPAN: - defer3<VectorValidator>(call, props, props.vReverbPan); - break; + case EAXREVERB_REVERBDELAY: + defer3<ReverbDelayValidator>(call, props, props.flReverbDelay); + break; - case EAXREVERB_ECHOTIME: - defer3<EchoTimeValidator>(call, props, props.flEchoTime); - break; + case EAXREVERB_REVERBPAN: + defer3<VectorValidator>(call, props, props.vReverbPan); + break; - case EAXREVERB_ECHODEPTH: - defer3<EchoDepthValidator>(call, props, props.flEchoDepth); - break; + case EAXREVERB_ECHOTIME: + defer3<EchoTimeValidator>(call, props, props.flEchoTime); + break; - case EAXREVERB_MODULATIONTIME: - defer3<ModulationTimeValidator>(call, props, props.flModulationTime); - break; + case EAXREVERB_ECHODEPTH: + defer3<EchoDepthValidator>(call, props, props.flEchoDepth); + break; - case EAXREVERB_MODULATIONDEPTH: - defer3<ModulationDepthValidator>(call, props, props.flModulationDepth); - break; + case EAXREVERB_MODULATIONTIME: + defer3<ModulationTimeValidator>(call, props, props.flModulationTime); + break; - case EAXREVERB_AIRABSORPTIONHF: - defer3<AirAbsorptionHFValidator>(call, props, props.flAirAbsorptionHF); - break; + case EAXREVERB_MODULATIONDEPTH: + defer3<ModulationDepthValidator>(call, props, props.flModulationDepth); + break; - case EAXREVERB_HFREFERENCE: - defer3<HFReferenceValidator>(call, props, props.flHFReference); - break; + case EAXREVERB_AIRABSORPTIONHF: + defer3<AirAbsorptionHFValidator>(call, props, props.flAirAbsorptionHF); + break; - case EAXREVERB_LFREFERENCE: - defer3<LFReferenceValidator>(call, props, props.flLFReference); - break; + case EAXREVERB_HFREFERENCE: + defer3<HFReferenceValidator>(call, props, props.flHFReference); + break; - case EAXREVERB_ROOMROLLOFFFACTOR: - defer3<RoomRolloffFactorValidator>(call, props, props.flRoomRolloffFactor); - break; + case EAXREVERB_LFREFERENCE: + defer3<LFReferenceValidator>(call, props, props.flLFReference); + break; - case EAXREVERB_FLAGS: - defer3<FlagsValidator3>(call, props, props.ulFlags); - break; + case EAXREVERB_ROOMROLLOFFFACTOR: + defer3<RoomRolloffFactorValidator>(call, props, props.flRoomRolloffFactor); + break; - default: - fail_unknown_property_id(); - } -} + case EAXREVERB_FLAGS: + defer3<FlagsValidator3>(call, props, props.ulFlags); + break; -void EaxReverbEffect::set(const EaxCall& call) -{ - 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.mReverb); break; - case 5: set3(call, state5_.d.mReverb); break; - default: fail_unknown_version(); + default: + fail_unknown_property_id(); } - changed_ = true; - version_ = version; -} - -void EaxReverbEffect::translate(const Props1& src, Props4& dst) noexcept -{ - assert(src.environment <= EAX1REVERB_MAXENVIRONMENT); - dst.mType = EaxEffectType::Reverb; - dst.mReverb = EAXREVERB_PRESETS[src.environment]; - dst.mReverb.flDecayTime = src.fDecayTime_sec; - dst.mReverb.flDecayHFRatio = src.fDamping; - dst.mReverb.lReverb = mini(static_cast<int>(gain_to_level_mb(src.fVolume)), 0); -} - -void EaxReverbEffect::translate(const Props2& src, Props4& dst) noexcept -{ - assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT); - const auto& env = EAXREVERB_PRESETS[src.dwEnvironment]; - dst.mType = EaxEffectType::Reverb; - dst.mReverb.ulEnvironment = src.dwEnvironment; - dst.mReverb.flEnvironmentSize = src.flEnvironmentSize; - dst.mReverb.flEnvironmentDiffusion = src.flEnvironmentDiffusion; - dst.mReverb.lRoom = src.lRoom; - dst.mReverb.lRoomHF = src.lRoomHF; - dst.mReverb.lRoomLF = env.lRoomLF; - dst.mReverb.flDecayTime = src.flDecayTime; - dst.mReverb.flDecayHFRatio = src.flDecayHFRatio; - dst.mReverb.flDecayLFRatio = env.flDecayLFRatio; - dst.mReverb.lReflections = src.lReflections; - dst.mReverb.flReflectionsDelay = src.flReflectionsDelay; - dst.mReverb.vReflectionsPan = env.vReflectionsPan; - dst.mReverb.lReverb = src.lReverb; - dst.mReverb.flReverbDelay = src.flReverbDelay; - dst.mReverb.vReverbPan = env.vReverbPan; - dst.mReverb.flEchoTime = env.flEchoTime; - dst.mReverb.flEchoDepth = env.flEchoDepth; - dst.mReverb.flModulationTime = env.flModulationTime; - dst.mReverb.flModulationDepth = env.flModulationDepth; - dst.mReverb.flAirAbsorptionHF = src.flAirAbsorptionHF; - dst.mReverb.flHFReference = env.flHFReference; - dst.mReverb.flLFReference = env.flLFReference; - dst.mReverb.flRoomRolloffFactor = src.flRoomRolloffFactor; - dst.mReverb.ulFlags = src.dwFlags; } -void EaxReverbEffect::translate(const Props3& src, Props4& dst) noexcept -{ - dst.mType = EaxEffectType::Reverb; - dst.mReverb = src; -} - -} // namespace - -EaxEffectUPtr eax_create_eax_reverb_effect(int eax_version) +void EaxReverbCommitter::Set(const EaxCall &call, EaxEffectProps &props) { - return std::make_unique<EaxReverbEffect>(eax_version); + Set(call, props.mReverb); } #endif // ALSOFT_EAX |