]> git.tdb.fi Git - ext/openal.git/blob - al/effects/fshifter.cpp
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / al / effects / fshifter.cpp
1
2 #include "config.h"
3
4 #include <stdexcept>
5
6 #include "AL/al.h"
7 #include "AL/efx.h"
8
9 #include "alc/effects/base.h"
10 #include "aloptional.h"
11 #include "effects.h"
12
13 #ifdef ALSOFT_EAX
14 #include <cassert>
15 #include "alnumeric.h"
16 #include "al/eax/exception.h"
17 #include "al/eax/utils.h"
18 #endif // ALSOFT_EAX
19
20
21 namespace {
22
23 al::optional<FShifterDirection> DirectionFromEmum(ALenum value)
24 {
25     switch(value)
26     {
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;
30     }
31     return al::nullopt;
32 }
33 ALenum EnumFromDirection(FShifterDirection dir)
34 {
35     switch(dir)
36     {
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;
40     }
41     throw std::runtime_error{"Invalid direction: "+std::to_string(static_cast<int>(dir))};
42 }
43
44 void Fshifter_setParamf(EffectProps *props, ALenum param, float val)
45 {
46     switch(param)
47     {
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;
52         break;
53
54     default:
55         throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
56             param};
57     }
58 }
59 void Fshifter_setParamfv(EffectProps *props, ALenum param, const float *vals)
60 { Fshifter_setParamf(props, param, vals[0]); }
61
62 void Fshifter_setParami(EffectProps *props, ALenum param, int val)
63 {
64     switch(param)
65     {
66     case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
67         if(auto diropt = DirectionFromEmum(val))
68             props->Fshifter.LeftDirection = *diropt;
69         else
70             throw effect_exception{AL_INVALID_VALUE,
71                 "Unsupported frequency shifter left direction: 0x%04x", val};
72         break;
73
74     case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
75         if(auto diropt = DirectionFromEmum(val))
76             props->Fshifter.RightDirection = *diropt;
77         else
78             throw effect_exception{AL_INVALID_VALUE,
79                 "Unsupported frequency shifter right direction: 0x%04x", val};
80         break;
81
82     default:
83         throw effect_exception{AL_INVALID_ENUM,
84             "Invalid frequency shifter integer property 0x%04x", param};
85     }
86 }
87 void Fshifter_setParamiv(EffectProps *props, ALenum param, const int *vals)
88 { Fshifter_setParami(props, param, vals[0]); }
89
90 void Fshifter_getParami(const EffectProps *props, ALenum param, int *val)
91 {
92     switch(param)
93     {
94     case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
95         *val = EnumFromDirection(props->Fshifter.LeftDirection);
96         break;
97     case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
98         *val = EnumFromDirection(props->Fshifter.RightDirection);
99         break;
100     default:
101         throw effect_exception{AL_INVALID_ENUM,
102             "Invalid frequency shifter integer property 0x%04x", param};
103     }
104 }
105 void Fshifter_getParamiv(const EffectProps *props, ALenum param, int *vals)
106 { Fshifter_getParami(props, param, vals); }
107
108 void Fshifter_getParamf(const EffectProps *props, ALenum param, float *val)
109 {
110     switch(param)
111     {
112     case AL_FREQUENCY_SHIFTER_FREQUENCY:
113         *val = props->Fshifter.Frequency;
114         break;
115
116     default:
117         throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
118             param};
119     }
120 }
121 void Fshifter_getParamfv(const EffectProps *props, ALenum param, float *vals)
122 { Fshifter_getParamf(props, param, vals); }
123
124 EffectProps genDefaultProps() noexcept
125 {
126     EffectProps props{};
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);
130     return props;
131 }
132
133 } // namespace
134
135 DEFINE_ALEFFECT_VTABLE(Fshifter);
136
137 const EffectProps FshifterEffectProps{genDefaultProps()};
138
139 #ifdef ALSOFT_EAX
140 namespace {
141
142 using FrequencyShifterCommitter = EaxCommitter<EaxFrequencyShifterCommitter>;
143
144 struct FrequencyValidator {
145     void operator()(float flFrequency) const
146     {
147         eax_validate_range<FrequencyShifterCommitter::Exception>(
148             "Frequency",
149             flFrequency,
150             EAXFREQUENCYSHIFTER_MINFREQUENCY,
151             EAXFREQUENCYSHIFTER_MAXFREQUENCY);
152     }
153 }; // FrequencyValidator
154
155 struct LeftDirectionValidator {
156     void operator()(unsigned long ulLeftDirection) const
157     {
158         eax_validate_range<FrequencyShifterCommitter::Exception>(
159             "Left Direction",
160             ulLeftDirection,
161             EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
162             EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
163     }
164 }; // LeftDirectionValidator
165
166 struct RightDirectionValidator {
167     void operator()(unsigned long ulRightDirection) const
168     {
169         eax_validate_range<FrequencyShifterCommitter::Exception>(
170             "Right Direction",
171             ulRightDirection,
172             EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
173             EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
174     }
175 }; // RightDirectionValidator
176
177 struct AllValidator {
178     void operator()(const EAXFREQUENCYSHIFTERPROPERTIES& all) const
179     {
180         FrequencyValidator{}(all.flFrequency);
181         LeftDirectionValidator{}(all.ulLeftDirection);
182         RightDirectionValidator{}(all.ulRightDirection);
183     }
184 }; // AllValidator
185
186 } // namespace
187
188 template<>
189 struct FrequencyShifterCommitter::Exception : public EaxException {
190     explicit Exception(const char *message) : EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
191     { }
192 };
193
194 template<>
195 [[noreturn]] void FrequencyShifterCommitter::fail(const char *message)
196 {
197     throw Exception{message};
198 }
199
200 template<>
201 bool FrequencyShifterCommitter::commit(const EaxEffectProps &props)
202 {
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)
207         return false;
208
209     mEaxProps = props;
210
211     auto get_direction = [](unsigned long dir) noexcept
212     {
213         if(dir == EAX_FREQUENCYSHIFTER_DOWN)
214             return FShifterDirection::Down;
215         if(dir == EAX_FREQUENCYSHIFTER_UP)
216             return FShifterDirection::Up;
217         return FShifterDirection::Off;
218     };
219
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);
223
224     return true;
225 }
226
227 template<>
228 void FrequencyShifterCommitter::SetDefaults(EaxEffectProps &props)
229 {
230     props.mType = EaxEffectType::FrequencyShifter;
231     props.mFrequencyShifter.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
232     props.mFrequencyShifter.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
233     props.mFrequencyShifter.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
234 }
235
236 template<>
237 void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
238 {
239     switch(call.get_property_id())
240     {
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();
247     }
248 }
249
250 template<>
251 void FrequencyShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props)
252 {
253     switch(call.get_property_id())
254     {
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();
261     }
262 }
263
264 #endif // ALSOFT_EAX