]> git.tdb.fi Git - ext/openal.git/blob - al/effects/equalizer.cpp
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / al / effects / equalizer.cpp
1
2 #include "config.h"
3
4 #include "AL/al.h"
5 #include "AL/efx.h"
6
7 #include "alc/effects/base.h"
8 #include "effects.h"
9
10 #ifdef ALSOFT_EAX
11 #include "alnumeric.h"
12 #include "al/eax/exception.h"
13 #include "al/eax/utils.h"
14 #endif // ALSOFT_EAX
15
16
17 namespace {
18
19 void Equalizer_setParami(EffectProps*, ALenum param, int)
20 { throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
21 void Equalizer_setParamiv(EffectProps*, ALenum param, const int*)
22 {
23     throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
24         param};
25 }
26 void Equalizer_setParamf(EffectProps *props, ALenum param, float val)
27 {
28     switch(param)
29     {
30     case AL_EQUALIZER_LOW_GAIN:
31         if(!(val >= AL_EQUALIZER_MIN_LOW_GAIN && val <= AL_EQUALIZER_MAX_LOW_GAIN))
32             throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band gain out of range"};
33         props->Equalizer.LowGain = val;
34         break;
35
36     case AL_EQUALIZER_LOW_CUTOFF:
37         if(!(val >= AL_EQUALIZER_MIN_LOW_CUTOFF && val <= AL_EQUALIZER_MAX_LOW_CUTOFF))
38             throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band cutoff out of range"};
39         props->Equalizer.LowCutoff = val;
40         break;
41
42     case AL_EQUALIZER_MID1_GAIN:
43         if(!(val >= AL_EQUALIZER_MIN_MID1_GAIN && val <= AL_EQUALIZER_MAX_MID1_GAIN))
44             throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band gain out of range"};
45         props->Equalizer.Mid1Gain = val;
46         break;
47
48     case AL_EQUALIZER_MID1_CENTER:
49         if(!(val >= AL_EQUALIZER_MIN_MID1_CENTER && val <= AL_EQUALIZER_MAX_MID1_CENTER))
50             throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band center out of range"};
51         props->Equalizer.Mid1Center = val;
52         break;
53
54     case AL_EQUALIZER_MID1_WIDTH:
55         if(!(val >= AL_EQUALIZER_MIN_MID1_WIDTH && val <= AL_EQUALIZER_MAX_MID1_WIDTH))
56             throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band width out of range"};
57         props->Equalizer.Mid1Width = val;
58         break;
59
60     case AL_EQUALIZER_MID2_GAIN:
61         if(!(val >= AL_EQUALIZER_MIN_MID2_GAIN && val <= AL_EQUALIZER_MAX_MID2_GAIN))
62             throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band gain out of range"};
63         props->Equalizer.Mid2Gain = val;
64         break;
65
66     case AL_EQUALIZER_MID2_CENTER:
67         if(!(val >= AL_EQUALIZER_MIN_MID2_CENTER && val <= AL_EQUALIZER_MAX_MID2_CENTER))
68             throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band center out of range"};
69         props->Equalizer.Mid2Center = val;
70         break;
71
72     case AL_EQUALIZER_MID2_WIDTH:
73         if(!(val >= AL_EQUALIZER_MIN_MID2_WIDTH && val <= AL_EQUALIZER_MAX_MID2_WIDTH))
74             throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band width out of range"};
75         props->Equalizer.Mid2Width = val;
76         break;
77
78     case AL_EQUALIZER_HIGH_GAIN:
79         if(!(val >= AL_EQUALIZER_MIN_HIGH_GAIN && val <= AL_EQUALIZER_MAX_HIGH_GAIN))
80             throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band gain out of range"};
81         props->Equalizer.HighGain = val;
82         break;
83
84     case AL_EQUALIZER_HIGH_CUTOFF:
85         if(!(val >= AL_EQUALIZER_MIN_HIGH_CUTOFF && val <= AL_EQUALIZER_MAX_HIGH_CUTOFF))
86             throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band cutoff out of range"};
87         props->Equalizer.HighCutoff = val;
88         break;
89
90     default:
91         throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param};
92     }
93 }
94 void Equalizer_setParamfv(EffectProps *props, ALenum param, const float *vals)
95 { Equalizer_setParamf(props, param, vals[0]); }
96
97 void Equalizer_getParami(const EffectProps*, ALenum param, int*)
98 { throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
99 void Equalizer_getParamiv(const EffectProps*, ALenum param, int*)
100 {
101     throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
102         param};
103 }
104 void Equalizer_getParamf(const EffectProps *props, ALenum param, float *val)
105 {
106     switch(param)
107     {
108     case AL_EQUALIZER_LOW_GAIN:
109         *val = props->Equalizer.LowGain;
110         break;
111
112     case AL_EQUALIZER_LOW_CUTOFF:
113         *val = props->Equalizer.LowCutoff;
114         break;
115
116     case AL_EQUALIZER_MID1_GAIN:
117         *val = props->Equalizer.Mid1Gain;
118         break;
119
120     case AL_EQUALIZER_MID1_CENTER:
121         *val = props->Equalizer.Mid1Center;
122         break;
123
124     case AL_EQUALIZER_MID1_WIDTH:
125         *val = props->Equalizer.Mid1Width;
126         break;
127
128     case AL_EQUALIZER_MID2_GAIN:
129         *val = props->Equalizer.Mid2Gain;
130         break;
131
132     case AL_EQUALIZER_MID2_CENTER:
133         *val = props->Equalizer.Mid2Center;
134         break;
135
136     case AL_EQUALIZER_MID2_WIDTH:
137         *val = props->Equalizer.Mid2Width;
138         break;
139
140     case AL_EQUALIZER_HIGH_GAIN:
141         *val = props->Equalizer.HighGain;
142         break;
143
144     case AL_EQUALIZER_HIGH_CUTOFF:
145         *val = props->Equalizer.HighCutoff;
146         break;
147
148     default:
149         throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param};
150     }
151 }
152 void Equalizer_getParamfv(const EffectProps *props, ALenum param, float *vals)
153 { Equalizer_getParamf(props, param, vals); }
154
155 EffectProps genDefaultProps() noexcept
156 {
157     EffectProps props{};
158     props.Equalizer.LowCutoff = AL_EQUALIZER_DEFAULT_LOW_CUTOFF;
159     props.Equalizer.LowGain = AL_EQUALIZER_DEFAULT_LOW_GAIN;
160     props.Equalizer.Mid1Center = AL_EQUALIZER_DEFAULT_MID1_CENTER;
161     props.Equalizer.Mid1Gain = AL_EQUALIZER_DEFAULT_MID1_GAIN;
162     props.Equalizer.Mid1Width = AL_EQUALIZER_DEFAULT_MID1_WIDTH;
163     props.Equalizer.Mid2Center = AL_EQUALIZER_DEFAULT_MID2_CENTER;
164     props.Equalizer.Mid2Gain = AL_EQUALIZER_DEFAULT_MID2_GAIN;
165     props.Equalizer.Mid2Width = AL_EQUALIZER_DEFAULT_MID2_WIDTH;
166     props.Equalizer.HighCutoff = AL_EQUALIZER_DEFAULT_HIGH_CUTOFF;
167     props.Equalizer.HighGain = AL_EQUALIZER_DEFAULT_HIGH_GAIN;
168     return props;
169 }
170
171 } // namespace
172
173 DEFINE_ALEFFECT_VTABLE(Equalizer);
174
175 const EffectProps EqualizerEffectProps{genDefaultProps()};
176
177 #ifdef ALSOFT_EAX
178 namespace {
179
180 using EqualizerCommitter = EaxCommitter<EaxEqualizerCommitter>;
181
182 struct LowGainValidator {
183     void operator()(long lLowGain) const
184     {
185         eax_validate_range<EqualizerCommitter::Exception>(
186             "Low Gain",
187             lLowGain,
188             EAXEQUALIZER_MINLOWGAIN,
189             EAXEQUALIZER_MAXLOWGAIN);
190     }
191 }; // LowGainValidator
192
193 struct LowCutOffValidator {
194     void operator()(float flLowCutOff) const
195     {
196         eax_validate_range<EqualizerCommitter::Exception>(
197             "Low Cutoff",
198             flLowCutOff,
199             EAXEQUALIZER_MINLOWCUTOFF,
200             EAXEQUALIZER_MAXLOWCUTOFF);
201     }
202 }; // LowCutOffValidator
203
204 struct Mid1GainValidator {
205     void operator()(long lMid1Gain) const
206     {
207         eax_validate_range<EqualizerCommitter::Exception>(
208             "Mid1 Gain",
209             lMid1Gain,
210             EAXEQUALIZER_MINMID1GAIN,
211             EAXEQUALIZER_MAXMID1GAIN);
212     }
213 }; // Mid1GainValidator
214
215 struct Mid1CenterValidator {
216     void operator()(float flMid1Center) const
217     {
218         eax_validate_range<EqualizerCommitter::Exception>(
219             "Mid1 Center",
220             flMid1Center,
221             EAXEQUALIZER_MINMID1CENTER,
222             EAXEQUALIZER_MAXMID1CENTER);
223     }
224 }; // Mid1CenterValidator
225
226 struct Mid1WidthValidator {
227     void operator()(float flMid1Width) const
228     {
229         eax_validate_range<EqualizerCommitter::Exception>(
230             "Mid1 Width",
231             flMid1Width,
232             EAXEQUALIZER_MINMID1WIDTH,
233             EAXEQUALIZER_MAXMID1WIDTH);
234     }
235 }; // Mid1WidthValidator
236
237 struct Mid2GainValidator {
238     void operator()(long lMid2Gain) const
239     {
240         eax_validate_range<EqualizerCommitter::Exception>(
241             "Mid2 Gain",
242             lMid2Gain,
243             EAXEQUALIZER_MINMID2GAIN,
244             EAXEQUALIZER_MAXMID2GAIN);
245     }
246 }; // Mid2GainValidator
247
248 struct Mid2CenterValidator {
249     void operator()(float flMid2Center) const
250     {
251         eax_validate_range<EqualizerCommitter::Exception>(
252             "Mid2 Center",
253             flMid2Center,
254             EAXEQUALIZER_MINMID2CENTER,
255             EAXEQUALIZER_MAXMID2CENTER);
256     }
257 }; // Mid2CenterValidator
258
259 struct Mid2WidthValidator {
260     void operator()(float flMid2Width) const
261     {
262         eax_validate_range<EqualizerCommitter::Exception>(
263             "Mid2 Width",
264             flMid2Width,
265             EAXEQUALIZER_MINMID2WIDTH,
266             EAXEQUALIZER_MAXMID2WIDTH);
267     }
268 }; // Mid2WidthValidator
269
270 struct HighGainValidator {
271     void operator()(long lHighGain) const
272     {
273         eax_validate_range<EqualizerCommitter::Exception>(
274             "High Gain",
275             lHighGain,
276             EAXEQUALIZER_MINHIGHGAIN,
277             EAXEQUALIZER_MAXHIGHGAIN);
278     }
279 }; // HighGainValidator
280
281 struct HighCutOffValidator {
282     void operator()(float flHighCutOff) const
283     {
284         eax_validate_range<EqualizerCommitter::Exception>(
285             "High Cutoff",
286             flHighCutOff,
287             EAXEQUALIZER_MINHIGHCUTOFF,
288             EAXEQUALIZER_MAXHIGHCUTOFF);
289     }
290 }; // HighCutOffValidator
291
292 struct AllValidator {
293     void operator()(const EAXEQUALIZERPROPERTIES& all) const
294     {
295         LowGainValidator{}(all.lLowGain);
296         LowCutOffValidator{}(all.flLowCutOff);
297         Mid1GainValidator{}(all.lMid1Gain);
298         Mid1CenterValidator{}(all.flMid1Center);
299         Mid1WidthValidator{}(all.flMid1Width);
300         Mid2GainValidator{}(all.lMid2Gain);
301         Mid2CenterValidator{}(all.flMid2Center);
302         Mid2WidthValidator{}(all.flMid2Width);
303         HighGainValidator{}(all.lHighGain);
304         HighCutOffValidator{}(all.flHighCutOff);
305     }
306 }; // AllValidator
307
308 } // namespace
309
310 template<>
311 struct EqualizerCommitter::Exception : public EaxException {
312     explicit Exception(const char* message) : EaxException{"EAX_EQUALIZER_EFFECT", message}
313     { }
314 };
315
316 template<>
317 [[noreturn]] void EqualizerCommitter::fail(const char *message)
318 {
319     throw Exception{message};
320 }
321
322 template<>
323 bool EqualizerCommitter::commit(const EaxEffectProps &props)
324 {
325     if(props.mType == mEaxProps.mType && mEaxProps.mEqualizer.lLowGain == props.mEqualizer.lLowGain
326         && mEaxProps.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff
327         && mEaxProps.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain
328         && mEaxProps.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center
329         && mEaxProps.mEqualizer.flMid1Width == props.mEqualizer.flMid1Width
330         && mEaxProps.mEqualizer.lMid2Gain == props.mEqualizer.lMid2Gain
331         && mEaxProps.mEqualizer.flMid2Center == props.mEqualizer.flMid2Center
332         && mEaxProps.mEqualizer.flMid2Width == props.mEqualizer.flMid2Width
333         && mEaxProps.mEqualizer.lHighGain == props.mEqualizer.lHighGain
334         && mEaxProps.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff)
335         return false;
336
337     mEaxProps = props;
338
339     mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lLowGain));
340     mAlProps.Equalizer.LowCutoff = props.mEqualizer.flLowCutOff;
341     mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lMid1Gain));
342     mAlProps.Equalizer.Mid1Center = props.mEqualizer.flMid1Center;
343     mAlProps.Equalizer.Mid1Width = props.mEqualizer.flMid1Width;
344     mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lMid2Gain));
345     mAlProps.Equalizer.Mid2Center = props.mEqualizer.flMid2Center;
346     mAlProps.Equalizer.Mid2Width = props.mEqualizer.flMid2Width;
347     mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lHighGain));
348     mAlProps.Equalizer.HighCutoff = props.mEqualizer.flHighCutOff;
349
350     return true;
351 }
352
353 template<>
354 void EqualizerCommitter::SetDefaults(EaxEffectProps &props)
355 {
356     props.mType = EaxEffectType::Equalizer;
357     props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
358     props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
359     props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
360     props.mEqualizer.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
361     props.mEqualizer.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
362     props.mEqualizer.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
363     props.mEqualizer.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
364     props.mEqualizer.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
365     props.mEqualizer.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
366     props.mEqualizer.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
367 }
368
369 template<>
370 void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
371 {
372     switch(call.get_property_id())
373     {
374     case EAXEQUALIZER_NONE: break;
375     case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props.mEqualizer); break;
376     case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.mEqualizer.lLowGain); break;
377     case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.mEqualizer.flLowCutOff); break;
378     case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.mEqualizer.lMid1Gain); break;
379     case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.mEqualizer.flMid1Center); break;
380     case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.mEqualizer.flMid1Width); break;
381     case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.mEqualizer.lMid2Gain); break;
382     case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.mEqualizer.flMid2Center); break;
383     case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.mEqualizer.flMid2Width); break;
384     case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.mEqualizer.lHighGain); break;
385     case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.mEqualizer.flHighCutOff); break;
386     default: fail_unknown_property_id();
387     }
388 }
389
390 template<>
391 void EqualizerCommitter::Set(const EaxCall &call, EaxEffectProps &props)
392 {
393     switch(call.get_property_id())
394     {
395     case EAXEQUALIZER_NONE: break;
396     case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props.mEqualizer); break;
397     case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.mEqualizer.lLowGain); break;
398     case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.mEqualizer.flLowCutOff); break;
399     case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.mEqualizer.lMid1Gain); break;
400     case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.mEqualizer.flMid1Center); break;
401     case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.mEqualizer.flMid1Width); break;
402     case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.mEqualizer.lMid2Gain); break;
403     case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.mEqualizer.flMid2Center); break;
404     case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.mEqualizer.flMid2Width); break;
405     case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.mEqualizer.lHighGain); break;
406     case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.mEqualizer.flHighCutOff); break;
407     default: fail_unknown_property_id();
408     }
409 }
410
411 #endif // ALSOFT_EAX