Handle AL effect properties with a variant
[openal-soft.git] / al / effects / fshifter.cpp
bloba2321395247131d292f9253c2ec75342159633e0
2 #include "config.h"
4 #include <optional>
5 #include <stdexcept>
7 #include "AL/al.h"
8 #include "AL/efx.h"
10 #include "alc/effects/base.h"
11 #include "effects.h"
13 #ifdef ALSOFT_EAX
14 #include <cassert>
15 #include "alnumeric.h"
16 #include "al/eax/effect.h"
17 #include "al/eax/exception.h"
18 #include "al/eax/utils.h"
19 #endif // ALSOFT_EAX
22 namespace {
24 constexpr std::optional<FShifterDirection> DirectionFromEmum(ALenum value) noexcept
26 switch(value)
28 case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN: return FShifterDirection::Down;
29 case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return FShifterDirection::Up;
30 case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return FShifterDirection::Off;
32 return std::nullopt;
34 constexpr ALenum EnumFromDirection(FShifterDirection dir)
36 switch(dir)
38 case FShifterDirection::Down: return AL_FREQUENCY_SHIFTER_DIRECTION_DOWN;
39 case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
40 case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
42 throw std::runtime_error{"Invalid direction: "+std::to_string(static_cast<int>(dir))};
45 constexpr EffectProps genDefaultProps() noexcept
47 FshifterProps props{};
48 props.Frequency = AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY;
49 props.LeftDirection = DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION).value();
50 props.RightDirection = DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION).value();
51 return props;
54 } // namespace
56 const EffectProps FshifterEffectProps{genDefaultProps()};
58 void FshifterEffectHandler::SetParami(FshifterProps &props, ALenum param, int val)
60 switch(param)
62 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
63 if(auto diropt = DirectionFromEmum(val))
64 props.LeftDirection = *diropt;
65 else
66 throw effect_exception{AL_INVALID_VALUE,
67 "Unsupported frequency shifter left direction: 0x%04x", val};
68 break;
70 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
71 if(auto diropt = DirectionFromEmum(val))
72 props.RightDirection = *diropt;
73 else
74 throw effect_exception{AL_INVALID_VALUE,
75 "Unsupported frequency shifter right direction: 0x%04x", val};
76 break;
78 default:
79 throw effect_exception{AL_INVALID_ENUM,
80 "Invalid frequency shifter integer property 0x%04x", param};
83 void FshifterEffectHandler::SetParamiv(FshifterProps &props, ALenum param, const int *vals)
84 { SetParami(props, param, *vals); }
86 void FshifterEffectHandler::SetParamf(FshifterProps &props, ALenum param, float val)
88 switch(param)
90 case AL_FREQUENCY_SHIFTER_FREQUENCY:
91 if(!(val >= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY && val <= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY))
92 throw effect_exception{AL_INVALID_VALUE, "Frequency shifter frequency out of range"};
93 props.Frequency = val;
94 break;
96 default:
97 throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
98 param};
101 void FshifterEffectHandler::SetParamfv(FshifterProps &props, ALenum param, const float *vals)
102 { SetParamf(props, param, *vals); }
104 void FshifterEffectHandler::GetParami(const FshifterProps &props, ALenum param, int *val)
106 switch(param)
108 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
109 *val = EnumFromDirection(props.LeftDirection);
110 break;
111 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
112 *val = EnumFromDirection(props.RightDirection);
113 break;
115 default:
116 throw effect_exception{AL_INVALID_ENUM,
117 "Invalid frequency shifter integer property 0x%04x", param};
120 void FshifterEffectHandler::GetParamiv(const FshifterProps &props, ALenum param, int *vals)
121 { GetParami(props, param, vals); }
123 void FshifterEffectHandler::GetParamf(const FshifterProps &props, ALenum param, float *val)
125 switch(param)
127 case AL_FREQUENCY_SHIFTER_FREQUENCY:
128 *val = props.Frequency;
129 break;
131 default:
132 throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
133 param};
136 void FshifterEffectHandler::GetParamfv(const FshifterProps &props, ALenum param, float *vals)
137 { GetParamf(props, param, vals); }
140 #ifdef ALSOFT_EAX
141 namespace {
143 using FrequencyShifterCommitter = EaxCommitter<EaxFrequencyShifterCommitter>;
145 struct FrequencyValidator {
146 void operator()(float flFrequency) const
148 eax_validate_range<FrequencyShifterCommitter::Exception>(
149 "Frequency",
150 flFrequency,
151 EAXFREQUENCYSHIFTER_MINFREQUENCY,
152 EAXFREQUENCYSHIFTER_MAXFREQUENCY);
154 }; // FrequencyValidator
156 struct LeftDirectionValidator {
157 void operator()(unsigned long ulLeftDirection) const
159 eax_validate_range<FrequencyShifterCommitter::Exception>(
160 "Left Direction",
161 ulLeftDirection,
162 EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
163 EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
165 }; // LeftDirectionValidator
167 struct RightDirectionValidator {
168 void operator()(unsigned long ulRightDirection) const
170 eax_validate_range<FrequencyShifterCommitter::Exception>(
171 "Right Direction",
172 ulRightDirection,
173 EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
174 EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
176 }; // RightDirectionValidator
178 struct AllValidator {
179 void operator()(const EAXFREQUENCYSHIFTERPROPERTIES& all) const
181 FrequencyValidator{}(all.flFrequency);
182 LeftDirectionValidator{}(all.ulLeftDirection);
183 RightDirectionValidator{}(all.ulRightDirection);
185 }; // AllValidator
187 } // namespace
189 template<>
190 struct FrequencyShifterCommitter::Exception : public EaxException {
191 explicit Exception(const char *message) : EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
195 template<>
196 [[noreturn]] void FrequencyShifterCommitter::fail(const char *message)
198 throw Exception{message};
201 bool EaxFrequencyShifterCommitter::commit(const EAXFREQUENCYSHIFTERPROPERTIES &props)
203 if(auto *cur = std::get_if<EAXFREQUENCYSHIFTERPROPERTIES>(&mEaxProps); cur && *cur == props)
204 return false;
206 mEaxProps = props;
208 auto get_direction = [](unsigned long dir) noexcept
210 if(dir == EAX_FREQUENCYSHIFTER_DOWN)
211 return FShifterDirection::Down;
212 if(dir == EAX_FREQUENCYSHIFTER_UP)
213 return FShifterDirection::Up;
214 return FShifterDirection::Off;
217 mAlProps = [&]{
218 FshifterProps ret{};
219 ret.Frequency = props.flFrequency;
220 ret.LeftDirection = get_direction(props.ulLeftDirection);
221 ret.RightDirection = get_direction(props.ulRightDirection);
222 return ret;
223 }();
225 return true;
228 void EaxFrequencyShifterCommitter::SetDefaults(EaxEffectProps &props)
230 static constexpr EAXFREQUENCYSHIFTERPROPERTIES defprops{[]
232 EAXFREQUENCYSHIFTERPROPERTIES ret{};
233 ret.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
234 ret.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
235 ret.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
236 return ret;
237 }()};
238 props = defprops;
241 void EaxFrequencyShifterCommitter::Get(const EaxCall &call, const EAXFREQUENCYSHIFTERPROPERTIES &props)
243 switch(call.get_property_id())
245 case EAXFREQUENCYSHIFTER_NONE: break;
246 case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props); break;
247 case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value<Exception>(props.flFrequency); break;
248 case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value<Exception>(props.ulLeftDirection); break;
249 case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value<Exception>(props.ulRightDirection); break;
250 default: fail_unknown_property_id();
254 void EaxFrequencyShifterCommitter::Set(const EaxCall &call, EAXFREQUENCYSHIFTERPROPERTIES &props)
256 switch(call.get_property_id())
258 case EAXFREQUENCYSHIFTER_NONE: break;
259 case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
260 case EAXFREQUENCYSHIFTER_FREQUENCY: defer<FrequencyValidator>(call, props.flFrequency); break;
261 case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer<LeftDirectionValidator>(call, props.ulLeftDirection); break;
262 case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer<RightDirectionValidator>(call, props.ulRightDirection); break;
263 default: fail_unknown_property_id();
267 #endif // ALSOFT_EAX