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
*EffectSlot
, ALeffect
*effect
);
37 DECL_VERIFIER(EffectSlot
, ALeffectslot
, effectslot
)
38 DECL_VERIFIER(Effect
, ALeffect
, effect
)
40 AL_API 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
)))
58 ALeffectslot
**list
= &Context
->EffectSlotList
;
60 list
= &(*list
)->next
;
65 *list
= calloc(1, sizeof(ALeffectslot
));
66 if(!(*list
) || !((*list
)->EffectState
=NoneCreate()))
68 // We must have run out or memory
69 free(*list
); *list
= NULL
;
72 ALeffectslot
*temp
= end
->next
;
73 end
->next
= temp
->next
;
75 ALEffect_Destroy(temp
->EffectState
);
76 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
77 Context
->EffectSlotCount
--;
80 alSetError(Context
, AL_OUT_OF_MEMORY
);
85 (*list
)->AuxSendAuto
= AL_TRUE
;
86 for(j
= 0;j
< BUFFERSIZE
;j
++)
87 (*list
)->WetBuffer
[j
] = 0.0f
;
88 (*list
)->refcount
= 0;
90 effectslots
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
91 (*list
)->effectslot
= effectslots
[i
];
93 Context
->EffectSlotCount
++;
96 list
= &(*list
)->next
;
101 alSetError(Context
, AL_INVALID_OPERATION
);
104 ProcessContext(Context
);
107 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
110 ALeffectslot
*EffectSlot
;
113 Context
= GetContextSuspended();
118 // Check that all effectslots are valid
119 for (i
= 0; i
< n
; i
++)
121 if((EffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslots
[i
])) == NULL
)
123 alSetError(Context
, AL_INVALID_NAME
);
128 if(EffectSlot
->refcount
> 0)
130 alSetError(Context
, AL_INVALID_NAME
);
138 // All effectslots are valid
139 for (i
= 0; i
< n
; i
++)
141 // Recheck that the effectslot is valid, because there could be duplicated names
142 if((EffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslots
[i
])) != NULL
)
146 // Remove Source from list of Sources
147 list
= &Context
->EffectSlotList
;
148 while(*list
&& *list
!= EffectSlot
)
149 list
= &(*list
)->next
;
152 *list
= (*list
)->next
;
153 ALTHUNK_REMOVEENTRY(EffectSlot
->effectslot
);
155 ALEffect_Destroy(EffectSlot
->EffectState
);
157 memset(EffectSlot
, 0, sizeof(ALeffectslot
));
160 Context
->EffectSlotCount
--;
166 alSetError(Context
, AL_INVALID_VALUE
);
168 ProcessContext(Context
);
171 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
176 Context
= GetContextSuspended();
177 if(!Context
) return AL_FALSE
;
179 result
= (VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) ?
182 ProcessContext(Context
);
187 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
190 ALboolean updateSources
= AL_FALSE
;
191 ALeffectslot
*EffectSlot
;
193 Context
= GetContextSuspended();
196 if((EffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
200 case AL_EFFECTSLOT_EFFECT
: {
201 ALeffect
*effect
= NULL
;
204 (effect
=VerifyEffect(Context
->Device
->EffectList
, iValue
)) != NULL
)
206 InitializeEffect(Context
, EffectSlot
, effect
);
207 updateSources
= AL_TRUE
;
210 alSetError(Context
, AL_INVALID_VALUE
);
213 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
214 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
216 EffectSlot
->AuxSendAuto
= iValue
;
217 updateSources
= AL_TRUE
;
220 alSetError(Context
, AL_INVALID_VALUE
);
224 alSetError(Context
, AL_INVALID_ENUM
);
229 alSetError(Context
, AL_INVALID_NAME
);
231 // Force updating the sources that use this slot, since it affects the
232 // sending parameters
235 ALsource
*source
= Context
->SourceList
;
239 for(i
= 0;i
< MAX_SENDS
;i
++)
241 if(!source
->Send
[i
].Slot
||
242 source
->Send
[i
].Slot
->effectslot
!= effectslot
)
244 source
->NeedsUpdate
= AL_TRUE
;
247 source
= source
->next
;
251 ProcessContext(Context
);
254 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
258 Context
= GetContextSuspended();
261 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
265 case AL_EFFECTSLOT_EFFECT
:
266 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
267 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
271 alSetError(Context
, AL_INVALID_ENUM
);
276 alSetError(Context
, AL_INVALID_NAME
);
278 ProcessContext(Context
);
281 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
284 ALeffectslot
*EffectSlot
;
286 Context
= GetContextSuspended();
289 if((EffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
293 case AL_EFFECTSLOT_GAIN
:
294 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
295 EffectSlot
->Gain
= flValue
;
297 alSetError(Context
, AL_INVALID_VALUE
);
301 alSetError(Context
, AL_INVALID_ENUM
);
306 alSetError(Context
, AL_INVALID_NAME
);
308 ProcessContext(Context
);
311 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
315 Context
= GetContextSuspended();
318 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
322 case AL_EFFECTSLOT_GAIN
:
323 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
327 alSetError(Context
, AL_INVALID_ENUM
);
332 alSetError(Context
, AL_INVALID_NAME
);
334 ProcessContext(Context
);
337 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
340 ALeffectslot
*EffectSlot
;
342 Context
= GetContextSuspended();
345 if((EffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
349 case AL_EFFECTSLOT_EFFECT
:
350 *piValue
= EffectSlot
->effect
.effect
;
353 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
354 *piValue
= EffectSlot
->AuxSendAuto
;
358 alSetError(Context
, AL_INVALID_ENUM
);
363 alSetError(Context
, AL_INVALID_NAME
);
365 ProcessContext(Context
);
368 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
372 Context
= GetContextSuspended();
375 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
379 case AL_EFFECTSLOT_EFFECT
:
380 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
381 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
385 alSetError(Context
, AL_INVALID_ENUM
);
390 alSetError(Context
, AL_INVALID_NAME
);
392 ProcessContext(Context
);
395 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
398 ALeffectslot
*EffectSlot
;
400 Context
= GetContextSuspended();
403 if((EffectSlot
=VerifyEffectSlot(Context
->EffectSlotList
, effectslot
)) != NULL
)
407 case AL_EFFECTSLOT_GAIN
:
408 *pflValue
= EffectSlot
->Gain
;
412 alSetError(Context
, AL_INVALID_ENUM
);
417 alSetError(Context
, AL_INVALID_NAME
);
419 ProcessContext(Context
);
422 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
426 Context
= GetContextSuspended();
429 if(VerifyEffectSlot(Context
->EffectSlotList
, effectslot
) != NULL
)
433 case AL_EFFECTSLOT_GAIN
:
434 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
438 alSetError(Context
, AL_INVALID_ENUM
);
443 alSetError(Context
, AL_INVALID_NAME
);
445 ProcessContext(Context
);
449 static ALvoid
NoneDestroy(ALeffectState
*State
)
451 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
457 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffect
*Effect
)
463 static ALvoid
NoneProcess(ALeffectState
*State
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
471 ALeffectState
*NoneCreate(void)
473 ALeffectState
*state
;
475 state
= calloc(1, sizeof(*state
));
479 state
->Destroy
= NoneDestroy
;
480 state
->DeviceUpdate
= NoneDeviceUpdate
;
481 state
->Update
= NoneUpdate
;
482 state
->Process
= NoneProcess
;
487 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
489 if(EffectSlot
->effect
.type
!= (effect
?effect
->type
:AL_EFFECT_NULL
))
491 ALeffectState
*NewState
= NULL
;
492 if(!effect
|| effect
->type
== AL_EFFECT_NULL
)
493 NewState
= NoneCreate();
494 else if(effect
->type
== AL_EFFECT_EAXREVERB
)
495 NewState
= EAXVerbCreate();
496 else if(effect
->type
== AL_EFFECT_REVERB
)
497 NewState
= VerbCreate();
498 else if(effect
->type
== AL_EFFECT_ECHO
)
499 NewState
= EchoCreate();
500 /* No new state? An error occured.. */
501 if(NewState
== NULL
||
502 ALEffect_DeviceUpdate(NewState
, Context
->Device
) == AL_FALSE
)
505 ALEffect_Destroy(NewState
);
506 alSetError(Context
, AL_OUT_OF_MEMORY
);
509 if(EffectSlot
->EffectState
)
510 ALEffect_Destroy(EffectSlot
->EffectState
);
511 EffectSlot
->EffectState
= NewState
;
514 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
516 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
517 ALEffect_Update(EffectSlot
->EffectState
, Context
, effect
);
521 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
523 while(Context
->EffectSlotList
)
525 ALeffectslot
*temp
= Context
->EffectSlotList
;
526 Context
->EffectSlotList
= temp
->next
;
528 // Release effectslot structure
529 ALEffect_Destroy(temp
->EffectState
);
531 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
532 memset(temp
, 0, sizeof(ALeffectslot
));
535 Context
->EffectSlotCount
= 0;