1 #ifndef AL_AUXEFFECTSLOT_H
2 #define AL_AUXEFFECTSLOT_H
11 #include "alc/device.h"
12 #include "alc/effects/base.h"
15 #include "core/effectslot.h"
16 #include "intrusive_ptr.h"
22 #include "eax/effect.h"
23 #include "eax/exception.h"
24 #include "eax/fx_slot_index.h"
25 #include "eax/utils.h"
33 class EaxFxSlotException
: public EaxException
{
35 explicit EaxFxSlotException(const char* message
)
36 : EaxException
{"EAX_FX_SLOT", message
}
41 enum class SlotState
: ALenum
{
49 bool AuxSendAuto
{true};
50 ALeffectslot
*Target
{nullptr};
51 ALbuffer
*Buffer
{nullptr};
54 EffectSlotType Type
{EffectSlotType::None
};
57 al::intrusive_ptr
<EffectState
> State
;
60 bool mPropsDirty
{true};
62 SlotState mState
{SlotState::Initial
};
66 EffectSlot
*mSlot
{nullptr};
71 ALeffectslot(ALCcontext
*context
);
72 ALeffectslot(const ALeffectslot
&) = delete;
73 ALeffectslot
& operator=(const ALeffectslot
&) = delete;
76 ALenum
initEffect(ALenum effectType
, const EffectProps
&effectProps
, ALCcontext
*context
);
77 void updateProps(ALCcontext
*context
);
79 /* This can be new'd for the context's default effect slot. */
80 DEF_NEWDEL(ALeffectslot
)
85 void eax_initialize(ALCcontext
& al_context
, EaxFxSlotIndexValue index
);
87 EaxFxSlotIndexValue
eax_get_index() const noexcept
{ return eax_fx_slot_index_
; }
88 const EAX50FXSLOTPROPERTIES
& eax_get_eax_fx_slot() const noexcept
91 // Returns `true` if all sources should be updated, or `false` otherwise.
92 bool eax_dispatch(const EaxCall
& call
)
93 { return call
.is_get() ? eax_get(call
) : eax_set(call
); }
98 static constexpr auto eax_load_effect_dirty_bit
= EaxDirtyFlags
{1} << 0;
99 static constexpr auto eax_volume_dirty_bit
= EaxDirtyFlags
{1} << 1;
100 static constexpr auto eax_lock_dirty_bit
= EaxDirtyFlags
{1} << 2;
101 static constexpr auto eax_flags_dirty_bit
= EaxDirtyFlags
{1} << 3;
102 static constexpr auto eax_occlusion_dirty_bit
= EaxDirtyFlags
{1} << 4;
103 static constexpr auto eax_occlusion_lf_ratio_dirty_bit
= EaxDirtyFlags
{1} << 5;
105 using Exception
= EaxFxSlotException
;
107 using Eax4Props
= EAX40FXSLOTPROPERTIES
;
110 Eax4Props i
; // Immediate.
113 using Eax5Props
= EAX50FXSLOTPROPERTIES
;
116 Eax5Props i
; // Immediate.
119 struct EaxRangeValidator
{
120 template<typename TValue
>
124 const TValue
& min_value
,
125 const TValue
& max_value
) const
127 eax_validate_range
<Exception
>(name
, value
, min_value
, max_value
);
131 struct Eax4GuidLoadEffectValidator
{
132 void operator()(const GUID
& guidLoadEffect
) const
134 if (guidLoadEffect
!= EAX_NULL_GUID
&&
135 guidLoadEffect
!= EAX_REVERB_EFFECT
&&
136 guidLoadEffect
!= EAX_AGCCOMPRESSOR_EFFECT
&&
137 guidLoadEffect
!= EAX_AUTOWAH_EFFECT
&&
138 guidLoadEffect
!= EAX_CHORUS_EFFECT
&&
139 guidLoadEffect
!= EAX_DISTORTION_EFFECT
&&
140 guidLoadEffect
!= EAX_ECHO_EFFECT
&&
141 guidLoadEffect
!= EAX_EQUALIZER_EFFECT
&&
142 guidLoadEffect
!= EAX_FLANGER_EFFECT
/*&&
143 guidLoadEffect != EAX_FREQUENCYSHIFTER_EFFECT &&
144 guidLoadEffect != EAX_VOCALMORPHER_EFFECT &&
145 guidLoadEffect != EAX_PITCHSHIFTER_EFFECT &&
146 guidLoadEffect != EAX_RINGMODULATOR_EFFECT*/)
148 eax_fail_unknown_effect_id();
153 struct Eax4VolumeValidator
{
154 void operator()(long lVolume
) const
160 EAXFXSLOT_MAXVOLUME
);
164 struct Eax4LockValidator
{
165 void operator()(long lLock
) const
175 struct Eax4FlagsValidator
{
176 void operator()(unsigned long ulFlags
) const
182 ~EAX40FXSLOTFLAGS_RESERVED
);
186 struct Eax4AllValidator
{
187 void operator()(const EAX40FXSLOTPROPERTIES
& all
) const
189 Eax4GuidLoadEffectValidator
{}(all
.guidLoadEffect
);
190 Eax4VolumeValidator
{}(all
.lVolume
);
191 Eax4LockValidator
{}(all
.lLock
);
192 Eax4FlagsValidator
{}(all
.ulFlags
);
196 struct Eax5OcclusionValidator
{
197 void operator()(long lOcclusion
) const
202 EAXFXSLOT_MINOCCLUSION
,
203 EAXFXSLOT_MAXOCCLUSION
);
207 struct Eax5OcclusionLfRatioValidator
{
208 void operator()(float flOcclusionLFRatio
) const
211 "Occlusion LF Ratio",
213 EAXFXSLOT_MINOCCLUSIONLFRATIO
,
214 EAXFXSLOT_MAXOCCLUSIONLFRATIO
);
218 struct Eax5FlagsValidator
{
219 void operator()(unsigned long ulFlags
) const
225 ~EAX50FXSLOTFLAGS_RESERVED
);
229 struct Eax5AllValidator
{
230 void operator()(const EAX50FXSLOTPROPERTIES
& all
) const
232 Eax4AllValidator
{}(static_cast<const EAX40FXSLOTPROPERTIES
&>(all
));
233 Eax5OcclusionValidator
{}(all
.lOcclusion
);
234 Eax5OcclusionLfRatioValidator
{}(all
.flOcclusionLFRatio
);
238 ALCcontext
* eax_al_context_
{};
239 EaxFxSlotIndexValue eax_fx_slot_index_
{};
240 int eax_version_
{}; // Current EAX version.
241 EaxDirtyFlags eax_df_
{}; // Dirty flags for the current EAX version.
242 EaxEffectUPtr eax_effect_
{};
243 Eax5State eax123_
{}; // EAX1/EAX2/EAX3 state.
244 Eax4State eax4_
{}; // EAX4 state.
245 Eax5State eax5_
{}; // EAX5 state.
246 Eax5Props eax_
{}; // Current EAX state.
248 [[noreturn
]] static void eax_fail(const char* message
);
249 [[noreturn
]] static void eax_fail_unknown_effect_id();
250 [[noreturn
]] static void eax_fail_unknown_property_id();
251 [[noreturn
]] static void eax_fail_unknown_version();
253 // Gets a new value from EAX call,
255 // sets a dirty flag only if the new value differs form the old one,
256 // and assigns the new value.
257 template<typename TValidator
, EaxDirtyFlags TDirtyBit
, typename TProperties
>
258 static void eax_fx_slot_set(const EaxCall
& call
, TProperties
& dst
, EaxDirtyFlags
& dirty_flags
)
260 const auto& src
= call
.get_value
<Exception
, const TProperties
>();
262 dirty_flags
|= (dst
!= src
? TDirtyBit
: EaxDirtyFlags
{});
266 // Gets a new value from EAX call,
268 // sets a dirty flag without comparing the values,
269 // and assigns the new value.
270 template<typename TValidator
, EaxDirtyFlags TDirtyBit
, typename TProperties
>
271 static void eax_fx_slot_set_dirty(const EaxCall
& call
, TProperties
& dst
,
272 EaxDirtyFlags
& dirty_flags
)
274 const auto& src
= call
.get_value
<Exception
, const TProperties
>();
276 dirty_flags
|= TDirtyBit
;
280 constexpr bool eax4_fx_slot_is_legacy() const noexcept
281 { return eax_fx_slot_index_
< 2; }
283 void eax4_fx_slot_ensure_unlocked() const;
285 static ALenum
eax_get_efx_effect_type(const GUID
& guid
);
286 const GUID
& eax_get_eax_default_effect_guid() const noexcept
;
287 long eax_get_eax_default_lock() const noexcept
;
289 void eax4_fx_slot_set_defaults(Eax4Props
& props
) noexcept
;
290 void eax5_fx_slot_set_defaults(Eax5Props
& props
) noexcept
;
291 void eax4_fx_slot_set_current_defaults(const Eax4Props
& props
) noexcept
;
292 void eax5_fx_slot_set_current_defaults(const Eax5Props
& props
) noexcept
;
293 void eax_fx_slot_set_current_defaults();
294 void eax_fx_slot_set_defaults();
296 void eax4_fx_slot_get(const EaxCall
& call
, const Eax4Props
& props
) const;
297 void eax5_fx_slot_get(const EaxCall
& call
, const Eax5Props
& props
) const;
298 void eax_fx_slot_get(const EaxCall
& call
) const;
299 // Returns `true` if all sources should be updated, or `false` otherwise.
300 bool eax_get(const EaxCall
& call
);
302 void eax_fx_slot_load_effect(int version
, ALenum altype
);
303 void eax_fx_slot_set_volume();
304 void eax_fx_slot_set_environment_flag();
305 void eax_fx_slot_set_flags();
307 void eax4_fx_slot_set_all(const EaxCall
& call
);
308 void eax5_fx_slot_set_all(const EaxCall
& call
);
310 bool eax_fx_slot_should_update_sources() const noexcept
;
312 // Returns `true` if all sources should be updated, or `false` otherwise.
313 bool eax4_fx_slot_set(const EaxCall
& call
);
314 // Returns `true` if all sources should be updated, or `false` otherwise.
315 bool eax5_fx_slot_set(const EaxCall
& call
);
316 // Returns `true` if all sources should be updated, or `false` otherwise.
317 bool eax_fx_slot_set(const EaxCall
& call
);
318 // Returns `true` if all sources should be updated, or `false` otherwise.
319 bool eax_set(const EaxCall
& call
);
322 EaxDirtyFlags TDirtyBit
,
323 typename TMemberResult
,
326 void eax_fx_slot_commit_property(TState
& state
, EaxDirtyFlags
& dst_df
,
327 TMemberResult
TProps::*member
) noexcept
329 auto& src_i
= state
.i
;
332 if((eax_df_
& TDirtyBit
) != EaxDirtyFlags
{})
335 dst_i
.*member
= src_i
.*member
;
339 void eax4_fx_slot_commit(EaxDirtyFlags
& dst_df
);
340 void eax5_fx_slot_commit(Eax5State
& state
, EaxDirtyFlags
& dst_df
);
342 // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)`
343 void eax_set_efx_slot_effect(EaxEffect
&effect
);
345 // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)`
346 void eax_set_efx_slot_send_auto(bool is_send_auto
);
348 // `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)`
349 void eax_set_efx_slot_gain(ALfloat gain
);
354 void operator()(ALeffectslot
*effect_slot
);
359 void UpdateAllEffectSlotProps(ALCcontext
*context
);
362 using EaxAlEffectSlotUPtr
= std::unique_ptr
<ALeffectslot
, ALeffectslot::EaxDeleter
>;
364 EaxAlEffectSlotUPtr
eax_create_al_effect_slot(ALCcontext
& context
);
365 void eax_delete_al_effect_slot(ALCcontext
& context
, ALeffectslot
& effect_slot
);