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
:
144 const EaxEaxCall
& eax_call
) 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();
169 const EaxEaxCall
& eax_call
);
172 void validate_attack_time(
175 void validate_release_time(
176 float flReleaseTime
);
178 void validate_resonance(
181 void validate_peak_level(
185 const EAXAUTOWAHPROPERTIES
& eax_all
);
188 void defer_attack_time(
191 void defer_release_time(
192 float flReleaseTime
);
194 void defer_resonance(
197 void defer_peak_level(
201 const EAXAUTOWAHPROPERTIES
& eax_all
);
204 void defer_attack_time(
205 const EaxEaxCall
& eax_call
);
207 void defer_release_time(
208 const EaxEaxCall
& eax_call
);
210 void defer_resonance(
211 const EaxEaxCall
& eax_call
);
213 void defer_peak_level(
214 const EaxEaxCall
& eax_call
);
217 const EaxEaxCall
& eax_call
);
220 bool apply_deferred();
224 const EaxEaxCall
& eax_call
);
225 }; // EaxAutoWahEffect
228 class EaxAutoWahEffectException
:
232 explicit EaxAutoWahEffectException(
235 EaxException
{"EAX_AUTO_WAH_EFFECT", message
}
238 }; // EaxAutoWahEffectException
241 EaxAutoWahEffect::EaxAutoWahEffect()
242 : EaxEffect
{AL_EFFECT_AUTOWAH
}
249 bool EaxAutoWahEffect::dispatch(
250 const EaxEaxCall
& eax_call
)
252 return eax_call
.is_get() ? get(eax_call
) : set(eax_call
);
255 void EaxAutoWahEffect::set_eax_defaults()
257 eax_
.flAttackTime
= EAXAUTOWAH_DEFAULTATTACKTIME
;
258 eax_
.flReleaseTime
= EAXAUTOWAH_DEFAULTRELEASETIME
;
259 eax_
.lResonance
= EAXAUTOWAH_DEFAULTRESONANCE
;
260 eax_
.lPeakLevel
= EAXAUTOWAH_DEFAULTPEAKLEVEL
;
265 void EaxAutoWahEffect::set_efx_attack_time()
267 const auto attack_time
= clamp(
269 AL_AUTOWAH_MIN_ATTACK_TIME
,
270 AL_AUTOWAH_MAX_ATTACK_TIME
);
272 al_effect_props_
.Autowah
.AttackTime
= attack_time
;
275 void EaxAutoWahEffect::set_efx_release_time()
277 const auto release_time
= clamp(
279 AL_AUTOWAH_MIN_RELEASE_TIME
,
280 AL_AUTOWAH_MAX_RELEASE_TIME
);
282 al_effect_props_
.Autowah
.ReleaseTime
= release_time
;
285 void EaxAutoWahEffect::set_efx_resonance()
287 const auto resonance
= clamp(
288 level_mb_to_gain(static_cast<float>(eax_
.lResonance
)),
289 AL_AUTOWAH_MIN_RESONANCE
,
290 AL_AUTOWAH_MAX_RESONANCE
);
292 al_effect_props_
.Autowah
.Resonance
= resonance
;
295 void EaxAutoWahEffect::set_efx_peak_gain()
297 const auto peak_gain
= clamp(
298 level_mb_to_gain(static_cast<float>(eax_
.lPeakLevel
)),
299 AL_AUTOWAH_MIN_PEAK_GAIN
,
300 AL_AUTOWAH_MAX_PEAK_GAIN
);
302 al_effect_props_
.Autowah
.PeakGain
= peak_gain
;
305 void EaxAutoWahEffect::set_efx_defaults()
307 set_efx_attack_time();
308 set_efx_release_time();
313 bool EaxAutoWahEffect::get(
314 const EaxEaxCall
& eax_call
)
316 switch (eax_call
.get_property_id())
318 case EAXAUTOWAH_NONE
:
321 case EAXAUTOWAH_ALLPARAMETERS
:
322 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
);
325 case EAXAUTOWAH_ATTACKTIME
:
326 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.flAttackTime
);
329 case EAXAUTOWAH_RELEASETIME
:
330 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.flReleaseTime
);
333 case EAXAUTOWAH_RESONANCE
:
334 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.lResonance
);
337 case EAXAUTOWAH_PEAKLEVEL
:
338 eax_call
.set_value
<EaxAutoWahEffectException
>(eax_
.lPeakLevel
);
342 throw EaxAutoWahEffectException
{"Unsupported property id."};
348 void EaxAutoWahEffect::validate_attack_time(
351 eax_validate_range
<EaxAutoWahEffectException
>(
354 EAXAUTOWAH_MINATTACKTIME
,
355 EAXAUTOWAH_MAXATTACKTIME
);
358 void EaxAutoWahEffect::validate_release_time(
361 eax_validate_range
<EaxAutoWahEffectException
>(
364 EAXAUTOWAH_MINRELEASETIME
,
365 EAXAUTOWAH_MAXRELEASETIME
);
368 void EaxAutoWahEffect::validate_resonance(
371 eax_validate_range
<EaxAutoWahEffectException
>(
374 EAXAUTOWAH_MINRESONANCE
,
375 EAXAUTOWAH_MAXRESONANCE
);
378 void EaxAutoWahEffect::validate_peak_level(
381 eax_validate_range
<EaxAutoWahEffectException
>(
384 EAXAUTOWAH_MINPEAKLEVEL
,
385 EAXAUTOWAH_MAXPEAKLEVEL
);
388 void EaxAutoWahEffect::validate_all(
389 const EAXAUTOWAHPROPERTIES
& eax_all
)
391 validate_attack_time(eax_all
.flAttackTime
);
392 validate_release_time(eax_all
.flReleaseTime
);
393 validate_resonance(eax_all
.lResonance
);
394 validate_peak_level(eax_all
.lPeakLevel
);
397 void EaxAutoWahEffect::defer_attack_time(
400 eax_d_
.flAttackTime
= flAttackTime
;
401 eax_dirty_flags_
.flAttackTime
= (eax_
.flAttackTime
!= eax_d_
.flAttackTime
);
404 void EaxAutoWahEffect::defer_release_time(
407 eax_d_
.flReleaseTime
= flReleaseTime
;
408 eax_dirty_flags_
.flReleaseTime
= (eax_
.flReleaseTime
!= eax_d_
.flReleaseTime
);
411 void EaxAutoWahEffect::defer_resonance(
414 eax_d_
.lResonance
= lResonance
;
415 eax_dirty_flags_
.lResonance
= (eax_
.lResonance
!= eax_d_
.lResonance
);
418 void EaxAutoWahEffect::defer_peak_level(
421 eax_d_
.lPeakLevel
= lPeakLevel
;
422 eax_dirty_flags_
.lPeakLevel
= (eax_
.lPeakLevel
!= eax_d_
.lPeakLevel
);
425 void EaxAutoWahEffect::defer_all(
426 const EAXAUTOWAHPROPERTIES
& eax_all
)
428 validate_all(eax_all
);
430 defer_attack_time(eax_all
.flAttackTime
);
431 defer_release_time(eax_all
.flReleaseTime
);
432 defer_resonance(eax_all
.lResonance
);
433 defer_peak_level(eax_all
.lPeakLevel
);
436 void EaxAutoWahEffect::defer_attack_time(
437 const EaxEaxCall
& eax_call
)
439 const auto& attack_time
=
440 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::flAttackTime
)>();
442 validate_attack_time(attack_time
);
443 defer_attack_time(attack_time
);
446 void EaxAutoWahEffect::defer_release_time(
447 const EaxEaxCall
& eax_call
)
449 const auto& release_time
=
450 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::flReleaseTime
)>();
452 validate_release_time(release_time
);
453 defer_release_time(release_time
);
456 void EaxAutoWahEffect::defer_resonance(
457 const EaxEaxCall
& eax_call
)
459 const auto& resonance
=
460 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::lResonance
)>();
462 validate_resonance(resonance
);
463 defer_resonance(resonance
);
466 void EaxAutoWahEffect::defer_peak_level(
467 const EaxEaxCall
& eax_call
)
469 const auto& peak_level
=
470 eax_call
.get_value
<EaxAutoWahEffectException
, const decltype(EAXAUTOWAHPROPERTIES::lPeakLevel
)>();
472 validate_peak_level(peak_level
);
473 defer_peak_level(peak_level
);
476 void EaxAutoWahEffect::defer_all(
477 const EaxEaxCall
& eax_call
)
480 eax_call
.get_value
<EaxAutoWahEffectException
, const EAXAUTOWAHPROPERTIES
>();
487 bool EaxAutoWahEffect::apply_deferred()
489 if (eax_dirty_flags_
== EaxAutoWahEffectDirtyFlags
{})
496 if (eax_dirty_flags_
.flAttackTime
)
498 set_efx_attack_time();
501 if (eax_dirty_flags_
.flReleaseTime
)
503 set_efx_release_time();
506 if (eax_dirty_flags_
.lResonance
)
511 if (eax_dirty_flags_
.lPeakLevel
)
516 eax_dirty_flags_
= EaxAutoWahEffectDirtyFlags
{};
522 bool EaxAutoWahEffect::set(
523 const EaxEaxCall
& eax_call
)
525 switch (eax_call
.get_property_id())
527 case EAXAUTOWAH_NONE
:
530 case EAXAUTOWAH_ALLPARAMETERS
:
534 case EAXAUTOWAH_ATTACKTIME
:
535 defer_attack_time(eax_call
);
538 case EAXAUTOWAH_RELEASETIME
:
539 defer_release_time(eax_call
);
542 case EAXAUTOWAH_RESONANCE
:
543 defer_resonance(eax_call
);
546 case EAXAUTOWAH_PEAKLEVEL
:
547 defer_peak_level(eax_call
);
551 throw EaxAutoWahEffectException
{"Unsupported property id."};
554 if (!eax_call
.is_deferred())
556 return apply_deferred();
564 EaxEffectUPtr
eax_create_eax_auto_wah_effect()
566 return std::make_unique
<::EaxAutoWahEffect
>();