6.1 uses front- and back-center, not left- and right-back channels
[openal-soft.git] / OpenAL32 / alEffect.c
blob939b663f1e4d30efdf629c4f26eed47f06091e72
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>
25 #include "AL/al.h"
26 #include "AL/alc.h"
27 #include "alMain.h"
28 #include "alEffect.h"
29 #include "alThunk.h"
30 #include "alError.h"
33 ALboolean DisabledEffects[MAX_EFFECTS];
36 static ALeffect *g_EffectList;
37 static ALuint g_EffectCount;
39 static void InitEffectParams(ALeffect *effect, ALenum type);
42 ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
44 ALCcontext *Context;
45 ALsizei i;
47 Context = alcGetCurrentContext();
48 SuspendContext(Context);
50 if (n > 0)
52 // Check that enough memory has been allocted in the 'effects' array for n Effects
53 if (!IsBadWritePtr((void*)effects, n * sizeof(ALuint)))
55 ALeffect **list = &g_EffectList;
56 while(*list)
57 list = &(*list)->next;
59 i = 0;
60 while(i < n)
62 *list = calloc(1, sizeof(ALeffect));
63 if(!(*list))
65 // We must have run out or memory
66 alDeleteEffects(i, effects);
67 alSetError(AL_OUT_OF_MEMORY);
68 break;
71 effects[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
72 (*list)->effect = effects[i];
74 InitEffectParams(*list, AL_EFFECT_NULL);
75 g_EffectCount++;
76 i++;
78 list = &(*list)->next;
83 ProcessContext(Context);
86 ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects)
88 ALCcontext *Context;
89 ALeffect *ALEffect;
90 ALsizei i;
92 Context = alcGetCurrentContext();
93 SuspendContext(Context);
95 if (n >= 0)
97 // Check that all effects are valid
98 for (i = 0; i < n; i++)
100 if (!alIsEffect(effects[i]))
102 alSetError(AL_INVALID_NAME);
103 break;
107 if (i == n)
109 // All effects are valid
110 for (i = 0; i < n; i++)
112 // Recheck that the effect is valid, because there could be duplicated names
113 if (effects[i] && alIsEffect(effects[i]))
115 ALeffect **list;
117 ALEffect = ((ALeffect*)ALTHUNK_LOOKUPENTRY(effects[i]));
119 // Remove Source from list of Sources
120 list = &g_EffectList;
121 while(*list && *list != ALEffect)
122 list = &(*list)->next;
124 if(*list)
125 *list = (*list)->next;
126 ALTHUNK_REMOVEENTRY(ALEffect->effect);
128 memset(ALEffect, 0, sizeof(ALeffect));
129 free(ALEffect);
131 g_EffectCount--;
136 else
137 alSetError(AL_INVALID_VALUE);
139 ProcessContext(Context);
142 ALboolean AL_APIENTRY alIsEffect(ALuint effect)
144 ALCcontext *Context;
145 ALeffect **list;
147 Context = alcGetCurrentContext();
148 SuspendContext(Context);
150 list = &g_EffectList;
151 while(*list && (*list)->effect != effect)
152 list = &(*list)->next;
154 ProcessContext(Context);
156 return ((*list || !effect) ? AL_TRUE : AL_FALSE);
159 ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
161 ALCcontext *Context;
163 Context = alcGetCurrentContext();
164 SuspendContext(Context);
166 if (effect && alIsEffect(effect))
168 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
170 if(param == AL_EFFECT_TYPE)
172 ALboolean isOk = (iValue == AL_EFFECT_NULL ||
173 (iValue == AL_EFFECT_REVERB && !DisabledEffects[REVERB]));
175 if(isOk)
176 InitEffectParams(ALEffect, iValue);
177 else
178 alSetError(AL_INVALID_VALUE);
180 else if(ALEffect->type == AL_EFFECT_REVERB)
182 switch(param)
184 case AL_REVERB_DECAY_HFLIMIT:
185 if(iValue == AL_TRUE || iValue == AL_FALSE)
186 ALEffect->Reverb.DecayHFLimit = iValue;
187 else
188 alSetError(AL_INVALID_VALUE);
189 break;
191 default:
192 alSetError(AL_INVALID_ENUM);
193 break;
196 else
197 alSetError(AL_INVALID_ENUM);
199 else
200 alSetError(AL_INVALID_NAME);
202 ProcessContext(Context);
205 ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
207 ALCcontext *Context;
209 Context = alcGetCurrentContext();
210 SuspendContext(Context);
212 if (effect && alIsEffect(effect))
214 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
216 if(param == AL_EFFECT_TYPE)
218 alEffecti(effect, param, piValues[0]);
220 else if(ALEffect->type == AL_EFFECT_REVERB)
222 switch(param)
224 case AL_REVERB_DECAY_HFLIMIT:
225 alEffecti(effect, param, piValues[0]);
226 break;
228 default:
229 alSetError(AL_INVALID_ENUM);
230 break;
233 else
234 alSetError(AL_INVALID_ENUM);
236 else
237 alSetError(AL_INVALID_NAME);
239 ProcessContext(Context);
242 ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
244 ALCcontext *Context;
246 Context = alcGetCurrentContext();
247 SuspendContext(Context);
249 if (effect && alIsEffect(effect))
251 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
253 if(ALEffect->type == AL_EFFECT_REVERB)
255 switch(param)
257 case AL_REVERB_DENSITY:
258 if(flValue >= 0.0f && flValue <= 1.0f)
259 ALEffect->Reverb.Density = flValue;
260 else
261 alSetError(AL_INVALID_VALUE);
262 break;
264 case AL_REVERB_DIFFUSION:
265 if(flValue >= 0.0f && flValue <= 1.0f)
266 ALEffect->Reverb.Diffusion = flValue;
267 else
268 alSetError(AL_INVALID_VALUE);
269 break;
271 case AL_REVERB_GAIN:
272 if(flValue >= 0.0f && flValue <= 1.0f)
273 ALEffect->Reverb.Gain = flValue;
274 else
275 alSetError(AL_INVALID_VALUE);
276 break;
278 case AL_REVERB_GAINHF:
279 if(flValue >= 0.0f && flValue <= 1.0f)
280 ALEffect->Reverb.GainHF = flValue;
281 else
282 alSetError(AL_INVALID_VALUE);
283 break;
285 case AL_REVERB_DECAY_TIME:
286 if(flValue >= 0.1f && flValue <= 20.0f)
287 ALEffect->Reverb.DecayTime = flValue;
288 else
289 alSetError(AL_INVALID_VALUE);
290 break;
292 case AL_REVERB_DECAY_HFRATIO:
293 if(flValue >= 0.1f && flValue <= 2.0f)
294 ALEffect->Reverb.DecayHFRatio = flValue;
295 else
296 alSetError(AL_INVALID_VALUE);
297 break;
299 case AL_REVERB_REFLECTIONS_GAIN:
300 if(flValue >= 0.0f && flValue <= 3.16f)
301 ALEffect->Reverb.ReflectionsGain = flValue;
302 else
303 alSetError(AL_INVALID_VALUE);
304 break;
306 case AL_REVERB_REFLECTIONS_DELAY:
307 if(flValue >= 0.0f && flValue <= 0.3f)
308 ALEffect->Reverb.ReflectionsDelay = flValue;
309 else
310 alSetError(AL_INVALID_VALUE);
311 break;
313 case AL_REVERB_LATE_REVERB_GAIN:
314 if(flValue >= 0.0f && flValue <= 10.0f)
315 ALEffect->Reverb.LateReverbGain = flValue;
316 else
317 alSetError(AL_INVALID_VALUE);
318 break;
320 case AL_REVERB_LATE_REVERB_DELAY:
321 if(flValue >= 0.0f && flValue <= 0.1f)
322 ALEffect->Reverb.LateReverbDelay = flValue;
323 else
324 alSetError(AL_INVALID_VALUE);
325 break;
327 case AL_REVERB_AIR_ABSORPTION_GAINHF:
328 if(flValue >= 0.892f && flValue <= 1.0f)
329 ALEffect->Reverb.AirAbsorptionGainHF = flValue;
330 else
331 alSetError(AL_INVALID_VALUE);
332 break;
334 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
335 if(flValue >= 0.0f && flValue <= 10.0f)
336 ALEffect->Reverb.RoomRolloffFactor = flValue;
337 else
338 alSetError(AL_INVALID_VALUE);
339 break;
341 default:
342 alSetError(AL_INVALID_ENUM);
343 break;
346 else
347 alSetError(AL_INVALID_ENUM);
349 else
350 alSetError(AL_INVALID_NAME);
352 ProcessContext(Context);
355 ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
357 ALCcontext *Context;
359 Context = alcGetCurrentContext();
360 SuspendContext(Context);
362 if (effect && alIsEffect(effect))
364 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
366 if(ALEffect->type == AL_EFFECT_REVERB)
368 switch(param)
370 case AL_REVERB_DENSITY:
371 case AL_REVERB_DIFFUSION:
372 case AL_REVERB_GAIN:
373 case AL_REVERB_GAINHF:
374 case AL_REVERB_DECAY_TIME:
375 case AL_REVERB_DECAY_HFRATIO:
376 case AL_REVERB_REFLECTIONS_GAIN:
377 case AL_REVERB_REFLECTIONS_DELAY:
378 case AL_REVERB_LATE_REVERB_GAIN:
379 case AL_REVERB_LATE_REVERB_DELAY:
380 case AL_REVERB_AIR_ABSORPTION_GAINHF:
381 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
382 alEffectf(effect, param, pflValues[0]);
383 break;
385 default:
386 alSetError(AL_INVALID_ENUM);
387 break;
390 else
391 alSetError(AL_INVALID_ENUM);
393 else
394 alSetError(AL_INVALID_NAME);
396 ProcessContext(Context);
399 ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
401 ALCcontext *Context;
403 Context = alcGetCurrentContext();
404 SuspendContext(Context);
406 if (effect && alIsEffect(effect))
408 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
410 if(param == AL_EFFECT_TYPE)
412 *piValue = ALEffect->type;
414 else if(ALEffect->type == AL_EFFECT_REVERB)
416 switch(param)
418 case AL_REVERB_DECAY_HFLIMIT:
419 *piValue = ALEffect->Reverb.DecayHFLimit;
420 break;
422 default:
423 alSetError(AL_INVALID_ENUM);
424 break;
427 else
428 alSetError(AL_INVALID_ENUM);
430 else
431 alSetError(AL_INVALID_NAME);
433 ProcessContext(Context);
436 ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
438 ALCcontext *Context;
440 Context = alcGetCurrentContext();
441 SuspendContext(Context);
443 if (effect && alIsEffect(effect))
445 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
447 if(param == AL_EFFECT_TYPE)
449 alGetEffecti(effect, param, piValues);
451 else if(ALEffect->type == AL_EFFECT_REVERB)
453 switch(param)
455 case AL_REVERB_DECAY_HFLIMIT:
456 alGetEffecti(effect, param, piValues);
457 break;
459 default:
460 alSetError(AL_INVALID_ENUM);
461 break;
464 else
465 alSetError(AL_INVALID_ENUM);
467 else
468 alSetError(AL_INVALID_NAME);
470 ProcessContext(Context);
473 ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
475 ALCcontext *Context;
477 Context = alcGetCurrentContext();
478 SuspendContext(Context);
480 if (effect && alIsEffect(effect))
482 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
484 if(ALEffect->type == AL_EFFECT_REVERB)
486 switch(param)
488 case AL_REVERB_DENSITY:
489 *pflValue = ALEffect->Reverb.Density;
490 break;
492 case AL_REVERB_DIFFUSION:
493 *pflValue = ALEffect->Reverb.Diffusion;
494 break;
496 case AL_REVERB_GAIN:
497 *pflValue = ALEffect->Reverb.Gain;
498 break;
500 case AL_REVERB_GAINHF:
501 *pflValue = ALEffect->Reverb.GainHF;
502 break;
504 case AL_REVERB_DECAY_TIME:
505 *pflValue = ALEffect->Reverb.DecayTime;
506 break;
508 case AL_REVERB_DECAY_HFRATIO:
509 *pflValue = ALEffect->Reverb.DecayHFRatio;
510 break;
512 case AL_REVERB_REFLECTIONS_GAIN:
513 *pflValue = ALEffect->Reverb.ReflectionsGain;
514 break;
516 case AL_REVERB_REFLECTIONS_DELAY:
517 *pflValue = ALEffect->Reverb.ReflectionsDelay;
518 break;
520 case AL_REVERB_LATE_REVERB_GAIN:
521 *pflValue = ALEffect->Reverb.LateReverbGain;
522 break;
524 case AL_REVERB_LATE_REVERB_DELAY:
525 *pflValue = ALEffect->Reverb.LateReverbDelay;
526 break;
528 case AL_REVERB_AIR_ABSORPTION_GAINHF:
529 *pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
530 break;
532 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
533 *pflValue = ALEffect->Reverb.RoomRolloffFactor;
534 break;
536 default:
537 alSetError(AL_INVALID_ENUM);
538 break;
541 else
542 alSetError(AL_INVALID_ENUM);
544 else
545 alSetError(AL_INVALID_NAME);
547 ProcessContext(Context);
550 ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
552 ALCcontext *Context;
554 Context = alcGetCurrentContext();
555 SuspendContext(Context);
557 if (effect && alIsEffect(effect))
559 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
561 if(ALEffect->type == AL_EFFECT_REVERB)
563 switch(param)
565 case AL_REVERB_DENSITY:
566 case AL_REVERB_DIFFUSION:
567 case AL_REVERB_GAIN:
568 case AL_REVERB_GAINHF:
569 case AL_REVERB_DECAY_TIME:
570 case AL_REVERB_DECAY_HFRATIO:
571 case AL_REVERB_REFLECTIONS_GAIN:
572 case AL_REVERB_REFLECTIONS_DELAY:
573 case AL_REVERB_LATE_REVERB_GAIN:
574 case AL_REVERB_LATE_REVERB_DELAY:
575 case AL_REVERB_AIR_ABSORPTION_GAINHF:
576 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
577 alGetEffectf(effect, param, pflValues);
578 break;
580 default:
581 alSetError(AL_INVALID_ENUM);
582 break;
585 else
586 alSetError(AL_INVALID_ENUM);
588 else
589 alSetError(AL_INVALID_NAME);
591 ProcessContext(Context);
595 ALvoid ReleaseALEffects(ALvoid)
597 #ifdef _DEBUG
598 if(g_EffectCount > 0)
599 AL_PRINT("exit(): deleting %d Effect(s)\n", g_EffectCount);
600 #endif
602 while(g_EffectList)
604 ALeffect *temp = g_EffectList;
605 g_EffectList = g_EffectList->next;
607 // Release effect structure
608 memset(temp, 0, sizeof(ALeffect));
609 free(temp);
611 g_EffectCount = 0;
615 static void InitEffectParams(ALeffect *effect, ALenum type)
617 effect->type = type;
618 switch(type)
620 case AL_EFFECT_REVERB:
621 effect->Reverb.Density = 1.0f;
622 effect->Reverb.Diffusion = 1.0f;
623 effect->Reverb.Gain = 0.32f;
624 effect->Reverb.GainHF = 0.89f;
625 effect->Reverb.DecayTime = 1.49f;
626 effect->Reverb.DecayHFRatio = 0.83f;
627 effect->Reverb.ReflectionsGain = 0.05f;
628 effect->Reverb.ReflectionsDelay = 0.007f;
629 effect->Reverb.LateReverbGain = 1.26f;
630 effect->Reverb.LateReverbDelay = 0.011f;
631 effect->Reverb.AirAbsorptionGainHF = 0.994f;
632 effect->Reverb.RoomRolloffFactor = 0.0f;
633 effect->Reverb.DecayHFLimit = AL_TRUE;
634 break;