Don't needlessly expose a variable for the backends
[openal-soft/android/lowlatency.git] / OpenAL32 / alAuxEffectSlot.c
blobb659c5f5e9b3b703ef78198a8b62558fd0785be0
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);
37 DECL_VERIFIER(Effect, ALeffect, effect)
39 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
41 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
43 ALCcontext *Context;
44 ALsizei i=0, j;
46 Context = GetContextSuspended();
47 if(!Context) return;
49 if(n > 0)
51 ALCdevice *Device = Context->Device;
53 if(Context->EffectSlotMap.size+n <= (ALsizei)Device->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 ALenum err;
60 while(i < n)
62 ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
63 if(!slot || !(slot->EffectState=NoneCreate()))
65 free(slot);
66 // We must have run out or memory
67 alSetError(Context, AL_OUT_OF_MEMORY);
68 alDeleteAuxiliaryEffectSlots(i, effectslots);
69 break;
72 slot->effectslot = (ALuint)ALTHUNK_ADDENTRY(slot);
73 err = InsertUIntMapEntry(&Context->EffectSlotMap,
74 slot->effectslot, slot);
75 if(err != AL_NO_ERROR)
77 ALTHUNK_REMOVEENTRY(slot->effectslot);
78 ALEffect_Destroy(slot->EffectState);
79 free(slot);
81 alSetError(Context, err);
82 alDeleteAuxiliaryEffectSlots(i, effectslots);
83 break;
86 effectslots[i++] = slot->effectslot;
88 slot->Gain = 1.0;
89 slot->AuxSendAuto = AL_TRUE;
90 for(j = 0;j < BUFFERSIZE;j++)
91 slot->WetBuffer[j] = 0.0f;
92 slot->refcount = 0;
96 else
97 alSetError(Context, AL_INVALID_OPERATION);
100 ProcessContext(Context);
103 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
105 ALCcontext *Context;
106 ALeffectslot *EffectSlot;
107 ALsizei i;
109 Context = GetContextSuspended();
110 if(!Context) return;
112 if (n >= 0)
114 // Check that all effectslots are valid
115 for (i = 0; i < n; i++)
117 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
119 alSetError(Context, AL_INVALID_NAME);
120 break;
122 else
124 if(EffectSlot->refcount > 0)
126 alSetError(Context, 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((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) != NULL)
140 ALEffect_Destroy(EffectSlot->EffectState);
142 RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot);
143 ALTHUNK_REMOVEENTRY(EffectSlot->effectslot);
145 memset(EffectSlot, 0, sizeof(ALeffectslot));
146 free(EffectSlot);
151 else
152 alSetError(Context, AL_INVALID_VALUE);
154 ProcessContext(Context);
157 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
159 ALCcontext *Context;
160 ALboolean result;
162 Context = GetContextSuspended();
163 if(!Context) return AL_FALSE;
165 result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ?
166 AL_TRUE : AL_FALSE);
168 ProcessContext(Context);
170 return result;
173 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
175 ALCcontext *Context;
176 ALboolean updateSources = AL_FALSE;
177 ALeffectslot *EffectSlot;
179 Context = GetContextSuspended();
180 if(!Context) return;
182 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
184 switch(param)
186 case AL_EFFECTSLOT_EFFECT: {
187 ALeffect *effect = NULL;
189 if(iValue == 0 ||
190 (effect=VerifyEffect(Context->Device->EffectList, iValue)) != NULL)
192 InitializeEffect(Context, EffectSlot, effect);
193 updateSources = AL_TRUE;
195 else
196 alSetError(Context, AL_INVALID_VALUE);
197 } break;
199 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
200 if(iValue == AL_TRUE || iValue == AL_FALSE)
202 EffectSlot->AuxSendAuto = iValue;
203 updateSources = AL_TRUE;
205 else
206 alSetError(Context, AL_INVALID_VALUE);
207 break;
209 default:
210 alSetError(Context, AL_INVALID_ENUM);
211 break;
214 else
215 alSetError(Context, AL_INVALID_NAME);
217 // Force updating the sources that use this slot, since it affects the
218 // sending parameters
219 if(updateSources)
221 ALsizei pos;
222 for(pos = 0;pos < Context->SourceMap.size;pos++)
224 ALsource *source = Context->SourceMap.array[pos].value;
225 ALuint i;
226 for(i = 0;i < MAX_SENDS;i++)
228 if(!source->Send[i].Slot ||
229 source->Send[i].Slot->effectslot != effectslot)
230 continue;
231 source->NeedsUpdate = AL_TRUE;
232 break;
237 ProcessContext(Context);
240 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
242 ALCcontext *Context;
244 Context = GetContextSuspended();
245 if(!Context) return;
247 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
249 switch(param)
251 case AL_EFFECTSLOT_EFFECT:
252 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
253 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
254 break;
256 default:
257 alSetError(Context, AL_INVALID_ENUM);
258 break;
261 else
262 alSetError(Context, AL_INVALID_NAME);
264 ProcessContext(Context);
267 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
269 ALCcontext *Context;
270 ALeffectslot *EffectSlot;
272 Context = GetContextSuspended();
273 if(!Context) return;
275 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
277 switch(param)
279 case AL_EFFECTSLOT_GAIN:
280 if(flValue >= 0.0f && flValue <= 1.0f)
281 EffectSlot->Gain = flValue;
282 else
283 alSetError(Context, AL_INVALID_VALUE);
284 break;
286 default:
287 alSetError(Context, AL_INVALID_ENUM);
288 break;
291 else
292 alSetError(Context, AL_INVALID_NAME);
294 ProcessContext(Context);
297 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
299 ALCcontext *Context;
301 Context = GetContextSuspended();
302 if(!Context) return;
304 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
306 switch(param)
308 case AL_EFFECTSLOT_GAIN:
309 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
310 break;
312 default:
313 alSetError(Context, AL_INVALID_ENUM);
314 break;
317 else
318 alSetError(Context, AL_INVALID_NAME);
320 ProcessContext(Context);
323 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
325 ALCcontext *Context;
326 ALeffectslot *EffectSlot;
328 Context = GetContextSuspended();
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 ProcessContext(Context);
354 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
356 ALCcontext *Context;
358 Context = GetContextSuspended();
359 if(!Context) return;
361 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
363 switch(param)
365 case AL_EFFECTSLOT_EFFECT:
366 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
367 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
368 break;
370 default:
371 alSetError(Context, AL_INVALID_ENUM);
372 break;
375 else
376 alSetError(Context, AL_INVALID_NAME);
378 ProcessContext(Context);
381 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
383 ALCcontext *Context;
384 ALeffectslot *EffectSlot;
386 Context = GetContextSuspended();
387 if(!Context) return;
389 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
391 switch(param)
393 case AL_EFFECTSLOT_GAIN:
394 *pflValue = EffectSlot->Gain;
395 break;
397 default:
398 alSetError(Context, AL_INVALID_ENUM);
399 break;
402 else
403 alSetError(Context, AL_INVALID_NAME);
405 ProcessContext(Context);
408 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
410 ALCcontext *Context;
412 Context = GetContextSuspended();
413 if(!Context) return;
415 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
417 switch(param)
419 case AL_EFFECTSLOT_GAIN:
420 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
421 break;
423 default:
424 alSetError(Context, AL_INVALID_ENUM);
425 break;
428 else
429 alSetError(Context, AL_INVALID_NAME);
431 ProcessContext(Context);
435 static ALvoid NoneDestroy(ALeffectState *State)
436 { free(State); }
437 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
439 return AL_TRUE;
440 (void)State;
441 (void)Device;
443 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect)
445 (void)State;
446 (void)Context;
447 (void)Effect;
449 static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
451 (void)State;
452 (void)Slot;
453 (void)SamplesToDo;
454 (void)SamplesIn;
455 (void)SamplesOut;
457 ALeffectState *NoneCreate(void)
459 ALeffectState *state;
461 state = calloc(1, sizeof(*state));
462 if(!state)
463 return NULL;
465 state->Destroy = NoneDestroy;
466 state->DeviceUpdate = NoneDeviceUpdate;
467 state->Update = NoneUpdate;
468 state->Process = NoneProcess;
470 return state;
473 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
475 if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
477 ALeffectState *NewState = NULL;
478 if(!effect || effect->type == AL_EFFECT_NULL)
479 NewState = NoneCreate();
480 else if(effect->type == AL_EFFECT_EAXREVERB)
481 NewState = EAXVerbCreate();
482 else if(effect->type == AL_EFFECT_REVERB)
483 NewState = VerbCreate();
484 else if(effect->type == AL_EFFECT_ECHO)
485 NewState = EchoCreate();
486 else if(effect->type == AL_EFFECT_RING_MODULATOR)
487 NewState = ModulatorCreate();
488 /* No new state? An error occured.. */
489 if(NewState == NULL ||
490 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
492 if(NewState)
493 ALEffect_Destroy(NewState);
494 alSetError(Context, AL_OUT_OF_MEMORY);
495 return;
497 if(EffectSlot->EffectState)
498 ALEffect_Destroy(EffectSlot->EffectState);
499 EffectSlot->EffectState = NewState;
501 if(!effect)
502 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
503 else
504 memcpy(&EffectSlot->effect, effect, sizeof(*effect));
505 ALEffect_Update(EffectSlot->EffectState, Context, effect);
509 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
511 ALsizei pos;
512 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
514 ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
515 Context->EffectSlotMap.array[pos].value = NULL;
517 // Release effectslot structure
518 ALEffect_Destroy(temp->EffectState);
520 ALTHUNK_REMOVEENTRY(temp->effectslot);
521 memset(temp, 0, sizeof(ALeffectslot));
522 free(temp);