11 #include "alc/effects/base.h"
15 #include "alnumeric.h"
17 #include "al/eax_exception.h"
18 #include "al/eax_utils.h"
24 void Autowah_setParamf(EffectProps
*props
, ALenum param
, float val
)
28 case AL_AUTOWAH_ATTACK_TIME
:
29 if(!(val
>= AL_AUTOWAH_MIN_ATTACK_TIME
&& val
<= AL_AUTOWAH_MAX_ATTACK_TIME
))
30 throw effect_exception
{AL_INVALID_VALUE
, "Autowah attack time out of range"};
31 props
->Autowah
.AttackTime
= val
;
34 case AL_AUTOWAH_RELEASE_TIME
:
35 if(!(val
>= AL_AUTOWAH_MIN_RELEASE_TIME
&& val
<= AL_AUTOWAH_MAX_RELEASE_TIME
))
36 throw effect_exception
{AL_INVALID_VALUE
, "Autowah release time out of range"};
37 props
->Autowah
.ReleaseTime
= val
;
40 case AL_AUTOWAH_RESONANCE
:
41 if(!(val
>= AL_AUTOWAH_MIN_RESONANCE
&& val
<= AL_AUTOWAH_MAX_RESONANCE
))
42 throw effect_exception
{AL_INVALID_VALUE
, "Autowah resonance out of range"};
43 props
->Autowah
.Resonance
= val
;
46 case AL_AUTOWAH_PEAK_GAIN
:
47 if(!(val
>= AL_AUTOWAH_MIN_PEAK_GAIN
&& val
<= AL_AUTOWAH_MAX_PEAK_GAIN
))
48 throw effect_exception
{AL_INVALID_VALUE
, "Autowah peak gain out of range"};
49 props
->Autowah
.PeakGain
= val
;
53 throw effect_exception
{AL_INVALID_ENUM
, "Invalid autowah float property 0x%04x", param
};
56 void Autowah_setParamfv(EffectProps
*props
, ALenum param
, const float *vals
)
57 { Autowah_setParamf(props
, param
, vals
[0]); }
59 void Autowah_setParami(EffectProps
*, ALenum param
, int)
60 { throw effect_exception
{AL_INVALID_ENUM
, "Invalid autowah integer property 0x%04x", param
}; }
61 void Autowah_setParamiv(EffectProps
*, ALenum param
, const int*)
63 throw effect_exception
{AL_INVALID_ENUM
, "Invalid autowah integer vector property 0x%04x",
67 void Autowah_getParamf(const EffectProps
*props
, ALenum param
, float *val
)
71 case AL_AUTOWAH_ATTACK_TIME
:
72 *val
= props
->Autowah
.AttackTime
;
75 case AL_AUTOWAH_RELEASE_TIME
:
76 *val
= props
->Autowah
.ReleaseTime
;
79 case AL_AUTOWAH_RESONANCE
:
80 *val
= props
->Autowah
.Resonance
;
83 case AL_AUTOWAH_PEAK_GAIN
:
84 *val
= props
->Autowah
.PeakGain
;
88 throw effect_exception
{AL_INVALID_ENUM
, "Invalid autowah float property 0x%04x", param
};
92 void Autowah_getParamfv(const EffectProps
*props
, ALenum param
, float *vals
)
93 { Autowah_getParamf(props
, param
, vals
); }
95 void Autowah_getParami(const EffectProps
*, ALenum param
, int*)
96 { throw effect_exception
{AL_INVALID_ENUM
, "Invalid autowah integer property 0x%04x", param
}; }
97 void Autowah_getParamiv(const EffectProps
*, ALenum param
, int*)
99 throw effect_exception
{AL_INVALID_ENUM
, "Invalid autowah integer vector property 0x%04x",
103 EffectProps
genDefaultProps() noexcept
106 props
.Autowah
.AttackTime
= AL_AUTOWAH_DEFAULT_ATTACK_TIME
;
107 props
.Autowah
.ReleaseTime
= AL_AUTOWAH_DEFAULT_RELEASE_TIME
;
108 props
.Autowah
.Resonance
= AL_AUTOWAH_DEFAULT_RESONANCE
;
109 props
.Autowah
.PeakGain
= AL_AUTOWAH_DEFAULT_PEAK_GAIN
;
115 DEFINE_ALEFFECT_VTABLE(Autowah
);
117 const EffectProps AutowahEffectProps
{genDefaultProps()};
122 using EaxAutoWahEffectDirtyFlagsValue
= std::uint_least8_t;
124 struct EaxAutoWahEffectDirtyFlags
126 using EaxIsBitFieldStruct
= bool;
128 EaxAutoWahEffectDirtyFlagsValue flAttackTime
: 1;
129 EaxAutoWahEffectDirtyFlagsValue flReleaseTime
: 1;
130 EaxAutoWahEffectDirtyFlagsValue lResonance
: 1;
131 EaxAutoWahEffectDirtyFlagsValue lPeakLevel
: 1;
132 }; // EaxAutoWahEffectDirtyFlags
135 class EaxAutoWahEffect final
:
142 void dispatch(const EaxEaxCall
& eax_call
) override
;
145 bool apply_deferred() override
;
148 EAXAUTOWAHPROPERTIES eax_
{};
149 EAXAUTOWAHPROPERTIES eax_d_
{};
150 EaxAutoWahEffectDirtyFlags eax_dirty_flags_
{};
153 void set_eax_defaults();
156 void set_efx_attack_time();
158 void set_efx_release_time();
160 void set_efx_resonance();
162 void set_efx_peak_gain();
164 void set_efx_defaults();
167 void get(const EaxEaxCall
& eax_call
);
170 void validate_attack_time(
173 void validate_release_time(
174 float flReleaseTime
);
176 void validate_resonance(
179 void validate_peak_level(
183 const EAXAUTOWAHPROPERTIES
& eax_all
);
186 void defer_attack_time(
189 void defer_release_time(
190 float flReleaseTime
);
192 void defer_resonance(
195 void defer_peak_level(
199 const EAXAUTOWAHPROPERTIES
& eax_all
);
202 void defer_attack_time(
203 const EaxEaxCall
& eax_call
);
205 void defer_release_time(
206 const EaxEaxCall
& eax_call
);
208 void defer_resonance(
209 const EaxEaxCall
& eax_call
);
211 void defer_peak_level(
212 const EaxEaxCall
& eax_call
);
215 const EaxEaxCall
& eax_call
);
217 void set(const EaxEaxCall
& eax_call
);
218 }; // EaxAutoWahEffect
221 class EaxAutoWahEffectException
:
225 explicit EaxAutoWahEffectException(
228 EaxException
{"EAX_AUTO_WAH_EFFECT", message
}
231 }; // EaxAutoWahEffectException
234 EaxAutoWahEffect::EaxAutoWahEffect()
235 : EaxEffect
{AL_EFFECT_AUTOWAH
}
241 void EaxAutoWahEffect::dispatch(const EaxEaxCall
& eax_call
)
243 eax_call
.is_get() ? get(eax_call
) : set(eax_call
);
246 void EaxAutoWahEffect::set_eax_defaults()
248 eax_
.flAttackTime
= EAXAUTOWAH_DEFAULTATTACKTIME
;
249 eax_
.flReleaseTime
= EAXAUTOWAH_DEFAULTRELEASETIME
;
250 eax_
.lResonance
= EAXAUTOWAH_DEFAULTRESONANCE
;
251 eax_
.lPeakLevel
= EAXAUTOWAH_DEFAULTPEAKLEVEL
;
256 void EaxAutoWahEffect::set_efx_attack_time()
258 const auto attack_time
= clamp(
260 AL_AUTOWAH_MIN_ATTACK_TIME
,
261 AL_AUTOWAH_MAX_ATTACK_TIME
);
263 al_effect_props_
.Autowah
.AttackTime
= attack_time
;
266 void EaxAutoWahEffect::set_efx_release_time()
268 const auto release_time
= clamp(
270 AL_AUTOWAH_MIN_RELEASE_TIME
,
271 AL_AUTOWAH_MAX_RELEASE_TIME
);
273 al_effect_props_
.Autowah
.ReleaseTime
= release_time
;
276 void EaxAutoWahEffect::set_efx_resonance()
278 const auto resonance
= clamp(
279 level_mb_to_gain(static_cast<float>(eax_
.lResonance
)),
280 AL_AUTOWAH_MIN_RESONANCE
,
281 AL_AUTOWAH_MAX_RESONANCE
);
283 al_effect_props_
.Autowah
.Resonance
= resonance
;
286 void EaxAutoWahEffect::set_efx_peak_gain()
288 const auto peak_gain
= clamp(
289 level_mb_to_gain(static_cast<float>(eax_
.lPeakLevel
)),
290 AL_AUTOWAH_MIN_PEAK_GAIN
,
291 AL_AUTOWAH_MAX_PEAK_GAIN
);
293 al_effect_props_
.Autowah
.PeakGain
= peak_gain
;
296 void EaxAutoWahEffect::set_efx_defaults()
298 set_efx_attack_time();
299 set_efx_release_time();
304 void EaxAutoWahEffect::get(const EaxEaxCall
& eax_call
)
306 switch (eax_call
.get_property_id())
308 case EAXAUTOWAH_NONE
:
311 case EAXAUTOWAH_ALLPARAMETERS
:
312 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
);
315 case EAXAUTOWAH_ATTACKTIME
:
316 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.flAttackTime
);
319 case EAXAUTOWAH_RELEASETIME
:
320 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.flReleaseTime
);
323 case EAXAUTOWAH_RESONANCE
:
324 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.lResonance
);
327 case EAXAUTOWAH_PEAKLEVEL
:
328 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.lPeakLevel
);
332 throw EaxAutoWahEffectException
{"Unsupported property id."};
336 void EaxAutoWahEffect::validate_attack_time(
339 eax_validate_range
<EaxAutoWahEffectException
>(
342 EAXAUTOWAH_MINATTACKTIME
,
343 EAXAUTOWAH_MAXATTACKTIME
);
346 void EaxAutoWahEffect::validate_release_time(
349 eax_validate_range
<EaxAutoWahEffectException
>(
352 EAXAUTOWAH_MINRELEASETIME
,
353 EAXAUTOWAH_MAXRELEASETIME
);
356 void EaxAutoWahEffect::validate_resonance(
359 eax_validate_range
<EaxAutoWahEffectException
>(
362 EAXAUTOWAH_MINRESONANCE
,
363 EAXAUTOWAH_MAXRESONANCE
);
366 void EaxAutoWahEffect::validate_peak_level(
369 eax_validate_range
<EaxAutoWahEffectException
>(
372 EAXAUTOWAH_MINPEAKLEVEL
,
373 EAXAUTOWAH_MAXPEAKLEVEL
);
376 void EaxAutoWahEffect::validate_all(
377 const EAXAUTOWAHPROPERTIES
& eax_all
)
379 validate_attack_time(eax_all
.flAttackTime
);
380 validate_release_time(eax_all
.flReleaseTime
);
381 validate_resonance(eax_all
.lResonance
);
382 validate_peak_level(eax_all
.lPeakLevel
);
385 void EaxAutoWahEffect::defer_attack_time(
388 eax_d_
.flAttackTime
= flAttackTime
;
389 eax_dirty_flags_
.flAttackTime
= (eax_
.flAttackTime
!= eax_d_
.flAttackTime
);
392 void EaxAutoWahEffect::defer_release_time(
395 eax_d_
.flReleaseTime
= flReleaseTime
;
396 eax_dirty_flags_
.flReleaseTime
= (eax_
.flReleaseTime
!= eax_d_
.flReleaseTime
);
399 void EaxAutoWahEffect::defer_resonance(
402 eax_d_
.lResonance
= lResonance
;
403 eax_dirty_flags_
.lResonance
= (eax_
.lResonance
!= eax_d_
.lResonance
);
406 void EaxAutoWahEffect::defer_peak_level(
409 eax_d_
.lPeakLevel
= lPeakLevel
;
410 eax_dirty_flags_
.lPeakLevel
= (eax_
.lPeakLevel
!= eax_d_
.lPeakLevel
);
413 void EaxAutoWahEffect::defer_all(
414 const EAXAUTOWAHPROPERTIES
& eax_all
)
416 validate_all(eax_all
);
418 defer_attack_time(eax_all
.flAttackTime
);
419 defer_release_time(eax_all
.flReleaseTime
);
420 defer_resonance(eax_all
.lResonance
);
421 defer_peak_level(eax_all
.lPeakLevel
);
424 void EaxAutoWahEffect::defer_attack_time(
425 const EaxEaxCall
& eax_call
)
427 const auto& attack_time
=
428 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::flAttackTime
)>();
430 validate_attack_time(attack_time
);
431 defer_attack_time(attack_time
);
434 void EaxAutoWahEffect::defer_release_time(
435 const EaxEaxCall
& eax_call
)
437 const auto& release_time
=
438 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::flReleaseTime
)>();
440 validate_release_time(release_time
);
441 defer_release_time(release_time
);
444 void EaxAutoWahEffect::defer_resonance(
445 const EaxEaxCall
& eax_call
)
447 const auto& resonance
=
448 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::lResonance
)>();
450 validate_resonance(resonance
);
451 defer_resonance(resonance
);
454 void EaxAutoWahEffect::defer_peak_level(
455 const EaxEaxCall
& eax_call
)
457 const auto& peak_level
=
458 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::lPeakLevel
)>();
460 validate_peak_level(peak_level
);
461 defer_peak_level(peak_level
);
464 void EaxAutoWahEffect::defer_all(
465 const EaxEaxCall
& eax_call
)
468 eax_call
.get_value
<EaxAutoWahEffectException
, const EAXAUTOWAHPROPERTIES
>();
475 bool EaxAutoWahEffect::apply_deferred()
477 if (eax_dirty_flags_
== EaxAutoWahEffectDirtyFlags
{})
484 if (eax_dirty_flags_
.flAttackTime
)
486 set_efx_attack_time();
489 if (eax_dirty_flags_
.flReleaseTime
)
491 set_efx_release_time();
494 if (eax_dirty_flags_
.lResonance
)
499 if (eax_dirty_flags_
.lPeakLevel
)
504 eax_dirty_flags_
= EaxAutoWahEffectDirtyFlags
{};
509 void EaxAutoWahEffect::set(const EaxEaxCall
& eax_call
)
511 switch (eax_call
.get_property_id())
513 case EAXAUTOWAH_NONE
:
516 case EAXAUTOWAH_ALLPARAMETERS
:
520 case EAXAUTOWAH_ATTACKTIME
:
521 defer_attack_time(eax_call
);
524 case EAXAUTOWAH_RELEASETIME
:
525 defer_release_time(eax_call
);
528 case EAXAUTOWAH_RESONANCE
:
529 defer_resonance(eax_call
);
532 case EAXAUTOWAH_PEAKLEVEL
:
533 defer_peak_level(eax_call
);
537 throw EaxAutoWahEffectException
{"Unsupported property id."};
543 EaxEffectUPtr
eax_create_eax_auto_wah_effect()
545 return std::make_unique
<::EaxAutoWahEffect
>();