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
*, ALsizei
, const ALsizei
, ALsizei
);
41 ALfloat Gain
[MAX_EFFECT_CHANNELS
][MAX_OUTPUT_CHANNELS
];
43 ALfilterState Filter
[MAX_EFFECT_CHANNELS
];
46 static ALvoid
ALmodulatorState_Destruct(ALmodulatorState
*state
);
47 static ALboolean
ALmodulatorState_deviceUpdate(ALmodulatorState
*state
, ALCdevice
*device
);
48 static ALvoid
ALmodulatorState_update(ALmodulatorState
*state
, const ALCdevice
*Device
, const ALeffectslot
*Slot
, const ALeffectProps
*props
);
49 static ALvoid
ALmodulatorState_process(ALmodulatorState
*state
, ALsizei SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALsizei NumChannels
);
50 DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState
)
52 DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState
);
55 #define WAVEFORM_FRACBITS 24
56 #define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS)
57 #define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
59 static inline ALfloat
Sin(ALsizei index
)
61 return sinf(index
*(F_TAU
/WAVEFORM_FRACONE
) - F_PI
)*0.5f
+ 0.5f
;
64 static inline ALfloat
Saw(ALsizei index
)
66 return (ALfloat
)index
/ WAVEFORM_FRACONE
;
69 static inline ALfloat
Square(ALsizei index
)
71 return (ALfloat
)((index
>> (WAVEFORM_FRACBITS
- 1)) & 1);
74 #define DECL_TEMPLATE(func) \
75 static void Modulate##func(ALfloat *restrict dst, const ALfloat *restrict src,\
76 ALsizei index, const ALsizei step, ALsizei todo) \
79 for(i = 0;i < todo;i++) \
82 index &= WAVEFORM_FRACMASK; \
83 dst[i] = src[i] * func(index); \
94 static void ALmodulatorState_Construct(ALmodulatorState
*state
)
98 ALeffectState_Construct(STATIC_CAST(ALeffectState
, state
));
99 SET_VTABLE2(ALmodulatorState
, ALeffectState
, state
);
104 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
105 ALfilterState_clear(&state
->Filter
[i
]);
108 static ALvoid
ALmodulatorState_Destruct(ALmodulatorState
*state
)
110 ALeffectState_Destruct(STATIC_CAST(ALeffectState
,state
));
113 static ALboolean
ALmodulatorState_deviceUpdate(ALmodulatorState
*UNUSED(state
), ALCdevice
*UNUSED(device
))
118 static ALvoid
ALmodulatorState_update(ALmodulatorState
*state
, const ALCdevice
*Device
, const ALeffectslot
*Slot
, const ALeffectProps
*props
)
123 if(props
->Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
124 state
->Process
= ModulateSin
;
125 else if(props
->Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
126 state
->Process
= ModulateSaw
;
127 else /*if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
128 state
->Process
= ModulateSquare
;
130 state
->step
= fastf2i(props
->Modulator
.Frequency
*WAVEFORM_FRACONE
/
132 if(state
->step
== 0) state
->step
= 1;
134 /* Custom filter coeffs, which match the old version instead of a low-shelf. */
135 cw
= cosf(F_TAU
* props
->Modulator
.HighPassCutoff
/ Device
->Frequency
);
136 a
= (2.0f
-cw
) - sqrtf(powf(2.0f
-cw
, 2.0f
) - 1.0f
);
138 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
140 state
->Filter
[i
].b0
= a
;
141 state
->Filter
[i
].b1
= -a
;
142 state
->Filter
[i
].b2
= 0.0f
;
143 state
->Filter
[i
].a1
= -a
;
144 state
->Filter
[i
].a2
= 0.0f
;
147 STATIC_CAST(ALeffectState
,state
)->OutBuffer
= Device
->FOAOut
.Buffer
;
148 STATIC_CAST(ALeffectState
,state
)->OutChannels
= Device
->FOAOut
.NumChannels
;
149 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
150 ComputeFirstOrderGains(Device
->FOAOut
, IdentityMatrixf
.m
[i
],
151 Slot
->Params
.Gain
, state
->Gain
[i
]);
154 static ALvoid
ALmodulatorState_process(ALmodulatorState
*state
, ALsizei SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALsizei NumChannels
)
156 const ALsizei step
= state
->step
;
157 ALsizei index
= state
->index
;
160 for(base
= 0;base
< SamplesToDo
;)
162 ALfloat temps
[2][128];
163 ALsizei td
= mini(128, SamplesToDo
-base
);
166 for(j
= 0;j
< MAX_EFFECT_CHANNELS
;j
++)
168 ALfilterState_process(&state
->Filter
[j
], temps
[0], &SamplesIn
[j
][base
], td
);
169 state
->Process(temps
[1], temps
[0], index
, step
, td
);
171 for(k
= 0;k
< NumChannels
;k
++)
173 ALfloat gain
= state
->Gain
[j
][k
];
174 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
177 for(i
= 0;i
< td
;i
++)
178 SamplesOut
[k
][base
+i
] += gain
* temps
[1][i
];
182 for(i
= 0;i
< td
;i
++)
185 index
&= WAVEFORM_FRACMASK
;
189 state
->index
= index
;
193 typedef struct ALmodulatorStateFactory
{
194 DERIVE_FROM_TYPE(ALeffectStateFactory
);
195 } ALmodulatorStateFactory
;
197 static ALeffectState
*ALmodulatorStateFactory_create(ALmodulatorStateFactory
*UNUSED(factory
))
199 ALmodulatorState
*state
;
201 NEW_OBJ0(state
, ALmodulatorState
)();
202 if(!state
) return NULL
;
204 return STATIC_CAST(ALeffectState
, state
);
207 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory
);
209 ALeffectStateFactory
*ALmodulatorStateFactory_getFactory(void)
211 static ALmodulatorStateFactory ModulatorFactory
= { { GET_VTABLE2(ALmodulatorStateFactory
, ALeffectStateFactory
) } };
213 return STATIC_CAST(ALeffectStateFactory
, &ModulatorFactory
);
217 void ALmodulator_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
219 ALeffectProps
*props
= &effect
->Props
;
222 case AL_RING_MODULATOR_FREQUENCY
:
223 if(!(val
>= AL_RING_MODULATOR_MIN_FREQUENCY
&& val
<= AL_RING_MODULATOR_MAX_FREQUENCY
))
224 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
225 props
->Modulator
.Frequency
= val
;
228 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
229 if(!(val
>= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF
&& val
<= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF
))
230 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
231 props
->Modulator
.HighPassCutoff
= val
;
235 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
238 void ALmodulator_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
240 ALmodulator_setParamf(effect
, context
, param
, vals
[0]);
242 void ALmodulator_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
244 ALeffectProps
*props
= &effect
->Props
;
247 case AL_RING_MODULATOR_FREQUENCY
:
248 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
249 ALmodulator_setParamf(effect
, context
, param
, (ALfloat
)val
);
252 case AL_RING_MODULATOR_WAVEFORM
:
253 if(!(val
>= AL_RING_MODULATOR_MIN_WAVEFORM
&& val
<= AL_RING_MODULATOR_MAX_WAVEFORM
))
254 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
255 props
->Modulator
.Waveform
= val
;
259 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
262 void ALmodulator_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
264 ALmodulator_setParami(effect
, context
, param
, vals
[0]);
267 void ALmodulator_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
269 const ALeffectProps
*props
= &effect
->Props
;
272 case AL_RING_MODULATOR_FREQUENCY
:
273 *val
= (ALint
)props
->Modulator
.Frequency
;
275 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
276 *val
= (ALint
)props
->Modulator
.HighPassCutoff
;
278 case AL_RING_MODULATOR_WAVEFORM
:
279 *val
= props
->Modulator
.Waveform
;
283 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
286 void ALmodulator_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
288 ALmodulator_getParami(effect
, context
, param
, vals
);
290 void ALmodulator_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
292 const ALeffectProps
*props
= &effect
->Props
;
295 case AL_RING_MODULATOR_FREQUENCY
:
296 *val
= props
->Modulator
.Frequency
;
298 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
299 *val
= props
->Modulator
.HighPassCutoff
;
303 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
306 void ALmodulator_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
308 ALmodulator_getParamf(effect
, context
, param
, vals
);
311 DEFINE_ALEFFECT_VTABLE(ALmodulator
);