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_EFFECT_CHANNELS
][MAX_OUTPUT_CHANNELS
];
43 ALfilterState Filter
[MAX_EFFECT_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
*state
)
87 ALeffectState_Destruct(STATIC_CAST(ALeffectState
,state
));
90 static ALboolean
ALmodulatorState_deviceUpdate(ALmodulatorState
*UNUSED(state
), ALCdevice
*UNUSED(device
))
95 static ALvoid
ALmodulatorState_update(ALmodulatorState
*state
, const ALCdevice
*Device
, const ALeffectslot
*Slot
, const ALeffectProps
*props
)
101 if(props
->Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
102 state
->Process
= ModulateSin
;
103 else if(props
->Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
104 state
->Process
= ModulateSaw
;
105 else /*if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
106 state
->Process
= ModulateSquare
;
108 state
->step
= fastf2u(props
->Modulator
.Frequency
*WAVEFORM_FRACONE
/
110 if(state
->step
== 0) state
->step
= 1;
112 /* Custom filter coeffs, which match the old version instead of a low-shelf. */
113 cw
= cosf(F_TAU
* props
->Modulator
.HighPassCutoff
/ Device
->Frequency
);
114 a
= (2.0f
-cw
) - sqrtf(powf(2.0f
-cw
, 2.0f
) - 1.0f
);
116 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
118 state
->Filter
[i
].a1
= -a
;
119 state
->Filter
[i
].a2
= 0.0f
;
120 state
->Filter
[i
].b0
= a
;
121 state
->Filter
[i
].b1
= -a
;
122 state
->Filter
[i
].b2
= 0.0f
;
123 state
->Filter
[i
].process
= ALfilterState_processC
;
126 aluMatrixfSet(&matrix
,
127 1.0f
, 0.0f
, 0.0f
, 0.0f
,
128 0.0f
, 1.0f
, 0.0f
, 0.0f
,
129 0.0f
, 0.0f
, 1.0f
, 0.0f
,
130 0.0f
, 0.0f
, 0.0f
, 1.0f
133 STATIC_CAST(ALeffectState
,state
)->OutBuffer
= Device
->FOAOut
.Buffer
;
134 STATIC_CAST(ALeffectState
,state
)->OutChannels
= Device
->FOAOut
.NumChannels
;
135 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
136 ComputeFirstOrderGains(Device
->FOAOut
, matrix
.m
[i
], Slot
->Params
.Gain
,
140 static ALvoid
ALmodulatorState_process(ALmodulatorState
*state
, ALuint SamplesToDo
, const ALfloat (*restrict SamplesIn
)[BUFFERSIZE
], ALfloat (*restrict SamplesOut
)[BUFFERSIZE
], ALuint NumChannels
)
142 const ALuint step
= state
->step
;
143 ALuint index
= state
->index
;
146 for(base
= 0;base
< SamplesToDo
;)
148 ALfloat temps
[2][128];
149 ALuint td
= minu(128, SamplesToDo
-base
);
152 for(j
= 0;j
< MAX_EFFECT_CHANNELS
;j
++)
154 ALfilterState_process(&state
->Filter
[j
], temps
[0], &SamplesIn
[j
][base
], td
);
155 state
->Process(temps
[1], temps
[0], index
, step
, td
);
157 for(k
= 0;k
< NumChannels
;k
++)
159 ALfloat gain
= state
->Gain
[j
][k
];
160 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
163 for(i
= 0;i
< td
;i
++)
164 SamplesOut
[k
][base
+i
] += gain
* temps
[1][i
];
168 for(i
= 0;i
< td
;i
++)
171 index
&= WAVEFORM_FRACMASK
;
175 state
->index
= index
;
178 DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState
)
180 DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState
);
183 typedef struct ALmodulatorStateFactory
{
184 DERIVE_FROM_TYPE(ALeffectStateFactory
);
185 } ALmodulatorStateFactory
;
187 static ALeffectState
*ALmodulatorStateFactory_create(ALmodulatorStateFactory
*UNUSED(factory
))
189 ALmodulatorState
*state
;
192 state
= ALmodulatorState_New(sizeof(*state
));
193 if(!state
) return NULL
;
194 SET_VTABLE2(ALmodulatorState
, ALeffectState
, state
);
199 for(i
= 0;i
< MAX_EFFECT_CHANNELS
;i
++)
200 ALfilterState_clear(&state
->Filter
[i
]);
202 return STATIC_CAST(ALeffectState
, state
);
205 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory
);
207 ALeffectStateFactory
*ALmodulatorStateFactory_getFactory(void)
209 static ALmodulatorStateFactory ModulatorFactory
= { { GET_VTABLE2(ALmodulatorStateFactory
, ALeffectStateFactory
) } };
211 return STATIC_CAST(ALeffectStateFactory
, &ModulatorFactory
);
215 void ALmodulator_setParamf(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat val
)
217 ALeffectProps
*props
= &effect
->Props
;
220 case AL_RING_MODULATOR_FREQUENCY
:
221 if(!(val
>= AL_RING_MODULATOR_MIN_FREQUENCY
&& val
<= AL_RING_MODULATOR_MAX_FREQUENCY
))
222 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
223 props
->Modulator
.Frequency
= val
;
226 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
227 if(!(val
>= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF
&& val
<= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF
))
228 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
229 props
->Modulator
.HighPassCutoff
= val
;
233 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
236 void ALmodulator_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
238 ALmodulator_setParamf(effect
, context
, param
, vals
[0]);
240 void ALmodulator_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
242 ALeffectProps
*props
= &effect
->Props
;
245 case AL_RING_MODULATOR_FREQUENCY
:
246 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
247 ALmodulator_setParamf(effect
, context
, param
, (ALfloat
)val
);
250 case AL_RING_MODULATOR_WAVEFORM
:
251 if(!(val
>= AL_RING_MODULATOR_MIN_WAVEFORM
&& val
<= AL_RING_MODULATOR_MAX_WAVEFORM
))
252 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
253 props
->Modulator
.Waveform
= val
;
257 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
260 void ALmodulator_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
262 ALmodulator_setParami(effect
, context
, param
, vals
[0]);
265 void ALmodulator_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
267 const ALeffectProps
*props
= &effect
->Props
;
270 case AL_RING_MODULATOR_FREQUENCY
:
271 *val
= (ALint
)props
->Modulator
.Frequency
;
273 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
274 *val
= (ALint
)props
->Modulator
.HighPassCutoff
;
276 case AL_RING_MODULATOR_WAVEFORM
:
277 *val
= props
->Modulator
.Waveform
;
281 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
284 void ALmodulator_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
286 ALmodulator_getParami(effect
, context
, param
, vals
);
288 void ALmodulator_getParamf(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
290 const ALeffectProps
*props
= &effect
->Props
;
293 case AL_RING_MODULATOR_FREQUENCY
:
294 *val
= props
->Modulator
.Frequency
;
296 case AL_RING_MODULATOR_HIGHPASS_CUTOFF
:
297 *val
= props
->Modulator
.HighPassCutoff
;
301 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
304 void ALmodulator_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
306 ALmodulator_getParamf(effect
, context
, param
, vals
);
309 DEFINE_ALEFFECT_VTABLE(ALmodulator
);