Re-update effect slots when context properties change
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob1209210045a28808d687d56bbf57079a0f5e036f
1 /**
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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <math.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alThunk.h"
31 #include "alError.h"
32 #include "alListener.h"
33 #include "alSource.h"
35 #include "almalloc.h"
38 extern inline void LockEffectSlotsRead(ALCcontext *context);
39 extern inline void UnlockEffectSlotsRead(ALCcontext *context);
40 extern inline void LockEffectSlotsWrite(ALCcontext *context);
41 extern inline void UnlockEffectSlotsWrite(ALCcontext *context);
42 extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
43 extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
45 static UIntMap EffectStateFactoryMap;
46 static inline ALeffectStateFactory *getFactoryByType(ALenum type)
48 ALeffectStateFactory* (*getFactory)(void) = LookupUIntMapKey(&EffectStateFactoryMap, type);
49 if(getFactory != NULL)
50 return getFactory();
51 return NULL;
54 static void ALeffectState_IncRef(ALeffectState *state);
56 #define DO_UPDATEPROPS() do { \
57 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
58 UpdateEffectSlotProps(slot, context); \
59 else \
60 ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
61 } while(0)
64 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
66 ALCcontext *context;
67 ALeffectslot **tmpslots = NULL;
68 ALsizei cur;
69 ALenum err;
71 context = GetContextRef();
72 if(!context) return;
74 if(!(n >= 0))
75 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
76 tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
78 LockEffectSlotsWrite(context);
79 for(cur = 0;cur < n;cur++)
81 ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
82 err = AL_OUT_OF_MEMORY;
83 if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
85 al_free(slot);
86 UnlockEffectSlotsWrite(context);
88 alDeleteAuxiliaryEffectSlots(cur, effectslots);
89 SET_ERROR_AND_GOTO(context, err, done);
92 err = NewThunkEntry(&slot->id);
93 if(err == AL_NO_ERROR)
94 err = InsertUIntMapEntryNoLock(&context->EffectSlotMap, slot->id, slot);
95 if(err != AL_NO_ERROR)
97 FreeThunkEntry(slot->id);
98 ALeffectState_DecRef(slot->Effect.State);
99 if(slot->Params.EffectState)
100 ALeffectState_DecRef(slot->Params.EffectState);
101 al_free(slot);
102 UnlockEffectSlotsWrite(context);
104 alDeleteAuxiliaryEffectSlots(cur, effectslots);
105 SET_ERROR_AND_GOTO(context, err, done);
108 aluInitEffectPanning(slot);
110 tmpslots[cur] = slot;
111 effectslots[cur] = slot->id;
113 if(n > 0)
115 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
116 struct ALeffectslotArray *newarray = NULL;
117 ALsizei newcount = curarray->count + n;
118 ALCdevice *device;
120 newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
121 newarray->count = newcount;
122 memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
123 if(curarray)
124 memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
126 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
127 almemory_order_acq_rel);
128 device = context->Device;
129 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
130 althrd_yield();
131 al_free(newarray);
133 UnlockEffectSlotsWrite(context);
135 done:
136 al_free(tmpslots);
137 ALCcontext_DecRef(context);
140 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
142 ALCcontext *context;
143 ALeffectslot *slot;
144 ALsizei i;
146 context = GetContextRef();
147 if(!context) return;
149 LockEffectSlotsWrite(context);
150 if(!(n >= 0))
151 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
152 for(i = 0;i < n;i++)
154 if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
155 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
156 if(ReadRef(&slot->ref) != 0)
157 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
160 // All effectslots are valid
161 if(n > 0)
163 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
164 struct ALeffectslotArray *newarray = NULL;
165 ALsizei newcount = curarray->count - n;
166 ALCdevice *device;
167 ALsizei j, k;
169 assert(newcount >= 0);
170 newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
171 newarray->count = newcount;
172 for(i = j = 0;i < newarray->count;)
174 slot = curarray->slot[j++];
175 for(k = 0;k < n;k++)
177 if(slot->id == effectslots[k])
178 break;
180 if(k == n)
181 newarray->slot[i++] = slot;
184 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
185 almemory_order_acq_rel);
186 device = context->Device;
187 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
188 althrd_yield();
189 al_free(newarray);
192 for(i = 0;i < n;i++)
194 if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
195 continue;
196 FreeThunkEntry(slot->id);
198 DeinitEffectSlot(slot);
200 memset(slot, 0, sizeof(*slot));
201 al_free(slot);
204 done:
205 UnlockEffectSlotsWrite(context);
206 ALCcontext_DecRef(context);
209 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
211 ALCcontext *context;
212 ALboolean ret;
214 context = GetContextRef();
215 if(!context) return AL_FALSE;
217 LockEffectSlotsRead(context);
218 ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
219 UnlockEffectSlotsRead(context);
221 ALCcontext_DecRef(context);
223 return ret;
226 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
228 ALCdevice *device;
229 ALCcontext *context;
230 ALeffectslot *slot;
231 ALeffect *effect = NULL;
232 ALenum err;
234 context = GetContextRef();
235 if(!context) return;
237 WriteLock(&context->PropLock);
238 LockEffectSlotsRead(context);
239 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
240 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
241 switch(param)
243 case AL_EFFECTSLOT_EFFECT:
244 device = context->Device;
246 LockEffectsRead(device);
247 effect = (value ? LookupEffect(device, value) : NULL);
248 if(!(value == 0 || effect != NULL))
250 UnlockEffectsRead(device);
251 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
253 err = InitializeEffect(context, slot, effect);
254 UnlockEffectsRead(device);
256 if(err != AL_NO_ERROR)
257 SET_ERROR_AND_GOTO(context, err, done);
258 break;
260 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
261 if(!(value == AL_TRUE || value == AL_FALSE))
262 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
263 slot->AuxSendAuto = value;
264 break;
266 default:
267 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
269 DO_UPDATEPROPS();
271 done:
272 UnlockEffectSlotsRead(context);
273 WriteUnlock(&context->PropLock);
274 ALCcontext_DecRef(context);
277 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
279 ALCcontext *context;
281 switch(param)
283 case AL_EFFECTSLOT_EFFECT:
284 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
285 alAuxiliaryEffectSloti(effectslot, param, values[0]);
286 return;
289 context = GetContextRef();
290 if(!context) return;
292 LockEffectSlotsRead(context);
293 if(LookupEffectSlot(context, effectslot) == NULL)
294 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
295 switch(param)
297 default:
298 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
301 done:
302 UnlockEffectSlotsRead(context);
303 ALCcontext_DecRef(context);
306 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
308 ALCcontext *context;
309 ALeffectslot *slot;
311 context = GetContextRef();
312 if(!context) return;
314 WriteLock(&context->PropLock);
315 LockEffectSlotsRead(context);
316 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
317 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
318 switch(param)
320 case AL_EFFECTSLOT_GAIN:
321 if(!(value >= 0.0f && value <= 1.0f))
322 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
323 slot->Gain = value;
324 break;
326 default:
327 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
329 DO_UPDATEPROPS();
331 done:
332 UnlockEffectSlotsRead(context);
333 WriteUnlock(&context->PropLock);
334 ALCcontext_DecRef(context);
337 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
339 ALCcontext *context;
341 switch(param)
343 case AL_EFFECTSLOT_GAIN:
344 alAuxiliaryEffectSlotf(effectslot, param, values[0]);
345 return;
348 context = GetContextRef();
349 if(!context) return;
351 LockEffectSlotsRead(context);
352 if(LookupEffectSlot(context, effectslot) == NULL)
353 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
354 switch(param)
356 default:
357 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
360 done:
361 UnlockEffectSlotsRead(context);
362 ALCcontext_DecRef(context);
365 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
367 ALCcontext *context;
368 ALeffectslot *slot;
370 context = GetContextRef();
371 if(!context) return;
373 LockEffectSlotsRead(context);
374 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
375 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
376 switch(param)
378 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
379 *value = slot->AuxSendAuto;
380 break;
382 default:
383 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
386 done:
387 UnlockEffectSlotsRead(context);
388 ALCcontext_DecRef(context);
391 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
393 ALCcontext *context;
395 switch(param)
397 case AL_EFFECTSLOT_EFFECT:
398 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
399 alGetAuxiliaryEffectSloti(effectslot, param, values);
400 return;
403 context = GetContextRef();
404 if(!context) return;
406 LockEffectSlotsRead(context);
407 if(LookupEffectSlot(context, effectslot) == NULL)
408 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
409 switch(param)
411 default:
412 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
415 done:
416 UnlockEffectSlotsRead(context);
417 ALCcontext_DecRef(context);
420 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
422 ALCcontext *context;
423 ALeffectslot *slot;
425 context = GetContextRef();
426 if(!context) return;
428 LockEffectSlotsRead(context);
429 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
430 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
431 switch(param)
433 case AL_EFFECTSLOT_GAIN:
434 *value = slot->Gain;
435 break;
437 default:
438 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
441 done:
442 UnlockEffectSlotsRead(context);
443 ALCcontext_DecRef(context);
446 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
448 ALCcontext *context;
450 switch(param)
452 case AL_EFFECTSLOT_GAIN:
453 alGetAuxiliaryEffectSlotf(effectslot, param, values);
454 return;
457 context = GetContextRef();
458 if(!context) return;
460 LockEffectSlotsRead(context);
461 if(LookupEffectSlot(context, effectslot) == NULL)
462 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
463 switch(param)
465 default:
466 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
469 done:
470 UnlockEffectSlotsRead(context);
471 ALCcontext_DecRef(context);
475 void InitEffectFactoryMap(void)
477 InitUIntMap(&EffectStateFactoryMap, INT_MAX);
479 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory);
480 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory);
481 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory);
482 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory);
483 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory);
484 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory);
485 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_ECHO, ALechoStateFactory_getFactory);
486 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory);
487 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory);
488 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory);
489 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory);
490 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory);
493 void DeinitEffectFactoryMap(void)
495 ResetUIntMap(&EffectStateFactoryMap);
499 ALenum InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
501 ALCdevice *Device = Context->Device;
502 ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
503 struct ALeffectslotProps *props;
504 ALeffectState *State;
506 if(newtype != EffectSlot->Effect.Type)
508 ALeffectStateFactory *factory;
510 factory = getFactoryByType(newtype);
511 if(!factory)
513 ERR("Failed to find factory for effect type 0x%04x\n", newtype);
514 return AL_INVALID_ENUM;
516 State = V0(factory,create)();
517 if(!State) return AL_OUT_OF_MEMORY;
519 START_MIXER_MODE();
520 almtx_lock(&Device->BackendLock);
521 State->OutBuffer = Device->Dry.Buffer;
522 State->OutChannels = Device->Dry.NumChannels;
523 if(V(State,deviceUpdate)(Device) == AL_FALSE)
525 almtx_unlock(&Device->BackendLock);
526 LEAVE_MIXER_MODE();
527 ALeffectState_DecRef(State);
528 return AL_OUT_OF_MEMORY;
530 almtx_unlock(&Device->BackendLock);
531 END_MIXER_MODE();
533 if(!effect)
535 EffectSlot->Effect.Type = AL_EFFECT_NULL;
536 memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
538 else
540 EffectSlot->Effect.Type = effect->type;
541 EffectSlot->Effect.Props = effect->Props;
544 ALeffectState_DecRef(EffectSlot->Effect.State);
545 EffectSlot->Effect.State = State;
547 else if(effect)
548 EffectSlot->Effect.Props = effect->Props;
550 /* Remove state references from old effect slot property updates. */
551 props = ATOMIC_LOAD_SEQ(&Context->FreeEffectslotProps);
552 while(props)
554 if(props->State)
555 ALeffectState_DecRef(props->State);
556 props->State = NULL;
557 props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
560 return AL_NO_ERROR;
564 static void ALeffectState_IncRef(ALeffectState *state)
566 uint ref;
567 ref = IncrementRef(&state->Ref);
568 TRACEREF("%p increasing refcount to %u\n", state, ref);
571 void ALeffectState_DecRef(ALeffectState *state)
573 uint ref;
574 ref = DecrementRef(&state->Ref);
575 TRACEREF("%p decreasing refcount to %u\n", state, ref);
576 if(ref == 0) DELETE_OBJ(state);
580 void ALeffectState_Construct(ALeffectState *state)
582 InitRef(&state->Ref, 1);
584 state->OutBuffer = NULL;
585 state->OutChannels = 0;
588 void ALeffectState_Destruct(ALeffectState *UNUSED(state))
593 ALenum InitEffectSlot(ALeffectslot *slot)
595 ALeffectStateFactory *factory;
597 slot->Effect.Type = AL_EFFECT_NULL;
599 factory = getFactoryByType(AL_EFFECT_NULL);
600 if(!(slot->Effect.State=V0(factory,create)()))
601 return AL_OUT_OF_MEMORY;
603 slot->Gain = 1.0;
604 slot->AuxSendAuto = AL_TRUE;
605 ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_relaxed);
606 InitRef(&slot->ref, 0);
608 ATOMIC_INIT(&slot->Update, NULL);
610 slot->Params.Gain = 1.0f;
611 slot->Params.AuxSendAuto = AL_TRUE;
612 ALeffectState_IncRef(slot->Effect.State);
613 slot->Params.EffectState = slot->Effect.State;
614 slot->Params.RoomRolloff = 0.0f;
615 slot->Params.DecayTime = 0.0f;
616 slot->Params.DecayHFRatio = 0.0f;
617 slot->Params.DecayHFLimit = AL_FALSE;
618 slot->Params.AirAbsorptionGainHF = 1.0f;
620 return AL_NO_ERROR;
623 void DeinitEffectSlot(ALeffectslot *slot)
625 struct ALeffectslotProps *props;
627 props = ATOMIC_LOAD_SEQ(&slot->Update);
628 if(props)
630 if(props->State) ALeffectState_DecRef(props->State);
631 TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
632 al_free(props);
635 ALeffectState_DecRef(slot->Effect.State);
636 if(slot->Params.EffectState)
637 ALeffectState_DecRef(slot->Params.EffectState);
640 void UpdateEffectSlotProps(ALeffectslot *slot, ALCcontext *context)
642 struct ALeffectslotProps *props;
643 ALeffectState *oldstate;
645 /* Get an unused property container, or allocate a new one as needed. */
646 props = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
647 if(!props)
648 props = al_calloc(16, sizeof(*props));
649 else
651 struct ALeffectslotProps *next;
652 do {
653 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
654 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeEffectslotProps, &props, next,
655 almemory_order_seq_cst, almemory_order_acquire) == 0);
658 /* Copy in current property values. */
659 props->Gain = slot->Gain;
660 props->AuxSendAuto = slot->AuxSendAuto;
662 props->Type = slot->Effect.Type;
663 props->Props = slot->Effect.Props;
664 /* Swap out any stale effect state object there may be in the container, to
665 * delete it.
667 ALeffectState_IncRef(slot->Effect.State);
668 oldstate = props->State;
669 props->State = slot->Effect.State;
671 /* Set the new container for updating internal parameters. */
672 props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel);
673 if(props)
675 /* If there was an unused update container, put it back in the
676 * freelist.
678 ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
681 if(oldstate)
682 ALeffectState_DecRef(oldstate);
685 void UpdateAllEffectSlotProps(ALCcontext *context)
687 struct ALeffectslotArray *auxslots;
688 ALsizei i;
690 LockEffectSlotsRead(context);
691 auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
692 for(i = 0;i < auxslots->count;i++)
694 ALeffectslot *slot = auxslots->slot[i];
695 if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
696 UpdateEffectSlotProps(slot, context);
698 UnlockEffectSlotsRead(context);
701 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
703 ALsizei pos;
704 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
706 ALeffectslot *temp = Context->EffectSlotMap.values[pos];
707 Context->EffectSlotMap.values[pos] = NULL;
709 DeinitEffectSlot(temp);
711 FreeThunkEntry(temp->id);
712 memset(temp, 0, sizeof(ALeffectslot));
713 al_free(temp);