comparison ext/openal-soft/OpenAL32/alAuxEffectSlot.c @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
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
33
34 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
35
36
37 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
38 {
39 ALCcontext *Context;
40 ALsizei i;
41
42 Context = alcGetCurrentContext();
43 if(!Context)
44 {
45 alSetError(AL_INVALID_OPERATION);
46 return;
47 }
48 SuspendContext(Context);
49
50 if (n > 0)
51 {
52 /* NOTE: We only support one slot currently */
53 if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
54 {
55 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
56 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
57 {
58 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
59 while(*list)
60 list = &(*list)->next;
61
62 i = 0;
63 while(i < n)
64 {
65 *list = calloc(1, sizeof(ALeffectslot));
66 if(!(*list))
67 {
68 // We must have run out or memory
69 alDeleteAuxiliaryEffectSlots(i, effectslots);
70 alSetError(AL_OUT_OF_MEMORY);
71 break;
72 }
73
74 (*list)->Gain = 1.0;
75 (*list)->AuxSendAuto = AL_TRUE;
76 (*list)->refcount = 0;
77
78 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
79 (*list)->effectslot = effectslots[i];
80
81 Context->AuxiliaryEffectSlotCount++;
82 i++;
83
84 list = &(*list)->next;
85 }
86 }
87 }
88 else
89 alSetError(AL_INVALID_OPERATION);
90 }
91
92 ProcessContext(Context);
93 }
94
95 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
96 {
97 ALCcontext *Context;
98 ALeffectslot *ALAuxiliaryEffectSlot;
99 ALsizei i;
100
101 Context = alcGetCurrentContext();
102 if(!Context)
103 {
104 alSetError(AL_INVALID_OPERATION);
105 return;
106 }
107 SuspendContext(Context);
108
109 if (n >= 0)
110 {
111 // Check that all effectslots are valid
112 for (i = 0; i < n; i++)
113 {
114 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
115 {
116 alSetError(AL_INVALID_NAME);
117 break;
118 }
119 else
120 {
121 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
122 if(ALAuxiliaryEffectSlot->refcount > 0)
123 {
124 alSetError(AL_INVALID_NAME);
125 break;
126 }
127 }
128 }
129
130 if (i == n)
131 {
132 // All effectslots are valid
133 for (i = 0; i < n; i++)
134 {
135 // Recheck that the effectslot is valid, because there could be duplicated names
136 if (alIsAuxiliaryEffectSlot(effectslots[i]))
137 {
138 ALeffectslot **list;
139
140 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
141
142 // Remove Source from list of Sources
143 list = &Context->AuxiliaryEffectSlot;
144 while(*list && *list != ALAuxiliaryEffectSlot)
145 list = &(*list)->next;
146
147 if(*list)
148 *list = (*list)->next;
149 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
150
151 free(ALAuxiliaryEffectSlot->ReverbBuffer);
152
153 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
154 free(ALAuxiliaryEffectSlot);
155
156 Context->AuxiliaryEffectSlotCount--;
157 }
158 }
159 }
160 }
161 else
162 alSetError(AL_INVALID_VALUE);
163
164 ProcessContext(Context);
165 }
166
167 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
168 {
169 ALCcontext *Context;
170 ALeffectslot **list;
171
172 Context = alcGetCurrentContext();
173 if(!Context)
174 {
175 alSetError(AL_INVALID_OPERATION);
176 return AL_FALSE;
177 }
178 SuspendContext(Context);
179
180 list = &Context->AuxiliaryEffectSlot;
181 while(*list && (*list)->effectslot != effectslot)
182 list = &(*list)->next;
183
184 ProcessContext(Context);
185
186 return (*list ? AL_TRUE : AL_FALSE);
187 }
188
189 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
190 {
191 ALCcontext *Context;
192
193 Context = alcGetCurrentContext();
194 if(!Context)
195 {
196 alSetError(AL_INVALID_OPERATION);
197 return;
198 }
199 SuspendContext(Context);
200
201 if (alIsAuxiliaryEffectSlot(effectslot))
202 {
203 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
204
205 switch(param)
206 {
207 case AL_EFFECTSLOT_EFFECT:
208 if(alIsEffect(iValue))
209 {
210 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
211 InitializeEffect(Context, ALEffectSlot, effect);
212 }
213 else
214 alSetError(AL_INVALID_VALUE);
215 break;
216
217 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
218 if(iValue == AL_TRUE || iValue == AL_FALSE)
219 ALEffectSlot->AuxSendAuto = iValue;
220 else
221 alSetError(AL_INVALID_VALUE);
222 break;
223
224 default:
225 alSetError(AL_INVALID_ENUM);
226 break;
227 }
228 }
229 else
230 alSetError(AL_INVALID_NAME);
231
232 ProcessContext(Context);
233 }
234
235 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
236 {
237 ALCcontext *Context;
238
239 Context = alcGetCurrentContext();
240 if(!Context)
241 {
242 alSetError(AL_INVALID_OPERATION);
243 return;
244 }
245 SuspendContext(Context);
246
247 if (alIsAuxiliaryEffectSlot(effectslot))
248 {
249 switch(param)
250 {
251 case AL_EFFECTSLOT_EFFECT:
252 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
253 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
254 break;
255
256 default:
257 alSetError(AL_INVALID_ENUM);
258 break;
259 }
260 }
261 else
262 alSetError(AL_INVALID_NAME);
263
264 ProcessContext(Context);
265 }
266
267 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
268 {
269 ALCcontext *Context;
270
271 Context = alcGetCurrentContext();
272 if(!Context)
273 {
274 alSetError(AL_INVALID_OPERATION);
275 return;
276 }
277 SuspendContext(Context);
278
279 if (alIsAuxiliaryEffectSlot(effectslot))
280 {
281 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
282
283 switch(param)
284 {
285 case AL_EFFECTSLOT_GAIN:
286 if(flValue >= 0.0f && flValue <= 1.0f)
287 ALEffectSlot->Gain = flValue;
288 else
289 alSetError(AL_INVALID_VALUE);
290 break;
291
292 default:
293 alSetError(AL_INVALID_ENUM);
294 break;
295 }
296 }
297 else
298 alSetError(AL_INVALID_NAME);
299
300 ProcessContext(Context);
301 }
302
303 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
304 {
305 ALCcontext *Context;
306
307 Context = alcGetCurrentContext();
308 if(!Context)
309 {
310 alSetError(AL_INVALID_OPERATION);
311 return;
312 }
313 SuspendContext(Context);
314
315 if (alIsAuxiliaryEffectSlot(effectslot))
316 {
317 switch(param)
318 {
319 case AL_EFFECTSLOT_GAIN:
320 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
321 break;
322
323 default:
324 alSetError(AL_INVALID_ENUM);
325 break;
326 }
327 }
328 else
329 alSetError(AL_INVALID_NAME);
330
331 ProcessContext(Context);
332 }
333
334 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
335 {
336 ALCcontext *Context;
337
338 Context = alcGetCurrentContext();
339 if(!Context)
340 {
341 alSetError(AL_INVALID_OPERATION);
342 return;
343 }
344 SuspendContext(Context);
345
346 if (alIsAuxiliaryEffectSlot(effectslot))
347 {
348 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
349
350 switch(param)
351 {
352 case AL_EFFECTSLOT_EFFECT:
353 *piValue = ALEffectSlot->effect.effect;
354 break;
355
356 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
357 *piValue = ALEffectSlot->AuxSendAuto;
358 break;
359
360 default:
361 alSetError(AL_INVALID_ENUM);
362 break;
363 }
364 }
365 else
366 alSetError(AL_INVALID_NAME);
367
368 ProcessContext(Context);
369 }
370
371 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
372 {
373 ALCcontext *Context;
374
375 Context = alcGetCurrentContext();
376 if(!Context)
377 {
378 alSetError(AL_INVALID_OPERATION);
379 return;
380 }
381 SuspendContext(Context);
382
383 if (alIsAuxiliaryEffectSlot(effectslot))
384 {
385 switch(param)
386 {
387 case AL_EFFECTSLOT_EFFECT:
388 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
389 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
390 break;
391
392 default:
393 alSetError(AL_INVALID_ENUM);
394 break;
395 }
396 }
397 else
398 alSetError(AL_INVALID_NAME);
399
400 ProcessContext(Context);
401 }
402
403 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
404 {
405 ALCcontext *Context;
406
407 Context = alcGetCurrentContext();
408 if(!Context)
409 {
410 alSetError(AL_INVALID_OPERATION);
411 return;
412 }
413 SuspendContext(Context);
414
415 if (alIsAuxiliaryEffectSlot(effectslot))
416 {
417 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
418
419 switch(param)
420 {
421 case AL_EFFECTSLOT_GAIN:
422 *pflValue = ALEffectSlot->Gain;
423 break;
424
425 default:
426 alSetError(AL_INVALID_ENUM);
427 break;
428 }
429 }
430 else
431 alSetError(AL_INVALID_NAME);
432
433 ProcessContext(Context);
434 }
435
436 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
437 {
438 ALCcontext *Context;
439
440 Context = alcGetCurrentContext();
441 if(!Context)
442 {
443 alSetError(AL_INVALID_OPERATION);
444 return;
445 }
446 SuspendContext(Context);
447
448 if (alIsAuxiliaryEffectSlot(effectslot))
449 {
450 switch(param)
451 {
452 case AL_EFFECTSLOT_GAIN:
453 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
454 break;
455
456 default:
457 alSetError(AL_INVALID_ENUM);
458 break;
459 }
460 }
461 else
462 alSetError(AL_INVALID_NAME);
463
464 ProcessContext(Context);
465 }
466
467
468 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
469 {
470 ALfloat *ptr = NULL;
471
472 if(!effect)
473 {
474 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
475 goto done;
476 }
477
478 if(effect->type == AL_EFFECT_REVERB)
479 {
480 ALuint size;
481 ALfloat reverbwait;
482
483 reverbwait = (1.0f-effect->Reverb.Density)*(0.1f-0.075f) + 0.075f;
484
485 size = (ALuint)((ALfloat)Context->Frequency *
486 (effect->Reverb.ReflectionsDelay +
487 effect->Reverb.LateReverbDelay +
488 reverbwait)) + 1;
489
490 ptr = calloc(size, sizeof(ALfloat));
491 if(!ptr)
492 {
493 alSetError(AL_OUT_OF_MEMORY);
494 return;
495 }
496 if(ALEffectSlot->ReverbBuffer)
497 memcpy(ptr, ALEffectSlot->ReverbBuffer, min(size, ALEffectSlot->ReverbLength)*sizeof(ALfloat));
498 ALEffectSlot->ReverbLength = size;
499 ALEffectSlot->ReverbPos %= size;
500 ALEffectSlot->ReverbReflectPos = (ALuint)(ALEffectSlot->ReverbLength -
501 ((ALfloat)Context->Frequency *
502 effect->Reverb.ReflectionsDelay) +
503 ALEffectSlot->ReverbPos) %
504 ALEffectSlot->ReverbLength;
505 ALEffectSlot->ReverbLatePos = (ALuint)(ALEffectSlot->ReverbLength -
506 ((ALfloat)Context->Frequency *
507 (effect->Reverb.LateReverbDelay +
508 effect->Reverb.ReflectionsDelay)) +
509 ALEffectSlot->ReverbPos) %
510 ALEffectSlot->ReverbLength;
511 ALEffectSlot->ReverbDecayGain = pow(1.0/32768.0, 1.0/(effect->Reverb.DecayTime/reverbwait));
512 }
513
514 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
515 done:
516 free(ALEffectSlot->ReverbBuffer);
517 ALEffectSlot->ReverbBuffer = ptr;
518 }
519
520
521 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
522 {
523 #ifdef _DEBUG
524 if(Context->AuxiliaryEffectSlotCount > 0)
525 AL_PRINT("alcDestroyContext(): %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount);
526 #endif
527
528 while(Context->AuxiliaryEffectSlot)
529 {
530 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
531 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
532
533 // Release effectslot structure
534 free(temp->ReverbBuffer);
535 ALTHUNK_REMOVEENTRY(temp->effectslot);
536
537 memset(temp, 0, sizeof(ALeffectslot));
538 free(temp);
539 }
540 Context->AuxiliaryEffectSlotCount = 0;
541 }