10 #include "alc/effects/base.h"
16 #include "al/eax/effect.h"
17 #include "al/eax/exception.h"
18 #include "al/eax/utils.h"
24 constexpr std::optional
<ModulatorWaveform
> WaveformFromEmum(ALenum value
) noexcept
28 case AL_RING_MODULATOR_SINUSOID
: return ModulatorWaveform::Sinusoid
;
29 case AL_RING_MODULATOR_SAWTOOTH
: return ModulatorWaveform::Sawtooth
;
30 case AL_RING_MODULATOR_SQUARE
: return ModulatorWaveform::Square
;
34 constexpr ALenum
EnumFromWaveform(ModulatorWaveform type
)
38 case ModulatorWaveform::Sinusoid
: return AL_RING_MODULATOR_SINUSOID
;
39 case ModulatorWaveform::Sawtooth
: return AL_RING_MODULATOR_SAWTOOTH
;
40 case ModulatorWaveform::Square
: return AL_RING_MODULATOR_SQUARE
;
42 throw std::runtime_error
{"Invalid modulator waveform: " +
43 std::to_string(static_cast<int>(type
))};
46 constexpr EffectProps
genDefaultProps() noexcept
48 ModulatorProps props
{};
49 props
.Frequency
= AL_RING_MODULATOR_DEFAULT_FREQUENCY
;
50 props
.HighPassCutoff
= AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF
;
51 props
.Waveform
= WaveformFromEmum(AL_RING_MODULATOR_DEFAULT_WAVEFORM
).value();
57 const EffectProps ModulatorEffectProps
{genDefaultProps()};
59 void ModulatorEffectHandler::SetParami(ModulatorProps
&props
, ALenum param
, int val
)
63 case AL_RING_MODULATOR_FREQUENCY
:
64 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
65 SetParamf(props
, param
, static_cast<float>(val
));
68 case AL_RING_MODULATOR_WAVEFORM
:
69 if(auto formopt
= WaveformFromEmum(val
))
70 props
.Waveform
= *formopt
;
72 throw effect_exception
{AL_INVALID_VALUE
, "Invalid modulator waveform: 0x%04x", val
};
76 throw effect_exception
{AL_INVALID_ENUM
, "Invalid modulator integer property 0x%04x",
80 void ModulatorEffectHandler::SetParamiv(ModulatorProps
&props
, ALenum param
, const int *vals
)
81 { SetParami(props
, param
, *vals
); }
83 void ModulatorEffectHandler::SetParamf(ModulatorProps
&props
, ALenum param
, float val
)
87 case AL_RING_MODULATOR_FREQUENCY
:
88 if(!(val
>= AL_RING_MODULATOR_MIN_FREQUENCY
&& val
<= AL_RING_MODULATOR_MAX_FREQUENCY
))
89 throw effect_exception
{AL_INVALID_VALUE
, "Modulator frequency out of range: %f", val
};
90 props
.Frequency
= val
;
93 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
94 if(!(val
>= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF
&& val
<= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF
))
95 throw effect_exception
{AL_INVALID_VALUE
, "Modulator high-pass cutoff out of range: %f", val
};
96 props
.HighPassCutoff
= val
;
100 throw effect_exception
{AL_INVALID_ENUM
, "Invalid modulator float property 0x%04x", param
};
103 void ModulatorEffectHandler::SetParamfv(ModulatorProps
&props
, ALenum param
, const float *vals
)
104 { SetParamf(props
, param
, *vals
); }
106 void ModulatorEffectHandler::GetParami(const ModulatorProps
&props
, ALenum param
, int *val
)
110 case AL_RING_MODULATOR_FREQUENCY
: *val
= static_cast<int>(props
.Frequency
); break;
111 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
: *val
= static_cast<int>(props
.HighPassCutoff
); break;
112 case AL_RING_MODULATOR_WAVEFORM
: *val
= EnumFromWaveform(props
.Waveform
); break;
115 throw effect_exception
{AL_INVALID_ENUM
, "Invalid modulator integer property 0x%04x",
119 void ModulatorEffectHandler::GetParamiv(const ModulatorProps
&props
, ALenum param
, int *vals
)
120 { GetParami(props
, param
, vals
); }
121 void ModulatorEffectHandler::GetParamf(const ModulatorProps
&props
, ALenum param
, float *val
)
125 case AL_RING_MODULATOR_FREQUENCY
: *val
= props
.Frequency
; break;
126 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
: *val
= props
.HighPassCutoff
; break;
129 throw effect_exception
{AL_INVALID_ENUM
, "Invalid modulator float property 0x%04x", param
};
132 void ModulatorEffectHandler::GetParamfv(const ModulatorProps
&props
, ALenum param
, float *vals
)
133 { GetParamf(props
, param
, vals
); }
139 using ModulatorCommitter
= EaxCommitter
<EaxModulatorCommitter
>;
141 struct FrequencyValidator
{
142 void operator()(float flFrequency
) const
144 eax_validate_range
<ModulatorCommitter::Exception
>(
147 EAXRINGMODULATOR_MINFREQUENCY
,
148 EAXRINGMODULATOR_MAXFREQUENCY
);
150 }; // FrequencyValidator
152 struct HighPassCutOffValidator
{
153 void operator()(float flHighPassCutOff
) const
155 eax_validate_range
<ModulatorCommitter::Exception
>(
158 EAXRINGMODULATOR_MINHIGHPASSCUTOFF
,
159 EAXRINGMODULATOR_MAXHIGHPASSCUTOFF
);
161 }; // HighPassCutOffValidator
163 struct WaveformValidator
{
164 void operator()(unsigned long ulWaveform
) const
166 eax_validate_range
<ModulatorCommitter::Exception
>(
169 EAXRINGMODULATOR_MINWAVEFORM
,
170 EAXRINGMODULATOR_MAXWAVEFORM
);
172 }; // WaveformValidator
174 struct AllValidator
{
175 void operator()(const EAXRINGMODULATORPROPERTIES
& all
) const
177 FrequencyValidator
{}(all
.flFrequency
);
178 HighPassCutOffValidator
{}(all
.flHighPassCutOff
);
179 WaveformValidator
{}(all
.ulWaveform
);
186 struct ModulatorCommitter::Exception
: public EaxException
{
187 explicit Exception(const char *message
) : EaxException
{"EAX_RING_MODULATOR_EFFECT", message
}
192 [[noreturn
]] void ModulatorCommitter::fail(const char *message
)
194 throw Exception
{message
};
197 bool EaxModulatorCommitter::commit(const EAXRINGMODULATORPROPERTIES
&props
)
199 if(auto *cur
= std::get_if
<EAXRINGMODULATORPROPERTIES
>(&mEaxProps
); cur
&& *cur
== props
)
204 auto get_waveform
= [](unsigned long form
)
206 if(form
== EAX_RINGMODULATOR_SINUSOID
)
207 return ModulatorWaveform::Sinusoid
;
208 if(form
== EAX_RINGMODULATOR_SAWTOOTH
)
209 return ModulatorWaveform::Sawtooth
;
210 if(form
== EAX_RINGMODULATOR_SQUARE
)
211 return ModulatorWaveform::Square
;
212 return ModulatorWaveform::Sinusoid
;
216 ModulatorProps ret
{};
217 ret
.Frequency
= props
.flFrequency
;
218 ret
.HighPassCutoff
= props
.flHighPassCutOff
;
219 ret
.Waveform
= get_waveform(props
.ulWaveform
);
226 void EaxModulatorCommitter::SetDefaults(EaxEffectProps
&props
)
228 static constexpr EAXRINGMODULATORPROPERTIES defprops
{[]
230 EAXRINGMODULATORPROPERTIES ret
{};
231 ret
.flFrequency
= EAXRINGMODULATOR_DEFAULTFREQUENCY
;
232 ret
.flHighPassCutOff
= EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF
;
233 ret
.ulWaveform
= EAXRINGMODULATOR_DEFAULTWAVEFORM
;
239 void EaxModulatorCommitter::Get(const EaxCall
&call
, const EAXRINGMODULATORPROPERTIES
&props
)
241 switch(call
.get_property_id())
243 case EAXRINGMODULATOR_NONE
: break;
244 case EAXRINGMODULATOR_ALLPARAMETERS
: call
.set_value
<Exception
>(props
); break;
245 case EAXRINGMODULATOR_FREQUENCY
: call
.set_value
<Exception
>(props
.flFrequency
); break;
246 case EAXRINGMODULATOR_HIGHPASSCUTOFF
: call
.set_value
<Exception
>(props
.flHighPassCutOff
); break;
247 case EAXRINGMODULATOR_WAVEFORM
: call
.set_value
<Exception
>(props
.ulWaveform
); break;
248 default: fail_unknown_property_id();
252 void EaxModulatorCommitter::Set(const EaxCall
&call
, EAXRINGMODULATORPROPERTIES
&props
)
254 switch(call
.get_property_id())
256 case EAXRINGMODULATOR_NONE
: break;
257 case EAXRINGMODULATOR_ALLPARAMETERS
: defer
<AllValidator
>(call
, props
); break;
258 case EAXRINGMODULATOR_FREQUENCY
: defer
<FrequencyValidator
>(call
, props
.flFrequency
); break;
259 case EAXRINGMODULATOR_HIGHPASSCUTOFF
: defer
<HighPassCutOffValidator
>(call
, props
.flHighPassCutOff
); break;
260 case EAXRINGMODULATOR_WAVEFORM
: defer
<WaveformValidator
>(call
, props
.ulWaveform
); break;
261 default: fail_unknown_property_id();