1 
2 #include "config.h"
3 
4 #include "AL/al.h"
5 #include "AL/efx.h"
6 
7 #include "aloptional.h"
8 #include "effects.h"
9 #include "effects/base.h"
10 
11 
12 namespace {
13 
14 al::optional<ModulatorWaveform> WaveformFromEmum(ALenum value)
15 {
16     switch(value)
17     {
18     case AL_RING_MODULATOR_SINUSOID: return al::make_optional(ModulatorWaveform::Sinusoid);
19     case AL_RING_MODULATOR_SAWTOOTH: return al::make_optional(ModulatorWaveform::Sawtooth);
20     case AL_RING_MODULATOR_SQUARE: return al::make_optional(ModulatorWaveform::Square);
21     }
22     return al::nullopt;
23 }
24 ALenum EnumFromWaveform(ModulatorWaveform type)
25 {
26     switch(type)
27     {
28     case ModulatorWaveform::Sinusoid: return AL_RING_MODULATOR_SINUSOID;
29     case ModulatorWaveform::Sawtooth: return AL_RING_MODULATOR_SAWTOOTH;
30     case ModulatorWaveform::Square: return AL_RING_MODULATOR_SQUARE;
31     }
32     throw std::runtime_error{"Invalid modulator waveform: " +
33         std::to_string(static_cast<int>(type))};
34 }
35 
36 void Modulator_setParamf(EffectProps *props, ALenum param, float val)
37 {
38     switch(param)
39     {
40     case AL_RING_MODULATOR_FREQUENCY:
41         if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY))
42             throw effect_exception{AL_INVALID_VALUE, "Modulator frequency out of range: %f", val};
43         props->Modulator.Frequency = val;
44         break;
45 
46     case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
47         if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF))
48             throw effect_exception{AL_INVALID_VALUE, "Modulator high-pass cutoff out of range: %f", val};
49         props->Modulator.HighPassCutoff = val;
50         break;
51 
52     default:
53         throw effect_exception{AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param};
54     }
55 }
56 void Modulator_setParamfv(EffectProps *props, ALenum param, const float *vals)
57 { Modulator_setParamf(props, param, vals[0]); }
58 void Modulator_setParami(EffectProps *props, ALenum param, int val)
59 {
60     switch(param)
61     {
62     case AL_RING_MODULATOR_FREQUENCY:
63     case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
64         Modulator_setParamf(props, param, static_cast<float>(val));
65         break;
66 
67     case AL_RING_MODULATOR_WAVEFORM:
68         if(auto formopt = WaveformFromEmum(val))
69             props->Modulator.Waveform = *formopt;
70         else
71             throw effect_exception{AL_INVALID_VALUE, "Invalid modulator waveform: 0x%04x", val};
72         break;
73 
74     default:
75         throw effect_exception{AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x",
76             param};
77     }
78 }
79 void Modulator_setParamiv(EffectProps *props, ALenum param, const int *vals)
80 { Modulator_setParami(props, param, vals[0]); }
81 
82 void Modulator_getParami(const EffectProps *props, ALenum param, int *val)
83 {
84     switch(param)
85     {
86     case AL_RING_MODULATOR_FREQUENCY:
87         *val = static_cast<int>(props->Modulator.Frequency);
88         break;
89     case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
90         *val = static_cast<int>(props->Modulator.HighPassCutoff);
91         break;
92     case AL_RING_MODULATOR_WAVEFORM:
93         *val = EnumFromWaveform(props->Modulator.Waveform);
94         break;
95 
96     default:
97         throw effect_exception{AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x",
98             param};
99     }
100 }
101 void Modulator_getParamiv(const EffectProps *props, ALenum param, int *vals)
102 { Modulator_getParami(props, param, vals); }
103 void Modulator_getParamf(const EffectProps *props, ALenum param, float *val)
104 {
105     switch(param)
106     {
107     case AL_RING_MODULATOR_FREQUENCY:
108         *val = props->Modulator.Frequency;
109         break;
110     case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
111         *val = props->Modulator.HighPassCutoff;
112         break;
113 
114     default:
115         throw effect_exception{AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param};
116     }
117 }
118 void Modulator_getParamfv(const EffectProps *props, ALenum param, float *vals)
119 { Modulator_getParamf(props, param, vals); }
120 
121 EffectProps genDefaultProps() noexcept
122 {
123     EffectProps props{};
124     props.Modulator.Frequency      = AL_RING_MODULATOR_DEFAULT_FREQUENCY;
125     props.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF;
126     props.Modulator.Waveform       = *WaveformFromEmum(AL_RING_MODULATOR_DEFAULT_WAVEFORM);
127     return props;
128 }
129 
130 } // namespace
131 
132 DEFINE_ALEFFECT_VTABLE(Modulator);
133 
134 const EffectProps ModulatorEffectProps{genDefaultProps()};
135