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
, const_vector_ALeffectslotPtr slots
);
39 static void RemoveEffectSlotArray(ALCcontext
*Context
, const 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
)
55 vector_ALeffectslotPtr slotvec
;
59 context
= GetContextRef();
65 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
66 if(!VECTOR_RESERVE(slotvec
, n
))
67 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
69 for(cur
= 0;cur
< n
;cur
++)
71 ALeffectslot
*slot
= al_calloc(16, sizeof(ALeffectslot
));
72 err
= AL_OUT_OF_MEMORY
;
73 if(!slot
|| (err
=InitEffectSlot(slot
)) != AL_NO_ERROR
)
76 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
77 SET_ERROR_AND_GOTO(context
, err
, done
);
80 err
= NewThunkEntry(&slot
->id
);
81 if(err
== AL_NO_ERROR
)
82 err
= InsertUIntMapEntry(&context
->EffectSlotMap
, slot
->id
, slot
);
83 if(err
!= AL_NO_ERROR
)
85 FreeThunkEntry(slot
->id
);
86 DELETE_OBJ(slot
->EffectState
);
89 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
90 SET_ERROR_AND_GOTO(context
, err
, done
);
93 VECTOR_PUSH_BACK(slotvec
, slot
);
95 effectslots
[cur
] = slot
->id
;
97 err
= AddEffectSlotArray(context
, slotvec
);
98 if(err
!= AL_NO_ERROR
)
100 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
101 SET_ERROR_AND_GOTO(context
, err
, done
);
105 VECTOR_DEINIT(slotvec
);
107 ALCcontext_DecRef(context
);
110 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, const ALuint
*effectslots
)
116 context
= GetContextRef();
120 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
123 if((slot
=LookupEffectSlot(context
, effectslots
[i
])) == NULL
)
124 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
125 if(ReadRef(&slot
->ref
) != 0)
126 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
129 // All effectslots are valid
132 if((slot
=RemoveEffectSlot(context
, effectslots
[i
])) == NULL
)
134 FreeThunkEntry(slot
->id
);
136 RemoveEffectSlotArray(context
, slot
);
137 DELETE_OBJ(slot
->EffectState
);
139 memset(slot
, 0, sizeof(*slot
));
144 ALCcontext_DecRef(context
);
147 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
152 context
= GetContextRef();
153 if(!context
) return AL_FALSE
;
155 ret
= (LookupEffectSlot(context
, effectslot
) ? AL_TRUE
: AL_FALSE
);
157 ALCcontext_DecRef(context
);
162 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint value
)
167 ALeffect
*effect
= NULL
;
170 context
= GetContextRef();
173 device
= context
->Device
;
174 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
175 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
178 case AL_EFFECTSLOT_EFFECT
:
179 effect
= (value
? LookupEffect(device
, value
) : NULL
);
180 if(!(value
== 0 || effect
!= NULL
))
181 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
183 err
= InitializeEffect(device
, slot
, effect
);
184 if(err
!= AL_NO_ERROR
)
185 SET_ERROR_AND_GOTO(context
, err
, done
);
186 context
->UpdateSources
= AL_TRUE
;
189 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
190 if(!(value
== AL_TRUE
|| value
== AL_FALSE
))
191 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
193 slot
->AuxSendAuto
= value
;
194 context
->UpdateSources
= AL_TRUE
;
198 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
202 ALCcontext_DecRef(context
);
205 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, const ALint
*values
)
211 case AL_EFFECTSLOT_EFFECT
:
212 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
213 alAuxiliaryEffectSloti(effectslot
, param
, values
[0]);
217 context
= GetContextRef();
220 if(LookupEffectSlot(context
, effectslot
) == NULL
)
221 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
225 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
229 ALCcontext_DecRef(context
);
232 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat value
)
237 context
= GetContextRef();
240 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
241 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
244 case AL_EFFECTSLOT_GAIN
:
245 if(!(value
>= 0.0f
&& value
<= 1.0f
))
246 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
249 slot
->NeedsUpdate
= AL_TRUE
;
253 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
257 ALCcontext_DecRef(context
);
260 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, const ALfloat
*values
)
266 case AL_EFFECTSLOT_GAIN
:
267 alAuxiliaryEffectSlotf(effectslot
, param
, values
[0]);
271 context
= GetContextRef();
274 if(LookupEffectSlot(context
, effectslot
) == NULL
)
275 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
279 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
283 ALCcontext_DecRef(context
);
286 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*value
)
291 context
= GetContextRef();
294 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
295 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
298 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
299 *value
= slot
->AuxSendAuto
;
303 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
307 ALCcontext_DecRef(context
);
310 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*values
)
316 case AL_EFFECTSLOT_EFFECT
:
317 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
318 alGetAuxiliaryEffectSloti(effectslot
, param
, values
);
322 context
= GetContextRef();
325 if(LookupEffectSlot(context
, effectslot
) == NULL
)
326 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
330 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
334 ALCcontext_DecRef(context
);
337 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*value
)
342 context
= GetContextRef();
345 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
346 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
349 case AL_EFFECTSLOT_GAIN
:
354 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
358 ALCcontext_DecRef(context
);
361 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*values
)
367 case AL_EFFECTSLOT_GAIN
:
368 alGetAuxiliaryEffectSlotf(effectslot
, param
, values
);
372 context
= GetContextRef();
375 if(LookupEffectSlot(context
, effectslot
) == NULL
)
376 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
380 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
384 ALCcontext_DecRef(context
);
388 static ALenum
AddEffectSlotArray(ALCcontext
*context
, const_vector_ALeffectslotPtr slots
)
390 ALenum err
= AL_NO_ERROR
;
392 LockContext(context
);
393 if(!VECTOR_INSERT(context
->ActiveAuxSlots
, VECTOR_ITER_END(context
->ActiveAuxSlots
),
394 VECTOR_ITER_BEGIN(slots
), VECTOR_ITER_END(slots
)))
395 err
= AL_OUT_OF_MEMORY
;
396 UnlockContext(context
);
401 static void RemoveEffectSlotArray(ALCcontext
*context
, const ALeffectslot
*slot
)
403 ALeffectslot
**slotlist
, **slotlistend
;
405 LockContext(context
);
406 slotlist
= VECTOR_ITER_BEGIN(context
->ActiveAuxSlots
);
407 slotlistend
= VECTOR_ITER_END(context
->ActiveAuxSlots
);
408 while(slotlist
!= slotlistend
)
410 if(*slotlist
== slot
)
412 *slotlist
= VECTOR_BACK(context
->ActiveAuxSlots
);
413 VECTOR_POP_BACK(context
->ActiveAuxSlots
);
418 UnlockContext(context
);
422 void InitEffectFactoryMap(void)
424 InitUIntMap(&EffectStateFactoryMap
, ~0);
426 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_NULL
, ALnullStateFactory_getFactory
);
427 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_EAXREVERB
, ALreverbStateFactory_getFactory
);
428 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_REVERB
, ALreverbStateFactory_getFactory
);
429 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_AUTOWAH
, ALautowahStateFactory_getFactory
);
430 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_CHORUS
, ALchorusStateFactory_getFactory
);
431 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_COMPRESSOR
, ALcompressorStateFactory_getFactory
);
432 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DISTORTION
, ALdistortionStateFactory_getFactory
);
433 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_ECHO
, ALechoStateFactory_getFactory
);
434 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_EQUALIZER
, ALequalizerStateFactory_getFactory
);
435 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_FLANGER
, ALflangerStateFactory_getFactory
);
436 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_RING_MODULATOR
, ALmodulatorStateFactory_getFactory
);
437 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DEDICATED_DIALOGUE
, ALdedicatedStateFactory_getFactory
);
438 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
, ALdedicatedStateFactory_getFactory
);
441 void DeinitEffectFactoryMap(void)
443 ResetUIntMap(&EffectStateFactoryMap
);
447 ALenum
InitializeEffect(ALCdevice
*Device
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
449 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
450 ALeffectStateFactory
*factory
;
452 if(newtype
!= EffectSlot
->EffectType
)
454 ALeffectState
*State
;
457 factory
= getFactoryByType(newtype
);
460 ERR("Failed to find factory for effect type 0x%04x\n", newtype
);
461 return AL_INVALID_ENUM
;
463 State
= V0(factory
,create
)();
465 return AL_OUT_OF_MEMORY
;
467 SetMixerFPUMode(&oldMode
);
469 ALCdevice_Lock(Device
);
470 if(V(State
,deviceUpdate
)(Device
) == AL_FALSE
)
472 ALCdevice_Unlock(Device
);
473 RestoreFPUMode(&oldMode
);
475 return AL_OUT_OF_MEMORY
;
478 State
= ExchangePtr((XchgPtr
*)&EffectSlot
->EffectState
, State
);
481 memset(&EffectSlot
->EffectProps
, 0, sizeof(EffectSlot
->EffectProps
));
482 EffectSlot
->EffectType
= AL_EFFECT_NULL
;
486 memcpy(&EffectSlot
->EffectProps
, &effect
->Props
, sizeof(effect
->Props
));
487 EffectSlot
->EffectType
= effect
->type
;
490 /* FIXME: This should be done asynchronously, but since the EffectState
491 * object was changed, it needs an update before its Process method can
493 EffectSlot
->NeedsUpdate
= AL_FALSE
;
494 V(EffectSlot
->EffectState
,update
)(Device
, EffectSlot
);
495 ALCdevice_Unlock(Device
);
497 RestoreFPUMode(&oldMode
);
506 ALCdevice_Lock(Device
);
507 memcpy(&EffectSlot
->EffectProps
, &effect
->Props
, sizeof(effect
->Props
));
508 ALCdevice_Unlock(Device
);
509 EffectSlot
->NeedsUpdate
= AL_TRUE
;
517 ALenum
InitEffectSlot(ALeffectslot
*slot
)
519 ALeffectStateFactory
*factory
;
522 slot
->EffectType
= AL_EFFECT_NULL
;
524 factory
= getFactoryByType(AL_EFFECT_NULL
);
525 if(!(slot
->EffectState
=V0(factory
,create
)()))
526 return AL_OUT_OF_MEMORY
;
529 slot
->AuxSendAuto
= AL_TRUE
;
530 slot
->NeedsUpdate
= AL_FALSE
;
533 for(i
= 0;i
< BUFFERSIZE
;i
++)
534 slot
->WetBuffer
[c
][i
] = 0.0f
;
536 InitRef(&slot
->ref
, 0);
541 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
544 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
546 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
547 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
549 DELETE_OBJ(temp
->EffectState
);
551 FreeThunkEntry(temp
->id
);
552 memset(temp
, 0, sizeof(ALeffectslot
));