Define the CoreAudio default name only when needed
[openal-soft.git] / al / effects / vmorpher.cpp
blob3081201cd9335702a202f4b1738690992b9030d1
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 "effects.h"
13 #ifdef ALSOFT_EAX
14 #include <cassert>
16 #include "alnumeric.h"
18 #include "al/eax_exception.h"
19 #include "al/eax_utils.h"
20 #endif // ALSOFT_EAX
23 namespace {
25 al::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
27 #define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \
28 return al::make_optional(VMorpherPhenome::x)
29 switch(val)
31 HANDLE_PHENOME(A);
32 HANDLE_PHENOME(E);
33 HANDLE_PHENOME(I);
34 HANDLE_PHENOME(O);
35 HANDLE_PHENOME(U);
36 HANDLE_PHENOME(AA);
37 HANDLE_PHENOME(AE);
38 HANDLE_PHENOME(AH);
39 HANDLE_PHENOME(AO);
40 HANDLE_PHENOME(EH);
41 HANDLE_PHENOME(ER);
42 HANDLE_PHENOME(IH);
43 HANDLE_PHENOME(IY);
44 HANDLE_PHENOME(UH);
45 HANDLE_PHENOME(UW);
46 HANDLE_PHENOME(B);
47 HANDLE_PHENOME(D);
48 HANDLE_PHENOME(F);
49 HANDLE_PHENOME(G);
50 HANDLE_PHENOME(J);
51 HANDLE_PHENOME(K);
52 HANDLE_PHENOME(L);
53 HANDLE_PHENOME(M);
54 HANDLE_PHENOME(N);
55 HANDLE_PHENOME(P);
56 HANDLE_PHENOME(R);
57 HANDLE_PHENOME(S);
58 HANDLE_PHENOME(T);
59 HANDLE_PHENOME(V);
60 HANDLE_PHENOME(Z);
62 return al::nullopt;
63 #undef HANDLE_PHENOME
65 ALenum EnumFromPhenome(VMorpherPhenome phenome)
67 #define HANDLE_PHENOME(x) case VMorpherPhenome::x: return AL_VOCAL_MORPHER_PHONEME_ ## x
68 switch(phenome)
70 HANDLE_PHENOME(A);
71 HANDLE_PHENOME(E);
72 HANDLE_PHENOME(I);
73 HANDLE_PHENOME(O);
74 HANDLE_PHENOME(U);
75 HANDLE_PHENOME(AA);
76 HANDLE_PHENOME(AE);
77 HANDLE_PHENOME(AH);
78 HANDLE_PHENOME(AO);
79 HANDLE_PHENOME(EH);
80 HANDLE_PHENOME(ER);
81 HANDLE_PHENOME(IH);
82 HANDLE_PHENOME(IY);
83 HANDLE_PHENOME(UH);
84 HANDLE_PHENOME(UW);
85 HANDLE_PHENOME(B);
86 HANDLE_PHENOME(D);
87 HANDLE_PHENOME(F);
88 HANDLE_PHENOME(G);
89 HANDLE_PHENOME(J);
90 HANDLE_PHENOME(K);
91 HANDLE_PHENOME(L);
92 HANDLE_PHENOME(M);
93 HANDLE_PHENOME(N);
94 HANDLE_PHENOME(P);
95 HANDLE_PHENOME(R);
96 HANDLE_PHENOME(S);
97 HANDLE_PHENOME(T);
98 HANDLE_PHENOME(V);
99 HANDLE_PHENOME(Z);
101 throw std::runtime_error{"Invalid phenome: "+std::to_string(static_cast<int>(phenome))};
102 #undef HANDLE_PHENOME
105 al::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
107 switch(value)
109 case AL_VOCAL_MORPHER_WAVEFORM_SINUSOID: return al::make_optional(VMorpherWaveform::Sinusoid);
110 case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return al::make_optional(VMorpherWaveform::Triangle);
111 case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return al::make_optional(VMorpherWaveform::Sawtooth);
113 return al::nullopt;
115 ALenum EnumFromWaveform(VMorpherWaveform type)
117 switch(type)
119 case VMorpherWaveform::Sinusoid: return AL_VOCAL_MORPHER_WAVEFORM_SINUSOID;
120 case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
121 case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
123 throw std::runtime_error{"Invalid vocal morpher waveform: " +
124 std::to_string(static_cast<int>(type))};
127 void Vmorpher_setParami(EffectProps *props, ALenum param, int val)
129 switch(param)
131 case AL_VOCAL_MORPHER_PHONEMEA:
132 if(auto phenomeopt = PhenomeFromEnum(val))
133 props->Vmorpher.PhonemeA = *phenomeopt;
134 else
135 throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a out of range: 0x%04x", val};
136 break;
138 case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
139 if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING))
140 throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a coarse tuning out of range"};
141 props->Vmorpher.PhonemeACoarseTuning = val;
142 break;
144 case AL_VOCAL_MORPHER_PHONEMEB:
145 if(auto phenomeopt = PhenomeFromEnum(val))
146 props->Vmorpher.PhonemeB = *phenomeopt;
147 else
148 throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b out of range: 0x%04x", val};
149 break;
151 case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
152 if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING))
153 throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b coarse tuning out of range"};
154 props->Vmorpher.PhonemeBCoarseTuning = val;
155 break;
157 case AL_VOCAL_MORPHER_WAVEFORM:
158 if(auto formopt = WaveformFromEmum(val))
159 props->Vmorpher.Waveform = *formopt;
160 else
161 throw effect_exception{AL_INVALID_VALUE, "Vocal morpher waveform out of range: 0x%04x", val};
162 break;
164 default:
165 throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
166 param};
169 void Vmorpher_setParamiv(EffectProps*, ALenum param, const int*)
171 throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
172 param};
174 void Vmorpher_setParamf(EffectProps *props, ALenum param, float val)
176 switch(param)
178 case AL_VOCAL_MORPHER_RATE:
179 if(!(val >= AL_VOCAL_MORPHER_MIN_RATE && val <= AL_VOCAL_MORPHER_MAX_RATE))
180 throw effect_exception{AL_INVALID_VALUE, "Vocal morpher rate out of range"};
181 props->Vmorpher.Rate = val;
182 break;
184 default:
185 throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x",
186 param};
189 void Vmorpher_setParamfv(EffectProps *props, ALenum param, const float *vals)
190 { Vmorpher_setParamf(props, param, vals[0]); }
192 void Vmorpher_getParami(const EffectProps *props, ALenum param, int* val)
194 switch(param)
196 case AL_VOCAL_MORPHER_PHONEMEA:
197 *val = EnumFromPhenome(props->Vmorpher.PhonemeA);
198 break;
200 case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
201 *val = props->Vmorpher.PhonemeACoarseTuning;
202 break;
204 case AL_VOCAL_MORPHER_PHONEMEB:
205 *val = EnumFromPhenome(props->Vmorpher.PhonemeB);
206 break;
208 case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
209 *val = props->Vmorpher.PhonemeBCoarseTuning;
210 break;
212 case AL_VOCAL_MORPHER_WAVEFORM:
213 *val = EnumFromWaveform(props->Vmorpher.Waveform);
214 break;
216 default:
217 throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
218 param};
221 void Vmorpher_getParamiv(const EffectProps*, ALenum param, int*)
223 throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
224 param};
226 void Vmorpher_getParamf(const EffectProps *props, ALenum param, float *val)
228 switch(param)
230 case AL_VOCAL_MORPHER_RATE:
231 *val = props->Vmorpher.Rate;
232 break;
234 default:
235 throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x",
236 param};
239 void Vmorpher_getParamfv(const EffectProps *props, ALenum param, float *vals)
240 { Vmorpher_getParamf(props, param, vals); }
242 EffectProps genDefaultProps() noexcept
244 EffectProps props{};
245 props.Vmorpher.Rate = AL_VOCAL_MORPHER_DEFAULT_RATE;
246 props.Vmorpher.PhonemeA = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEA);
247 props.Vmorpher.PhonemeB = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEB);
248 props.Vmorpher.PhonemeACoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING;
249 props.Vmorpher.PhonemeBCoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING;
250 props.Vmorpher.Waveform = *WaveformFromEmum(AL_VOCAL_MORPHER_DEFAULT_WAVEFORM);
251 return props;
254 } // namespace
256 DEFINE_ALEFFECT_VTABLE(Vmorpher);
258 const EffectProps VmorpherEffectProps{genDefaultProps()};
260 #ifdef ALSOFT_EAX
261 namespace {
263 using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t;
265 struct EaxVocalMorpherEffectDirtyFlags
267 using EaxIsBitFieldStruct = bool;
269 EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeA : 1;
270 EaxVocalMorpherEffectDirtyFlagsValue lPhonemeACoarseTuning : 1;
271 EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeB : 1;
272 EaxVocalMorpherEffectDirtyFlagsValue lPhonemeBCoarseTuning : 1;
273 EaxVocalMorpherEffectDirtyFlagsValue ulWaveform : 1;
274 EaxVocalMorpherEffectDirtyFlagsValue flRate : 1;
275 }; // EaxPitchShifterEffectDirtyFlags
278 class EaxVocalMorpherEffect final :
279 public EaxEffect
281 public:
282 EaxVocalMorpherEffect();
284 // [[nodiscard]]
285 bool dispatch(
286 const EaxEaxCall& eax_call) override;
288 private:
289 EAXVOCALMORPHERPROPERTIES eax_{};
290 EAXVOCALMORPHERPROPERTIES eax_d_{};
291 EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{};
294 void set_eax_defaults();
297 void set_efx_phoneme_a();
299 void set_efx_phoneme_a_coarse_tuning();
301 void set_efx_phoneme_b();
303 void set_efx_phoneme_b_coarse_tuning();
305 void set_efx_waveform();
307 void set_efx_rate();
309 void set_efx_defaults();
312 // [[nodiscard]]
313 bool get(
314 const EaxEaxCall& eax_call);
317 void validate_phoneme_a(
318 unsigned long ulPhonemeA);
320 void validate_phoneme_a_coarse_tuning(
321 long lPhonemeACoarseTuning);
323 void validate_phoneme_b(
324 unsigned long ulPhonemeB);
326 void validate_phoneme_b_coarse_tuning(
327 long lPhonemeBCoarseTuning);
329 void validate_waveform(
330 unsigned long ulWaveform);
332 void validate_rate(
333 float flRate);
335 void validate_all(
336 const EAXVOCALMORPHERPROPERTIES& all);
339 void defer_phoneme_a(
340 unsigned long ulPhonemeA);
342 void defer_phoneme_a_coarse_tuning(
343 long lPhonemeACoarseTuning);
345 void defer_phoneme_b(
346 unsigned long ulPhonemeB);
348 void defer_phoneme_b_coarse_tuning(
349 long lPhonemeBCoarseTuning);
351 void defer_waveform(
352 unsigned long ulWaveform);
354 void defer_rate(
355 float flRate);
357 void defer_all(
358 const EAXVOCALMORPHERPROPERTIES& all);
361 void defer_phoneme_a(
362 const EaxEaxCall& eax_call);
364 void defer_phoneme_a_coarse_tuning(
365 const EaxEaxCall& eax_call);
367 void defer_phoneme_b(
368 const EaxEaxCall& eax_call);
370 void defer_phoneme_b_coarse_tuning(
371 const EaxEaxCall& eax_call);
373 void defer_waveform(
374 const EaxEaxCall& eax_call);
376 void defer_rate(
377 const EaxEaxCall& eax_call);
379 void defer_all(
380 const EaxEaxCall& eax_call);
383 // [[nodiscard]]
384 bool apply_deferred();
386 // [[nodiscard]]
387 bool set(
388 const EaxEaxCall& eax_call);
389 }; // EaxVocalMorpherEffect
392 class EaxVocalMorpherEffectException :
393 public EaxException
395 public:
396 explicit EaxVocalMorpherEffectException(
397 const char* message)
399 EaxException{"EAX_VOCAL_MORPHER_EFFECT", message}
402 }; // EaxVocalMorpherEffectException
405 EaxVocalMorpherEffect::EaxVocalMorpherEffect()
406 : EaxEffect{AL_EFFECT_VOCAL_MORPHER}
408 set_eax_defaults();
409 set_efx_defaults();
412 // [[nodiscard]]
413 bool EaxVocalMorpherEffect::dispatch(
414 const EaxEaxCall& eax_call)
416 return eax_call.is_get() ? get(eax_call) : set(eax_call);
419 void EaxVocalMorpherEffect::set_eax_defaults()
421 eax_.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
422 eax_.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
423 eax_.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
424 eax_.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
425 eax_.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
426 eax_.flRate = EAXVOCALMORPHER_DEFAULTRATE;
428 eax_d_ = eax_;
431 void EaxVocalMorpherEffect::set_efx_phoneme_a()
433 const auto phoneme_a = clamp(
434 static_cast<ALint>(eax_.ulPhonemeA),
435 AL_VOCAL_MORPHER_MIN_PHONEMEA,
436 AL_VOCAL_MORPHER_MAX_PHONEMEA);
438 const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a);
439 assert(efx_phoneme_a.has_value());
440 al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a;
443 void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning()
445 const auto phoneme_a_coarse_tuning = clamp(
446 static_cast<ALint>(eax_.lPhonemeACoarseTuning),
447 AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING,
448 AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING);
450 al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning;
453 void EaxVocalMorpherEffect::set_efx_phoneme_b()
455 const auto phoneme_b = clamp(
456 static_cast<ALint>(eax_.ulPhonemeB),
457 AL_VOCAL_MORPHER_MIN_PHONEMEB,
458 AL_VOCAL_MORPHER_MAX_PHONEMEB);
460 const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b);
461 assert(efx_phoneme_b.has_value());
462 al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b;
465 void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning()
467 const auto phoneme_b_coarse_tuning = clamp(
468 static_cast<ALint>(eax_.lPhonemeBCoarseTuning),
469 AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING,
470 AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING);
472 al_effect_props_.Vmorpher.PhonemeBCoarseTuning = phoneme_b_coarse_tuning;
475 void EaxVocalMorpherEffect::set_efx_waveform()
477 const auto waveform = clamp(
478 static_cast<ALint>(eax_.ulWaveform),
479 AL_VOCAL_MORPHER_MIN_WAVEFORM,
480 AL_VOCAL_MORPHER_MAX_WAVEFORM);
482 const auto wfx_waveform = WaveformFromEmum(waveform);
483 assert(wfx_waveform.has_value());
484 al_effect_props_.Vmorpher.Waveform = *wfx_waveform;
487 void EaxVocalMorpherEffect::set_efx_rate()
489 const auto rate = clamp(
490 eax_.flRate,
491 AL_VOCAL_MORPHER_MIN_RATE,
492 AL_VOCAL_MORPHER_MAX_RATE);
494 al_effect_props_.Vmorpher.Rate = rate;
497 void EaxVocalMorpherEffect::set_efx_defaults()
499 set_efx_phoneme_a();
500 set_efx_phoneme_a_coarse_tuning();
501 set_efx_phoneme_b();
502 set_efx_phoneme_b_coarse_tuning();
503 set_efx_waveform();
504 set_efx_rate();
507 // [[nodiscard]]
508 bool EaxVocalMorpherEffect::get(
509 const EaxEaxCall& eax_call)
511 switch (eax_call.get_property_id())
513 case EAXVOCALMORPHER_NONE:
514 break;
516 case EAXVOCALMORPHER_ALLPARAMETERS:
517 eax_call.set_value<EaxVocalMorpherEffectException>(eax_);
518 break;
520 case EAXVOCALMORPHER_PHONEMEA:
521 eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeA);
522 break;
524 case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
525 eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeACoarseTuning);
526 break;
528 case EAXVOCALMORPHER_PHONEMEB:
529 eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeB);
530 break;
532 case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
533 eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeBCoarseTuning);
534 break;
536 case EAXVOCALMORPHER_WAVEFORM:
537 eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulWaveform);
538 break;
540 case EAXVOCALMORPHER_RATE:
541 eax_call.set_value<EaxVocalMorpherEffectException>(eax_.flRate);
542 break;
544 default:
545 throw EaxVocalMorpherEffectException{"Unsupported property id."};
548 return false;
551 void EaxVocalMorpherEffect::validate_phoneme_a(
552 unsigned long ulPhonemeA)
554 eax_validate_range<EaxVocalMorpherEffectException>(
555 "Phoneme A",
556 ulPhonemeA,
557 EAXVOCALMORPHER_MINPHONEMEA,
558 EAXVOCALMORPHER_MAXPHONEMEA);
561 void EaxVocalMorpherEffect::validate_phoneme_a_coarse_tuning(
562 long lPhonemeACoarseTuning)
564 eax_validate_range<EaxVocalMorpherEffectException>(
565 "Phoneme A Coarse Tuning",
566 lPhonemeACoarseTuning,
567 EAXVOCALMORPHER_MINPHONEMEACOARSETUNING,
568 EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING);
571 void EaxVocalMorpherEffect::validate_phoneme_b(
572 unsigned long ulPhonemeB)
574 eax_validate_range<EaxVocalMorpherEffectException>(
575 "Phoneme B",
576 ulPhonemeB,
577 EAXVOCALMORPHER_MINPHONEMEB,
578 EAXVOCALMORPHER_MAXPHONEMEB);
581 void EaxVocalMorpherEffect::validate_phoneme_b_coarse_tuning(
582 long lPhonemeBCoarseTuning)
584 eax_validate_range<EaxVocalMorpherEffectException>(
585 "Phoneme B Coarse Tuning",
586 lPhonemeBCoarseTuning,
587 EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING,
588 EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING);
591 void EaxVocalMorpherEffect::validate_waveform(
592 unsigned long ulWaveform)
594 eax_validate_range<EaxVocalMorpherEffectException>(
595 "Waveform",
596 ulWaveform,
597 EAXVOCALMORPHER_MINWAVEFORM,
598 EAXVOCALMORPHER_MAXWAVEFORM);
601 void EaxVocalMorpherEffect::validate_rate(
602 float flRate)
604 eax_validate_range<EaxVocalMorpherEffectException>(
605 "Rate",
606 flRate,
607 EAXVOCALMORPHER_MINRATE,
608 EAXVOCALMORPHER_MAXRATE);
611 void EaxVocalMorpherEffect::validate_all(
612 const EAXVOCALMORPHERPROPERTIES& all)
614 validate_phoneme_a(all.ulPhonemeA);
615 validate_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
616 validate_phoneme_b(all.ulPhonemeB);
617 validate_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
618 validate_waveform(all.ulWaveform);
619 validate_rate(all.flRate);
622 void EaxVocalMorpherEffect::defer_phoneme_a(
623 unsigned long ulPhonemeA)
625 eax_d_.ulPhonemeA = ulPhonemeA;
626 eax_dirty_flags_.ulPhonemeA = (eax_.ulPhonemeA != eax_d_.ulPhonemeA);
629 void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
630 long lPhonemeACoarseTuning)
632 eax_d_.lPhonemeACoarseTuning = lPhonemeACoarseTuning;
633 eax_dirty_flags_.lPhonemeACoarseTuning = (eax_.lPhonemeACoarseTuning != eax_d_.lPhonemeACoarseTuning);
636 void EaxVocalMorpherEffect::defer_phoneme_b(
637 unsigned long ulPhonemeB)
639 eax_d_.ulPhonemeB = ulPhonemeB;
640 eax_dirty_flags_.ulPhonemeB = (eax_.ulPhonemeB != eax_d_.ulPhonemeB);
643 void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
644 long lPhonemeBCoarseTuning)
646 eax_d_.lPhonemeBCoarseTuning = lPhonemeBCoarseTuning;
647 eax_dirty_flags_.lPhonemeBCoarseTuning = (eax_.lPhonemeBCoarseTuning != eax_d_.lPhonemeBCoarseTuning);
650 void EaxVocalMorpherEffect::defer_waveform(
651 unsigned long ulWaveform)
653 eax_d_.ulWaveform = ulWaveform;
654 eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
657 void EaxVocalMorpherEffect::defer_rate(
658 float flRate)
660 eax_d_.flRate = flRate;
661 eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate);
664 void EaxVocalMorpherEffect::defer_all(
665 const EAXVOCALMORPHERPROPERTIES& all)
667 defer_phoneme_a(all.ulPhonemeA);
668 defer_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
669 defer_phoneme_b(all.ulPhonemeB);
670 defer_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
671 defer_waveform(all.ulWaveform);
672 defer_rate(all.flRate);
675 void EaxVocalMorpherEffect::defer_phoneme_a(
676 const EaxEaxCall& eax_call)
678 const auto& phoneme_a = eax_call.get_value<
679 EaxVocalMorpherEffectException,
680 const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeA)
681 >();
683 validate_phoneme_a(phoneme_a);
684 defer_phoneme_a(phoneme_a);
687 void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
688 const EaxEaxCall& eax_call)
690 const auto& phoneme_a_coarse_tuning = eax_call.get_value<
691 EaxVocalMorpherEffectException,
692 const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeACoarseTuning)
693 >();
695 validate_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
696 defer_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
699 void EaxVocalMorpherEffect::defer_phoneme_b(
700 const EaxEaxCall& eax_call)
702 const auto& phoneme_b = eax_call.get_value<
703 EaxVocalMorpherEffectException,
704 const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeB)
705 >();
707 validate_phoneme_b(phoneme_b);
708 defer_phoneme_b(phoneme_b);
711 void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
712 const EaxEaxCall& eax_call)
714 const auto& phoneme_b_coarse_tuning = eax_call.get_value<
715 EaxVocalMorpherEffectException,
716 const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeBCoarseTuning)
717 >();
719 validate_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
720 defer_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
723 void EaxVocalMorpherEffect::defer_waveform(
724 const EaxEaxCall& eax_call)
726 const auto& waveform = eax_call.get_value<
727 EaxVocalMorpherEffectException,
728 const decltype(EAXVOCALMORPHERPROPERTIES::ulWaveform)
729 >();
731 validate_waveform(waveform);
732 defer_waveform(waveform);
735 void EaxVocalMorpherEffect::defer_rate(
736 const EaxEaxCall& eax_call)
738 const auto& rate = eax_call.get_value<
739 EaxVocalMorpherEffectException,
740 const decltype(EAXVOCALMORPHERPROPERTIES::flRate)
741 >();
743 validate_rate(rate);
744 defer_rate(rate);
747 void EaxVocalMorpherEffect::defer_all(
748 const EaxEaxCall& eax_call)
750 const auto& all = eax_call.get_value<
751 EaxVocalMorpherEffectException,
752 const EAXVOCALMORPHERPROPERTIES
753 >();
755 validate_all(all);
756 defer_all(all);
759 // [[nodiscard]]
760 bool EaxVocalMorpherEffect::apply_deferred()
762 if (eax_dirty_flags_ == EaxVocalMorpherEffectDirtyFlags{})
764 return false;
767 eax_ = eax_d_;
769 if (eax_dirty_flags_.ulPhonemeA)
771 set_efx_phoneme_a();
774 if (eax_dirty_flags_.lPhonemeACoarseTuning)
776 set_efx_phoneme_a_coarse_tuning();
779 if (eax_dirty_flags_.ulPhonemeB)
781 set_efx_phoneme_b();
784 if (eax_dirty_flags_.lPhonemeBCoarseTuning)
786 set_efx_phoneme_b_coarse_tuning();
789 if (eax_dirty_flags_.ulWaveform)
791 set_efx_waveform();
794 if (eax_dirty_flags_.flRate)
796 set_efx_rate();
799 eax_dirty_flags_ = EaxVocalMorpherEffectDirtyFlags{};
801 return true;
804 // [[nodiscard]]
805 bool EaxVocalMorpherEffect::set(
806 const EaxEaxCall& eax_call)
808 switch (eax_call.get_property_id())
810 case EAXVOCALMORPHER_NONE:
811 break;
813 case EAXVOCALMORPHER_ALLPARAMETERS:
814 defer_all(eax_call);
815 break;
817 case EAXVOCALMORPHER_PHONEMEA:
818 defer_phoneme_a(eax_call);
819 break;
821 case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
822 defer_phoneme_a_coarse_tuning(eax_call);
823 break;
825 case EAXVOCALMORPHER_PHONEMEB:
826 defer_phoneme_b(eax_call);
827 break;
829 case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
830 defer_phoneme_b_coarse_tuning(eax_call);
831 break;
833 case EAXVOCALMORPHER_WAVEFORM:
834 defer_waveform(eax_call);
835 break;
837 case EAXVOCALMORPHER_RATE:
838 defer_rate(eax_call);
839 break;
841 default:
842 throw EaxVocalMorpherEffectException{"Unsupported property id."};
845 if (!eax_call.is_deferred())
847 return apply_deferred();
850 return false;
853 } // namespace
856 EaxEffectUPtr eax_create_eax_vocal_morpher_effect()
858 return std::make_unique<EaxVocalMorpherEffect>();
861 #endif // ALSOFT_EAX