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_TAU
/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_TAU
* Slot
->EffectProps
.Modulator
.HighPassCutoff
/ Device
->Frequency
);
143 a
= (2.0f
-cw
) - sqrtf(powf(2.0f
-cw
, 2.0f
) - 1.0f
);
145 state
->Filter
.a1
= -a
;
146 state
->Filter
.a2
= 0.0f
;
147 state
->Filter
.b1
= -a
;
148 state
->Filter
.b2
= 0.0f
;
149 state
->Filter
.input_gain
= a
;
151 ComputeAmbientGains(Device
, Slot
->Gain
, state
->Gain
);
154 static ALvoid
ALmodulatorState_process(ALmodulatorState
*state
, ALuint SamplesToDo
, const ALfloat
*restrict SamplesIn
, ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
156 switch(state
->Waveform
)
159 ProcessSin(state
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
163 ProcessSaw(state
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
167 ProcessSquare(state
, SamplesToDo
, SamplesIn
, SamplesOut
, NumChannels
);
172 DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState
)
174 DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState
);
177 typedef struct ALmodulatorStateFactory
{
178 DERIVE_FROM_TYPE(ALeffectStateFactory
);
179 } ALmodulatorStateFactory
;
181 static ALeffectState
*ALmodulatorStateFactory_create(ALmodulatorStateFactory
*UNUSED(factory
))
183 ALmodulatorState
*state
;
185 state
= ALmodulatorState_New(sizeof(*state
));
186 if(!state
) return NULL
;
187 SET_VTABLE2(ALmodulatorState
, ALeffectState
, state
);
192 ALfilterState_clear(&state
->Filter
);
194 return STATIC_CAST(ALeffectState
, state
);
197 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory
);
199 ALeffectStateFactory
*ALmodulatorStateFactory_getFactory(void)
201 static ALmodulatorStateFactory ModulatorFactory
= { { GET_VTABLE2(ALmodulatorStateFactory
, ALeffectStateFactory
) } };
203 return STATIC_CAST(ALeffectStateFactory
, &ModulatorFactory
);
207 void ALmodulator_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
209 ALeffectProps
*props
= &effect
->Props
;
212 case AL_RING_MODULATOR_FREQUENCY
:
213 if(!(val
>= AL_RING_MODULATOR_MIN_FREQUENCY
&& val
<= AL_RING_MODULATOR_MAX_FREQUENCY
))
214 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
215 props
->Modulator
.Frequency
= val
;
218 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
219 if(!(val
>= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF
&& val
<= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF
))
220 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
221 props
->Modulator
.HighPassCutoff
= val
;
225 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
228 void ALmodulator_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
230 ALmodulator_setParamf(effect
, context
, param
, vals
[0]);
232 void ALmodulator_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
234 ALeffectProps
*props
= &effect
->Props
;
237 case AL_RING_MODULATOR_FREQUENCY
:
238 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
239 ALmodulator_setParamf(effect
, context
, param
, (ALfloat
)val
);
242 case AL_RING_MODULATOR_WAVEFORM
:
243 if(!(val
>= AL_RING_MODULATOR_MIN_WAVEFORM
&& val
<= AL_RING_MODULATOR_MAX_WAVEFORM
))
244 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
245 props
->Modulator
.Waveform
= val
;
249 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
252 void ALmodulator_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
254 ALmodulator_setParami(effect
, context
, param
, vals
[0]);
257 void ALmodulator_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
259 const ALeffectProps
*props
= &effect
->Props
;
262 case AL_RING_MODULATOR_FREQUENCY
:
263 *val
= (ALint
)props
->Modulator
.Frequency
;
265 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
266 *val
= (ALint
)props
->Modulator
.HighPassCutoff
;
268 case AL_RING_MODULATOR_WAVEFORM
:
269 *val
= props
->Modulator
.Waveform
;
273 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
276 void ALmodulator_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
278 ALmodulator_getParami(effect
, context
, param
, vals
);
280 void ALmodulator_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
282 const ALeffectProps
*props
= &effect
->Props
;
285 case AL_RING_MODULATOR_FREQUENCY
:
286 *val
= props
->Modulator
.Frequency
;
288 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
289 *val
= props
->Modulator
.HighPassCutoff
;
293 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
296 void ALmodulator_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
298 ALmodulator_getParamf(effect
, context
, param
, vals
);
301 DEFINE_ALEFFECT_VTABLE(ALmodulator
);