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
;
96 alSetError(Context
, AL_INVALID_OPERATION
);
99 ProcessContext(Context
);
102 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
105 ALeffectslot
*EffectSlot
;
108 Context
= GetContextSuspended();
113 // Check that all effectslots are valid
114 for (i
= 0; i
< n
; i
++)
116 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslots
[i
])) == NULL
)
118 alSetError(Context
, AL_INVALID_NAME
);
123 if(EffectSlot
->refcount
> 0)
125 alSetError(Context
, AL_INVALID_NAME
);
133 // All effectslots are valid
134 for (i
= 0; i
< n
; i
++)
136 // Recheck that the effectslot is valid, because there could be duplicated names
137 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslots
[i
])) != NULL
)
139 ALEffect_Destroy(EffectSlot
->EffectState
);
141 RemoveUIntMapKey(&Context
->EffectSlotMap
, EffectSlot
->effectslot
);
142 ALTHUNK_REMOVEENTRY(EffectSlot
->effectslot
);
144 memset(EffectSlot
, 0, sizeof(ALeffectslot
));
151 alSetError(Context
, AL_INVALID_VALUE
);
153 ProcessContext(Context
);
156 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
161 Context
= GetContextSuspended();
162 if(!Context
) return AL_FALSE
;
164 result
= (LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) ?
167 ProcessContext(Context
);
172 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
175 ALboolean updateSources
= AL_FALSE
;
176 ALeffectslot
*EffectSlot
;
178 Context
= GetContextSuspended();
181 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
185 case AL_EFFECTSLOT_EFFECT
: {
186 ALeffect
*effect
= NULL
;
189 (effect
=LookupEffect(Context
->Device
->EffectMap
, iValue
)) != NULL
)
191 InitializeEffect(Context
, EffectSlot
, effect
);
192 updateSources
= AL_TRUE
;
195 alSetError(Context
, AL_INVALID_VALUE
);
198 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
199 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
201 EffectSlot
->AuxSendAuto
= iValue
;
202 updateSources
= AL_TRUE
;
205 alSetError(Context
, AL_INVALID_VALUE
);
209 alSetError(Context
, AL_INVALID_ENUM
);
214 alSetError(Context
, AL_INVALID_NAME
);
216 // Force updating the sources that use this slot, since it affects the
217 // sending parameters
221 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
223 ALsource
*source
= Context
->SourceMap
.array
[pos
].value
;
225 for(i
= 0;i
< MAX_SENDS
;i
++)
227 if(!source
->Send
[i
].Slot
||
228 source
->Send
[i
].Slot
->effectslot
!= effectslot
)
230 source
->NeedsUpdate
= AL_TRUE
;
236 ProcessContext(Context
);
239 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
243 Context
= GetContextSuspended();
246 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
250 case AL_EFFECTSLOT_EFFECT
:
251 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
252 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
256 alSetError(Context
, AL_INVALID_ENUM
);
261 alSetError(Context
, AL_INVALID_NAME
);
263 ProcessContext(Context
);
266 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
269 ALeffectslot
*EffectSlot
;
271 Context
= GetContextSuspended();
274 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
278 case AL_EFFECTSLOT_GAIN
:
279 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
280 EffectSlot
->Gain
= flValue
;
282 alSetError(Context
, AL_INVALID_VALUE
);
286 alSetError(Context
, AL_INVALID_ENUM
);
291 alSetError(Context
, AL_INVALID_NAME
);
293 ProcessContext(Context
);
296 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
300 Context
= GetContextSuspended();
303 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
307 case AL_EFFECTSLOT_GAIN
:
308 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
312 alSetError(Context
, AL_INVALID_ENUM
);
317 alSetError(Context
, AL_INVALID_NAME
);
319 ProcessContext(Context
);
322 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
325 ALeffectslot
*EffectSlot
;
327 Context
= GetContextSuspended();
330 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
334 case AL_EFFECTSLOT_EFFECT
:
335 *piValue
= EffectSlot
->effect
.effect
;
338 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
339 *piValue
= EffectSlot
->AuxSendAuto
;
343 alSetError(Context
, AL_INVALID_ENUM
);
348 alSetError(Context
, AL_INVALID_NAME
);
350 ProcessContext(Context
);
353 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
357 Context
= GetContextSuspended();
360 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
364 case AL_EFFECTSLOT_EFFECT
:
365 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
366 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
370 alSetError(Context
, AL_INVALID_ENUM
);
375 alSetError(Context
, AL_INVALID_NAME
);
377 ProcessContext(Context
);
380 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
383 ALeffectslot
*EffectSlot
;
385 Context
= GetContextSuspended();
388 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
392 case AL_EFFECTSLOT_GAIN
:
393 *pflValue
= EffectSlot
->Gain
;
397 alSetError(Context
, AL_INVALID_ENUM
);
402 alSetError(Context
, AL_INVALID_NAME
);
404 ProcessContext(Context
);
407 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
411 Context
= GetContextSuspended();
414 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
418 case AL_EFFECTSLOT_GAIN
:
419 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
423 alSetError(Context
, AL_INVALID_ENUM
);
428 alSetError(Context
, AL_INVALID_NAME
);
430 ProcessContext(Context
);
434 static ALvoid
NoneDestroy(ALeffectState
*State
)
436 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
442 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffect
*Effect
)
448 static ALvoid
NoneProcess(ALeffectState
*State
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
456 ALeffectState
*NoneCreate(void)
458 ALeffectState
*state
;
460 state
= calloc(1, sizeof(*state
));
464 state
->Destroy
= NoneDestroy
;
465 state
->DeviceUpdate
= NoneDeviceUpdate
;
466 state
->Update
= NoneUpdate
;
467 state
->Process
= NoneProcess
;
472 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
474 if(EffectSlot
->effect
.type
!= (effect
?effect
->type
:AL_EFFECT_NULL
))
476 ALeffectState
*NewState
= NULL
;
477 if(!effect
|| effect
->type
== AL_EFFECT_NULL
)
478 NewState
= NoneCreate();
479 else if(effect
->type
== AL_EFFECT_EAXREVERB
)
480 NewState
= EAXVerbCreate();
481 else if(effect
->type
== AL_EFFECT_REVERB
)
482 NewState
= VerbCreate();
483 else if(effect
->type
== AL_EFFECT_ECHO
)
484 NewState
= EchoCreate();
485 else if(effect
->type
== AL_EFFECT_RING_MODULATOR
)
486 NewState
= ModulatorCreate();
487 /* No new state? An error occured.. */
488 if(NewState
== NULL
||
489 ALEffect_DeviceUpdate(NewState
, Context
->Device
) == AL_FALSE
)
492 ALEffect_Destroy(NewState
);
493 alSetError(Context
, AL_OUT_OF_MEMORY
);
496 if(EffectSlot
->EffectState
)
497 ALEffect_Destroy(EffectSlot
->EffectState
);
498 EffectSlot
->EffectState
= NewState
;
501 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
503 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
504 ALEffect_Update(EffectSlot
->EffectState
, Context
, effect
);
508 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
511 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
513 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
514 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
516 // Release effectslot structure
517 ALEffect_Destroy(temp
->EffectState
);
519 ALTHUNK_REMOVEENTRY(temp
->effectslot
);
520 memset(temp
, 0, sizeof(ALeffectslot
));