Add options to reverse local X and Y coordinates
[openal-soft.git] / al / effects / pshifter.cpp
blob1b2dcff08ee9a2d646dbeafe85716b09b0a31fc2
2 #include "config.h"
4 #include "AL/al.h"
5 #include "AL/efx.h"
7 #include "alc/effects/base.h"
8 #include "effects.h"
10 #ifdef ALSOFT_EAX
11 #include "alnumeric.h"
13 #include "al/eax_exception.h"
14 #include "al/eax_utils.h"
15 #endif // ALSOFT_EAX
18 namespace {
20 void Pshifter_setParamf(EffectProps*, ALenum param, float)
21 { throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; }
22 void Pshifter_setParamfv(EffectProps*, ALenum param, const float*)
24 throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float-vector property 0x%04x",
25 param};
28 void Pshifter_setParami(EffectProps *props, ALenum param, int val)
30 switch(param)
32 case AL_PITCH_SHIFTER_COARSE_TUNE:
33 if(!(val >= AL_PITCH_SHIFTER_MIN_COARSE_TUNE && val <= AL_PITCH_SHIFTER_MAX_COARSE_TUNE))
34 throw effect_exception{AL_INVALID_VALUE, "Pitch shifter coarse tune out of range"};
35 props->Pshifter.CoarseTune = val;
36 break;
38 case AL_PITCH_SHIFTER_FINE_TUNE:
39 if(!(val >= AL_PITCH_SHIFTER_MIN_FINE_TUNE && val <= AL_PITCH_SHIFTER_MAX_FINE_TUNE))
40 throw effect_exception{AL_INVALID_VALUE, "Pitch shifter fine tune out of range"};
41 props->Pshifter.FineTune = val;
42 break;
44 default:
45 throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x",
46 param};
49 void Pshifter_setParamiv(EffectProps *props, ALenum param, const int *vals)
50 { Pshifter_setParami(props, param, vals[0]); }
52 void Pshifter_getParami(const EffectProps *props, ALenum param, int *val)
54 switch(param)
56 case AL_PITCH_SHIFTER_COARSE_TUNE:
57 *val = props->Pshifter.CoarseTune;
58 break;
59 case AL_PITCH_SHIFTER_FINE_TUNE:
60 *val = props->Pshifter.FineTune;
61 break;
63 default:
64 throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x",
65 param};
68 void Pshifter_getParamiv(const EffectProps *props, ALenum param, int *vals)
69 { Pshifter_getParami(props, param, vals); }
71 void Pshifter_getParamf(const EffectProps*, ALenum param, float*)
72 { throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; }
73 void Pshifter_getParamfv(const EffectProps*, ALenum param, float*)
75 throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float vector-property 0x%04x",
76 param};
79 EffectProps genDefaultProps() noexcept
81 EffectProps props{};
82 props.Pshifter.CoarseTune = AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE;
83 props.Pshifter.FineTune = AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE;
84 return props;
87 } // namespace
89 DEFINE_ALEFFECT_VTABLE(Pshifter);
91 const EffectProps PshifterEffectProps{genDefaultProps()};
93 #ifdef ALSOFT_EAX
94 namespace {
96 using EaxPitchShifterEffectDirtyFlagsValue = std::uint_least8_t;
98 struct EaxPitchShifterEffectDirtyFlags
100 using EaxIsBitFieldStruct = bool;
102 EaxPitchShifterEffectDirtyFlagsValue lCoarseTune : 1;
103 EaxPitchShifterEffectDirtyFlagsValue lFineTune : 1;
104 }; // EaxPitchShifterEffectDirtyFlags
107 class EaxPitchShifterEffect final :
108 public EaxEffect
110 public:
111 EaxPitchShifterEffect();
113 void dispatch(const EaxEaxCall& eax_call) override;
115 // [[nodiscard]]
116 bool apply_deferred() override;
118 private:
119 EAXPITCHSHIFTERPROPERTIES eax_{};
120 EAXPITCHSHIFTERPROPERTIES eax_d_{};
121 EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{};
123 void set_eax_defaults();
125 void set_efx_coarse_tune();
126 void set_efx_fine_tune();
127 void set_efx_defaults();
129 void get(const EaxEaxCall& eax_call);
131 void validate_coarse_tune(long lCoarseTune);
132 void validate_fine_tune(long lFineTune);
133 void validate_all(const EAXPITCHSHIFTERPROPERTIES& all);
135 void defer_coarse_tune(long lCoarseTune);
136 void defer_fine_tune(long lFineTune);
137 void defer_all(const EAXPITCHSHIFTERPROPERTIES& all);
139 void defer_coarse_tune(const EaxEaxCall& eax_call);
140 void defer_fine_tune(const EaxEaxCall& eax_call);
141 void defer_all(const EaxEaxCall& eax_call);
143 void set(const EaxEaxCall& eax_call);
144 }; // EaxPitchShifterEffect
147 class EaxPitchShifterEffectException :
148 public EaxException
150 public:
151 explicit EaxPitchShifterEffectException(
152 const char* message)
154 EaxException{"EAX_PITCH_SHIFTER_EFFECT", message}
157 }; // EaxPitchShifterEffectException
160 EaxPitchShifterEffect::EaxPitchShifterEffect()
161 : EaxEffect{AL_EFFECT_PITCH_SHIFTER}
163 set_eax_defaults();
164 set_efx_defaults();
167 void EaxPitchShifterEffect::dispatch(const EaxEaxCall& eax_call)
169 eax_call.is_get() ? get(eax_call) : set(eax_call);
172 void EaxPitchShifterEffect::set_eax_defaults()
174 eax_.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE;
175 eax_.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE;
177 eax_d_ = eax_;
180 void EaxPitchShifterEffect::set_efx_coarse_tune()
182 const auto coarse_tune = clamp(
183 static_cast<ALint>(eax_.lCoarseTune),
184 AL_PITCH_SHIFTER_MIN_COARSE_TUNE,
185 AL_PITCH_SHIFTER_MAX_COARSE_TUNE);
187 al_effect_props_.Pshifter.CoarseTune = coarse_tune;
190 void EaxPitchShifterEffect::set_efx_fine_tune()
192 const auto fine_tune = clamp(
193 static_cast<ALint>(eax_.lFineTune),
194 AL_PITCH_SHIFTER_MIN_FINE_TUNE,
195 AL_PITCH_SHIFTER_MAX_FINE_TUNE);
197 al_effect_props_.Pshifter.FineTune = fine_tune;
200 void EaxPitchShifterEffect::set_efx_defaults()
202 set_efx_coarse_tune();
203 set_efx_fine_tune();
206 void EaxPitchShifterEffect::get(const EaxEaxCall& eax_call)
208 switch(eax_call.get_property_id())
210 case EAXPITCHSHIFTER_NONE:
211 break;
213 case EAXPITCHSHIFTER_ALLPARAMETERS:
214 eax_call.set_value<EaxPitchShifterEffectException>(eax_);
215 break;
217 case EAXPITCHSHIFTER_COARSETUNE:
218 eax_call.set_value<EaxPitchShifterEffectException>(eax_.lCoarseTune);
219 break;
221 case EAXPITCHSHIFTER_FINETUNE:
222 eax_call.set_value<EaxPitchShifterEffectException>(eax_.lFineTune);
223 break;
225 default:
226 throw EaxPitchShifterEffectException{"Unsupported property id."};
230 void EaxPitchShifterEffect::validate_coarse_tune(
231 long lCoarseTune)
233 eax_validate_range<EaxPitchShifterEffectException>(
234 "Coarse Tune",
235 lCoarseTune,
236 EAXPITCHSHIFTER_MINCOARSETUNE,
237 EAXPITCHSHIFTER_MAXCOARSETUNE);
240 void EaxPitchShifterEffect::validate_fine_tune(
241 long lFineTune)
243 eax_validate_range<EaxPitchShifterEffectException>(
244 "Fine Tune",
245 lFineTune,
246 EAXPITCHSHIFTER_MINFINETUNE,
247 EAXPITCHSHIFTER_MAXFINETUNE);
250 void EaxPitchShifterEffect::validate_all(
251 const EAXPITCHSHIFTERPROPERTIES& all)
253 validate_coarse_tune(all.lCoarseTune);
254 validate_fine_tune(all.lFineTune);
257 void EaxPitchShifterEffect::defer_coarse_tune(
258 long lCoarseTune)
260 eax_d_.lCoarseTune = lCoarseTune;
261 eax_dirty_flags_.lCoarseTune = (eax_.lCoarseTune != eax_d_.lCoarseTune);
264 void EaxPitchShifterEffect::defer_fine_tune(
265 long lFineTune)
267 eax_d_.lFineTune = lFineTune;
268 eax_dirty_flags_.lFineTune = (eax_.lFineTune != eax_d_.lFineTune);
271 void EaxPitchShifterEffect::defer_all(
272 const EAXPITCHSHIFTERPROPERTIES& all)
274 defer_coarse_tune(all.lCoarseTune);
275 defer_fine_tune(all.lFineTune);
278 void EaxPitchShifterEffect::defer_coarse_tune(
279 const EaxEaxCall& eax_call)
281 const auto& coarse_tune =
282 eax_call.get_value<EaxPitchShifterEffectException, const decltype(EAXPITCHSHIFTERPROPERTIES::lCoarseTune)>();
284 validate_coarse_tune(coarse_tune);
285 defer_coarse_tune(coarse_tune);
288 void EaxPitchShifterEffect::defer_fine_tune(
289 const EaxEaxCall& eax_call)
291 const auto& fine_tune =
292 eax_call.get_value<EaxPitchShifterEffectException, const decltype(EAXPITCHSHIFTERPROPERTIES::lFineTune)>();
294 validate_fine_tune(fine_tune);
295 defer_fine_tune(fine_tune);
298 void EaxPitchShifterEffect::defer_all(
299 const EaxEaxCall& eax_call)
301 const auto& all =
302 eax_call.get_value<EaxPitchShifterEffectException, const EAXPITCHSHIFTERPROPERTIES>();
304 validate_all(all);
305 defer_all(all);
308 // [[nodiscard]]
309 bool EaxPitchShifterEffect::apply_deferred()
311 if (eax_dirty_flags_ == EaxPitchShifterEffectDirtyFlags{})
313 return false;
316 eax_ = eax_d_;
318 if (eax_dirty_flags_.lCoarseTune)
320 set_efx_coarse_tune();
323 if (eax_dirty_flags_.lFineTune)
325 set_efx_fine_tune();
328 eax_dirty_flags_ = EaxPitchShifterEffectDirtyFlags{};
330 return true;
333 void EaxPitchShifterEffect::set(const EaxEaxCall& eax_call)
335 switch(eax_call.get_property_id())
337 case EAXPITCHSHIFTER_NONE:
338 break;
340 case EAXPITCHSHIFTER_ALLPARAMETERS:
341 defer_all(eax_call);
342 break;
344 case EAXPITCHSHIFTER_COARSETUNE:
345 defer_coarse_tune(eax_call);
346 break;
348 case EAXPITCHSHIFTER_FINETUNE:
349 defer_fine_tune(eax_call);
350 break;
352 default:
353 throw EaxPitchShifterEffectException{"Unsupported property id."};
357 } // namespace
359 EaxEffectUPtr eax_create_eax_pitch_shifter_effect()
361 return std::make_unique<EaxPitchShifterEffect>();
364 #endif // ALSOFT_EAX