Merge pull request from bibendovsky/wip_20220714

[EAX] Various fixes
This commit is contained in:
kcat 2022-07-17 13:28:47 -07:00 committed by GitHub
commit c6064a2034
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 198 additions and 58 deletions

@ -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,30 +1190,56 @@ 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);
}
void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props)
{
eax4_fx_slot_set_defaults(static_cast<Eax4Props&>(props));
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()
void ALeffectslot::eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept
{
eax5_fx_slot_set_defaults(eax5_.i);
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()
{
eax4_fx_slot_set_defaults();
eax5_fx_slot_set_defaults();
eax123_ = eax5_;
eax_ = eax5_.i;
eax_df_ = ~EaxDirtyFlags{};
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
@ -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.

@ -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.

@ -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)
{

@ -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:

@ -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);

@ -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(); });
}
}

@ -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();