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_, EffectProps &al_props_)
612 if(props.mType == props_.mType)
614 auto&& src = props_.*Field;
615 auto&& dst = props.*Field;
616 if(dst.ulWaveform == src.ulWaveform && dst.lPhase == src.lPhase
617 && dst.flRate == src.flRate && dst.flDepth == src.flDepth
618 && dst.flFeedback == src.flFeedback && dst.flDelay == src.flDelay)
623 auto&& dst = props.*Field;
625 al_props_.Chorus.Waveform = Traits::eax_waveform(dst.ulWaveform);
626 al_props_.Chorus.Phase = static_cast<int>(dst.lPhase);
627 al_props_.Chorus.Rate = dst.flRate;
628 al_props_.Chorus.Depth = dst.flDepth;
629 al_props_.Chorus.Feedback = dst.flFeedback;
630 al_props_.Chorus.Delay = dst.flDelay;
634 }; // EaxChorusFlangerEffect
637 using ChorusCommitter = EaxCommitter<EaxChorusCommitter>;
638 using FlangerCommitter = EaxCommitter<EaxFlangerCommitter>;
643 struct ChorusCommitter::Exception : public EaxException
645 explicit Exception(const char *message) : EaxException{"EAX_CHORUS_EFFECT", message}
650 [[noreturn]] void ChorusCommitter::fail(const char *message)
652 throw Exception{message};
656 bool ChorusCommitter::commit(const EaxEffectProps &props)
658 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
659 return Committer::Commit(props, mEaxProps, mAlProps);
663 void ChorusCommitter::SetDefaults(EaxEffectProps &props)
665 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
666 Committer::SetDefaults(props);
670 void ChorusCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
672 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
673 Committer::Get(call, props);
677 void ChorusCommitter::Set(const EaxCall &call, EaxEffectProps &props)
679 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
680 Committer::Set(call, props);
684 struct FlangerCommitter::Exception : public EaxException
686 explicit Exception(const char *message) : EaxException{"EAX_FLANGER_EFFECT", message}
691 [[noreturn]] void FlangerCommitter::fail(const char *message)
693 throw Exception{message};
697 bool FlangerCommitter::commit(const EaxEffectProps &props)
699 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
700 return Committer::Commit(props, mEaxProps, mAlProps);
704 void FlangerCommitter::SetDefaults(EaxEffectProps &props)
706 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
707 Committer::SetDefaults(props);
711 void FlangerCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
713 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
714 Committer::Get(call, props);
718 void FlangerCommitter::Set(const EaxCall &call, EaxEffectProps &props)
720 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
721 Committer::Set(call, props);