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 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
38 #define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k)))
40 AL_API ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
45 Context
= GetContextSuspended();
50 ALCdevice
*Device
= Context
->Device
;
52 if(Context
->EffectSlotMap
.size
+n
<= (ALsizei
)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
)))
61 ALeffectslot
*slot
= calloc(1, sizeof(ALeffectslot
));
62 if(!slot
|| !(slot
->EffectState
=NoneCreate()))
65 // We must have run out or memory
66 alSetError(Context
, AL_OUT_OF_MEMORY
);
67 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
71 slot
->effectslot
= (ALuint
)ALTHUNK_ADDENTRY(slot
);
72 err
= InsertUIntMapEntry(&Context
->EffectSlotMap
,
73 slot
->effectslot
, slot
);
74 if(err
!= AL_NO_ERROR
)
76 ALTHUNK_REMOVEENTRY(slot
->effectslot
);
77 ALEffect_Destroy(slot
->EffectState
);
80 alSetError(Context
, err
);
81 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
85 effectslots
[i
++] = slot
->effectslot
;
88 slot
->AuxSendAuto
= AL_TRUE
;
89 for(j
= 0;j
< BUFFERSIZE
;j
++)
90 slot
->WetBuffer
[j
] = 0.0f
;
92 slot
->ClickRemoval
[j
] = 0.0f
;
98 alSetError(Context
, AL_INVALID_OPERATION
);
101 ProcessContext(Context
);
104 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
107 ALeffectslot
*EffectSlot
;
110 Context
= GetContextSuspended();
115 // Check that all effectslots are valid
116 for (i
= 0; i
< n
; i
++)
118 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslots
[i
])) == NULL
)
120 alSetError(Context
, AL_INVALID_NAME
);
125 if(EffectSlot
->refcount
> 0)
127 alSetError(Context
, AL_INVALID_NAME
);
135 // All effectslots are valid
136 for (i
= 0; i
< n
; i
++)
138 // Recheck that the effectslot is valid, because there could be duplicated names
139 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslots
[i
])) != NULL
)
141 ALEffect_Destroy(EffectSlot
->EffectState
);
143 RemoveUIntMapKey(&Context
->EffectSlotMap
, EffectSlot
->effectslot
);
144 ALTHUNK_REMOVEENTRY(EffectSlot
->effectslot
);
146 memset(EffectSlot
, 0, sizeof(ALeffectslot
));
153 alSetError(Context
, AL_INVALID_VALUE
);
155 ProcessContext(Context
);
158 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
163 Context
= GetContextSuspended();
164 if(!Context
) return AL_FALSE
;
166 result
= (LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) ?
169 ProcessContext(Context
);
174 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
177 ALboolean updateSources
= AL_FALSE
;
178 ALeffectslot
*EffectSlot
;
180 Context
= GetContextSuspended();
183 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
187 case AL_EFFECTSLOT_EFFECT
: {
188 ALeffect
*effect
= NULL
;
191 (effect
=LookupEffect(Context
->Device
->EffectMap
, iValue
)) != NULL
)
193 InitializeEffect(Context
, EffectSlot
, effect
);
194 updateSources
= AL_TRUE
;
197 alSetError(Context
, AL_INVALID_VALUE
);
200 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
201 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
203 EffectSlot
->AuxSendAuto
= iValue
;
204 updateSources
= AL_TRUE
;
207 alSetError(Context
, AL_INVALID_VALUE
);
211 alSetError(Context
, AL_INVALID_ENUM
);
216 alSetError(Context
, AL_INVALID_NAME
);
218 // Force updating the sources that use this slot, since it affects the
219 // sending parameters
223 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
225 ALsource
*source
= Context
->SourceMap
.array
[pos
].value
;
227 for(i
= 0;i
< MAX_SENDS
;i
++)
229 if(!source
->Send
[i
].Slot
||
230 source
->Send
[i
].Slot
->effectslot
!= effectslot
)
232 source
->NeedsUpdate
= AL_TRUE
;
238 ProcessContext(Context
);
241 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
245 Context
= GetContextSuspended();
248 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
252 case AL_EFFECTSLOT_EFFECT
:
253 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
254 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
258 alSetError(Context
, AL_INVALID_ENUM
);
263 alSetError(Context
, AL_INVALID_NAME
);
265 ProcessContext(Context
);
268 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
271 ALeffectslot
*EffectSlot
;
273 Context
= GetContextSuspended();
276 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
280 case AL_EFFECTSLOT_GAIN
:
281 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
282 EffectSlot
->Gain
= flValue
;
284 alSetError(Context
, AL_INVALID_VALUE
);
288 alSetError(Context
, AL_INVALID_ENUM
);
293 alSetError(Context
, AL_INVALID_NAME
);
295 ProcessContext(Context
);
298 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
302 Context
= GetContextSuspended();
305 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
309 case AL_EFFECTSLOT_GAIN
:
310 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
314 alSetError(Context
, AL_INVALID_ENUM
);
319 alSetError(Context
, AL_INVALID_NAME
);
321 ProcessContext(Context
);
324 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
327 ALeffectslot
*EffectSlot
;
329 Context
= GetContextSuspended();
332 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
336 case AL_EFFECTSLOT_EFFECT
:
337 *piValue
= EffectSlot
->effect
.effect
;
340 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
341 *piValue
= EffectSlot
->AuxSendAuto
;
345 alSetError(Context
, AL_INVALID_ENUM
);
350 alSetError(Context
, AL_INVALID_NAME
);
352 ProcessContext(Context
);
355 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
359 Context
= GetContextSuspended();
362 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
366 case AL_EFFECTSLOT_EFFECT
:
367 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
368 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
372 alSetError(Context
, AL_INVALID_ENUM
);
377 alSetError(Context
, AL_INVALID_NAME
);
379 ProcessContext(Context
);
382 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
385 ALeffectslot
*EffectSlot
;
387 Context
= GetContextSuspended();
390 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
394 case AL_EFFECTSLOT_GAIN
:
395 *pflValue
= EffectSlot
->Gain
;
399 alSetError(Context
, AL_INVALID_ENUM
);
404 alSetError(Context
, AL_INVALID_NAME
);
406 ProcessContext(Context
);
409 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
413 Context
= GetContextSuspended();
416 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
420 case AL_EFFECTSLOT_GAIN
:
421 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
425 alSetError(Context
, AL_INVALID_ENUM
);
430 alSetError(Context
, AL_INVALID_NAME
);
432 ProcessContext(Context
);
436 static ALvoid
NoneDestroy(ALeffectState
*State
)
438 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
444 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffect
*Effect
)
450 static ALvoid
NoneProcess(ALeffectState
*State
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
458 ALeffectState
*NoneCreate(void)
460 ALeffectState
*state
;
462 state
= calloc(1, sizeof(*state
));
466 state
->Destroy
= NoneDestroy
;
467 state
->DeviceUpdate
= NoneDeviceUpdate
;
468 state
->Update
= NoneUpdate
;
469 state
->Process
= NoneProcess
;
474 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
476 if(EffectSlot
->effect
.type
!= (effect
?effect
->type
:AL_EFFECT_NULL
))
478 ALeffectState
*NewState
= NULL
;
479 if(!effect
|| effect
->type
== AL_EFFECT_NULL
)
480 NewState
= NoneCreate();
481 else if(effect
->type
== AL_EFFECT_EAXREVERB
)
482 NewState
= EAXVerbCreate();
483 else if(effect
->type
== AL_EFFECT_REVERB
)
484 NewState
= VerbCreate();
485 else if(effect
->type
== AL_EFFECT_ECHO
)
486 NewState
= EchoCreate();
487 else if(effect
->type
== AL_EFFECT_RING_MODULATOR
)
488 NewState
= ModulatorCreate();
489 /* No new state? An error occured.. */
490 if(NewState
== NULL
||
491 ALEffect_DeviceUpdate(NewState
, Context
->Device
) == AL_FALSE
)
494 ALEffect_Destroy(NewState
);
495 alSetError(Context
, AL_OUT_OF_MEMORY
);
498 if(EffectSlot
->EffectState
)
499 ALEffect_Destroy(EffectSlot
->EffectState
);
500 EffectSlot
->EffectState
= NewState
;
503 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
505 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
506 ALEffect_Update(EffectSlot
->EffectState
, Context
, effect
);
510 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
513 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
515 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
516 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
518 // Release effectslot structure
519 ALEffect_Destroy(temp
->EffectState
);
521 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
522 memset(temp
, 0, sizeof(ALeffectslot
));