Handle AL effect properties with a variant
[openal-soft.git] / al / effects / autowah.cpp
blobfe52b8be40cde2ecc0fc05828443df3d438317ba
2 #include "config.h"
4 #include <cmath>
5 #include <cstdlib>
7 #include <algorithm>
9 #include "AL/efx.h"
11 #include "alc/effects/base.h"
12 #include "effects.h"
14 #ifdef ALSOFT_EAX
15 #include "alnumeric.h"
16 #include "al/eax/effect.h"
17 #include "al/eax/exception.h"
18 #include "al/eax/utils.h"
19 #endif // ALSOFT_EAX
22 namespace {
24 constexpr EffectProps genDefaultProps() noexcept
26 AutowahProps props{};
27 props.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME;
28 props.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME;
29 props.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE;
30 props.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN;
31 return props;
34 } // namespace
36 const EffectProps AutowahEffectProps{genDefaultProps()};
38 void AutowahEffectHandler::SetParami(AutowahProps&, ALenum param, int)
39 { throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
40 void AutowahEffectHandler::SetParamiv(AutowahProps&, ALenum param, const int*)
42 throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
43 param};
46 void AutowahEffectHandler::SetParamf(AutowahProps &props, ALenum param, float val)
48 switch(param)
50 case AL_AUTOWAH_ATTACK_TIME:
51 if(!(val >= AL_AUTOWAH_MIN_ATTACK_TIME && val <= AL_AUTOWAH_MAX_ATTACK_TIME))
52 throw effect_exception{AL_INVALID_VALUE, "Autowah attack time out of range"};
53 props.AttackTime = val;
54 break;
56 case AL_AUTOWAH_RELEASE_TIME:
57 if(!(val >= AL_AUTOWAH_MIN_RELEASE_TIME && val <= AL_AUTOWAH_MAX_RELEASE_TIME))
58 throw effect_exception{AL_INVALID_VALUE, "Autowah release time out of range"};
59 props.ReleaseTime = val;
60 break;
62 case AL_AUTOWAH_RESONANCE:
63 if(!(val >= AL_AUTOWAH_MIN_RESONANCE && val <= AL_AUTOWAH_MAX_RESONANCE))
64 throw effect_exception{AL_INVALID_VALUE, "Autowah resonance out of range"};
65 props.Resonance = val;
66 break;
68 case AL_AUTOWAH_PEAK_GAIN:
69 if(!(val >= AL_AUTOWAH_MIN_PEAK_GAIN && val <= AL_AUTOWAH_MAX_PEAK_GAIN))
70 throw effect_exception{AL_INVALID_VALUE, "Autowah peak gain out of range"};
71 props.PeakGain = val;
72 break;
74 default:
75 throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
78 void AutowahEffectHandler::SetParamfv(AutowahProps &props, ALenum param, const float *vals)
79 { SetParamf(props, param, *vals); }
81 void AutowahEffectHandler::GetParami(const AutowahProps&, ALenum param, int*)
82 { throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
83 void AutowahEffectHandler::GetParamiv(const AutowahProps&, ALenum param, int*)
85 throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
86 param};
89 void AutowahEffectHandler::GetParamf(const AutowahProps &props, ALenum param, float *val)
91 switch(param)
93 case AL_AUTOWAH_ATTACK_TIME: *val = props.AttackTime; break;
94 case AL_AUTOWAH_RELEASE_TIME: *val = props.ReleaseTime; break;
95 case AL_AUTOWAH_RESONANCE: *val = props.Resonance; break;
96 case AL_AUTOWAH_PEAK_GAIN: *val = props.PeakGain; break;
98 default:
99 throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
103 void AutowahEffectHandler::GetParamfv(const AutowahProps &props, ALenum param, float *vals)
104 { GetParamf(props, param, vals); }
106 #ifdef ALSOFT_EAX
107 namespace {
109 using AutowahCommitter = EaxCommitter<EaxAutowahCommitter>;
111 struct AttackTimeValidator {
112 void operator()(float flAttackTime) const
114 eax_validate_range<AutowahCommitter::Exception>(
115 "Attack Time",
116 flAttackTime,
117 EAXAUTOWAH_MINATTACKTIME,
118 EAXAUTOWAH_MAXATTACKTIME);
120 }; // AttackTimeValidator
122 struct ReleaseTimeValidator {
123 void operator()(float flReleaseTime) const
125 eax_validate_range<AutowahCommitter::Exception>(
126 "Release Time",
127 flReleaseTime,
128 EAXAUTOWAH_MINRELEASETIME,
129 EAXAUTOWAH_MAXRELEASETIME);
131 }; // ReleaseTimeValidator
133 struct ResonanceValidator {
134 void operator()(long lResonance) const
136 eax_validate_range<AutowahCommitter::Exception>(
137 "Resonance",
138 lResonance,
139 EAXAUTOWAH_MINRESONANCE,
140 EAXAUTOWAH_MAXRESONANCE);
142 }; // ResonanceValidator
144 struct PeakLevelValidator {
145 void operator()(long lPeakLevel) const
147 eax_validate_range<AutowahCommitter::Exception>(
148 "Peak Level",
149 lPeakLevel,
150 EAXAUTOWAH_MINPEAKLEVEL,
151 EAXAUTOWAH_MAXPEAKLEVEL);
153 }; // PeakLevelValidator
155 struct AllValidator {
156 void operator()(const EAXAUTOWAHPROPERTIES& all) const
158 AttackTimeValidator{}(all.flAttackTime);
159 ReleaseTimeValidator{}(all.flReleaseTime);
160 ResonanceValidator{}(all.lResonance);
161 PeakLevelValidator{}(all.lPeakLevel);
163 }; // AllValidator
165 } // namespace
167 template<>
168 struct AutowahCommitter::Exception : public EaxException
170 explicit Exception(const char *message) : EaxException{"EAX_AUTOWAH_EFFECT", message}
174 template<>
175 [[noreturn]] void AutowahCommitter::fail(const char *message)
177 throw Exception{message};
180 bool EaxAutowahCommitter::commit(const EAXAUTOWAHPROPERTIES &props)
182 if(auto *cur = std::get_if<EAXAUTOWAHPROPERTIES>(&mEaxProps); cur && *cur == props)
183 return false;
185 mEaxProps = props;
186 mAlProps = [&]{
187 AutowahProps ret{};
188 ret.AttackTime = props.flAttackTime;
189 ret.ReleaseTime = props.flReleaseTime;
190 ret.Resonance = level_mb_to_gain(static_cast<float>(props.lResonance));
191 ret.PeakGain = level_mb_to_gain(static_cast<float>(props.lPeakLevel));
192 return ret;
193 }();
195 return true;
198 void EaxAutowahCommitter::SetDefaults(EaxEffectProps &props)
200 static constexpr EAXAUTOWAHPROPERTIES defprops{[]
202 EAXAUTOWAHPROPERTIES ret{};
203 ret.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
204 ret.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
205 ret.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
206 ret.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
207 return ret;
208 }()};
209 props = defprops;
212 void EaxAutowahCommitter::Get(const EaxCall &call, const EAXAUTOWAHPROPERTIES &props)
214 switch(call.get_property_id())
216 case EAXAUTOWAH_NONE: break;
217 case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props); break;
218 case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.flAttackTime); break;
219 case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.flReleaseTime); break;
220 case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.lResonance); break;
221 case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.lPeakLevel); break;
222 default: fail_unknown_property_id();
226 void EaxAutowahCommitter::Set(const EaxCall &call, EAXAUTOWAHPROPERTIES &props)
228 switch(call.get_property_id())
230 case EAXAUTOWAH_NONE: break;
231 case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props); break;
232 case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.flAttackTime); break;
233 case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.flReleaseTime); break;
234 case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.lResonance); break;
235 case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.lPeakLevel); break;
236 default: fail_unknown_property_id();
240 #endif // ALSOFT_EAX