view OpenAL32/alAuxEffectSlot.c @ 19:22ac5a0367cd

finally, a first pass at ear.org
author Robert McIntyre <rlm@mit.edu>
date Thu, 03 Nov 2011 14:54:45 -0700
parents f9476ff7637e
children
line wrap: on
line source
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.
8 *
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.
13 *
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
19 */
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 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
38 #define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k)))
40 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
41 {
42 ALCcontext *Context;
43 ALCdevice *Device;
45 Context = GetLockedContext();
46 if(!Context) return;
48 Device = Context->Device;
49 if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
50 alSetError(Context, AL_INVALID_VALUE);
51 else if((ALuint)n > Device->AuxiliaryEffectSlotMax - Context->EffectSlotMap.size)
52 alSetError(Context, AL_INVALID_VALUE);
53 else
54 {
55 ALenum err;
56 ALsizei i, j;
58 i = 0;
59 while(i < n)
60 {
61 ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
62 if(!slot || !(slot->EffectState=NoneCreate()))
63 {
64 free(slot);
65 // We must have run out or memory
66 alSetError(Context, AL_OUT_OF_MEMORY);
67 alDeleteAuxiliaryEffectSlots(i, effectslots);
68 break;
69 }
71 err = NewThunkEntry(&slot->effectslot);
72 if(err == AL_NO_ERROR)
73 err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->effectslot, slot);
74 if(err != AL_NO_ERROR)
75 {
76 FreeThunkEntry(slot->effectslot);
77 ALEffect_Destroy(slot->EffectState);
78 free(slot);
80 alSetError(Context, err);
81 alDeleteAuxiliaryEffectSlots(i, effectslots);
82 break;
83 }
85 effectslots[i++] = slot->effectslot;
87 slot->Gain = 1.0;
88 slot->AuxSendAuto = AL_TRUE;
89 slot->NeedsUpdate = AL_FALSE;
90 for(j = 0;j < BUFFERSIZE;j++)
91 slot->WetBuffer[j] = 0.0f;
92 for(j = 0;j < 1;j++)
93 {
94 slot->ClickRemoval[j] = 0.0f;
95 slot->PendingClicks[j] = 0.0f;
96 }
97 slot->refcount = 0;
98 }
99 }
101 UnlockContext(Context);
102 }
104 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
105 {
106 ALCcontext *Context;
107 ALeffectslot *EffectSlot;
108 ALboolean SlotsValid = AL_FALSE;
109 ALsizei i;
111 Context = GetLockedContext();
112 if(!Context) return;
114 if(n < 0)
115 alSetError(Context, AL_INVALID_VALUE);
116 else
117 {
118 SlotsValid = AL_TRUE;
119 // Check that all effectslots are valid
120 for(i = 0;i < n;i++)
121 {
122 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
123 {
124 alSetError(Context, AL_INVALID_NAME);
125 SlotsValid = AL_FALSE;
126 break;
127 }
128 else if(EffectSlot->refcount > 0)
129 {
130 alSetError(Context, AL_INVALID_NAME);
131 SlotsValid = AL_FALSE;
132 break;
133 }
134 }
135 }
137 if(SlotsValid)
138 {
139 // All effectslots are valid
140 for(i = 0;i < n;i++)
141 {
142 // Recheck that the effectslot is valid, because there could be duplicated names
143 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
144 continue;
146 ALEffect_Destroy(EffectSlot->EffectState);
148 RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot);
149 FreeThunkEntry(EffectSlot->effectslot);
151 memset(EffectSlot, 0, sizeof(ALeffectslot));
152 free(EffectSlot);
153 }
154 }
156 UnlockContext(Context);
157 }
159 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
160 {
161 ALCcontext *Context;
162 ALboolean result;
164 Context = GetLockedContext();
165 if(!Context) return AL_FALSE;
167 result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ?
168 AL_TRUE : AL_FALSE);
170 UnlockContext(Context);
172 return result;
173 }
175 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
176 {
177 ALCdevice *Device;
178 ALCcontext *Context;
179 ALeffectslot *EffectSlot;
181 Context = GetLockedContext();
182 if(!Context) return;
184 Device = Context->Device;
185 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
186 {
187 switch(param)
188 {
189 case AL_EFFECTSLOT_EFFECT: {
190 ALeffect *effect = NULL;
192 if(iValue == 0 ||
193 (effect=LookupEffect(Device->EffectMap, iValue)) != NULL)
194 {
195 InitializeEffect(Context, EffectSlot, effect);
196 Context->UpdateSources = AL_TRUE;
197 }
198 else
199 alSetError(Context, AL_INVALID_VALUE);
200 } break;
202 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
203 if(iValue == AL_TRUE || iValue == AL_FALSE)
204 {
205 EffectSlot->AuxSendAuto = iValue;
206 Context->UpdateSources = AL_TRUE;
207 }
208 else
209 alSetError(Context, AL_INVALID_VALUE);
210 break;
212 default:
213 alSetError(Context, AL_INVALID_ENUM);
214 break;
215 }
216 }
217 else
218 alSetError(Context, AL_INVALID_NAME);
220 UnlockContext(Context);
221 }
223 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
224 {
225 ALCcontext *Context;
227 switch(param)
228 {
229 case AL_EFFECTSLOT_EFFECT:
230 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
231 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
232 return;
233 }
235 Context = GetLockedContext();
236 if(!Context) return;
238 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
239 {
240 switch(param)
241 {
242 default:
243 alSetError(Context, AL_INVALID_ENUM);
244 break;
245 }
246 }
247 else
248 alSetError(Context, AL_INVALID_NAME);
250 UnlockContext(Context);
251 }
253 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
254 {
255 ALCcontext *Context;
256 ALeffectslot *EffectSlot;
258 Context = GetLockedContext();
259 if(!Context) return;
261 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
262 {
263 switch(param)
264 {
265 case AL_EFFECTSLOT_GAIN:
266 if(flValue >= 0.0f && flValue <= 1.0f)
267 {
268 EffectSlot->Gain = flValue;
269 EffectSlot->NeedsUpdate = AL_TRUE;
270 }
271 else
272 alSetError(Context, AL_INVALID_VALUE);
273 break;
275 default:
276 alSetError(Context, AL_INVALID_ENUM);
277 break;
278 }
279 }
280 else
281 alSetError(Context, AL_INVALID_NAME);
283 UnlockContext(Context);
284 }
286 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
287 {
288 ALCcontext *Context;
290 switch(param)
291 {
292 case AL_EFFECTSLOT_GAIN:
293 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
294 return;
295 }
297 Context = GetLockedContext();
298 if(!Context) return;
300 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
301 {
302 switch(param)
303 {
304 default:
305 alSetError(Context, AL_INVALID_ENUM);
306 break;
307 }
308 }
309 else
310 alSetError(Context, AL_INVALID_NAME);
312 UnlockContext(Context);
313 }
315 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
316 {
317 ALCcontext *Context;
318 ALeffectslot *EffectSlot;
320 Context = GetLockedContext();
321 if(!Context) return;
323 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
324 {
325 switch(param)
326 {
327 case AL_EFFECTSLOT_EFFECT:
328 *piValue = EffectSlot->effect.effect;
329 break;
331 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
332 *piValue = EffectSlot->AuxSendAuto;
333 break;
335 default:
336 alSetError(Context, AL_INVALID_ENUM);
337 break;
338 }
339 }
340 else
341 alSetError(Context, AL_INVALID_NAME);
343 UnlockContext(Context);
344 }
346 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
347 {
348 ALCcontext *Context;
350 switch(param)
351 {
352 case AL_EFFECTSLOT_EFFECT:
353 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
354 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
355 return;
356 }
358 Context = GetLockedContext();
359 if(!Context) return;
361 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
362 {
363 switch(param)
364 {
365 default:
366 alSetError(Context, AL_INVALID_ENUM);
367 break;
368 }
369 }
370 else
371 alSetError(Context, AL_INVALID_NAME);
373 UnlockContext(Context);
374 }
376 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
377 {
378 ALCcontext *Context;
379 ALeffectslot *EffectSlot;
381 Context = GetLockedContext();
382 if(!Context) return;
384 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
385 {
386 switch(param)
387 {
388 case AL_EFFECTSLOT_GAIN:
389 *pflValue = EffectSlot->Gain;
390 break;
392 default:
393 alSetError(Context, AL_INVALID_ENUM);
394 break;
395 }
396 }
397 else
398 alSetError(Context, AL_INVALID_NAME);
400 UnlockContext(Context);
401 }
403 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
404 {
405 ALCcontext *Context;
407 switch(param)
408 {
409 case AL_EFFECTSLOT_GAIN:
410 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
411 return;
412 }
414 Context = GetLockedContext();
415 if(!Context) return;
417 if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
418 {
419 switch(param)
420 {
421 default:
422 alSetError(Context, AL_INVALID_ENUM);
423 break;
424 }
425 }
426 else
427 alSetError(Context, AL_INVALID_NAME);
429 UnlockContext(Context);
430 }
433 static ALvoid NoneDestroy(ALeffectState *State)
434 { free(State); }
435 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
436 {
437 return AL_TRUE;
438 (void)State;
439 (void)Device;
440 }
441 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffectslot *Slot)
442 {
443 (void)State;
444 (void)Context;
445 (void)Slot;
446 }
447 static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
448 {
449 (void)State;
450 (void)Slot;
451 (void)SamplesToDo;
452 (void)SamplesIn;
453 (void)SamplesOut;
454 }
455 ALeffectState *NoneCreate(void)
456 {
457 ALeffectState *state;
459 state = calloc(1, sizeof(*state));
460 if(!state)
461 return NULL;
463 state->Destroy = NoneDestroy;
464 state->DeviceUpdate = NoneDeviceUpdate;
465 state->Update = NoneUpdate;
466 state->Process = NoneProcess;
468 return state;
469 }
471 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
472 {
473 if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
474 {
475 ALeffectState *NewState = NULL;
476 if(!effect || effect->type == AL_EFFECT_NULL)
477 NewState = NoneCreate();
478 else if(effect->type == AL_EFFECT_EAXREVERB)
479 NewState = EAXVerbCreate();
480 else if(effect->type == AL_EFFECT_REVERB)
481 NewState = VerbCreate();
482 else if(effect->type == AL_EFFECT_ECHO)
483 NewState = EchoCreate();
484 else if(effect->type == AL_EFFECT_RING_MODULATOR)
485 NewState = ModulatorCreate();
486 else if(effect->type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
487 NewState = DedicatedLFECreate();
488 else if(effect->type == AL_EFFECT_DEDICATED_DIALOGUE)
489 NewState = DedicatedDLGCreate();
490 /* No new state? An error occured.. */
491 if(NewState == NULL ||
492 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
493 {
494 if(NewState)
495 ALEffect_Destroy(NewState);
496 alSetError(Context, AL_OUT_OF_MEMORY);
497 return;
498 }
499 if(EffectSlot->EffectState)
500 ALEffect_Destroy(EffectSlot->EffectState);
501 EffectSlot->EffectState = NewState;
503 if(!effect)
504 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
505 else
506 memcpy(&EffectSlot->effect, effect, sizeof(*effect));
507 /* FIXME: This should be done asychronously, but since the EfefctState
508 * object was changed, it needs an update before its Process method can
509 * be called (coming changes may not guarantee an update when the
510 * NeedsUpdate flag is set). */
511 EffectSlot->NeedsUpdate = AL_FALSE;
512 ALEffect_Update(EffectSlot->EffectState, Context, EffectSlot);
513 }
514 else
515 {
516 if(!effect)
517 memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
518 else
519 memcpy(&EffectSlot->effect, effect, sizeof(*effect));
520 EffectSlot->NeedsUpdate = AL_TRUE;
521 }
522 }
525 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
526 {
527 ALsizei pos;
528 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
529 {
530 ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
531 Context->EffectSlotMap.array[pos].value = NULL;
533 // Release effectslot structure
534 ALEffect_Destroy(temp->EffectState);
536 FreeThunkEntry(temp->effectslot);
537 memset(temp, 0, sizeof(ALeffectslot));
538 free(temp);
539 }
540 }