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
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
)
47 Context
= alcGetCurrentContext();
48 SuspendContext(Context
);
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
;
57 list
= &(*list
)->next
;
62 *list
= calloc(1, sizeof(ALeffect
));
65 // We must have run out or memory
66 alDeleteEffects(i
, effects
);
67 alSetError(AL_OUT_OF_MEMORY
);
71 effects
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
72 (*list
)->effect
= effects
[i
];
74 InitEffectParams(*list
, AL_EFFECT_NULL
);
78 list
= &(*list
)->next
;
83 ProcessContext(Context
);
86 ALvoid AL_APIENTRY
alDeleteEffects(ALsizei n
, ALuint
*effects
)
92 Context
= alcGetCurrentContext();
93 SuspendContext(Context
);
97 // Check that all effects are valid
98 for (i
= 0; i
< n
; i
++)
100 if (!alIsEffect(effects
[i
]))
102 alSetError(AL_INVALID_NAME
);
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
]))
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
;
125 *list
= (*list
)->next
;
126 ALTHUNK_REMOVEENTRY(ALEffect
->effect
);
128 memset(ALEffect
, 0, sizeof(ALeffect
));
137 alSetError(AL_INVALID_VALUE
);
139 ProcessContext(Context
);
142 ALboolean AL_APIENTRY
alIsEffect(ALuint effect
)
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
)
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
]));
177 InitEffectParams(ALEffect
, iValue
);
179 alSetError(AL_INVALID_VALUE
);
181 else if(ALEffect
->type
== AL_EFFECT_REVERB
)
185 case AL_REVERB_DECAY_HFLIMIT
:
186 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
187 ALEffect
->Reverb
.DecayHFLimit
= iValue
;
189 alSetError(AL_INVALID_VALUE
);
193 alSetError(AL_INVALID_ENUM
);
197 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
202 alSetError(AL_INVALID_ENUM
);
207 alSetError(AL_INVALID_ENUM
);
210 alSetError(AL_INVALID_NAME
);
212 ProcessContext(Context
);
215 ALvoid AL_APIENTRY
alEffectiv(ALuint effect
, ALenum param
, ALint
*piValues
)
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
)
234 case AL_REVERB_DECAY_HFLIMIT
:
235 alEffecti(effect
, param
, piValues
[0]);
239 alSetError(AL_INVALID_ENUM
);
243 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
248 alSetError(AL_INVALID_ENUM
);
253 alSetError(AL_INVALID_ENUM
);
256 alSetError(AL_INVALID_NAME
);
258 ProcessContext(Context
);
261 ALvoid AL_APIENTRY
alEffectf(ALuint effect
, ALenum param
, ALfloat flValue
)
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
)
276 case AL_REVERB_DENSITY
:
277 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
278 ALEffect
->Reverb
.Density
= flValue
;
280 alSetError(AL_INVALID_VALUE
);
283 case AL_REVERB_DIFFUSION
:
284 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
285 ALEffect
->Reverb
.Diffusion
= flValue
;
287 alSetError(AL_INVALID_VALUE
);
291 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
292 ALEffect
->Reverb
.Gain
= flValue
;
294 alSetError(AL_INVALID_VALUE
);
297 case AL_REVERB_GAINHF
:
298 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
299 ALEffect
->Reverb
.GainHF
= flValue
;
301 alSetError(AL_INVALID_VALUE
);
304 case AL_REVERB_DECAY_TIME
:
305 if(flValue
>= 0.1f
&& flValue
<= 20.0f
)
306 ALEffect
->Reverb
.DecayTime
= flValue
;
308 alSetError(AL_INVALID_VALUE
);
311 case AL_REVERB_DECAY_HFRATIO
:
312 if(flValue
>= 0.1f
&& flValue
<= 2.0f
)
313 ALEffect
->Reverb
.DecayHFRatio
= flValue
;
315 alSetError(AL_INVALID_VALUE
);
318 case AL_REVERB_REFLECTIONS_GAIN
:
319 if(flValue
>= 0.0f
&& flValue
<= 3.16f
)
320 ALEffect
->Reverb
.ReflectionsGain
= flValue
;
322 alSetError(AL_INVALID_VALUE
);
325 case AL_REVERB_REFLECTIONS_DELAY
:
326 if(flValue
>= 0.0f
&& flValue
<= 0.3f
)
327 ALEffect
->Reverb
.ReflectionsDelay
= flValue
;
329 alSetError(AL_INVALID_VALUE
);
332 case AL_REVERB_LATE_REVERB_GAIN
:
333 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
334 ALEffect
->Reverb
.LateReverbGain
= flValue
;
336 alSetError(AL_INVALID_VALUE
);
339 case AL_REVERB_LATE_REVERB_DELAY
:
340 if(flValue
>= 0.0f
&& flValue
<= 0.1f
)
341 ALEffect
->Reverb
.LateReverbDelay
= flValue
;
343 alSetError(AL_INVALID_VALUE
);
346 case AL_REVERB_AIR_ABSORPTION_GAINHF
:
347 if(flValue
>= 0.892f
&& flValue
<= 1.0f
)
348 ALEffect
->Reverb
.AirAbsorptionGainHF
= flValue
;
350 alSetError(AL_INVALID_VALUE
);
353 case AL_REVERB_ROOM_ROLLOFF_FACTOR
:
354 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
355 ALEffect
->Reverb
.RoomRolloffFactor
= flValue
;
357 alSetError(AL_INVALID_VALUE
);
361 alSetError(AL_INVALID_ENUM
);
365 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
370 if(flValue
>= AL_ECHO_MIN_DELAY
&& flValue
<= AL_ECHO_MAX_DELAY
)
371 ALEffect
->Echo
.Delay
= flValue
;
373 alSetError(AL_INVALID_VALUE
);
376 case AL_ECHO_LRDELAY
:
377 if(flValue
>= AL_ECHO_MIN_LRDELAY
&& flValue
<= AL_ECHO_MAX_LRDELAY
)
378 ALEffect
->Echo
.LRDelay
= flValue
;
380 alSetError(AL_INVALID_VALUE
);
383 case AL_ECHO_DAMPING
:
384 if(flValue
>= AL_ECHO_MIN_DAMPING
&& flValue
<= AL_ECHO_MAX_DAMPING
)
385 ALEffect
->Echo
.Damping
= flValue
;
387 alSetError(AL_INVALID_VALUE
);
390 case AL_ECHO_FEEDBACK
:
391 if(flValue
>= AL_ECHO_MIN_FEEDBACK
&& flValue
<= AL_ECHO_MAX_FEEDBACK
)
392 ALEffect
->Echo
.Feedback
= flValue
;
394 alSetError(AL_INVALID_VALUE
);
398 if(flValue
>= AL_ECHO_MIN_SPREAD
&& flValue
<= AL_ECHO_MAX_SPREAD
)
399 ALEffect
->Echo
.Spread
= flValue
;
401 alSetError(AL_INVALID_VALUE
);
405 alSetError(AL_INVALID_ENUM
);
410 alSetError(AL_INVALID_ENUM
);
413 alSetError(AL_INVALID_NAME
);
415 ProcessContext(Context
);
418 ALvoid AL_APIENTRY
alEffectfv(ALuint effect
, ALenum param
, ALfloat
*pflValues
)
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
)
433 case AL_REVERB_DENSITY
:
434 case AL_REVERB_DIFFUSION
:
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]);
449 alSetError(AL_INVALID_ENUM
);
453 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
458 case AL_ECHO_LRDELAY
:
459 case AL_ECHO_DAMPING
:
460 case AL_ECHO_FEEDBACK
:
462 alEffectf(effect
, param
, pflValues
[0]);
466 alSetError(AL_INVALID_ENUM
);
471 alSetError(AL_INVALID_ENUM
);
474 alSetError(AL_INVALID_NAME
);
476 ProcessContext(Context
);
479 ALvoid AL_APIENTRY
alGetEffecti(ALuint effect
, ALenum param
, ALint
*piValue
)
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
)
498 case AL_REVERB_DECAY_HFLIMIT
:
499 *piValue
= ALEffect
->Reverb
.DecayHFLimit
;
503 alSetError(AL_INVALID_ENUM
);
507 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
512 alSetError(AL_INVALID_ENUM
);
517 alSetError(AL_INVALID_ENUM
);
520 alSetError(AL_INVALID_NAME
);
522 ProcessContext(Context
);
525 ALvoid AL_APIENTRY
alGetEffectiv(ALuint effect
, ALenum param
, ALint
*piValues
)
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
)
544 case AL_REVERB_DECAY_HFLIMIT
:
545 alGetEffecti(effect
, param
, piValues
);
549 alSetError(AL_INVALID_ENUM
);
553 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
558 alSetError(AL_INVALID_ENUM
);
563 alSetError(AL_INVALID_ENUM
);
566 alSetError(AL_INVALID_NAME
);
568 ProcessContext(Context
);
571 ALvoid AL_APIENTRY
alGetEffectf(ALuint effect
, ALenum param
, ALfloat
*pflValue
)
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
)
586 case AL_REVERB_DENSITY
:
587 *pflValue
= ALEffect
->Reverb
.Density
;
590 case AL_REVERB_DIFFUSION
:
591 *pflValue
= ALEffect
->Reverb
.Diffusion
;
595 *pflValue
= ALEffect
->Reverb
.Gain
;
598 case AL_REVERB_GAINHF
:
599 *pflValue
= ALEffect
->Reverb
.GainHF
;
602 case AL_REVERB_DECAY_TIME
:
603 *pflValue
= ALEffect
->Reverb
.DecayTime
;
606 case AL_REVERB_DECAY_HFRATIO
:
607 *pflValue
= ALEffect
->Reverb
.DecayHFRatio
;
610 case AL_REVERB_REFLECTIONS_GAIN
:
611 *pflValue
= ALEffect
->Reverb
.ReflectionsGain
;
614 case AL_REVERB_REFLECTIONS_DELAY
:
615 *pflValue
= ALEffect
->Reverb
.ReflectionsDelay
;
618 case AL_REVERB_LATE_REVERB_GAIN
:
619 *pflValue
= ALEffect
->Reverb
.LateReverbGain
;
622 case AL_REVERB_LATE_REVERB_DELAY
:
623 *pflValue
= ALEffect
->Reverb
.LateReverbDelay
;
626 case AL_REVERB_AIR_ABSORPTION_GAINHF
:
627 *pflValue
= ALEffect
->Reverb
.AirAbsorptionGainHF
;
630 case AL_REVERB_ROOM_ROLLOFF_FACTOR
:
631 *pflValue
= ALEffect
->Reverb
.RoomRolloffFactor
;
635 alSetError(AL_INVALID_ENUM
);
639 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
644 *pflValue
= ALEffect
->Echo
.Delay
;
647 case AL_ECHO_LRDELAY
:
648 *pflValue
= ALEffect
->Echo
.LRDelay
;
651 case AL_ECHO_DAMPING
:
652 *pflValue
= ALEffect
->Echo
.Damping
;
655 case AL_ECHO_FEEDBACK
:
656 *pflValue
= ALEffect
->Echo
.Feedback
;
660 *pflValue
= ALEffect
->Echo
.Spread
;
664 alSetError(AL_INVALID_ENUM
);
669 alSetError(AL_INVALID_ENUM
);
672 alSetError(AL_INVALID_NAME
);
674 ProcessContext(Context
);
677 ALvoid AL_APIENTRY
alGetEffectfv(ALuint effect
, ALenum param
, ALfloat
*pflValues
)
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
)
692 case AL_REVERB_DENSITY
:
693 case AL_REVERB_DIFFUSION
:
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
);
708 alSetError(AL_INVALID_ENUM
);
712 else if(ALEffect
->type
== AL_EFFECT_ECHO
)
717 case AL_ECHO_LRDELAY
:
718 case AL_ECHO_DAMPING
:
719 case AL_ECHO_FEEDBACK
:
721 alGetEffectf(effect
, param
, pflValues
);
725 alSetError(AL_INVALID_ENUM
);
730 alSetError(AL_INVALID_ENUM
);
733 alSetError(AL_INVALID_NAME
);
735 ProcessContext(Context
);
739 ALvoid
ReleaseALEffects(ALvoid
)
742 if(g_EffectCount
> 0)
743 AL_PRINT("exit(): deleting %d Effect(s)\n", g_EffectCount
);
748 ALeffect
*temp
= g_EffectList
;
749 g_EffectList
= g_EffectList
->next
;
751 // Release effect structure
752 memset(temp
, 0, sizeof(ALeffect
));
759 static void InitEffectParams(ALeffect
*effect
, ALenum 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
;
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
;