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 extern inline struct ALeffectslot
*LookupEffectSlot(ALCcontext
*context
, ALuint id
);
36 extern inline struct ALeffectslot
*RemoveEffectSlot(ALCcontext
*context
, ALuint id
);
38 static ALenum
AddEffectSlotArray(ALCcontext
*Context
, ALsizei count
, const ALuint
*slots
);
39 static ALvoid
RemoveEffectSlotArray(ALCcontext
*Context
, ALeffectslot
*slot
);
42 static UIntMap EffectStateFactoryMap
;
43 static inline ALeffectStateFactory
*getFactoryByType(ALenum type
)
45 ALeffectStateFactory
* (*getFactory
)(void) = LookupUIntMapKey(&EffectStateFactoryMap
, type
);
46 if(getFactory
!= NULL
)
52 AL_API ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
58 context
= GetContextRef();
62 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
63 for(cur
= 0;cur
< n
;cur
++)
65 ALeffectslot
*slot
= al_calloc(16, sizeof(ALeffectslot
));
66 err
= AL_OUT_OF_MEMORY
;
67 if(!slot
|| (err
=InitEffectSlot(slot
)) != AL_NO_ERROR
)
70 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
71 SET_ERROR_AND_GOTO(context
, err
, done
);
74 err
= NewThunkEntry(&slot
->id
);
75 if(err
== AL_NO_ERROR
)
76 err
= InsertUIntMapEntry(&context
->EffectSlotMap
, slot
->id
, slot
);
77 if(err
!= AL_NO_ERROR
)
79 FreeThunkEntry(slot
->id
);
80 DELETE_OBJ(slot
->EffectState
);
83 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
84 SET_ERROR_AND_GOTO(context
, err
, done
);
87 effectslots
[cur
] = slot
->id
;
89 err
= AddEffectSlotArray(context
, n
, effectslots
);
90 if(err
!= AL_NO_ERROR
)
92 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
93 SET_ERROR_AND_GOTO(context
, err
, done
);
97 ALCcontext_DecRef(context
);
100 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, const ALuint
*effectslots
)
106 context
= GetContextRef();
110 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
113 if((slot
=LookupEffectSlot(context
, effectslots
[i
])) == NULL
)
114 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
116 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
119 // All effectslots are valid
122 if((slot
=RemoveEffectSlot(context
, effectslots
[i
])) == NULL
)
124 FreeThunkEntry(slot
->id
);
126 RemoveEffectSlotArray(context
, slot
);
127 DELETE_OBJ(slot
->EffectState
);
129 memset(slot
, 0, sizeof(*slot
));
134 ALCcontext_DecRef(context
);
137 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
142 context
= GetContextRef();
143 if(!context
) return AL_FALSE
;
145 ret
= (LookupEffectSlot(context
, effectslot
) ? AL_TRUE
: AL_FALSE
);
147 ALCcontext_DecRef(context
);
152 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint value
)
157 ALeffect
*effect
= NULL
;
160 context
= GetContextRef();
163 device
= context
->Device
;
164 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
165 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
168 case AL_EFFECTSLOT_EFFECT
:
169 effect
= (value
? LookupEffect(device
, value
) : NULL
);
170 if(!(value
== 0 || effect
!= NULL
))
171 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
173 err
= InitializeEffect(device
, slot
, effect
);
174 if(err
!= AL_NO_ERROR
)
175 SET_ERROR_AND_GOTO(context
, err
, done
);
176 context
->UpdateSources
= AL_TRUE
;
179 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
180 if(!(value
== AL_TRUE
|| value
== AL_FALSE
))
181 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
183 slot
->AuxSendAuto
= value
;
184 context
->UpdateSources
= AL_TRUE
;
188 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
192 ALCcontext_DecRef(context
);
195 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, const ALint
*values
)
201 case AL_EFFECTSLOT_EFFECT
:
202 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
203 alAuxiliaryEffectSloti(effectslot
, param
, values
[0]);
207 context
= GetContextRef();
210 if(LookupEffectSlot(context
, effectslot
) == NULL
)
211 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
215 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
219 ALCcontext_DecRef(context
);
222 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat value
)
227 context
= GetContextRef();
230 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
231 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
234 case AL_EFFECTSLOT_GAIN
:
235 if(!(value
>= 0.0f
&& value
<= 1.0f
))
236 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
239 slot
->NeedsUpdate
= AL_TRUE
;
243 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
247 ALCcontext_DecRef(context
);
250 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, const ALfloat
*values
)
256 case AL_EFFECTSLOT_GAIN
:
257 alAuxiliaryEffectSlotf(effectslot
, param
, values
[0]);
261 context
= GetContextRef();
264 if(LookupEffectSlot(context
, effectslot
) == NULL
)
265 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
269 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
273 ALCcontext_DecRef(context
);
276 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*value
)
281 context
= GetContextRef();
284 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
285 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
288 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
289 *value
= slot
->AuxSendAuto
;
293 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
297 ALCcontext_DecRef(context
);
300 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*values
)
306 case AL_EFFECTSLOT_EFFECT
:
307 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
308 alGetAuxiliaryEffectSloti(effectslot
, param
, values
);
312 context
= GetContextRef();
315 if(LookupEffectSlot(context
, effectslot
) == NULL
)
316 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
320 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
324 ALCcontext_DecRef(context
);
327 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*value
)
332 context
= GetContextRef();
335 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
336 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
339 case AL_EFFECTSLOT_GAIN
:
344 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
348 ALCcontext_DecRef(context
);
351 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*values
)
357 case AL_EFFECTSLOT_GAIN
:
358 alGetAuxiliaryEffectSlotf(effectslot
, param
, values
);
362 context
= GetContextRef();
365 if(LookupEffectSlot(context
, effectslot
) == NULL
)
366 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
370 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
374 ALCcontext_DecRef(context
);
378 static ALvoid
RemoveEffectSlotArray(ALCcontext
*context
, ALeffectslot
*slot
)
380 ALeffectslot
**slotlist
, **slotlistend
;
382 LockContext(context
);
383 slotlist
= VECTOR_ITER_BEGIN(context
->ActiveAuxSlots
);
384 slotlistend
= VECTOR_ITER_END(context
->ActiveAuxSlots
);
385 while(slotlist
!= slotlistend
)
387 if(*slotlist
== slot
)
389 *slotlist
= *(--slotlistend
);
390 VECTOR_POP_BACK(context
->ActiveAuxSlots
);
395 UnlockContext(context
);
398 static ALenum
AddEffectSlotArray(ALCcontext
*context
, ALsizei count
, const ALuint
*slots
)
400 ALsizei total
= count
+ VECTOR_SIZE(context
->ActiveAuxSlots
);
402 LockContext(context
);
403 if(total
< VECTOR_SIZE(context
->ActiveAuxSlots
) || VECTOR_RESERVE(context
->ActiveAuxSlots
, total
) == AL_FALSE
)
405 UnlockContext(context
);
406 return AL_OUT_OF_MEMORY
;
409 while(VECTOR_SIZE(context
->ActiveAuxSlots
) < total
)
411 ALeffectslot
*slot
= LookupEffectSlot(context
, *(slots
++));
412 assert(slot
!= NULL
);
413 VECTOR_PUSH_BACK(context
->ActiveAuxSlots
, slot
);
415 UnlockContext(context
);
421 void InitEffectFactoryMap(void)
423 InitUIntMap(&EffectStateFactoryMap
, ~0);
425 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_NULL
, ALnullStateFactory_getFactory
);
426 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_EAXREVERB
, ALreverbStateFactory_getFactory
);
427 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_REVERB
, ALreverbStateFactory_getFactory
);
428 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_AUTOWAH
, ALautowahStateFactory_getFactory
);
429 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_CHORUS
, ALchorusStateFactory_getFactory
);
430 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_COMPRESSOR
, ALcompressorStateFactory_getFactory
);
431 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DISTORTION
, ALdistortionStateFactory_getFactory
);
432 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_ECHO
, ALechoStateFactory_getFactory
);
433 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_EQUALIZER
, ALequalizerStateFactory_getFactory
);
434 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_FLANGER
, ALflangerStateFactory_getFactory
);
435 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_RING_MODULATOR
, ALmodulatorStateFactory_getFactory
);
436 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DEDICATED_DIALOGUE
, ALdedicatedStateFactory_getFactory
);
437 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
, ALdedicatedStateFactory_getFactory
);
440 void DeinitEffectFactoryMap(void)
442 ResetUIntMap(&EffectStateFactoryMap
);
446 ALenum
InitializeEffect(ALCdevice
*Device
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
448 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
449 ALeffectStateFactory
*factory
;
451 if(newtype
!= EffectSlot
->EffectType
)
453 ALeffectState
*State
;
456 factory
= getFactoryByType(newtype
);
459 ERR("Failed to find factory for effect type 0x%04x\n", newtype
);
460 return AL_INVALID_ENUM
;
462 State
= V0(factory
,create
)();
464 return AL_OUT_OF_MEMORY
;
466 SetMixerFPUMode(&oldMode
);
468 ALCdevice_Lock(Device
);
469 if(V(State
,deviceUpdate
)(Device
) == AL_FALSE
)
471 ALCdevice_Unlock(Device
);
472 RestoreFPUMode(&oldMode
);
474 return AL_OUT_OF_MEMORY
;
477 State
= ExchangePtr((XchgPtr
*)&EffectSlot
->EffectState
, State
);
480 memset(&EffectSlot
->EffectProps
, 0, sizeof(EffectSlot
->EffectProps
));
481 EffectSlot
->EffectType
= AL_EFFECT_NULL
;
485 memcpy(&EffectSlot
->EffectProps
, &effect
->Props
, sizeof(effect
->Props
));
486 EffectSlot
->EffectType
= effect
->type
;
489 /* FIXME: This should be done asynchronously, but since the EffectState
490 * object was changed, it needs an update before its Process method can
492 EffectSlot
->NeedsUpdate
= AL_FALSE
;
493 V(EffectSlot
->EffectState
,update
)(Device
, EffectSlot
);
494 ALCdevice_Unlock(Device
);
496 RestoreFPUMode(&oldMode
);
505 ALCdevice_Lock(Device
);
506 memcpy(&EffectSlot
->EffectProps
, &effect
->Props
, sizeof(effect
->Props
));
507 ALCdevice_Unlock(Device
);
508 EffectSlot
->NeedsUpdate
= AL_TRUE
;
516 ALenum
InitEffectSlot(ALeffectslot
*slot
)
518 ALeffectStateFactory
*factory
;
521 slot
->EffectType
= AL_EFFECT_NULL
;
523 factory
= getFactoryByType(AL_EFFECT_NULL
);
524 if(!(slot
->EffectState
=V0(factory
,create
)()))
525 return AL_OUT_OF_MEMORY
;
528 slot
->AuxSendAuto
= AL_TRUE
;
529 slot
->NeedsUpdate
= AL_FALSE
;
532 for(i
= 0;i
< BUFFERSIZE
;i
++)
533 slot
->WetBuffer
[c
][i
] = 0.0f
;
534 slot
->ClickRemoval
[c
] = 0.0f
;
535 slot
->PendingClicks
[c
] = 0.0f
;
542 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
545 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
547 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
548 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
550 DELETE_OBJ(temp
->EffectState
);
552 FreeThunkEntry(temp
->id
);
553 memset(temp
, 0, sizeof(ALeffectslot
));