9 #include "alc/effects/base.h"
10 #include "aloptional.h"
11 #include "core/logging.h"
16 #include "alnumeric.h"
17 #include "al/eax/exception.h"
18 #include "al/eax/utils.h"
24 static_assert(ChorusMaxDelay
>= AL_CHORUS_MAX_DELAY
, "Chorus max delay too small");
25 static_assert(FlangerMaxDelay
>= AL_FLANGER_MAX_DELAY
, "Flanger max delay too small");
27 static_assert(AL_CHORUS_WAVEFORM_SINUSOID
== AL_FLANGER_WAVEFORM_SINUSOID
, "Chorus/Flanger waveform value mismatch");
28 static_assert(AL_CHORUS_WAVEFORM_TRIANGLE
== AL_FLANGER_WAVEFORM_TRIANGLE
, "Chorus/Flanger waveform value mismatch");
30 inline al::optional
<ChorusWaveform
> WaveformFromEnum(ALenum type
)
34 case AL_CHORUS_WAVEFORM_SINUSOID
: return ChorusWaveform::Sinusoid
;
35 case AL_CHORUS_WAVEFORM_TRIANGLE
: return ChorusWaveform::Triangle
;
39 inline ALenum
EnumFromWaveform(ChorusWaveform type
)
43 case ChorusWaveform::Sinusoid
: return AL_CHORUS_WAVEFORM_SINUSOID
;
44 case ChorusWaveform::Triangle
: return AL_CHORUS_WAVEFORM_TRIANGLE
;
46 throw std::runtime_error
{"Invalid chorus waveform: "+std::to_string(static_cast<int>(type
))};
49 void Chorus_setParami(EffectProps
*props
, ALenum param
, int val
)
53 case AL_CHORUS_WAVEFORM
:
54 if(auto formopt
= WaveformFromEnum(val
))
55 props
->Chorus
.Waveform
= *formopt
;
57 throw effect_exception
{AL_INVALID_VALUE
, "Invalid chorus waveform: 0x%04x", val
};
61 if(!(val
>= AL_CHORUS_MIN_PHASE
&& val
<= AL_CHORUS_MAX_PHASE
))
62 throw effect_exception
{AL_INVALID_VALUE
, "Chorus phase out of range: %d", val
};
63 props
->Chorus
.Phase
= val
;
67 throw effect_exception
{AL_INVALID_ENUM
, "Invalid chorus integer property 0x%04x", param
};
70 void Chorus_setParamiv(EffectProps
*props
, ALenum param
, const int *vals
)
71 { Chorus_setParami(props
, param
, vals
[0]); }
72 void Chorus_setParamf(EffectProps
*props
, ALenum param
, float val
)
77 if(!(val
>= AL_CHORUS_MIN_RATE
&& val
<= AL_CHORUS_MAX_RATE
))
78 throw effect_exception
{AL_INVALID_VALUE
, "Chorus rate out of range: %f", val
};
79 props
->Chorus
.Rate
= val
;
83 if(!(val
>= AL_CHORUS_MIN_DEPTH
&& val
<= AL_CHORUS_MAX_DEPTH
))
84 throw effect_exception
{AL_INVALID_VALUE
, "Chorus depth out of range: %f", val
};
85 props
->Chorus
.Depth
= val
;
88 case AL_CHORUS_FEEDBACK
:
89 if(!(val
>= AL_CHORUS_MIN_FEEDBACK
&& val
<= AL_CHORUS_MAX_FEEDBACK
))
90 throw effect_exception
{AL_INVALID_VALUE
, "Chorus feedback out of range: %f", val
};
91 props
->Chorus
.Feedback
= val
;
95 if(!(val
>= AL_CHORUS_MIN_DELAY
&& val
<= AL_CHORUS_MAX_DELAY
))
96 throw effect_exception
{AL_INVALID_VALUE
, "Chorus delay out of range: %f", val
};
97 props
->Chorus
.Delay
= val
;
101 throw effect_exception
{AL_INVALID_ENUM
, "Invalid chorus float property 0x%04x", param
};
104 void Chorus_setParamfv(EffectProps
*props
, ALenum param
, const float *vals
)
105 { Chorus_setParamf(props
, param
, vals
[0]); }
107 void Chorus_getParami(const EffectProps
*props
, ALenum param
, int *val
)
111 case AL_CHORUS_WAVEFORM
:
112 *val
= EnumFromWaveform(props
->Chorus
.Waveform
);
115 case AL_CHORUS_PHASE
:
116 *val
= props
->Chorus
.Phase
;
120 throw effect_exception
{AL_INVALID_ENUM
, "Invalid chorus integer property 0x%04x", param
};
123 void Chorus_getParamiv(const EffectProps
*props
, ALenum param
, int *vals
)
124 { Chorus_getParami(props
, param
, vals
); }
125 void Chorus_getParamf(const EffectProps
*props
, ALenum param
, float *val
)
130 *val
= props
->Chorus
.Rate
;
133 case AL_CHORUS_DEPTH
:
134 *val
= props
->Chorus
.Depth
;
137 case AL_CHORUS_FEEDBACK
:
138 *val
= props
->Chorus
.Feedback
;
141 case AL_CHORUS_DELAY
:
142 *val
= props
->Chorus
.Delay
;
146 throw effect_exception
{AL_INVALID_ENUM
, "Invalid chorus float property 0x%04x", param
};
149 void Chorus_getParamfv(const EffectProps
*props
, ALenum param
, float *vals
)
150 { Chorus_getParamf(props
, param
, vals
); }
152 EffectProps
genDefaultChorusProps() noexcept
155 props
.Chorus
.Waveform
= *WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM
);
156 props
.Chorus
.Phase
= AL_CHORUS_DEFAULT_PHASE
;
157 props
.Chorus
.Rate
= AL_CHORUS_DEFAULT_RATE
;
158 props
.Chorus
.Depth
= AL_CHORUS_DEFAULT_DEPTH
;
159 props
.Chorus
.Feedback
= AL_CHORUS_DEFAULT_FEEDBACK
;
160 props
.Chorus
.Delay
= AL_CHORUS_DEFAULT_DELAY
;
165 void Flanger_setParami(EffectProps
*props
, ALenum param
, int val
)
169 case AL_FLANGER_WAVEFORM
:
170 if(auto formopt
= WaveformFromEnum(val
))
171 props
->Chorus
.Waveform
= *formopt
;
173 throw effect_exception
{AL_INVALID_VALUE
, "Invalid flanger waveform: 0x%04x", val
};
176 case AL_FLANGER_PHASE
:
177 if(!(val
>= AL_FLANGER_MIN_PHASE
&& val
<= AL_FLANGER_MAX_PHASE
))
178 throw effect_exception
{AL_INVALID_VALUE
, "Flanger phase out of range: %d", val
};
179 props
->Chorus
.Phase
= val
;
183 throw effect_exception
{AL_INVALID_ENUM
, "Invalid flanger integer property 0x%04x", param
};
186 void Flanger_setParamiv(EffectProps
*props
, ALenum param
, const int *vals
)
187 { Flanger_setParami(props
, param
, vals
[0]); }
188 void Flanger_setParamf(EffectProps
*props
, ALenum param
, float val
)
192 case AL_FLANGER_RATE
:
193 if(!(val
>= AL_FLANGER_MIN_RATE
&& val
<= AL_FLANGER_MAX_RATE
))
194 throw effect_exception
{AL_INVALID_VALUE
, "Flanger rate out of range: %f", val
};
195 props
->Chorus
.Rate
= val
;
198 case AL_FLANGER_DEPTH
:
199 if(!(val
>= AL_FLANGER_MIN_DEPTH
&& val
<= AL_FLANGER_MAX_DEPTH
))
200 throw effect_exception
{AL_INVALID_VALUE
, "Flanger depth out of range: %f", val
};
201 props
->Chorus
.Depth
= val
;
204 case AL_FLANGER_FEEDBACK
:
205 if(!(val
>= AL_FLANGER_MIN_FEEDBACK
&& val
<= AL_FLANGER_MAX_FEEDBACK
))
206 throw effect_exception
{AL_INVALID_VALUE
, "Flanger feedback out of range: %f", val
};
207 props
->Chorus
.Feedback
= val
;
210 case AL_FLANGER_DELAY
:
211 if(!(val
>= AL_FLANGER_MIN_DELAY
&& val
<= AL_FLANGER_MAX_DELAY
))
212 throw effect_exception
{AL_INVALID_VALUE
, "Flanger delay out of range: %f", val
};
213 props
->Chorus
.Delay
= val
;
217 throw effect_exception
{AL_INVALID_ENUM
, "Invalid flanger float property 0x%04x", param
};
220 void Flanger_setParamfv(EffectProps
*props
, ALenum param
, const float *vals
)
221 { Flanger_setParamf(props
, param
, vals
[0]); }
223 void Flanger_getParami(const EffectProps
*props
, ALenum param
, int *val
)
227 case AL_FLANGER_WAVEFORM
:
228 *val
= EnumFromWaveform(props
->Chorus
.Waveform
);
231 case AL_FLANGER_PHASE
:
232 *val
= props
->Chorus
.Phase
;
236 throw effect_exception
{AL_INVALID_ENUM
, "Invalid flanger integer property 0x%04x", param
};
239 void Flanger_getParamiv(const EffectProps
*props
, ALenum param
, int *vals
)
240 { Flanger_getParami(props
, param
, vals
); }
241 void Flanger_getParamf(const EffectProps
*props
, ALenum param
, float *val
)
245 case AL_FLANGER_RATE
:
246 *val
= props
->Chorus
.Rate
;
249 case AL_FLANGER_DEPTH
:
250 *val
= props
->Chorus
.Depth
;
253 case AL_FLANGER_FEEDBACK
:
254 *val
= props
->Chorus
.Feedback
;
257 case AL_FLANGER_DELAY
:
258 *val
= props
->Chorus
.Delay
;
262 throw effect_exception
{AL_INVALID_ENUM
, "Invalid flanger float property 0x%04x", param
};
265 void Flanger_getParamfv(const EffectProps
*props
, ALenum param
, float *vals
)
266 { Flanger_getParamf(props
, param
, vals
); }
268 EffectProps
genDefaultFlangerProps() noexcept
271 props
.Chorus
.Waveform
= *WaveformFromEnum(AL_FLANGER_DEFAULT_WAVEFORM
);
272 props
.Chorus
.Phase
= AL_FLANGER_DEFAULT_PHASE
;
273 props
.Chorus
.Rate
= AL_FLANGER_DEFAULT_RATE
;
274 props
.Chorus
.Depth
= AL_FLANGER_DEFAULT_DEPTH
;
275 props
.Chorus
.Feedback
= AL_FLANGER_DEFAULT_FEEDBACK
;
276 props
.Chorus
.Delay
= AL_FLANGER_DEFAULT_DELAY
;
282 DEFINE_ALEFFECT_VTABLE(Chorus
);
284 const EffectProps ChorusEffectProps
{genDefaultChorusProps()};
286 DEFINE_ALEFFECT_VTABLE(Flanger
);
288 const EffectProps FlangerEffectProps
{genDefaultFlangerProps()};
294 struct EaxChorusTraits
{
295 using Props
= EAXCHORUSPROPERTIES
;
296 using Committer
= EaxChorusCommitter
;
297 static constexpr auto Field
= &EaxEffectProps::mChorus
;
299 static constexpr auto eax_effect_type() { return EaxEffectType::Chorus
; }
300 static constexpr auto efx_effect() { return AL_EFFECT_CHORUS
; }
302 static constexpr auto eax_none_param_id() { return EAXCHORUS_NONE
; }
303 static constexpr auto eax_allparameters_param_id() { return EAXCHORUS_ALLPARAMETERS
; }
304 static constexpr auto eax_waveform_param_id() { return EAXCHORUS_WAVEFORM
; }
305 static constexpr auto eax_phase_param_id() { return EAXCHORUS_PHASE
; }
306 static constexpr auto eax_rate_param_id() { return EAXCHORUS_RATE
; }
307 static constexpr auto eax_depth_param_id() { return EAXCHORUS_DEPTH
; }
308 static constexpr auto eax_feedback_param_id() { return EAXCHORUS_FEEDBACK
; }
309 static constexpr auto eax_delay_param_id() { return EAXCHORUS_DELAY
; }
311 static constexpr auto eax_min_waveform() { return EAXCHORUS_MINWAVEFORM
; }
312 static constexpr auto eax_min_phase() { return EAXCHORUS_MINPHASE
; }
313 static constexpr auto eax_min_rate() { return EAXCHORUS_MINRATE
; }
314 static constexpr auto eax_min_depth() { return EAXCHORUS_MINDEPTH
; }
315 static constexpr auto eax_min_feedback() { return EAXCHORUS_MINFEEDBACK
; }
316 static constexpr auto eax_min_delay() { return EAXCHORUS_MINDELAY
; }
318 static constexpr auto eax_max_waveform() { return EAXCHORUS_MAXWAVEFORM
; }
319 static constexpr auto eax_max_phase() { return EAXCHORUS_MAXPHASE
; }
320 static constexpr auto eax_max_rate() { return EAXCHORUS_MAXRATE
; }
321 static constexpr auto eax_max_depth() { return EAXCHORUS_MAXDEPTH
; }
322 static constexpr auto eax_max_feedback() { return EAXCHORUS_MAXFEEDBACK
; }
323 static constexpr auto eax_max_delay() { return EAXCHORUS_MAXDELAY
; }
325 static constexpr auto eax_default_waveform() { return EAXCHORUS_DEFAULTWAVEFORM
; }
326 static constexpr auto eax_default_phase() { return EAXCHORUS_DEFAULTPHASE
; }
327 static constexpr auto eax_default_rate() { return EAXCHORUS_DEFAULTRATE
; }
328 static constexpr auto eax_default_depth() { return EAXCHORUS_DEFAULTDEPTH
; }
329 static constexpr auto eax_default_feedback() { return EAXCHORUS_DEFAULTFEEDBACK
; }
330 static constexpr auto eax_default_delay() { return EAXCHORUS_DEFAULTDELAY
; }
332 static constexpr auto efx_min_waveform() { return AL_CHORUS_MIN_WAVEFORM
; }
333 static constexpr auto efx_min_phase() { return AL_CHORUS_MIN_PHASE
; }
334 static constexpr auto efx_min_rate() { return AL_CHORUS_MIN_RATE
; }
335 static constexpr auto efx_min_depth() { return AL_CHORUS_MIN_DEPTH
; }
336 static constexpr auto efx_min_feedback() { return AL_CHORUS_MIN_FEEDBACK
; }
337 static constexpr auto efx_min_delay() { return AL_CHORUS_MIN_DELAY
; }
339 static constexpr auto efx_max_waveform() { return AL_CHORUS_MAX_WAVEFORM
; }
340 static constexpr auto efx_max_phase() { return AL_CHORUS_MAX_PHASE
; }
341 static constexpr auto efx_max_rate() { return AL_CHORUS_MAX_RATE
; }
342 static constexpr auto efx_max_depth() { return AL_CHORUS_MAX_DEPTH
; }
343 static constexpr auto efx_max_feedback() { return AL_CHORUS_MAX_FEEDBACK
; }
344 static constexpr auto efx_max_delay() { return AL_CHORUS_MAX_DELAY
; }
346 static constexpr auto efx_default_waveform() { return AL_CHORUS_DEFAULT_WAVEFORM
; }
347 static constexpr auto efx_default_phase() { return AL_CHORUS_DEFAULT_PHASE
; }
348 static constexpr auto efx_default_rate() { return AL_CHORUS_DEFAULT_RATE
; }
349 static constexpr auto efx_default_depth() { return AL_CHORUS_DEFAULT_DEPTH
; }
350 static constexpr auto efx_default_feedback() { return AL_CHORUS_DEFAULT_FEEDBACK
; }
351 static constexpr auto efx_default_delay() { return AL_CHORUS_DEFAULT_DELAY
; }
353 static ChorusWaveform
eax_waveform(unsigned long type
)
355 if(type
== EAX_CHORUS_SINUSOID
) return ChorusWaveform::Sinusoid
;
356 if(type
== EAX_CHORUS_TRIANGLE
) return ChorusWaveform::Triangle
;
357 return ChorusWaveform::Sinusoid
;
359 }; // EaxChorusTraits
361 struct EaxFlangerTraits
{
362 using Props
= EAXFLANGERPROPERTIES
;
363 using Committer
= EaxFlangerCommitter
;
364 static constexpr auto Field
= &EaxEffectProps::mFlanger
;
366 static constexpr auto eax_effect_type() { return EaxEffectType::Flanger
; }
367 static constexpr auto efx_effect() { return AL_EFFECT_FLANGER
; }
369 static constexpr auto eax_none_param_id() { return EAXFLANGER_NONE
; }
370 static constexpr auto eax_allparameters_param_id() { return EAXFLANGER_ALLPARAMETERS
; }
371 static constexpr auto eax_waveform_param_id() { return EAXFLANGER_WAVEFORM
; }
372 static constexpr auto eax_phase_param_id() { return EAXFLANGER_PHASE
; }
373 static constexpr auto eax_rate_param_id() { return EAXFLANGER_RATE
; }
374 static constexpr auto eax_depth_param_id() { return EAXFLANGER_DEPTH
; }
375 static constexpr auto eax_feedback_param_id() { return EAXFLANGER_FEEDBACK
; }
376 static constexpr auto eax_delay_param_id() { return EAXFLANGER_DELAY
; }
378 static constexpr auto eax_min_waveform() { return EAXFLANGER_MINWAVEFORM
; }
379 static constexpr auto eax_min_phase() { return EAXFLANGER_MINPHASE
; }
380 static constexpr auto eax_min_rate() { return EAXFLANGER_MINRATE
; }
381 static constexpr auto eax_min_depth() { return EAXFLANGER_MINDEPTH
; }
382 static constexpr auto eax_min_feedback() { return EAXFLANGER_MINFEEDBACK
; }
383 static constexpr auto eax_min_delay() { return EAXFLANGER_MINDELAY
; }
385 static constexpr auto eax_max_waveform() { return EAXFLANGER_MAXWAVEFORM
; }
386 static constexpr auto eax_max_phase() { return EAXFLANGER_MAXPHASE
; }
387 static constexpr auto eax_max_rate() { return EAXFLANGER_MAXRATE
; }
388 static constexpr auto eax_max_depth() { return EAXFLANGER_MAXDEPTH
; }
389 static constexpr auto eax_max_feedback() { return EAXFLANGER_MAXFEEDBACK
; }
390 static constexpr auto eax_max_delay() { return EAXFLANGER_MAXDELAY
; }
392 static constexpr auto eax_default_waveform() { return EAXFLANGER_DEFAULTWAVEFORM
; }
393 static constexpr auto eax_default_phase() { return EAXFLANGER_DEFAULTPHASE
; }
394 static constexpr auto eax_default_rate() { return EAXFLANGER_DEFAULTRATE
; }
395 static constexpr auto eax_default_depth() { return EAXFLANGER_DEFAULTDEPTH
; }
396 static constexpr auto eax_default_feedback() { return EAXFLANGER_DEFAULTFEEDBACK
; }
397 static constexpr auto eax_default_delay() { return EAXFLANGER_DEFAULTDELAY
; }
399 static constexpr auto efx_min_waveform() { return AL_FLANGER_MIN_WAVEFORM
; }
400 static constexpr auto efx_min_phase() { return AL_FLANGER_MIN_PHASE
; }
401 static constexpr auto efx_min_rate() { return AL_FLANGER_MIN_RATE
; }
402 static constexpr auto efx_min_depth() { return AL_FLANGER_MIN_DEPTH
; }
403 static constexpr auto efx_min_feedback() { return AL_FLANGER_MIN_FEEDBACK
; }
404 static constexpr auto efx_min_delay() { return AL_FLANGER_MIN_DELAY
; }
406 static constexpr auto efx_max_waveform() { return AL_FLANGER_MAX_WAVEFORM
; }
407 static constexpr auto efx_max_phase() { return AL_FLANGER_MAX_PHASE
; }
408 static constexpr auto efx_max_rate() { return AL_FLANGER_MAX_RATE
; }
409 static constexpr auto efx_max_depth() { return AL_FLANGER_MAX_DEPTH
; }
410 static constexpr auto efx_max_feedback() { return AL_FLANGER_MAX_FEEDBACK
; }
411 static constexpr auto efx_max_delay() { return AL_FLANGER_MAX_DELAY
; }
413 static constexpr auto efx_default_waveform() { return AL_FLANGER_DEFAULT_WAVEFORM
; }
414 static constexpr auto efx_default_phase() { return AL_FLANGER_DEFAULT_PHASE
; }
415 static constexpr auto efx_default_rate() { return AL_FLANGER_DEFAULT_RATE
; }
416 static constexpr auto efx_default_depth() { return AL_FLANGER_DEFAULT_DEPTH
; }
417 static constexpr auto efx_default_feedback() { return AL_FLANGER_DEFAULT_FEEDBACK
; }
418 static constexpr auto efx_default_delay() { return AL_FLANGER_DEFAULT_DELAY
; }
420 static ChorusWaveform
eax_waveform(unsigned long type
)
422 if(type
== EAX_FLANGER_SINUSOID
) return ChorusWaveform::Sinusoid
;
423 if(type
== EAX_FLANGER_TRIANGLE
) return ChorusWaveform::Triangle
;
424 return ChorusWaveform::Sinusoid
;
426 }; // EaxFlangerTraits
428 template<typename TTraits
>
429 struct ChorusFlangerEffect
{
430 using Traits
= TTraits
;
431 using Committer
= typename
Traits::Committer
;
432 using Exception
= typename
Committer::Exception
;
434 static constexpr auto Field
= Traits::Field
;
436 struct WaveformValidator
{
437 void operator()(unsigned long ulWaveform
) const
439 eax_validate_range
<Exception
>(
442 Traits::eax_min_waveform(),
443 Traits::eax_max_waveform());
445 }; // WaveformValidator
447 struct PhaseValidator
{
448 void operator()(long lPhase
) const
450 eax_validate_range
<Exception
>(
453 Traits::eax_min_phase(),
454 Traits::eax_max_phase());
458 struct RateValidator
{
459 void operator()(float flRate
) const
461 eax_validate_range
<Exception
>(
464 Traits::eax_min_rate(),
465 Traits::eax_max_rate());
469 struct DepthValidator
{
470 void operator()(float flDepth
) const
472 eax_validate_range
<Exception
>(
475 Traits::eax_min_depth(),
476 Traits::eax_max_depth());
480 struct FeedbackValidator
{
481 void operator()(float flFeedback
) const
483 eax_validate_range
<Exception
>(
486 Traits::eax_min_feedback(),
487 Traits::eax_max_feedback());
489 }; // FeedbackValidator
491 struct DelayValidator
{
492 void operator()(float flDelay
) const
494 eax_validate_range
<Exception
>(
497 Traits::eax_min_delay(),
498 Traits::eax_max_delay());
502 struct AllValidator
{
503 void operator()(const typename
Traits::Props
& all
) const
505 WaveformValidator
{}(all
.ulWaveform
);
506 PhaseValidator
{}(all
.lPhase
);
507 RateValidator
{}(all
.flRate
);
508 DepthValidator
{}(all
.flDepth
);
509 FeedbackValidator
{}(all
.flFeedback
);
510 DelayValidator
{}(all
.flDelay
);
515 static void SetDefaults(EaxEffectProps
&props
)
517 auto&& all
= props
.*Field
;
518 props
.mType
= Traits::eax_effect_type();
519 all
.ulWaveform
= Traits::eax_default_waveform();
520 all
.lPhase
= Traits::eax_default_phase();
521 all
.flRate
= Traits::eax_default_rate();
522 all
.flDepth
= Traits::eax_default_depth();
523 all
.flFeedback
= Traits::eax_default_feedback();
524 all
.flDelay
= Traits::eax_default_delay();
528 static void Get(const EaxCall
&call
, const EaxEffectProps
&props
)
530 auto&& all
= props
.*Field
;
531 switch(call
.get_property_id())
533 case Traits::eax_none_param_id():
536 case Traits::eax_allparameters_param_id():
537 call
.template set_value
<Exception
>(all
);
540 case Traits::eax_waveform_param_id():
541 call
.template set_value
<Exception
>(all
.ulWaveform
);
544 case Traits::eax_phase_param_id():
545 call
.template set_value
<Exception
>(all
.lPhase
);
548 case Traits::eax_rate_param_id():
549 call
.template set_value
<Exception
>(all
.flRate
);
552 case Traits::eax_depth_param_id():
553 call
.template set_value
<Exception
>(all
.flDepth
);
556 case Traits::eax_feedback_param_id():
557 call
.template set_value
<Exception
>(all
.flFeedback
);
560 case Traits::eax_delay_param_id():
561 call
.template set_value
<Exception
>(all
.flDelay
);
565 Committer::fail_unknown_property_id();
569 static void Set(const EaxCall
&call
, EaxEffectProps
&props
)
571 auto&& all
= props
.*Field
;
572 switch(call
.get_property_id())
574 case Traits::eax_none_param_id():
577 case Traits::eax_allparameters_param_id():
578 Committer::template defer
<AllValidator
>(call
, all
);
581 case Traits::eax_waveform_param_id():
582 Committer::template defer
<WaveformValidator
>(call
, all
.ulWaveform
);
585 case Traits::eax_phase_param_id():
586 Committer::template defer
<PhaseValidator
>(call
, all
.lPhase
);
589 case Traits::eax_rate_param_id():
590 Committer::template defer
<RateValidator
>(call
, all
.flRate
);
593 case Traits::eax_depth_param_id():
594 Committer::template defer
<DepthValidator
>(call
, all
.flDepth
);
597 case Traits::eax_feedback_param_id():
598 Committer::template defer
<FeedbackValidator
>(call
, all
.flFeedback
);
601 case Traits::eax_delay_param_id():
602 Committer::template defer
<DelayValidator
>(call
, all
.flDelay
);
606 Committer::fail_unknown_property_id();
610 static bool Commit(const EaxEffectProps
&props
, EaxEffectProps
&props_
,
611 EffectProps
&al_effect_props_
)
613 const auto orig
= props_
;
616 auto&& src
= orig
.*Field
;
617 auto&& dst
= props_
.*Field
;
618 if(orig
.mType
== props_
.mType
&& dst
.ulWaveform
== src
.ulWaveform
619 && dst
.lPhase
== src
.lPhase
&& dst
.flRate
== src
.flRate
&& dst
.flDepth
== src
.flDepth
620 && dst
.flFeedback
== src
.flFeedback
&& dst
.flDelay
== src
.flDelay
)
623 al_effect_props_
.Chorus
.Waveform
= Traits::eax_waveform(dst
.ulWaveform
);
624 al_effect_props_
.Chorus
.Phase
= static_cast<ALint
>(dst
.lPhase
);
625 al_effect_props_
.Chorus
.Rate
= dst
.flRate
;
626 al_effect_props_
.Chorus
.Depth
= dst
.flDepth
;
627 al_effect_props_
.Chorus
.Feedback
= dst
.flFeedback
;
628 al_effect_props_
.Chorus
.Delay
= dst
.flDelay
;
632 }; // EaxChorusFlangerEffect
635 using ChorusCommitter
= EaxCommitter
<EaxChorusCommitter
>;
636 using FlangerCommitter
= EaxCommitter
<EaxFlangerCommitter
>;
641 struct ChorusCommitter::Exception
: public EaxException
643 explicit Exception(const char *message
) : EaxException
{"EAX_CHORUS_EFFECT", message
}
648 [[noreturn
]] void ChorusCommitter::fail(const char *message
)
650 throw Exception
{message
};
654 bool ChorusCommitter::commit(const EaxEffectProps
&props
)
656 using Committer
= ChorusFlangerEffect
<EaxChorusTraits
>;
657 return Committer::Commit(props
, props_
, al_effect_props_
);
661 void ChorusCommitter::SetDefaults(EaxEffectProps
&props
)
663 using Committer
= ChorusFlangerEffect
<EaxChorusTraits
>;
664 Committer::SetDefaults(props
);
668 void ChorusCommitter::Get(const EaxCall
&call
, const EaxEffectProps
&props
)
670 using Committer
= ChorusFlangerEffect
<EaxChorusTraits
>;
671 Committer::Get(call
, props
);
675 void ChorusCommitter::Set(const EaxCall
&call
, EaxEffectProps
&props
)
677 using Committer
= ChorusFlangerEffect
<EaxChorusTraits
>;
678 Committer::Set(call
, props
);
682 struct FlangerCommitter::Exception
: public EaxException
684 explicit Exception(const char *message
) : EaxException
{"EAX_FLANGER_EFFECT", message
}
689 [[noreturn
]] void FlangerCommitter::fail(const char *message
)
691 throw Exception
{message
};
695 bool FlangerCommitter::commit(const EaxEffectProps
&props
)
697 using Committer
= ChorusFlangerEffect
<EaxFlangerTraits
>;
698 return Committer::Commit(props
, props_
, al_effect_props_
);
702 void FlangerCommitter::SetDefaults(EaxEffectProps
&props
)
704 using Committer
= ChorusFlangerEffect
<EaxFlangerTraits
>;
705 Committer::SetDefaults(props
);
709 void FlangerCommitter::Get(const EaxCall
&call
, const EaxEffectProps
&props
)
711 using Committer
= ChorusFlangerEffect
<EaxFlangerTraits
>;
712 Committer::Get(call
, props
);
716 void FlangerCommitter::Set(const EaxCall
&call
, EaxEffectProps
&props
)
718 using Committer
= ChorusFlangerEffect
<EaxFlangerTraits
>;
719 Committer::Set(call
, props
);