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
);
36 static ALenum
ResizeEffectSlotArray(ALCcontext
*Context
, ALsizei count
);
37 static ALvoid
RemoveEffectSlotArray(ALCcontext
*Context
, ALeffectslot
*val
);
39 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
40 #define RemoveEffectSlot(m, k) ((ALeffectslot*)PopUIntMapValue(&(m), (k)))
41 #define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k)))
43 AL_API ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
48 Context
= GetContextRef();
51 Device
= Context
->Device
;
52 if(n
< 0 || IsBadWritePtr((void*)effectslots
, n
* sizeof(ALuint
)))
53 alSetError(Context
, AL_INVALID_VALUE
);
59 err
= ResizeEffectSlotArray(Context
, n
);
60 if(err
!= AL_NO_ERROR
)
62 alSetError(Context
, err
);
68 ALeffectslot
*slot
= calloc(1, sizeof(ALeffectslot
));
69 if(!slot
|| !(slot
->EffectState
=NoneCreate()))
72 // We must have run out or memory
73 alSetError(Context
, AL_OUT_OF_MEMORY
);
74 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
79 slot
->AuxSendAuto
= AL_TRUE
;
80 slot
->NeedsUpdate
= AL_FALSE
;
81 for(j
= 0;j
< BUFFERSIZE
;j
++)
82 slot
->WetBuffer
[j
] = 0.0f
;
85 slot
->ClickRemoval
[j
] = 0.0f
;
86 slot
->PendingClicks
[j
] = 0.0f
;
91 err
= ResizeEffectSlotArray(Context
, 1);
92 if(err
== AL_NO_ERROR
)
93 Context
->ActiveEffectSlots
[Context
->ActiveEffectSlotCount
++] = slot
;
94 UnlockContext(Context
);
95 if(err
== AL_NO_ERROR
)
96 err
= NewThunkEntry(&slot
->effectslot
);
97 if(err
== AL_NO_ERROR
)
98 err
= InsertUIntMapEntry(&Context
->EffectSlotMap
, slot
->effectslot
, slot
);
99 if(err
!= AL_NO_ERROR
)
101 RemoveEffectSlotArray(Context
, slot
);
102 FreeThunkEntry(slot
->effectslot
);
103 ALeffectState_Destroy(slot
->EffectState
);
106 alSetError(Context
, err
);
107 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
111 effectslots
[i
] = slot
->effectslot
;
115 ALCcontext_DecRef(Context
);
118 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
121 ALeffectslot
*EffectSlot
;
124 Context
= GetContextRef();
128 alSetError(Context
, AL_INVALID_VALUE
);
131 // Check that all effectslots are valid
134 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslots
[i
])) == NULL
)
136 alSetError(Context
, AL_INVALID_NAME
);
140 else if(EffectSlot
->ref
!= 0)
142 alSetError(Context
, AL_INVALID_OPERATION
);
148 // All effectslots are valid
151 // Recheck that the effectslot is valid, because there could be duplicated names
152 if((EffectSlot
=RemoveEffectSlot(Context
->EffectSlotMap
, effectslots
[i
])) == NULL
)
154 FreeThunkEntry(EffectSlot
->effectslot
);
156 RemoveEffectSlotArray(Context
, EffectSlot
);
157 ALeffectState_Destroy(EffectSlot
->EffectState
);
159 memset(EffectSlot
, 0, sizeof(ALeffectslot
));
164 ALCcontext_DecRef(Context
);
167 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
172 Context
= GetContextRef();
173 if(!Context
) return AL_FALSE
;
175 result
= (LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) ?
178 ALCcontext_DecRef(Context
);
183 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
187 ALeffectslot
*EffectSlot
;
189 Context
= GetContextRef();
192 Device
= Context
->Device
;
193 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
197 case AL_EFFECTSLOT_EFFECT
: {
198 ALeffect
*effect
= NULL
;
201 (effect
=LookupEffect(Device
->EffectMap
, iValue
)) != NULL
)
203 InitializeEffect(Context
, EffectSlot
, effect
);
204 Context
->UpdateSources
= AL_TRUE
;
207 alSetError(Context
, AL_INVALID_VALUE
);
210 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
211 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
213 EffectSlot
->AuxSendAuto
= iValue
;
214 Context
->UpdateSources
= AL_TRUE
;
217 alSetError(Context
, AL_INVALID_VALUE
);
221 alSetError(Context
, AL_INVALID_ENUM
);
226 alSetError(Context
, AL_INVALID_NAME
);
228 ALCcontext_DecRef(Context
);
231 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
237 case AL_EFFECTSLOT_EFFECT
:
238 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
239 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
243 Context
= GetContextRef();
246 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
251 alSetError(Context
, AL_INVALID_ENUM
);
256 alSetError(Context
, AL_INVALID_NAME
);
258 ALCcontext_DecRef(Context
);
261 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
264 ALeffectslot
*EffectSlot
;
266 Context
= GetContextRef();
269 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
273 case AL_EFFECTSLOT_GAIN
:
274 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
276 EffectSlot
->Gain
= flValue
;
277 EffectSlot
->NeedsUpdate
= AL_TRUE
;
280 alSetError(Context
, AL_INVALID_VALUE
);
284 alSetError(Context
, AL_INVALID_ENUM
);
289 alSetError(Context
, AL_INVALID_NAME
);
291 ALCcontext_DecRef(Context
);
294 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
300 case AL_EFFECTSLOT_GAIN
:
301 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
305 Context
= GetContextRef();
308 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
313 alSetError(Context
, AL_INVALID_ENUM
);
318 alSetError(Context
, AL_INVALID_NAME
);
320 ALCcontext_DecRef(Context
);
323 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
326 ALeffectslot
*EffectSlot
;
328 Context
= GetContextRef();
331 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
335 case AL_EFFECTSLOT_EFFECT
:
336 *piValue
= EffectSlot
->effect
.effect
;
339 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
340 *piValue
= EffectSlot
->AuxSendAuto
;
344 alSetError(Context
, AL_INVALID_ENUM
);
349 alSetError(Context
, AL_INVALID_NAME
);
351 ALCcontext_DecRef(Context
);
354 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
360 case AL_EFFECTSLOT_EFFECT
:
361 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
362 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
366 Context
= GetContextRef();
369 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
374 alSetError(Context
, AL_INVALID_ENUM
);
379 alSetError(Context
, AL_INVALID_NAME
);
381 ALCcontext_DecRef(Context
);
384 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
387 ALeffectslot
*EffectSlot
;
389 Context
= GetContextRef();
392 if((EffectSlot
=LookupEffectSlot(Context
->EffectSlotMap
, effectslot
)) != NULL
)
396 case AL_EFFECTSLOT_GAIN
:
397 *pflValue
= EffectSlot
->Gain
;
401 alSetError(Context
, AL_INVALID_ENUM
);
406 alSetError(Context
, AL_INVALID_NAME
);
408 ALCcontext_DecRef(Context
);
411 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
417 case AL_EFFECTSLOT_GAIN
:
418 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
422 Context
= GetContextRef();
425 if(LookupEffectSlot(Context
->EffectSlotMap
, effectslot
) != NULL
)
430 alSetError(Context
, AL_INVALID_ENUM
);
435 alSetError(Context
, AL_INVALID_NAME
);
437 ALCcontext_DecRef(Context
);
441 static ALvoid
NoneDestroy(ALeffectState
*State
)
443 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
449 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffectslot
*Slot
)
455 static ALvoid
NoneProcess(ALeffectState
*State
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[MAXCHANNELS
])
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
;
479 static ALvoid
RemoveEffectSlotArray(ALCcontext
*Context
, ALeffectslot
*slot
)
481 ALeffectslot
**slotlist
, **slotlistend
;
483 LockContext(Context
);
484 slotlist
= Context
->ActiveEffectSlots
;
485 slotlistend
= slotlist
+ Context
->ActiveEffectSlotCount
;
486 while(slotlist
!= slotlistend
)
488 if(*slotlist
== slot
)
490 *slotlist
= *(--slotlistend
);
491 Context
->ActiveEffectSlotCount
--;
496 UnlockContext(Context
);
499 static ALenum
ResizeEffectSlotArray(ALCcontext
*Context
, ALsizei count
)
504 if(count
<= Context
->MaxActiveEffectSlots
-Context
->ActiveEffectSlotCount
)
507 newcount
= Context
->MaxActiveEffectSlots
?
508 (Context
->MaxActiveEffectSlots
<<1) : 1;
509 if(newcount
<= Context
->MaxActiveEffectSlots
||
510 !(temp
=realloc(Context
->ActiveEffectSlots
, newcount
*
511 sizeof(*Context
->ActiveEffectSlots
))))
512 return AL_OUT_OF_MEMORY
;
514 Context
->ActiveEffectSlots
= temp
;
515 Context
->MaxActiveEffectSlots
= newcount
;
519 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
521 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
522 ALeffectState
*State
= NULL
;
523 ALenum err
= AL_NO_ERROR
;
525 LockContext(Context
);
526 if(newtype
== AL_EFFECT_NULL
&& EffectSlot
->effect
.type
!= AL_EFFECT_NULL
)
528 State
= NoneCreate();
529 if(!State
) err
= AL_OUT_OF_MEMORY
;
531 else if(newtype
== AL_EFFECT_EAXREVERB
|| newtype
== AL_EFFECT_REVERB
)
533 if(EffectSlot
->effect
.type
!= AL_EFFECT_EAXREVERB
&& EffectSlot
->effect
.type
!= AL_EFFECT_REVERB
)
535 State
= ReverbCreate();
536 if(!State
) err
= AL_OUT_OF_MEMORY
;
539 else if(newtype
== AL_EFFECT_ECHO
&& EffectSlot
->effect
.type
!= AL_EFFECT_ECHO
)
541 State
= EchoCreate();
542 if(!State
) err
= AL_OUT_OF_MEMORY
;
544 else if(newtype
== AL_EFFECT_RING_MODULATOR
&& EffectSlot
->effect
.type
!= AL_EFFECT_RING_MODULATOR
)
546 State
= ModulatorCreate();
547 if(!State
) err
= AL_OUT_OF_MEMORY
;
549 else if(newtype
== AL_EFFECT_DEDICATED_DIALOGUE
|| newtype
== AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
)
551 if(EffectSlot
->effect
.type
!= AL_EFFECT_DEDICATED_DIALOGUE
&& EffectSlot
->effect
.type
!= AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
)
553 State
= DedicatedCreate();
554 if(!State
) err
= AL_OUT_OF_MEMORY
;
558 if(err
!= AL_NO_ERROR
)
560 UnlockContext(Context
);
561 alSetError(Context
, err
);
567 if(ALeffectState_DeviceUpdate(State
, Context
->Device
) == AL_FALSE
)
569 UnlockContext(Context
);
570 ALeffectState_Destroy(State
);
571 alSetError(Context
, AL_OUT_OF_MEMORY
);
574 State
= ExchangePtr((void**)&EffectSlot
->EffectState
, State
);
577 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
579 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
580 /* FIXME: This should be done asynchronously, but since the EffectState
581 * object was changed, it needs an update before its Process method can
583 EffectSlot
->NeedsUpdate
= AL_FALSE
;
584 ALeffectState_Update(EffectSlot
->EffectState
, Context
, EffectSlot
);
585 UnlockContext(Context
);
587 ALeffectState_Destroy(State
);
593 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
595 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
596 UnlockContext(Context
);
597 EffectSlot
->NeedsUpdate
= AL_TRUE
;
602 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
605 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
607 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
608 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
610 // Release effectslot structure
611 ALeffectState_Destroy(temp
->EffectState
);
613 FreeThunkEntry(temp
->effectslot
);
614 memset(temp
, 0, sizeof(ALeffectslot
));