10 #include "core/effects/base.h"
15 #include "al/eax/effect.h"
16 #include "al/eax/exception.h"
17 #include "al/eax/utils.h"
23 constexpr std::optional
<VMorpherPhenome
> PhenomeFromEnum(ALenum val
) noexcept
25 #define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \
26 return VMorpherPhenome::x
63 constexpr ALenum
EnumFromPhenome(VMorpherPhenome phenome
)
65 #define HANDLE_PHENOME(x) case VMorpherPhenome::x: return AL_VOCAL_MORPHER_PHONEME_ ## x
99 throw std::runtime_error
{"Invalid phenome: "+std::to_string(static_cast<int>(phenome
))};
100 #undef HANDLE_PHENOME
103 constexpr std::optional
<VMorpherWaveform
> WaveformFromEmum(ALenum value
) noexcept
107 case AL_VOCAL_MORPHER_WAVEFORM_SINUSOID
: return VMorpherWaveform::Sinusoid
;
108 case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE
: return VMorpherWaveform::Triangle
;
109 case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH
: return VMorpherWaveform::Sawtooth
;
113 constexpr ALenum
EnumFromWaveform(VMorpherWaveform type
)
117 case VMorpherWaveform::Sinusoid
: return AL_VOCAL_MORPHER_WAVEFORM_SINUSOID
;
118 case VMorpherWaveform::Triangle
: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE
;
119 case VMorpherWaveform::Sawtooth
: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH
;
121 throw std::runtime_error
{"Invalid vocal morpher waveform: " +
122 std::to_string(static_cast<int>(type
))};
125 constexpr EffectProps
genDefaultProps() noexcept
127 VmorpherProps props
{};
128 props
.Rate
= AL_VOCAL_MORPHER_DEFAULT_RATE
;
129 props
.PhonemeA
= PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEA
).value();
130 props
.PhonemeB
= PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEB
).value();
131 props
.PhonemeACoarseTuning
= AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING
;
132 props
.PhonemeBCoarseTuning
= AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING
;
133 props
.Waveform
= WaveformFromEmum(AL_VOCAL_MORPHER_DEFAULT_WAVEFORM
).value();
139 const EffectProps VmorpherEffectProps
{genDefaultProps()};
141 void VmorpherEffectHandler::SetParami(VmorpherProps
&props
, ALenum param
, int val
)
145 case AL_VOCAL_MORPHER_PHONEMEA
:
146 if(auto phenomeopt
= PhenomeFromEnum(val
))
147 props
.PhonemeA
= *phenomeopt
;
149 throw effect_exception
{AL_INVALID_VALUE
, "Vocal morpher phoneme-a out of range: 0x%04x", val
};
152 case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING
:
153 if(!(val
>= AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING
&& val
<= AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING
))
154 throw effect_exception
{AL_INVALID_VALUE
, "Vocal morpher phoneme-a coarse tuning out of range"};
155 props
.PhonemeACoarseTuning
= val
;
158 case AL_VOCAL_MORPHER_PHONEMEB
:
159 if(auto phenomeopt
= PhenomeFromEnum(val
))
160 props
.PhonemeB
= *phenomeopt
;
162 throw effect_exception
{AL_INVALID_VALUE
, "Vocal morpher phoneme-b out of range: 0x%04x", val
};
165 case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
:
166 if(!(val
>= AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING
&& val
<= AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING
))
167 throw effect_exception
{AL_INVALID_VALUE
, "Vocal morpher phoneme-b coarse tuning out of range"};
168 props
.PhonemeBCoarseTuning
= val
;
171 case AL_VOCAL_MORPHER_WAVEFORM
:
172 if(auto formopt
= WaveformFromEmum(val
))
173 props
.Waveform
= *formopt
;
175 throw effect_exception
{AL_INVALID_VALUE
, "Vocal morpher waveform out of range: 0x%04x", val
};
179 throw effect_exception
{AL_INVALID_ENUM
, "Invalid vocal morpher integer property 0x%04x",
183 void VmorpherEffectHandler::SetParamiv(VmorpherProps
&, ALenum param
, const int*)
185 throw effect_exception
{AL_INVALID_ENUM
, "Invalid vocal morpher integer-vector property 0x%04x",
188 void VmorpherEffectHandler::SetParamf(VmorpherProps
&props
, ALenum param
, float val
)
192 case AL_VOCAL_MORPHER_RATE
:
193 if(!(val
>= AL_VOCAL_MORPHER_MIN_RATE
&& val
<= AL_VOCAL_MORPHER_MAX_RATE
))
194 throw effect_exception
{AL_INVALID_VALUE
, "Vocal morpher rate out of range"};
199 throw effect_exception
{AL_INVALID_ENUM
, "Invalid vocal morpher float property 0x%04x",
203 void VmorpherEffectHandler::SetParamfv(VmorpherProps
&props
, ALenum param
, const float *vals
)
204 { SetParamf(props
, param
, *vals
); }
206 void VmorpherEffectHandler::GetParami(const VmorpherProps
&props
, ALenum param
, int* val
)
210 case AL_VOCAL_MORPHER_PHONEMEA
: *val
= EnumFromPhenome(props
.PhonemeA
); break;
211 case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING
: *val
= props
.PhonemeACoarseTuning
; break;
212 case AL_VOCAL_MORPHER_PHONEMEB
: *val
= EnumFromPhenome(props
.PhonemeB
); break;
213 case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
: *val
= props
.PhonemeBCoarseTuning
; break;
214 case AL_VOCAL_MORPHER_WAVEFORM
: *val
= EnumFromWaveform(props
.Waveform
); break;
217 throw effect_exception
{AL_INVALID_ENUM
, "Invalid vocal morpher integer property 0x%04x",
221 void VmorpherEffectHandler::GetParamiv(const VmorpherProps
&, ALenum param
, int*)
223 throw effect_exception
{AL_INVALID_ENUM
, "Invalid vocal morpher integer-vector property 0x%04x",
226 void VmorpherEffectHandler::GetParamf(const VmorpherProps
&props
, ALenum param
, float *val
)
230 case AL_VOCAL_MORPHER_RATE
:
235 throw effect_exception
{AL_INVALID_ENUM
, "Invalid vocal morpher float property 0x%04x",
239 void VmorpherEffectHandler::GetParamfv(const VmorpherProps
&props
, ALenum param
, float *vals
)
240 { GetParamf(props
, param
, vals
); }
246 using VocalMorpherCommitter
= EaxCommitter
<EaxVocalMorpherCommitter
>;
248 struct PhonemeAValidator
{
249 void operator()(unsigned long ulPhonemeA
) const
251 eax_validate_range
<VocalMorpherCommitter::Exception
>(
254 EAXVOCALMORPHER_MINPHONEMEA
,
255 EAXVOCALMORPHER_MAXPHONEMEA
);
257 }; // PhonemeAValidator
259 struct PhonemeACoarseTuningValidator
{
260 void operator()(long lPhonemeACoarseTuning
) const
262 eax_validate_range
<VocalMorpherCommitter::Exception
>(
263 "Phoneme A Coarse Tuning",
264 lPhonemeACoarseTuning
,
265 EAXVOCALMORPHER_MINPHONEMEACOARSETUNING
,
266 EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING
);
268 }; // PhonemeACoarseTuningValidator
270 struct PhonemeBValidator
{
271 void operator()(unsigned long ulPhonemeB
) const
273 eax_validate_range
<VocalMorpherCommitter::Exception
>(
276 EAXVOCALMORPHER_MINPHONEMEB
,
277 EAXVOCALMORPHER_MAXPHONEMEB
);
279 }; // PhonemeBValidator
281 struct PhonemeBCoarseTuningValidator
{
282 void operator()(long lPhonemeBCoarseTuning
) const
284 eax_validate_range
<VocalMorpherCommitter::Exception
>(
285 "Phoneme B Coarse Tuning",
286 lPhonemeBCoarseTuning
,
287 EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING
,
288 EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING
);
290 }; // PhonemeBCoarseTuningValidator
292 struct WaveformValidator
{
293 void operator()(unsigned long ulWaveform
) const
295 eax_validate_range
<VocalMorpherCommitter::Exception
>(
298 EAXVOCALMORPHER_MINWAVEFORM
,
299 EAXVOCALMORPHER_MAXWAVEFORM
);
301 }; // WaveformValidator
303 struct RateValidator
{
304 void operator()(float flRate
) const
306 eax_validate_range
<VocalMorpherCommitter::Exception
>(
309 EAXVOCALMORPHER_MINRATE
,
310 EAXVOCALMORPHER_MAXRATE
);
314 struct AllValidator
{
315 void operator()(const EAXVOCALMORPHERPROPERTIES
& all
) const
317 PhonemeAValidator
{}(all
.ulPhonemeA
);
318 PhonemeACoarseTuningValidator
{}(all
.lPhonemeACoarseTuning
);
319 PhonemeBValidator
{}(all
.ulPhonemeB
);
320 PhonemeBCoarseTuningValidator
{}(all
.lPhonemeBCoarseTuning
);
321 WaveformValidator
{}(all
.ulWaveform
);
322 RateValidator
{}(all
.flRate
);
329 struct VocalMorpherCommitter::Exception
: public EaxException
{
330 explicit Exception(const char *message
) : EaxException
{"EAX_VOCAL_MORPHER_EFFECT", message
}
335 [[noreturn
]] void VocalMorpherCommitter::fail(const char *message
)
337 throw Exception
{message
};
340 bool EaxVocalMorpherCommitter::commit(const EAXVOCALMORPHERPROPERTIES
&props
)
342 if(auto *cur
= std::get_if
<EAXVOCALMORPHERPROPERTIES
>(&mEaxProps
); cur
&& *cur
== props
)
347 auto get_phoneme
= [](unsigned long phoneme
) noexcept
349 #define HANDLE_PHENOME(x) case x: return VMorpherPhenome::x
383 return VMorpherPhenome::A
;
384 #undef HANDLE_PHENOME
386 auto get_waveform
= [](unsigned long form
) noexcept
388 if(form
== EAX_VOCALMORPHER_SINUSOID
) return VMorpherWaveform::Sinusoid
;
389 if(form
== EAX_VOCALMORPHER_TRIANGLE
) return VMorpherWaveform::Triangle
;
390 if(form
== EAX_VOCALMORPHER_SAWTOOTH
) return VMorpherWaveform::Sawtooth
;
391 return VMorpherWaveform::Sinusoid
;
396 ret
.PhonemeA
= get_phoneme(props
.ulPhonemeA
);
397 ret
.PhonemeACoarseTuning
= static_cast<int>(props
.lPhonemeACoarseTuning
);
398 ret
.PhonemeB
= get_phoneme(props
.ulPhonemeB
);
399 ret
.PhonemeBCoarseTuning
= static_cast<int>(props
.lPhonemeBCoarseTuning
);
400 ret
.Waveform
= get_waveform(props
.ulWaveform
);
401 ret
.Rate
= props
.flRate
;
408 void EaxVocalMorpherCommitter::SetDefaults(EaxEffectProps
&props
)
410 static constexpr EAXVOCALMORPHERPROPERTIES defprops
{[]
412 EAXVOCALMORPHERPROPERTIES ret
{};
413 ret
.ulPhonemeA
= EAXVOCALMORPHER_DEFAULTPHONEMEA
;
414 ret
.lPhonemeACoarseTuning
= EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING
;
415 ret
.ulPhonemeB
= EAXVOCALMORPHER_DEFAULTPHONEMEB
;
416 ret
.lPhonemeBCoarseTuning
= EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING
;
417 ret
.ulWaveform
= EAXVOCALMORPHER_DEFAULTWAVEFORM
;
418 ret
.flRate
= EAXVOCALMORPHER_DEFAULTRATE
;
424 void EaxVocalMorpherCommitter::Get(const EaxCall
&call
, const EAXVOCALMORPHERPROPERTIES
&props
)
426 switch(call
.get_property_id())
428 case EAXVOCALMORPHER_NONE
: break;
429 case EAXVOCALMORPHER_ALLPARAMETERS
: call
.set_value
<Exception
>(props
); break;
430 case EAXVOCALMORPHER_PHONEMEA
: call
.set_value
<Exception
>(props
.ulPhonemeA
); break;
431 case EAXVOCALMORPHER_PHONEMEACOARSETUNING
: call
.set_value
<Exception
>(props
.lPhonemeACoarseTuning
); break;
432 case EAXVOCALMORPHER_PHONEMEB
: call
.set_value
<Exception
>(props
.ulPhonemeB
); break;
433 case EAXVOCALMORPHER_PHONEMEBCOARSETUNING
: call
.set_value
<Exception
>(props
.lPhonemeBCoarseTuning
); break;
434 case EAXVOCALMORPHER_WAVEFORM
: call
.set_value
<Exception
>(props
.ulWaveform
); break;
435 case EAXVOCALMORPHER_RATE
: call
.set_value
<Exception
>(props
.flRate
); break;
436 default: fail_unknown_property_id();
440 void EaxVocalMorpherCommitter::Set(const EaxCall
&call
, EAXVOCALMORPHERPROPERTIES
&props
)
442 switch(call
.get_property_id())
444 case EAXVOCALMORPHER_NONE
: break;
445 case EAXVOCALMORPHER_ALLPARAMETERS
: defer
<AllValidator
>(call
, props
); break;
446 case EAXVOCALMORPHER_PHONEMEA
: defer
<PhonemeAValidator
>(call
, props
.ulPhonemeA
); break;
447 case EAXVOCALMORPHER_PHONEMEACOARSETUNING
: defer
<PhonemeACoarseTuningValidator
>(call
, props
.lPhonemeACoarseTuning
); break;
448 case EAXVOCALMORPHER_PHONEMEB
: defer
<PhonemeBValidator
>(call
, props
.ulPhonemeB
); break;
449 case EAXVOCALMORPHER_PHONEMEBCOARSETUNING
: defer
<PhonemeBCoarseTuningValidator
>(call
, props
.lPhonemeBCoarseTuning
); break;
450 case EAXVOCALMORPHER_WAVEFORM
: defer
<WaveformValidator
>(call
, props
.ulWaveform
); break;
451 case EAXVOCALMORPHER_RATE
: defer
<RateValidator
>(call
, props
.flRate
); break;
452 default: fail_unknown_property_id();