Get rid of the ugly ok() macro
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob810b380e37a9453bef2fd5c32285acfd34af4835
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 if(Context->AuxiliaryEffectSlotCount+n <= Context->AuxiliaryEffectSlotMax)
55 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
56 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
58 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
59 while(*list)
60 list = &(*list)->next;
62 i = 0;
63 while(i < n)
65 *list = calloc(1, sizeof(ALeffectslot));
66 if(!(*list))
68 // We must have run out or memory
69 alDeleteAuxiliaryEffectSlots(i, effectslots);
70 alSetError(AL_OUT_OF_MEMORY);
71 break;
74 (*list)->Gain = 1.0;
75 (*list)->AuxSendAuto = AL_TRUE;
76 for(j = 0;j < BUFFERSIZE;j++)
77 (*list)->WetBuffer[j] = 0.0f;
78 (*list)->refcount = 0;
80 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
81 (*list)->effectslot = effectslots[i];
83 Context->AuxiliaryEffectSlotCount++;
84 i++;
86 list = &(*list)->next;
90 else
91 alSetError(AL_INVALID_OPERATION);
94 ProcessContext(Context);
97 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
99 ALCcontext *Context;
100 ALeffectslot *ALAuxiliaryEffectSlot;
101 ALsizei i;
103 Context = alcGetCurrentContext();
104 if(!Context)
106 alSetError(AL_INVALID_OPERATION);
107 return;
109 SuspendContext(Context);
111 if (n >= 0)
113 // Check that all effectslots are valid
114 for (i = 0; i < n; i++)
116 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
118 alSetError(AL_INVALID_NAME);
119 break;
121 else
123 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
124 if(ALAuxiliaryEffectSlot->refcount > 0)
126 alSetError(AL_INVALID_NAME);
127 break;
132 if (i == n)
134 // All effectslots are valid
135 for (i = 0; i < n; i++)
137 // Recheck that the effectslot is valid, because there could be duplicated names
138 if (alIsAuxiliaryEffectSlot(effectslots[i]))
140 ALeffectslot **list;
142 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
144 // Remove Source from list of Sources
145 list = &Context->AuxiliaryEffectSlot;
146 while(*list && *list != ALAuxiliaryEffectSlot)
147 list = &(*list)->next;
149 if(*list)
150 *list = (*list)->next;
151 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
153 VerbDestroy(ALAuxiliaryEffectSlot->ReverbState);
154 EchoDestroy(ALAuxiliaryEffectSlot->EchoState);
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 EchoDestroy(ALEffectSlot->EchoState);
479 ALEffectSlot->EchoState = NULL;
480 return;
482 if(effect->type == AL_EFFECT_REVERB)
484 if(ALEffectSlot->EchoState)
486 EchoDestroy(ALEffectSlot->EchoState);
487 ALEffectSlot->EchoState = NULL;
489 if(!ALEffectSlot->ReverbState)
490 ALEffectSlot->ReverbState = VerbCreate(Context);
491 VerbUpdate(Context, ALEffectSlot, effect);
493 else if(effect->type == AL_EFFECT_ECHO)
495 if(ALEffectSlot->ReverbState)
497 VerbDestroy(ALEffectSlot->ReverbState);
498 ALEffectSlot->ReverbState = NULL;
500 if(!ALEffectSlot->EchoState)
501 ALEffectSlot->EchoState = EchoCreate(Context);
502 EchoUpdate(Context, ALEffectSlot, effect);
504 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
508 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
510 #ifdef _DEBUG
511 if(Context->AuxiliaryEffectSlotCount > 0)
512 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
513 #endif
515 while(Context->AuxiliaryEffectSlot)
517 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
518 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
520 // Release effectslot structure
521 VerbDestroy(temp->ReverbState);
522 EchoDestroy(temp->EchoState);
523 ALTHUNK_REMOVEENTRY(temp->effectslot);
525 memset(temp, 0, sizeof(ALeffectslot));
526 free(temp);
528 Context->AuxiliaryEffectSlotCount = 0;