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
= context
->ActiveEffectSlots
;
384 slotlistend
= slotlist
+ context
->ActiveEffectSlotCount
;
385 while(slotlist
!= slotlistend
)
387 if(*slotlist
== slot
)
389 *slotlist
= *(--slotlistend
);
390 context
->ActiveEffectSlotCount
--;
395 UnlockContext(context
);
398 static ALenum
AddEffectSlotArray(ALCcontext
*context
, ALsizei count
, const ALuint
*slots
)
402 LockContext(context
);
403 if(count
> context
->MaxActiveEffectSlots
-context
->ActiveEffectSlotCount
)
408 newcount
= context
->MaxActiveEffectSlots
? (context
->MaxActiveEffectSlots
<<1) : 1;
409 if(newcount
> context
->MaxActiveEffectSlots
)
410 temp
= realloc(context
->ActiveEffectSlots
,
411 newcount
* sizeof(*context
->ActiveEffectSlots
));
414 UnlockContext(context
);
415 return AL_OUT_OF_MEMORY
;
417 context
->ActiveEffectSlots
= temp
;
418 context
->MaxActiveEffectSlots
= newcount
;
420 for(i
= 0;i
< count
;i
++)
422 ALeffectslot
*slot
= LookupEffectSlot(context
, slots
[i
]);
423 assert(slot
!= NULL
);
424 context
->ActiveEffectSlots
[context
->ActiveEffectSlotCount
++] = slot
;
426 UnlockContext(context
);
431 void InitEffectFactoryMap(void)
433 InitUIntMap(&EffectStateFactoryMap
, ~0);
435 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_NULL
, ALnullStateFactory_getFactory
);
436 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_EAXREVERB
, ALreverbStateFactory_getFactory
);
437 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_REVERB
, ALreverbStateFactory_getFactory
);
438 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_AUTOWAH
, ALautowahStateFactory_getFactory
);
439 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_CHORUS
, ALchorusStateFactory_getFactory
);
440 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_COMPRESSOR
, ALcompressorStateFactory_getFactory
);
441 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DISTORTION
, ALdistortionStateFactory_getFactory
);
442 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_ECHO
, ALechoStateFactory_getFactory
);
443 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_EQUALIZER
, ALequalizerStateFactory_getFactory
);
444 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_FLANGER
, ALflangerStateFactory_getFactory
);
445 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_RING_MODULATOR
, ALmodulatorStateFactory_getFactory
);
446 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DEDICATED_DIALOGUE
, ALdedicatedStateFactory_getFactory
);
447 InsertUIntMapEntry(&EffectStateFactoryMap
, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
, ALdedicatedStateFactory_getFactory
);
450 void DeinitEffectFactoryMap(void)
452 ResetUIntMap(&EffectStateFactoryMap
);
456 ALenum
InitializeEffect(ALCdevice
*Device
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
458 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
459 ALeffectStateFactory
*factory
;
461 if(newtype
!= EffectSlot
->EffectType
)
463 ALeffectState
*State
;
466 factory
= getFactoryByType(newtype
);
469 ERR("Failed to find factory for effect type 0x%04x\n", newtype
);
470 return AL_INVALID_ENUM
;
472 State
= V0(factory
,create
)();
474 return AL_OUT_OF_MEMORY
;
476 SetMixerFPUMode(&oldMode
);
478 ALCdevice_Lock(Device
);
479 if(V(State
,deviceUpdate
)(Device
) == AL_FALSE
)
481 ALCdevice_Unlock(Device
);
482 RestoreFPUMode(&oldMode
);
484 return AL_OUT_OF_MEMORY
;
487 State
= ExchangePtr((XchgPtr
*)&EffectSlot
->EffectState
, State
);
490 memset(&EffectSlot
->EffectProps
, 0, sizeof(EffectSlot
->EffectProps
));
491 EffectSlot
->EffectType
= AL_EFFECT_NULL
;
495 memcpy(&EffectSlot
->EffectProps
, &effect
->Props
, sizeof(effect
->Props
));
496 EffectSlot
->EffectType
= effect
->type
;
499 /* FIXME: This should be done asynchronously, but since the EffectState
500 * object was changed, it needs an update before its Process method can
502 EffectSlot
->NeedsUpdate
= AL_FALSE
;
503 V(EffectSlot
->EffectState
,update
)(Device
, EffectSlot
);
504 ALCdevice_Unlock(Device
);
506 RestoreFPUMode(&oldMode
);
515 ALCdevice_Lock(Device
);
516 memcpy(&EffectSlot
->EffectProps
, &effect
->Props
, sizeof(effect
->Props
));
517 ALCdevice_Unlock(Device
);
518 EffectSlot
->NeedsUpdate
= AL_TRUE
;
526 ALenum
InitEffectSlot(ALeffectslot
*slot
)
528 ALeffectStateFactory
*factory
;
531 slot
->EffectType
= AL_EFFECT_NULL
;
533 factory
= getFactoryByType(AL_EFFECT_NULL
);
534 if(!(slot
->EffectState
=V0(factory
,create
)()))
535 return AL_OUT_OF_MEMORY
;
538 slot
->AuxSendAuto
= AL_TRUE
;
539 slot
->NeedsUpdate
= AL_FALSE
;
542 for(i
= 0;i
< BUFFERSIZE
;i
++)
543 slot
->WetBuffer
[c
][i
] = 0.0f
;
544 slot
->ClickRemoval
[c
] = 0.0f
;
545 slot
->PendingClicks
[c
] = 0.0f
;
552 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*Context
)
555 for(pos
= 0;pos
< Context
->EffectSlotMap
.size
;pos
++)
557 ALeffectslot
*temp
= Context
->EffectSlotMap
.array
[pos
].value
;
558 Context
->EffectSlotMap
.array
[pos
].value
= NULL
;
560 DELETE_OBJ(temp
->EffectState
);
562 FreeThunkEntry(temp
->id
);
563 memset(temp
, 0, sizeof(ALeffectslot
));