Allow getting and setting reverb parameters, as well as setting reverb effects
[openal-soft.git] / OpenAL32 / alEffect.c
blobbe132e4f6becbe6491f4d007cff5138a4e38d104
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 <stdlib.h>
23 #include "config.h"
25 #include "AL/al.h"
26 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alEffect.h"
30 #include "alThunk.h"
31 #include "alError.h"
33 static ALeffect *g_EffectList;
34 static ALuint g_EffectCount;
36 static void InitEffectParams(ALeffect *effect, ALenum type);
39 AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
41 ALCcontext *Context;
42 ALsizei i;
44 Context = alcGetCurrentContext();
45 SuspendContext(Context);
47 if (n > 0)
49 // Check that enough memory has been allocted in the 'effects' array for n Effects
50 if (!IsBadWritePtr((void*)effects, n * sizeof(ALuint)))
52 ALeffect **list = &g_EffectList;
53 while(*list)
54 list = &(*list)->next;
56 i = 0;
57 while(i < n)
59 *list = calloc(1, sizeof(ALeffect));
60 if(!(*list))
62 // We must have run out or memory
63 alDeleteEffects(i, effects);
64 alSetError(AL_OUT_OF_MEMORY);
65 break;
68 effects[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
69 (*list)->effect = effects[i];
71 InitEffectParams(*list, AL_EFFECT_NULL);
72 g_EffectCount++;
73 i++;
75 list = &(*list)->next;
80 ProcessContext(Context);
83 AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects)
85 ALCcontext *Context;
86 ALeffect *ALEffect;
87 ALsizei i;
89 Context = alcGetCurrentContext();
90 SuspendContext(Context);
92 if (n >= 0)
94 // Check that all effects are valid
95 for (i = 0; i < n; i++)
97 if (!alIsEffect(effects[i]))
99 alSetError(AL_INVALID_NAME);
100 break;
104 if (i == n)
106 // All effects are valid
107 for (i = 0; i < n; i++)
109 // Recheck that the effect is valid, because there could be duplicated names
110 if (effects[i] && alIsEffect(effects[i]))
112 ALeffect **list;
114 ALEffect = ((ALeffect*)ALTHUNK_LOOKUPENTRY(effects[i]));
116 // Remove Source from list of Sources
117 list = &g_EffectList;
118 while(*list && *list != ALEffect)
119 list = &(*list)->next;
121 if(*list)
122 *list = (*list)->next;
123 ALTHUNK_REMOVEENTRY(ALEffect->effect);
125 memset(ALEffect, 0, sizeof(ALeffect));
126 free(ALEffect);
128 g_EffectCount--;
133 else
134 alSetError(AL_INVALID_VALUE);
136 ProcessContext(Context);
139 AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
141 ALCcontext *Context;
142 ALeffect **list;
144 Context = alcGetCurrentContext();
145 SuspendContext(Context);
147 list = &g_EffectList;
148 while(*list && (*list)->effect != effect)
149 list = &(*list)->next;
151 ProcessContext(Context);
153 return ((*list || !effect) ? AL_TRUE : AL_FALSE);
156 AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
158 ALCcontext *Context;
160 Context = alcGetCurrentContext();
161 SuspendContext(Context);
163 if (effect && alIsEffect(effect))
165 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
167 if(param == AL_EFFECT_TYPE)
169 if(iValue == AL_EFFECT_NULL ||
170 iValue == AL_EFFECT_REVERB)
171 InitEffectParams(ALEffect, iValue);
172 else
173 alSetError(AL_INVALID_VALUE);
175 else if(ALEffect->type == AL_EFFECT_REVERB)
177 switch(param)
179 case AL_REVERB_DECAY_HFLIMIT:
180 if(iValue == AL_TRUE || iValue == AL_FALSE)
181 ALEffect->Reverb.DecayHFLimit = iValue;
182 else
183 alSetError(AL_INVALID_VALUE);
184 break;
186 default:
187 alSetError(AL_INVALID_ENUM);
188 break;
191 else
192 alSetError(AL_INVALID_ENUM);
194 else
195 alSetError(AL_INVALID_NAME);
197 ProcessContext(Context);
200 AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
202 ALCcontext *Context;
204 Context = alcGetCurrentContext();
205 SuspendContext(Context);
207 if (effect && alIsEffect(effect))
209 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
211 if(param == AL_EFFECT_TYPE)
213 alEffecti(effect, param, piValues[0]);
215 else if(ALEffect->type == AL_EFFECT_REVERB)
217 switch(param)
219 case AL_REVERB_DECAY_HFLIMIT:
220 alEffecti(effect, param, piValues[0]);
221 break;
223 default:
224 alSetError(AL_INVALID_ENUM);
225 break;
228 else
229 alSetError(AL_INVALID_ENUM);
231 else
232 alSetError(AL_INVALID_NAME);
234 ProcessContext(Context);
237 AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
239 ALCcontext *Context;
241 Context = alcGetCurrentContext();
242 SuspendContext(Context);
244 if (effect && alIsEffect(effect))
246 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
248 if(ALEffect->type == AL_EFFECT_REVERB)
250 switch(param)
252 case AL_REVERB_DENSITY:
253 if(flValue >= 0.0f && flValue <= 1.0f)
254 ALEffect->Reverb.Density = flValue;
255 else
256 alSetError(AL_INVALID_VALUE);
257 break;
259 case AL_REVERB_DIFFUSION:
260 if(flValue >= 0.0f && flValue <= 1.0f)
261 ALEffect->Reverb.Diffusion = flValue;
262 else
263 alSetError(AL_INVALID_VALUE);
264 break;
266 case AL_REVERB_GAIN:
267 if(flValue >= 0.0f && flValue <= 1.0f)
268 ALEffect->Reverb.Gain = flValue;
269 else
270 alSetError(AL_INVALID_VALUE);
271 break;
273 case AL_REVERB_GAINHF:
274 if(flValue >= 0.0f && flValue <= 1.0f)
275 ALEffect->Reverb.GainHF = flValue;
276 else
277 alSetError(AL_INVALID_VALUE);
278 break;
280 case AL_REVERB_DECAY_TIME:
281 if(flValue >= 0.1f && flValue <= 20.0f)
282 ALEffect->Reverb.DecayTime = flValue;
283 else
284 alSetError(AL_INVALID_VALUE);
285 break;
287 case AL_REVERB_DECAY_HFRATIO:
288 if(flValue >= 0.1f && flValue <= 2.0f)
289 ALEffect->Reverb.DecayHFRatio = flValue;
290 else
291 alSetError(AL_INVALID_VALUE);
292 break;
294 case AL_REVERB_REFLECTIONS_GAIN:
295 if(flValue >= 0.0f && flValue <= 3.16f)
296 ALEffect->Reverb.ReflectionsGain = flValue;
297 else
298 alSetError(AL_INVALID_VALUE);
299 break;
301 case AL_REVERB_REFLECTIONS_DELAY:
302 if(flValue >= 0.0f && flValue <= 0.3f)
303 ALEffect->Reverb.ReflectionsDelay = flValue;
304 else
305 alSetError(AL_INVALID_VALUE);
306 break;
308 case AL_REVERB_LATE_REVERB_GAIN:
309 if(flValue >= 0.0f && flValue <= 10.0f)
310 ALEffect->Reverb.LateReverbGain = flValue;
311 else
312 alSetError(AL_INVALID_VALUE);
313 break;
315 case AL_REVERB_LATE_REVERB_DELAY:
316 if(flValue >= 0.0f && flValue <= 0.1f)
317 ALEffect->Reverb.LateReverbDelay = flValue;
318 else
319 alSetError(AL_INVALID_VALUE);
320 break;
322 case AL_REVERB_AIR_ABSORPTION_GAINHF:
323 if(flValue >= 0.892f && flValue <= 1.0f)
324 ALEffect->Reverb.AirAbsorptionGainHF = flValue;
325 else
326 alSetError(AL_INVALID_VALUE);
327 break;
329 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
330 if(flValue >= 0.0f && flValue <= 10.0f)
331 ALEffect->Reverb.RoomRolloffFactor = flValue;
332 else
333 alSetError(AL_INVALID_VALUE);
334 break;
336 default:
337 alSetError(AL_INVALID_ENUM);
338 break;
341 else
342 alSetError(AL_INVALID_ENUM);
344 else
345 alSetError(AL_INVALID_NAME);
347 ProcessContext(Context);
350 AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
352 ALCcontext *Context;
354 Context = alcGetCurrentContext();
355 SuspendContext(Context);
357 if (effect && alIsEffect(effect))
359 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
361 if(ALEffect->type == AL_EFFECT_REVERB)
363 switch(param)
365 case AL_REVERB_DENSITY:
366 case AL_REVERB_DIFFUSION:
367 case AL_REVERB_GAIN:
368 case AL_REVERB_GAINHF:
369 case AL_REVERB_DECAY_TIME:
370 case AL_REVERB_DECAY_HFRATIO:
371 case AL_REVERB_REFLECTIONS_GAIN:
372 case AL_REVERB_REFLECTIONS_DELAY:
373 case AL_REVERB_LATE_REVERB_GAIN:
374 case AL_REVERB_LATE_REVERB_DELAY:
375 case AL_REVERB_AIR_ABSORPTION_GAINHF:
376 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
377 alEffectf(effect, param, pflValues[0]);
378 break;
380 default:
381 alSetError(AL_INVALID_ENUM);
382 break;
385 else
386 alSetError(AL_INVALID_ENUM);
388 else
389 alSetError(AL_INVALID_NAME);
391 ProcessContext(Context);
394 AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
396 ALCcontext *Context;
398 Context = alcGetCurrentContext();
399 SuspendContext(Context);
401 if (effect && alIsEffect(effect))
403 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
405 if(param == AL_EFFECT_TYPE)
407 *piValue = ALEffect->type;
409 else if(ALEffect->type == AL_EFFECT_REVERB)
411 switch(param)
413 case AL_REVERB_DECAY_HFLIMIT:
414 *piValue = ALEffect->Reverb.DecayHFLimit;
415 break;
417 default:
418 alSetError(AL_INVALID_ENUM);
419 break;
422 else
423 alSetError(AL_INVALID_ENUM);
425 else
426 alSetError(AL_INVALID_NAME);
428 ProcessContext(Context);
431 AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
433 ALCcontext *Context;
435 Context = alcGetCurrentContext();
436 SuspendContext(Context);
438 if (effect && alIsEffect(effect))
440 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
442 if(param == AL_EFFECT_TYPE)
444 alGetEffecti(effect, param, piValues);
446 else if(ALEffect->type == AL_EFFECT_REVERB)
448 switch(param)
450 case AL_REVERB_DECAY_HFLIMIT:
451 alGetEffecti(effect, param, piValues);
452 break;
454 default:
455 alSetError(AL_INVALID_ENUM);
456 break;
459 else
460 alSetError(AL_INVALID_ENUM);
462 else
463 alSetError(AL_INVALID_NAME);
465 ProcessContext(Context);
468 AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
470 ALCcontext *Context;
472 Context = alcGetCurrentContext();
473 SuspendContext(Context);
475 if (effect && alIsEffect(effect))
477 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
479 if(ALEffect->type == AL_EFFECT_REVERB)
481 switch(param)
483 case AL_REVERB_DENSITY:
484 *pflValue = ALEffect->Reverb.Density;
485 break;
487 case AL_REVERB_DIFFUSION:
488 *pflValue = ALEffect->Reverb.Diffusion;
489 break;
491 case AL_REVERB_GAIN:
492 *pflValue = ALEffect->Reverb.Gain;
493 break;
495 case AL_REVERB_GAINHF:
496 *pflValue = ALEffect->Reverb.GainHF;
497 break;
499 case AL_REVERB_DECAY_TIME:
500 *pflValue = ALEffect->Reverb.DecayTime;
501 break;
503 case AL_REVERB_DECAY_HFRATIO:
504 *pflValue = ALEffect->Reverb.DecayHFRatio;
505 break;
507 case AL_REVERB_REFLECTIONS_GAIN:
508 *pflValue = ALEffect->Reverb.ReflectionsGain;
509 break;
511 case AL_REVERB_REFLECTIONS_DELAY:
512 *pflValue = ALEffect->Reverb.ReflectionsDelay;
513 break;
515 case AL_REVERB_LATE_REVERB_GAIN:
516 *pflValue = ALEffect->Reverb.LateReverbGain;
517 break;
519 case AL_REVERB_LATE_REVERB_DELAY:
520 *pflValue = ALEffect->Reverb.LateReverbDelay;
521 break;
523 case AL_REVERB_AIR_ABSORPTION_GAINHF:
524 *pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
525 break;
527 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
528 *pflValue = ALEffect->Reverb.RoomRolloffFactor;
529 break;
531 default:
532 alSetError(AL_INVALID_ENUM);
533 break;
536 else
537 alSetError(AL_INVALID_ENUM);
539 else
540 alSetError(AL_INVALID_NAME);
542 ProcessContext(Context);
545 AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
547 ALCcontext *Context;
549 Context = alcGetCurrentContext();
550 SuspendContext(Context);
552 if (effect && alIsEffect(effect))
554 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
556 if(ALEffect->type == AL_EFFECT_REVERB)
558 switch(param)
560 case AL_REVERB_DENSITY:
561 case AL_REVERB_DIFFUSION:
562 case AL_REVERB_GAIN:
563 case AL_REVERB_GAINHF:
564 case AL_REVERB_DECAY_TIME:
565 case AL_REVERB_DECAY_HFRATIO:
566 case AL_REVERB_REFLECTIONS_GAIN:
567 case AL_REVERB_REFLECTIONS_DELAY:
568 case AL_REVERB_LATE_REVERB_GAIN:
569 case AL_REVERB_LATE_REVERB_DELAY:
570 case AL_REVERB_AIR_ABSORPTION_GAINHF:
571 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
572 alGetEffectf(effect, param, pflValues);
573 break;
575 default:
576 alSetError(AL_INVALID_ENUM);
577 break;
580 else
581 alSetError(AL_INVALID_ENUM);
583 else
584 alSetError(AL_INVALID_NAME);
586 ProcessContext(Context);
590 ALvoid ReleaseALEffects(ALvoid)
592 #ifdef _DEBUG
593 if(g_EffectCount > 0)
594 AL_PRINT("exit() %d Effect(s) NOT deleted\n", g_EffectCount);
595 #endif
597 while(g_EffectList)
599 ALeffect *temp = g_EffectList;
600 g_EffectList = g_EffectList->next;
602 // Release effect structure
603 memset(temp, 0, sizeof(ALeffect));
604 free(temp);
606 g_EffectCount = 0;
610 static void InitEffectParams(ALeffect *effect, ALenum type)
612 effect->type = type;
613 switch(type)
615 case AL_EFFECT_REVERB:
616 effect->Reverb.Density = 1.0f;
617 effect->Reverb.Diffusion = 1.0f;
618 effect->Reverb.Gain = 0.32f;
619 effect->Reverb.GainHF = 0.89f;
620 effect->Reverb.DecayTime = 1.49f;
621 effect->Reverb.DecayHFRatio = 0.83f;
622 effect->Reverb.ReflectionsGain = 0.05f;
623 effect->Reverb.ReflectionsDelay = 0.007f;
624 effect->Reverb.LateReverbGain = 1.26f;
625 effect->Reverb.LateReverbDelay = 0.011f;
626 effect->Reverb.AirAbsorptionGainHF = 0.994f;
627 effect->Reverb.RoomRolloffFactor = 0.0f;
628 effect->Reverb.DecayHFLimit = AL_TRUE;
629 break;