#ifndef AL_AUXEFFECTSLOT_H #define AL_AUXEFFECTSLOT_H #include #include #include "AL/al.h" #include "AL/alc.h" #include "AL/efx.h" #include "alc/device.h" #include "alc/effects/base.h" #include "almalloc.h" #include "atomic.h" #include "core/effectslot.h" #include "intrusive_ptr.h" #include "vector.h" #ifdef ALSOFT_EAX #include #include "eax/call.h" #include "eax/effect.h" #include "eax/fx_slot_index.h" #endif // ALSOFT_EAX struct ALbuffer; struct ALeffect; struct WetBuffer; enum class SlotState : ALenum { Initial = AL_INITIAL, Playing = AL_PLAYING, Stopped = AL_STOPPED, }; struct ALeffectslot { float Gain{1.0f}; bool AuxSendAuto{true}; ALeffectslot *Target{nullptr}; ALbuffer *Buffer{nullptr}; struct { EffectSlotType Type{EffectSlotType::None}; EffectProps Props{}; al::intrusive_ptr State; } Effect; bool mPropsDirty{true}; SlotState mState{SlotState::Initial}; RefCount ref{0u}; EffectSlot mSlot; /* Self ID */ ALuint id{}; ALeffectslot(); ALeffectslot(const ALeffectslot&) = delete; ALeffectslot& operator=(const ALeffectslot&) = delete; ~ALeffectslot(); ALenum initEffect(ALenum effectType, const EffectProps &effectProps, ALCcontext *context); void updateProps(ALCcontext *context); /* This can be new'd for the context's default effect slot. */ DEF_NEWDEL(ALeffectslot) #ifdef ALSOFT_EAX public: void eax_initialize( const EaxCall& call, ALCcontext& al_context, EaxFxSlotIndexValue index); const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept; // [[nodiscard]] bool eax_dispatch(const EaxCall& call) { return call.is_get() ? eax_get(call) : eax_set(call); } void eax_unlock_legacy() noexcept; void eax_commit() { eax_apply_deferred(); } private: ALCcontext* eax_al_context_{}; EaxFxSlotIndexValue eax_fx_slot_index_{}; EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{}; EaxEffectUPtr eax_effect_{}; bool eax_is_locked_{}; [[noreturn]] static void eax_fail( const char* message); GUID eax_get_eax_default_effect_guid() const noexcept; 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(const EaxCall& call); void eax_get_fx_slot_all(const EaxCall& call) const; void eax_get_fx_slot(const EaxCall& call) const; // [[nodiscard]] bool eax_get(const EaxCall& call); void eax_set_fx_slot_effect(const EaxCall& call, ALenum effect_type); void eax_set_fx_slot_effect(const EaxCall& call); void eax_set_efx_effect_slot_gain(); void eax_set_fx_slot_volume(); void eax_set_effect_slot_send_auto(); void eax_set_fx_slot_flags(); void eax_ensure_is_unlocked() const; void eax_validate_fx_slot_effect(const GUID& eax_effect_id); void eax_validate_fx_slot_volume(long eax_volume); void eax_validate_fx_slot_lock(long eax_lock); void eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags); void eax_validate_fx_slot_occlusion(long eax_occlusion); void eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio); void eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot); void eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot); void eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id); void eax_set_fx_slot_volume( long eax_volume); void eax_set_fx_slot_lock( long eax_lock); void eax_set_fx_slot_flags( unsigned long eax_flags); // [[nodiscard]] bool eax_set_fx_slot_occlusion( long eax_occlusion); // [[nodiscard]] bool eax_set_fx_slot_occlusion_lf_ratio( float eax_occlusion_lf_ratio); void eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot); // [[nodiscard]] bool eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot); void eax_defer_fx_slot_effect(const EaxCall& call); void eax_defer_fx_slot_volume(const EaxCall& call); void eax_defer_fx_slot_lock(const EaxCall& call); void eax_defer_fx_slot_flags(const EaxCall& call); // [[nodiscard]] bool eax_defer_fx_slot_occlusion(const EaxCall& call); // [[nodiscard]] bool eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call); // [[nodiscard]] bool eax_defer_fx_slot_all(const EaxCall& call); bool eax_set_fx_slot(const EaxCall& call); void eax_apply_deferred(); // [[nodiscard]] bool eax_set(const EaxCall& call); void eax_dispatch_effect(const EaxCall& call); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` void eax_set_effect_slot_effect(EaxEffect &effect); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)` void eax_set_effect_slot_send_auto(bool is_send_auto); // `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)` void eax_set_effect_slot_gain(ALfloat gain); public: class EaxDeleter { public: void operator()(ALeffectslot *effect_slot); }; // EaxAlEffectSlotDeleter #endif // ALSOFT_EAX }; void UpdateAllEffectSlotProps(ALCcontext *context); #ifdef ALSOFT_EAX using EaxAlEffectSlotUPtr = std::unique_ptr; EaxAlEffectSlotUPtr eax_create_al_effect_slot( ALCcontext& context); void eax_delete_al_effect_slot( ALCcontext& context, ALeffectslot& effect_slot); #endif // ALSOFT_EAX #endif