diff options
Diffstat (limited to 'al/effects/vmorpher.cpp')
-rw-r--r-- | al/effects/vmorpher.cpp | 480 |
1 files changed, 211 insertions, 269 deletions
diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index d8d74b94..f8be5856 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -258,116 +258,174 @@ const EffectProps VmorpherEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxVocalMorpherEffectException : public EaxException { -public: - explicit EaxVocalMorpherEffectException(const char* message) - : EaxException{"EAX_VOCAL_MORPHER_EFFECT", message} - {} -}; // EaxVocalMorpherEffectException - -class EaxVocalMorpherEffect final : public EaxEffect4<EaxVocalMorpherEffectException> { -public: - EaxVocalMorpherEffect(int eax_version); - -private: - struct PhonemeAValidator { - void operator()(unsigned long ulPhonemeA) const - { - eax_validate_range<Exception>( - "Phoneme A", - ulPhonemeA, - EAXVOCALMORPHER_MINPHONEMEA, - EAXVOCALMORPHER_MAXPHONEMEA); - } - }; // PhonemeAValidator +using VocalMorpherCommitter = EaxCommitter<EaxVocalMorpherCommitter>; - struct PhonemeACoarseTuningValidator { - void operator()(long lPhonemeACoarseTuning) const - { - eax_validate_range<Exception>( - "Phoneme A Coarse Tuning", - lPhonemeACoarseTuning, - EAXVOCALMORPHER_MINPHONEMEACOARSETUNING, - EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING); - } - }; // PhonemeACoarseTuningValidator +struct PhonemeAValidator { + void operator()(unsigned long ulPhonemeA) const + { + eax_validate_range<VocalMorpherCommitter::Exception>( + "Phoneme A", + ulPhonemeA, + EAXVOCALMORPHER_MINPHONEMEA, + EAXVOCALMORPHER_MAXPHONEMEA); + } +}; // PhonemeAValidator - struct PhonemeBValidator { - void operator()(unsigned long ulPhonemeB) const - { - eax_validate_range<Exception>( - "Phoneme B", - ulPhonemeB, - EAXVOCALMORPHER_MINPHONEMEB, - EAXVOCALMORPHER_MAXPHONEMEB); - } - }; // PhonemeBValidator +struct PhonemeACoarseTuningValidator { + void operator()(long lPhonemeACoarseTuning) const + { + eax_validate_range<VocalMorpherCommitter::Exception>( + "Phoneme A Coarse Tuning", + lPhonemeACoarseTuning, + EAXVOCALMORPHER_MINPHONEMEACOARSETUNING, + EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING); + } +}; // PhonemeACoarseTuningValidator - struct PhonemeBCoarseTuningValidator { - void operator()(long lPhonemeBCoarseTuning) const - { - eax_validate_range<Exception>( - "Phoneme B Coarse Tuning", - lPhonemeBCoarseTuning, - EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING, - EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING); - } - }; // PhonemeBCoarseTuningValidator +struct PhonemeBValidator { + void operator()(unsigned long ulPhonemeB) const + { + eax_validate_range<VocalMorpherCommitter::Exception>( + "Phoneme B", + ulPhonemeB, + EAXVOCALMORPHER_MINPHONEMEB, + EAXVOCALMORPHER_MAXPHONEMEB); + } +}; // PhonemeBValidator - struct WaveformValidator { - void operator()(unsigned long ulWaveform) const - { - eax_validate_range<Exception>( - "Waveform", - ulWaveform, - EAXVOCALMORPHER_MINWAVEFORM, - EAXVOCALMORPHER_MAXWAVEFORM); - } - }; // WaveformValidator +struct PhonemeBCoarseTuningValidator { + void operator()(long lPhonemeBCoarseTuning) const + { + eax_validate_range<VocalMorpherCommitter::Exception>( + "Phoneme B Coarse Tuning", + lPhonemeBCoarseTuning, + EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING, + EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING); + } +}; // PhonemeBCoarseTuningValidator - struct RateValidator { - void operator()(float flRate) const - { - eax_validate_range<Exception>( - "Rate", - flRate, - EAXVOCALMORPHER_MINRATE, - EAXVOCALMORPHER_MAXRATE); - } - }; // RateValidator +struct WaveformValidator { + void operator()(unsigned long ulWaveform) const + { + eax_validate_range<VocalMorpherCommitter::Exception>( + "Waveform", + ulWaveform, + EAXVOCALMORPHER_MINWAVEFORM, + EAXVOCALMORPHER_MAXWAVEFORM); + } +}; // WaveformValidator - struct AllValidator { - void operator()(const EAXVOCALMORPHERPROPERTIES& all) const - { - PhonemeAValidator{}(all.ulPhonemeA); - PhonemeACoarseTuningValidator{}(all.lPhonemeACoarseTuning); - PhonemeBValidator{}(all.ulPhonemeB); - PhonemeBCoarseTuningValidator{}(all.lPhonemeBCoarseTuning); - WaveformValidator{}(all.ulWaveform); - RateValidator{}(all.flRate); - } - }; // AllValidator +struct RateValidator { + void operator()(float flRate) const + { + eax_validate_range<VocalMorpherCommitter::Exception>( + "Rate", + flRate, + EAXVOCALMORPHER_MINRATE, + EAXVOCALMORPHER_MAXRATE); + } +}; // RateValidator - void set_defaults(Props4& props) override; +struct AllValidator { + void operator()(const EAXVOCALMORPHERPROPERTIES& all) const + { + PhonemeAValidator{}(all.ulPhonemeA); + PhonemeACoarseTuningValidator{}(all.lPhonemeACoarseTuning); + PhonemeBValidator{}(all.ulPhonemeB); + PhonemeBCoarseTuningValidator{}(all.lPhonemeBCoarseTuning); + WaveformValidator{}(all.ulWaveform); + RateValidator{}(all.flRate); + } +}; // AllValidator - void set_efx_phoneme_a(); - void set_efx_phoneme_a_coarse_tuning() noexcept; - void set_efx_phoneme_b(); - void set_efx_phoneme_b_coarse_tuning() noexcept; - void set_efx_waveform(); - void set_efx_rate() noexcept; - void set_efx_defaults() override; +} // namespace - void get(const EaxCall& call, const Props4& props) override; - void set(const EaxCall& call, Props4& props) override; - bool commit_props(const Props4& props) override; -}; // EaxVocalMorpherEffect +template<> +struct VocalMorpherCommitter::Exception : public EaxException { + explicit Exception(const char *message) : EaxException{"EAX_VOCAL_MORPHER_EFFECT", message} + { } +}; -EaxVocalMorpherEffect::EaxVocalMorpherEffect(int eax_version) - : EaxEffect4{AL_EFFECT_VOCAL_MORPHER, eax_version} -{} +template<> +[[noreturn]] void VocalMorpherCommitter::fail(const char *message) +{ + throw Exception{message}; +} -void EaxVocalMorpherEffect::set_defaults(Props4& props) +template<> +bool VocalMorpherCommitter::commit(const EaxEffectProps &props) +{ + const auto orig = props_; + props_ = props; + + if(orig.mType == props_.mType + && props_.mVocalMorpher.ulPhonemeA == props.mVocalMorpher.ulPhonemeA + && props_.mVocalMorpher.lPhonemeACoarseTuning == props.mVocalMorpher.lPhonemeACoarseTuning + && props_.mVocalMorpher.ulPhonemeB == props.mVocalMorpher.ulPhonemeB + && props_.mVocalMorpher.lPhonemeBCoarseTuning == props.mVocalMorpher.lPhonemeBCoarseTuning + && props_.mVocalMorpher.ulWaveform == props.mVocalMorpher.ulWaveform + && props_.mVocalMorpher.flRate == props.mVocalMorpher.flRate) + return false; + + auto get_phoneme = [](unsigned long phoneme) noexcept + { +#define HANDLE_PHENOME(x) case x: return VMorpherPhenome::x + switch(phoneme) + { + HANDLE_PHENOME(A); + HANDLE_PHENOME(E); + HANDLE_PHENOME(I); + HANDLE_PHENOME(O); + HANDLE_PHENOME(U); + HANDLE_PHENOME(AA); + HANDLE_PHENOME(AE); + HANDLE_PHENOME(AH); + HANDLE_PHENOME(AO); + HANDLE_PHENOME(EH); + HANDLE_PHENOME(ER); + HANDLE_PHENOME(IH); + HANDLE_PHENOME(IY); + HANDLE_PHENOME(UH); + HANDLE_PHENOME(UW); + HANDLE_PHENOME(B); + HANDLE_PHENOME(D); + HANDLE_PHENOME(F); + HANDLE_PHENOME(G); + HANDLE_PHENOME(J); + HANDLE_PHENOME(K); + HANDLE_PHENOME(L); + HANDLE_PHENOME(M); + HANDLE_PHENOME(N); + HANDLE_PHENOME(P); + HANDLE_PHENOME(R); + HANDLE_PHENOME(S); + HANDLE_PHENOME(T); + HANDLE_PHENOME(V); + HANDLE_PHENOME(Z); + } + return VMorpherPhenome::A; +#undef HANDLE_PHENOME + }; + auto get_waveform = [](unsigned long form) noexcept + { + if(form == EAX_VOCALMORPHER_SINUSOID) return VMorpherWaveform::Sinusoid; + if(form == EAX_VOCALMORPHER_TRIANGLE) return VMorpherWaveform::Triangle; + if(form == EAX_VOCALMORPHER_SAWTOOTH) return VMorpherWaveform::Sawtooth; + return VMorpherWaveform::Sinusoid; + }; + + al_effect_props_.Vmorpher.PhonemeA = get_phoneme(props_.mVocalMorpher.ulPhonemeA); + al_effect_props_.Vmorpher.PhonemeACoarseTuning = static_cast<ALint>(props_.mVocalMorpher.lPhonemeACoarseTuning); + al_effect_props_.Vmorpher.PhonemeB = get_phoneme(props_.mVocalMorpher.ulPhonemeB); + al_effect_props_.Vmorpher.PhonemeBCoarseTuning = static_cast<ALint>(props_.mVocalMorpher.lPhonemeBCoarseTuning); + al_effect_props_.Vmorpher.Waveform = get_waveform(props_.mVocalMorpher.ulWaveform); + al_effect_props_.Vmorpher.Rate = props_.mVocalMorpher.flRate; + + return true; +} + +template<> +void VocalMorpherCommitter::SetDefaults(EaxEffectProps &props) { props.mType = EaxEffectType::VocalMorpher; props.mVocalMorpher.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; @@ -378,202 +436,86 @@ void EaxVocalMorpherEffect::set_defaults(Props4& props) props.mVocalMorpher.flRate = EAXVOCALMORPHER_DEFAULTRATE; } -void EaxVocalMorpherEffect::set_efx_phoneme_a() -{ - const auto phoneme_a = clamp( - static_cast<ALint>(props_.mVocalMorpher.ulPhonemeA), - AL_VOCAL_MORPHER_MIN_PHONEMEA, - AL_VOCAL_MORPHER_MAX_PHONEMEA); - const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a); - assert(efx_phoneme_a.has_value()); - al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a; -} - -void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() noexcept -{ - const auto phoneme_a_coarse_tuning = clamp( - static_cast<ALint>(props_.mVocalMorpher.lPhonemeACoarseTuning), - AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING, - AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING); - al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning; -} - -void EaxVocalMorpherEffect::set_efx_phoneme_b() -{ - const auto phoneme_b = clamp( - static_cast<ALint>(props_.mVocalMorpher.ulPhonemeB), - AL_VOCAL_MORPHER_MIN_PHONEMEB, - AL_VOCAL_MORPHER_MAX_PHONEMEB); - const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b); - assert(efx_phoneme_b.has_value()); - al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b; -} - -void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() noexcept -{ - al_effect_props_.Vmorpher.PhonemeBCoarseTuning = clamp( - static_cast<ALint>(props_.mVocalMorpher.lPhonemeBCoarseTuning), - AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING, - AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING); -} - -void EaxVocalMorpherEffect::set_efx_waveform() -{ - const auto waveform = clamp( - static_cast<ALint>(props_.mVocalMorpher.ulWaveform), - AL_VOCAL_MORPHER_MIN_WAVEFORM, - AL_VOCAL_MORPHER_MAX_WAVEFORM); - const auto wfx_waveform = WaveformFromEmum(waveform); - assert(wfx_waveform.has_value()); - al_effect_props_.Vmorpher.Waveform = *wfx_waveform; -} - -void EaxVocalMorpherEffect::set_efx_rate() noexcept -{ - al_effect_props_.Vmorpher.Rate = clamp( - props_.mVocalMorpher.flRate, - AL_VOCAL_MORPHER_MIN_RATE, - AL_VOCAL_MORPHER_MAX_RATE); -} - -void EaxVocalMorpherEffect::set_efx_defaults() -{ - set_efx_phoneme_a(); - set_efx_phoneme_a_coarse_tuning(); - set_efx_phoneme_b(); - set_efx_phoneme_b_coarse_tuning(); - set_efx_waveform(); - set_efx_rate(); -} - -void EaxVocalMorpherEffect::get(const EaxCall& call, const Props4& props) +template<> +void VocalMorpherCommitter::Get(const EaxCall &call, const EaxEffectProps &props) { switch(call.get_property_id()) { - case EAXVOCALMORPHER_NONE: - break; + case EAXVOCALMORPHER_NONE: + break; - case EAXVOCALMORPHER_ALLPARAMETERS: - call.set_value<Exception>(props.mVocalMorpher); - break; + case EAXVOCALMORPHER_ALLPARAMETERS: + call.set_value<Exception>(props.mVocalMorpher); + break; - case EAXVOCALMORPHER_PHONEMEA: - call.set_value<Exception>(props.mVocalMorpher.ulPhonemeA); - break; + case EAXVOCALMORPHER_PHONEMEA: + call.set_value<Exception>(props.mVocalMorpher.ulPhonemeA); + break; - case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - call.set_value<Exception>(props.mVocalMorpher.lPhonemeACoarseTuning); - break; + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: + call.set_value<Exception>(props.mVocalMorpher.lPhonemeACoarseTuning); + break; - case EAXVOCALMORPHER_PHONEMEB: - call.set_value<Exception>(props.mVocalMorpher.ulPhonemeB); - break; + case EAXVOCALMORPHER_PHONEMEB: + call.set_value<Exception>(props.mVocalMorpher.ulPhonemeB); + break; - case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - call.set_value<Exception>(props.mVocalMorpher.lPhonemeBCoarseTuning); - break; + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: + call.set_value<Exception>(props.mVocalMorpher.lPhonemeBCoarseTuning); + break; - case EAXVOCALMORPHER_WAVEFORM: - call.set_value<Exception>(props.mVocalMorpher.ulWaveform); - break; + case EAXVOCALMORPHER_WAVEFORM: + call.set_value<Exception>(props.mVocalMorpher.ulWaveform); + break; - case EAXVOCALMORPHER_RATE: - call.set_value<Exception>(props.mVocalMorpher.flRate); - break; + case EAXVOCALMORPHER_RATE: + call.set_value<Exception>(props.mVocalMorpher.flRate); + break; - default: - fail_unknown_property_id(); + default: + fail_unknown_property_id(); } } -void EaxVocalMorpherEffect::set(const EaxCall& call, Props4& props) +template<> +void VocalMorpherCommitter::Set(const EaxCall &call, EaxEffectProps &props) { switch(call.get_property_id()) { - case EAXVOCALMORPHER_NONE: - break; - - case EAXVOCALMORPHER_ALLPARAMETERS: - defer<AllValidator>(call, props.mVocalMorpher); - break; - - case EAXVOCALMORPHER_PHONEMEA: - defer<PhonemeAValidator>(call, props.mVocalMorpher.ulPhonemeA); - break; - - case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - defer<PhonemeACoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeACoarseTuning); - break; - - case EAXVOCALMORPHER_PHONEMEB: - defer<PhonemeBValidator>(call, props.mVocalMorpher.ulPhonemeB); - break; - - case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - defer<PhonemeBCoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeBCoarseTuning); - break; - - case EAXVOCALMORPHER_WAVEFORM: - defer<WaveformValidator>(call, props.mVocalMorpher.ulWaveform); - break; - - case EAXVOCALMORPHER_RATE: - defer<RateValidator>(call, props.mVocalMorpher.flRate); - break; + case EAXVOCALMORPHER_NONE: + break; - default: - fail_unknown_property_id(); - } -} + case EAXVOCALMORPHER_ALLPARAMETERS: + defer<AllValidator>(call, props.mVocalMorpher); + break; -bool EaxVocalMorpherEffect::commit_props(const Props4& props) -{ - auto is_dirty = false; + case EAXVOCALMORPHER_PHONEMEA: + defer<PhonemeAValidator>(call, props.mVocalMorpher.ulPhonemeA); + break; - if (props_.mVocalMorpher.ulPhonemeA != props.mVocalMorpher.ulPhonemeA) - { - is_dirty = true; - set_efx_phoneme_a(); - } + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: + defer<PhonemeACoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeACoarseTuning); + break; - if (props_.mVocalMorpher.lPhonemeACoarseTuning != props.mVocalMorpher.lPhonemeACoarseTuning) - { - is_dirty = true; - set_efx_phoneme_a_coarse_tuning(); - } + case EAXVOCALMORPHER_PHONEMEB: + defer<PhonemeBValidator>(call, props.mVocalMorpher.ulPhonemeB); + break; - if (props_.mVocalMorpher.ulPhonemeB != props.mVocalMorpher.ulPhonemeB) - { - is_dirty = true; - set_efx_phoneme_b(); - } + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: + defer<PhonemeBCoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeBCoarseTuning); + break; - if (props_.mVocalMorpher.lPhonemeBCoarseTuning != props.mVocalMorpher.lPhonemeBCoarseTuning) - { - is_dirty = true; - set_efx_phoneme_b_coarse_tuning(); - } + case EAXVOCALMORPHER_WAVEFORM: + defer<WaveformValidator>(call, props.mVocalMorpher.ulWaveform); + break; - if (props_.mVocalMorpher.ulWaveform != props.mVocalMorpher.ulWaveform) - { - is_dirty = true; - set_efx_waveform(); - } + case EAXVOCALMORPHER_RATE: + defer<RateValidator>(call, props.mVocalMorpher.flRate); + break; - if (props_.mVocalMorpher.flRate != props.mVocalMorpher.flRate) - { - is_dirty = true; - set_efx_rate(); + default: + fail_unknown_property_id(); } - - return is_dirty; -} - -} // namespace - -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(int eax_version) -{ - return eax_create_eax4_effect<EaxVocalMorpherEffect>(eax_version); } #endif // ALSOFT_EAX |