1 #ifndef EAX_EFFECT_INCLUDED
2 #define EAX_EFFECT_INCLUDED
12 #include "core/effects/base.h"
15 struct EaxEffectErrorMessages
{
16 static constexpr auto unknown_property_id() noexcept
{ return "Unknown property id."; }
17 static constexpr auto unknown_version() noexcept
{ return "Unknown version."; }
18 }; // EaxEffectErrorMessages
20 using EaxEffectProps
= std::variant
<std::monostate
,
24 EAXAGCCOMPRESSORPROPERTIES
,
25 EAXDISTORTIONPROPERTIES
,
27 EAXEQUALIZERPROPERTIES
,
29 EAXFREQUENCYSHIFTERPROPERTIES
,
30 EAXRINGMODULATORPROPERTIES
,
31 EAXPITCHSHIFTERPROPERTIES
,
32 EAXVOCALMORPHERPROPERTIES
>;
34 template<typename
... Ts
>
35 struct overloaded
: Ts
... { using Ts::operator()...; };
37 template<typename
... Ts
>
38 overloaded(Ts
...) -> overloaded
<Ts
...>;
40 constexpr ALenum
EnumFromEaxEffectType(const EaxEffectProps
&props
)
42 return std::visit(overloaded
{
43 [](const std::monostate
&) noexcept
{ return AL_EFFECT_NULL
; },
44 [](const EAXREVERBPROPERTIES
&) noexcept
{ return AL_EFFECT_EAXREVERB
; },
45 [](const EAXCHORUSPROPERTIES
&) noexcept
{ return AL_EFFECT_CHORUS
; },
46 [](const EAXAUTOWAHPROPERTIES
&) noexcept
{ return AL_EFFECT_AUTOWAH
; },
47 [](const EAXAGCCOMPRESSORPROPERTIES
&) noexcept
{ return AL_EFFECT_COMPRESSOR
; },
48 [](const EAXDISTORTIONPROPERTIES
&) noexcept
{ return AL_EFFECT_DISTORTION
; },
49 [](const EAXECHOPROPERTIES
&) noexcept
{ return AL_EFFECT_ECHO
; },
50 [](const EAXEQUALIZERPROPERTIES
&) noexcept
{ return AL_EFFECT_EQUALIZER
; },
51 [](const EAXFLANGERPROPERTIES
&) noexcept
{ return AL_EFFECT_FLANGER
; },
52 [](const EAXFREQUENCYSHIFTERPROPERTIES
&) noexcept
{ return AL_EFFECT_FREQUENCY_SHIFTER
; },
53 [](const EAXRINGMODULATORPROPERTIES
&) noexcept
{ return AL_EFFECT_RING_MODULATOR
; },
54 [](const EAXPITCHSHIFTERPROPERTIES
&) noexcept
{ return AL_EFFECT_PITCH_SHIFTER
; },
55 [](const EAXVOCALMORPHERPROPERTIES
&) noexcept
{ return AL_EFFECT_VOCAL_MORPHER
; }
59 struct EaxReverbCommitter
{
62 EaxReverbCommitter(EaxEffectProps
&eaxprops
, EffectProps
&alprops
)
63 : mEaxProps
{eaxprops
}, mAlProps
{alprops
}
66 EaxEffectProps
&mEaxProps
;
67 EffectProps
&mAlProps
;
69 [[noreturn
]] static void fail(const char* message
);
70 [[noreturn
]] static void fail_unknown_property_id()
71 { fail(EaxEffectErrorMessages::unknown_property_id()); }
73 template<typename TValidator
, typename TProperty
>
74 static void defer(const EaxCall
& call
, TProperty
& property
)
76 const auto& value
= call
.get_value
<Exception
, const TProperty
>();
81 template<typename TValidator
, typename TDeferrer
, typename TProperties
, typename TProperty
>
82 static void defer(const EaxCall
& call
, TProperties
& properties
, TProperty
&)
84 const auto& value
= call
.get_value
<Exception
, const TProperty
>();
86 TDeferrer
{}(properties
, value
);
89 template<typename TValidator
, typename TProperty
>
90 static void defer3(const EaxCall
& call
, EAXREVERBPROPERTIES
& properties
, TProperty
& property
)
92 const auto& value
= call
.get_value
<Exception
, const TProperty
>();
94 if (value
== property
)
97 properties
.ulEnvironment
= EAX_ENVIRONMENT_UNDEFINED
;
101 bool commit(const EAX_REVERBPROPERTIES
&props
);
102 bool commit(const EAX20LISTENERPROPERTIES
&props
);
103 bool commit(const EAXREVERBPROPERTIES
&props
);
105 static void SetDefaults(EAX_REVERBPROPERTIES
&props
);
106 static void SetDefaults(EAX20LISTENERPROPERTIES
&props
);
107 static void SetDefaults(EAXREVERBPROPERTIES
&props
);
108 static void SetDefaults(EaxEffectProps
&props
);
110 static void Get(const EaxCall
&call
, const EAX_REVERBPROPERTIES
&props
);
111 static void Get(const EaxCall
&call
, const EAX20LISTENERPROPERTIES
&props
);
112 static void Get(const EaxCall
&call
, const EAXREVERBPROPERTIES
&props
);
114 static void Set(const EaxCall
&call
, EAX_REVERBPROPERTIES
&props
);
115 static void Set(const EaxCall
&call
, EAX20LISTENERPROPERTIES
&props
);
116 static void Set(const EaxCall
&call
, EAXREVERBPROPERTIES
&props
);
118 static void translate(const EAX_REVERBPROPERTIES
& src
, EAXREVERBPROPERTIES
& dst
) noexcept
;
119 static void translate(const EAX20LISTENERPROPERTIES
& src
, EAXREVERBPROPERTIES
& dst
) noexcept
;
123 struct EaxCommitter
{
126 EaxCommitter(EaxEffectProps
&eaxprops
, EffectProps
&alprops
)
127 : mEaxProps
{eaxprops
}, mAlProps
{alprops
}
130 EaxEffectProps
&mEaxProps
;
131 EffectProps
&mAlProps
;
133 template<typename TValidator
, typename TProperty
>
134 static void defer(const EaxCall
& call
, TProperty
& property
)
136 const auto& value
= call
.get_value
<Exception
, const TProperty
>();
141 [[noreturn
]] static void fail(const char *message
);
142 [[noreturn
]] static void fail_unknown_property_id()
143 { fail(EaxEffectErrorMessages::unknown_property_id()); }
146 struct EaxAutowahCommitter
: public EaxCommitter
<EaxAutowahCommitter
> {
147 using EaxCommitter
<EaxAutowahCommitter
>::EaxCommitter
;
149 bool commit(const EAXAUTOWAHPROPERTIES
&props
);
151 static void SetDefaults(EaxEffectProps
&props
);
152 static void Get(const EaxCall
&call
, const EAXAUTOWAHPROPERTIES
&props
);
153 static void Set(const EaxCall
&call
, EAXAUTOWAHPROPERTIES
&props
);
155 struct EaxChorusCommitter
: public EaxCommitter
<EaxChorusCommitter
> {
156 using EaxCommitter
<EaxChorusCommitter
>::EaxCommitter
;
158 bool commit(const EAXCHORUSPROPERTIES
&props
);
160 static void SetDefaults(EaxEffectProps
&props
);
161 static void Get(const EaxCall
&call
, const EAXCHORUSPROPERTIES
&props
);
162 static void Set(const EaxCall
&call
, EAXCHORUSPROPERTIES
&props
);
164 struct EaxCompressorCommitter
: public EaxCommitter
<EaxCompressorCommitter
> {
165 using EaxCommitter
<EaxCompressorCommitter
>::EaxCommitter
;
167 bool commit(const EAXAGCCOMPRESSORPROPERTIES
&props
);
169 static void SetDefaults(EaxEffectProps
&props
);
170 static void Get(const EaxCall
&call
, const EAXAGCCOMPRESSORPROPERTIES
&props
);
171 static void Set(const EaxCall
&call
, EAXAGCCOMPRESSORPROPERTIES
&props
);
173 struct EaxDistortionCommitter
: public EaxCommitter
<EaxDistortionCommitter
> {
174 using EaxCommitter
<EaxDistortionCommitter
>::EaxCommitter
;
176 bool commit(const EAXDISTORTIONPROPERTIES
&props
);
178 static void SetDefaults(EaxEffectProps
&props
);
179 static void Get(const EaxCall
&call
, const EAXDISTORTIONPROPERTIES
&props
);
180 static void Set(const EaxCall
&call
, EAXDISTORTIONPROPERTIES
&props
);
182 struct EaxEchoCommitter
: public EaxCommitter
<EaxEchoCommitter
> {
183 using EaxCommitter
<EaxEchoCommitter
>::EaxCommitter
;
185 bool commit(const EAXECHOPROPERTIES
&props
);
187 static void SetDefaults(EaxEffectProps
&props
);
188 static void Get(const EaxCall
&call
, const EAXECHOPROPERTIES
&props
);
189 static void Set(const EaxCall
&call
, EAXECHOPROPERTIES
&props
);
191 struct EaxEqualizerCommitter
: public EaxCommitter
<EaxEqualizerCommitter
> {
192 using EaxCommitter
<EaxEqualizerCommitter
>::EaxCommitter
;
194 bool commit(const EAXEQUALIZERPROPERTIES
&props
);
196 static void SetDefaults(EaxEffectProps
&props
);
197 static void Get(const EaxCall
&call
, const EAXEQUALIZERPROPERTIES
&props
);
198 static void Set(const EaxCall
&call
, EAXEQUALIZERPROPERTIES
&props
);
200 struct EaxFlangerCommitter
: public EaxCommitter
<EaxFlangerCommitter
> {
201 using EaxCommitter
<EaxFlangerCommitter
>::EaxCommitter
;
203 bool commit(const EAXFLANGERPROPERTIES
&props
);
205 static void SetDefaults(EaxEffectProps
&props
);
206 static void Get(const EaxCall
&call
, const EAXFLANGERPROPERTIES
&props
);
207 static void Set(const EaxCall
&call
, EAXFLANGERPROPERTIES
&props
);
209 struct EaxFrequencyShifterCommitter
: public EaxCommitter
<EaxFrequencyShifterCommitter
> {
210 using EaxCommitter
<EaxFrequencyShifterCommitter
>::EaxCommitter
;
212 bool commit(const EAXFREQUENCYSHIFTERPROPERTIES
&props
);
214 static void SetDefaults(EaxEffectProps
&props
);
215 static void Get(const EaxCall
&call
, const EAXFREQUENCYSHIFTERPROPERTIES
&props
);
216 static void Set(const EaxCall
&call
, EAXFREQUENCYSHIFTERPROPERTIES
&props
);
218 struct EaxModulatorCommitter
: public EaxCommitter
<EaxModulatorCommitter
> {
219 using EaxCommitter
<EaxModulatorCommitter
>::EaxCommitter
;
221 bool commit(const EAXRINGMODULATORPROPERTIES
&props
);
223 static void SetDefaults(EaxEffectProps
&props
);
224 static void Get(const EaxCall
&call
, const EAXRINGMODULATORPROPERTIES
&props
);
225 static void Set(const EaxCall
&call
, EAXRINGMODULATORPROPERTIES
&props
);
227 struct EaxPitchShifterCommitter
: public EaxCommitter
<EaxPitchShifterCommitter
> {
228 using EaxCommitter
<EaxPitchShifterCommitter
>::EaxCommitter
;
230 bool commit(const EAXPITCHSHIFTERPROPERTIES
&props
);
232 static void SetDefaults(EaxEffectProps
&props
);
233 static void Get(const EaxCall
&call
, const EAXPITCHSHIFTERPROPERTIES
&props
);
234 static void Set(const EaxCall
&call
, EAXPITCHSHIFTERPROPERTIES
&props
);
236 struct EaxVocalMorpherCommitter
: public EaxCommitter
<EaxVocalMorpherCommitter
> {
237 using EaxCommitter
<EaxVocalMorpherCommitter
>::EaxCommitter
;
239 bool commit(const EAXVOCALMORPHERPROPERTIES
&props
);
241 static void SetDefaults(EaxEffectProps
&props
);
242 static void Get(const EaxCall
&call
, const EAXVOCALMORPHERPROPERTIES
&props
);
243 static void Set(const EaxCall
&call
, EAXVOCALMORPHERPROPERTIES
&props
);
245 struct EaxNullCommitter
: public EaxCommitter
<EaxNullCommitter
> {
246 using EaxCommitter
<EaxNullCommitter
>::EaxCommitter
;
248 bool commit(const std::monostate
&props
);
250 static void SetDefaults(EaxEffectProps
&props
);
251 static void Get(const EaxCall
&call
, const std::monostate
&props
);
252 static void Set(const EaxCall
&call
, std::monostate
&props
);
256 struct CommitterFromProps
{ };
258 template<> struct CommitterFromProps
<std::monostate
> { using type
= EaxNullCommitter
; };
259 template<> struct CommitterFromProps
<EAXREVERBPROPERTIES
> { using type
= EaxReverbCommitter
; };
260 template<> struct CommitterFromProps
<EAXCHORUSPROPERTIES
> { using type
= EaxChorusCommitter
; };
261 template<> struct CommitterFromProps
<EAXAGCCOMPRESSORPROPERTIES
> { using type
= EaxCompressorCommitter
; };
262 template<> struct CommitterFromProps
<EAXAUTOWAHPROPERTIES
> { using type
= EaxAutowahCommitter
; };
263 template<> struct CommitterFromProps
<EAXDISTORTIONPROPERTIES
> { using type
= EaxDistortionCommitter
; };
264 template<> struct CommitterFromProps
<EAXECHOPROPERTIES
> { using type
= EaxEchoCommitter
; };
265 template<> struct CommitterFromProps
<EAXEQUALIZERPROPERTIES
> { using type
= EaxEqualizerCommitter
; };
266 template<> struct CommitterFromProps
<EAXFLANGERPROPERTIES
> { using type
= EaxFlangerCommitter
; };
267 template<> struct CommitterFromProps
<EAXFREQUENCYSHIFTERPROPERTIES
> { using type
= EaxFrequencyShifterCommitter
; };
268 template<> struct CommitterFromProps
<EAXRINGMODULATORPROPERTIES
> { using type
= EaxModulatorCommitter
; };
269 template<> struct CommitterFromProps
<EAXPITCHSHIFTERPROPERTIES
> { using type
= EaxPitchShifterCommitter
; };
270 template<> struct CommitterFromProps
<EAXVOCALMORPHERPROPERTIES
> { using type
= EaxVocalMorpherCommitter
; };
273 using CommitterFor
= typename CommitterFromProps
<std::remove_cv_t
<std::remove_reference_t
<T
>>>::type
;
278 EaxEffect() noexcept
= default;
279 ~EaxEffect() = default;
281 ALenum al_effect_type_
{AL_EFFECT_NULL
};
282 EffectProps al_effect_props_
{};
284 using Props1
= EAX_REVERBPROPERTIES
;
285 using Props2
= EAX20LISTENERPROPERTIES
;
286 using Props3
= EAXREVERBPROPERTIES
;
287 using Props4
= EaxEffectProps
;
290 Props1 i
; // Immediate.
291 Props1 d
; // Deferred.
295 Props2 i
; // Immediate.
296 Props2 d
; // Deferred.
300 Props3 i
; // Immediate.
301 Props3 d
; // Deferred.
305 Props4 i
; // Immediate.
306 Props4 d
; // Deferred.
319 static void call_set_defaults(const ALenum altype
, EaxEffectProps
&props
)
323 case AL_EFFECT_EAXREVERB
: return EaxReverbCommitter::SetDefaults(props
);
324 case AL_EFFECT_CHORUS
: return EaxChorusCommitter::SetDefaults(props
);
325 case AL_EFFECT_AUTOWAH
: return EaxAutowahCommitter::SetDefaults(props
);
326 case AL_EFFECT_COMPRESSOR
: return EaxCompressorCommitter::SetDefaults(props
);
327 case AL_EFFECT_DISTORTION
: return EaxDistortionCommitter::SetDefaults(props
);
328 case AL_EFFECT_ECHO
: return EaxEchoCommitter::SetDefaults(props
);
329 case AL_EFFECT_EQUALIZER
: return EaxEqualizerCommitter::SetDefaults(props
);
330 case AL_EFFECT_FLANGER
: return EaxFlangerCommitter::SetDefaults(props
);
331 case AL_EFFECT_FREQUENCY_SHIFTER
: return EaxFrequencyShifterCommitter::SetDefaults(props
);
332 case AL_EFFECT_RING_MODULATOR
: return EaxModulatorCommitter::SetDefaults(props
);
333 case AL_EFFECT_PITCH_SHIFTER
: return EaxPitchShifterCommitter::SetDefaults(props
);
334 case AL_EFFECT_VOCAL_MORPHER
: return EaxVocalMorpherCommitter::SetDefaults(props
);
335 case AL_EFFECT_NULL
: break;
337 return EaxNullCommitter::SetDefaults(props
);
343 EaxReverbCommitter::SetDefaults(state1_
.d
);
344 state1_
.i
= state1_
.d
;
345 EaxReverbCommitter::SetDefaults(state2_
.d
);
346 state2_
.i
= state2_
.d
;
347 EaxReverbCommitter::SetDefaults(state3_
.d
);
348 state3_
.i
= state3_
.d
;
349 T::SetDefaults(state4_
.d
);
350 state4_
.i
= state4_
.d
;
351 T::SetDefaults(state5_
.d
);
352 state5_
.i
= state5_
.d
;
355 void set_defaults(int eax_version
, ALenum altype
)
359 case 1: EaxReverbCommitter::SetDefaults(state1_
.d
); break;
360 case 2: EaxReverbCommitter::SetDefaults(state2_
.d
); break;
361 case 3: EaxReverbCommitter::SetDefaults(state3_
.d
); break;
362 case 4: call_set_defaults(altype
, state4_
.d
); break;
363 case 5: call_set_defaults(altype
, state5_
.d
); break;
369 static void call_set(const EaxCall
&call
, EaxEffectProps
&props
)
371 return std::visit([&](auto &arg
)
372 { return CommitterFor
<decltype(arg
)>::Set(call
, arg
); },
376 void set(const EaxCall
&call
)
378 switch(call
.get_version())
380 case 1: EaxReverbCommitter::Set(call
, state1_
.d
); break;
381 case 2: EaxReverbCommitter::Set(call
, state2_
.d
); break;
382 case 3: EaxReverbCommitter::Set(call
, state3_
.d
); break;
383 case 4: call_set(call
, state4_
.d
); break;
384 case 5: call_set(call
, state5_
.d
); break;
390 static void call_get(const EaxCall
&call
, const EaxEffectProps
&props
)
392 return std::visit([&](auto &arg
)
393 { return CommitterFor
<decltype(arg
)>::Get(call
, arg
); },
397 void get(const EaxCall
&call
) const
399 switch(call
.get_version())
401 case 1: EaxReverbCommitter::Get(call
, state1_
.d
); break;
402 case 2: EaxReverbCommitter::Get(call
, state2_
.d
); break;
403 case 3: EaxReverbCommitter::Get(call
, state3_
.d
); break;
404 case 4: call_get(call
, state4_
.d
); break;
405 case 5: call_get(call
, state5_
.d
); break;
410 bool call_commit(const EaxEffectProps
&props
)
412 return std::visit([&](auto &arg
)
413 { return CommitterFor
<decltype(arg
)>{props_
, al_effect_props_
}.commit(arg
); },
417 bool commit(int eax_version
)
419 changed_
|= version_
!= eax_version
;
420 if(!changed_
) return false;
422 bool ret
{version_
!= eax_version
};
423 version_
= eax_version
;
429 state1_
.i
= state1_
.d
;
430 ret
|= EaxReverbCommitter
{props_
, al_effect_props_
}.commit(state1_
.d
);
433 state2_
.i
= state2_
.d
;
434 ret
|= EaxReverbCommitter
{props_
, al_effect_props_
}.commit(state2_
.d
);
437 state3_
.i
= state3_
.d
;
438 ret
|= EaxReverbCommitter
{props_
, al_effect_props_
}.commit(state3_
.d
);
441 state4_
.i
= state4_
.d
;
442 ret
|= call_commit(state4_
.d
);
445 state5_
.i
= state5_
.d
;
446 ret
|= call_commit(state5_
.d
);
449 al_effect_type_
= EnumFromEaxEffectType(props_
);
455 using EaxEffectUPtr
= std::unique_ptr
<EaxEffect
>;
457 #endif // !EAX_EFFECT_INCLUDED