Simplify committing EAX effect properties
[openal-soft.git] / al / effects / chorus.cpp
bloba6845ee84a46a21cde34d4a6b6d4410147acbc04
2 #include "config.h"
4 #include <stdexcept>
6 #include "AL/al.h"
7 #include "AL/efx.h"
9 #include "alc/effects/base.h"
10 #include "aloptional.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/exception.h"
18 #include "al/eax/utils.h"
19 #endif // ALSOFT_EAX
22 namespace {
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)
32 switch(type)
34 case AL_CHORUS_WAVEFORM_SINUSOID: return ChorusWaveform::Sinusoid;
35 case AL_CHORUS_WAVEFORM_TRIANGLE: return ChorusWaveform::Triangle;
37 return al::nullopt;
39 inline ALenum EnumFromWaveform(ChorusWaveform type)
41 switch(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)
51 switch(param)
53 case AL_CHORUS_WAVEFORM:
54 if(auto formopt = WaveformFromEnum(val))
55 props->Chorus.Waveform = *formopt;
56 else
57 throw effect_exception{AL_INVALID_VALUE, "Invalid chorus waveform: 0x%04x", val};
58 break;
60 case AL_CHORUS_PHASE:
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;
64 break;
66 default:
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)
74 switch(param)
76 case AL_CHORUS_RATE:
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;
80 break;
82 case AL_CHORUS_DEPTH:
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;
86 break;
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;
92 break;
94 case AL_CHORUS_DELAY:
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;
98 break;
100 default:
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)
109 switch(param)
111 case AL_CHORUS_WAVEFORM:
112 *val = EnumFromWaveform(props->Chorus.Waveform);
113 break;
115 case AL_CHORUS_PHASE:
116 *val = props->Chorus.Phase;
117 break;
119 default:
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)
127 switch(param)
129 case AL_CHORUS_RATE:
130 *val = props->Chorus.Rate;
131 break;
133 case AL_CHORUS_DEPTH:
134 *val = props->Chorus.Depth;
135 break;
137 case AL_CHORUS_FEEDBACK:
138 *val = props->Chorus.Feedback;
139 break;
141 case AL_CHORUS_DELAY:
142 *val = props->Chorus.Delay;
143 break;
145 default:
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
154 EffectProps props{};
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;
161 return props;
165 void Flanger_setParami(EffectProps *props, ALenum param, int val)
167 switch(param)
169 case AL_FLANGER_WAVEFORM:
170 if(auto formopt = WaveformFromEnum(val))
171 props->Chorus.Waveform = *formopt;
172 else
173 throw effect_exception{AL_INVALID_VALUE, "Invalid flanger waveform: 0x%04x", val};
174 break;
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;
180 break;
182 default:
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)
190 switch(param)
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;
196 break;
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;
202 break;
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;
208 break;
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;
214 break;
216 default:
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)
225 switch(param)
227 case AL_FLANGER_WAVEFORM:
228 *val = EnumFromWaveform(props->Chorus.Waveform);
229 break;
231 case AL_FLANGER_PHASE:
232 *val = props->Chorus.Phase;
233 break;
235 default:
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)
243 switch(param)
245 case AL_FLANGER_RATE:
246 *val = props->Chorus.Rate;
247 break;
249 case AL_FLANGER_DEPTH:
250 *val = props->Chorus.Depth;
251 break;
253 case AL_FLANGER_FEEDBACK:
254 *val = props->Chorus.Feedback;
255 break;
257 case AL_FLANGER_DELAY:
258 *val = props->Chorus.Delay;
259 break;
261 default:
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
270 EffectProps props{};
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;
277 return props;
280 } // namespace
282 DEFINE_ALEFFECT_VTABLE(Chorus);
284 const EffectProps ChorusEffectProps{genDefaultChorusProps()};
286 DEFINE_ALEFFECT_VTABLE(Flanger);
288 const EffectProps FlangerEffectProps{genDefaultFlangerProps()};
291 #ifdef ALSOFT_EAX
292 namespace {
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>(
440 "Waveform",
441 ulWaveform,
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>(
451 "Phase",
452 lPhase,
453 Traits::eax_min_phase(),
454 Traits::eax_max_phase());
456 }; // PhaseValidator
458 struct RateValidator {
459 void operator()(float flRate) const
461 eax_validate_range<Exception>(
462 "Rate",
463 flRate,
464 Traits::eax_min_rate(),
465 Traits::eax_max_rate());
467 }; // RateValidator
469 struct DepthValidator {
470 void operator()(float flDepth) const
472 eax_validate_range<Exception>(
473 "Depth",
474 flDepth,
475 Traits::eax_min_depth(),
476 Traits::eax_max_depth());
478 }; // DepthValidator
480 struct FeedbackValidator {
481 void operator()(float flFeedback) const
483 eax_validate_range<Exception>(
484 "Feedback",
485 flFeedback,
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>(
495 "Delay",
496 flDelay,
497 Traits::eax_min_delay(),
498 Traits::eax_max_delay());
500 }; // DelayValidator
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);
512 }; // AllValidator
514 public:
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():
534 break;
536 case Traits::eax_allparameters_param_id():
537 call.template set_value<Exception>(all);
538 break;
540 case Traits::eax_waveform_param_id():
541 call.template set_value<Exception>(all.ulWaveform);
542 break;
544 case Traits::eax_phase_param_id():
545 call.template set_value<Exception>(all.lPhase);
546 break;
548 case Traits::eax_rate_param_id():
549 call.template set_value<Exception>(all.flRate);
550 break;
552 case Traits::eax_depth_param_id():
553 call.template set_value<Exception>(all.flDepth);
554 break;
556 case Traits::eax_feedback_param_id():
557 call.template set_value<Exception>(all.flFeedback);
558 break;
560 case Traits::eax_delay_param_id():
561 call.template set_value<Exception>(all.flDelay);
562 break;
564 default:
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():
575 break;
577 case Traits::eax_allparameters_param_id():
578 Committer::template defer<AllValidator>(call, all);
579 break;
581 case Traits::eax_waveform_param_id():
582 Committer::template defer<WaveformValidator>(call, all.ulWaveform);
583 break;
585 case Traits::eax_phase_param_id():
586 Committer::template defer<PhaseValidator>(call, all.lPhase);
587 break;
589 case Traits::eax_rate_param_id():
590 Committer::template defer<RateValidator>(call, all.flRate);
591 break;
593 case Traits::eax_depth_param_id():
594 Committer::template defer<DepthValidator>(call, all.flDepth);
595 break;
597 case Traits::eax_feedback_param_id():
598 Committer::template defer<FeedbackValidator>(call, all.flFeedback);
599 break;
601 case Traits::eax_delay_param_id():
602 Committer::template defer<DelayValidator>(call, all.flDelay);
603 break;
605 default:
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_;
614 props_ = 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)
621 return false;
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;
630 return true;
632 }; // EaxChorusFlangerEffect
635 using ChorusCommitter = EaxCommitter<EaxChorusCommitter>;
636 using FlangerCommitter = EaxCommitter<EaxFlangerCommitter>;
638 } // namespace
640 template<>
641 struct ChorusCommitter::Exception : public EaxException
643 explicit Exception(const char *message) : EaxException{"EAX_CHORUS_EFFECT", message}
647 template<>
648 [[noreturn]] void ChorusCommitter::fail(const char *message)
650 throw Exception{message};
653 template<>
654 bool ChorusCommitter::commit(const EaxEffectProps &props)
656 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
657 return Committer::Commit(props, props_, al_effect_props_);
660 template<>
661 void ChorusCommitter::SetDefaults(EaxEffectProps &props)
663 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
664 Committer::SetDefaults(props);
667 template<>
668 void ChorusCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
670 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
671 Committer::Get(call, props);
674 template<>
675 void ChorusCommitter::Set(const EaxCall &call, EaxEffectProps &props)
677 using Committer = ChorusFlangerEffect<EaxChorusTraits>;
678 Committer::Set(call, props);
681 template<>
682 struct FlangerCommitter::Exception : public EaxException
684 explicit Exception(const char *message) : EaxException{"EAX_FLANGER_EFFECT", message}
688 template<>
689 [[noreturn]] void FlangerCommitter::fail(const char *message)
691 throw Exception{message};
694 template<>
695 bool FlangerCommitter::commit(const EaxEffectProps &props)
697 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
698 return Committer::Commit(props, props_, al_effect_props_);
701 template<>
702 void FlangerCommitter::SetDefaults(EaxEffectProps &props)
704 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
705 Committer::SetDefaults(props);
708 template<>
709 void FlangerCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
711 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
712 Committer::Get(call, props);
715 template<>
716 void FlangerCommitter::Set(const EaxCall &call, EaxEffectProps &props)
718 using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
719 Committer::Set(call, props);
722 #endif // ALSOFT_EAX