Use powf when available
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobf6cb6e4bb623805e431942a4cf6805160460e15f
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 "alSource.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 = GetContextSuspended();
44 if(!Context) return;
46 if (n > 0)
48 ALCdevice *Device = Context->Device;
50 if(Context->AuxiliaryEffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
52 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
53 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
55 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
56 while(*list)
57 list = &(*list)->next;
59 i = 0;
60 while(i < n)
62 *list = calloc(1, sizeof(ALeffectslot));
63 if(!(*list) || !((*list)->EffectState=NoneCreate()))
65 // We must have run out or memory
66 free(*list); *list = NULL;
67 alDeleteAuxiliaryEffectSlots(i, effectslots);
68 alSetError(AL_OUT_OF_MEMORY);
69 break;
72 (*list)->Gain = 1.0;
73 (*list)->AuxSendAuto = AL_TRUE;
74 for(j = 0;j < BUFFERSIZE;j++)
75 (*list)->WetBuffer[j] = 0.0f;
76 (*list)->refcount = 0;
78 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
79 (*list)->effectslot = effectslots[i];
81 Context->AuxiliaryEffectSlotCount++;
82 i++;
84 list = &(*list)->next;
88 else
89 alSetError(AL_INVALID_OPERATION);
92 ProcessContext(Context);
95 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
97 ALCcontext *Context;
98 ALeffectslot *ALAuxiliaryEffectSlot;
99 ALsizei i;
101 Context = GetContextSuspended();
102 if(!Context) return;
104 if (n >= 0)
106 // Check that all effectslots are valid
107 for (i = 0; i < n; i++)
109 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
111 alSetError(AL_INVALID_NAME);
112 break;
114 else
116 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
117 if(ALAuxiliaryEffectSlot->refcount > 0)
119 alSetError(AL_INVALID_NAME);
120 break;
125 if (i == n)
127 // All effectslots are valid
128 for (i = 0; i < n; i++)
130 // Recheck that the effectslot is valid, because there could be duplicated names
131 if (alIsAuxiliaryEffectSlot(effectslots[i]))
133 ALeffectslot **list;
135 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
137 // Remove Source from list of Sources
138 list = &Context->AuxiliaryEffectSlot;
139 while(*list && *list != ALAuxiliaryEffectSlot)
140 list = &(*list)->next;
142 if(*list)
143 *list = (*list)->next;
144 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
146 if(ALAuxiliaryEffectSlot->EffectState)
147 ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
149 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
150 free(ALAuxiliaryEffectSlot);
152 Context->AuxiliaryEffectSlotCount--;
157 else
158 alSetError(AL_INVALID_VALUE);
160 ProcessContext(Context);
163 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
165 ALCcontext *Context;
166 ALeffectslot **list;
168 Context = GetContextSuspended();
169 if(!Context) return AL_FALSE;
171 list = &Context->AuxiliaryEffectSlot;
172 while(*list && (*list)->effectslot != effectslot)
173 list = &(*list)->next;
175 ProcessContext(Context);
177 return (*list ? AL_TRUE : AL_FALSE);
180 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
182 ALCcontext *Context;
183 ALboolean updateSources = AL_FALSE;
185 Context = GetContextSuspended();
186 if(!Context) return;
188 if (alIsAuxiliaryEffectSlot(effectslot))
190 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
192 switch(param)
194 case AL_EFFECTSLOT_EFFECT:
195 if(alIsEffect(iValue))
197 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
198 InitializeEffect(Context, ALEffectSlot, effect);
199 updateSources = AL_TRUE;
201 else
202 alSetError(AL_INVALID_VALUE);
203 break;
205 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
206 if(iValue == AL_TRUE || iValue == AL_FALSE)
208 ALEffectSlot->AuxSendAuto = iValue;
209 updateSources = AL_TRUE;
211 else
212 alSetError(AL_INVALID_VALUE);
213 break;
215 default:
216 alSetError(AL_INVALID_ENUM);
217 break;
220 else
221 alSetError(AL_INVALID_NAME);
223 // Force updating the sources that use this slot, since it affects the
224 // sending parameters
225 if(updateSources)
227 ALsource *source = Context->Source;
228 while(source)
230 ALuint i;
231 for(i = 0;i < MAX_SENDS;i++)
233 if(!source->Send[i].Slot ||
234 source->Send[i].Slot->effectslot != effectslot)
235 continue;
236 source->NeedsUpdate = AL_TRUE;
237 break;
239 source = source->next;
243 ProcessContext(Context);
246 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
248 ALCcontext *Context;
250 Context = GetContextSuspended();
251 if(!Context) return;
253 if (alIsAuxiliaryEffectSlot(effectslot))
255 switch(param)
257 case AL_EFFECTSLOT_EFFECT:
258 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
259 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
260 break;
262 default:
263 alSetError(AL_INVALID_ENUM);
264 break;
267 else
268 alSetError(AL_INVALID_NAME);
270 ProcessContext(Context);
273 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
275 ALCcontext *Context;
277 Context = GetContextSuspended();
278 if(!Context) return;
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 = GetContextSuspended();
309 if(!Context) return;
311 if (alIsAuxiliaryEffectSlot(effectslot))
313 switch(param)
315 case AL_EFFECTSLOT_GAIN:
316 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
317 break;
319 default:
320 alSetError(AL_INVALID_ENUM);
321 break;
324 else
325 alSetError(AL_INVALID_NAME);
327 ProcessContext(Context);
330 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
332 ALCcontext *Context;
334 Context = GetContextSuspended();
335 if(!Context) return;
337 if (alIsAuxiliaryEffectSlot(effectslot))
339 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
341 switch(param)
343 case AL_EFFECTSLOT_EFFECT:
344 *piValue = ALEffectSlot->effect.effect;
345 break;
347 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
348 *piValue = ALEffectSlot->AuxSendAuto;
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 alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
364 ALCcontext *Context;
366 Context = GetContextSuspended();
367 if(!Context) return;
369 if (alIsAuxiliaryEffectSlot(effectslot))
371 switch(param)
373 case AL_EFFECTSLOT_EFFECT:
374 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
375 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
376 break;
378 default:
379 alSetError(AL_INVALID_ENUM);
380 break;
383 else
384 alSetError(AL_INVALID_NAME);
386 ProcessContext(Context);
389 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
391 ALCcontext *Context;
393 Context = GetContextSuspended();
394 if(!Context) return;
396 if (alIsAuxiliaryEffectSlot(effectslot))
398 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
400 switch(param)
402 case AL_EFFECTSLOT_GAIN:
403 *pflValue = ALEffectSlot->Gain;
404 break;
406 default:
407 alSetError(AL_INVALID_ENUM);
408 break;
411 else
412 alSetError(AL_INVALID_NAME);
414 ProcessContext(Context);
417 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
419 ALCcontext *Context;
421 Context = GetContextSuspended();
422 if(!Context) return;
424 if (alIsAuxiliaryEffectSlot(effectslot))
426 switch(param)
428 case AL_EFFECTSLOT_GAIN:
429 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
430 break;
432 default:
433 alSetError(AL_INVALID_ENUM);
434 break;
437 else
438 alSetError(AL_INVALID_NAME);
440 ProcessContext(Context);
444 static ALvoid NoneDestroy(ALeffectState *State)
445 { free(State); }
446 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
448 return AL_TRUE;
449 (void)State;
450 (void)Device;
452 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect)
454 (void)State;
455 (void)Context;
456 (void)Effect;
458 static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
460 (void)State;
461 (void)Slot;
462 (void)SamplesToDo;
463 (void)SamplesIn;
464 (void)SamplesOut;
466 ALeffectState *NoneCreate(void)
468 ALeffectState *state;
470 state = calloc(1, sizeof(*state));
471 if(!state)
473 alSetError(AL_OUT_OF_MEMORY);
474 return NULL;
477 state->Destroy = NoneDestroy;
478 state->DeviceUpdate = NoneDeviceUpdate;
479 state->Update = NoneUpdate;
480 state->Process = NoneProcess;
482 return state;
485 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
487 if(ALEffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
489 ALeffectState *NewState = NULL;
490 if(!effect || effect->type == AL_EFFECT_NULL)
491 NewState = NoneCreate();
492 else if(effect->type == AL_EFFECT_EAXREVERB)
493 NewState = EAXVerbCreate();
494 else if(effect->type == AL_EFFECT_REVERB)
495 NewState = VerbCreate();
496 else if(effect->type == AL_EFFECT_ECHO)
497 NewState = EchoCreate();
498 /* No new state? An error occured.. */
499 if(NewState == NULL ||
500 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
502 if(NewState)
503 ALEffect_Destroy(NewState);
504 return;
506 if(ALEffectSlot->EffectState)
507 ALEffect_Destroy(ALEffectSlot->EffectState);
508 ALEffectSlot->EffectState = NewState;
510 if(!effect)
511 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
512 else
513 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
514 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
518 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
520 while(Context->AuxiliaryEffectSlot)
522 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
523 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
525 // Release effectslot structure
526 if(temp->EffectState)
527 ALEffect_Destroy(temp->EffectState);
528 ALTHUNK_REMOVEENTRY(temp->effectslot);
530 memset(temp, 0, sizeof(ALeffectslot));
531 free(temp);
533 Context->AuxiliaryEffectSlotCount = 0;