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
);
40 AL_API ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
45 Context
= GetContextRef();
48 Device
= Context
->Device
;
49 if(n
< 0 || IsBadWritePtr((void*)effectslots
, n
* sizeof(ALuint
)))
50 alSetError(Context
, AL_INVALID_VALUE
);
56 err
= ResizeEffectSlotArray(Context
, n
);
57 if(err
!= AL_NO_ERROR
)
59 alSetError(Context
, err
);
65 ALeffectslot
*slot
= calloc(1, sizeof(ALeffectslot
));
66 if(!slot
|| !(slot
->EffectState
=NoneCreate()))
69 // We must have run out or memory
70 alSetError(Context
, AL_OUT_OF_MEMORY
);
71 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
76 slot
->AuxSendAuto
= AL_TRUE
;
77 slot
->NeedsUpdate
= AL_FALSE
;
78 for(j
= 0;j
< BUFFERSIZE
;j
++)
79 slot
->WetBuffer
[j
] = 0.0f
;
82 slot
->ClickRemoval
[j
] = 0.0f
;
83 slot
->PendingClicks
[j
] = 0.0f
;
88 err
= ResizeEffectSlotArray(Context
, 1);
89 if(err
== AL_NO_ERROR
)
90 Context
->ActiveEffectSlots
[Context
->ActiveEffectSlotCount
++] = slot
;
91 UnlockContext(Context
);
92 if(err
== AL_NO_ERROR
)
93 err
= NewThunkEntry(&slot
->effectslot
);
94 if(err
== AL_NO_ERROR
)
95 err
= InsertUIntMapEntry(&Context
->EffectSlotMap
, slot
->effectslot
, slot
);
96 if(err
!= AL_NO_ERROR
)
98 RemoveEffectSlotArray(Context
, slot
);
99 FreeThunkEntry(slot
->effectslot
);
100 ALeffectState_Destroy(slot
->EffectState
);
103 alSetError(Context
, err
);
104 alDeleteAuxiliaryEffectSlots(i
, effectslots
);
108 effectslots
[i
] = slot
->effectslot
;
112 ALCcontext_DecRef(Context
);
115 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, const ALuint
*effectslots
)
118 ALeffectslot
*EffectSlot
;
121 Context
= GetContextRef();
125 alSetError(Context
, AL_INVALID_VALUE
);
128 // Check that all effectslots are valid
131 if((EffectSlot
=LookupEffectSlot(Context
, effectslots
[i
])) == NULL
)
133 alSetError(Context
, AL_INVALID_NAME
);
137 else if(EffectSlot
->ref
!= 0)
139 alSetError(Context
, AL_INVALID_OPERATION
);
145 // All effectslots are valid
148 // Recheck that the effectslot is valid, because there could be duplicated names
149 if((EffectSlot
=RemoveEffectSlot(Context
, effectslots
[i
])) == NULL
)
151 FreeThunkEntry(EffectSlot
->effectslot
);
153 RemoveEffectSlotArray(Context
, EffectSlot
);
154 ALeffectState_Destroy(EffectSlot
->EffectState
);
156 memset(EffectSlot
, 0, sizeof(ALeffectslot
));
161 ALCcontext_DecRef(Context
);
164 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
169 Context
= GetContextRef();
170 if(!Context
) return AL_FALSE
;
172 result
= (LookupEffectSlot(Context
, effectslot
) ? AL_TRUE
: AL_FALSE
);
174 ALCcontext_DecRef(Context
);
179 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint iValue
)
183 ALeffectslot
*EffectSlot
;
185 Context
= GetContextRef();
188 Device
= Context
->Device
;
189 if((EffectSlot
=LookupEffectSlot(Context
, effectslot
)) != NULL
)
193 case AL_EFFECTSLOT_EFFECT
: {
194 ALeffect
*effect
= NULL
;
197 (effect
=LookupEffect(Device
, iValue
)) != NULL
)
199 InitializeEffect(Context
, EffectSlot
, effect
);
200 Context
->UpdateSources
= AL_TRUE
;
203 alSetError(Context
, AL_INVALID_VALUE
);
206 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
207 if(iValue
== AL_TRUE
|| iValue
== AL_FALSE
)
209 EffectSlot
->AuxSendAuto
= iValue
;
210 Context
->UpdateSources
= AL_TRUE
;
213 alSetError(Context
, AL_INVALID_VALUE
);
217 alSetError(Context
, AL_INVALID_ENUM
);
222 alSetError(Context
, AL_INVALID_NAME
);
224 ALCcontext_DecRef(Context
);
227 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, const ALint
*piValues
)
233 case AL_EFFECTSLOT_EFFECT
:
234 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
235 alAuxiliaryEffectSloti(effectslot
, param
, piValues
[0]);
239 Context
= GetContextRef();
242 if(LookupEffectSlot(Context
, effectslot
) != NULL
)
247 alSetError(Context
, AL_INVALID_ENUM
);
252 alSetError(Context
, AL_INVALID_NAME
);
254 ALCcontext_DecRef(Context
);
257 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat flValue
)
260 ALeffectslot
*EffectSlot
;
262 Context
= GetContextRef();
265 if((EffectSlot
=LookupEffectSlot(Context
, effectslot
)) != NULL
)
269 case AL_EFFECTSLOT_GAIN
:
270 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
272 EffectSlot
->Gain
= flValue
;
273 EffectSlot
->NeedsUpdate
= AL_TRUE
;
276 alSetError(Context
, AL_INVALID_VALUE
);
280 alSetError(Context
, AL_INVALID_ENUM
);
285 alSetError(Context
, AL_INVALID_NAME
);
287 ALCcontext_DecRef(Context
);
290 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, const ALfloat
*pflValues
)
296 case AL_EFFECTSLOT_GAIN
:
297 alAuxiliaryEffectSlotf(effectslot
, param
, pflValues
[0]);
301 Context
= GetContextRef();
304 if(LookupEffectSlot(Context
, effectslot
) != NULL
)
309 alSetError(Context
, AL_INVALID_ENUM
);
314 alSetError(Context
, AL_INVALID_NAME
);
316 ALCcontext_DecRef(Context
);
319 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*piValue
)
322 ALeffectslot
*EffectSlot
;
324 Context
= GetContextRef();
327 if((EffectSlot
=LookupEffectSlot(Context
, effectslot
)) != NULL
)
331 case AL_EFFECTSLOT_EFFECT
:
332 *piValue
= EffectSlot
->effect
.effect
;
335 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
336 *piValue
= EffectSlot
->AuxSendAuto
;
340 alSetError(Context
, AL_INVALID_ENUM
);
345 alSetError(Context
, AL_INVALID_NAME
);
347 ALCcontext_DecRef(Context
);
350 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*piValues
)
356 case AL_EFFECTSLOT_EFFECT
:
357 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
358 alGetAuxiliaryEffectSloti(effectslot
, param
, piValues
);
362 Context
= GetContextRef();
365 if(LookupEffectSlot(Context
, effectslot
) != NULL
)
370 alSetError(Context
, AL_INVALID_ENUM
);
375 alSetError(Context
, AL_INVALID_NAME
);
377 ALCcontext_DecRef(Context
);
380 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*pflValue
)
383 ALeffectslot
*EffectSlot
;
385 Context
= GetContextRef();
388 if((EffectSlot
=LookupEffectSlot(Context
, effectslot
)) != NULL
)
392 case AL_EFFECTSLOT_GAIN
:
393 *pflValue
= EffectSlot
->Gain
;
397 alSetError(Context
, AL_INVALID_ENUM
);
402 alSetError(Context
, AL_INVALID_NAME
);
404 ALCcontext_DecRef(Context
);
407 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*pflValues
)
413 case AL_EFFECTSLOT_GAIN
:
414 alGetAuxiliaryEffectSlotf(effectslot
, param
, pflValues
);
418 Context
= GetContextRef();
421 if(LookupEffectSlot(Context
, effectslot
) != NULL
)
426 alSetError(Context
, AL_INVALID_ENUM
);
431 alSetError(Context
, AL_INVALID_NAME
);
433 ALCcontext_DecRef(Context
);
437 static ALvoid
NoneDestroy(ALeffectState
*State
)
439 static ALboolean
NoneDeviceUpdate(ALeffectState
*State
, ALCdevice
*Device
)
445 static ALvoid
NoneUpdate(ALeffectState
*State
, ALCcontext
*Context
, const ALeffectslot
*Slot
)
451 static ALvoid
NoneProcess(ALeffectState
*State
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[MAXCHANNELS
])
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
;
475 static ALvoid
RemoveEffectSlotArray(ALCcontext
*Context
, ALeffectslot
*slot
)
477 ALeffectslot
**slotlist
, **slotlistend
;
479 LockContext(Context
);
480 slotlist
= Context
->ActiveEffectSlots
;
481 slotlistend
= slotlist
+ Context
->ActiveEffectSlotCount
;
482 while(slotlist
!= slotlistend
)
484 if(*slotlist
== slot
)
486 *slotlist
= *(--slotlistend
);
487 Context
->ActiveEffectSlotCount
--;
492 UnlockContext(Context
);
495 static ALenum
ResizeEffectSlotArray(ALCcontext
*Context
, ALsizei count
)
500 if(count
<= Context
->MaxActiveEffectSlots
-Context
->ActiveEffectSlotCount
)
503 newcount
= Context
->MaxActiveEffectSlots
?
504 (Context
->MaxActiveEffectSlots
<<1) : 1;
505 if(newcount
<= Context
->MaxActiveEffectSlots
||
506 !(temp
=realloc(Context
->ActiveEffectSlots
, newcount
*
507 sizeof(*Context
->ActiveEffectSlots
))))
508 return AL_OUT_OF_MEMORY
;
510 Context
->ActiveEffectSlots
= temp
;
511 Context
->MaxActiveEffectSlots
= newcount
;
515 static ALvoid
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
517 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
518 ALeffectState
*State
= NULL
;
519 ALenum err
= AL_NO_ERROR
;
521 LockContext(Context
);
522 if(newtype
== AL_EFFECT_NULL
&& EffectSlot
->effect
.type
!= AL_EFFECT_NULL
)
524 State
= NoneCreate();
525 if(!State
) err
= AL_OUT_OF_MEMORY
;
527 else if(newtype
== AL_EFFECT_EAXREVERB
|| newtype
== AL_EFFECT_REVERB
)
529 if(EffectSlot
->effect
.type
!= AL_EFFECT_EAXREVERB
&& EffectSlot
->effect
.type
!= AL_EFFECT_REVERB
)
531 State
= ReverbCreate();
532 if(!State
) err
= AL_OUT_OF_MEMORY
;
535 else if(newtype
== AL_EFFECT_ECHO
&& EffectSlot
->effect
.type
!= AL_EFFECT_ECHO
)
537 State
= EchoCreate();
538 if(!State
) err
= AL_OUT_OF_MEMORY
;
540 else if(newtype
== AL_EFFECT_RING_MODULATOR
&& EffectSlot
->effect
.type
!= AL_EFFECT_RING_MODULATOR
)
542 State
= ModulatorCreate();
543 if(!State
) err
= AL_OUT_OF_MEMORY
;
545 else if(newtype
== AL_EFFECT_DEDICATED_DIALOGUE
|| newtype
== AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
)
547 if(EffectSlot
->effect
.type
!= AL_EFFECT_DEDICATED_DIALOGUE
&& EffectSlot
->effect
.type
!= AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
)
549 State
= DedicatedCreate();
550 if(!State
) err
= AL_OUT_OF_MEMORY
;
554 if(err
!= AL_NO_ERROR
)
556 UnlockContext(Context
);
557 alSetError(Context
, err
);
564 oldMode
= SetMixerFPUMode();
566 if(ALeffectState_DeviceUpdate(State
, Context
->Device
) == AL_FALSE
)
568 UnlockContext(Context
);
569 ALeffectState_Destroy(State
);
570 alSetError(Context
, AL_OUT_OF_MEMORY
);
573 State
= ExchangePtr((void**)&EffectSlot
->EffectState
, State
);
576 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
578 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
579 /* FIXME: This should be done asynchronously, but since the EffectState
580 * object was changed, it needs an update before its Process method can
582 EffectSlot
->NeedsUpdate
= AL_FALSE
;
583 ALeffectState_Update(EffectSlot
->EffectState
, Context
, EffectSlot
);
584 UnlockContext(Context
);
586 RestoreFPUMode(oldMode
);
588 ALeffectState_Destroy(State
);
594 memset(&EffectSlot
->effect
, 0, sizeof(EffectSlot
->effect
));
596 memcpy(&EffectSlot
->effect
, effect
, sizeof(*effect
));
597 UnlockContext(Context
);
598 EffectSlot
->NeedsUpdate
= AL_TRUE
;
603 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
606 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
608 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
609 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
611 // Release effectslot structure
612 ALeffectState_Destroy(temp
->EffectState
);
614 FreeThunkEntry(temp
->effectslot
);
615 memset(temp
, 0, sizeof(ALeffectslot
));