]> git.tdb.fi Git - ext/openal.git/blob - al/effects/echo.cpp
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / al / effects / echo.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 static_assert(EchoMaxDelay >= AL_ECHO_MAX_DELAY, "Echo max delay too short");
20 static_assert(EchoMaxLRDelay >= AL_ECHO_MAX_LRDELAY, "Echo max left-right delay too short");
21
22 void Echo_setParami(EffectProps*, ALenum param, int)
23 { throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
24 void Echo_setParamiv(EffectProps*, ALenum param, const int*)
25 { throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; }
26 void Echo_setParamf(EffectProps *props, ALenum param, float val)
27 {
28     switch(param)
29     {
30     case AL_ECHO_DELAY:
31         if(!(val >= AL_ECHO_MIN_DELAY && val <= AL_ECHO_MAX_DELAY))
32             throw effect_exception{AL_INVALID_VALUE, "Echo delay out of range"};
33         props->Echo.Delay = val;
34         break;
35
36     case AL_ECHO_LRDELAY:
37         if(!(val >= AL_ECHO_MIN_LRDELAY && val <= AL_ECHO_MAX_LRDELAY))
38             throw effect_exception{AL_INVALID_VALUE, "Echo LR delay out of range"};
39         props->Echo.LRDelay = val;
40         break;
41
42     case AL_ECHO_DAMPING:
43         if(!(val >= AL_ECHO_MIN_DAMPING && val <= AL_ECHO_MAX_DAMPING))
44             throw effect_exception{AL_INVALID_VALUE, "Echo damping out of range"};
45         props->Echo.Damping = val;
46         break;
47
48     case AL_ECHO_FEEDBACK:
49         if(!(val >= AL_ECHO_MIN_FEEDBACK && val <= AL_ECHO_MAX_FEEDBACK))
50             throw effect_exception{AL_INVALID_VALUE, "Echo feedback out of range"};
51         props->Echo.Feedback = val;
52         break;
53
54     case AL_ECHO_SPREAD:
55         if(!(val >= AL_ECHO_MIN_SPREAD && val <= AL_ECHO_MAX_SPREAD))
56             throw effect_exception{AL_INVALID_VALUE, "Echo spread out of range"};
57         props->Echo.Spread = val;
58         break;
59
60     default:
61         throw effect_exception{AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param};
62     }
63 }
64 void Echo_setParamfv(EffectProps *props, ALenum param, const float *vals)
65 { Echo_setParamf(props, param, vals[0]); }
66
67 void Echo_getParami(const EffectProps*, ALenum param, int*)
68 { throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
69 void Echo_getParamiv(const EffectProps*, ALenum param, int*)
70 { throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; }
71 void Echo_getParamf(const EffectProps *props, ALenum param, float *val)
72 {
73     switch(param)
74     {
75     case AL_ECHO_DELAY:
76         *val = props->Echo.Delay;
77         break;
78
79     case AL_ECHO_LRDELAY:
80         *val = props->Echo.LRDelay;
81         break;
82
83     case AL_ECHO_DAMPING:
84         *val = props->Echo.Damping;
85         break;
86
87     case AL_ECHO_FEEDBACK:
88         *val = props->Echo.Feedback;
89         break;
90
91     case AL_ECHO_SPREAD:
92         *val = props->Echo.Spread;
93         break;
94
95     default:
96         throw effect_exception{AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param};
97     }
98 }
99 void Echo_getParamfv(const EffectProps *props, ALenum param, float *vals)
100 { Echo_getParamf(props, param, vals); }
101
102 EffectProps genDefaultProps() noexcept
103 {
104     EffectProps props{};
105     props.Echo.Delay    = AL_ECHO_DEFAULT_DELAY;
106     props.Echo.LRDelay  = AL_ECHO_DEFAULT_LRDELAY;
107     props.Echo.Damping  = AL_ECHO_DEFAULT_DAMPING;
108     props.Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK;
109     props.Echo.Spread   = AL_ECHO_DEFAULT_SPREAD;
110     return props;
111 }
112
113 } // namespace
114
115 DEFINE_ALEFFECT_VTABLE(Echo);
116
117 const EffectProps EchoEffectProps{genDefaultProps()};
118
119 #ifdef ALSOFT_EAX
120 namespace {
121
122 using EchoCommitter = EaxCommitter<EaxEchoCommitter>;
123
124 struct DelayValidator {
125     void operator()(float flDelay) const
126     {
127         eax_validate_range<EchoCommitter::Exception>(
128             "Delay",
129             flDelay,
130             EAXECHO_MINDELAY,
131             EAXECHO_MAXDELAY);
132     }
133 }; // DelayValidator
134
135 struct LrDelayValidator {
136     void operator()(float flLRDelay) const
137     {
138         eax_validate_range<EchoCommitter::Exception>(
139             "LR Delay",
140             flLRDelay,
141             EAXECHO_MINLRDELAY,
142             EAXECHO_MAXLRDELAY);
143     }
144 }; // LrDelayValidator
145
146 struct DampingValidator {
147     void operator()(float flDamping) const
148     {
149         eax_validate_range<EchoCommitter::Exception>(
150             "Damping",
151             flDamping,
152             EAXECHO_MINDAMPING,
153             EAXECHO_MAXDAMPING);
154     }
155 }; // DampingValidator
156
157 struct FeedbackValidator {
158     void operator()(float flFeedback) const
159     {
160         eax_validate_range<EchoCommitter::Exception>(
161             "Feedback",
162             flFeedback,
163             EAXECHO_MINFEEDBACK,
164             EAXECHO_MAXFEEDBACK);
165     }
166 }; // FeedbackValidator
167
168 struct SpreadValidator {
169     void operator()(float flSpread) const
170     {
171         eax_validate_range<EchoCommitter::Exception>(
172             "Spread",
173             flSpread,
174             EAXECHO_MINSPREAD,
175             EAXECHO_MAXSPREAD);
176     }
177 }; // SpreadValidator
178
179 struct AllValidator {
180     void operator()(const EAXECHOPROPERTIES& all) const
181     {
182         DelayValidator{}(all.flDelay);
183         LrDelayValidator{}(all.flLRDelay);
184         DampingValidator{}(all.flDamping);
185         FeedbackValidator{}(all.flFeedback);
186         SpreadValidator{}(all.flSpread);
187     }
188 }; // AllValidator
189
190 } // namespace
191
192 template<>
193 struct EchoCommitter::Exception : public EaxException {
194     explicit Exception(const char* message) : EaxException{"EAX_ECHO_EFFECT", message}
195     { }
196 };
197
198 template<>
199 [[noreturn]] void EchoCommitter::fail(const char *message)
200 {
201     throw Exception{message};
202 }
203
204 template<>
205 bool EchoCommitter::commit(const EaxEffectProps &props)
206 {
207     if(props.mType == mEaxProps.mType && mEaxProps.mEcho.flDelay == props.mEcho.flDelay
208         && mEaxProps.mEcho.flLRDelay == props.mEcho.flLRDelay
209         && mEaxProps.mEcho.flDamping == props.mEcho.flDamping
210         && mEaxProps.mEcho.flFeedback == props.mEcho.flFeedback
211         && mEaxProps.mEcho.flSpread == props.mEcho.flSpread)
212         return false;
213
214     mEaxProps = props;
215
216     mAlProps.Echo.Delay = props.mEcho.flDelay;
217     mAlProps.Echo.LRDelay = props.mEcho.flLRDelay;
218     mAlProps.Echo.Damping = props.mEcho.flDamping;
219     mAlProps.Echo.Feedback = props.mEcho.flFeedback;
220     mAlProps.Echo.Spread = props.mEcho.flSpread;
221
222     return true;
223 }
224
225 template<>
226 void EchoCommitter::SetDefaults(EaxEffectProps &props)
227 {
228     props.mType = EaxEffectType::Echo;
229     props.mEcho.flDelay = EAXECHO_DEFAULTDELAY;
230     props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY;
231     props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING;
232     props.mEcho.flFeedback = EAXECHO_DEFAULTFEEDBACK;
233     props.mEcho.flSpread = EAXECHO_DEFAULTSPREAD;
234 }
235
236 template<>
237 void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
238 {
239     switch(call.get_property_id())
240     {
241     case EAXECHO_NONE: break;
242     case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props.mEcho); break;
243     case EAXECHO_DELAY: call.set_value<Exception>(props.mEcho.flDelay); break;
244     case EAXECHO_LRDELAY: call.set_value<Exception>(props.mEcho.flLRDelay); break;
245     case EAXECHO_DAMPING: call.set_value<Exception>(props.mEcho.flDamping); break;
246     case EAXECHO_FEEDBACK: call.set_value<Exception>(props.mEcho.flFeedback); break;
247     case EAXECHO_SPREAD: call.set_value<Exception>(props.mEcho.flSpread); break;
248     default: fail_unknown_property_id();
249     }
250 }
251
252 template<>
253 void EchoCommitter::Set(const EaxCall &call, EaxEffectProps &props)
254 {
255     switch(call.get_property_id())
256     {
257     case EAXECHO_NONE: break;
258     case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props.mEcho); break;
259     case EAXECHO_DELAY: defer<DelayValidator>(call, props.mEcho.flDelay); break;
260     case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.mEcho.flLRDelay); break;
261     case EAXECHO_DAMPING: defer<DampingValidator>(call, props.mEcho.flDamping); break;
262     case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.mEcho.flFeedback); break;
263     case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.mEcho.flSpread); break;
264     default: fail_unknown_property_id();
265     }
266 }
267
268 #endif // ALSOFT_EAX