9 #include "alc/effects/base.h"
10 #include "aloptional.h"
16 #include "alnumeric.h"
18 #include "al/eax_exception.h"
19 #include "al/eax_utils.h"
25 al::optional
<FShifterDirection
> DirectionFromEmum(ALenum value
)
29 case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN
: return al::make_optional(FShifterDirection::Down
);
30 case AL_FREQUENCY_SHIFTER_DIRECTION_UP
: return al::make_optional(FShifterDirection::Up
);
31 case AL_FREQUENCY_SHIFTER_DIRECTION_OFF
: return al::make_optional(FShifterDirection::Off
);
35 ALenum
EnumFromDirection(FShifterDirection dir
)
39 case FShifterDirection::Down
: return AL_FREQUENCY_SHIFTER_DIRECTION_DOWN
;
40 case FShifterDirection::Up
: return AL_FREQUENCY_SHIFTER_DIRECTION_UP
;
41 case FShifterDirection::Off
: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF
;
43 throw std::runtime_error
{"Invalid direction: "+std::to_string(static_cast<int>(dir
))};
46 void Fshifter_setParamf(EffectProps
*props
, ALenum param
, float val
)
50 case AL_FREQUENCY_SHIFTER_FREQUENCY
:
51 if(!(val
>= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY
&& val
<= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY
))
52 throw effect_exception
{AL_INVALID_VALUE
, "Frequency shifter frequency out of range"};
53 props
->Fshifter
.Frequency
= val
;
57 throw effect_exception
{AL_INVALID_ENUM
, "Invalid frequency shifter float property 0x%04x",
61 void Fshifter_setParamfv(EffectProps
*props
, ALenum param
, const float *vals
)
62 { Fshifter_setParamf(props
, param
, vals
[0]); }
64 void Fshifter_setParami(EffectProps
*props
, ALenum param
, int val
)
68 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
:
69 if(auto diropt
= DirectionFromEmum(val
))
70 props
->Fshifter
.LeftDirection
= *diropt
;
72 throw effect_exception
{AL_INVALID_VALUE
,
73 "Unsupported frequency shifter left direction: 0x%04x", val
};
76 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
:
77 if(auto diropt
= DirectionFromEmum(val
))
78 props
->Fshifter
.RightDirection
= *diropt
;
80 throw effect_exception
{AL_INVALID_VALUE
,
81 "Unsupported frequency shifter right direction: 0x%04x", val
};
85 throw effect_exception
{AL_INVALID_ENUM
,
86 "Invalid frequency shifter integer property 0x%04x", param
};
89 void Fshifter_setParamiv(EffectProps
*props
, ALenum param
, const int *vals
)
90 { Fshifter_setParami(props
, param
, vals
[0]); }
92 void Fshifter_getParami(const EffectProps
*props
, ALenum param
, int *val
)
96 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
:
97 *val
= EnumFromDirection(props
->Fshifter
.LeftDirection
);
99 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
:
100 *val
= EnumFromDirection(props
->Fshifter
.RightDirection
);
103 throw effect_exception
{AL_INVALID_ENUM
,
104 "Invalid frequency shifter integer property 0x%04x", param
};
107 void Fshifter_getParamiv(const EffectProps
*props
, ALenum param
, int *vals
)
108 { Fshifter_getParami(props
, param
, vals
); }
110 void Fshifter_getParamf(const EffectProps
*props
, ALenum param
, float *val
)
114 case AL_FREQUENCY_SHIFTER_FREQUENCY
:
115 *val
= props
->Fshifter
.Frequency
;
119 throw effect_exception
{AL_INVALID_ENUM
, "Invalid frequency shifter float property 0x%04x",
123 void Fshifter_getParamfv(const EffectProps
*props
, ALenum param
, float *vals
)
124 { Fshifter_getParamf(props
, param
, vals
); }
126 EffectProps
genDefaultProps() noexcept
129 props
.Fshifter
.Frequency
= AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY
;
130 props
.Fshifter
.LeftDirection
= *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION
);
131 props
.Fshifter
.RightDirection
= *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION
);
137 DEFINE_ALEFFECT_VTABLE(Fshifter
);
139 const EffectProps FshifterEffectProps
{genDefaultProps()};
144 using EaxFrequencyShifterEffectDirtyFlagsValue
= std::uint_least8_t;
146 struct EaxFrequencyShifterEffectDirtyFlags
148 using EaxIsBitFieldStruct
= bool;
150 EaxFrequencyShifterEffectDirtyFlagsValue flFrequency
: 1;
151 EaxFrequencyShifterEffectDirtyFlagsValue ulLeftDirection
: 1;
152 EaxFrequencyShifterEffectDirtyFlagsValue ulRightDirection
: 1;
153 }; // EaxFrequencyShifterEffectDirtyFlags
156 class EaxFrequencyShifterEffect final
:
160 EaxFrequencyShifterEffect();
165 const EaxEaxCall
& eax_call
) override
;
169 EAXFREQUENCYSHIFTERPROPERTIES eax_
{};
170 EAXFREQUENCYSHIFTERPROPERTIES eax_d_
{};
171 EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_
{};
174 void set_eax_defaults();
177 void set_efx_frequency();
179 void set_efx_left_direction();
181 void set_efx_right_direction();
183 void set_efx_defaults();
188 const EaxEaxCall
& eax_call
);
191 void validate_frequency(
194 void validate_left_direction(
195 unsigned long ulLeftDirection
);
197 void validate_right_direction(
198 unsigned long ulRightDirection
);
201 const EAXFREQUENCYSHIFTERPROPERTIES
& all
);
204 void defer_frequency(
207 void defer_left_direction(
208 unsigned long ulLeftDirection
);
210 void defer_right_direction(
211 unsigned long ulRightDirection
);
214 const EAXFREQUENCYSHIFTERPROPERTIES
& all
);
217 void defer_frequency(
218 const EaxEaxCall
& eax_call
);
220 void defer_left_direction(
221 const EaxEaxCall
& eax_call
);
223 void defer_right_direction(
224 const EaxEaxCall
& eax_call
);
227 const EaxEaxCall
& eax_call
);
231 bool apply_deferred();
235 const EaxEaxCall
& eax_call
);
236 }; // EaxFrequencyShifterEffect
239 class EaxFrequencyShifterEffectException
:
243 explicit EaxFrequencyShifterEffectException(
246 EaxException
{"EAX_FREQUENCY_SHIFTER_EFFECT", message
}
249 }; // EaxFrequencyShifterEffectException
252 EaxFrequencyShifterEffect::EaxFrequencyShifterEffect()
253 : EaxEffect
{AL_EFFECT_FREQUENCY_SHIFTER
}
260 bool EaxFrequencyShifterEffect::dispatch(
261 const EaxEaxCall
& eax_call
)
263 return eax_call
.is_get() ? get(eax_call
) : set(eax_call
);
266 void EaxFrequencyShifterEffect::set_eax_defaults()
268 eax_
.flFrequency
= EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY
;
269 eax_
.ulLeftDirection
= EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION
;
270 eax_
.ulRightDirection
= EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION
;
275 void EaxFrequencyShifterEffect::set_efx_frequency()
277 const auto frequency
= clamp(
279 AL_FREQUENCY_SHIFTER_MIN_FREQUENCY
,
280 AL_FREQUENCY_SHIFTER_MAX_FREQUENCY
);
282 al_effect_props_
.Fshifter
.Frequency
= frequency
;
285 void EaxFrequencyShifterEffect::set_efx_left_direction()
287 const auto left_direction
= clamp(
288 static_cast<ALint
>(eax_
.ulLeftDirection
),
289 AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION
,
290 AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION
);
292 const auto efx_left_direction
= DirectionFromEmum(left_direction
);
293 assert(efx_left_direction
.has_value());
294 al_effect_props_
.Fshifter
.LeftDirection
= *efx_left_direction
;
297 void EaxFrequencyShifterEffect::set_efx_right_direction()
299 const auto right_direction
= clamp(
300 static_cast<ALint
>(eax_
.ulRightDirection
),
301 AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION
,
302 AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION
);
304 const auto efx_right_direction
= DirectionFromEmum(right_direction
);
305 assert(efx_right_direction
.has_value());
306 al_effect_props_
.Fshifter
.RightDirection
= *efx_right_direction
;
309 void EaxFrequencyShifterEffect::set_efx_defaults()
312 set_efx_left_direction();
313 set_efx_right_direction();
317 bool EaxFrequencyShifterEffect::get(
318 const EaxEaxCall
& eax_call
)
320 switch (eax_call
.get_property_id())
322 case EAXFREQUENCYSHIFTER_NONE
:
325 case EAXFREQUENCYSHIFTER_ALLPARAMETERS
:
326 eax_call
.set_value
<EaxFrequencyShifterEffectException
>(eax_
);
329 case EAXFREQUENCYSHIFTER_FREQUENCY
:
330 eax_call
.set_value
<EaxFrequencyShifterEffectException
>(eax_
.flFrequency
);
333 case EAXFREQUENCYSHIFTER_LEFTDIRECTION
:
334 eax_call
.set_value
<EaxFrequencyShifterEffectException
>(eax_
.ulLeftDirection
);
337 case EAXFREQUENCYSHIFTER_RIGHTDIRECTION
:
338 eax_call
.set_value
<EaxFrequencyShifterEffectException
>(eax_
.ulRightDirection
);
342 throw EaxFrequencyShifterEffectException
{"Unsupported property id."};
348 void EaxFrequencyShifterEffect::validate_frequency(
351 eax_validate_range
<EaxFrequencyShifterEffectException
>(
354 EAXFREQUENCYSHIFTER_MINFREQUENCY
,
355 EAXFREQUENCYSHIFTER_MAXFREQUENCY
);
358 void EaxFrequencyShifterEffect::validate_left_direction(
359 unsigned long ulLeftDirection
)
361 eax_validate_range
<EaxFrequencyShifterEffectException
>(
364 EAXFREQUENCYSHIFTER_MINLEFTDIRECTION
,
365 EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION
);
368 void EaxFrequencyShifterEffect::validate_right_direction(
369 unsigned long ulRightDirection
)
371 eax_validate_range
<EaxFrequencyShifterEffectException
>(
374 EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION
,
375 EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION
);
378 void EaxFrequencyShifterEffect::validate_all(
379 const EAXFREQUENCYSHIFTERPROPERTIES
& all
)
381 validate_frequency(all
.flFrequency
);
382 validate_left_direction(all
.ulLeftDirection
);
383 validate_right_direction(all
.ulRightDirection
);
386 void EaxFrequencyShifterEffect::defer_frequency(
389 eax_d_
.flFrequency
= flFrequency
;
390 eax_dirty_flags_
.flFrequency
= (eax_
.flFrequency
!= eax_d_
.flFrequency
);
393 void EaxFrequencyShifterEffect::defer_left_direction(
394 unsigned long ulLeftDirection
)
396 eax_d_
.ulLeftDirection
= ulLeftDirection
;
397 eax_dirty_flags_
.ulLeftDirection
= (eax_
.ulLeftDirection
!= eax_d_
.ulLeftDirection
);
400 void EaxFrequencyShifterEffect::defer_right_direction(
401 unsigned long ulRightDirection
)
403 eax_d_
.ulRightDirection
= ulRightDirection
;
404 eax_dirty_flags_
.ulRightDirection
= (eax_
.ulRightDirection
!= eax_d_
.ulRightDirection
);
407 void EaxFrequencyShifterEffect::defer_all(
408 const EAXFREQUENCYSHIFTERPROPERTIES
& all
)
410 defer_frequency(all
.flFrequency
);
411 defer_left_direction(all
.ulLeftDirection
);
412 defer_right_direction(all
.ulRightDirection
);
415 void EaxFrequencyShifterEffect::defer_frequency(
416 const EaxEaxCall
& eax_call
)
418 const auto& frequency
=
420 EaxFrequencyShifterEffectException
, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::flFrequency
)>();
422 validate_frequency(frequency
);
423 defer_frequency(frequency
);
426 void EaxFrequencyShifterEffect::defer_left_direction(
427 const EaxEaxCall
& eax_call
)
429 const auto& left_direction
=
431 EaxFrequencyShifterEffectException
, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulLeftDirection
)>();
433 validate_left_direction(left_direction
);
434 defer_left_direction(left_direction
);
437 void EaxFrequencyShifterEffect::defer_right_direction(
438 const EaxEaxCall
& eax_call
)
440 const auto& right_direction
=
442 EaxFrequencyShifterEffectException
, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulRightDirection
)>();
444 validate_right_direction(right_direction
);
445 defer_right_direction(right_direction
);
448 void EaxFrequencyShifterEffect::defer_all(
449 const EaxEaxCall
& eax_call
)
453 EaxFrequencyShifterEffectException
, const EAXFREQUENCYSHIFTERPROPERTIES
>();
460 bool EaxFrequencyShifterEffect::apply_deferred()
462 if (eax_dirty_flags_
== EaxFrequencyShifterEffectDirtyFlags
{})
469 if (eax_dirty_flags_
.flFrequency
)
474 if (eax_dirty_flags_
.ulLeftDirection
)
476 set_efx_left_direction();
479 if (eax_dirty_flags_
.ulRightDirection
)
481 set_efx_right_direction();
484 eax_dirty_flags_
= EaxFrequencyShifterEffectDirtyFlags
{};
490 bool EaxFrequencyShifterEffect::set(
491 const EaxEaxCall
& eax_call
)
493 switch (eax_call
.get_property_id())
495 case EAXFREQUENCYSHIFTER_NONE
:
498 case EAXFREQUENCYSHIFTER_ALLPARAMETERS
:
502 case EAXFREQUENCYSHIFTER_FREQUENCY
:
503 defer_frequency(eax_call
);
506 case EAXFREQUENCYSHIFTER_LEFTDIRECTION
:
507 defer_left_direction(eax_call
);
510 case EAXFREQUENCYSHIFTER_RIGHTDIRECTION
:
511 defer_right_direction(eax_call
);
515 throw EaxFrequencyShifterEffectException
{"Unsupported property id."};
518 if (!eax_call
.is_deferred())
520 return apply_deferred();
528 EaxEffectUPtr
eax_create_eax_frequency_shifter_effect()
530 return std::make_unique
<EaxFrequencyShifterEffect
>();