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"
35 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*ALEffectSlot
, ALeffect
*effect
);
38 ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
43 Context
= GetContextSuspended();
48 ALCdevice
*Device
= Context
->Device
;
50 if(Context
->AuxiliaryEffectSlotCount
+n
<= Device
->AuxiliaryEffectSlotMax
)
52 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
53 if (!IsBadWritePtr((void*)effectslots
, n
* sizeof(ALuint
)))
55 ALeffectslot
**list
= &Context
->AuxiliaryEffectSlot
;
57 list
= &(*list
)->next
;
62 *list
= calloc(1, sizeof(ALeffectslot
));
63 if(!(*list
) || !((*list
)->EffectState
=NoneCreate()))
65 // We must have run out or memory
66 free(*list
); *list
= NULL
;
67 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
68 alSetError(AL_OUT_OF_MEMORY
);
73 (*list
)->AuxSendAuto
= AL_TRUE
;
74 for(j
= 0;j
< BUFFERSIZE
;j
++)
75 (*list
)->WetBuffer
[j
] = 0.0f
;
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 ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
98 ALeffectslot
*ALAuxiliaryEffectSlot
;
101 Context
= GetContextSuspended();
106 // Check that all effectslots are valid
107 for (i
= 0; i
< n
; i
++)
109 if (!alIsAuxiliaryEffectSlot(effectslots
[i
]))
111 alSetError(AL_INVALID_NAME
);
116 ALAuxiliaryEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslots
[i
]);
117 if(ALAuxiliaryEffectSlot
->refcount
> 0)
119 alSetError(AL_INVALID_NAME
);
127 // All effectslots are valid
128 for (i
= 0; i
< n
; i
++)
130 // Recheck that the effectslot is valid, because there could be duplicated names
131 if (alIsAuxiliaryEffectSlot(effectslots
[i
]))
135 ALAuxiliaryEffectSlot
= ((ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslots
[i
]));
137 // Remove Source from list of Sources
138 list
= &Context
->AuxiliaryEffectSlot
;
139 while(*list
&& *list
!= ALAuxiliaryEffectSlot
)
140 list
= &(*list
)->next
;
143 *list
= (*list
)->next
;
144 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot
->effectslot
);
146 if(ALAuxiliaryEffectSlot
->EffectState
)
147 ALEffect_Destroy(ALAuxiliaryEffectSlot
->EffectState
);
149 memset(ALAuxiliaryEffectSlot
, 0, sizeof(ALeffectslot
));
150 free(ALAuxiliaryEffectSlot
);
152 Context
->AuxiliaryEffectSlotCount
--;
158 alSetError(AL_INVALID_VALUE
);
160 ProcessContext(Context
);
163 ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
168 Context
= GetContextSuspended();
169 if(!Context
) return AL_FALSE
;
171 list
= &Context
->AuxiliaryEffectSlot
;
172 while(*list
&& (*list
)->effectslot
!= effectslot
)
173 list
= &(*list
)->next
;
175 ProcessContext(Context
);
177 return (*list
? AL_TRUE
: AL_FALSE
);
180 ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
183 ALboolean updateSources
= AL_FALSE
;
185 Context
= GetContextSuspended();
188 if (alIsAuxiliaryEffectSlot(effectslot
))
190 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
194 case AL_EFFECTSLOT_EFFECT
:
195 if(alIsEffect(iValue
))
197 ALeffect
*effect
= (ALeffect
*)ALTHUNK_LOOKUPENTRY(iValue
);
198 InitializeEffect(Context
, ALEffectSlot
, effect
);
199 updateSources
= AL_TRUE
;
202 alSetError(AL_INVALID_VALUE
);
205 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
206 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
208 ALEffectSlot
->AuxSendAuto
= iValue
;
209 updateSources
= AL_TRUE
;
212 alSetError(AL_INVALID_VALUE
);
216 alSetError(AL_INVALID_ENUM
);
221 alSetError(AL_INVALID_NAME
);
223 // Force updating the sources that use this slot, since it affects the
224 // sending parameters
227 ALsource
*source
= Context
->Source
;
231 for(i
= 0;i
< MAX_SENDS
;i
++)
233 if(!source
->Send
[i
].Slot
||
234 source
->Send
[i
].Slot
->effectslot
!= effectslot
)
236 source
->NeedsUpdate
= AL_TRUE
;
239 source
= source
->next
;
243 ProcessContext(Context
);
246 ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
250 Context
= GetContextSuspended();
253 if (alIsAuxiliaryEffectSlot(effectslot
))
257 case AL_EFFECTSLOT_EFFECT
:
258 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
259 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
263 alSetError(AL_INVALID_ENUM
);
268 alSetError(AL_INVALID_NAME
);
270 ProcessContext(Context
);
273 ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
277 Context
= GetContextSuspended();
280 if (alIsAuxiliaryEffectSlot(effectslot
))
282 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
286 case AL_EFFECTSLOT_GAIN
:
287 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
288 ALEffectSlot
->Gain
= flValue
;
290 alSetError(AL_INVALID_VALUE
);
294 alSetError(AL_INVALID_ENUM
);
299 alSetError(AL_INVALID_NAME
);
301 ProcessContext(Context
);
304 ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
308 Context
= GetContextSuspended();
311 if (alIsAuxiliaryEffectSlot(effectslot
))
315 case AL_EFFECTSLOT_GAIN
:
316 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
320 alSetError(AL_INVALID_ENUM
);
325 alSetError(AL_INVALID_NAME
);
327 ProcessContext(Context
);
330 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
334 Context
= GetContextSuspended();
337 if (alIsAuxiliaryEffectSlot(effectslot
))
339 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
343 case AL_EFFECTSLOT_EFFECT
:
344 *piValue
= ALEffectSlot
->effect
.effect
;
347 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
348 *piValue
= ALEffectSlot
->AuxSendAuto
;
352 alSetError(AL_INVALID_ENUM
);
357 alSetError(AL_INVALID_NAME
);
359 ProcessContext(Context
);
362 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
366 Context
= GetContextSuspended();
369 if (alIsAuxiliaryEffectSlot(effectslot
))
373 case AL_EFFECTSLOT_EFFECT
:
374 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
375 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
379 alSetError(AL_INVALID_ENUM
);
384 alSetError(AL_INVALID_NAME
);
386 ProcessContext(Context
);
389 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
393 Context
= GetContextSuspended();
396 if (alIsAuxiliaryEffectSlot(effectslot
))
398 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(effectslot
);
402 case AL_EFFECTSLOT_GAIN
:
403 *pflValue
= ALEffectSlot
->Gain
;
407 alSetError(AL_INVALID_ENUM
);
412 alSetError(AL_INVALID_NAME
);
414 ProcessContext(Context
);
417 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
421 Context
= GetContextSuspended();
424 if (alIsAuxiliaryEffectSlot(effectslot
))
428 case AL_EFFECTSLOT_GAIN
:
429 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
433 alSetError(AL_INVALID_ENUM
);
438 alSetError(AL_INVALID_NAME
);
440 ProcessContext(Context
);
444 static ALvoid
NoneDestroy(ALeffectState
*State
)
446 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
452 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffect
*Effect
)
458 static ALvoid
NoneProcess(ALeffectState
*State
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
466 ALeffectState
*NoneCreate(void)
468 ALeffectState
*state
;
470 state
= calloc(1, sizeof(*state
));
473 alSetError(AL_OUT_OF_MEMORY
);
477 state
->Destroy
= NoneDestroy
;
478 state
->DeviceUpdate
= NoneDeviceUpdate
;
479 state
->Update
= NoneUpdate
;
480 state
->Process
= NoneProcess
;
485 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*ALEffectSlot
, ALeffect
*effect
)
487 if(ALEffectSlot
->effect
.type
!= (effect
?effect
->type
:AL_EFFECT_NULL
))
489 ALeffectState
*NewState
= NULL
;
490 if(!effect
|| effect
->type
== AL_EFFECT_NULL
)
491 NewState
= NoneCreate();
492 else if(effect
->type
== AL_EFFECT_EAXREVERB
)
493 NewState
= EAXVerbCreate();
494 else if(effect
->type
== AL_EFFECT_REVERB
)
495 NewState
= VerbCreate();
496 else if(effect
->type
== AL_EFFECT_ECHO
)
497 NewState
= EchoCreate();
498 /* No new state? An error occured.. */
499 if(NewState
== NULL
||
500 ALEffect_DeviceUpdate(NewState
, Context
->Device
) == AL_FALSE
)
503 ALEffect_Destroy(NewState
);
506 if(ALEffectSlot
->EffectState
)
507 ALEffect_Destroy(ALEffectSlot
->EffectState
);
508 ALEffectSlot
->EffectState
= NewState
;
511 memset(&ALEffectSlot
->effect
, 0, sizeof(ALEffectSlot
->effect
));
513 memcpy(&ALEffectSlot
->effect
, effect
, sizeof(*effect
));
514 ALEffect_Update(ALEffectSlot
->EffectState
, Context
, effect
);
518 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
520 while(Context
->AuxiliaryEffectSlot
)
522 ALeffectslot
*temp
= Context
->AuxiliaryEffectSlot
;
523 Context
->AuxiliaryEffectSlot
= Context
->AuxiliaryEffectSlot
->next
;
525 // Release effectslot structure
526 if(temp
->EffectState
)
527 ALEffect_Destroy(temp
->EffectState
);
528 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
530 memset(temp
, 0, sizeof(ALeffectslot
));
533 Context
->AuxiliaryEffectSlotCount
= 0;