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
);
37 DECL_VERIFIER(EffectSlot
, ALeffectslot
, effectslot
)
38 DECL_VERIFIER(Effect
, ALeffect
, effect
)
40 ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
45 Context
= GetContextSuspended();
50 ALCdevice
*Device
= Context
->Device
;
52 if(Context
->EffectSlotCount
+n
<= Device
->AuxiliaryEffectSlotMax
)
54 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
55 if (!IsBadWritePtr((void*)effectslots
, n
* sizeof(ALuint
)))
57 ALeffectslot
**list
= &Context
->EffectSlotList
;
59 list
= &(*list
)->next
;
64 *list
= calloc(1, sizeof(ALeffectslot
));
65 if(!(*list
) || !((*list
)->EffectState
=NoneCreate()))
67 // We must have run out or memory
68 free(*list
); *list
= NULL
;
69 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
70 alSetError(Context
, AL_OUT_OF_MEMORY
);
75 (*list
)->AuxSendAuto
= AL_TRUE
;
76 for(j
= 0;j
< BUFFERSIZE
;j
++)
77 (*list
)->WetBuffer
[j
] = 0.0f
;
78 (*list
)->refcount
= 0;
80 effectslots
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
81 (*list
)->effectslot
= effectslots
[i
];
83 Context
->EffectSlotCount
++;
86 list
= &(*list
)->next
;
91 alSetError(Context
, AL_INVALID_OPERATION
);
94 ProcessContext(Context
);
97 ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
100 ALeffectslot
*ALAuxiliaryEffectSlot
;
103 Context
= GetContextSuspended();
108 // Check that all effectslots are valid
109 for (i
= 0; i
< n
; i
++)
111 if((ALAuxiliaryEffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslots
[i
])) == NULL
)
113 alSetError(Context
, AL_INVALID_NAME
);
118 if(ALAuxiliaryEffectSlot
->refcount
> 0)
120 alSetError(Context
, AL_INVALID_NAME
);
128 // All effectslots are valid
129 for (i
= 0; i
< n
; i
++)
131 // Recheck that the effectslot is valid, because there could be duplicated names
132 if((ALAuxiliaryEffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslots
[i
])) != NULL
)
136 // Remove Source from list of Sources
137 list
= &Context
->EffectSlotList
;
138 while(*list
&& *list
!= ALAuxiliaryEffectSlot
)
139 list
= &(*list
)->next
;
142 *list
= (*list
)->next
;
143 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot
->effectslot
);
145 if(ALAuxiliaryEffectSlot
->EffectState
)
146 ALEffect_Destroy(ALAuxiliaryEffectSlot
->EffectState
);
148 memset(ALAuxiliaryEffectSlot
, 0, sizeof(ALeffectslot
));
149 free(ALAuxiliaryEffectSlot
);
151 Context
->EffectSlotCount
--;
157 alSetError(Context
, AL_INVALID_VALUE
);
159 ProcessContext(Context
);
162 ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
167 Context
= GetContextSuspended();
168 if(!Context
) return AL_FALSE
;
170 result
= (VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) ?
173 ProcessContext(Context
);
178 ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
181 ALboolean updateSources
= AL_FALSE
;
182 ALeffectslot
*ALEffectSlot
;
184 Context
= GetContextSuspended();
187 if((ALEffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
191 case AL_EFFECTSLOT_EFFECT
: {
192 ALeffect
*effect
= NULL
;
195 (effect
=VerifyEffect(Context
->Device
->EffectList
, iValue
)) != NULL
)
197 InitializeEffect(Context
, ALEffectSlot
, effect
);
198 updateSources
= AL_TRUE
;
201 alSetError(Context
, AL_INVALID_VALUE
);
204 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
205 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
207 ALEffectSlot
->AuxSendAuto
= iValue
;
208 updateSources
= AL_TRUE
;
211 alSetError(Context
, AL_INVALID_VALUE
);
215 alSetError(Context
, AL_INVALID_ENUM
);
220 alSetError(Context
, AL_INVALID_NAME
);
222 // Force updating the sources that use this slot, since it affects the
223 // sending parameters
226 ALsource
*source
= Context
->SourceList
;
230 for(i
= 0;i
< MAX_SENDS
;i
++)
232 if(!source
->Send
[i
].Slot
||
233 source
->Send
[i
].Slot
->effectslot
!= effectslot
)
235 source
->NeedsUpdate
= AL_TRUE
;
238 source
= source
->next
;
242 ProcessContext(Context
);
245 ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
249 Context
= GetContextSuspended();
252 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
256 case AL_EFFECTSLOT_EFFECT
:
257 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
258 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
262 alSetError(Context
, AL_INVALID_ENUM
);
267 alSetError(Context
, AL_INVALID_NAME
);
269 ProcessContext(Context
);
272 ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
275 ALeffectslot
*ALEffectSlot
;
277 Context
= GetContextSuspended();
280 if((ALEffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
284 case AL_EFFECTSLOT_GAIN
:
285 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
286 ALEffectSlot
->Gain
= flValue
;
288 alSetError(Context
, AL_INVALID_VALUE
);
292 alSetError(Context
, AL_INVALID_ENUM
);
297 alSetError(Context
, AL_INVALID_NAME
);
299 ProcessContext(Context
);
302 ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
306 Context
= GetContextSuspended();
309 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
313 case AL_EFFECTSLOT_GAIN
:
314 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
318 alSetError(Context
, AL_INVALID_ENUM
);
323 alSetError(Context
, AL_INVALID_NAME
);
325 ProcessContext(Context
);
328 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
331 ALeffectslot
*ALEffectSlot
;
333 Context
= GetContextSuspended();
336 if((ALEffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
340 case AL_EFFECTSLOT_EFFECT
:
341 *piValue
= ALEffectSlot
->effect
.effect
;
344 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
345 *piValue
= ALEffectSlot
->AuxSendAuto
;
349 alSetError(Context
, AL_INVALID_ENUM
);
354 alSetError(Context
, AL_INVALID_NAME
);
356 ProcessContext(Context
);
359 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
363 Context
= GetContextSuspended();
366 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
370 case AL_EFFECTSLOT_EFFECT
:
371 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
372 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
376 alSetError(Context
, AL_INVALID_ENUM
);
381 alSetError(Context
, AL_INVALID_NAME
);
383 ProcessContext(Context
);
386 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
389 ALeffectslot
*ALEffectSlot
;
391 Context
= GetContextSuspended();
394 if((ALEffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
398 case AL_EFFECTSLOT_GAIN
:
399 *pflValue
= ALEffectSlot
->Gain
;
403 alSetError(Context
, AL_INVALID_ENUM
);
408 alSetError(Context
, AL_INVALID_NAME
);
410 ProcessContext(Context
);
413 ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
417 Context
= GetContextSuspended();
420 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
424 case AL_EFFECTSLOT_GAIN
:
425 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
429 alSetError(Context
, AL_INVALID_ENUM
);
434 alSetError(Context
, AL_INVALID_NAME
);
436 ProcessContext(Context
);
440 static ALvoid
NoneDestroy(ALeffectState
*State
)
442 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
448 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffect
*Effect
)
454 static ALvoid
NoneProcess(ALeffectState
*State
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
462 ALeffectState
*NoneCreate(void)
464 ALeffectState
*state
;
466 state
= calloc(1, sizeof(*state
));
470 state
->Destroy
= NoneDestroy
;
471 state
->DeviceUpdate
= NoneDeviceUpdate
;
472 state
->Update
= NoneUpdate
;
473 state
->Process
= NoneProcess
;
478 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*ALEffectSlot
, ALeffect
*effect
)
480 if(ALEffectSlot
->effect
.type
!= (effect
?effect
->type
:AL_EFFECT_NULL
))
482 ALeffectState
*NewState
= NULL
;
483 if(!effect
|| effect
->type
== AL_EFFECT_NULL
)
484 NewState
= NoneCreate();
485 else if(effect
->type
== AL_EFFECT_EAXREVERB
)
486 NewState
= EAXVerbCreate();
487 else if(effect
->type
== AL_EFFECT_REVERB
)
488 NewState
= VerbCreate();
489 else if(effect
->type
== AL_EFFECT_ECHO
)
490 NewState
= EchoCreate();
491 /* No new state? An error occured.. */
492 if(NewState
== NULL
||
493 ALEffect_DeviceUpdate(NewState
, Context
->Device
) == AL_FALSE
)
496 ALEffect_Destroy(NewState
);
497 alSetError(Context
, AL_OUT_OF_MEMORY
);
500 if(ALEffectSlot
->EffectState
)
501 ALEffect_Destroy(ALEffectSlot
->EffectState
);
502 ALEffectSlot
->EffectState
= NewState
;
505 memset(&ALEffectSlot
->effect
, 0, sizeof(ALEffectSlot
->effect
));
507 memcpy(&ALEffectSlot
->effect
, effect
, sizeof(*effect
));
508 ALEffect_Update(ALEffectSlot
->EffectState
, Context
, effect
);
512 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
514 while(Context
->EffectSlotList
)
516 ALeffectslot
*temp
= Context
->EffectSlotList
;
517 Context
->EffectSlotList
= temp
->next
;
519 // Release effectslot structure
520 if(temp
->EffectState
)
521 ALEffect_Destroy(temp
->EffectState
);
522 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
524 memset(temp
, 0, sizeof(ALeffectslot
));
527 Context
->EffectSlotCount
= 0;