9 #include "alc/effects/base.h"
10 #include "aloptional.h"
15 #include "alnumeric.h"
16 #include "al/eax/exception.h"
17 #include "al/eax/utils.h"
23 al::optional<FShifterDirection> DirectionFromEmum(ALenum value)
27 case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN: return FShifterDirection::Down;
28 case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return FShifterDirection::Up;
29 case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return FShifterDirection::Off;
33 ALenum EnumFromDirection(FShifterDirection dir)
37 case FShifterDirection::Down: return AL_FREQUENCY_SHIFTER_DIRECTION_DOWN;
38 case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
39 case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
41 throw std::runtime_error{"Invalid direction: "+std::to_string(static_cast<int>(dir))};
44 void Fshifter_setParamf(EffectProps *props, ALenum param, float val)
48 case AL_FREQUENCY_SHIFTER_FREQUENCY:
49 if(!(val >= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY && val <= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY))
50 throw effect_exception{AL_INVALID_VALUE, "Frequency shifter frequency out of range"};
51 props->Fshifter.Frequency = val;
55 throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
59 void Fshifter_setParamfv(EffectProps *props, ALenum param, const float *vals)
60 { Fshifter_setParamf(props, param, vals[0]); }
62 void Fshifter_setParami(EffectProps *props, ALenum param, int val)
66 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
67 if(auto diropt = DirectionFromEmum(val))
68 props->Fshifter.LeftDirection = *diropt;
70 throw effect_exception{AL_INVALID_VALUE,
71 "Unsupported frequency shifter left direction: 0x%04x", val};
74 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
75 if(auto diropt = DirectionFromEmum(val))
76 props->Fshifter.RightDirection = *diropt;
78 throw effect_exception{AL_INVALID_VALUE,
79 "Unsupported frequency shifter right direction: 0x%04x", val};
83 throw effect_exception{AL_INVALID_ENUM,
84 "Invalid frequency shifter integer property 0x%04x", param};
87 void Fshifter_setParamiv(EffectProps *props, ALenum param, const int *vals)
88 { Fshifter_setParami(props, param, vals[0]); }
90 void Fshifter_getParami(const EffectProps *props, ALenum param, int *val)
94 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
95 *val = EnumFromDirection(props->Fshifter.LeftDirection);
97 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
98 *val = EnumFromDirection(props->Fshifter.RightDirection);
101 throw effect_exception{AL_INVALID_ENUM,
102 "Invalid frequency shifter integer property 0x%04x", param};
105 void Fshifter_getParamiv(const EffectProps *props, ALenum param, int *vals)
106 { Fshifter_getParami(props, param, vals); }
108 void Fshifter_getParamf(const EffectProps *props, ALenum param, float *val)
112 case AL_FREQUENCY_SHIFTER_FREQUENCY:
113 *val = props->Fshifter.Frequency;
117 throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
121 void Fshifter_getParamfv(const EffectProps *props, ALenum param, float *vals)
122 { Fshifter_getParamf(props, param, vals); }
124 EffectProps genDefaultProps() noexcept
127 props.Fshifter.Frequency = AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY;
128 props.Fshifter.LeftDirection = *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION);
129 props.Fshifter.RightDirection = *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION);
135 DEFINE_ALEFFECT_VTABLE(Fshifter);
137 const EffectProps FshifterEffectProps{genDefaultProps()};
142 using FrequencyShifterCommitter = EaxCommitter<EaxFrequencyShifterCommitter>;
144 struct FrequencyValidator {
145 void operator()(float flFrequency) const
147 eax_validate_range<FrequencyShifterCommitter::Exception>(
150 EAXFREQUENCYSHIFTER_MINFREQUENCY,
151 EAXFREQUENCYSHIFTER_MAXFREQUENCY);
153 }; // FrequencyValidator
155 struct LeftDirectionValidator {
156 void operator()(unsigned long ulLeftDirection) const
158 eax_validate_range<FrequencyShifterCommitter::Exception>(
161 EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
162 EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
164 }; // LeftDirectionValidator
166 struct RightDirectionValidator {
167 void operator()(unsigned long ulRightDirection) const
169 eax_validate_range<FrequencyShifterCommitter::Exception>(
172 EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
173 EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
175 }; // RightDirectionValidator
177 struct AllValidator {
178 void operator()(const EAXFREQUENCYSHIFTERPROPERTIES& all) const
180 FrequencyValidator{}(all.flFrequency);
181 LeftDirectionValidator{}(all.ulLeftDirection);
182 RightDirectionValidator{}(all.ulRightDirection);
189 struct FrequencyShifterCommitter::Exception : public EaxException {
190 explicit Exception(const char *message) : EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
195 [[noreturn]] void FrequencyShifterCommitter::fail(const char *message)
197 throw Exception{message};
201 bool FrequencyShifterCommitter::commit(const EaxEffectProps &props)
203 if(props.mType == mEaxProps.mType
204 && mEaxProps.mFrequencyShifter.flFrequency == props.mFrequencyShifter.flFrequency
205 && mEaxProps.mFrequencyShifter.ulLeftDirection == props.mFrequencyShifter.ulLeftDirection
206 && mEaxProps.mFrequencyShifter.ulRightDirection == props.mFrequencyShifter.ulRightDirection)
211 auto get_direction = [](unsigned long dir) noexcept
213 if(dir == EAX_FREQUENCYSHIFTER_DOWN)
214 return FShifterDirection::Down;
215 if(dir == EAX_FREQUENCYSHIFTER_UP)
216 return FShifterDirection::Up;
217 return FShifterDirection::Off;
220 mAlProps.Fshifter.Frequency = props.mFrequencyShifter.flFrequency;
221 mAlProps.Fshifter.LeftDirection = get_direction(props.mFrequencyShifter.ulLeftDirection);
222 mAlProps.Fshifter.RightDirection = get_direction(props.mFrequencyShifter.ulRightDirection);
228 void FrequencyShifterCommitter::SetDefaults(EaxEffectProps &props)
230 props.mType = EaxEffectType::FrequencyShifter;
231 props.mFrequencyShifter.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
232 props.mFrequencyShifter.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
233 props.mFrequencyShifter.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
237 void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
239 switch(call.get_property_id())
241 case EAXFREQUENCYSHIFTER_NONE: break;
242 case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props.mFrequencyShifter); break;
243 case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value<Exception>(props.mFrequencyShifter.flFrequency); break;
244 case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value<Exception>(props.mFrequencyShifter.ulLeftDirection); break;
245 case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value<Exception>(props.mFrequencyShifter.ulRightDirection); break;
246 default: fail_unknown_property_id();
251 void FrequencyShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props)
253 switch(call.get_property_id())
255 case EAXFREQUENCYSHIFTER_NONE: break;
256 case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props.mFrequencyShifter); break;
257 case EAXFREQUENCYSHIFTER_FREQUENCY: defer<FrequencyValidator>(call, props.mFrequencyShifter.flFrequency); break;
258 case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer<LeftDirectionValidator>(call, props.mFrequencyShifter.ulLeftDirection); break;
259 case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer<RightDirectionValidator>(call, props.mFrequencyShifter.ulRightDirection); break;
260 default: fail_unknown_property_id();