[EAX_SOURCE] Fix source's occlusion and exclusion contribution

Source's oclussion and exclusion properties should be taken into account only for listener's environment (see p. 16, p. 56, pp. 62-63 and p. 64 of "EAX® 4.0 Programmer’s Guide").
master
Boris I. Bendovsky 2022-07-15 15:14:55 +03:00
parent 6f3500f458
commit 7e9c0285b4
No known key found for this signature in database
GPG Key ID: 48CD539C0518594B
3 changed files with 62 additions and 19 deletions

View File

@ -1379,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)
{
@ -1409,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.
@ -1446,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.

View File

@ -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_; }
@ -306,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.

View File

@ -4016,27 +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])
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];
if(send.lOcclusion == 0)
continue;
if(send.lOcclusion != 0) {
gain_mb += eax_calculate_dst_occlusion_mb(
send.lOcclusion,
send.flOcclusionDirectRatio,
send.flOcclusionLFRatio);
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{
@ -4052,27 +4069,37 @@ EaxAlLowPassParam ALsource::eax_create_room_filter_param(
{
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>(fx_slot_eax.lOcclusion) * fx_slot_eax.flOcclusionLFRatio) +
static_cast<float>((is_environmental_fx ? eax_.source.lRoom : 0) + send.lSend) +
eax_calculate_dst_occlusion_mb(
eax_.source.lOcclusion,
eax_.source.flOcclusionRoomRatio,
eax_.source.flOcclusionLFRatio) +
(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>(fx_slot_eax.lOcclusion) +
static_cast<float>((is_environmental_fx ? eax_.source.lRoomHF : 0) + send.lSendHF) +
(static_cast<float>(eax_.source.lOcclusion) * eax_.source.flOcclusionRoomRatio) +
(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),