Implement a new reverb effect
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobdd524f0278e7ed4ed426de106371e4eb6dfa7040
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;
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 (*list)->refcount = 0;
79 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
80 (*list)->effectslot = effectslots[i];
82 Context->AuxiliaryEffectSlotCount++;
83 i++;
85 list = &(*list)->next;
89 else
90 alSetError(AL_INVALID_OPERATION);
93 ProcessContext(Context);
96 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
98 ALCcontext *Context;
99 ALeffectslot *ALAuxiliaryEffectSlot;
100 ALsizei i;
102 Context = alcGetCurrentContext();
103 if(!Context)
105 alSetError(AL_INVALID_OPERATION);
106 return;
108 SuspendContext(Context);
110 if (n >= 0)
112 // Check that all effectslots are valid
113 for (i = 0; i < n; i++)
115 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
117 alSetError(AL_INVALID_NAME);
118 break;
120 else
122 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
123 if(ALAuxiliaryEffectSlot->refcount > 0)
125 alSetError(AL_INVALID_NAME);
126 break;
131 if (i == n)
133 // All effectslots are valid
134 for (i = 0; i < n; i++)
136 // Recheck that the effectslot is valid, because there could be duplicated names
137 if (alIsAuxiliaryEffectSlot(effectslots[i]))
139 ALeffectslot **list;
141 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
143 // Remove Source from list of Sources
144 list = &Context->AuxiliaryEffectSlot;
145 while(*list && *list != ALAuxiliaryEffectSlot)
146 list = &(*list)->next;
148 if(*list)
149 *list = (*list)->next;
150 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
152 VerbDestroy(ALAuxiliaryEffectSlot->ReverbState);
154 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
155 free(ALAuxiliaryEffectSlot);
157 Context->AuxiliaryEffectSlotCount--;
162 else
163 alSetError(AL_INVALID_VALUE);
165 ProcessContext(Context);
168 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
170 ALCcontext *Context;
171 ALeffectslot **list;
173 Context = alcGetCurrentContext();
174 if(!Context)
176 alSetError(AL_INVALID_OPERATION);
177 return AL_FALSE;
179 SuspendContext(Context);
181 list = &Context->AuxiliaryEffectSlot;
182 while(*list && (*list)->effectslot != effectslot)
183 list = &(*list)->next;
185 ProcessContext(Context);
187 return (*list ? AL_TRUE : AL_FALSE);
190 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
192 ALCcontext *Context;
194 Context = alcGetCurrentContext();
195 if(!Context)
197 alSetError(AL_INVALID_OPERATION);
198 return;
200 SuspendContext(Context);
202 if (alIsAuxiliaryEffectSlot(effectslot))
204 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
206 switch(param)
208 case AL_EFFECTSLOT_EFFECT:
209 if(alIsEffect(iValue))
211 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
212 InitializeEffect(Context, ALEffectSlot, effect);
214 else
215 alSetError(AL_INVALID_VALUE);
216 break;
218 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
219 if(iValue == AL_TRUE || iValue == AL_FALSE)
220 ALEffectSlot->AuxSendAuto = iValue;
221 else
222 alSetError(AL_INVALID_VALUE);
223 break;
225 default:
226 alSetError(AL_INVALID_ENUM);
227 break;
230 else
231 alSetError(AL_INVALID_NAME);
233 ProcessContext(Context);
236 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
238 ALCcontext *Context;
240 Context = alcGetCurrentContext();
241 if(!Context)
243 alSetError(AL_INVALID_OPERATION);
244 return;
246 SuspendContext(Context);
248 if (alIsAuxiliaryEffectSlot(effectslot))
250 switch(param)
252 case AL_EFFECTSLOT_EFFECT:
253 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
254 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
255 break;
257 default:
258 alSetError(AL_INVALID_ENUM);
259 break;
262 else
263 alSetError(AL_INVALID_NAME);
265 ProcessContext(Context);
268 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
270 ALCcontext *Context;
272 Context = alcGetCurrentContext();
273 if(!Context)
275 alSetError(AL_INVALID_OPERATION);
276 return;
278 SuspendContext(Context);
280 if (alIsAuxiliaryEffectSlot(effectslot))
282 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
284 switch(param)
286 case AL_EFFECTSLOT_GAIN:
287 if(flValue >= 0.0f && flValue <= 1.0f)
288 ALEffectSlot->Gain = flValue;
289 else
290 alSetError(AL_INVALID_VALUE);
291 break;
293 default:
294 alSetError(AL_INVALID_ENUM);
295 break;
298 else
299 alSetError(AL_INVALID_NAME);
301 ProcessContext(Context);
304 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
306 ALCcontext *Context;
308 Context = alcGetCurrentContext();
309 if(!Context)
311 alSetError(AL_INVALID_OPERATION);
312 return;
314 SuspendContext(Context);
316 if (alIsAuxiliaryEffectSlot(effectslot))
318 switch(param)
320 case AL_EFFECTSLOT_GAIN:
321 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
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 alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
337 ALCcontext *Context;
339 Context = alcGetCurrentContext();
340 if(!Context)
342 alSetError(AL_INVALID_OPERATION);
343 return;
345 SuspendContext(Context);
347 if (alIsAuxiliaryEffectSlot(effectslot))
349 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
351 switch(param)
353 case AL_EFFECTSLOT_EFFECT:
354 *piValue = ALEffectSlot->effect.effect;
355 break;
357 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
358 *piValue = ALEffectSlot->AuxSendAuto;
359 break;
361 default:
362 alSetError(AL_INVALID_ENUM);
363 break;
366 else
367 alSetError(AL_INVALID_NAME);
369 ProcessContext(Context);
372 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
374 ALCcontext *Context;
376 Context = alcGetCurrentContext();
377 if(!Context)
379 alSetError(AL_INVALID_OPERATION);
380 return;
382 SuspendContext(Context);
384 if (alIsAuxiliaryEffectSlot(effectslot))
386 switch(param)
388 case AL_EFFECTSLOT_EFFECT:
389 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
390 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
391 break;
393 default:
394 alSetError(AL_INVALID_ENUM);
395 break;
398 else
399 alSetError(AL_INVALID_NAME);
401 ProcessContext(Context);
404 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
406 ALCcontext *Context;
408 Context = alcGetCurrentContext();
409 if(!Context)
411 alSetError(AL_INVALID_OPERATION);
412 return;
414 SuspendContext(Context);
416 if (alIsAuxiliaryEffectSlot(effectslot))
418 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
420 switch(param)
422 case AL_EFFECTSLOT_GAIN:
423 *pflValue = ALEffectSlot->Gain;
424 break;
426 default:
427 alSetError(AL_INVALID_ENUM);
428 break;
431 else
432 alSetError(AL_INVALID_NAME);
434 ProcessContext(Context);
437 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
439 ALCcontext *Context;
441 Context = alcGetCurrentContext();
442 if(!Context)
444 alSetError(AL_INVALID_OPERATION);
445 return;
447 SuspendContext(Context);
449 if (alIsAuxiliaryEffectSlot(effectslot))
451 switch(param)
453 case AL_EFFECTSLOT_GAIN:
454 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
455 break;
457 default:
458 alSetError(AL_INVALID_ENUM);
459 break;
462 else
463 alSetError(AL_INVALID_NAME);
465 ProcessContext(Context);
469 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
471 if(!effect)
473 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
474 VerbDestroy(ALEffectSlot->ReverbState);
475 ALEffectSlot->ReverbState = NULL;
476 return;
478 if(effect->type == AL_EFFECT_REVERB)
480 if(!ALEffectSlot->ReverbState)
481 ALEffectSlot->ReverbState = VerbCreate(Context);
482 VerbUpdate(Context, ALEffectSlot, effect);
484 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
488 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
490 #ifdef _DEBUG
491 if(Context->AuxiliaryEffectSlotCount > 0)
492 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
493 #endif
495 while(Context->AuxiliaryEffectSlot)
497 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
498 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
500 // Release effectslot structure
501 VerbDestroy(temp->ReverbState);
502 ALTHUNK_REMOVEENTRY(temp->effectslot);
504 memset(temp, 0, sizeof(ALeffectslot));
505 free(temp);
507 Context->AuxiliaryEffectSlotCount = 0;