Print whether direct channels are off or on to stdout in alffplay
[openal-soft.git] / Alc / effects / chorus.c
blob63d0ca018321aeb8fdcdef4d595fa511ebe2dfc2
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 ALuint BufferLength;
43 ALuint offset;
44 ALuint 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, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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 ALuint maxlen;
92 ALuint it;
94 maxlen = fastf2u(AL_CHORUS_MAX_DELAY * 3.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->depth = props->Chorus.Depth;
135 state->feedback = props->Chorus.Feedback;
136 state->delay = fastf2i(props->Chorus.Delay * frequency);
138 /* Gains for left and right sides */
139 CalcXYZCoeffs(-1.0f, 0.0f, 0.0f, 0.0f, coeffs);
140 ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]);
141 CalcXYZCoeffs( 1.0f, 0.0f, 0.0f, 0.0f, coeffs);
142 ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]);
144 phase = props->Chorus.Phase;
145 rate = props->Chorus.Rate;
146 if(!(rate > 0.0f))
148 state->lfo_scale = 0.0f;
149 state->lfo_range = 1;
150 state->lfo_disp = 0;
152 else
154 /* Calculate LFO coefficient */
155 state->lfo_range = fastf2u(frequency/rate + 0.5f);
156 switch(state->waveform)
158 case CWF_Triangle:
159 state->lfo_scale = 4.0f / state->lfo_range;
160 break;
161 case CWF_Sinusoid:
162 state->lfo_scale = F_TAU / state->lfo_range;
163 break;
166 /* Calculate lfo phase displacement */
167 state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f));
171 static inline void Triangle(ALint *delay_left, ALint *delay_right, ALuint offset, const ALchorusState *state)
173 ALfloat lfo_value;
175 lfo_value = 2.0f - fabsf(2.0f - state->lfo_scale*(offset%state->lfo_range));
176 lfo_value *= state->depth * state->delay;
177 *delay_left = fastf2i(lfo_value) + state->delay;
179 offset += state->lfo_disp;
180 lfo_value = 2.0f - fabsf(2.0f - state->lfo_scale*(offset%state->lfo_range));
181 lfo_value *= state->depth * state->delay;
182 *delay_right = fastf2i(lfo_value) + state->delay;
185 static inline void Sinusoid(ALint *delay_left, ALint *delay_right, ALuint offset, const ALchorusState *state)
187 ALfloat lfo_value;
189 lfo_value = 1.0f + sinf(state->lfo_scale*(offset%state->lfo_range));
190 lfo_value *= state->depth * state->delay;
191 *delay_left = fastf2i(lfo_value) + state->delay;
193 offset += state->lfo_disp;
194 lfo_value = 1.0f + sinf(state->lfo_scale*(offset%state->lfo_range));
195 lfo_value *= state->depth * state->delay;
196 *delay_right = fastf2i(lfo_value) + state->delay;
199 #define DECL_TEMPLATE(Func) \
200 static void Process##Func(ALchorusState *state, const ALuint SamplesToDo, \
201 const ALfloat *restrict SamplesIn, ALfloat (*restrict out)[2]) \
203 const ALuint bufmask = state->BufferLength-1; \
204 ALfloat *restrict leftbuf = state->SampleBuffer[0]; \
205 ALfloat *restrict rightbuf = state->SampleBuffer[1]; \
206 ALuint offset = state->offset; \
207 const ALfloat feedback = state->feedback; \
208 ALuint it; \
210 for(it = 0;it < SamplesToDo;it++) \
212 ALint delay_left, delay_right; \
213 Func(&delay_left, &delay_right, offset, state); \
215 out[it][0] = leftbuf[(offset-delay_left)&bufmask]; \
216 leftbuf[offset&bufmask] = (out[it][0]+SamplesIn[it]) * feedback; \
218 out[it][1] = rightbuf[(offset-delay_right)&bufmask]; \
219 rightbuf[offset&bufmask] = (out[it][1]+SamplesIn[it]) * feedback; \
221 offset++; \
223 state->offset = offset; \
226 DECL_TEMPLATE(Triangle)
227 DECL_TEMPLATE(Sinusoid)
229 #undef DECL_TEMPLATE
231 static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
233 ALuint it, kt;
234 ALuint base;
236 for(base = 0;base < SamplesToDo;)
238 ALfloat temps[128][2];
239 ALuint td = minu(128, SamplesToDo-base);
241 switch(state->waveform)
243 case CWF_Triangle:
244 ProcessTriangle(state, td, SamplesIn[0]+base, temps);
245 break;
246 case CWF_Sinusoid:
247 ProcessSinusoid(state, td, SamplesIn[0]+base, temps);
248 break;
251 for(kt = 0;kt < NumChannels;kt++)
253 ALfloat gain = state->Gain[0][kt];
254 if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
256 for(it = 0;it < td;it++)
257 SamplesOut[kt][it+base] += temps[it][0] * gain;
260 gain = state->Gain[1][kt];
261 if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
263 for(it = 0;it < td;it++)
264 SamplesOut[kt][it+base] += temps[it][1] * gain;
268 base += td;
273 typedef struct ALchorusStateFactory {
274 DERIVE_FROM_TYPE(ALeffectStateFactory);
275 } ALchorusStateFactory;
277 static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(factory))
279 ALchorusState *state;
281 NEW_OBJ0(state, ALchorusState)();
282 if(!state) return NULL;
284 return STATIC_CAST(ALeffectState, state);
287 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALchorusStateFactory);
290 ALeffectStateFactory *ALchorusStateFactory_getFactory(void)
292 static ALchorusStateFactory ChorusFactory = { { GET_VTABLE2(ALchorusStateFactory, ALeffectStateFactory) } };
294 return STATIC_CAST(ALeffectStateFactory, &ChorusFactory);
298 void ALchorus_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
300 ALeffectProps *props = &effect->Props;
301 switch(param)
303 case AL_CHORUS_WAVEFORM:
304 if(!(val >= AL_CHORUS_MIN_WAVEFORM && val <= AL_CHORUS_MAX_WAVEFORM))
305 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
306 props->Chorus.Waveform = val;
307 break;
309 case AL_CHORUS_PHASE:
310 if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
311 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
312 props->Chorus.Phase = val;
313 break;
315 default:
316 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
319 void ALchorus_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
321 ALchorus_setParami(effect, context, param, vals[0]);
323 void ALchorus_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
325 ALeffectProps *props = &effect->Props;
326 switch(param)
328 case AL_CHORUS_RATE:
329 if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
330 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
331 props->Chorus.Rate = val;
332 break;
334 case AL_CHORUS_DEPTH:
335 if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
336 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
337 props->Chorus.Depth = val;
338 break;
340 case AL_CHORUS_FEEDBACK:
341 if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
342 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
343 props->Chorus.Feedback = val;
344 break;
346 case AL_CHORUS_DELAY:
347 if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
348 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
349 props->Chorus.Delay = val;
350 break;
352 default:
353 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
356 void ALchorus_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
358 ALchorus_setParamf(effect, context, param, vals[0]);
361 void ALchorus_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
363 const ALeffectProps *props = &effect->Props;
364 switch(param)
366 case AL_CHORUS_WAVEFORM:
367 *val = props->Chorus.Waveform;
368 break;
370 case AL_CHORUS_PHASE:
371 *val = props->Chorus.Phase;
372 break;
374 default:
375 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
378 void ALchorus_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
380 ALchorus_getParami(effect, context, param, vals);
382 void ALchorus_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
384 const ALeffectProps *props = &effect->Props;
385 switch(param)
387 case AL_CHORUS_RATE:
388 *val = props->Chorus.Rate;
389 break;
391 case AL_CHORUS_DEPTH:
392 *val = props->Chorus.Depth;
393 break;
395 case AL_CHORUS_FEEDBACK:
396 *val = props->Chorus.Feedback;
397 break;
399 case AL_CHORUS_DELAY:
400 *val = props->Chorus.Delay;
401 break;
403 default:
404 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
407 void ALchorus_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
409 ALchorus_getParamf(effect, context, param, vals);
412 DEFINE_ALEFFECT_VTABLE(ALchorus);