Mercurial > audio-send
comparison OpenAL32/alAuxEffectSlot.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
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 */ | |
20 | |
21 #include "config.h" | |
22 | |
23 #include <stdlib.h> | |
24 #include <math.h> | |
25 | |
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" | |
33 | |
34 | |
35 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect); | |
36 | |
37 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k))) | |
38 #define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k))) | |
39 | |
40 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) | |
41 { | |
42 ALCcontext *Context; | |
43 ALCdevice *Device; | |
44 | |
45 Context = GetLockedContext(); | |
46 if(!Context) return; | |
47 | |
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; | |
57 | |
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 } | |
70 | |
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); | |
79 | |
80 alSetError(Context, err); | |
81 alDeleteAuxiliaryEffectSlots(i, effectslots); | |
82 break; | |
83 } | |
84 | |
85 effectslots[i++] = slot->effectslot; | |
86 | |
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 } | |
100 | |
101 UnlockContext(Context); | |
102 } | |
103 | |
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; | |
110 | |
111 Context = GetLockedContext(); | |
112 if(!Context) return; | |
113 | |
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 } | |
136 | |
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; | |
145 | |
146 ALEffect_Destroy(EffectSlot->EffectState); | |
147 | |
148 RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot); | |
149 FreeThunkEntry(EffectSlot->effectslot); | |
150 | |
151 memset(EffectSlot, 0, sizeof(ALeffectslot)); | |
152 free(EffectSlot); | |
153 } | |
154 } | |
155 | |
156 UnlockContext(Context); | |
157 } | |
158 | |
159 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) | |
160 { | |
161 ALCcontext *Context; | |
162 ALboolean result; | |
163 | |
164 Context = GetLockedContext(); | |
165 if(!Context) return AL_FALSE; | |
166 | |
167 result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ? | |
168 AL_TRUE : AL_FALSE); | |
169 | |
170 UnlockContext(Context); | |
171 | |
172 return result; | |
173 } | |
174 | |
175 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) | |
176 { | |
177 ALCdevice *Device; | |
178 ALCcontext *Context; | |
179 ALeffectslot *EffectSlot; | |
180 | |
181 Context = GetLockedContext(); | |
182 if(!Context) return; | |
183 | |
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; | |
191 | |
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; | |
201 | |
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; | |
211 | |
212 default: | |
213 alSetError(Context, AL_INVALID_ENUM); | |
214 break; | |
215 } | |
216 } | |
217 else | |
218 alSetError(Context, AL_INVALID_NAME); | |
219 | |
220 UnlockContext(Context); | |
221 } | |
222 | |
223 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) | |
224 { | |
225 ALCcontext *Context; | |
226 | |
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 } | |
234 | |
235 Context = GetLockedContext(); | |
236 if(!Context) return; | |
237 | |
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); | |
249 | |
250 UnlockContext(Context); | |
251 } | |
252 | |
253 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) | |
254 { | |
255 ALCcontext *Context; | |
256 ALeffectslot *EffectSlot; | |
257 | |
258 Context = GetLockedContext(); | |
259 if(!Context) return; | |
260 | |
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; | |
274 | |
275 default: | |
276 alSetError(Context, AL_INVALID_ENUM); | |
277 break; | |
278 } | |
279 } | |
280 else | |
281 alSetError(Context, AL_INVALID_NAME); | |
282 | |
283 UnlockContext(Context); | |
284 } | |
285 | |
286 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) | |
287 { | |
288 ALCcontext *Context; | |
289 | |
290 switch(param) | |
291 { | |
292 case AL_EFFECTSLOT_GAIN: | |
293 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]); | |
294 return; | |
295 } | |
296 | |
297 Context = GetLockedContext(); | |
298 if(!Context) return; | |
299 | |
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); | |
311 | |
312 UnlockContext(Context); | |
313 } | |
314 | |
315 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) | |
316 { | |
317 ALCcontext *Context; | |
318 ALeffectslot *EffectSlot; | |
319 | |
320 Context = GetLockedContext(); | |
321 if(!Context) return; | |
322 | |
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; | |
330 | |
331 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: | |
332 *piValue = EffectSlot->AuxSendAuto; | |
333 break; | |
334 | |
335 default: | |
336 alSetError(Context, AL_INVALID_ENUM); | |
337 break; | |
338 } | |
339 } | |
340 else | |
341 alSetError(Context, AL_INVALID_NAME); | |
342 | |
343 UnlockContext(Context); | |
344 } | |
345 | |
346 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) | |
347 { | |
348 ALCcontext *Context; | |
349 | |
350 switch(param) | |
351 { | |
352 case AL_EFFECTSLOT_EFFECT: | |
353 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: | |
354 alGetAuxiliaryEffectSloti(effectslot, param, piValues); | |
355 return; | |
356 } | |
357 | |
358 Context = GetLockedContext(); | |
359 if(!Context) return; | |
360 | |
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); | |
372 | |
373 UnlockContext(Context); | |
374 } | |
375 | |
376 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) | |
377 { | |
378 ALCcontext *Context; | |
379 ALeffectslot *EffectSlot; | |
380 | |
381 Context = GetLockedContext(); | |
382 if(!Context) return; | |
383 | |
384 if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) | |
385 { | |
386 switch(param) | |
387 { | |
388 case AL_EFFECTSLOT_GAIN: | |
389 *pflValue = EffectSlot->Gain; | |
390 break; | |
391 | |
392 default: | |
393 alSetError(Context, AL_INVALID_ENUM); | |
394 break; | |
395 } | |
396 } | |
397 else | |
398 alSetError(Context, AL_INVALID_NAME); | |
399 | |
400 UnlockContext(Context); | |
401 } | |
402 | |
403 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) | |
404 { | |
405 ALCcontext *Context; | |
406 | |
407 switch(param) | |
408 { | |
409 case AL_EFFECTSLOT_GAIN: | |
410 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues); | |
411 return; | |
412 } | |
413 | |
414 Context = GetLockedContext(); | |
415 if(!Context) return; | |
416 | |
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); | |
428 | |
429 UnlockContext(Context); | |
430 } | |
431 | |
432 | |
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; | |
458 | |
459 state = calloc(1, sizeof(*state)); | |
460 if(!state) | |
461 return NULL; | |
462 | |
463 state->Destroy = NoneDestroy; | |
464 state->DeviceUpdate = NoneDeviceUpdate; | |
465 state->Update = NoneUpdate; | |
466 state->Process = NoneProcess; | |
467 | |
468 return state; | |
469 } | |
470 | |
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; | |
502 | |
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 } | |
523 | |
524 | |
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; | |
532 | |
533 // Release effectslot structure | |
534 ALEffect_Destroy(temp->EffectState); | |
535 | |
536 FreeThunkEntry(temp->effectslot); | |
537 memset(temp, 0, sizeof(ALeffectslot)); | |
538 free(temp); | |
539 } | |
540 } |