Move the WetBuffer into the effect slot object
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob65db34b393c8f899c5a73dd18f7838c457fc2801
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"
32 #include "alReverb.h"
35 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
38 ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
40 ALCcontext *Context;
41 ALsizei i, j;
43 Context = alcGetCurrentContext();
44 if(!Context)
46 alSetError(AL_INVALID_OPERATION);
47 return;
49 SuspendContext(Context);
51 if (n > 0)
53 /* NOTE: We only support one slot currently */
54 if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
56 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
57 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
59 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
60 while(*list)
61 list = &(*list)->next;
63 i = 0;
64 while(i < n)
66 *list = calloc(1, sizeof(ALeffectslot));
67 if(!(*list))
69 // We must have run out or memory
70 alDeleteAuxiliaryEffectSlots(i, effectslots);
71 alSetError(AL_OUT_OF_MEMORY);
72 break;
75 (*list)->Gain = 1.0;
76 (*list)->AuxSendAuto = AL_TRUE;
77 for(j = 0;j < BUFFERSIZE;j++)
78 (*list)->WetBuffer[j] = 0.0f;
79 (*list)->refcount = 0;
81 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
82 (*list)->effectslot = effectslots[i];
84 Context->AuxiliaryEffectSlotCount++;
85 i++;
87 list = &(*list)->next;
91 else
92 alSetError(AL_INVALID_OPERATION);
95 ProcessContext(Context);
98 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
100 ALCcontext *Context;
101 ALeffectslot *ALAuxiliaryEffectSlot;
102 ALsizei i;
104 Context = alcGetCurrentContext();
105 if(!Context)
107 alSetError(AL_INVALID_OPERATION);
108 return;
110 SuspendContext(Context);
112 if (n >= 0)
114 // Check that all effectslots are valid
115 for (i = 0; i < n; i++)
117 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
119 alSetError(AL_INVALID_NAME);
120 break;
122 else
124 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
125 if(ALAuxiliaryEffectSlot->refcount > 0)
127 alSetError(AL_INVALID_NAME);
128 break;
133 if (i == n)
135 // All effectslots are valid
136 for (i = 0; i < n; i++)
138 // Recheck that the effectslot is valid, because there could be duplicated names
139 if (alIsAuxiliaryEffectSlot(effectslots[i]))
141 ALeffectslot **list;
143 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
145 // Remove Source from list of Sources
146 list = &Context->AuxiliaryEffectSlot;
147 while(*list && *list != ALAuxiliaryEffectSlot)
148 list = &(*list)->next;
150 if(*list)
151 *list = (*list)->next;
152 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
154 VerbDestroy(ALAuxiliaryEffectSlot->ReverbState);
156 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
157 free(ALAuxiliaryEffectSlot);
159 Context->AuxiliaryEffectSlotCount--;
164 else
165 alSetError(AL_INVALID_VALUE);
167 ProcessContext(Context);
170 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
172 ALCcontext *Context;
173 ALeffectslot **list;
175 Context = alcGetCurrentContext();
176 if(!Context)
178 alSetError(AL_INVALID_OPERATION);
179 return AL_FALSE;
181 SuspendContext(Context);
183 list = &Context->AuxiliaryEffectSlot;
184 while(*list && (*list)->effectslot != effectslot)
185 list = &(*list)->next;
187 ProcessContext(Context);
189 return (*list ? AL_TRUE : AL_FALSE);
192 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
194 ALCcontext *Context;
196 Context = alcGetCurrentContext();
197 if(!Context)
199 alSetError(AL_INVALID_OPERATION);
200 return;
202 SuspendContext(Context);
204 if (alIsAuxiliaryEffectSlot(effectslot))
206 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
208 switch(param)
210 case AL_EFFECTSLOT_EFFECT:
211 if(alIsEffect(iValue))
213 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
214 InitializeEffect(Context, ALEffectSlot, effect);
216 else
217 alSetError(AL_INVALID_VALUE);
218 break;
220 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
221 if(iValue == AL_TRUE || iValue == AL_FALSE)
222 ALEffectSlot->AuxSendAuto = iValue;
223 else
224 alSetError(AL_INVALID_VALUE);
225 break;
227 default:
228 alSetError(AL_INVALID_ENUM);
229 break;
232 else
233 alSetError(AL_INVALID_NAME);
235 ProcessContext(Context);
238 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
240 ALCcontext *Context;
242 Context = alcGetCurrentContext();
243 if(!Context)
245 alSetError(AL_INVALID_OPERATION);
246 return;
248 SuspendContext(Context);
250 if (alIsAuxiliaryEffectSlot(effectslot))
252 switch(param)
254 case AL_EFFECTSLOT_EFFECT:
255 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
256 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
257 break;
259 default:
260 alSetError(AL_INVALID_ENUM);
261 break;
264 else
265 alSetError(AL_INVALID_NAME);
267 ProcessContext(Context);
270 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
272 ALCcontext *Context;
274 Context = alcGetCurrentContext();
275 if(!Context)
277 alSetError(AL_INVALID_OPERATION);
278 return;
280 SuspendContext(Context);
282 if (alIsAuxiliaryEffectSlot(effectslot))
284 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
286 switch(param)
288 case AL_EFFECTSLOT_GAIN:
289 if(flValue >= 0.0f && flValue <= 1.0f)
290 ALEffectSlot->Gain = flValue;
291 else
292 alSetError(AL_INVALID_VALUE);
293 break;
295 default:
296 alSetError(AL_INVALID_ENUM);
297 break;
300 else
301 alSetError(AL_INVALID_NAME);
303 ProcessContext(Context);
306 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
308 ALCcontext *Context;
310 Context = alcGetCurrentContext();
311 if(!Context)
313 alSetError(AL_INVALID_OPERATION);
314 return;
316 SuspendContext(Context);
318 if (alIsAuxiliaryEffectSlot(effectslot))
320 switch(param)
322 case AL_EFFECTSLOT_GAIN:
323 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
324 break;
326 default:
327 alSetError(AL_INVALID_ENUM);
328 break;
331 else
332 alSetError(AL_INVALID_NAME);
334 ProcessContext(Context);
337 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
339 ALCcontext *Context;
341 Context = alcGetCurrentContext();
342 if(!Context)
344 alSetError(AL_INVALID_OPERATION);
345 return;
347 SuspendContext(Context);
349 if (alIsAuxiliaryEffectSlot(effectslot))
351 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
353 switch(param)
355 case AL_EFFECTSLOT_EFFECT:
356 *piValue = ALEffectSlot->effect.effect;
357 break;
359 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
360 *piValue = ALEffectSlot->AuxSendAuto;
361 break;
363 default:
364 alSetError(AL_INVALID_ENUM);
365 break;
368 else
369 alSetError(AL_INVALID_NAME);
371 ProcessContext(Context);
374 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
376 ALCcontext *Context;
378 Context = alcGetCurrentContext();
379 if(!Context)
381 alSetError(AL_INVALID_OPERATION);
382 return;
384 SuspendContext(Context);
386 if (alIsAuxiliaryEffectSlot(effectslot))
388 switch(param)
390 case AL_EFFECTSLOT_EFFECT:
391 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
392 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
393 break;
395 default:
396 alSetError(AL_INVALID_ENUM);
397 break;
400 else
401 alSetError(AL_INVALID_NAME);
403 ProcessContext(Context);
406 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
408 ALCcontext *Context;
410 Context = alcGetCurrentContext();
411 if(!Context)
413 alSetError(AL_INVALID_OPERATION);
414 return;
416 SuspendContext(Context);
418 if (alIsAuxiliaryEffectSlot(effectslot))
420 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
422 switch(param)
424 case AL_EFFECTSLOT_GAIN:
425 *pflValue = ALEffectSlot->Gain;
426 break;
428 default:
429 alSetError(AL_INVALID_ENUM);
430 break;
433 else
434 alSetError(AL_INVALID_NAME);
436 ProcessContext(Context);
439 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
441 ALCcontext *Context;
443 Context = alcGetCurrentContext();
444 if(!Context)
446 alSetError(AL_INVALID_OPERATION);
447 return;
449 SuspendContext(Context);
451 if (alIsAuxiliaryEffectSlot(effectslot))
453 switch(param)
455 case AL_EFFECTSLOT_GAIN:
456 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
457 break;
459 default:
460 alSetError(AL_INVALID_ENUM);
461 break;
464 else
465 alSetError(AL_INVALID_NAME);
467 ProcessContext(Context);
471 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
473 if(!effect)
475 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
476 VerbDestroy(ALEffectSlot->ReverbState);
477 ALEffectSlot->ReverbState = NULL;
478 return;
480 if(effect->type == AL_EFFECT_REVERB)
482 if(!ALEffectSlot->ReverbState)
483 ALEffectSlot->ReverbState = VerbCreate(Context);
484 VerbUpdate(Context, ALEffectSlot, effect);
486 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
490 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
492 #ifdef _DEBUG
493 if(Context->AuxiliaryEffectSlotCount > 0)
494 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
495 #endif
497 while(Context->AuxiliaryEffectSlot)
499 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
500 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
502 // Release effectslot structure
503 VerbDestroy(temp->ReverbState);
504 ALTHUNK_REMOVEENTRY(temp->effectslot);
506 memset(temp, 0, sizeof(ALeffectslot));
507 free(temp);
509 Context->AuxiliaryEffectSlotCount = 0;