7 #include "alc/effects/base.h"
11 #include "alnumeric.h"
13 #include "al/eax_exception.h"
14 #include "al/eax_utils.h"
20 static_assert(EchoMaxDelay
>= AL_ECHO_MAX_DELAY
, "Echo max delay too short");
21 static_assert(EchoMaxLRDelay
>= AL_ECHO_MAX_LRDELAY
, "Echo max left-right delay too short");
23 void Echo_setParami(EffectProps
*, ALenum param
, int)
24 { throw effect_exception
{AL_INVALID_ENUM
, "Invalid echo integer property 0x%04x", param
}; }
25 void Echo_setParamiv(EffectProps
*, ALenum param
, const int*)
26 { throw effect_exception
{AL_INVALID_ENUM
, "Invalid echo integer-vector property 0x%04x", param
}; }
27 void Echo_setParamf(EffectProps
*props
, ALenum param
, float val
)
32 if(!(val
>= AL_ECHO_MIN_DELAY
&& val
<= AL_ECHO_MAX_DELAY
))
33 throw effect_exception
{AL_INVALID_VALUE
, "Echo delay out of range"};
34 props
->Echo
.Delay
= val
;
38 if(!(val
>= AL_ECHO_MIN_LRDELAY
&& val
<= AL_ECHO_MAX_LRDELAY
))
39 throw effect_exception
{AL_INVALID_VALUE
, "Echo LR delay out of range"};
40 props
->Echo
.LRDelay
= val
;
44 if(!(val
>= AL_ECHO_MIN_DAMPING
&& val
<= AL_ECHO_MAX_DAMPING
))
45 throw effect_exception
{AL_INVALID_VALUE
, "Echo damping out of range"};
46 props
->Echo
.Damping
= val
;
49 case AL_ECHO_FEEDBACK
:
50 if(!(val
>= AL_ECHO_MIN_FEEDBACK
&& val
<= AL_ECHO_MAX_FEEDBACK
))
51 throw effect_exception
{AL_INVALID_VALUE
, "Echo feedback out of range"};
52 props
->Echo
.Feedback
= val
;
56 if(!(val
>= AL_ECHO_MIN_SPREAD
&& val
<= AL_ECHO_MAX_SPREAD
))
57 throw effect_exception
{AL_INVALID_VALUE
, "Echo spread out of range"};
58 props
->Echo
.Spread
= val
;
62 throw effect_exception
{AL_INVALID_ENUM
, "Invalid echo float property 0x%04x", param
};
65 void Echo_setParamfv(EffectProps
*props
, ALenum param
, const float *vals
)
66 { Echo_setParamf(props
, param
, vals
[0]); }
68 void Echo_getParami(const EffectProps
*, ALenum param
, int*)
69 { throw effect_exception
{AL_INVALID_ENUM
, "Invalid echo integer property 0x%04x", param
}; }
70 void Echo_getParamiv(const EffectProps
*, ALenum param
, int*)
71 { throw effect_exception
{AL_INVALID_ENUM
, "Invalid echo integer-vector property 0x%04x", param
}; }
72 void Echo_getParamf(const EffectProps
*props
, ALenum param
, float *val
)
77 *val
= props
->Echo
.Delay
;
81 *val
= props
->Echo
.LRDelay
;
85 *val
= props
->Echo
.Damping
;
88 case AL_ECHO_FEEDBACK
:
89 *val
= props
->Echo
.Feedback
;
93 *val
= props
->Echo
.Spread
;
97 throw effect_exception
{AL_INVALID_ENUM
, "Invalid echo float property 0x%04x", param
};
100 void Echo_getParamfv(const EffectProps
*props
, ALenum param
, float *vals
)
101 { Echo_getParamf(props
, param
, vals
); }
103 EffectProps
genDefaultProps() noexcept
106 props
.Echo
.Delay
= AL_ECHO_DEFAULT_DELAY
;
107 props
.Echo
.LRDelay
= AL_ECHO_DEFAULT_LRDELAY
;
108 props
.Echo
.Damping
= AL_ECHO_DEFAULT_DAMPING
;
109 props
.Echo
.Feedback
= AL_ECHO_DEFAULT_FEEDBACK
;
110 props
.Echo
.Spread
= AL_ECHO_DEFAULT_SPREAD
;
116 DEFINE_ALEFFECT_VTABLE(Echo
);
118 const EffectProps EchoEffectProps
{genDefaultProps()};
123 using EaxEchoEffectDirtyFlagsValue
= std::uint_least8_t;
125 struct EaxEchoEffectDirtyFlags
127 using EaxIsBitFieldStruct
= bool;
129 EaxEchoEffectDirtyFlagsValue flDelay
: 1;
130 EaxEchoEffectDirtyFlagsValue flLRDelay
: 1;
131 EaxEchoEffectDirtyFlagsValue flDamping
: 1;
132 EaxEchoEffectDirtyFlagsValue flFeedback
: 1;
133 EaxEchoEffectDirtyFlagsValue flSpread
: 1;
134 }; // EaxEchoEffectDirtyFlags
137 class EaxEchoEffect final
:
146 const EaxEaxCall
& eax_call
) override
;
150 EAXECHOPROPERTIES eax_
{};
151 EAXECHOPROPERTIES eax_d_
{};
152 EaxEchoEffectDirtyFlags eax_dirty_flags_
{};
155 void set_eax_defaults();
158 void set_efx_delay();
160 void set_efx_lr_delay();
162 void set_efx_damping();
164 void set_efx_feedback();
166 void set_efx_spread();
168 void set_efx_defaults();
173 const EaxEaxCall
& eax_call
);
179 void validate_lr_delay(
182 void validate_damping(
185 void validate_feedback(
188 void validate_spread(
192 const EAXECHOPROPERTIES
& all
);
211 const EAXECHOPROPERTIES
& all
);
215 const EaxEaxCall
& eax_call
);
218 const EaxEaxCall
& eax_call
);
221 const EaxEaxCall
& eax_call
);
224 const EaxEaxCall
& eax_call
);
227 const EaxEaxCall
& eax_call
);
230 const EaxEaxCall
& eax_call
);
233 bool apply_deferred();
236 const EaxEaxCall
& eax_call
);
240 class EaxEchoEffectException
:
244 explicit EaxEchoEffectException(
247 EaxException
{"EAX_ECHO_EFFECT", message
}
250 }; // EaxEchoEffectException
253 EaxEchoEffect::EaxEchoEffect()
254 : EaxEffect
{AL_EFFECT_ECHO
}
261 bool EaxEchoEffect::dispatch(
262 const EaxEaxCall
& eax_call
)
264 return eax_call
.is_get() ? get(eax_call
) : set(eax_call
);
267 void EaxEchoEffect::set_eax_defaults()
269 eax_
.flDelay
= EAXECHO_DEFAULTDELAY
;
270 eax_
.flLRDelay
= EAXECHO_DEFAULTLRDELAY
;
271 eax_
.flDamping
= EAXECHO_DEFAULTDAMPING
;
272 eax_
.flFeedback
= EAXECHO_DEFAULTFEEDBACK
;
273 eax_
.flSpread
= EAXECHO_DEFAULTSPREAD
;
278 void EaxEchoEffect::set_efx_delay()
280 const auto delay
= clamp(
285 al_effect_props_
.Echo
.Delay
= delay
;
288 void EaxEchoEffect::set_efx_lr_delay()
290 const auto lr_delay
= clamp(
293 AL_ECHO_MAX_LRDELAY
);
295 al_effect_props_
.Echo
.LRDelay
= lr_delay
;
298 void EaxEchoEffect::set_efx_damping()
300 const auto damping
= clamp(
303 AL_ECHO_MAX_DAMPING
);
305 al_effect_props_
.Echo
.Damping
= damping
;
308 void EaxEchoEffect::set_efx_feedback()
310 const auto feedback
= clamp(
312 AL_ECHO_MIN_FEEDBACK
,
313 AL_ECHO_MAX_FEEDBACK
);
315 al_effect_props_
.Echo
.Feedback
= feedback
;
318 void EaxEchoEffect::set_efx_spread()
320 const auto spread
= clamp(
325 al_effect_props_
.Echo
.Spread
= spread
;
328 void EaxEchoEffect::set_efx_defaults()
338 bool EaxEchoEffect::get(
339 const EaxEaxCall
& eax_call
)
341 switch (eax_call
.get_property_id())
346 case EAXECHO_ALLPARAMETERS
:
347 eax_call
.set_value
<EaxEchoEffectException
>(eax_
);
351 eax_call
.set_value
<EaxEchoEffectException
>(eax_
.flDelay
);
354 case EAXECHO_LRDELAY
:
355 eax_call
.set_value
<EaxEchoEffectException
>(eax_
.flLRDelay
);
358 case EAXECHO_DAMPING
:
359 eax_call
.set_value
<EaxEchoEffectException
>(eax_
.flDamping
);
362 case EAXECHO_FEEDBACK
:
363 eax_call
.set_value
<EaxEchoEffectException
>(eax_
.flFeedback
);
367 eax_call
.set_value
<EaxEchoEffectException
>(eax_
.flSpread
);
371 throw EaxEchoEffectException
{"Unsupported property id."};
377 void EaxEchoEffect::validate_delay(
380 eax_validate_range
<EaxEchoEffectException
>(
387 void EaxEchoEffect::validate_lr_delay(
390 eax_validate_range
<EaxEchoEffectException
>(
397 void EaxEchoEffect::validate_damping(
400 eax_validate_range
<EaxEchoEffectException
>(
407 void EaxEchoEffect::validate_feedback(
410 eax_validate_range
<EaxEchoEffectException
>(
414 EAXECHO_MAXFEEDBACK
);
417 void EaxEchoEffect::validate_spread(
420 eax_validate_range
<EaxEchoEffectException
>(
427 void EaxEchoEffect::validate_all(
428 const EAXECHOPROPERTIES
& all
)
430 validate_delay(all
.flDelay
);
431 validate_lr_delay(all
.flLRDelay
);
432 validate_damping(all
.flDamping
);
433 validate_feedback(all
.flFeedback
);
434 validate_spread(all
.flSpread
);
437 void EaxEchoEffect::defer_delay(
440 eax_d_
.flDelay
= flDelay
;
441 eax_dirty_flags_
.flDelay
= (eax_
.flDelay
!= eax_d_
.flDelay
);
444 void EaxEchoEffect::defer_lr_delay(
447 eax_d_
.flLRDelay
= flLRDelay
;
448 eax_dirty_flags_
.flLRDelay
= (eax_
.flLRDelay
!= eax_d_
.flLRDelay
);
451 void EaxEchoEffect::defer_damping(
454 eax_d_
.flDamping
= flDamping
;
455 eax_dirty_flags_
.flDamping
= (eax_
.flDamping
!= eax_d_
.flDamping
);
458 void EaxEchoEffect::defer_feedback(
461 eax_d_
.flFeedback
= flFeedback
;
462 eax_dirty_flags_
.flFeedback
= (eax_
.flFeedback
!= eax_d_
.flFeedback
);
465 void EaxEchoEffect::defer_spread(
468 eax_d_
.flSpread
= flSpread
;
469 eax_dirty_flags_
.flSpread
= (eax_
.flSpread
!= eax_d_
.flSpread
);
472 void EaxEchoEffect::defer_all(
473 const EAXECHOPROPERTIES
& all
)
475 defer_delay(all
.flDelay
);
476 defer_lr_delay(all
.flLRDelay
);
477 defer_damping(all
.flDamping
);
478 defer_feedback(all
.flFeedback
);
479 defer_spread(all
.flSpread
);
482 void EaxEchoEffect::defer_delay(
483 const EaxEaxCall
& eax_call
)
486 eax_call
.get_value
<EaxEchoEffectException
, const decltype(EAXECHOPROPERTIES::flDelay
)>();
488 validate_delay(delay
);
492 void EaxEchoEffect::defer_lr_delay(
493 const EaxEaxCall
& eax_call
)
495 const auto& lr_delay
=
496 eax_call
.get_value
<EaxEchoEffectException
, const decltype(EAXECHOPROPERTIES::flLRDelay
)>();
498 validate_lr_delay(lr_delay
);
499 defer_lr_delay(lr_delay
);
502 void EaxEchoEffect::defer_damping(
503 const EaxEaxCall
& eax_call
)
505 const auto& damping
=
506 eax_call
.get_value
<EaxEchoEffectException
, const decltype(EAXECHOPROPERTIES::flDamping
)>();
508 validate_damping(damping
);
509 defer_damping(damping
);
512 void EaxEchoEffect::defer_feedback(
513 const EaxEaxCall
& eax_call
)
515 const auto& feedback
=
516 eax_call
.get_value
<EaxEchoEffectException
, const decltype(EAXECHOPROPERTIES::flFeedback
)>();
518 validate_feedback(feedback
);
519 defer_feedback(feedback
);
522 void EaxEchoEffect::defer_spread(
523 const EaxEaxCall
& eax_call
)
526 eax_call
.get_value
<EaxEchoEffectException
, const decltype(EAXECHOPROPERTIES::flSpread
)>();
528 validate_spread(spread
);
529 defer_spread(spread
);
532 void EaxEchoEffect::defer_all(
533 const EaxEaxCall
& eax_call
)
536 eax_call
.get_value
<EaxEchoEffectException
, const EAXECHOPROPERTIES
>();
543 bool EaxEchoEffect::apply_deferred()
545 if (eax_dirty_flags_
== EaxEchoEffectDirtyFlags
{})
552 if (eax_dirty_flags_
.flDelay
)
557 if (eax_dirty_flags_
.flLRDelay
)
562 if (eax_dirty_flags_
.flDamping
)
567 if (eax_dirty_flags_
.flFeedback
)
572 if (eax_dirty_flags_
.flSpread
)
577 eax_dirty_flags_
= EaxEchoEffectDirtyFlags
{};
583 bool EaxEchoEffect::set(
584 const EaxEaxCall
& eax_call
)
586 switch (eax_call
.get_property_id())
591 case EAXECHO_ALLPARAMETERS
:
596 defer_delay(eax_call
);
599 case EAXECHO_LRDELAY
:
600 defer_lr_delay(eax_call
);
603 case EAXECHO_DAMPING
:
604 defer_damping(eax_call
);
607 case EAXECHO_FEEDBACK
:
608 defer_feedback(eax_call
);
612 defer_spread(eax_call
);
616 throw EaxEchoEffectException
{"Unsupported property id."};
619 if (!eax_call
.is_deferred())
621 return apply_deferred();
629 EaxEffectUPtr
eax_create_eax_echo_effect()
631 return std::make_unique
<EaxEchoEffect
>();