Update ChangeLog
[openal-soft.git] / Alc / effects / chorus.c
blobf4383aa564b553f12dab191e188e27cc52d203d6
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 2013 by Mike Gorchak
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
26 #include "alMain.h"
27 #include "alFilter.h"
28 #include "alAuxEffectSlot.h"
29 #include "alError.h"
30 #include "alu.h"
33 enum ChorusWaveForm {
34 CWF_Triangle = AL_CHORUS_WAVEFORM_TRIANGLE,
35 CWF_Sinusoid = AL_CHORUS_WAVEFORM_SINUSOID
38 typedef struct ALchorusState {
39 DERIVE_FROM_TYPE(ALeffectState);
41 ALfloat *SampleBuffer[2];
42 ALsizei BufferLength;
43 ALsizei offset;
44 ALsizei lfo_range;
45 ALfloat lfo_scale;
46 ALint lfo_disp;
48 /* Gains for left and right sides */
49 ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
51 /* effect parameters */
52 enum ChorusWaveForm waveform;
53 ALint delay;
54 ALfloat depth;
55 ALfloat feedback;
56 } ALchorusState;
58 static ALvoid ALchorusState_Destruct(ALchorusState *state);
59 static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device);
60 static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props);
61 static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
62 DECLARE_DEFAULT_ALLOCATORS(ALchorusState)
64 DEFINE_ALEFFECTSTATE_VTABLE(ALchorusState);
67 static void ALchorusState_Construct(ALchorusState *state)
69 ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
70 SET_VTABLE2(ALchorusState, ALeffectState, state);
72 state->BufferLength = 0;
73 state->SampleBuffer[0] = NULL;
74 state->SampleBuffer[1] = NULL;
75 state->offset = 0;
76 state->lfo_range = 1;
77 state->waveform = CWF_Triangle;
80 static ALvoid ALchorusState_Destruct(ALchorusState *state)
82 al_free(state->SampleBuffer[0]);
83 state->SampleBuffer[0] = NULL;
84 state->SampleBuffer[1] = NULL;
86 ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
89 static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device)
91 ALsizei maxlen;
92 ALsizei it;
94 maxlen = fastf2i(AL_CHORUS_MAX_DELAY * 2.0f * Device->Frequency) + 1;
95 maxlen = NextPowerOf2(maxlen);
97 if(maxlen != state->BufferLength)
99 void *temp = al_calloc(16, maxlen * sizeof(ALfloat) * 2);
100 if(!temp) return AL_FALSE;
102 al_free(state->SampleBuffer[0]);
103 state->SampleBuffer[0] = temp;
104 state->SampleBuffer[1] = state->SampleBuffer[0] + maxlen;
106 state->BufferLength = maxlen;
109 for(it = 0;it < state->BufferLength;it++)
111 state->SampleBuffer[0][it] = 0.0f;
112 state->SampleBuffer[1][it] = 0.0f;
115 return AL_TRUE;
118 static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
120 ALfloat frequency = (ALfloat)Device->Frequency;
121 ALfloat coeffs[MAX_AMBI_COEFFS];
122 ALfloat rate;
123 ALint phase;
125 switch(props->Chorus.Waveform)
127 case AL_CHORUS_WAVEFORM_TRIANGLE:
128 state->waveform = CWF_Triangle;
129 break;
130 case AL_CHORUS_WAVEFORM_SINUSOID:
131 state->waveform = CWF_Sinusoid;
132 break;
134 state->feedback = props->Chorus.Feedback;
135 state->delay = fastf2i(props->Chorus.Delay * frequency);
136 /* The LFO depth is scaled to be relative to the sample delay. */
137 state->depth = props->Chorus.Depth * state->delay;
139 /* Gains for left and right sides */
140 CalcAngleCoeffs(-F_PI_2, 0.0f, 0.0f, coeffs);
141 ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]);
142 CalcAngleCoeffs( F_PI_2, 0.0f, 0.0f, coeffs);
143 ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]);
145 phase = props->Chorus.Phase;
146 rate = props->Chorus.Rate;
147 if(!(rate > 0.0f))
149 state->lfo_scale = 0.0f;
150 state->lfo_range = 1;
151 state->lfo_disp = 0;
153 else
155 /* Calculate LFO coefficient */
156 state->lfo_range = fastf2i(frequency/rate + 0.5f);
157 switch(state->waveform)
159 case CWF_Triangle:
160 state->lfo_scale = 4.0f / state->lfo_range;
161 break;
162 case CWF_Sinusoid:
163 state->lfo_scale = F_TAU / state->lfo_range;
164 break;
167 /* Calculate lfo phase displacement */
168 if(phase >= 0)
169 state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f));
170 else
171 state->lfo_disp = fastf2i(state->lfo_range * ((360+phase)/360.0f));
175 static void GetTriangleDelays(ALint *restrict delays, ALsizei offset, const ALsizei lfo_range,
176 const ALfloat lfo_scale, const ALfloat depth, const ALsizei delay,
177 const ALsizei todo)
179 ALsizei i;
180 for(i = 0;i < todo;i++)
182 delays[i] = fastf2i((1.0f - fabsf(2.0f - lfo_scale*offset)) * depth) + delay;
183 offset = (offset+1)%lfo_range;
187 static void GetSinusoidDelays(ALint *restrict delays, ALsizei offset, const ALsizei lfo_range,
188 const ALfloat lfo_scale, const ALfloat depth, const ALsizei delay,
189 const ALsizei todo)
191 ALsizei i;
192 for(i = 0;i < todo;i++)
194 delays[i] = fastf2i(sinf(lfo_scale*offset) * depth) + delay;
195 offset = (offset+1)%lfo_range;
200 static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
202 ALfloat *restrict leftbuf = state->SampleBuffer[0];
203 ALfloat *restrict rightbuf = state->SampleBuffer[1];
204 const ALsizei bufmask = state->BufferLength-1;
205 const ALfloat feedback = state->feedback;
206 ALsizei offset = state->offset;
207 ALsizei i, c;
208 ALsizei base;
210 for(base = 0;base < SamplesToDo;)
212 const ALsizei todo = mini(128, SamplesToDo-base);
213 ALfloat temps[128][2];
214 ALint moddelays[2][128];
216 switch(state->waveform)
218 case CWF_Triangle:
219 GetTriangleDelays(moddelays[0], offset%state->lfo_range, state->lfo_range,
220 state->lfo_scale, state->depth, state->delay, todo);
221 GetTriangleDelays(moddelays[1], (offset+state->lfo_disp)%state->lfo_range,
222 state->lfo_range, state->lfo_scale, state->depth, state->delay,
223 todo);
224 break;
225 case CWF_Sinusoid:
226 GetSinusoidDelays(moddelays[0], offset%state->lfo_range, state->lfo_range,
227 state->lfo_scale, state->depth, state->delay, todo);
228 GetSinusoidDelays(moddelays[1], (offset+state->lfo_disp)%state->lfo_range,
229 state->lfo_range, state->lfo_scale, state->depth, state->delay,
230 todo);
231 break;
234 for(i = 0;i < todo;i++)
236 leftbuf[offset&bufmask] = SamplesIn[0][base+i];
237 temps[i][0] = leftbuf[(offset-moddelays[0][i])&bufmask] * feedback;
238 leftbuf[offset&bufmask] += temps[i][0];
240 rightbuf[offset&bufmask] = SamplesIn[0][base+i];
241 temps[i][1] = rightbuf[(offset-moddelays[1][i])&bufmask] * feedback;
242 rightbuf[offset&bufmask] += temps[i][1];
244 offset++;
247 for(c = 0;c < NumChannels;c++)
249 ALfloat gain = state->Gain[0][c];
250 if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
252 for(i = 0;i < todo;i++)
253 SamplesOut[c][i+base] += temps[i][0] * gain;
256 gain = state->Gain[1][c];
257 if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
259 for(i = 0;i < todo;i++)
260 SamplesOut[c][i+base] += temps[i][1] * gain;
264 base += todo;
267 state->offset = offset;
271 typedef struct ALchorusStateFactory {
272 DERIVE_FROM_TYPE(ALeffectStateFactory);
273 } ALchorusStateFactory;
275 static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(factory))
277 ALchorusState *state;
279 NEW_OBJ0(state, ALchorusState)();
280 if(!state) return NULL;
282 return STATIC_CAST(ALeffectState, state);
285 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALchorusStateFactory);
288 ALeffectStateFactory *ALchorusStateFactory_getFactory(void)
290 static ALchorusStateFactory ChorusFactory = { { GET_VTABLE2(ALchorusStateFactory, ALeffectStateFactory) } };
292 return STATIC_CAST(ALeffectStateFactory, &ChorusFactory);
296 void ALchorus_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
298 ALeffectProps *props = &effect->Props;
299 switch(param)
301 case AL_CHORUS_WAVEFORM:
302 if(!(val >= AL_CHORUS_MIN_WAVEFORM && val <= AL_CHORUS_MAX_WAVEFORM))
303 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
304 props->Chorus.Waveform = val;
305 break;
307 case AL_CHORUS_PHASE:
308 if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
309 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
310 props->Chorus.Phase = val;
311 break;
313 default:
314 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
317 void ALchorus_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
319 ALchorus_setParami(effect, context, param, vals[0]);
321 void ALchorus_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
323 ALeffectProps *props = &effect->Props;
324 switch(param)
326 case AL_CHORUS_RATE:
327 if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
328 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
329 props->Chorus.Rate = val;
330 break;
332 case AL_CHORUS_DEPTH:
333 if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
334 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
335 props->Chorus.Depth = val;
336 break;
338 case AL_CHORUS_FEEDBACK:
339 if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
340 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
341 props->Chorus.Feedback = val;
342 break;
344 case AL_CHORUS_DELAY:
345 if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
346 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
347 props->Chorus.Delay = val;
348 break;
350 default:
351 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
354 void ALchorus_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
356 ALchorus_setParamf(effect, context, param, vals[0]);
359 void ALchorus_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
361 const ALeffectProps *props = &effect->Props;
362 switch(param)
364 case AL_CHORUS_WAVEFORM:
365 *val = props->Chorus.Waveform;
366 break;
368 case AL_CHORUS_PHASE:
369 *val = props->Chorus.Phase;
370 break;
372 default:
373 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
376 void ALchorus_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
378 ALchorus_getParami(effect, context, param, vals);
380 void ALchorus_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
382 const ALeffectProps *props = &effect->Props;
383 switch(param)
385 case AL_CHORUS_RATE:
386 *val = props->Chorus.Rate;
387 break;
389 case AL_CHORUS_DEPTH:
390 *val = props->Chorus.Depth;
391 break;
393 case AL_CHORUS_FEEDBACK:
394 *val = props->Chorus.Feedback;
395 break;
397 case AL_CHORUS_DELAY:
398 *val = props->Chorus.Delay;
399 break;
401 default:
402 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
405 void ALchorus_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
407 ALchorus_getParamf(effect, context, param, vals);
410 DEFINE_ALEFFECT_VTABLE(ALchorus);