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
);
36 void (*Process
)(ALfloat
*, const ALfloat
*, ALuint
, const ALuint
, ALuint
);
41 ALfloat Gain
[MAX_OUTPUT_CHANNELS
];
46 #define WAVEFORM_FRACBITS 24
47 #define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS)
48 #define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
50 static inline ALfloat
Sin(ALuint index
)
52 return sinf(index
*(F_TAU
/WAVEFORM_FRACONE
) - F_PI
)*0.5f
+ 0.5f
;
55 static inline ALfloat
Saw(ALuint index
)
57 return (ALfloat
)index
/ WAVEFORM_FRACONE
;
60 static inline ALfloat
Square(ALuint index
)
62 return (ALfloat
)((index
>> (WAVEFORM_FRACBITS
- 1)) & 1);
65 #define DECL_TEMPLATE(func) \
66 static void Modulate##func(ALfloat *restrict dst, const ALfloat *restrict src,\
67 ALuint index, const ALuint step, ALuint todo) \
70 for(i = 0;i < todo;i++) \
73 index &= WAVEFORM_FRACMASK; \
74 dst[i] = src[i] * func(index); \
85 static ALvoid
ALmodulatorState_Destruct(ALmodulatorState
*UNUSED(state
))
89 static ALboolean
ALmodulatorState_deviceUpdate(ALmodulatorState
*UNUSED(state
), ALCdevice
*UNUSED(device
))
94 static ALvoid
ALmodulatorState_update(ALmodulatorState
*state
, const ALCdevice
*Device
, const ALeffectslot
*Slot
)
98 if(Slot
->EffectProps
.Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
99 state
->Process
= ModulateSin
;
100 else if(Slot
->EffectProps
.Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
101 state
->Process
= ModulateSaw
;
102 else /*if(Slot->EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
103 state
->Process
= ModulateSquare
;
105 state
->step
= fastf2u(Slot
->EffectProps
.Modulator
.Frequency
*WAVEFORM_FRACONE
/
107 if(state
->step
== 0) state
->step
= 1;
109 /* Custom filter coeffs, which match the old version instead of a low-shelf. */
110 cw
= cosf(F_TAU
* Slot
->EffectProps
.Modulator
.HighPassCutoff
/ Device
->Frequency
);
111 a
= (2.0f
-cw
) - sqrtf(powf(2.0f
-cw
, 2.0f
) - 1.0f
);
113 state
->Filter
.a1
= -a
;
114 state
->Filter
.a2
= 0.0f
;
115 state
->Filter
.b1
= -a
;
116 state
->Filter
.b2
= 0.0f
;
117 state
->Filter
.input_gain
= a
;
118 state
->Filter
.process
= ALfilterState_processC
;
120 ComputeAmbientGains(Device
->AmbiCoeffs
, Device
->NumChannels
, Slot
->Gain
, state
->Gain
);
123 static ALvoid
ALmodulatorState_process(ALmodulatorState
*state
, ALuint SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
125 const ALuint step
= state
->step
;
126 ALuint index
= state
->index
;
129 for(base
= 0;base
< SamplesToDo
;)
131 ALfloat temps
[2][128];
132 ALuint td
= minu(128, SamplesToDo
-base
);
135 ALfilterState_process(&state
->Filter
, temps
[0], &SamplesIn
[0][base
], td
);
136 state
->Process(temps
[1], temps
[0], index
, step
, td
);
138 for(k
= 0;k
< NumChannels
;k
++)
140 ALfloat gain
= state
->Gain
[k
];
141 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
144 for(i
= 0;i
< td
;i
++)
145 SamplesOut
[k
][base
+i
] += gain
* temps
[1][i
];
148 for(i
= 0;i
< td
;i
++)
151 index
&= WAVEFORM_FRACMASK
;
155 state
->index
= index
;
158 DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState
)
160 DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState
);
163 typedef struct ALmodulatorStateFactory
{
164 DERIVE_FROM_TYPE(ALeffectStateFactory
);
165 } ALmodulatorStateFactory
;
167 static ALeffectState
*ALmodulatorStateFactory_create(ALmodulatorStateFactory
*UNUSED(factory
))
169 ALmodulatorState
*state
;
171 state
= ALmodulatorState_New(sizeof(*state
));
172 if(!state
) return NULL
;
173 SET_VTABLE2(ALmodulatorState
, ALeffectState
, state
);
178 ALfilterState_clear(&state
->Filter
);
180 return STATIC_CAST(ALeffectState
, state
);
183 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory
);
185 ALeffectStateFactory
*ALmodulatorStateFactory_getFactory(void)
187 static ALmodulatorStateFactory ModulatorFactory
= { { GET_VTABLE2(ALmodulatorStateFactory
, ALeffectStateFactory
) } };
189 return STATIC_CAST(ALeffectStateFactory
, &ModulatorFactory
);
193 void ALmodulator_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
195 ALeffectProps
*props
= &effect
->Props
;
198 case AL_RING_MODULATOR_FREQUENCY
:
199 if(!(val
>= AL_RING_MODULATOR_MIN_FREQUENCY
&& val
<= AL_RING_MODULATOR_MAX_FREQUENCY
))
200 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
201 props
->Modulator
.Frequency
= val
;
204 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
205 if(!(val
>= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF
&& val
<= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF
))
206 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
207 props
->Modulator
.HighPassCutoff
= val
;
211 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
214 void ALmodulator_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
216 ALmodulator_setParamf(effect
, context
, param
, vals
[0]);
218 void ALmodulator_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
220 ALeffectProps
*props
= &effect
->Props
;
223 case AL_RING_MODULATOR_FREQUENCY
:
224 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
225 ALmodulator_setParamf(effect
, context
, param
, (ALfloat
)val
);
228 case AL_RING_MODULATOR_WAVEFORM
:
229 if(!(val
>= AL_RING_MODULATOR_MIN_WAVEFORM
&& val
<= AL_RING_MODULATOR_MAX_WAVEFORM
))
230 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
231 props
->Modulator
.Waveform
= val
;
235 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
238 void ALmodulator_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
240 ALmodulator_setParami(effect
, context
, param
, vals
[0]);
243 void ALmodulator_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
245 const ALeffectProps
*props
= &effect
->Props
;
248 case AL_RING_MODULATOR_FREQUENCY
:
249 *val
= (ALint
)props
->Modulator
.Frequency
;
251 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
252 *val
= (ALint
)props
->Modulator
.HighPassCutoff
;
254 case AL_RING_MODULATOR_WAVEFORM
:
255 *val
= props
->Modulator
.Waveform
;
259 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
262 void ALmodulator_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
264 ALmodulator_getParami(effect
, context
, param
, vals
);
266 void ALmodulator_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
268 const ALeffectProps
*props
= &effect
->Props
;
271 case AL_RING_MODULATOR_FREQUENCY
:
272 *val
= props
->Modulator
.Frequency
;
274 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
275 *val
= props
->Modulator
.HighPassCutoff
;
279 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
282 void ALmodulator_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
284 ALmodulator_getParamf(effect
, context
, param
, vals
);
287 DEFINE_ALEFFECT_VTABLE(ALmodulator
);