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
);
74 InitLowPassFilter(Context
, &(*list
)->iirFilter
);
77 (*list
)->AuxSendAuto
= AL_TRUE
;
78 (*list
)->refcount
= 0;
80 effectslots
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
81 (*list
)->effectslot
= effectslots
[i
];
83 Context
->AuxiliaryEffectSlotCount
++;
86 list
= &(*list
)->next
;
91 alSetError(AL_INVALID_OPERATION
);
94 ProcessContext(Context
);
97 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
100 ALeffectslot
*ALAuxiliaryEffectSlot
;
103 Context
= alcGetCurrentContext();
106 alSetError(AL_INVALID_OPERATION
);
109 SuspendContext(Context
);
113 // Check that all effectslots are valid
114 for (i
= 0; i
< n
; i
++)
116 if (!alIsAuxiliaryEffectSlot(effectslots
[i
]))
118 alSetError(AL_INVALID_NAME
);
123 ALAuxiliaryEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslots
[i
]);
124 if(ALAuxiliaryEffectSlot
->refcount
> 0)
126 alSetError(AL_INVALID_NAME
);
134 // All effectslots are valid
135 for (i
= 0; i
< n
; i
++)
137 // Recheck that the effectslot is valid, because there could be duplicated names
138 if (alIsAuxiliaryEffectSlot(effectslots
[i
]))
142 ALAuxiliaryEffectSlot
= ((ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslots
[i
]));
144 // Remove Source from list of Sources
145 list
= &Context
->AuxiliaryEffectSlot
;
146 while(*list
&& *list
!= ALAuxiliaryEffectSlot
)
147 list
= &(*list
)->next
;
150 *list
= (*list
)->next
;
151 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot
->effectslot
);
153 free(ALAuxiliaryEffectSlot
->ReverbBuffer
);
155 memset(ALAuxiliaryEffectSlot
, 0, sizeof(ALeffectslot
));
156 free(ALAuxiliaryEffectSlot
);
158 Context
->AuxiliaryEffectSlotCount
--;
164 alSetError(AL_INVALID_VALUE
);
166 ProcessContext(Context
);
169 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
174 Context
= alcGetCurrentContext();
177 alSetError(AL_INVALID_OPERATION
);
180 SuspendContext(Context
);
182 list
= &Context
->AuxiliaryEffectSlot
;
183 while(*list
&& (*list
)->effectslot
!= effectslot
)
184 list
= &(*list
)->next
;
186 ProcessContext(Context
);
188 return (*list
? AL_TRUE
: AL_FALSE
);
191 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
195 Context
= alcGetCurrentContext();
198 alSetError(AL_INVALID_OPERATION
);
201 SuspendContext(Context
);
203 if (alIsAuxiliaryEffectSlot(effectslot
))
205 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
209 case AL_EFFECTSLOT_EFFECT
:
210 if(alIsEffect(iValue
))
212 ALeffect
*effect
= (ALeffect
*)ALTHUNK_LOOKUPENTRY(iValue
);
213 InitializeEffect(Context
, ALEffectSlot
, effect
);
216 alSetError(AL_INVALID_VALUE
);
219 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
220 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
221 ALEffectSlot
->AuxSendAuto
= iValue
;
223 alSetError(AL_INVALID_VALUE
);
227 alSetError(AL_INVALID_ENUM
);
232 alSetError(AL_INVALID_NAME
);
234 ProcessContext(Context
);
237 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
241 Context
= alcGetCurrentContext();
244 alSetError(AL_INVALID_OPERATION
);
247 SuspendContext(Context
);
249 if (alIsAuxiliaryEffectSlot(effectslot
))
253 case AL_EFFECTSLOT_EFFECT
:
254 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
255 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
259 alSetError(AL_INVALID_ENUM
);
264 alSetError(AL_INVALID_NAME
);
266 ProcessContext(Context
);
269 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
273 Context
= alcGetCurrentContext();
276 alSetError(AL_INVALID_OPERATION
);
279 SuspendContext(Context
);
281 if (alIsAuxiliaryEffectSlot(effectslot
))
283 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
287 case AL_EFFECTSLOT_GAIN
:
288 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
289 ALEffectSlot
->Gain
= flValue
;
291 alSetError(AL_INVALID_VALUE
);
295 alSetError(AL_INVALID_ENUM
);
300 alSetError(AL_INVALID_NAME
);
302 ProcessContext(Context
);
305 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
309 Context
= alcGetCurrentContext();
312 alSetError(AL_INVALID_OPERATION
);
315 SuspendContext(Context
);
317 if (alIsAuxiliaryEffectSlot(effectslot
))
321 case AL_EFFECTSLOT_GAIN
:
322 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
326 alSetError(AL_INVALID_ENUM
);
331 alSetError(AL_INVALID_NAME
);
333 ProcessContext(Context
);
336 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
340 Context
= alcGetCurrentContext();
343 alSetError(AL_INVALID_OPERATION
);
346 SuspendContext(Context
);
348 if (alIsAuxiliaryEffectSlot(effectslot
))
350 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
354 case AL_EFFECTSLOT_EFFECT
:
355 *piValue
= ALEffectSlot
->effect
.effect
;
358 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
359 *piValue
= ALEffectSlot
->AuxSendAuto
;
363 alSetError(AL_INVALID_ENUM
);
368 alSetError(AL_INVALID_NAME
);
370 ProcessContext(Context
);
373 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
377 Context
= alcGetCurrentContext();
380 alSetError(AL_INVALID_OPERATION
);
383 SuspendContext(Context
);
385 if (alIsAuxiliaryEffectSlot(effectslot
))
389 case AL_EFFECTSLOT_EFFECT
:
390 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
391 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
395 alSetError(AL_INVALID_ENUM
);
400 alSetError(AL_INVALID_NAME
);
402 ProcessContext(Context
);
405 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
409 Context
= alcGetCurrentContext();
412 alSetError(AL_INVALID_OPERATION
);
415 SuspendContext(Context
);
417 if (alIsAuxiliaryEffectSlot(effectslot
))
419 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
423 case AL_EFFECTSLOT_GAIN
:
424 *pflValue
= ALEffectSlot
->Gain
;
428 alSetError(AL_INVALID_ENUM
);
433 alSetError(AL_INVALID_NAME
);
435 ProcessContext(Context
);
438 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
442 Context
= alcGetCurrentContext();
445 alSetError(AL_INVALID_OPERATION
);
448 SuspendContext(Context
);
450 if (alIsAuxiliaryEffectSlot(effectslot
))
454 case AL_EFFECTSLOT_GAIN
:
455 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
459 alSetError(AL_INVALID_ENUM
);
464 alSetError(AL_INVALID_NAME
);
466 ProcessContext(Context
);
470 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*ALEffectSlot
, ALeffect
*effect
)
476 memset(&ALEffectSlot
->effect
, 0, sizeof(ALEffectSlot
->effect
));
480 if(effect
->type
== AL_EFFECT_REVERB
)
485 reverbwait
= (1.0f
-effect
->Reverb
.Density
)*(0.1f
-0.075f
) + 0.075f
;
487 size
= (ALuint
)((ALfloat
)Context
->Frequency
*
488 (effect
->Reverb
.ReflectionsDelay
+
489 effect
->Reverb
.LateReverbDelay
+
492 ptr
= calloc(size
, sizeof(ALfloat
));
495 alSetError(AL_OUT_OF_MEMORY
);
498 if(ALEffectSlot
->ReverbBuffer
)
499 memcpy(ptr
, ALEffectSlot
->ReverbBuffer
, min(size
, ALEffectSlot
->ReverbLength
)*sizeof(ALfloat
));
500 ALEffectSlot
->ReverbLength
= size
;
501 ALEffectSlot
->ReverbPos
%= size
;
502 ALEffectSlot
->ReverbReflectPos
= (ALuint
)(ALEffectSlot
->ReverbLength
-
503 ((ALfloat
)Context
->Frequency
*
504 effect
->Reverb
.ReflectionsDelay
) +
505 ALEffectSlot
->ReverbPos
) %
506 ALEffectSlot
->ReverbLength
;
507 ALEffectSlot
->ReverbLatePos
= (ALuint
)(ALEffectSlot
->ReverbLength
-
508 ((ALfloat
)Context
->Frequency
*
509 (effect
->Reverb
.LateReverbDelay
+
510 effect
->Reverb
.ReflectionsDelay
)) +
511 ALEffectSlot
->ReverbPos
) %
512 ALEffectSlot
->ReverbLength
;
513 ALEffectSlot
->ReverbDecayGain
= pow(1.0/32768.0, 1.0/(effect
->Reverb
.DecayTime
/reverbwait
));
516 memcpy(&ALEffectSlot
->effect
, effect
, sizeof(*effect
));
518 free(ALEffectSlot
->ReverbBuffer
);
519 ALEffectSlot
->ReverbBuffer
= ptr
;
523 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
526 if(Context
->AuxiliaryEffectSlotCount
> 0)
527 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context
->AuxiliaryEffectSlotCount
);
530 while(Context
->AuxiliaryEffectSlot
)
532 ALeffectslot
*temp
= Context
->AuxiliaryEffectSlot
;
533 Context
->AuxiliaryEffectSlot
= Context
->AuxiliaryEffectSlot
->next
;
535 // Release effectslot structure
536 free(temp
->ReverbBuffer
);
537 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
539 memset(temp
, 0, sizeof(ALeffectslot
));
542 Context
->AuxiliaryEffectSlotCount
= 0;