Retreive and store source params once per mix update
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob7a9c6326d911c2ba4b4213a848d736c2b994c4da
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <math.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alThunk.h"
31 #include "alError.h"
34 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
37 ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
39 ALCcontext *Context;
40 ALsizei i, j;
42 Context = GetContextSuspended();
43 if(!Context) return;
45 if (n > 0)
47 ALCdevice *Device = Context->Device;
49 if(Context->AuxiliaryEffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
51 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
52 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
54 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
55 while(*list)
56 list = &(*list)->next;
58 i = 0;
59 while(i < n)
61 *list = calloc(1, sizeof(ALeffectslot));
62 if(!(*list))
64 // We must have run out or memory
65 alDeleteAuxiliaryEffectSlots(i, effectslots);
66 alSetError(AL_OUT_OF_MEMORY);
67 break;
70 (*list)->Gain = 1.0;
71 (*list)->AuxSendAuto = AL_TRUE;
72 for(j = 0;j < BUFFERSIZE;j++)
73 (*list)->WetBuffer[j] = 0.0f;
74 (*list)->refcount = 0;
76 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
77 (*list)->effectslot = effectslots[i];
79 Context->AuxiliaryEffectSlotCount++;
80 i++;
82 list = &(*list)->next;
86 else
87 alSetError(AL_INVALID_OPERATION);
90 ProcessContext(Context);
93 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
95 ALCcontext *Context;
96 ALeffectslot *ALAuxiliaryEffectSlot;
97 ALsizei i;
99 Context = GetContextSuspended();
100 if(!Context) return;
102 if (n >= 0)
104 // Check that all effectslots are valid
105 for (i = 0; i < n; i++)
107 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
109 alSetError(AL_INVALID_NAME);
110 break;
112 else
114 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
115 if(ALAuxiliaryEffectSlot->refcount > 0)
117 alSetError(AL_INVALID_NAME);
118 break;
123 if (i == n)
125 // All effectslots are valid
126 for (i = 0; i < n; i++)
128 // Recheck that the effectslot is valid, because there could be duplicated names
129 if (alIsAuxiliaryEffectSlot(effectslots[i]))
131 ALeffectslot **list;
133 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
135 // Remove Source from list of Sources
136 list = &Context->AuxiliaryEffectSlot;
137 while(*list && *list != ALAuxiliaryEffectSlot)
138 list = &(*list)->next;
140 if(*list)
141 *list = (*list)->next;
142 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
144 if(ALAuxiliaryEffectSlot->EffectState)
145 ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
147 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
148 free(ALAuxiliaryEffectSlot);
150 Context->AuxiliaryEffectSlotCount--;
155 else
156 alSetError(AL_INVALID_VALUE);
158 ProcessContext(Context);
161 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
163 ALCcontext *Context;
164 ALeffectslot **list;
166 Context = GetContextSuspended();
167 if(!Context) return AL_FALSE;
169 list = &Context->AuxiliaryEffectSlot;
170 while(*list && (*list)->effectslot != effectslot)
171 list = &(*list)->next;
173 ProcessContext(Context);
175 return (*list ? AL_TRUE : AL_FALSE);
178 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
180 ALCcontext *Context;
182 Context = GetContextSuspended();
183 if(!Context) return;
185 if (alIsAuxiliaryEffectSlot(effectslot))
187 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
189 switch(param)
191 case AL_EFFECTSLOT_EFFECT:
192 if(alIsEffect(iValue))
194 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
195 InitializeEffect(Context, ALEffectSlot, effect);
197 else
198 alSetError(AL_INVALID_VALUE);
199 break;
201 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
202 if(iValue == AL_TRUE || iValue == AL_FALSE)
203 ALEffectSlot->AuxSendAuto = iValue;
204 else
205 alSetError(AL_INVALID_VALUE);
206 break;
208 default:
209 alSetError(AL_INVALID_ENUM);
210 break;
213 else
214 alSetError(AL_INVALID_NAME);
216 ProcessContext(Context);
219 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
221 ALCcontext *Context;
223 Context = GetContextSuspended();
224 if(!Context) return;
226 if (alIsAuxiliaryEffectSlot(effectslot))
228 switch(param)
230 case AL_EFFECTSLOT_EFFECT:
231 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
232 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
233 break;
235 default:
236 alSetError(AL_INVALID_ENUM);
237 break;
240 else
241 alSetError(AL_INVALID_NAME);
243 ProcessContext(Context);
246 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
248 ALCcontext *Context;
250 Context = GetContextSuspended();
251 if(!Context) return;
253 if (alIsAuxiliaryEffectSlot(effectslot))
255 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
257 switch(param)
259 case AL_EFFECTSLOT_GAIN:
260 if(flValue >= 0.0f && flValue <= 1.0f)
261 ALEffectSlot->Gain = flValue;
262 else
263 alSetError(AL_INVALID_VALUE);
264 break;
266 default:
267 alSetError(AL_INVALID_ENUM);
268 break;
271 else
272 alSetError(AL_INVALID_NAME);
274 ProcessContext(Context);
277 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
279 ALCcontext *Context;
281 Context = GetContextSuspended();
282 if(!Context) return;
284 if (alIsAuxiliaryEffectSlot(effectslot))
286 switch(param)
288 case AL_EFFECTSLOT_GAIN:
289 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
290 break;
292 default:
293 alSetError(AL_INVALID_ENUM);
294 break;
297 else
298 alSetError(AL_INVALID_NAME);
300 ProcessContext(Context);
303 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
305 ALCcontext *Context;
307 Context = GetContextSuspended();
308 if(!Context) return;
310 if (alIsAuxiliaryEffectSlot(effectslot))
312 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
314 switch(param)
316 case AL_EFFECTSLOT_EFFECT:
317 *piValue = ALEffectSlot->effect.effect;
318 break;
320 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
321 *piValue = ALEffectSlot->AuxSendAuto;
322 break;
324 default:
325 alSetError(AL_INVALID_ENUM);
326 break;
329 else
330 alSetError(AL_INVALID_NAME);
332 ProcessContext(Context);
335 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
337 ALCcontext *Context;
339 Context = GetContextSuspended();
340 if(!Context) return;
342 if (alIsAuxiliaryEffectSlot(effectslot))
344 switch(param)
346 case AL_EFFECTSLOT_EFFECT:
347 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
348 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
349 break;
351 default:
352 alSetError(AL_INVALID_ENUM);
353 break;
356 else
357 alSetError(AL_INVALID_NAME);
359 ProcessContext(Context);
362 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
364 ALCcontext *Context;
366 Context = GetContextSuspended();
367 if(!Context) return;
369 if (alIsAuxiliaryEffectSlot(effectslot))
371 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
373 switch(param)
375 case AL_EFFECTSLOT_GAIN:
376 *pflValue = ALEffectSlot->Gain;
377 break;
379 default:
380 alSetError(AL_INVALID_ENUM);
381 break;
384 else
385 alSetError(AL_INVALID_NAME);
387 ProcessContext(Context);
390 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
392 ALCcontext *Context;
394 Context = GetContextSuspended();
395 if(!Context) return;
397 if (alIsAuxiliaryEffectSlot(effectslot))
399 switch(param)
401 case AL_EFFECTSLOT_GAIN:
402 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
403 break;
405 default:
406 alSetError(AL_INVALID_ENUM);
407 break;
410 else
411 alSetError(AL_INVALID_NAME);
413 ProcessContext(Context);
417 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
419 if((!effect) || (effect->type != ALEffectSlot->effect.type))
421 ALeffectState *NewState = NULL;
422 if(effect)
424 if(effect->type == AL_EFFECT_EAXREVERB)
425 NewState = EAXVerbCreate();
426 else if(effect->type == AL_EFFECT_REVERB)
427 NewState = VerbCreate();
428 else if(effect->type == AL_EFFECT_ECHO)
429 NewState = EchoCreate();
430 /* No new state? An error occured.. */
431 if(NewState == NULL ||
432 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
434 if(NewState)
435 ALEffect_Destroy(NewState);
436 return;
439 if(ALEffectSlot->EffectState)
440 ALEffect_Destroy(ALEffectSlot->EffectState);
441 ALEffectSlot->EffectState = NewState;
443 if(!effect)
445 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
446 return;
448 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
449 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
453 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
455 while(Context->AuxiliaryEffectSlot)
457 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
458 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
460 // Release effectslot structure
461 if(temp->EffectState)
462 ALEffect_Destroy(temp->EffectState);
463 ALTHUNK_REMOVEENTRY(temp->effectslot);
465 memset(temp, 0, sizeof(ALeffectslot));
466 free(temp);
468 Context->AuxiliaryEffectSlotCount = 0;