10 #include "alc/effects/base.h"
11 #include "core/logging.h"
16 #include "alnumeric.h"
17 #include "al/eax/effect.h"
18 #include "al/eax/exception.h"
19 #include "al/eax/utils.h"
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
35 case AL_CHORUS_WAVEFORM_SINUSOID
: return ChorusWaveform::Sinusoid
;
36 case AL_CHORUS_WAVEFORM_TRIANGLE
: return ChorusWaveform::Triangle
;
40 constexpr ALenum
EnumFromWaveform(ChorusWaveform 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
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
;
62 constexpr EffectProps
genDefaultFlangerProps() noexcept
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
;
76 const EffectProps ChorusEffectProps
{genDefaultChorusProps()};
78 void EffectHandler::SetParami(ChorusProps
&props
, ALenum param
, int val
)
82 case AL_CHORUS_WAVEFORM
:
83 if(auto formopt
= WaveformFromEnum(val
))
84 props
.Waveform
= *formopt
;
86 throw effect_exception
{AL_INVALID_VALUE
, "Invalid chorus waveform: 0x%04x", val
};
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
};
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
)
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
};
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
};
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
;
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
};
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
)
140 case AL_CHORUS_WAVEFORM
: *val
= EnumFromWaveform(props
.Waveform
); break;
141 case AL_CHORUS_PHASE
: *val
= props
.Phase
; break;
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
)
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;
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
)
172 case AL_FLANGER_WAVEFORM
:
173 if(auto formopt
= WaveformFromEnum(val
))
174 props
.Waveform
= *formopt
;
176 throw effect_exception
{AL_INVALID_VALUE
, "Invalid flanger waveform: 0x%04x", val
};
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
};
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
)
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
};
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
};
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
;
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
};
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
)
230 case AL_FLANGER_WAVEFORM
: *val
= EnumFromWaveform(props
.Waveform
); break;
231 case AL_FLANGER_PHASE
: *val
= props
.Phase
; break;
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
)
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;
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
); }
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
>(
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
>(
416 Traits::eax_min_phase(),
417 Traits::eax_max_phase());
421 struct RateValidator
{
422 void operator()(float flRate
) const
424 eax_validate_range
<Exception
>(
427 Traits::eax_min_rate(),
428 Traits::eax_max_rate());
432 struct DepthValidator
{
433 void operator()(float flDepth
) const
435 eax_validate_range
<Exception
>(
438 Traits::eax_min_depth(),
439 Traits::eax_max_depth());
443 struct FeedbackValidator
{
444 void operator()(float flFeedback
) const
446 eax_validate_range
<Exception
>(
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
>(
460 Traits::eax_min_delay(),
461 Traits::eax_max_delay());
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
);
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():
496 case Traits::eax_allparameters_param_id():
497 call
.template set_value
<Exception
>(all
);
499 case Traits::eax_waveform_param_id():
500 call
.template set_value
<Exception
>(all
.ulWaveform
);
502 case Traits::eax_phase_param_id():
503 call
.template set_value
<Exception
>(all
.lPhase
);
505 case Traits::eax_rate_param_id():
506 call
.template set_value
<Exception
>(all
.flRate
);
508 case Traits::eax_depth_param_id():
509 call
.template set_value
<Exception
>(all
.flDepth
);
511 case Traits::eax_feedback_param_id():
512 call
.template set_value
<Exception
>(all
.flFeedback
);
514 case Traits::eax_delay_param_id():
515 call
.template set_value
<Exception
>(all
.flDelay
);
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():
528 case Traits::eax_allparameters_param_id():
529 Committer::template defer
<AllValidator
>(call
, all
);
531 case Traits::eax_waveform_param_id():
532 Committer::template defer
<WaveformValidator
>(call
, all
.ulWaveform
);
534 case Traits::eax_phase_param_id():
535 Committer::template defer
<PhaseValidator
>(call
, all
.lPhase
);
537 case Traits::eax_rate_param_id():
538 Committer::template defer
<RateValidator
>(call
, all
.flRate
);
540 case Traits::eax_depth_param_id():
541 Committer::template defer
<DepthValidator
>(call
, all
.flDepth
);
543 case Traits::eax_feedback_param_id():
544 Committer::template defer
<FeedbackValidator
>(call
, all
.flFeedback
);
546 case Traits::eax_delay_param_id():
547 Committer::template defer
<DelayValidator
>(call
, all
.flDelay
);
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
)
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
;
570 }; // EaxChorusFlangerEffect
573 using ChorusCommitter
= EaxCommitter
<EaxChorusCommitter
>;
574 using FlangerCommitter
= EaxCommitter
<EaxFlangerCommitter
>;
579 struct ChorusCommitter::Exception
: public EaxException
581 explicit Exception(const char *message
) : EaxException
{"EAX_CHORUS_EFFECT", message
}
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
);
616 struct FlangerCommitter::Exception
: public EaxException
618 explicit Exception(const char *message
) : EaxException
{"EAX_FLANGER_EFFECT", message
}
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
);