diff options
-rw-r--r-- | al/auxeffectslot.h | 8 | ||||
-rw-r--r-- | al/eax/effect.h | 14 | ||||
-rw-r--r-- | al/effects/autowah.cpp | 283 | ||||
-rw-r--r-- | al/effects/distortion.cpp | 329 |
4 files changed, 278 insertions, 356 deletions
diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index cfb8a0f2..71d05ef3 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -133,10 +133,10 @@ private: { if (guidLoadEffect != EAX_NULL_GUID && guidLoadEffect != EAX_REVERB_EFFECT && - guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT /*&& - guidLoadEffect != EAX_AUTOWAH_EFFECT*/ && - guidLoadEffect != EAX_CHORUS_EFFECT /*&& - guidLoadEffect != EAX_DISTORTION_EFFECT && + guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT && + guidLoadEffect != EAX_AUTOWAH_EFFECT && + guidLoadEffect != EAX_CHORUS_EFFECT && + guidLoadEffect != EAX_DISTORTION_EFFECT /*&& guidLoadEffect != EAX_ECHO_EFFECT && guidLoadEffect != EAX_EQUALIZER_EFFECT*/ && guidLoadEffect != EAX_FLANGER_EFFECT /*&& diff --git a/al/eax/effect.h b/al/eax/effect.h index a8dc903a..bf03fea3 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -165,12 +165,18 @@ struct EaxCommitter { static void Set(const EaxCall &call, EaxEffectProps &props); }; +struct EaxAutowahCommitter : public EaxCommitter<EaxAutowahCommitter> { + using EaxCommitter<EaxAutowahCommitter>::EaxCommitter; +}; struct EaxChorusCommitter : public EaxCommitter<EaxChorusCommitter> { using EaxCommitter<EaxChorusCommitter>::EaxCommitter; }; struct EaxCompressorCommitter : public EaxCommitter<EaxCompressorCommitter> { using EaxCommitter<EaxCompressorCommitter>::EaxCommitter; }; +struct EaxDistortionCommitter : public EaxCommitter<EaxDistortionCommitter> { + using EaxCommitter<EaxDistortionCommitter>::EaxCommitter; +}; struct EaxFlangerCommitter : public EaxCommitter<EaxFlangerCommitter> { using EaxCommitter<EaxFlangerCommitter>::EaxCommitter; }; @@ -236,8 +242,12 @@ public: return call_set_defaults<EaxReverbCommitter>(props); if(altype == AL_EFFECT_CHORUS) return call_set_defaults<EaxChorusCommitter>(props); + if(altype == AL_EFFECT_AUTOWAH) + return call_set_defaults<EaxAutowahCommitter>(props); if(altype == AL_EFFECT_COMPRESSOR) return call_set_defaults<EaxCompressorCommitter>(props); + if(altype == AL_EFFECT_DISTORTION) + return call_set_defaults<EaxDistortionCommitter>(props); if(altype == AL_EFFECT_FLANGER) return call_set_defaults<EaxFlangerCommitter>(props); return call_set_defaults<EaxNullCommitter>(props); @@ -277,8 +287,12 @@ public: return Callable<EaxReverbCommitter>(__VA_ARGS__); \ if(T == EaxEffectType::Chorus) \ return Callable<EaxChorusCommitter>(__VA_ARGS__); \ + if(T == EaxEffectType::Autowah) \ + return Callable<EaxAutowahCommitter>(__VA_ARGS__); \ if(T == EaxEffectType::Compressor) \ return Callable<EaxCompressorCommitter>(__VA_ARGS__); \ + if(T == EaxEffectType::Distortion) \ + return Callable<EaxDistortionCommitter>(__VA_ARGS__); \ if(T == EaxEffectType::Flanger) \ return Callable<EaxFlangerCommitter>(__VA_ARGS__); \ return Callable<EaxNullCommitter>(__VA_ARGS__) diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 22c3ab9f..532d7276 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -118,202 +118,161 @@ const EffectProps AutowahEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxAutoWahEffectException : public EaxException { -public: - explicit EaxAutoWahEffectException(const char* message) - : EaxException{"EAX_AUTO_WAH_EFFECT", message} - {} -}; // EaxAutoWahEffectException - -class EaxAutoWahEffect final : public EaxEffect4<EaxAutoWahEffectException> { -public: - EaxAutoWahEffect(int eax_version); - -private: - struct AttackTimeValidator { - void operator()(float flAttackTime) const - { - eax_validate_range<Exception>( - "Attack Time", - flAttackTime, - EAXAUTOWAH_MINATTACKTIME, - EAXAUTOWAH_MAXATTACKTIME); - } - }; // AttackTimeValidator - - struct ReleaseTimeValidator { - void operator()(float flReleaseTime) const - { - eax_validate_range<Exception>( - "Release Time", - flReleaseTime, - EAXAUTOWAH_MINRELEASETIME, - EAXAUTOWAH_MAXRELEASETIME); - } - }; // ReleaseTimeValidator - - struct ResonanceValidator { - void operator()(long lResonance) const - { - eax_validate_range<Exception>( - "Resonance", - lResonance, - EAXAUTOWAH_MINRESONANCE, - EAXAUTOWAH_MAXRESONANCE); - } - }; // ResonanceValidator - - struct PeakLevelValidator { - void operator()(long lPeakLevel) const - { - eax_validate_range<Exception>( - "Peak Level", - lPeakLevel, - EAXAUTOWAH_MINPEAKLEVEL, - EAXAUTOWAH_MAXPEAKLEVEL); - } - }; // PeakLevelValidator - - struct AllValidator { - void operator()(const EAXAUTOWAHPROPERTIES& all) const - { - AttackTimeValidator{}(all.flAttackTime); - ReleaseTimeValidator{}(all.flReleaseTime); - ResonanceValidator{}(all.lResonance); - PeakLevelValidator{}(all.lPeakLevel); - } - }; // AllValidator - - void set_defaults(Props4& props) override; - - void set_efx_attack_time() noexcept; - void set_efx_release_time() noexcept; - void set_efx_resonance() noexcept; - void set_efx_peak_gain() noexcept; - void set_efx_defaults() override; - - void get(const EaxCall& call, const Props4& props) override; - void set(const EaxCall& call, Props4& props) override; - bool commit_props(const Props4& props) override; -}; // EaxAutoWahEffect - -EaxAutoWahEffect::EaxAutoWahEffect(int eax_version) - : EaxEffect4{AL_EFFECT_AUTOWAH, eax_version} -{} - -void EaxAutoWahEffect::set_defaults(Props4& props) -{ - props.mType = EaxEffectType::Autowah; - props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; - props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; - props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; - props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; -} - -void EaxAutoWahEffect::set_efx_attack_time() noexcept -{ - al_effect_props_.Autowah.AttackTime = clamp( - props_.mAutowah.flAttackTime, - AL_AUTOWAH_MIN_ATTACK_TIME, - AL_AUTOWAH_MAX_ATTACK_TIME); -} - -void EaxAutoWahEffect::set_efx_release_time() noexcept -{ - al_effect_props_.Autowah.ReleaseTime = clamp( - props_.mAutowah.flReleaseTime, - AL_AUTOWAH_MIN_RELEASE_TIME, - AL_AUTOWAH_MAX_RELEASE_TIME); -} +using AutowahCommitter = EaxCommitter<EaxAutowahCommitter>; -void EaxAutoWahEffect::set_efx_resonance() noexcept -{ - al_effect_props_.Autowah.Resonance = clamp( - level_mb_to_gain(static_cast<float>(props_.mAutowah.lResonance)), - AL_AUTOWAH_MIN_RESONANCE, - AL_AUTOWAH_MAX_RESONANCE); -} +struct AttackTimeValidator { + void operator()(float flAttackTime) const + { + eax_validate_range<AutowahCommitter::Exception>( + "Attack Time", + flAttackTime, + EAXAUTOWAH_MINATTACKTIME, + EAXAUTOWAH_MAXATTACKTIME); + } +}; // AttackTimeValidator -void EaxAutoWahEffect::set_efx_peak_gain() noexcept -{ - al_effect_props_.Autowah.PeakGain = clamp( - level_mb_to_gain(static_cast<float>(props_.mAutowah.lPeakLevel)), - AL_AUTOWAH_MIN_PEAK_GAIN, - AL_AUTOWAH_MAX_PEAK_GAIN); -} +struct ReleaseTimeValidator { + void operator()(float flReleaseTime) const + { + eax_validate_range<AutowahCommitter::Exception>( + "Release Time", + flReleaseTime, + EAXAUTOWAH_MINRELEASETIME, + EAXAUTOWAH_MAXRELEASETIME); + } +}; // ReleaseTimeValidator -void EaxAutoWahEffect::set_efx_defaults() -{ - set_efx_attack_time(); - set_efx_release_time(); - set_efx_resonance(); - set_efx_peak_gain(); -} +struct ResonanceValidator { + void operator()(long lResonance) const + { + eax_validate_range<AutowahCommitter::Exception>( + "Resonance", + lResonance, + EAXAUTOWAH_MINRESONANCE, + EAXAUTOWAH_MAXRESONANCE); + } +}; // ResonanceValidator -void EaxAutoWahEffect::get(const EaxCall& call, const Props4& props) -{ - switch (call.get_property_id()) +struct PeakLevelValidator { + void operator()(long lPeakLevel) const { - case EAXAUTOWAH_NONE: break; - case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props.mAutowah); break; - case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.mAutowah.flAttackTime); break; - case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.mAutowah.flReleaseTime); break; - case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.mAutowah.lResonance); break; - case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.mAutowah.lPeakLevel); break; - default: fail_unknown_property_id(); + eax_validate_range<AutowahCommitter::Exception>( + "Peak Level", + lPeakLevel, + EAXAUTOWAH_MINPEAKLEVEL, + EAXAUTOWAH_MAXPEAKLEVEL); } -} +}; // PeakLevelValidator -void EaxAutoWahEffect::set(const EaxCall& call, Props4& props) -{ - switch (call.get_property_id()) +struct AllValidator { + void operator()(const EAXAUTOWAHPROPERTIES& all) const { - case EAXAUTOWAH_NONE: break; - case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props.mAutowah); break; - case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.mAutowah.flAttackTime); break; - case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.mAutowah.flReleaseTime); break; - case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.mAutowah.lResonance); break; - case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.mAutowah.lPeakLevel); break; - default: fail_unknown_property_id(); + AttackTimeValidator{}(all.flAttackTime); + ReleaseTimeValidator{}(all.flReleaseTime); + ResonanceValidator{}(all.lResonance); + PeakLevelValidator{}(all.lPeakLevel); } +}; // AllValidator + +} // namespace + +template<> +struct AutowahCommitter::Exception : public EaxException +{ + explicit Exception(const char *message) : EaxException{"EAX_AUTOWAH_EFFECT", message} + { } +}; + +template<> +[[noreturn]] void AutowahCommitter::fail(const char *message) +{ + throw Exception{message}; } -bool EaxAutoWahEffect::commit_props(const Props4& props) +template<> +bool AutowahCommitter::commit(const EaxEffectProps &props) { - auto is_dirty = false; + const auto orig = props_; + props_ = props; - if (props_.mAutowah.flAttackTime != props.mAutowah.flAttackTime) + auto is_dirty = bool{orig.mType != props_.mType}; + if(props_.mAutowah.flAttackTime != props.mAutowah.flAttackTime) { is_dirty = true; - set_efx_attack_time(); + al_effect_props_.Autowah.AttackTime = clamp( + props_.mAutowah.flAttackTime, + AL_AUTOWAH_MIN_ATTACK_TIME, + AL_AUTOWAH_MAX_ATTACK_TIME); } - if (props_.mAutowah.flReleaseTime != props.mAutowah.flReleaseTime) + if(props_.mAutowah.flReleaseTime != props.mAutowah.flReleaseTime) { is_dirty = true; - set_efx_release_time(); + al_effect_props_.Autowah.ReleaseTime = clamp( + props_.mAutowah.flReleaseTime, + AL_AUTOWAH_MIN_RELEASE_TIME, + AL_AUTOWAH_MAX_RELEASE_TIME); } - if (props_.mAutowah.lResonance != props.mAutowah.lResonance) + if(props_.mAutowah.lResonance != props.mAutowah.lResonance) { is_dirty = true; - set_efx_resonance(); + al_effect_props_.Autowah.Resonance = clamp( + level_mb_to_gain(static_cast<float>(props_.mAutowah.lResonance)), + AL_AUTOWAH_MIN_RESONANCE, + AL_AUTOWAH_MAX_RESONANCE); } - if (props_.mAutowah.lPeakLevel != props.mAutowah.lPeakLevel) + if(props_.mAutowah.lPeakLevel != props.mAutowah.lPeakLevel) { is_dirty = true; - set_efx_peak_gain(); + al_effect_props_.Autowah.PeakGain = clamp( + level_mb_to_gain(static_cast<float>(props_.mAutowah.lPeakLevel)), + AL_AUTOWAH_MIN_PEAK_GAIN, + AL_AUTOWAH_MAX_PEAK_GAIN); } return is_dirty; } -} // namespace +template<> +void AutowahCommitter::SetDefaults(EaxEffectProps &props) +{ + props.mType = EaxEffectType::Autowah; + props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; + props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; + props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; + props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; +} + +template<> +void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props) +{ + switch(call.get_property_id()) + { + case EAXAUTOWAH_NONE: break; + case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props.mAutowah); break; + case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.mAutowah.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.mAutowah.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.mAutowah.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.mAutowah.lPeakLevel); break; + default: fail_unknown_property_id(); + } +} -EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version) +template<> +void AutowahCommitter::Set(const EaxCall &call, EaxEffectProps &props) { - return eax_create_eax4_effect<EaxAutoWahEffect>(eax_version); + switch(call.get_property_id()) + { + case EAXAUTOWAH_NONE: break; + case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props.mAutowah); break; + case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.mAutowah.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.mAutowah.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.mAutowah.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.mAutowah.lPeakLevel); break; + default: fail_unknown_property_id(); + } } #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 5f1206ab..f91314de 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -122,235 +122,184 @@ const EffectProps DistortionEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxDistortionEffectException : public EaxException -{ -public: - explicit EaxDistortionEffectException(const char* message) - : EaxException{"EAX_DISTORTION_EFFECT", message} - {} -}; // EaxDistortionEffectException - -class EaxDistortionEffect final : public EaxEffect4<EaxDistortionEffectException> -{ -public: - EaxDistortionEffect(int eax_version); - -private: - struct EdgeValidator { - void operator()(float flEdge) const - { - eax_validate_range<Exception>( - "Edge", - flEdge, - EAXDISTORTION_MINEDGE, - EAXDISTORTION_MAXEDGE); - } - }; // EdgeValidator - - struct GainValidator { - void operator()(long lGain) const - { - eax_validate_range<Exception>( - "Gain", - lGain, - EAXDISTORTION_MINGAIN, - EAXDISTORTION_MAXGAIN); - } - }; // GainValidator - - struct LowPassCutOffValidator { - void operator()(float flLowPassCutOff) const - { - eax_validate_range<Exception>( - "Low-pass Cut-off", - flLowPassCutOff, - EAXDISTORTION_MINLOWPASSCUTOFF, - EAXDISTORTION_MAXLOWPASSCUTOFF); - } - }; // LowPassCutOffValidator - - struct EqCenterValidator { - void operator()(float flEQCenter) const - { - eax_validate_range<Exception>( - "EQ Center", - flEQCenter, - EAXDISTORTION_MINEQCENTER, - EAXDISTORTION_MAXEQCENTER); - } - }; // EqCenterValidator - - struct EqBandwidthValidator { - void operator()(float flEQBandwidth) const - { - eax_validate_range<Exception>( - "EQ Bandwidth", - flEQBandwidth, - EAXDISTORTION_MINEQBANDWIDTH, - EAXDISTORTION_MAXEQBANDWIDTH); - } - }; // EqBandwidthValidator - - struct AllValidator { - void operator()(const EAXDISTORTIONPROPERTIES& all) const - { - EdgeValidator{}(all.flEdge); - GainValidator{}(all.lGain); - LowPassCutOffValidator{}(all.flLowPassCutOff); - EqCenterValidator{}(all.flEQCenter); - EqBandwidthValidator{}(all.flEQBandwidth); - } - }; // AllValidator - - void set_defaults(Props4& props) override; - - void set_efx_edge() noexcept; - void set_efx_gain() noexcept; - void set_efx_lowpass_cutoff() noexcept; - void set_efx_eq_center() noexcept; - void set_efx_eq_bandwidth() noexcept; - void set_efx_defaults() override; - - void get(const EaxCall& call, const Props4& props) override; - void set(const EaxCall& call, Props4& props) override; - bool commit_props(const Props4& props) override; -}; // EaxDistortionEffect - -EaxDistortionEffect::EaxDistortionEffect(int eax_version) - : EaxEffect4{AL_EFFECT_DISTORTION, eax_version} -{} - -void EaxDistortionEffect::set_defaults(Props4& props) -{ - props.mType = EaxEffectType::Distortion; - props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE; - props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN; - props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; - props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; - props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; -} - -void EaxDistortionEffect::set_efx_edge() noexcept -{ - al_effect_props_.Distortion.Edge = clamp( - props_.mDistortion.flEdge, - AL_DISTORTION_MIN_EDGE, - AL_DISTORTION_MAX_EDGE); -} +using DistortionCommitter = EaxCommitter<EaxDistortionCommitter>; -void EaxDistortionEffect::set_efx_gain() noexcept -{ - al_effect_props_.Distortion.Gain = clamp( - level_mb_to_gain(static_cast<float>(props_.mDistortion.lGain)), - AL_DISTORTION_MIN_GAIN, - AL_DISTORTION_MAX_GAIN); -} - -void EaxDistortionEffect::set_efx_lowpass_cutoff() noexcept -{ - al_effect_props_.Distortion.LowpassCutoff = clamp( - props_.mDistortion.flLowPassCutOff, - AL_DISTORTION_MIN_LOWPASS_CUTOFF, - AL_DISTORTION_MAX_LOWPASS_CUTOFF); -} +struct EdgeValidator { + void operator()(float flEdge) const + { + eax_validate_range<DistortionCommitter::Exception>( + "Edge", + flEdge, + EAXDISTORTION_MINEDGE, + EAXDISTORTION_MAXEDGE); + } +}; // EdgeValidator -void EaxDistortionEffect::set_efx_eq_center() noexcept -{ - al_effect_props_.Distortion.EQCenter = clamp( - props_.mDistortion.flEQCenter, - AL_DISTORTION_MIN_EQCENTER, - AL_DISTORTION_MAX_EQCENTER); -} +struct GainValidator { + void operator()(long lGain) const + { + eax_validate_range<DistortionCommitter::Exception>( + "Gain", + lGain, + EAXDISTORTION_MINGAIN, + EAXDISTORTION_MAXGAIN); + } +}; // GainValidator -void EaxDistortionEffect::set_efx_eq_bandwidth() noexcept -{ - al_effect_props_.Distortion.EQBandwidth = clamp( - props_.mDistortion.flEdge, - AL_DISTORTION_MIN_EQBANDWIDTH, - AL_DISTORTION_MAX_EQBANDWIDTH); -} +struct LowPassCutOffValidator { + void operator()(float flLowPassCutOff) const + { + eax_validate_range<DistortionCommitter::Exception>( + "Low-pass Cut-off", + flLowPassCutOff, + EAXDISTORTION_MINLOWPASSCUTOFF, + EAXDISTORTION_MAXLOWPASSCUTOFF); + } +}; // LowPassCutOffValidator -void EaxDistortionEffect::set_efx_defaults() -{ - set_efx_edge(); - set_efx_gain(); - set_efx_lowpass_cutoff(); - set_efx_eq_center(); - set_efx_eq_bandwidth(); -} +struct EqCenterValidator { + void operator()(float flEQCenter) const + { + eax_validate_range<DistortionCommitter::Exception>( + "EQ Center", + flEQCenter, + EAXDISTORTION_MINEQCENTER, + EAXDISTORTION_MAXEQCENTER); + } +}; // EqCenterValidator -void EaxDistortionEffect::get(const EaxCall& call, const Props4& props) -{ - switch(call.get_property_id()) +struct EqBandwidthValidator { + void operator()(float flEQBandwidth) const { - case EAXDISTORTION_NONE: break; - case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props.mDistortion); break; - case EAXDISTORTION_EDGE: call.set_value<Exception>(props.mDistortion.flEdge); break; - case EAXDISTORTION_GAIN: call.set_value<Exception>(props.mDistortion.lGain); break; - case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.mDistortion.flLowPassCutOff); break; - case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.mDistortion.flEQCenter); break; - case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.mDistortion.flEQBandwidth); break; - default: fail_unknown_property_id(); + eax_validate_range<DistortionCommitter::Exception>( + "EQ Bandwidth", + flEQBandwidth, + EAXDISTORTION_MINEQBANDWIDTH, + EAXDISTORTION_MAXEQBANDWIDTH); } -} +}; // EqBandwidthValidator -void EaxDistortionEffect::set(const EaxCall& call, Props4& props) -{ - switch(call.get_property_id()) +struct AllValidator { + void operator()(const EAXDISTORTIONPROPERTIES& all) const { - case EAXDISTORTION_NONE: break; - case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props.mDistortion); break; - case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.mDistortion.flEdge); break; - case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.mDistortion.lGain); break; - case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.mDistortion.flLowPassCutOff); break; - case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.mDistortion.flEQCenter); break; - case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.mDistortion.flEQBandwidth); break; - default: fail_unknown_property_id(); + EdgeValidator{}(all.flEdge); + GainValidator{}(all.lGain); + LowPassCutOffValidator{}(all.flLowPassCutOff); + EqCenterValidator{}(all.flEQCenter); + EqBandwidthValidator{}(all.flEQBandwidth); } +}; // AllValidator + +} // namespace + +template<> +struct DistortionCommitter::Exception : public EaxException { + explicit Exception(const char *message) : EaxException{"EAX_DISTORTION_EFFECT", message} + { } +}; + +template<> +[[noreturn]] void DistortionCommitter::fail(const char *message) +{ + throw Exception{message}; } -bool EaxDistortionEffect::commit_props(const Props4& props) +template<> +bool DistortionCommitter::commit(const EaxEffectProps &props) { - auto is_dirty = false; + const auto orig = props_; + props_ = props; - if (props_.mDistortion.flEdge != props.mDistortion.flEdge) + auto is_dirty = bool{orig.mType != props_.mType}; + if(props_.mDistortion.flEdge != props.mDistortion.flEdge) { is_dirty = true; - set_efx_edge(); + al_effect_props_.Distortion.Edge = clamp( + props_.mDistortion.flEdge, + AL_DISTORTION_MIN_EDGE, + AL_DISTORTION_MAX_EDGE); } - if (props_.mDistortion.lGain != props.mDistortion.lGain) + if(props_.mDistortion.lGain != props.mDistortion.lGain) { is_dirty = true; - set_efx_gain(); + al_effect_props_.Distortion.Gain = clamp( + level_mb_to_gain(static_cast<float>(props_.mDistortion.lGain)), + AL_DISTORTION_MIN_GAIN, + AL_DISTORTION_MAX_GAIN); } - if (props_.mDistortion.flLowPassCutOff != props.mDistortion.flLowPassCutOff) + if(props_.mDistortion.flLowPassCutOff != props.mDistortion.flLowPassCutOff) { is_dirty = true; - set_efx_lowpass_cutoff(); + al_effect_props_.Distortion.LowpassCutoff = clamp( + props_.mDistortion.flLowPassCutOff, + AL_DISTORTION_MIN_LOWPASS_CUTOFF, + AL_DISTORTION_MAX_LOWPASS_CUTOFF); } - if (props_.mDistortion.flEQCenter != props.mDistortion.flEQCenter) + if(props_.mDistortion.flEQCenter != props.mDistortion.flEQCenter) { is_dirty = true; - set_efx_eq_center(); + al_effect_props_.Distortion.EQCenter = clamp( + props_.mDistortion.flEQCenter, + AL_DISTORTION_MIN_EQCENTER, + AL_DISTORTION_MAX_EQCENTER); } - if (props_.mDistortion.flEQBandwidth != props.mDistortion.flEQBandwidth) + if(props_.mDistortion.flEQBandwidth != props.mDistortion.flEQBandwidth) { is_dirty = true; - set_efx_eq_bandwidth(); + al_effect_props_.Distortion.EQBandwidth = clamp( + props_.mDistortion.flEdge, + AL_DISTORTION_MIN_EQBANDWIDTH, + AL_DISTORTION_MAX_EQBANDWIDTH); } return is_dirty; } -} // namespace +template<> +void DistortionCommitter::SetDefaults(EaxEffectProps &props) +{ + props.mType = EaxEffectType::Distortion; + props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE; + props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN; + props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; + props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; + props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; +} -EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version) +template<> +void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props) { - return eax_create_eax4_effect<EaxDistortionEffect>(eax_version); + switch(call.get_property_id()) + { + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props.mDistortion); break; + case EAXDISTORTION_EDGE: call.set_value<Exception>(props.mDistortion.flEdge); break; + case EAXDISTORTION_GAIN: call.set_value<Exception>(props.mDistortion.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.mDistortion.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.mDistortion.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.mDistortion.flEQBandwidth); break; + default: fail_unknown_property_id(); + } +} + +template<> +void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props) +{ + switch(call.get_property_id()) + { + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props.mDistortion); break; + case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.mDistortion.flEdge); break; + case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.mDistortion.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.mDistortion.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.mDistortion.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.mDistortion.flEQBandwidth); break; + default: fail_unknown_property_id(); + } } #endif // ALSOFT_EAX |