diff options
author | Boris I. Bendovsky <[email protected]> | 2022-02-08 18:20:46 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2022-02-08 08:20:46 -0800 |
commit | d42077680890fee9e8f150e99bc259435bbe5d44 (patch) | |
tree | 0606b99eba2a09c18a8b82a2b5aafe11557eba91 /al | |
parent | f23c7fe8ba77d4d406d37c60501f961313db7d1a (diff) |
EAX various fixes (#657)
* [EAX] Fix effect GUID validation
Only NULL and REVERB was valid.
* [EAX] Fix default FX slot flags
EAX4 and EAX5 both sets to ENVIRONMENT.
* [EAX] Set default values for legacy FX slots in the initialization
* [EAX] Fix FX slot locking policy
Fail on attempt to load an effect or change a lock for EAX4 "set" call.
Unlock legacy FX slots on any EAX5 call.
* [EAX] Allow DEFER flag for "get" calls.
* [EAX] Make speaker configuration read-only
* [EAX] Initialize speaker configuration
* [EAX] Commit EAX source on a 3D source parameter call
Reference: EAX 4.0 Programmer's Guide
* [EAX] Commit EAX source on a 3D listener parameter call
Reference: EAX 4.0 Programmer's Guide
* [EAX] Commit source when it begins to play
Reference: EAX 4.0 Programmer's Guide
Diffstat (limited to 'al')
-rw-r--r-- | al/auxeffectslot.cpp | 99 | ||||
-rw-r--r-- | al/auxeffectslot.h | 22 | ||||
-rw-r--r-- | al/eax_eax_call.cpp | 9 | ||||
-rw-r--r-- | al/eax_fx_slots.cpp | 5 | ||||
-rw-r--r-- | al/eax_fx_slots.h | 2 | ||||
-rw-r--r-- | al/listener.cpp | 9 | ||||
-rw-r--r-- | al/source.cpp | 50 | ||||
-rw-r--r-- | al/source.h | 4 |
8 files changed, 133 insertions, 67 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 5ddd2a28..d0487925 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1087,8 +1087,8 @@ void ALeffectslot::eax_initialize( eax_fx_slot_index_ = index; eax_initialize_eax(); + eax_initialize_lock(); eax_initialize_effects(); - eax_set_default_slots_defaults(); } const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept @@ -1096,11 +1096,30 @@ const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept return eax_eax_fx_slot_; } +void ALeffectslot::eax_ensure_is_unlocked() const +{ + if (eax_is_locked_) + eax_fail("Locked."); +} + void ALeffectslot::eax_validate_fx_slot_effect( const GUID& eax_effect_id) { + eax_ensure_is_unlocked(); + if (eax_effect_id != EAX_NULL_GUID && - eax_effect_id != EAX_REVERB_EFFECT) + eax_effect_id != EAX_REVERB_EFFECT && + eax_effect_id != EAX_AGCCOMPRESSOR_EFFECT && + eax_effect_id != EAX_AUTOWAH_EFFECT && + eax_effect_id != EAX_CHORUS_EFFECT && + eax_effect_id != EAX_DISTORTION_EFFECT && + eax_effect_id != EAX_ECHO_EFFECT && + eax_effect_id != EAX_EQUALIZER_EFFECT && + eax_effect_id != EAX_FLANGER_EFFECT && + eax_effect_id != EAX_FREQUENCYSHIFTER_EFFECT && + eax_effect_id != EAX_VOCALMORPHER_EFFECT && + eax_effect_id != EAX_PITCHSHIFTER_EFFECT && + eax_effect_id != EAX_RINGMODULATOR_EFFECT) { eax_fail("Unsupported EAX effect GUID."); } @@ -1119,6 +1138,8 @@ void ALeffectslot::eax_validate_fx_slot_volume( void ALeffectslot::eax_validate_fx_slot_lock( long eax_lock) { + eax_ensure_is_unlocked(); + eax_validate_range<EaxFxSlotException>( "Lock", eax_lock, @@ -1126,16 +1147,6 @@ void ALeffectslot::eax_validate_fx_slot_lock( EAXFXSLOT_MAXLOCK); } -void ALeffectslot::eax_validate_fx_slot_lock_state( - long eax_lock, - const GUID& eax_effect_id) -{ - if (eax_lock == EAXFXSLOT_LOCKED && eax_effect_id != eax_eax_fx_slot_.guidLoadEffect) - { - eax_fail("Loading an effect in a locked slot."); - } -} - void ALeffectslot::eax_validate_fx_slot_flags( unsigned long eax_flags, int eax_version) @@ -1293,6 +1304,13 @@ bool ALeffectslot::eax_dispatch( return eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); } +void ALeffectslot::eax_unlock_legacy() noexcept +{ + assert(eax_fx_slot_index_ < 2); + eax_is_locked_ = false; + eax_eax_fx_slot_.lLock = EAXFXSLOT_UNLOCKED; +} + [[noreturn]] void ALeffectslot::eax_fail( const char* message) @@ -1300,55 +1318,44 @@ void ALeffectslot::eax_fail( throw EaxFxSlotException{message}; } -void ALeffectslot::eax_set_eax_fx_slot_defaults() +GUID ALeffectslot::eax_get_eax_default_effect_guid() const noexcept { - eax_eax_fx_slot_.guidLoadEffect = EAX_NULL_GUID; - eax_eax_fx_slot_.lVolume = EAXFXSLOT_DEFAULTVOLUME; - eax_eax_fx_slot_.lLock = EAXFXSLOT_UNLOCKED; - eax_eax_fx_slot_.ulFlags = EAX50FXSLOT_DEFAULTFLAGS; - eax_eax_fx_slot_.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; - eax_eax_fx_slot_.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; + switch (eax_fx_slot_index_) + { + case 0: return EAX_REVERB_EFFECT; + case 1: return EAX_CHORUS_EFFECT; + default: return EAX_NULL_GUID; + } } -void ALeffectslot::eax_initialize_eax() +unsigned long ALeffectslot::eax_get_eax_default_lock() const noexcept { - eax_set_eax_fx_slot_defaults(); + return eax_fx_slot_index_ < 2 ? EAXFXSLOT_LOCKED : EAXFXSLOT_UNLOCKED; } -void ALeffectslot::eax_initialize_effects() +void ALeffectslot::eax_set_eax_fx_slot_defaults() { - eax_set_fx_slot_effect(); + eax_eax_fx_slot_.guidLoadEffect = eax_get_eax_default_effect_guid(); + eax_eax_fx_slot_.lVolume = EAXFXSLOT_DEFAULTVOLUME; + eax_eax_fx_slot_.lLock = eax_get_eax_default_lock(); + eax_eax_fx_slot_.ulFlags = EAX40FXSLOT_DEFAULTFLAGS; + eax_eax_fx_slot_.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; + eax_eax_fx_slot_.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } -void ALeffectslot::eax_set_default_slot_0_defaults() +void ALeffectslot::eax_initialize_eax() { - eax_set_fx_slot_effect(EAX_REVERB_EFFECT); + eax_set_eax_fx_slot_defaults(); } -void ALeffectslot::eax_set_default_slot_1_defaults() +void ALeffectslot::eax_initialize_lock() { - eax_set_fx_slot_effect(EAX_CHORUS_EFFECT); + eax_is_locked_ = (eax_fx_slot_index_ < 2); } -void ALeffectslot::eax_set_default_slots_defaults() +void ALeffectslot::eax_initialize_effects() { - switch (eax_fx_slot_index_) - { - case 0: - eax_set_default_slot_0_defaults(); - break; - - case 1: - eax_set_default_slot_1_defaults(); - break; - - case 2: - case 3: - break; - - default: - eax_fail("FX slot index out of range."); - } + eax_set_fx_slot_effect(); } void ALeffectslot::eax_get_fx_slot_all( @@ -1540,8 +1547,6 @@ void ALeffectslot::eax_set_fx_slot_effect( eax_call.get_value<EaxFxSlotException, const decltype(EAX40FXSLOTPROPERTIES::guidLoadEffect)>(); eax_validate_fx_slot_effect(eax_effect_id); - eax_validate_fx_slot_lock_state(eax_eax_fx_slot_.lLock, eax_effect_id); - eax_set_fx_slot_effect(eax_effect_id); } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 8182c082..0ee1d022 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -85,6 +85,8 @@ public: bool eax_dispatch( const EaxEaxCall& eax_call); + void eax_unlock_legacy() noexcept; + private: ALCcontext* eax_al_context_{}; @@ -94,6 +96,7 @@ private: EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{}; EaxEffectUPtr eax_effect_{}; + bool eax_is_locked_{}; [[noreturn]] @@ -101,19 +104,17 @@ private: const char* message); + GUID eax_get_eax_default_effect_guid() const noexcept; + unsigned long eax_get_eax_default_lock() const noexcept; + void eax_set_eax_fx_slot_defaults(); void eax_initialize_eax(); + void eax_initialize_lock(); - void eax_initialize_effects(); - - - void eax_set_default_slot_0_defaults(); - - void eax_set_default_slot_1_defaults(); - void eax_set_default_slots_defaults(); + void eax_initialize_effects(); void eax_get_fx_slot_all( @@ -143,6 +144,9 @@ private: void eax_set_fx_slot_flags(); + void eax_ensure_is_unlocked() const; + + void eax_validate_fx_slot_effect( const GUID& eax_effect_id); @@ -152,10 +156,6 @@ private: void eax_validate_fx_slot_lock( long eax_lock); - void eax_validate_fx_slot_lock_state( - long eax_lock, - const GUID& eax_effect_id); - void eax_validate_fx_slot_flags( unsigned long eax_flags, int eax_version); diff --git a/al/eax_eax_call.cpp b/al/eax_eax_call.cpp index 76f3dbfd..6c9b00ec 100644 --- a/al/eax_eax_call.cpp +++ b/al/eax_eax_call.cpp @@ -158,14 +158,7 @@ EaxEaxCall::EaxEaxCall( fail("EAX version out of range."); } - if (is_deferred_) - { - if (is_get_) - { - fail("Getting deferred properties not supported."); - } - } - else + if (!is_deferred_) { if (property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) diff --git a/al/eax_fx_slots.cpp b/al/eax_fx_slots.cpp index f2db3ede..61d5e168 100644 --- a/al/eax_fx_slots.cpp +++ b/al/eax_fx_slots.cpp @@ -60,6 +60,11 @@ ALeffectslot& EaxFxSlots::get( return const_cast<ALeffectslot&>(const_cast<const EaxFxSlots*>(this)->get(index)); } +void EaxFxSlots::unlock_legacy() noexcept +{ + fx_slots_[0]->eax_unlock_legacy(); + fx_slots_[1]->eax_unlock_legacy(); +} [[noreturn]] void EaxFxSlots::fail( diff --git a/al/eax_fx_slots.h b/al/eax_fx_slots.h index 6abe61b6..0ebb9b7d 100644 --- a/al/eax_fx_slots.h +++ b/al/eax_fx_slots.h @@ -26,6 +26,8 @@ public: ALeffectslot& get( EaxFxSlotIndex index); + void unlock_legacy() noexcept; + private: using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>; diff --git a/al/listener.cpp b/al/listener.cpp index 97652a9a..eb7b6b2f 100644 --- a/al/listener.cpp +++ b/al/listener.cpp @@ -95,6 +95,9 @@ START_API_FUNC listener.Position[1] = value2; listener.Position[2] = value3; UpdateProps(listener, context.get()); +#ifdef ALSOFT_EAX + context->eax_on_3d_listener_param_call(); +#endif // ALSOFT_EAX break; case AL_VELOCITY: @@ -104,6 +107,9 @@ START_API_FUNC listener.Velocity[1] = value2; listener.Velocity[2] = value3; UpdateProps(listener, context.get()); +#ifdef ALSOFT_EAX + context->eax_on_3d_listener_param_call(); +#endif // ALSOFT_EAX break; default: @@ -151,6 +157,9 @@ START_API_FUNC listener.OrientUp[1] = values[4]; listener.OrientUp[2] = values[5]; UpdateProps(listener, context.get()); +#ifdef ALSOFT_EAX + context->eax_on_3d_listener_param_call(); +#endif // ALSOFT_EAX break; default: diff --git a/al/source.cpp b/al/source.cpp index 87696147..08049bce 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -74,7 +74,6 @@ #ifdef ALSOFT_EAX #include "eax_exception.h" -#include "eax_globals.h" #endif // ALSOFT_EAX namespace { @@ -1177,6 +1176,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a CHECKVAL(values[0] >= 0.0f && values[0] <= 360.0f); Source->InnerAngle = values[0]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_CONE_OUTER_ANGLE: @@ -1184,6 +1186,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a CHECKVAL(values[0] >= 0.0f && values[0] <= 360.0f); Source->OuterAngle = values[0]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_GAIN: @@ -1198,6 +1203,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a CHECKVAL(values[0] >= 0.0f); Source->MaxDistance = values[0]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_ROLLOFF_FACTOR: @@ -1205,6 +1213,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a CHECKVAL(values[0] >= 0.0f); Source->RolloffFactor = values[0]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_REFERENCE_DISTANCE: @@ -1212,6 +1223,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a CHECKVAL(values[0] >= 0.0f); Source->RefDistance = values[0]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_MIN_GAIN: @@ -1314,6 +1328,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a Source->Position[0] = values[0]; Source->Position[1] = values[1]; Source->Position[2] = values[2]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_VELOCITY: @@ -1323,6 +1340,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a Source->Velocity[0] = values[0]; Source->Velocity[1] = values[1]; Source->Velocity[2] = values[2]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_DIRECTION: @@ -1332,6 +1352,9 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a Source->Direction[0] = values[0]; Source->Direction[1] = values[1]; Source->Direction[2] = values[2]; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_ORIENTATION: @@ -1410,6 +1433,9 @@ bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); Source->HeadRelative = values[0] != AL_FALSE; +#ifdef ALSOFT_EAX + Source->eax_commit(); +#endif // ALSOFT_EAX return UpdateSourceProps(Source, Context); case AL_LOOPING: @@ -3099,6 +3125,9 @@ START_API_FUNC cur = cur->mNext.load(std::memory_order_relaxed); } Voice *voice{GetSourceVoice(source, context.get())}; +#ifdef ALSOFT_EAX + auto eax_is_begins_to_play = false; +#endif // ALSOFT_EAX switch(GetSourceState(source, voice)) { case AL_PAUSED: @@ -3111,6 +3140,9 @@ START_API_FUNC cur->mSourceID = source->id; cur->mState = VChangeState::Play; source->state = AL_PLAYING; +#ifdef ALSOFT_EAX + eax_is_begins_to_play = true; +#endif // ALSOFT_EAX continue; case AL_PLAYING: @@ -3127,6 +3159,9 @@ START_API_FUNC default: assert(voice == nullptr); cur->mOldVoice = nullptr; +#ifdef ALSOFT_EAX + eax_is_begins_to_play = true; +#endif // ALSOFT_EAX break; } @@ -3173,6 +3208,11 @@ START_API_FUNC cur->mVoice = voice; cur->mSourceID = source->id; cur->mState = VChangeState::Play; + +#ifdef ALSOFT_EAX + if (eax_is_begins_to_play) + source->eax_commit(); +#endif // ALSOFT_EAX } if LIKELY(tail) SendVoiceChanges(context.get(), tail); @@ -3715,6 +3755,14 @@ void ALsource::eax_update( } } +void ALsource::eax_commit() +{ + if (!eax_is_initialized()) + return; + + eax_apply_deferred(); +} + ALsource* ALsource::eax_lookup_source( ALCcontext& al_context, ALuint source_id) noexcept diff --git a/al/source.h b/al/source.h index b2fea08b..0066b6b4 100644 --- a/al/source.h +++ b/al/source.h @@ -220,6 +220,8 @@ public: void eax_update( EaxContextSharedDirtyFlags dirty_flags); + void eax_commit(); + static ALsource* eax_lookup_source( ALCcontext& al_context, @@ -265,6 +267,8 @@ private: const char* message); + bool eax_is_initialized() const noexcept { return eax_al_context_; } + void eax_set_source_defaults() noexcept; void eax_set_active_fx_slots_defaults() noexcept; void eax_set_send_defaults(EAXSOURCEALLSENDPROPERTIES& eax_send) noexcept; |