Mercurial > fife-parpg
comparison ext/openal-soft/OpenAL32/alAuxEffectSlot.c @ 89:fa33cda75471
* Reverting back to 2543 as requested by sleek
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sat, 19 Jul 2008 11:38:52 +0000 |
parents | 4a0efb7baf70 |
children |
comparison
equal
deleted
inserted
replaced
88:1c2842ebe393 | 89:fa33cda75471 |
---|---|
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 } |