Make the filter history buffer size flexible
[openal-soft.git] / OpenAL32 / alEffect.c
blob4455a2303dc3e9f1e4062987dfcb3a08ec4e6bbf
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]) ||
174 (iValue == AL_EFFECT_ECHO && !DisabledEffects[ECHO]));
176 if(isOk)
177 InitEffectParams(ALEffect, iValue);
178 else
179 alSetError(AL_INVALID_VALUE);
181 else if(ALEffect->type == AL_EFFECT_REVERB)
183 switch(param)
185 case AL_REVERB_DECAY_HFLIMIT:
186 if(iValue == AL_TRUE || iValue == AL_FALSE)
187 ALEffect->Reverb.DecayHFLimit = iValue;
188 else
189 alSetError(AL_INVALID_VALUE);
190 break;
192 default:
193 alSetError(AL_INVALID_ENUM);
194 break;
197 else if(ALEffect->type == AL_EFFECT_ECHO)
199 switch(param)
201 default:
202 alSetError(AL_INVALID_ENUM);
203 break;
206 else
207 alSetError(AL_INVALID_ENUM);
209 else
210 alSetError(AL_INVALID_NAME);
212 ProcessContext(Context);
215 ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
217 ALCcontext *Context;
219 Context = alcGetCurrentContext();
220 SuspendContext(Context);
222 if (effect && alIsEffect(effect))
224 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
226 if(param == AL_EFFECT_TYPE)
228 alEffecti(effect, param, piValues[0]);
230 else if(ALEffect->type == AL_EFFECT_REVERB)
232 switch(param)
234 case AL_REVERB_DECAY_HFLIMIT:
235 alEffecti(effect, param, piValues[0]);
236 break;
238 default:
239 alSetError(AL_INVALID_ENUM);
240 break;
243 else if(ALEffect->type == AL_EFFECT_ECHO)
245 switch(param)
247 default:
248 alSetError(AL_INVALID_ENUM);
249 break;
252 else
253 alSetError(AL_INVALID_ENUM);
255 else
256 alSetError(AL_INVALID_NAME);
258 ProcessContext(Context);
261 ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
263 ALCcontext *Context;
265 Context = alcGetCurrentContext();
266 SuspendContext(Context);
268 if (effect && alIsEffect(effect))
270 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
272 if(ALEffect->type == AL_EFFECT_REVERB)
274 switch(param)
276 case AL_REVERB_DENSITY:
277 if(flValue >= 0.0f && flValue <= 1.0f)
278 ALEffect->Reverb.Density = flValue;
279 else
280 alSetError(AL_INVALID_VALUE);
281 break;
283 case AL_REVERB_DIFFUSION:
284 if(flValue >= 0.0f && flValue <= 1.0f)
285 ALEffect->Reverb.Diffusion = flValue;
286 else
287 alSetError(AL_INVALID_VALUE);
288 break;
290 case AL_REVERB_GAIN:
291 if(flValue >= 0.0f && flValue <= 1.0f)
292 ALEffect->Reverb.Gain = flValue;
293 else
294 alSetError(AL_INVALID_VALUE);
295 break;
297 case AL_REVERB_GAINHF:
298 if(flValue >= 0.0f && flValue <= 1.0f)
299 ALEffect->Reverb.GainHF = flValue;
300 else
301 alSetError(AL_INVALID_VALUE);
302 break;
304 case AL_REVERB_DECAY_TIME:
305 if(flValue >= 0.1f && flValue <= 20.0f)
306 ALEffect->Reverb.DecayTime = flValue;
307 else
308 alSetError(AL_INVALID_VALUE);
309 break;
311 case AL_REVERB_DECAY_HFRATIO:
312 if(flValue >= 0.1f && flValue <= 2.0f)
313 ALEffect->Reverb.DecayHFRatio = flValue;
314 else
315 alSetError(AL_INVALID_VALUE);
316 break;
318 case AL_REVERB_REFLECTIONS_GAIN:
319 if(flValue >= 0.0f && flValue <= 3.16f)
320 ALEffect->Reverb.ReflectionsGain = flValue;
321 else
322 alSetError(AL_INVALID_VALUE);
323 break;
325 case AL_REVERB_REFLECTIONS_DELAY:
326 if(flValue >= 0.0f && flValue <= 0.3f)
327 ALEffect->Reverb.ReflectionsDelay = flValue;
328 else
329 alSetError(AL_INVALID_VALUE);
330 break;
332 case AL_REVERB_LATE_REVERB_GAIN:
333 if(flValue >= 0.0f && flValue <= 10.0f)
334 ALEffect->Reverb.LateReverbGain = flValue;
335 else
336 alSetError(AL_INVALID_VALUE);
337 break;
339 case AL_REVERB_LATE_REVERB_DELAY:
340 if(flValue >= 0.0f && flValue <= 0.1f)
341 ALEffect->Reverb.LateReverbDelay = flValue;
342 else
343 alSetError(AL_INVALID_VALUE);
344 break;
346 case AL_REVERB_AIR_ABSORPTION_GAINHF:
347 if(flValue >= 0.892f && flValue <= 1.0f)
348 ALEffect->Reverb.AirAbsorptionGainHF = flValue;
349 else
350 alSetError(AL_INVALID_VALUE);
351 break;
353 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
354 if(flValue >= 0.0f && flValue <= 10.0f)
355 ALEffect->Reverb.RoomRolloffFactor = flValue;
356 else
357 alSetError(AL_INVALID_VALUE);
358 break;
360 default:
361 alSetError(AL_INVALID_ENUM);
362 break;
365 else if(ALEffect->type == AL_EFFECT_ECHO)
367 switch(param)
369 case AL_ECHO_DELAY:
370 if(flValue >= AL_ECHO_MIN_DELAY && flValue <= AL_ECHO_MAX_DELAY)
371 ALEffect->Echo.Delay = flValue;
372 else
373 alSetError(AL_INVALID_VALUE);
374 break;
376 case AL_ECHO_LRDELAY:
377 if(flValue >= AL_ECHO_MIN_LRDELAY && flValue <= AL_ECHO_MAX_LRDELAY)
378 ALEffect->Echo.LRDelay = flValue;
379 else
380 alSetError(AL_INVALID_VALUE);
381 break;
383 case AL_ECHO_DAMPING:
384 if(flValue >= AL_ECHO_MIN_DAMPING && flValue <= AL_ECHO_MAX_DAMPING)
385 ALEffect->Echo.Damping = flValue;
386 else
387 alSetError(AL_INVALID_VALUE);
388 break;
390 case AL_ECHO_FEEDBACK:
391 if(flValue >= AL_ECHO_MIN_FEEDBACK && flValue <= AL_ECHO_MAX_FEEDBACK)
392 ALEffect->Echo.Feedback = flValue;
393 else
394 alSetError(AL_INVALID_VALUE);
395 break;
397 case AL_ECHO_SPREAD:
398 if(flValue >= AL_ECHO_MIN_SPREAD && flValue <= AL_ECHO_MAX_SPREAD)
399 ALEffect->Echo.Spread = flValue;
400 else
401 alSetError(AL_INVALID_VALUE);
402 break;
404 default:
405 alSetError(AL_INVALID_ENUM);
406 break;
409 else
410 alSetError(AL_INVALID_ENUM);
412 else
413 alSetError(AL_INVALID_NAME);
415 ProcessContext(Context);
418 ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
420 ALCcontext *Context;
422 Context = alcGetCurrentContext();
423 SuspendContext(Context);
425 if (effect && alIsEffect(effect))
427 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
429 if(ALEffect->type == AL_EFFECT_REVERB)
431 switch(param)
433 case AL_REVERB_DENSITY:
434 case AL_REVERB_DIFFUSION:
435 case AL_REVERB_GAIN:
436 case AL_REVERB_GAINHF:
437 case AL_REVERB_DECAY_TIME:
438 case AL_REVERB_DECAY_HFRATIO:
439 case AL_REVERB_REFLECTIONS_GAIN:
440 case AL_REVERB_REFLECTIONS_DELAY:
441 case AL_REVERB_LATE_REVERB_GAIN:
442 case AL_REVERB_LATE_REVERB_DELAY:
443 case AL_REVERB_AIR_ABSORPTION_GAINHF:
444 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
445 alEffectf(effect, param, pflValues[0]);
446 break;
448 default:
449 alSetError(AL_INVALID_ENUM);
450 break;
453 else if(ALEffect->type == AL_EFFECT_ECHO)
455 switch(param)
457 case AL_ECHO_DELAY:
458 case AL_ECHO_LRDELAY:
459 case AL_ECHO_DAMPING:
460 case AL_ECHO_FEEDBACK:
461 case AL_ECHO_SPREAD:
462 alEffectf(effect, param, pflValues[0]);
463 break;
465 default:
466 alSetError(AL_INVALID_ENUM);
467 break;
470 else
471 alSetError(AL_INVALID_ENUM);
473 else
474 alSetError(AL_INVALID_NAME);
476 ProcessContext(Context);
479 ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
481 ALCcontext *Context;
483 Context = alcGetCurrentContext();
484 SuspendContext(Context);
486 if (effect && alIsEffect(effect))
488 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
490 if(param == AL_EFFECT_TYPE)
492 *piValue = ALEffect->type;
494 else if(ALEffect->type == AL_EFFECT_REVERB)
496 switch(param)
498 case AL_REVERB_DECAY_HFLIMIT:
499 *piValue = ALEffect->Reverb.DecayHFLimit;
500 break;
502 default:
503 alSetError(AL_INVALID_ENUM);
504 break;
507 else if(ALEffect->type == AL_EFFECT_ECHO)
509 switch(param)
511 default:
512 alSetError(AL_INVALID_ENUM);
513 break;
516 else
517 alSetError(AL_INVALID_ENUM);
519 else
520 alSetError(AL_INVALID_NAME);
522 ProcessContext(Context);
525 ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
527 ALCcontext *Context;
529 Context = alcGetCurrentContext();
530 SuspendContext(Context);
532 if (effect && alIsEffect(effect))
534 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
536 if(param == AL_EFFECT_TYPE)
538 alGetEffecti(effect, param, piValues);
540 else if(ALEffect->type == AL_EFFECT_REVERB)
542 switch(param)
544 case AL_REVERB_DECAY_HFLIMIT:
545 alGetEffecti(effect, param, piValues);
546 break;
548 default:
549 alSetError(AL_INVALID_ENUM);
550 break;
553 else if(ALEffect->type == AL_EFFECT_ECHO)
555 switch(param)
557 default:
558 alSetError(AL_INVALID_ENUM);
559 break;
562 else
563 alSetError(AL_INVALID_ENUM);
565 else
566 alSetError(AL_INVALID_NAME);
568 ProcessContext(Context);
571 ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
573 ALCcontext *Context;
575 Context = alcGetCurrentContext();
576 SuspendContext(Context);
578 if (effect && alIsEffect(effect))
580 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
582 if(ALEffect->type == AL_EFFECT_REVERB)
584 switch(param)
586 case AL_REVERB_DENSITY:
587 *pflValue = ALEffect->Reverb.Density;
588 break;
590 case AL_REVERB_DIFFUSION:
591 *pflValue = ALEffect->Reverb.Diffusion;
592 break;
594 case AL_REVERB_GAIN:
595 *pflValue = ALEffect->Reverb.Gain;
596 break;
598 case AL_REVERB_GAINHF:
599 *pflValue = ALEffect->Reverb.GainHF;
600 break;
602 case AL_REVERB_DECAY_TIME:
603 *pflValue = ALEffect->Reverb.DecayTime;
604 break;
606 case AL_REVERB_DECAY_HFRATIO:
607 *pflValue = ALEffect->Reverb.DecayHFRatio;
608 break;
610 case AL_REVERB_REFLECTIONS_GAIN:
611 *pflValue = ALEffect->Reverb.ReflectionsGain;
612 break;
614 case AL_REVERB_REFLECTIONS_DELAY:
615 *pflValue = ALEffect->Reverb.ReflectionsDelay;
616 break;
618 case AL_REVERB_LATE_REVERB_GAIN:
619 *pflValue = ALEffect->Reverb.LateReverbGain;
620 break;
622 case AL_REVERB_LATE_REVERB_DELAY:
623 *pflValue = ALEffect->Reverb.LateReverbDelay;
624 break;
626 case AL_REVERB_AIR_ABSORPTION_GAINHF:
627 *pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
628 break;
630 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
631 *pflValue = ALEffect->Reverb.RoomRolloffFactor;
632 break;
634 default:
635 alSetError(AL_INVALID_ENUM);
636 break;
639 else if(ALEffect->type == AL_EFFECT_ECHO)
641 switch(param)
643 case AL_ECHO_DELAY:
644 *pflValue = ALEffect->Echo.Delay;
645 break;
647 case AL_ECHO_LRDELAY:
648 *pflValue = ALEffect->Echo.LRDelay;
649 break;
651 case AL_ECHO_DAMPING:
652 *pflValue = ALEffect->Echo.Damping;
653 break;
655 case AL_ECHO_FEEDBACK:
656 *pflValue = ALEffect->Echo.Feedback;
657 break;
659 case AL_ECHO_SPREAD:
660 *pflValue = ALEffect->Echo.Spread;
661 break;
663 default:
664 alSetError(AL_INVALID_ENUM);
665 break;
668 else
669 alSetError(AL_INVALID_ENUM);
671 else
672 alSetError(AL_INVALID_NAME);
674 ProcessContext(Context);
677 ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
679 ALCcontext *Context;
681 Context = alcGetCurrentContext();
682 SuspendContext(Context);
684 if (effect && alIsEffect(effect))
686 ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
688 if(ALEffect->type == AL_EFFECT_REVERB)
690 switch(param)
692 case AL_REVERB_DENSITY:
693 case AL_REVERB_DIFFUSION:
694 case AL_REVERB_GAIN:
695 case AL_REVERB_GAINHF:
696 case AL_REVERB_DECAY_TIME:
697 case AL_REVERB_DECAY_HFRATIO:
698 case AL_REVERB_REFLECTIONS_GAIN:
699 case AL_REVERB_REFLECTIONS_DELAY:
700 case AL_REVERB_LATE_REVERB_GAIN:
701 case AL_REVERB_LATE_REVERB_DELAY:
702 case AL_REVERB_AIR_ABSORPTION_GAINHF:
703 case AL_REVERB_ROOM_ROLLOFF_FACTOR:
704 alGetEffectf(effect, param, pflValues);
705 break;
707 default:
708 alSetError(AL_INVALID_ENUM);
709 break;
712 else if(ALEffect->type == AL_EFFECT_ECHO)
714 switch(param)
716 case AL_ECHO_DELAY:
717 case AL_ECHO_LRDELAY:
718 case AL_ECHO_DAMPING:
719 case AL_ECHO_FEEDBACK:
720 case AL_ECHO_SPREAD:
721 alGetEffectf(effect, param, pflValues);
722 break;
724 default:
725 alSetError(AL_INVALID_ENUM);
726 break;
729 else
730 alSetError(AL_INVALID_ENUM);
732 else
733 alSetError(AL_INVALID_NAME);
735 ProcessContext(Context);
739 ALvoid ReleaseALEffects(ALvoid)
741 #ifdef _DEBUG
742 if(g_EffectCount > 0)
743 AL_PRINT("exit(): deleting %d Effect(s)\n", g_EffectCount);
744 #endif
746 while(g_EffectList)
748 ALeffect *temp = g_EffectList;
749 g_EffectList = g_EffectList->next;
751 // Release effect structure
752 memset(temp, 0, sizeof(ALeffect));
753 free(temp);
755 g_EffectCount = 0;
759 static void InitEffectParams(ALeffect *effect, ALenum type)
761 effect->type = type;
762 switch(type)
764 case AL_EFFECT_REVERB:
765 effect->Reverb.Density = 1.0f;
766 effect->Reverb.Diffusion = 1.0f;
767 effect->Reverb.Gain = 0.32f;
768 effect->Reverb.GainHF = 0.89f;
769 effect->Reverb.DecayTime = 1.49f;
770 effect->Reverb.DecayHFRatio = 0.83f;
771 effect->Reverb.ReflectionsGain = 0.05f;
772 effect->Reverb.ReflectionsDelay = 0.007f;
773 effect->Reverb.LateReverbGain = 1.26f;
774 effect->Reverb.LateReverbDelay = 0.011f;
775 effect->Reverb.AirAbsorptionGainHF = 0.994f;
776 effect->Reverb.RoomRolloffFactor = 0.0f;
777 effect->Reverb.DecayHFLimit = AL_TRUE;
778 break;
779 case AL_EFFECT_ECHO:
780 effect->Echo.Delay = AL_ECHO_DEFAULT_DELAY;
781 effect->Echo.LRDelay = AL_ECHO_DEFAULT_LRDELAY;
782 effect->Echo.Damping = AL_ECHO_DEFAULT_DAMPING;
783 effect->Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK;
784 effect->Echo.Spread = AL_ECHO_DEFAULT_SPREAD;
785 break;