Limit the dry and wet path filter gains to -60dB
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob5d110500f17f3d790fac3b012b0fa05d8a94e435
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);
55 static void ALeffectState_DecRef(ALeffectState *state);
57 #define DO_UPDATEPROPS() do { \
58 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
59 UpdateEffectSlotProps(slot); \
60 else \
61 ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
62 } while(0)
65 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
67 ALCcontext *context;
68 ALeffectslot **tmpslots = NULL;
69 ALsizei cur;
70 ALenum err;
72 context = GetContextRef();
73 if(!context) return;
75 if(!(n >= 0))
76 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
77 tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
79 LockEffectSlotsWrite(context);
80 for(cur = 0;cur < n;cur++)
82 ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
83 err = AL_OUT_OF_MEMORY;
84 if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
86 al_free(slot);
87 UnlockEffectSlotsWrite(context);
89 alDeleteAuxiliaryEffectSlots(cur, effectslots);
90 SET_ERROR_AND_GOTO(context, err, done);
93 err = NewThunkEntry(&slot->id);
94 if(err == AL_NO_ERROR)
95 err = InsertUIntMapEntryNoLock(&context->EffectSlotMap, slot->id, slot);
96 if(err != AL_NO_ERROR)
98 FreeThunkEntry(slot->id);
99 ALeffectState_DecRef(slot->Effect.State);
100 if(slot->Params.EffectState)
101 ALeffectState_DecRef(slot->Params.EffectState);
102 al_free(slot);
103 UnlockEffectSlotsWrite(context);
105 alDeleteAuxiliaryEffectSlots(cur, effectslots);
106 SET_ERROR_AND_GOTO(context, err, done);
109 aluInitEffectPanning(slot);
111 tmpslots[cur] = slot;
112 effectslots[cur] = slot->id;
114 if(n > 0)
116 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
117 struct ALeffectslotArray *newarray = NULL;
118 ALsizei newcount = curarray->count + n;
119 ALCdevice *device;
121 newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
122 newarray->count = newcount;
123 memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
124 if(curarray)
125 memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
127 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
128 almemory_order_acq_rel);
129 device = context->Device;
130 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
131 althrd_yield();
132 al_free(newarray);
134 UnlockEffectSlotsWrite(context);
136 done:
137 al_free(tmpslots);
138 ALCcontext_DecRef(context);
141 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
143 ALCcontext *context;
144 ALeffectslot *slot;
145 ALsizei i;
147 context = GetContextRef();
148 if(!context) return;
150 LockEffectSlotsWrite(context);
151 if(!(n >= 0))
152 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
153 for(i = 0;i < n;i++)
155 if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
156 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
157 if(ReadRef(&slot->ref) != 0)
158 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
161 // All effectslots are valid
162 if(n > 0)
164 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
165 struct ALeffectslotArray *newarray = NULL;
166 ALsizei newcount = curarray->count - n;
167 ALCdevice *device;
168 ALsizei j, k;
170 assert(newcount >= 0);
171 newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
172 newarray->count = newcount;
173 for(i = j = 0;i < newarray->count;)
175 slot = curarray->slot[j++];
176 for(k = 0;k < n;k++)
178 if(slot->id == effectslots[k])
179 break;
181 if(k == n)
182 newarray->slot[i++] = slot;
185 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
186 almemory_order_acq_rel);
187 device = context->Device;
188 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
189 althrd_yield();
190 al_free(newarray);
193 for(i = 0;i < n;i++)
195 if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
196 continue;
197 FreeThunkEntry(slot->id);
199 DeinitEffectSlot(slot);
201 memset(slot, 0, sizeof(*slot));
202 al_free(slot);
205 done:
206 UnlockEffectSlotsWrite(context);
207 ALCcontext_DecRef(context);
210 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
212 ALCcontext *context;
213 ALboolean ret;
215 context = GetContextRef();
216 if(!context) return AL_FALSE;
218 LockEffectSlotsRead(context);
219 ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
220 UnlockEffectSlotsRead(context);
222 ALCcontext_DecRef(context);
224 return ret;
227 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
229 ALCdevice *device;
230 ALCcontext *context;
231 ALeffectslot *slot;
232 ALeffect *effect = NULL;
233 ALenum err;
235 context = GetContextRef();
236 if(!context) return;
238 WriteLock(&context->PropLock);
239 LockEffectSlotsRead(context);
240 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
241 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
242 switch(param)
244 case AL_EFFECTSLOT_EFFECT:
245 device = context->Device;
247 LockEffectsRead(device);
248 effect = (value ? LookupEffect(device, value) : NULL);
249 if(!(value == 0 || effect != NULL))
251 UnlockEffectsRead(device);
252 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
254 err = InitializeEffect(device, slot, effect);
255 UnlockEffectsRead(device);
257 if(err != AL_NO_ERROR)
258 SET_ERROR_AND_GOTO(context, err, done);
259 break;
261 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
262 if(!(value == AL_TRUE || value == AL_FALSE))
263 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
264 slot->AuxSendAuto = value;
265 break;
267 default:
268 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
270 DO_UPDATEPROPS();
272 done:
273 UnlockEffectSlotsRead(context);
274 WriteUnlock(&context->PropLock);
275 ALCcontext_DecRef(context);
278 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
280 ALCcontext *context;
282 switch(param)
284 case AL_EFFECTSLOT_EFFECT:
285 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
286 alAuxiliaryEffectSloti(effectslot, param, values[0]);
287 return;
290 context = GetContextRef();
291 if(!context) return;
293 LockEffectSlotsRead(context);
294 if(LookupEffectSlot(context, effectslot) == NULL)
295 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
296 switch(param)
298 default:
299 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
302 done:
303 UnlockEffectSlotsRead(context);
304 ALCcontext_DecRef(context);
307 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
309 ALCcontext *context;
310 ALeffectslot *slot;
312 context = GetContextRef();
313 if(!context) return;
315 WriteLock(&context->PropLock);
316 LockEffectSlotsRead(context);
317 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
318 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
319 switch(param)
321 case AL_EFFECTSLOT_GAIN:
322 if(!(value >= 0.0f && value <= 1.0f))
323 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
324 slot->Gain = value;
325 break;
327 default:
328 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
330 DO_UPDATEPROPS();
332 done:
333 UnlockEffectSlotsRead(context);
334 WriteUnlock(&context->PropLock);
335 ALCcontext_DecRef(context);
338 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
340 ALCcontext *context;
342 switch(param)
344 case AL_EFFECTSLOT_GAIN:
345 alAuxiliaryEffectSlotf(effectslot, param, values[0]);
346 return;
349 context = GetContextRef();
350 if(!context) return;
352 LockEffectSlotsRead(context);
353 if(LookupEffectSlot(context, effectslot) == NULL)
354 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
355 switch(param)
357 default:
358 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
361 done:
362 UnlockEffectSlotsRead(context);
363 ALCcontext_DecRef(context);
366 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
368 ALCcontext *context;
369 ALeffectslot *slot;
371 context = GetContextRef();
372 if(!context) return;
374 LockEffectSlotsRead(context);
375 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
376 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
377 switch(param)
379 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
380 *value = slot->AuxSendAuto;
381 break;
383 default:
384 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
387 done:
388 UnlockEffectSlotsRead(context);
389 ALCcontext_DecRef(context);
392 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
394 ALCcontext *context;
396 switch(param)
398 case AL_EFFECTSLOT_EFFECT:
399 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
400 alGetAuxiliaryEffectSloti(effectslot, param, values);
401 return;
404 context = GetContextRef();
405 if(!context) return;
407 LockEffectSlotsRead(context);
408 if(LookupEffectSlot(context, effectslot) == NULL)
409 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
410 switch(param)
412 default:
413 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
416 done:
417 UnlockEffectSlotsRead(context);
418 ALCcontext_DecRef(context);
421 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
423 ALCcontext *context;
424 ALeffectslot *slot;
426 context = GetContextRef();
427 if(!context) return;
429 LockEffectSlotsRead(context);
430 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
431 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
432 switch(param)
434 case AL_EFFECTSLOT_GAIN:
435 *value = slot->Gain;
436 break;
438 default:
439 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
442 done:
443 UnlockEffectSlotsRead(context);
444 ALCcontext_DecRef(context);
447 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
449 ALCcontext *context;
451 switch(param)
453 case AL_EFFECTSLOT_GAIN:
454 alGetAuxiliaryEffectSlotf(effectslot, param, values);
455 return;
458 context = GetContextRef();
459 if(!context) return;
461 LockEffectSlotsRead(context);
462 if(LookupEffectSlot(context, effectslot) == NULL)
463 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
464 switch(param)
466 default:
467 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
470 done:
471 UnlockEffectSlotsRead(context);
472 ALCcontext_DecRef(context);
476 void InitEffectFactoryMap(void)
478 InitUIntMap(&EffectStateFactoryMap, INT_MAX);
480 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory);
481 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory);
482 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory);
483 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory);
484 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory);
485 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory);
486 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_ECHO, ALechoStateFactory_getFactory);
487 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory);
488 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory);
489 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory);
490 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory);
491 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory);
494 void DeinitEffectFactoryMap(void)
496 ResetUIntMap(&EffectStateFactoryMap);
500 ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
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;
509 FPUCtl oldMode;
511 factory = getFactoryByType(newtype);
512 if(!factory)
514 ERR("Failed to find factory for effect type 0x%04x\n", newtype);
515 return AL_INVALID_ENUM;
517 State = V0(factory,create)();
518 if(!State) return AL_OUT_OF_MEMORY;
520 SetMixerFPUMode(&oldMode);
521 almtx_lock(&Device->BackendLock);
522 State->OutBuffer = Device->Dry.Buffer;
523 State->OutChannels = Device->Dry.NumChannels;
524 if(V(State,deviceUpdate)(Device) == AL_FALSE)
526 almtx_unlock(&Device->BackendLock);
527 RestoreFPUMode(&oldMode);
528 ALeffectState_DecRef(State);
529 return AL_OUT_OF_MEMORY;
531 almtx_unlock(&Device->BackendLock);
532 RestoreFPUMode(&oldMode);
534 if(!effect)
536 EffectSlot->Effect.Type = AL_EFFECT_NULL;
537 memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
539 else
541 EffectSlot->Effect.Type = effect->type;
542 EffectSlot->Effect.Props = effect->Props;
545 ALeffectState_DecRef(EffectSlot->Effect.State);
546 EffectSlot->Effect.State = State;
548 else if(effect)
549 EffectSlot->Effect.Props = effect->Props;
551 /* Remove state references from old effect slot property updates. */
552 props = ATOMIC_LOAD_SEQ(&EffectSlot->FreeList);
553 while(props)
555 if(props->State)
556 ALeffectState_DecRef(props->State);
557 props->State = NULL;
558 props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
561 return AL_NO_ERROR;
565 static void ALeffectState_IncRef(ALeffectState *state)
567 uint ref;
568 ref = IncrementRef(&state->Ref);
569 TRACEREF("%p increasing refcount to %u\n", state, ref);
572 static void ALeffectState_DecRef(ALeffectState *state)
574 uint ref;
575 ref = DecrementRef(&state->Ref);
576 TRACEREF("%p decreasing refcount to %u\n", state, ref);
577 if(ref == 0) DELETE_OBJ(state);
581 void ALeffectState_Construct(ALeffectState *state)
583 InitRef(&state->Ref, 1);
585 state->OutBuffer = NULL;
586 state->OutChannels = 0;
589 void ALeffectState_Destruct(ALeffectState *UNUSED(state))
594 ALenum InitEffectSlot(ALeffectslot *slot)
596 ALeffectStateFactory *factory;
598 slot->Effect.Type = AL_EFFECT_NULL;
600 factory = getFactoryByType(AL_EFFECT_NULL);
601 if(!(slot->Effect.State=V0(factory,create)()))
602 return AL_OUT_OF_MEMORY;
604 slot->Gain = 1.0;
605 slot->AuxSendAuto = AL_TRUE;
606 ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_relaxed);
607 InitRef(&slot->ref, 0);
609 ATOMIC_INIT(&slot->Update, NULL);
610 ATOMIC_INIT(&slot->FreeList, NULL);
612 slot->Params.Gain = 1.0f;
613 slot->Params.AuxSendAuto = AL_TRUE;
614 ALeffectState_IncRef(slot->Effect.State);
615 slot->Params.EffectState = slot->Effect.State;
616 slot->Params.RoomRolloff = 0.0f;
617 slot->Params.DecayTime = 0.0f;
618 slot->Params.AirAbsorptionGainHF = 1.0f;
620 return AL_NO_ERROR;
623 void DeinitEffectSlot(ALeffectslot *slot)
625 struct ALeffectslotProps *props;
626 size_t count = 0;
628 props = ATOMIC_LOAD_SEQ(&slot->Update);
629 if(props)
631 if(props->State) ALeffectState_DecRef(props->State);
632 TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
633 al_free(props);
635 props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
636 while(props)
638 struct ALeffectslotProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
639 if(props->State) ALeffectState_DecRef(props->State);
640 al_free(props);
641 props = next;
642 ++count;
644 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
646 ALeffectState_DecRef(slot->Effect.State);
647 if(slot->Params.EffectState)
648 ALeffectState_DecRef(slot->Params.EffectState);
651 void UpdateEffectSlotProps(ALeffectslot *slot)
653 struct ALeffectslotProps *props;
654 ALeffectState *oldstate;
656 /* Get an unused property container, or allocate a new one as needed. */
657 props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
658 if(!props)
659 props = al_calloc(16, sizeof(*props));
660 else
662 struct ALeffectslotProps *next;
663 do {
664 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
665 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next,
666 almemory_order_seq_cst, almemory_order_acquire) == 0);
669 /* Copy in current property values. */
670 props->Gain = slot->Gain;
671 props->AuxSendAuto = slot->AuxSendAuto;
673 props->Type = slot->Effect.Type;
674 props->Props = slot->Effect.Props;
675 /* Swap out any stale effect state object there may be in the container, to
676 * delete it.
678 ALeffectState_IncRef(slot->Effect.State);
679 oldstate = props->State;
680 props->State = slot->Effect.State;
682 /* Set the new container for updating internal parameters. */
683 props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel);
684 if(props)
686 /* If there was an unused update container, put it back in the
687 * freelist.
689 ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props);
692 if(oldstate)
693 ALeffectState_DecRef(oldstate);
696 void UpdateAllEffectSlotProps(ALCcontext *context)
698 struct ALeffectslotArray *auxslots;
699 ALsizei i;
701 LockEffectSlotsRead(context);
702 auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
703 for(i = 0;i < auxslots->count;i++)
705 ALeffectslot *slot = auxslots->slot[i];
706 if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
707 UpdateEffectSlotProps(slot);
709 UnlockEffectSlotsRead(context);
712 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
714 ALsizei pos;
715 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
717 ALeffectslot *temp = Context->EffectSlotMap.values[pos];
718 Context->EffectSlotMap.values[pos] = NULL;
720 DeinitEffectSlot(temp);
722 FreeThunkEntry(temp->id);
723 memset(temp, 0, sizeof(ALeffectslot));
724 al_free(temp);