2 * OpenAL cross platform audio library
3 * Copyright (C) 2009 by Chris Robinson.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
28 #include "alAuxEffectSlot.h"
33 typedef struct ALmodulatorState
{
34 DERIVE_FROM_TYPE(ALeffectState
);
45 ALfloat Gain
[MAX_OUTPUT_CHANNELS
];
50 #define WAVEFORM_FRACBITS 24
51 #define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS)
52 #define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
54 static inline ALfloat
Sin(ALuint index
)
56 return sinf(index
*(F_2PI
/WAVEFORM_FRACONE
) - F_PI
)*0.5f
+ 0.5f
;
59 static inline ALfloat
Saw(ALuint index
)
61 return (ALfloat
)index
/ WAVEFORM_FRACONE
;
64 static inline ALfloat
Square(ALuint index
)
66 return (ALfloat
)((index
>> (WAVEFORM_FRACBITS
- 1)) & 1);
69 #define DECL_TEMPLATE(func) \
70 static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
71 const ALfloat *restrict SamplesIn, \
72 ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) \
74 const ALuint step = state->step; \
75 ALuint index = state->index; \
78 for(base = 0;base < SamplesToDo;) \
81 ALuint td = minu(256, SamplesToDo-base); \
84 for(i = 0;i < td;i++) \
87 samp = SamplesIn[base+i]; \
88 samp = ALfilterState_processSingle(&state->Filter, samp); \
91 index &= WAVEFORM_FRACMASK; \
92 temps[i] = samp * func(index); \
95 for(k = 0;k < NumChannels;k++) \
97 ALfloat gain = state->Gain[k]; \
98 if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) \
101 for(i = 0;i < td;i++) \
102 SamplesOut[k][base+i] += gain * temps[i]; \
107 state->index = index; \
112 DECL_TEMPLATE(Square
)
117 static ALvoid
ALmodulatorState_Destruct(ALmodulatorState
*UNUSED(state
))
121 static ALboolean
ALmodulatorState_deviceUpdate(ALmodulatorState
*UNUSED(state
), ALCdevice
*UNUSED(device
))
126 static ALvoid
ALmodulatorState_update(ALmodulatorState
*state
, ALCdevice
*Device
, const ALeffectslot
*Slot
)
130 if(Slot
->EffectProps
.Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
131 state
->Waveform
= SINUSOID
;
132 else if(Slot
->EffectProps
.Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
133 state
->Waveform
= SAWTOOTH
;
134 else if(Slot
->EffectProps
.Modulator
.Waveform
== AL_RING_MODULATOR_SQUARE
)
135 state
->Waveform
= SQUARE
;
137 state
->step
= fastf2u(Slot
->EffectProps
.Modulator
.Frequency
*WAVEFORM_FRACONE
/
139 if(state
->step
== 0) state
->step
= 1;
141 /* Custom filter coeffs, which match the old version instead of a low-shelf. */
142 cw
= cosf(F_2PI
* Slot
->EffectProps
.Modulator
.HighPassCutoff
/ Device
->Frequency
);
143 a
= (2.0f
-cw
) - sqrtf(powf(2.0f
-cw
, 2.0f
) - 1.0f
);
145 state
->Filter
.b
[0] = a
;
146 state
->Filter
.b
[1] = -a
;
147 state
->Filter
.b
[2] = 0.0f
;
148 state
->Filter
.a
[0] = 1.0f
;
149 state
->Filter
.a
[1] = -a
;
150 state
->Filter
.a
[2] = 0.0f
;
152 ComputeAmbientGains(Device
, Slot
->Gain
, state
->Gain
);
155 static ALvoid
ALmodulatorState_process(ALmodulatorState
*state
, ALuint SamplesToDo
, const ALfloat
*restrict SamplesIn
, ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
157 switch(state
->Waveform
)
160 ProcessSin(state
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
164 ProcessSaw(state
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
168 ProcessSquare(state
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
173 DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState
)
175 DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState
);
178 typedef struct ALmodulatorStateFactory
{
179 DERIVE_FROM_TYPE(ALeffectStateFactory
);
180 } ALmodulatorStateFactory
;
182 static ALeffectState
*ALmodulatorStateFactory_create(ALmodulatorStateFactory
*UNUSED(factory
))
184 ALmodulatorState
*state
;
186 state
= ALmodulatorState_New(sizeof(*state
));
187 if(!state
) return NULL
;
188 SET_VTABLE2(ALmodulatorState
, ALeffectState
, state
);
193 ALfilterState_clear(&state
->Filter
);
195 return STATIC_CAST(ALeffectState
, state
);
198 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory
);
200 ALeffectStateFactory
*ALmodulatorStateFactory_getFactory(void)
202 static ALmodulatorStateFactory ModulatorFactory
= { { GET_VTABLE2(ALmodulatorStateFactory
, ALeffectStateFactory
) } };
204 return STATIC_CAST(ALeffectStateFactory
, &ModulatorFactory
);
208 void ALmodulator_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
210 ALeffectProps
*props
= &effect
->Props
;
213 case AL_RING_MODULATOR_FREQUENCY
:
214 if(!(val
>= AL_RING_MODULATOR_MIN_FREQUENCY
&& val
<= AL_RING_MODULATOR_MAX_FREQUENCY
))
215 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
216 props
->Modulator
.Frequency
= val
;
219 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
220 if(!(val
>= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF
&& val
<= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF
))
221 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
222 props
->Modulator
.HighPassCutoff
= val
;
226 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
229 void ALmodulator_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
231 ALmodulator_setParamf(effect
, context
, param
, vals
[0]);
233 void ALmodulator_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
235 ALeffectProps
*props
= &effect
->Props
;
238 case AL_RING_MODULATOR_FREQUENCY
:
239 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
240 ALmodulator_setParamf(effect
, context
, param
, (ALfloat
)val
);
243 case AL_RING_MODULATOR_WAVEFORM
:
244 if(!(val
>= AL_RING_MODULATOR_MIN_WAVEFORM
&& val
<= AL_RING_MODULATOR_MAX_WAVEFORM
))
245 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
246 props
->Modulator
.Waveform
= val
;
250 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
253 void ALmodulator_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
255 ALmodulator_setParami(effect
, context
, param
, vals
[0]);
258 void ALmodulator_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
260 const ALeffectProps
*props
= &effect
->Props
;
263 case AL_RING_MODULATOR_FREQUENCY
:
264 *val
= (ALint
)props
->Modulator
.Frequency
;
266 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
267 *val
= (ALint
)props
->Modulator
.HighPassCutoff
;
269 case AL_RING_MODULATOR_WAVEFORM
:
270 *val
= props
->Modulator
.Waveform
;
274 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
277 void ALmodulator_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
279 ALmodulator_getParami(effect
, context
, param
, vals
);
281 void ALmodulator_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
283 const ALeffectProps
*props
= &effect
->Props
;
286 case AL_RING_MODULATOR_FREQUENCY
:
287 *val
= props
->Modulator
.Frequency
;
289 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
290 *val
= props
->Modulator
.HighPassCutoff
;
294 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
297 void ALmodulator_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
299 ALmodulator_getParamf(effect
, context
, param
, vals
);
302 DEFINE_ALEFFECT_VTABLE(ALmodulator
);