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
29 #include "alAuxEffectSlot.h"
34 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*ALEffectSlot
, ALeffect
*effect
);
37 AL_API ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
42 Context
= alcGetCurrentContext();
45 alSetError(AL_INVALID_OPERATION
);
48 SuspendContext(Context
);
52 /* NOTE: We only support one slot currently */
53 if(n
== 1 && Context
->AuxiliaryEffectSlotCount
== 0)
55 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
56 if (!IsBadWritePtr((void*)effectslots
, n
* sizeof(ALuint
)))
58 ALeffectslot
**list
= &Context
->AuxiliaryEffectSlot
;
60 list
= &(*list
)->next
;
65 *list
= calloc(1, sizeof(ALeffectslot
));
68 // We must have run out or memory
69 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
70 alSetError(AL_OUT_OF_MEMORY
);
75 (*list
)->AuxSendAuto
= AL_TRUE
;
76 (*list
)->refcount
= 0;
78 effectslots
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
79 (*list
)->effectslot
= effectslots
[i
];
81 Context
->AuxiliaryEffectSlotCount
++;
84 list
= &(*list
)->next
;
89 alSetError(AL_INVALID_OPERATION
);
92 ProcessContext(Context
);
95 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
98 ALeffectslot
*ALAuxiliaryEffectSlot
;
101 Context
= alcGetCurrentContext();
104 alSetError(AL_INVALID_OPERATION
);
107 SuspendContext(Context
);
111 // Check that all effectslots are valid
112 for (i
= 0; i
< n
; i
++)
114 if (!alIsAuxiliaryEffectSlot(effectslots
[i
]))
116 alSetError(AL_INVALID_NAME
);
121 ALAuxiliaryEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslots
[i
]);
122 if(ALAuxiliaryEffectSlot
->refcount
> 0)
124 alSetError(AL_INVALID_NAME
);
132 // All effectslots are valid
133 for (i
= 0; i
< n
; i
++)
135 // Recheck that the effectslot is valid, because there could be duplicated names
136 if (alIsAuxiliaryEffectSlot(effectslots
[i
]))
140 ALAuxiliaryEffectSlot
= ((ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslots
[i
]));
142 // Remove Source from list of Sources
143 list
= &Context
->AuxiliaryEffectSlot
;
144 while(*list
&& *list
!= ALAuxiliaryEffectSlot
)
145 list
= &(*list
)->next
;
148 *list
= (*list
)->next
;
149 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot
->effectslot
);
151 free(ALAuxiliaryEffectSlot
->ReverbBuffer
);
153 memset(ALAuxiliaryEffectSlot
, 0, sizeof(ALeffectslot
));
154 free(ALAuxiliaryEffectSlot
);
156 Context
->AuxiliaryEffectSlotCount
--;
162 alSetError(AL_INVALID_VALUE
);
164 ProcessContext(Context
);
167 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
172 Context
= alcGetCurrentContext();
175 alSetError(AL_INVALID_OPERATION
);
178 SuspendContext(Context
);
180 list
= &Context
->AuxiliaryEffectSlot
;
181 while(*list
&& (*list
)->effectslot
!= effectslot
)
182 list
= &(*list
)->next
;
184 ProcessContext(Context
);
186 return (*list
? AL_TRUE
: AL_FALSE
);
189 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
193 Context
= alcGetCurrentContext();
196 alSetError(AL_INVALID_OPERATION
);
199 SuspendContext(Context
);
201 if (alIsAuxiliaryEffectSlot(effectslot
))
203 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
207 case AL_EFFECTSLOT_EFFECT
:
208 if(alIsEffect(iValue
))
210 ALeffect
*effect
= (ALeffect
*)ALTHUNK_LOOKUPENTRY(iValue
);
211 InitializeEffect(Context
, ALEffectSlot
, effect
);
214 alSetError(AL_INVALID_VALUE
);
217 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
218 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
219 ALEffectSlot
->AuxSendAuto
= iValue
;
221 alSetError(AL_INVALID_VALUE
);
225 alSetError(AL_INVALID_ENUM
);
230 alSetError(AL_INVALID_NAME
);
232 ProcessContext(Context
);
235 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
239 Context
= alcGetCurrentContext();
242 alSetError(AL_INVALID_OPERATION
);
245 SuspendContext(Context
);
247 if (alIsAuxiliaryEffectSlot(effectslot
))
251 case AL_EFFECTSLOT_EFFECT
:
252 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
253 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
257 alSetError(AL_INVALID_ENUM
);
262 alSetError(AL_INVALID_NAME
);
264 ProcessContext(Context
);
267 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
271 Context
= alcGetCurrentContext();
274 alSetError(AL_INVALID_OPERATION
);
277 SuspendContext(Context
);
279 if (alIsAuxiliaryEffectSlot(effectslot
))
281 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
285 case AL_EFFECTSLOT_GAIN
:
286 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
287 ALEffectSlot
->Gain
= flValue
;
289 alSetError(AL_INVALID_VALUE
);
293 alSetError(AL_INVALID_ENUM
);
298 alSetError(AL_INVALID_NAME
);
300 ProcessContext(Context
);
303 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
307 Context
= alcGetCurrentContext();
310 alSetError(AL_INVALID_OPERATION
);
313 SuspendContext(Context
);
315 if (alIsAuxiliaryEffectSlot(effectslot
))
319 case AL_EFFECTSLOT_GAIN
:
320 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
324 alSetError(AL_INVALID_ENUM
);
329 alSetError(AL_INVALID_NAME
);
331 ProcessContext(Context
);
334 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
338 Context
= alcGetCurrentContext();
341 alSetError(AL_INVALID_OPERATION
);
344 SuspendContext(Context
);
346 if (alIsAuxiliaryEffectSlot(effectslot
))
348 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
352 case AL_EFFECTSLOT_EFFECT
:
353 *piValue
= ALEffectSlot
->effect
.effect
;
356 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
357 *piValue
= ALEffectSlot
->AuxSendAuto
;
361 alSetError(AL_INVALID_ENUM
);
366 alSetError(AL_INVALID_NAME
);
368 ProcessContext(Context
);
371 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
375 Context
= alcGetCurrentContext();
378 alSetError(AL_INVALID_OPERATION
);
381 SuspendContext(Context
);
383 if (alIsAuxiliaryEffectSlot(effectslot
))
387 case AL_EFFECTSLOT_EFFECT
:
388 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
389 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
393 alSetError(AL_INVALID_ENUM
);
398 alSetError(AL_INVALID_NAME
);
400 ProcessContext(Context
);
403 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
407 Context
= alcGetCurrentContext();
410 alSetError(AL_INVALID_OPERATION
);
413 SuspendContext(Context
);
415 if (alIsAuxiliaryEffectSlot(effectslot
))
417 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
421 case AL_EFFECTSLOT_GAIN
:
422 *pflValue
= ALEffectSlot
->Gain
;
426 alSetError(AL_INVALID_ENUM
);
431 alSetError(AL_INVALID_NAME
);
433 ProcessContext(Context
);
436 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
440 Context
= alcGetCurrentContext();
443 alSetError(AL_INVALID_OPERATION
);
446 SuspendContext(Context
);
448 if (alIsAuxiliaryEffectSlot(effectslot
))
452 case AL_EFFECTSLOT_GAIN
:
453 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
457 alSetError(AL_INVALID_ENUM
);
462 alSetError(AL_INVALID_NAME
);
464 ProcessContext(Context
);
468 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*ALEffectSlot
, ALeffect
*effect
)
474 memset(&ALEffectSlot
->effect
, 0, sizeof(ALEffectSlot
->effect
));
478 if(effect
->type
== AL_EFFECT_REVERB
)
483 reverbwait
= (1.0f
-effect
->Reverb
.Density
)*(0.1f
-0.075f
) + 0.075f
;
485 size
= (ALuint
)((ALfloat
)Context
->Frequency
*
486 (effect
->Reverb
.ReflectionsDelay
+
487 effect
->Reverb
.LateReverbDelay
+
490 ptr
= calloc(size
, sizeof(ALfloat
));
493 alSetError(AL_OUT_OF_MEMORY
);
496 ALEffectSlot
->ReverbLength
= size
;
497 ALEffectSlot
->ReverbPos
= 0;
498 ALEffectSlot
->ReverbReflectPos
= (ALuint
)(ALEffectSlot
->ReverbLength
-
499 ((ALfloat
)Context
->Frequency
*
500 effect
->Reverb
.ReflectionsDelay
)) %
501 ALEffectSlot
->ReverbLength
;
502 ALEffectSlot
->ReverbLatePos
= (ALuint
)(ALEffectSlot
->ReverbLength
-
503 ((ALfloat
)Context
->Frequency
*
504 (effect
->Reverb
.LateReverbDelay
+
505 effect
->Reverb
.ReflectionsDelay
))) %
506 ALEffectSlot
->ReverbLength
;
507 ALEffectSlot
->ReverbDecayGain
= pow(1.0/32768.0, 1.0/(effect
->Reverb
.DecayTime
/reverbwait
));
510 memcpy(&ALEffectSlot
->effect
, effect
, sizeof(*effect
));
512 free(ALEffectSlot
->ReverbBuffer
);
513 ALEffectSlot
->ReverbBuffer
= ptr
;
517 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
520 if(Context
->AuxiliaryEffectSlotCount
> 0)
521 AL_PRINT("alcDestroyContext(): %d AuxiliaryEffectSlot(s) NOT deleted\n", Context
->AuxiliaryEffectSlotCount
);
524 while(Context
->AuxiliaryEffectSlot
)
526 ALeffectslot
*temp
= Context
->AuxiliaryEffectSlot
;
527 Context
->AuxiliaryEffectSlot
= Context
->AuxiliaryEffectSlot
->next
;
529 // Release effectslot structure
530 free(temp
->ReverbBuffer
);
531 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
533 memset(temp
, 0, sizeof(ALeffectslot
));
536 Context
->AuxiliaryEffectSlotCount
= 0;