diff options
-rw-r--r-- | al/auxeffectslot.cpp | 75 | ||||
-rw-r--r-- | al/auxeffectslot.h | 12 | ||||
-rw-r--r-- | al/eax/call.cpp | 23 | ||||
-rw-r--r-- | al/source.cpp | 83 | ||||
-rw-r--r-- | al/source.h | 2 | ||||
-rw-r--r-- | alc/context.cpp | 47 | ||||
-rw-r--r-- | alc/context.h | 12 |
7 files changed, 197 insertions, 57 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 162b5137..0cfd6636 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1182,7 +1182,7 @@ long ALeffectslot::eax_get_eax_default_lock() const noexcept return eax4_fx_slot_is_legacy() ? EAXFXSLOT_LOCKED : EAXFXSLOT_UNLOCKED; } -void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) +void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) noexcept { props.guidLoadEffect = eax_get_eax_default_effect_guid(); props.lVolume = EAXFXSLOT_DEFAULTVOLUME; @@ -1190,32 +1190,58 @@ void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) props.ulFlags = EAX40FXSLOT_DEFAULTFLAGS; } -void ALeffectslot::eax4_fx_slot_set_defaults() +void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) noexcept { - eax4_fx_slot_set_defaults(eax4_.i); + props.guidLoadEffect = eax_get_eax_default_effect_guid(); + props.lVolume = EAXFXSLOT_DEFAULTVOLUME; + props.lLock = EAXFXSLOT_UNLOCKED; + props.ulFlags = EAX50FXSLOT_DEFAULTFLAGS; + props.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; + props.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } -void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) +void ALeffectslot::eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept { - eax4_fx_slot_set_defaults(static_cast<Eax4Props&>(props)); - props.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; - props.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; + static_cast<Eax4Props&>(eax_) = props; + eax_.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; + eax_.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } -void ALeffectslot::eax5_fx_slot_set_defaults() +void ALeffectslot::eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept { - eax5_fx_slot_set_defaults(eax5_.i); + eax_ = props; } -void ALeffectslot::eax_fx_slot_set_defaults() +void ALeffectslot::eax_fx_slot_set_current_defaults() { - eax4_fx_slot_set_defaults(); - eax5_fx_slot_set_defaults(); - eax123_ = eax5_; - eax_ = eax5_.i; + 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(); +} + void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const { switch(call.get_property_id()) @@ -1275,7 +1301,7 @@ void ALeffectslot::eax_fx_slot_get(const EaxCall& call) const switch(call.get_version()) { case 4: eax4_fx_slot_get(call, eax4_.i); break; - case 5: eax4_fx_slot_get(call, eax5_.i); break; + case 5: eax5_fx_slot_get(call, eax5_.i); break; default: eax_fail_unknown_version(); } } @@ -1353,6 +1379,19 @@ void ALeffectslot::eax5_fx_slot_set_all(const EaxCall& call) dst = src; } +bool ALeffectslot::eax_fx_slot_should_update_sources() const noexcept +{ + const auto dirty_bits = + eax_occlusion_dirty_bit | + eax_occlusion_lf_ratio_dirty_bit | + eax_flags_dirty_bit; + + if((eax_df_ & dirty_bits) != EaxDirtyFlags{}) + return true; + + return false; +} + // Returns `true` if all sources should be updated, or `false` otherwise. bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) { @@ -1383,7 +1422,7 @@ bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) eax_fail_unknown_property_id(); } - return (eax_df_ & (eax_occlusion_dirty_bit | eax_occlusion_lf_ratio_dirty_bit)) != EaxDirtyFlags{}; + return eax_fx_slot_should_update_sources(); } // Returns `true` if all sources should be updated, or `false` otherwise. @@ -1408,7 +1447,7 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) eax_fx_slot_set<Eax4LockValidator, eax_lock_dirty_bit>(call, dst.lLock, eax_df_); break; case EAXFXSLOT_FLAGS: - eax_fx_slot_set<Eax4FlagsValidator, eax_flags_dirty_bit>(call, dst.ulFlags, eax_df_); + eax_fx_slot_set<Eax5FlagsValidator, eax_flags_dirty_bit>(call, dst.ulFlags, eax_df_); break; case EAXFXSLOT_OCCLUSION: eax_fx_slot_set<Eax5OcclusionValidator, eax_occlusion_dirty_bit>(call, dst.lOcclusion, eax_df_); @@ -1420,7 +1459,7 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) eax_fail_unknown_property_id(); } - return (eax_df_ & (eax_occlusion_dirty_bit | eax_occlusion_lf_ratio_dirty_bit)) != EaxDirtyFlags{}; + return eax_fx_slot_should_update_sources(); } // Returns `true` if all sources should be updated, or `false` otherwise. diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 78b0c95a..9b6403f4 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -84,6 +84,7 @@ struct ALeffectslot { public: void eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index); + EaxFxSlotIndexValue eax_get_index() const noexcept { return eax_fx_slot_index_; } const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept { return eax_; } @@ -285,10 +286,11 @@ private: const GUID& eax_get_eax_default_effect_guid() const noexcept; long eax_get_eax_default_lock() const noexcept; - void eax4_fx_slot_set_defaults(Eax4Props& props); - void eax4_fx_slot_set_defaults(); - void eax5_fx_slot_set_defaults(Eax5Props& props); - void eax5_fx_slot_set_defaults(); + void eax4_fx_slot_set_defaults(Eax4Props& props) noexcept; + void eax5_fx_slot_set_defaults(Eax5Props& props) noexcept; + void eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept; + void eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept; + void eax_fx_slot_set_current_defaults(); void eax_fx_slot_set_defaults(); void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const; @@ -305,6 +307,8 @@ private: void eax4_fx_slot_set_all(const EaxCall& call); void eax5_fx_slot_set_all(const EaxCall& call); + bool eax_fx_slot_should_update_sources() const noexcept; + // Returns `true` if all sources should be updated, or `false` otherwise. bool eax4_fx_slot_set(const EaxCall& call); // Returns `true` if all sources should be updated, or `false` otherwise. diff --git a/al/eax/call.cpp b/al/eax/call.cpp index f779c2b0..abb27933 100644 --- a/al/eax/call.cpp +++ b/al/eax/call.cpp @@ -151,7 +151,28 @@ EaxCall::EaxCall( fail("EAX version out of range."); } - if(!(property_id&deferred_flag)) + switch(property_id) + { + case EAXCONTEXT_LASTERROR: + case EAXCONTEXT_SPEAKERCONFIG: + case EAXCONTEXT_EAXSESSION: + case EAXFXSLOT_NONE: + case EAXFXSLOT_ALLPARAMETERS: + case EAXFXSLOT_LOADEFFECT: + case EAXFXSLOT_VOLUME: + case EAXFXSLOT_LOCK: + case EAXFXSLOT_FLAGS: + case EAXFXSLOT_OCCLUSION: + case EAXFXSLOT_OCCLUSIONLFRATIO: + // EAX allow to set "defer" flag on immediate-only properties. + // If we don't clear our flag then "applyAllUpdates" in EAX context won't be called. + is_deferred_ = false; + break; + default: + break; + } + + if(!is_deferred_) { if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0) { diff --git a/al/source.cpp b/al/source.cpp index e5241a39..8856bafc 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -3996,6 +3996,9 @@ float ALsource::eax_calculate_dst_occlusion_mb( float path_ratio, float lf_ratio) noexcept { + if(src_occlusion_mb == 0) + return 0.0f; + const auto ratio_1 = path_ratio + lf_ratio - 1.0F; const auto ratio_2 = path_ratio * lf_ratio; const auto ratio = (ratio_2 > ratio_1) ? ratio_2 : ratio_1; @@ -4013,26 +4016,44 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept eax_.source.flOcclusionDirectRatio, eax_.source.flOcclusionLFRatio); + const auto has_source_occlusion = (eax_.source.lOcclusion != 0); + auto gain_hf_mb = static_cast<float>(eax_.source.lDirectHF) + - static_cast<float>(eax_.source.lObstruction) + - (static_cast<float>(eax_.source.lOcclusion) * eax_.source.flOcclusionDirectRatio); + static_cast<float>(eax_.source.lObstruction); for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i) { - if (!eax_active_fx_slots_[i]) - { + if(!eax_active_fx_slots_[i]) continue; + + if(has_source_occlusion) { + const auto& fx_slot = eax_al_context_->eax_get_fx_slot(i); + const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot(); + const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); + const auto is_primary = (eax_primary_fx_slot_id_.value_or(-1) == fx_slot.eax_get_index()); + const auto is_listener_environment = (is_environmental_fx && is_primary); + + if(is_listener_environment) { + gain_mb += eax_calculate_dst_occlusion_mb( + eax_.source.lOcclusion, + eax_.source.flOcclusionDirectRatio, + eax_.source.flOcclusionLFRatio); + + gain_hf_mb += static_cast<float>(eax_.source.lOcclusion) * eax_.source.flOcclusionDirectRatio; + } } const auto& send = eax_.sends[i]; - gain_mb += eax_calculate_dst_occlusion_mb( - send.lOcclusion, - send.flOcclusionDirectRatio, - send.flOcclusionLFRatio); + if(send.lOcclusion != 0) { + gain_mb += eax_calculate_dst_occlusion_mb( + send.lOcclusion, + send.flOcclusionDirectRatio, + send.flOcclusionLFRatio); - gain_hf_mb += static_cast<float>(send.lOcclusion) * send.flOcclusionDirectRatio; + gain_hf_mb += static_cast<float>(send.lOcclusion) * send.flOcclusionDirectRatio; + } } const auto al_low_pass_param = EaxAlLowPassParam{ @@ -4047,25 +4068,38 @@ EaxAlLowPassParam ALsource::eax_create_room_filter_param( const EAXSOURCEALLSENDPROPERTIES& send) const noexcept { const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot(); + const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); + const auto is_primary = (eax_primary_fx_slot_id_.value_or(-1) == fx_slot.eax_get_index()); + const auto is_listener_environment = (is_environmental_fx && is_primary); const auto gain_mb = - static_cast<float>(eax_.source.lRoom + send.lSend) + - eax_calculate_dst_occlusion_mb( - eax_.source.lOcclusion, - eax_.source.flOcclusionRoomRatio, - eax_.source.flOcclusionLFRatio) + + (static_cast<float>(fx_slot_eax.lOcclusion) * fx_slot_eax.flOcclusionLFRatio) + + static_cast<float>((is_environmental_fx ? eax_.source.lRoom : 0) + send.lSend) + + (is_listener_environment ? + eax_calculate_dst_occlusion_mb( + eax_.source.lOcclusion, + eax_.source.flOcclusionRoomRatio, + eax_.source.flOcclusionLFRatio) : + 0.0f) + eax_calculate_dst_occlusion_mb( send.lOcclusion, send.flOcclusionRoomRatio, send.flOcclusionLFRatio) + - (static_cast<float>(eax_.source.lExclusion) * eax_.source.flExclusionLFRatio) + + (is_listener_environment ? + (static_cast<float>(eax_.source.lExclusion) * eax_.source.flExclusionLFRatio) : + 0.0f) + (static_cast<float>(send.lExclusion) * send.flExclusionLFRatio); const auto gain_hf_mb = - static_cast<float>(eax_.source.lRoomHF + send.lSendHF) + - (static_cast<float>(fx_slot_eax.lOcclusion + eax_.source.lOcclusion) * eax_.source.flOcclusionRoomRatio) + + static_cast<float>(fx_slot_eax.lOcclusion) + + static_cast<float>((is_environmental_fx ? eax_.source.lRoomHF : 0) + send.lSendHF) + + (is_listener_environment ? + ((static_cast<float>(eax_.source.lOcclusion) * eax_.source.flOcclusionRoomRatio)) : + 0.0f) + (static_cast<float>(send.lOcclusion) * send.flOcclusionRoomRatio) + - static_cast<float>(eax_.source.lExclusion + send.lExclusion); + (is_listener_environment ? + static_cast<float>(eax_.source.lExclusion + send.lExclusion) : + 0.0f); const auto al_low_pass_param = EaxAlLowPassParam{ level_mb_to_gain(gain_mb), @@ -4486,6 +4520,15 @@ void ALsource::eax_set(const EaxCall& call) eax_version_ = eax_version; } +void ALsource::eax_get_active_fx_slot_id(const EaxCall& call, const GUID* ids, int max_count) +{ + assert(ids != nullptr); + assert(max_count == EAX40_MAX_ACTIVE_FXSLOTS || max_count == EAX50_MAX_ACTIVE_FXSLOTS); + const auto dst_ids = call.get_values<GUID>(max_count); + const auto count = dst_ids.size(); + std::uninitialized_copy_n(ids, count, dst_ids.begin()); +} + void ALsource::eax1_get(const EaxCall& call, const Eax1Props& props) { switch (call.get_property_id()) { @@ -4731,7 +4774,7 @@ void ALsource::eax4_get(const EaxCall& call, const Eax4Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - call.set_value<Exception>(props.active_fx_slots); + eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots, EAX40_MAX_ACTIVE_FXSLOTS); break; default: @@ -4803,7 +4846,7 @@ void ALsource::eax5_get(const EaxCall& call, const Eax5Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - call.set_value<Exception>(props.active_fx_slots); + eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots, EAX50_MAX_ACTIVE_FXSLOTS); break; case EAXSOURCE_MACROFXFACTOR: diff --git a/al/source.h b/al/source.h index a1efd527..513a334a 100644 --- a/al/source.h +++ b/al/source.h @@ -163,6 +163,7 @@ public: void eax_dispatch(const EaxCall& call); void eax_commit() { eax_commit(EaxCommitType::normal); } void eax_commit_and_update(); + void eax_mark_as_changed() { eax_changed_ = true; } bool eax_is_initialized() const noexcept { return eax_al_context_ != nullptr; } static ALsource* eax_lookup_source(ALCcontext& al_context, ALuint source_id) noexcept; @@ -901,6 +902,7 @@ private: } } + void eax_get_active_fx_slot_id(const EaxCall& call, const GUID* ids, int max_count); void eax1_get(const EaxCall& call, const Eax1Props& props); void eax2_get(const EaxCall& call, const Eax2Props& props); void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props); diff --git a/alc/context.cpp b/alc/context.cpp index 403c4fa3..86c76aaa 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -384,11 +384,6 @@ ALenum ALCcontext::eax_eax_get( return AL_NO_ERROR; } -void ALCcontext::eax_update_filters() -{ - ForEachSource(this, [](ALsource& source){ source.eax_commit(); }); -} - void ALCcontext::eax_commit_and_update_sources() { std::unique_lock<std::mutex> source_lock{mSourceLock}; @@ -600,16 +595,48 @@ void ALCcontext::eax5_context_set_defaults(Eax5State& state) noexcept state.d = state.i; } -void ALCcontext::eax_context_set_defaults() noexcept +void ALCcontext::eax4_context_set_current_defaults(const Eax4Props& props) noexcept +{ + static_cast<Eax4Props&>(eax_) = props; + eax_.flMacroFXFactor = EAXCONTEXT_DEFAULTMACROFXFACTOR; +} + +void ALCcontext::eax5_context_set_current_defaults(const Eax5Props& props) noexcept +{ + eax_ = props; +} + +void ALCcontext::eax_context_set_current_defaults() +{ + switch(eax_version_) + { + case 1: + case 2: + case 3: + eax5_context_set_current_defaults(eax123_.i); + break; + case 4: + eax4_context_set_current_defaults(eax4_.i); + break; + case 5: + eax5_context_set_current_defaults(eax5_.i); + break; + default: + eax_fail_unknown_version(); + } + + eax_df_ = ~EaxDirtyFlags{}; +} + +void ALCcontext::eax_context_set_defaults() { eax5_context_set_defaults(eax123_); eax4_context_set_defaults(eax4_); eax5_context_set_defaults(eax5_); - eax_ = eax5_.i; - eax_df_ = ~EaxDirtyFlags{}; + eax_context_set_current_defaults(); } -void ALCcontext::eax_set_defaults() noexcept +void ALCcontext::eax_set_defaults() { eax_set_last_error_defaults(); eax_session_set_defaults(); @@ -626,7 +653,7 @@ void ALCcontext::eax_dispatch_fx_slot(const EaxCall& call) if(fx_slot.eax_dispatch(call)) { std::lock_guard<std::mutex> source_lock{mSourceLock}; - eax_update_filters(); + ForEachSource(this, [](ALsource& source){ source.eax_mark_as_changed(); }); } } diff --git a/alc/context.h b/alc/context.h index 660a6559..448ae980 100644 --- a/alc/context.h +++ b/alc/context.h @@ -204,7 +204,6 @@ public: ALvoid* property_value, ALuint property_value_size); - void eax_update_filters(); void eax_commit_and_update_sources(); void eax_set_last_error() noexcept; @@ -451,7 +450,9 @@ private: if((eax_df_ & TDirtyBit) != EaxDirtyFlags{}) { dst_df |= TDirtyBit; - eax_.*member = state.i.*member; + const auto& src_d = state.d.*member; + state.i.*member = src_d; + eax_.*member = src_d; } } @@ -473,8 +474,11 @@ private: static void eax4_context_set_defaults(Eax4State& state) noexcept; static void eax5_context_set_defaults(Eax5Props& props) noexcept; static void eax5_context_set_defaults(Eax5State& state) noexcept; - void eax_context_set_defaults() noexcept; - void eax_set_defaults() noexcept; + void eax4_context_set_current_defaults(const Eax4Props& props) noexcept; + void eax5_context_set_current_defaults(const Eax5Props& props) noexcept; + void eax_context_set_current_defaults(); + void eax_context_set_defaults(); + void eax_set_defaults(); void eax_initialize_sources(); |