]> git.tdb.fi Git - ext/openal.git/blob - al/effects/distortion.cpp
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / al / effects / distortion.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 Distortion_setParami(EffectProps*, ALenum param, int)
20 { throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; }
21 void Distortion_setParamiv(EffectProps*, ALenum param, const int*)
22 {
23     throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x",
24         param};
25 }
26 void Distortion_setParamf(EffectProps *props, ALenum param, float val)
27 {
28     switch(param)
29     {
30     case AL_DISTORTION_EDGE:
31         if(!(val >= AL_DISTORTION_MIN_EDGE && val <= AL_DISTORTION_MAX_EDGE))
32             throw effect_exception{AL_INVALID_VALUE, "Distortion edge out of range"};
33         props->Distortion.Edge = val;
34         break;
35
36     case AL_DISTORTION_GAIN:
37         if(!(val >= AL_DISTORTION_MIN_GAIN && val <= AL_DISTORTION_MAX_GAIN))
38             throw effect_exception{AL_INVALID_VALUE, "Distortion gain out of range"};
39         props->Distortion.Gain = val;
40         break;
41
42     case AL_DISTORTION_LOWPASS_CUTOFF:
43         if(!(val >= AL_DISTORTION_MIN_LOWPASS_CUTOFF && val <= AL_DISTORTION_MAX_LOWPASS_CUTOFF))
44             throw effect_exception{AL_INVALID_VALUE, "Distortion low-pass cutoff out of range"};
45         props->Distortion.LowpassCutoff = val;
46         break;
47
48     case AL_DISTORTION_EQCENTER:
49         if(!(val >= AL_DISTORTION_MIN_EQCENTER && val <= AL_DISTORTION_MAX_EQCENTER))
50             throw effect_exception{AL_INVALID_VALUE, "Distortion EQ center out of range"};
51         props->Distortion.EQCenter = val;
52         break;
53
54     case AL_DISTORTION_EQBANDWIDTH:
55         if(!(val >= AL_DISTORTION_MIN_EQBANDWIDTH && val <= AL_DISTORTION_MAX_EQBANDWIDTH))
56             throw effect_exception{AL_INVALID_VALUE, "Distortion EQ bandwidth out of range"};
57         props->Distortion.EQBandwidth = val;
58         break;
59
60     default:
61         throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param};
62     }
63 }
64 void Distortion_setParamfv(EffectProps *props, ALenum param, const float *vals)
65 { Distortion_setParamf(props, param, vals[0]); }
66
67 void Distortion_getParami(const EffectProps*, ALenum param, int*)
68 { throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; }
69 void Distortion_getParamiv(const EffectProps*, ALenum param, int*)
70 {
71     throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x",
72         param};
73 }
74 void Distortion_getParamf(const EffectProps *props, ALenum param, float *val)
75 {
76     switch(param)
77     {
78     case AL_DISTORTION_EDGE:
79         *val = props->Distortion.Edge;
80         break;
81
82     case AL_DISTORTION_GAIN:
83         *val = props->Distortion.Gain;
84         break;
85
86     case AL_DISTORTION_LOWPASS_CUTOFF:
87         *val = props->Distortion.LowpassCutoff;
88         break;
89
90     case AL_DISTORTION_EQCENTER:
91         *val = props->Distortion.EQCenter;
92         break;
93
94     case AL_DISTORTION_EQBANDWIDTH:
95         *val = props->Distortion.EQBandwidth;
96         break;
97
98     default:
99         throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param};
100     }
101 }
102 void Distortion_getParamfv(const EffectProps *props, ALenum param, float *vals)
103 { Distortion_getParamf(props, param, vals); }
104
105 EffectProps genDefaultProps() noexcept
106 {
107     EffectProps props{};
108     props.Distortion.Edge = AL_DISTORTION_DEFAULT_EDGE;
109     props.Distortion.Gain = AL_DISTORTION_DEFAULT_GAIN;
110     props.Distortion.LowpassCutoff = AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF;
111     props.Distortion.EQCenter = AL_DISTORTION_DEFAULT_EQCENTER;
112     props.Distortion.EQBandwidth = AL_DISTORTION_DEFAULT_EQBANDWIDTH;
113     return props;
114 }
115
116 } // namespace
117
118 DEFINE_ALEFFECT_VTABLE(Distortion);
119
120 const EffectProps DistortionEffectProps{genDefaultProps()};
121
122 #ifdef ALSOFT_EAX
123 namespace {
124
125 using DistortionCommitter = EaxCommitter<EaxDistortionCommitter>;
126
127 struct EdgeValidator {
128     void operator()(float flEdge) const
129     {
130         eax_validate_range<DistortionCommitter::Exception>(
131             "Edge",
132             flEdge,
133             EAXDISTORTION_MINEDGE,
134             EAXDISTORTION_MAXEDGE);
135     }
136 }; // EdgeValidator
137
138 struct GainValidator {
139     void operator()(long lGain) const
140     {
141         eax_validate_range<DistortionCommitter::Exception>(
142             "Gain",
143             lGain,
144             EAXDISTORTION_MINGAIN,
145             EAXDISTORTION_MAXGAIN);
146     }
147 }; // GainValidator
148
149 struct LowPassCutOffValidator {
150     void operator()(float flLowPassCutOff) const
151     {
152         eax_validate_range<DistortionCommitter::Exception>(
153             "Low-pass Cut-off",
154             flLowPassCutOff,
155             EAXDISTORTION_MINLOWPASSCUTOFF,
156             EAXDISTORTION_MAXLOWPASSCUTOFF);
157     }
158 }; // LowPassCutOffValidator
159
160 struct EqCenterValidator {
161     void operator()(float flEQCenter) const
162     {
163         eax_validate_range<DistortionCommitter::Exception>(
164             "EQ Center",
165             flEQCenter,
166             EAXDISTORTION_MINEQCENTER,
167             EAXDISTORTION_MAXEQCENTER);
168     }
169 }; // EqCenterValidator
170
171 struct EqBandwidthValidator {
172     void operator()(float flEQBandwidth) const
173     {
174         eax_validate_range<DistortionCommitter::Exception>(
175             "EQ Bandwidth",
176             flEQBandwidth,
177             EAXDISTORTION_MINEQBANDWIDTH,
178             EAXDISTORTION_MAXEQBANDWIDTH);
179     }
180 }; // EqBandwidthValidator
181
182 struct AllValidator {
183     void operator()(const EAXDISTORTIONPROPERTIES& all) const
184     {
185         EdgeValidator{}(all.flEdge);
186         GainValidator{}(all.lGain);
187         LowPassCutOffValidator{}(all.flLowPassCutOff);
188         EqCenterValidator{}(all.flEQCenter);
189         EqBandwidthValidator{}(all.flEQBandwidth);
190     }
191 }; // AllValidator
192
193 } // namespace
194
195 template<>
196 struct DistortionCommitter::Exception : public EaxException {
197     explicit Exception(const char *message) : EaxException{"EAX_DISTORTION_EFFECT", message}
198     { }
199 };
200
201 template<>
202 [[noreturn]] void DistortionCommitter::fail(const char *message)
203 {
204     throw Exception{message};
205 }
206
207 template<>
208 bool DistortionCommitter::commit(const EaxEffectProps &props)
209 {
210     if(props.mType == mEaxProps.mType && mEaxProps.mDistortion.flEdge == props.mDistortion.flEdge
211         && mEaxProps.mDistortion.lGain == props.mDistortion.lGain
212         && mEaxProps.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff
213         && mEaxProps.mDistortion.flEQCenter == props.mDistortion.flEQCenter
214         && mEaxProps.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth)
215         return false;
216
217     mEaxProps = props;
218
219     mAlProps.Distortion.Edge = props.mDistortion.flEdge;
220     mAlProps.Distortion.Gain = level_mb_to_gain(static_cast<float>(props.mDistortion.lGain));
221     mAlProps.Distortion.LowpassCutoff = props.mDistortion.flLowPassCutOff;
222     mAlProps.Distortion.EQCenter = props.mDistortion.flEQCenter;
223     mAlProps.Distortion.EQBandwidth = props.mDistortion.flEdge;
224
225     return true;
226 }
227
228 template<>
229 void DistortionCommitter::SetDefaults(EaxEffectProps &props)
230 {
231     props.mType = EaxEffectType::Distortion;
232     props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE;
233     props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN;
234     props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF;
235     props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER;
236     props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH;
237 }
238
239 template<>
240 void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
241 {
242     switch(call.get_property_id())
243     {
244     case EAXDISTORTION_NONE: break;
245     case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props.mDistortion); break;
246     case EAXDISTORTION_EDGE: call.set_value<Exception>(props.mDistortion.flEdge); break;
247     case EAXDISTORTION_GAIN: call.set_value<Exception>(props.mDistortion.lGain); break;
248     case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.mDistortion.flLowPassCutOff); break;
249     case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.mDistortion.flEQCenter); break;
250     case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.mDistortion.flEQBandwidth); break;
251     default: fail_unknown_property_id();
252     }
253 }
254
255 template<>
256 void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props)
257 {
258     switch(call.get_property_id())
259     {
260     case EAXDISTORTION_NONE: break;
261     case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props.mDistortion); break;
262     case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.mDistortion.flEdge); break;
263     case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.mDistortion.lGain); break;
264     case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.mDistortion.flLowPassCutOff); break;
265     case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.mDistortion.flEQCenter); break;
266     case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.mDistortion.flEQBandwidth); break;
267     default: fail_unknown_property_id();
268     }
269 }
270
271 #endif // ALSOFT_EAX