Move some function definitions to a more appropriate source
[openal-soft.git] / al / effects / chorus.cpp
blob93771a1f4843d40ce9678cffb8ab9d425ca3f02c
2 #include "config.h"
4 #include <optional>
5 #include <stdexcept>
7 #include "AL/al.h"
8 #include "AL/efx.h"
10 #include "alc/effects/base.h"
11 #include "core/logging.h"
12 #include "effects.h"
14 #ifdef ALSOFT_EAX
15 #include <cassert>
16 #include "alnumeric.h"
17 #include "al/eax/effect.h"
18 #include "al/eax/exception.h"
19 #include "al/eax/utils.h"
20 #endif // ALSOFT_EAX
23 namespace {
25 static_assert(ChorusMaxDelay >= AL_CHORUS_MAX_DELAY, "Chorus max delay too small");
26 static_assert(FlangerMaxDelay >= AL_FLANGER_MAX_DELAY, "Flanger max delay too small");
28 static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch");
29 static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch");
31 constexpr std::optional<ChorusWaveform> WaveformFromEnum(ALenum type) noexcept
33 switch(type)
35 case AL_CHORUS_WAVEFORM_SINUSOID: return ChorusWaveform::Sinusoid;
36 case AL_CHORUS_WAVEFORM_TRIANGLE: return ChorusWaveform::Triangle;
38 return std::nullopt;
40 constexpr ALenum EnumFromWaveform(ChorusWaveform type)
42 switch(type)
44 case ChorusWaveform::Sinusoid: return AL_CHORUS_WAVEFORM_SINUSOID;
45 case ChorusWaveform::Triangle: return AL_CHORUS_WAVEFORM_TRIANGLE;
47 throw std::runtime_error{"Invalid chorus waveform: "+std::to_string(static_cast<int>(type))};
50 constexpr EffectProps genDefaultChorusProps() noexcept
52 ChorusProps props{};
53 props.Waveform = WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM).value();
54 props.Phase = AL_CHORUS_DEFAULT_PHASE;
55 props.Rate = AL_CHORUS_DEFAULT_RATE;
56 props.Depth = AL_CHORUS_DEFAULT_DEPTH;
57 props.Feedback = AL_CHORUS_DEFAULT_FEEDBACK;
58 props.Delay = AL_CHORUS_DEFAULT_DELAY;
59 return props;
62 constexpr EffectProps genDefaultFlangerProps() noexcept
64 FlangerProps props{};
65 props.Waveform = WaveformFromEnum(AL_FLANGER_DEFAULT_WAVEFORM).value();
66 props.Phase = AL_FLANGER_DEFAULT_PHASE;
67 props.Rate = AL_FLANGER_DEFAULT_RATE;
68 props.Depth = AL_FLANGER_DEFAULT_DEPTH;
69 props.Feedback = AL_FLANGER_DEFAULT_FEEDBACK;
70 props.Delay = AL_FLANGER_DEFAULT_DELAY;
71 return props;
74 } // namespace
76 const EffectProps ChorusEffectProps{genDefaultChorusProps()};
78 void EffectHandler::SetParami(ChorusProps &props, ALenum param, int val)
80 switch(param)
82 case AL_CHORUS_WAVEFORM:
83 if(auto formopt = WaveformFromEnum(val))
84 props.Waveform = *formopt;
85 else
86 throw effect_exception{AL_INVALID_VALUE, "Invalid chorus waveform: 0x%04x", val};
87 break;
89 case AL_CHORUS_PHASE:
90 if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
91 throw effect_exception{AL_INVALID_VALUE, "Chorus phase out of range: %d", val};
92 props.Phase = val;
93 break;
95 default:
96 throw effect_exception{AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param};
99 void EffectHandler::SetParamiv(ChorusProps &props, ALenum param, const int *vals)
100 { SetParami(props, param, *vals); }
101 void EffectHandler::SetParamf(ChorusProps &props, ALenum param, float val)
103 switch(param)
105 case AL_CHORUS_RATE:
106 if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
107 throw effect_exception{AL_INVALID_VALUE, "Chorus rate out of range: %f", val};
108 props.Rate = val;
109 break;
111 case AL_CHORUS_DEPTH:
112 if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
113 throw effect_exception{AL_INVALID_VALUE, "Chorus depth out of range: %f", val};
114 props.Depth = val;
115 break;
117 case AL_CHORUS_FEEDBACK:
118 if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
119 throw effect_exception{AL_INVALID_VALUE, "Chorus feedback out of range: %f", val};
120 props.Feedback = val;
121 break;
123 case AL_CHORUS_DELAY:
124 if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
125 throw effect_exception{AL_INVALID_VALUE, "Chorus delay out of range: %f", val};
126 props.Delay = val;
127 break;
129 default:
130 throw effect_exception{AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param};
133 void EffectHandler::SetParamfv(ChorusProps &props, ALenum param, const float *vals)
134 { SetParamf(props, param, *vals); }
136 void EffectHandler::GetParami(const ChorusProps &props, ALenum param, int *val)
138 switch(param)
140 case AL_CHORUS_WAVEFORM: *val = EnumFromWaveform(props.Waveform); break;
141 case AL_CHORUS_PHASE: *val = props.Phase; break;
143 default:
144 throw effect_exception{AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param};
147 void EffectHandler::GetParamiv(const ChorusProps &props, ALenum param, int *vals)
148 { GetParami(props, param, vals); }
149 void EffectHandler::GetParamf(const ChorusProps &props, ALenum param, float *val)
151 switch(param)
153 case AL_CHORUS_RATE: *val = props.Rate; break;
154 case AL_CHORUS_DEPTH: *val = props.Depth; break;
155 case AL_CHORUS_FEEDBACK: *val = props.Feedback; break;
156 case AL_CHORUS_DELAY: *val = props.Delay; break;
158 default:
159 throw effect_exception{AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param};
162 void EffectHandler::GetParamfv(const ChorusProps &props, ALenum param, float *vals)
163 { GetParamf(props, param, vals); }
166 const EffectProps FlangerEffectProps{genDefaultFlangerProps()};
168 void EffectHandler::SetParami(FlangerProps &props, ALenum param, int val)
170 switch(param)
172 case AL_FLANGER_WAVEFORM:
173 if(auto formopt = WaveformFromEnum(val))
174 props.Waveform = *formopt;
175 else
176 throw effect_exception{AL_INVALID_VALUE, "Invalid flanger waveform: 0x%04x", val};
177 break;
179 case AL_FLANGER_PHASE:
180 if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE))
181 throw effect_exception{AL_INVALID_VALUE, "Flanger phase out of range: %d", val};
182 props.Phase = val;
183 break;
185 default:
186 throw effect_exception{AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param};
189 void EffectHandler::SetParamiv(FlangerProps &props, ALenum param, const int *vals)
190 { SetParami(props, param, *vals); }
191 void EffectHandler::SetParamf(FlangerProps &props, ALenum param, float val)
193 switch(param)
195 case AL_FLANGER_RATE:
196 if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE))
197 throw effect_exception{AL_INVALID_VALUE, "Flanger rate out of range: %f", val};
198 props.Rate = val;
199 break;
201 case AL_FLANGER_DEPTH:
202 if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH))
203 throw effect_exception{AL_INVALID_VALUE, "Flanger depth out of range: %f", val};
204 props.Depth = val;
205 break;
207 case AL_FLANGER_FEEDBACK:
208 if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK))
209 throw effect_exception{AL_INVALID_VALUE, "Flanger feedback out of range: %f", val};
210 props.Feedback = val;
211 break;
213 case AL_FLANGER_DELAY:
214 if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY))
215 throw effect_exception{AL_INVALID_VALUE, "Flanger delay out of range: %f", val};
216 props.Delay = val;
217 break;
219 default:
220 throw effect_exception{AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param};
223 void EffectHandler::SetParamfv(FlangerProps &props, ALenum param, const float *vals)
224 { SetParamf(props, param, *vals); }
226 void EffectHandler::GetParami(const FlangerProps &props, ALenum param, int *val)
228 switch(param)
230 case AL_FLANGER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); break;
231 case AL_FLANGER_PHASE: *val = props.Phase; break;
233 default:
234 throw effect_exception{AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param};
237 void EffectHandler::GetParamiv(const FlangerProps &props, ALenum param, int *vals)
238 { GetParami(props, param, vals); }
239 void EffectHandler::GetParamf(const FlangerProps &props, ALenum param, float *val)
241 switch(param)
243 case AL_FLANGER_RATE: *val = props.Rate; break;
244 case AL_FLANGER_DEPTH: *val = props.Depth; break;
245 case AL_FLANGER_FEEDBACK: *val = props.Feedback; break;
246 case AL_FLANGER_DELAY: *val = props.Delay; break;
248 default:
249 throw effect_exception{AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param};
252 void EffectHandler::GetParamfv(const FlangerProps &props, ALenum param, float *vals)
253 { GetParamf(props, param, vals); }
256 #ifdef ALSOFT_EAX
257 namespace {
259 struct EaxChorusTraits {
260 using EaxProps = EAXCHORUSPROPERTIES;
261 using Committer = EaxChorusCommitter;
262 using AlProps = ChorusProps;
264 static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; }
266 static constexpr auto eax_none_param_id() { return EAXCHORUS_NONE; }
267 static constexpr auto eax_allparameters_param_id() { return EAXCHORUS_ALLPARAMETERS; }
268 static constexpr auto eax_waveform_param_id() { return EAXCHORUS_WAVEFORM; }
269 static constexpr auto eax_phase_param_id() { return EAXCHORUS_PHASE; }
270 static constexpr auto eax_rate_param_id() { return EAXCHORUS_RATE; }
271 static constexpr auto eax_depth_param_id() { return EAXCHORUS_DEPTH; }
272 static constexpr auto eax_feedback_param_id() { return EAXCHORUS_FEEDBACK; }
273 static constexpr auto eax_delay_param_id() { return EAXCHORUS_DELAY; }
275 static constexpr auto eax_min_waveform() { return EAXCHORUS_MINWAVEFORM; }
276 static constexpr auto eax_min_phase() { return EAXCHORUS_MINPHASE; }
277 static constexpr auto eax_min_rate() { return EAXCHORUS_MINRATE; }
278 static constexpr auto eax_min_depth() { return EAXCHORUS_MINDEPTH; }
279 static constexpr auto eax_min_feedback() { return EAXCHORUS_MINFEEDBACK; }
280 static constexpr auto eax_min_delay() { return EAXCHORUS_MINDELAY; }
282 static constexpr auto eax_max_waveform() { return EAXCHORUS_MAXWAVEFORM; }
283 static constexpr auto eax_max_phase() { return EAXCHORUS_MAXPHASE; }
284 static constexpr auto eax_max_rate() { return EAXCHORUS_MAXRATE; }
285 static constexpr auto eax_max_depth() { return EAXCHORUS_MAXDEPTH; }
286 static constexpr auto eax_max_feedback() { return EAXCHORUS_MAXFEEDBACK; }
287 static constexpr auto eax_max_delay() { return EAXCHORUS_MAXDELAY; }
289 static constexpr auto eax_default_waveform() { return EAXCHORUS_DEFAULTWAVEFORM; }
290 static constexpr auto eax_default_phase() { return EAXCHORUS_DEFAULTPHASE; }
291 static constexpr auto eax_default_rate() { return EAXCHORUS_DEFAULTRATE; }
292 static constexpr auto eax_default_depth() { return EAXCHORUS_DEFAULTDEPTH; }
293 static constexpr auto eax_default_feedback() { return EAXCHORUS_DEFAULTFEEDBACK; }
294 static constexpr auto eax_default_delay() { return EAXCHORUS_DEFAULTDELAY; }
296 static constexpr auto efx_min_waveform() { return AL_CHORUS_MIN_WAVEFORM; }
297 static constexpr auto efx_min_phase() { return AL_CHORUS_MIN_PHASE; }
298 static constexpr auto efx_min_rate() { return AL_CHORUS_MIN_RATE; }
299 static constexpr auto efx_min_depth() { return AL_CHORUS_MIN_DEPTH; }
300 static constexpr auto efx_min_feedback() { return AL_CHORUS_MIN_FEEDBACK; }
301 static constexpr auto efx_min_delay() { return AL_CHORUS_MIN_DELAY; }
303 static constexpr auto efx_max_waveform() { return AL_CHORUS_MAX_WAVEFORM; }
304 static constexpr auto efx_max_phase() { return AL_CHORUS_MAX_PHASE; }
305 static constexpr auto efx_max_rate() { return AL_CHORUS_MAX_RATE; }
306 static constexpr auto efx_max_depth() { return AL_CHORUS_MAX_DEPTH; }
307 static constexpr auto efx_max_feedback() { return AL_CHORUS_MAX_FEEDBACK; }
308 static constexpr auto efx_max_delay() { return AL_CHORUS_MAX_DELAY; }
310 static constexpr auto efx_default_waveform() { return AL_CHORUS_DEFAULT_WAVEFORM; }
311 static constexpr auto efx_default_phase() { return AL_CHORUS_DEFAULT_PHASE; }
312 static constexpr auto efx_default_rate() { return AL_CHORUS_DEFAULT_RATE; }
313 static constexpr auto efx_default_depth() { return AL_CHORUS_DEFAULT_DEPTH; }
314 static constexpr auto efx_default_feedback() { return AL_CHORUS_DEFAULT_FEEDBACK; }
315 static constexpr auto efx_default_delay() { return AL_CHORUS_DEFAULT_DELAY; }
317 static ChorusWaveform eax_waveform(unsigned long type)
319 if(type == EAX_CHORUS_SINUSOID) return ChorusWaveform::Sinusoid;
320 if(type == EAX_CHORUS_TRIANGLE) return ChorusWaveform::Triangle;
321 return ChorusWaveform::Sinusoid;
323 }; // EaxChorusTraits
325 struct EaxFlangerTraits {
326 using EaxProps = EAXFLANGERPROPERTIES;
327 using Committer = EaxFlangerCommitter;
328 using AlProps = FlangerProps;
330 static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; }
332 static constexpr auto eax_none_param_id() { return EAXFLANGER_NONE; }
333 static constexpr auto eax_allparameters_param_id() { return EAXFLANGER_ALLPARAMETERS; }
334 static constexpr auto eax_waveform_param_id() { return EAXFLANGER_WAVEFORM; }
335 static constexpr auto eax_phase_param_id() { return EAXFLANGER_PHASE; }
336 static constexpr auto eax_rate_param_id() { return EAXFLANGER_RATE; }
337 static constexpr auto eax_depth_param_id() { return EAXFLANGER_DEPTH; }
338 static constexpr auto eax_feedback_param_id() { return EAXFLANGER_FEEDBACK; }
339 static constexpr auto eax_delay_param_id() { return EAXFLANGER_DELAY; }
341 static constexpr auto eax_min_waveform() { return EAXFLANGER_MINWAVEFORM; }
342 static constexpr auto eax_min_phase() { return EAXFLANGER_MINPHASE; }
343 static constexpr auto eax_min_rate() { return EAXFLANGER_MINRATE; }
344 static constexpr auto eax_min_depth() { return EAXFLANGER_MINDEPTH; }
345 static constexpr auto eax_min_feedback() { return EAXFLANGER_MINFEEDBACK; }
346 static constexpr auto eax_min_delay() { return EAXFLANGER_MINDELAY; }
348 static constexpr auto eax_max_waveform() { return EAXFLANGER_MAXWAVEFORM; }
349 static constexpr auto eax_max_phase() { return EAXFLANGER_MAXPHASE; }
350 static constexpr auto eax_max_rate() { return EAXFLANGER_MAXRATE; }
351 static constexpr auto eax_max_depth() { return EAXFLANGER_MAXDEPTH; }
352 static constexpr auto eax_max_feedback() { return EAXFLANGER_MAXFEEDBACK; }
353 static constexpr auto eax_max_delay() { return EAXFLANGER_MAXDELAY; }
355 static constexpr auto eax_default_waveform() { return EAXFLANGER_DEFAULTWAVEFORM; }
356 static constexpr auto eax_default_phase() { return EAXFLANGER_DEFAULTPHASE; }
357 static constexpr auto eax_default_rate() { return EAXFLANGER_DEFAULTRATE; }
358 static constexpr auto eax_default_depth() { return EAXFLANGER_DEFAULTDEPTH; }
359 static constexpr auto eax_default_feedback() { return EAXFLANGER_DEFAULTFEEDBACK; }
360 static constexpr auto eax_default_delay() { return EAXFLANGER_DEFAULTDELAY; }
362 static constexpr auto efx_min_waveform() { return AL_FLANGER_MIN_WAVEFORM; }
363 static constexpr auto efx_min_phase() { return AL_FLANGER_MIN_PHASE; }
364 static constexpr auto efx_min_rate() { return AL_FLANGER_MIN_RATE; }
365 static constexpr auto efx_min_depth() { return AL_FLANGER_MIN_DEPTH; }
366 static constexpr auto efx_min_feedback() { return AL_FLANGER_MIN_FEEDBACK; }
367 static constexpr auto efx_min_delay() { return AL_FLANGER_MIN_DELAY; }
369 static constexpr auto efx_max_waveform() { return AL_FLANGER_MAX_WAVEFORM; }
370 static constexpr auto efx_max_phase() { return AL_FLANGER_MAX_PHASE; }
371 static constexpr auto efx_max_rate() { return AL_FLANGER_MAX_RATE; }
372 static constexpr auto efx_max_depth() { return AL_FLANGER_MAX_DEPTH; }
373 static constexpr auto efx_max_feedback() { return AL_FLANGER_MAX_FEEDBACK; }
374 static constexpr auto efx_max_delay() { return AL_FLANGER_MAX_DELAY; }
376 static constexpr auto efx_default_waveform() { return AL_FLANGER_DEFAULT_WAVEFORM; }
377 static constexpr auto efx_default_phase() { return AL_FLANGER_DEFAULT_PHASE; }
378 static constexpr auto efx_default_rate() { return AL_FLANGER_DEFAULT_RATE; }
379 static constexpr auto efx_default_depth() { return AL_FLANGER_DEFAULT_DEPTH; }
380 static constexpr auto efx_default_feedback() { return AL_FLANGER_DEFAULT_FEEDBACK; }
381 static constexpr auto efx_default_delay() { return AL_FLANGER_DEFAULT_DELAY; }
383 static ChorusWaveform eax_waveform(unsigned long type)
385 if(type == EAX_FLANGER_SINUSOID) return ChorusWaveform::Sinusoid;
386 if(type == EAX_FLANGER_TRIANGLE) return ChorusWaveform::Triangle;
387 return ChorusWaveform::Sinusoid;
389 }; // EaxFlangerTraits
391 template<typename TTraits>
392 struct ChorusFlangerEffect {
393 using Traits = TTraits;
394 using EaxProps = typename Traits::EaxProps;
395 using Committer = typename Traits::Committer;
396 using AlProps = typename Traits::AlProps;
397 using Exception = typename Committer::Exception;
399 struct WaveformValidator {
400 void operator()(unsigned long ulWaveform) const
402 eax_validate_range<Exception>(
403 "Waveform",
404 ulWaveform,
405 Traits::eax_min_waveform(),
406 Traits::eax_max_waveform());
408 }; // WaveformValidator
410 struct PhaseValidator {
411 void operator()(long lPhase) const
413 eax_validate_range<Exception>(
414 "Phase",
415 lPhase,
416 Traits::eax_min_phase(),
417 Traits::eax_max_phase());
419 }; // PhaseValidator
421 struct RateValidator {
422 void operator()(float flRate) const
424 eax_validate_range<Exception>(
425 "Rate",
426 flRate,
427 Traits::eax_min_rate(),
428 Traits::eax_max_rate());
430 }; // RateValidator
432 struct DepthValidator {
433 void operator()(float flDepth) const
435 eax_validate_range<Exception>(
436 "Depth",
437 flDepth,
438 Traits::eax_min_depth(),
439 Traits::eax_max_depth());
441 }; // DepthValidator
443 struct FeedbackValidator {
444 void operator()(float flFeedback) const
446 eax_validate_range<Exception>(
447 "Feedback",
448 flFeedback,
449 Traits::eax_min_feedback(),
450 Traits::eax_max_feedback());
452 }; // FeedbackValidator
454 struct DelayValidator {
455 void operator()(float flDelay) const
457 eax_validate_range<Exception>(
458 "Delay",
459 flDelay,
460 Traits::eax_min_delay(),
461 Traits::eax_max_delay());
463 }; // DelayValidator
465 struct AllValidator {
466 void operator()(const EaxProps& all) const
468 WaveformValidator{}(all.ulWaveform);
469 PhaseValidator{}(all.lPhase);
470 RateValidator{}(all.flRate);
471 DepthValidator{}(all.flDepth);
472 FeedbackValidator{}(all.flFeedback);
473 DelayValidator{}(all.flDelay);
475 }; // AllValidator
477 public:
478 static void SetDefaults(EaxEffectProps &props)
480 auto&& all = props.emplace<EaxProps>();
481 all.ulWaveform = Traits::eax_default_waveform();
482 all.lPhase = Traits::eax_default_phase();
483 all.flRate = Traits::eax_default_rate();
484 all.flDepth = Traits::eax_default_depth();
485 all.flFeedback = Traits::eax_default_feedback();
486 all.flDelay = Traits::eax_default_delay();
490 static void Get(const EaxCall &call, const EaxProps &all)
492 switch(call.get_property_id())
494 case Traits::eax_none_param_id():
495 break;
496 case Traits::eax_allparameters_param_id():
497 call.template set_value<Exception>(all);
498 break;
499 case Traits::eax_waveform_param_id():
500 call.template set_value<Exception>(all.ulWaveform);
501 break;
502 case Traits::eax_phase_param_id():
503 call.template set_value<Exception>(all.lPhase);
504 break;
505 case Traits::eax_rate_param_id():
506 call.template set_value<Exception>(all.flRate);
507 break;
508 case Traits::eax_depth_param_id():
509 call.template set_value<Exception>(all.flDepth);
510 break;
511 case Traits::eax_feedback_param_id():
512 call.template set_value<Exception>(all.flFeedback);
513 break;
514 case Traits::eax_delay_param_id():
515 call.template set_value<Exception>(all.flDelay);
516 break;
517 default:
518 Committer::fail_unknown_property_id();
522 static void Set(const EaxCall &call, EaxProps &all)
524 switch(call.get_property_id())
526 case Traits::eax_none_param_id():
527 break;
528 case Traits::eax_allparameters_param_id():
529 Committer::template defer<AllValidator>(call, all);
530 break;
531 case Traits::eax_waveform_param_id():
532 Committer::template defer<WaveformValidator>(call, all.ulWaveform);
533 break;
534 case Traits::eax_phase_param_id():
535 Committer::template defer<PhaseValidator>(call, all.lPhase);
536 break;
537 case Traits::eax_rate_param_id():
538 Committer::template defer<RateValidator>(call, all.flRate);
539 break;
540 case Traits::eax_depth_param_id():
541 Committer::template defer<DepthValidator>(call, all.flDepth);
542 break;
543 case Traits::eax_feedback_param_id():
544 Committer::template defer<FeedbackValidator>(call, all.flFeedback);
545 break;
546 case Traits::eax_delay_param_id():
547 Committer::template defer<DelayValidator>(call, all.flDelay);
548 break;
549 default:
550 Committer::fail_unknown_property_id();
554 static bool Commit(const EaxProps &props, EaxEffectProps &props_, AlProps &al_props_)
556 if(auto *cur = std::get_if<EaxProps>(&props_); cur && *cur == props)
557 return false;
559 props_ = props;
561 al_props_.Waveform = Traits::eax_waveform(props.ulWaveform);
562 al_props_.Phase = static_cast<int>(props.lPhase);
563 al_props_.Rate = props.flRate;
564 al_props_.Depth = props.flDepth;
565 al_props_.Feedback = props.flFeedback;
566 al_props_.Delay = props.flDelay;
568 return true;
570 }; // EaxChorusFlangerEffect
573 using ChorusCommitter = EaxCommitter<EaxChorusCommitter>;
574 using FlangerCommitter = EaxCommitter<EaxFlangerCommitter>;
576 } // namespace
578 template<>
579 struct ChorusCommitter::Exception : public EaxException
581 explicit Exception(const char *message) : EaxException{"EAX_CHORUS_EFFECT", message}
585 template<>
586 [[noreturn]] void ChorusCommitter::fail(const char *message)
588 throw Exception{message};
591 bool EaxChorusCommitter::commit(const EAXCHORUSPROPERTIES &props)
593 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
594 return Committer::Commit(props, mEaxProps, mAlProps.emplace<ChorusProps>());
597 void EaxChorusCommitter::SetDefaults(EaxEffectProps &props)
599 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
600 Committer::SetDefaults(props);
603 void EaxChorusCommitter::Get(const EaxCall &call, const EAXCHORUSPROPERTIES &props)
605 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
606 Committer::Get(call, props);
609 void EaxChorusCommitter::Set(const EaxCall &call, EAXCHORUSPROPERTIES &props)
611 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
612 Committer::Set(call, props);
615 template<>
616 struct FlangerCommitter::Exception : public EaxException
618 explicit Exception(const char *message) : EaxException{"EAX_FLANGER_EFFECT", message}
622 template<>
623 [[noreturn]] void FlangerCommitter::fail(const char *message)
625 throw Exception{message};
628 bool EaxFlangerCommitter::commit(const EAXFLANGERPROPERTIES &props)
630 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
631 return Committer::Commit(props, mEaxProps, mAlProps.emplace<FlangerProps>());
634 void EaxFlangerCommitter::SetDefaults(EaxEffectProps &props)
636 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
637 Committer::SetDefaults(props);
640 void EaxFlangerCommitter::Get(const EaxCall &call, const EAXFLANGERPROPERTIES &props)
642 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
643 Committer::Get(call, props);
646 void EaxFlangerCommitter::Set(const EaxCall &call, EAXFLANGERPROPERTIES &props)
648 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
649 Committer::Set(call, props);
652 #endif // ALSOFT_EAX