Rename the ALEffect_ macros to ALeffectState_ to reflect what they work on
[openal-soft/android.git] / OpenAL32 / alAuxEffectSlot.c
blobdf042815c8fb3c96dfdc31495b9457677f0f2e8c
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 *EffectSlot, ALeffect *effect);
36 static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count);
37 static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *val);
39 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
40 #define RemoveEffectSlot(m, k) ((ALeffectslot*)PopUIntMapValue(&(m), (k)))
41 #define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k)))
43 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
45 ALCcontext *Context;
46 ALCdevice *Device;
48 Context = GetContextRef();
49 if(!Context) return;
51 Device = Context->Device;
52 if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
53 alSetError(Context, AL_INVALID_VALUE);
54 else
56 ALenum err;
57 ALsizei i, j;
59 err = ResizeEffectSlotArray(Context, n);
60 if(err != AL_NO_ERROR)
62 alSetError(Context, err);
63 n = 0;
66 for(i = 0;i < n;i++)
68 ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
69 if(!slot || !(slot->EffectState=NoneCreate()))
71 free(slot);
72 // We must have run out or memory
73 alSetError(Context, AL_OUT_OF_MEMORY);
74 alDeleteAuxiliaryEffectSlots(i, effectslots);
75 break;
78 slot->Gain = 1.0;
79 slot->AuxSendAuto = AL_TRUE;
80 slot->NeedsUpdate = AL_FALSE;
81 for(j = 0;j < BUFFERSIZE;j++)
82 slot->WetBuffer[j] = 0.0f;
83 for(j = 0;j < 1;j++)
85 slot->ClickRemoval[j] = 0.0f;
86 slot->PendingClicks[j] = 0.0f;
88 slot->ref = 0;
90 LockContext(Context);
91 err = ResizeEffectSlotArray(Context, 1);
92 if(err == AL_NO_ERROR)
93 Context->ActiveEffectSlots[Context->ActiveEffectSlotCount++] = slot;
94 UnlockContext(Context);
95 if(err == AL_NO_ERROR)
96 err = NewThunkEntry(&slot->effectslot);
97 if(err == AL_NO_ERROR)
98 err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->effectslot, slot);
99 if(err != AL_NO_ERROR)
101 RemoveEffectSlotArray(Context, slot);
102 FreeThunkEntry(slot->effectslot);
103 ALeffectState_Destroy(slot->EffectState);
104 free(slot);
106 alSetError(Context, err);
107 alDeleteAuxiliaryEffectSlots(i, effectslots);
108 break;
111 effectslots[i] = slot->effectslot;
115 ALCcontext_DecRef(Context);
118 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
120 ALCcontext *Context;
121 ALeffectslot *EffectSlot;
122 ALsizei i;
124 Context = GetContextRef();
125 if(!Context) return;
127 if(n < 0)
128 alSetError(Context, AL_INVALID_VALUE);
129 else
131 // Check that all effectslots are valid
132 for(i = 0;i < n;i++)
134 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
136 alSetError(Context, AL_INVALID_NAME);
137 n = 0;
138 break;
140 else if(EffectSlot->ref != 0)
142 alSetError(Context, AL_INVALID_OPERATION);
143 n = 0;
144 break;
148 // All effectslots are valid
149 for(i = 0;i < n;i++)
151 // Recheck that the effectslot is valid, because there could be duplicated names
152 if((EffectSlot=RemoveEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
153 continue;
154 FreeThunkEntry(EffectSlot->effectslot);
156 RemoveEffectSlotArray(Context, EffectSlot);
157 ALeffectState_Destroy(EffectSlot->EffectState);
159 memset(EffectSlot, 0, sizeof(ALeffectslot));
160 free(EffectSlot);
164 ALCcontext_DecRef(Context);
167 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
169 ALCcontext *Context;
170 ALboolean result;
172 Context = GetContextRef();
173 if(!Context) return AL_FALSE;
175 result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ?
176 AL_TRUE : AL_FALSE);
178 ALCcontext_DecRef(Context);
180 return result;
183 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
185 ALCdevice *Device;
186 ALCcontext *Context;
187 ALeffectslot *EffectSlot;
189 Context = GetContextRef();
190 if(!Context) return;
192 Device = Context->Device;
193 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
195 switch(param)
197 case AL_EFFECTSLOT_EFFECT: {
198 ALeffect *effect = NULL;
200 if(iValue == 0 ||
201 (effect=LookupEffect(Device->EffectMap, iValue)) != NULL)
203 InitializeEffect(Context, EffectSlot, effect);
204 Context->UpdateSources = AL_TRUE;
206 else
207 alSetError(Context, AL_INVALID_VALUE);
208 } break;
210 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
211 if(iValue == AL_TRUE || iValue == AL_FALSE)
213 EffectSlot->AuxSendAuto = iValue;
214 Context->UpdateSources = AL_TRUE;
216 else
217 alSetError(Context, AL_INVALID_VALUE);
218 break;
220 default:
221 alSetError(Context, AL_INVALID_ENUM);
222 break;
225 else
226 alSetError(Context, AL_INVALID_NAME);
228 ALCcontext_DecRef(Context);
231 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
233 ALCcontext *Context;
235 switch(param)
237 case AL_EFFECTSLOT_EFFECT:
238 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
239 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
240 return;
243 Context = GetContextRef();
244 if(!Context) return;
246 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
248 switch(param)
250 default:
251 alSetError(Context, AL_INVALID_ENUM);
252 break;
255 else
256 alSetError(Context, AL_INVALID_NAME);
258 ALCcontext_DecRef(Context);
261 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
263 ALCcontext *Context;
264 ALeffectslot *EffectSlot;
266 Context = GetContextRef();
267 if(!Context) return;
269 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
271 switch(param)
273 case AL_EFFECTSLOT_GAIN:
274 if(flValue >= 0.0f && flValue <= 1.0f)
276 EffectSlot->Gain = flValue;
277 EffectSlot->NeedsUpdate = AL_TRUE;
279 else
280 alSetError(Context, AL_INVALID_VALUE);
281 break;
283 default:
284 alSetError(Context, AL_INVALID_ENUM);
285 break;
288 else
289 alSetError(Context, AL_INVALID_NAME);
291 ALCcontext_DecRef(Context);
294 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
296 ALCcontext *Context;
298 switch(param)
300 case AL_EFFECTSLOT_GAIN:
301 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
302 return;
305 Context = GetContextRef();
306 if(!Context) return;
308 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
310 switch(param)
312 default:
313 alSetError(Context, AL_INVALID_ENUM);
314 break;
317 else
318 alSetError(Context, AL_INVALID_NAME);
320 ALCcontext_DecRef(Context);
323 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
325 ALCcontext *Context;
326 ALeffectslot *EffectSlot;
328 Context = GetContextRef();
329 if(!Context) return;
331 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
333 switch(param)
335 case AL_EFFECTSLOT_EFFECT:
336 *piValue = EffectSlot->effect.effect;
337 break;
339 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
340 *piValue = EffectSlot->AuxSendAuto;
341 break;
343 default:
344 alSetError(Context, AL_INVALID_ENUM);
345 break;
348 else
349 alSetError(Context, AL_INVALID_NAME);
351 ALCcontext_DecRef(Context);
354 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
356 ALCcontext *Context;
358 switch(param)
360 case AL_EFFECTSLOT_EFFECT:
361 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
362 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
363 return;
366 Context = GetContextRef();
367 if(!Context) return;
369 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
371 switch(param)
373 default:
374 alSetError(Context, AL_INVALID_ENUM);
375 break;
378 else
379 alSetError(Context, AL_INVALID_NAME);
381 ALCcontext_DecRef(Context);
384 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
386 ALCcontext *Context;
387 ALeffectslot *EffectSlot;
389 Context = GetContextRef();
390 if(!Context) return;
392 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
394 switch(param)
396 case AL_EFFECTSLOT_GAIN:
397 *pflValue = EffectSlot->Gain;
398 break;
400 default:
401 alSetError(Context, AL_INVALID_ENUM);
402 break;
405 else
406 alSetError(Context, AL_INVALID_NAME);
408 ALCcontext_DecRef(Context);
411 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
413 ALCcontext *Context;
415 switch(param)
417 case AL_EFFECTSLOT_GAIN:
418 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
419 return;
422 Context = GetContextRef();
423 if(!Context) return;
425 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
427 switch(param)
429 default:
430 alSetError(Context, AL_INVALID_ENUM);
431 break;
434 else
435 alSetError(Context, AL_INVALID_NAME);
437 ALCcontext_DecRef(Context);
441 static ALvoid NoneDestroy(ALeffectState *State)
442 { free(State); }
443 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
445 return AL_TRUE;
446 (void)State;
447 (void)Device;
449 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffectslot *Slot)
451 (void)State;
452 (void)Context;
453 (void)Slot;
455 static ALvoid NoneProcess(ALeffectState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
457 (void)State;
458 (void)SamplesToDo;
459 (void)SamplesIn;
460 (void)SamplesOut;
462 ALeffectState *NoneCreate(void)
464 ALeffectState *state;
466 state = calloc(1, sizeof(*state));
467 if(!state)
468 return NULL;
470 state->Destroy = NoneDestroy;
471 state->DeviceUpdate = NoneDeviceUpdate;
472 state->Update = NoneUpdate;
473 state->Process = NoneProcess;
475 return state;
479 static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *slot)
481 ALeffectslot **slotlist, **slotlistend;
483 LockContext(Context);
484 slotlist = Context->ActiveEffectSlots;
485 slotlistend = slotlist + Context->ActiveEffectSlotCount;
486 while(slotlist != slotlistend)
488 if(*slotlist == slot)
490 *slotlist = *(--slotlistend);
491 Context->ActiveEffectSlotCount--;
492 break;
494 slotlist++;
496 UnlockContext(Context);
499 static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count)
501 ALsizei newcount;
502 void *temp;
504 if(count <= Context->MaxActiveEffectSlots-Context->ActiveEffectSlotCount)
505 return AL_NO_ERROR;
507 newcount = Context->MaxActiveEffectSlots ?
508 (Context->MaxActiveEffectSlots<<1) : 1;
509 if(newcount <= Context->MaxActiveEffectSlots ||
510 !(temp=realloc(Context->ActiveEffectSlots, newcount *
511 sizeof(*Context->ActiveEffectSlots))))
512 return AL_OUT_OF_MEMORY;
514 Context->ActiveEffectSlots = temp;
515 Context->MaxActiveEffectSlots = newcount;
516 return AL_NO_ERROR;
519 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
521 ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
522 ALeffectState *State = NULL;
523 ALenum err = AL_NO_ERROR;
525 LockContext(Context);
526 if(newtype == AL_EFFECT_NULL && EffectSlot->effect.type != AL_EFFECT_NULL)
528 State = NoneCreate();
529 if(!State) err = AL_OUT_OF_MEMORY;
531 else if(newtype == AL_EFFECT_EAXREVERB || newtype == AL_EFFECT_REVERB)
533 if(EffectSlot->effect.type != AL_EFFECT_EAXREVERB && EffectSlot->effect.type != AL_EFFECT_REVERB)
535 State = ReverbCreate();
536 if(!State) err = AL_OUT_OF_MEMORY;
539 else if(newtype == AL_EFFECT_ECHO && EffectSlot->effect.type != AL_EFFECT_ECHO)
541 State = EchoCreate();
542 if(!State) err = AL_OUT_OF_MEMORY;
544 else if(newtype == AL_EFFECT_RING_MODULATOR && EffectSlot->effect.type != AL_EFFECT_RING_MODULATOR)
546 State = ModulatorCreate();
547 if(!State) err = AL_OUT_OF_MEMORY;
549 else if(newtype == AL_EFFECT_DEDICATED_DIALOGUE || newtype == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
551 if(EffectSlot->effect.type != AL_EFFECT_DEDICATED_DIALOGUE && EffectSlot->effect.type != AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
553 State = DedicatedCreate();
554 if(!State) err = AL_OUT_OF_MEMORY;
558 if(err != AL_NO_ERROR)
560 UnlockContext(Context);
561 alSetError(Context, err);
562 return;
565 if(State)
567 if(ALeffectState_DeviceUpdate(State, Context->Device) == AL_FALSE)
569 UnlockContext(Context);
570 ALeffectState_Destroy(State);
571 alSetError(Context, AL_OUT_OF_MEMORY);
572 return;
574 State = ExchangePtr((void**)&EffectSlot->EffectState, State);
576 if(!effect)
577 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
578 else
579 memcpy(&EffectSlot->effect, effect, sizeof(*effect));
580 /* FIXME: This should be done asynchronously, but since the EffectState
581 * object was changed, it needs an update before its Process method can
582 * be called. */
583 EffectSlot->NeedsUpdate = AL_FALSE;
584 ALeffectState_Update(EffectSlot->EffectState, Context, EffectSlot);
585 UnlockContext(Context);
587 ALeffectState_Destroy(State);
588 State = NULL;
590 else
592 if(!effect)
593 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
594 else
595 memcpy(&EffectSlot->effect, effect, sizeof(*effect));
596 UnlockContext(Context);
597 EffectSlot->NeedsUpdate = AL_TRUE;
602 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
604 ALsizei pos;
605 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
607 ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
608 Context->EffectSlotMap.array[pos].value = NULL;
610 // Release effectslot structure
611 ALeffectState_Destroy(temp->EffectState);
613 FreeThunkEntry(temp->effectslot);
614 memset(temp, 0, sizeof(ALeffectslot));
615 free(temp);