Add an example for multi-zone reverb
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob038adbb0b81c53a0ffe2d3f60c610ec851a8df9c
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 "alError.h"
31 #include "alListener.h"
32 #include "alSource.h"
34 #include "fpu_modes.h"
35 #include "almalloc.h"
38 extern inline void LockEffectSlotList(ALCcontext *context);
39 extern inline void UnlockEffectSlotList(ALCcontext *context);
41 static const struct {
42 ALenum Type;
43 ALeffectStateFactory* (*GetFactory)(void);
44 } FactoryList[] = {
45 { AL_EFFECT_NULL, ALnullStateFactory_getFactory },
46 { AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory },
47 { AL_EFFECT_REVERB, ALreverbStateFactory_getFactory },
48 { AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory },
49 { AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory },
50 { AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory },
51 { AL_EFFECT_ECHO, ALechoStateFactory_getFactory },
52 { AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory },
53 { AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory },
54 { AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory },
55 { AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory },
56 { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory }
59 static inline ALeffectStateFactory *getFactoryByType(ALenum type)
61 size_t i;
62 for(i = 0;i < COUNTOF(FactoryList);i++)
64 if(FactoryList[i].Type == type)
65 return FactoryList[i].GetFactory();
67 return NULL;
70 static void ALeffectState_IncRef(ALeffectState *state);
73 static inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
75 id--;
76 if(UNLIKELY(id >= VECTOR_SIZE(context->EffectSlotList)))
77 return NULL;
78 return VECTOR_ELEM(context->EffectSlotList, id);
81 static inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
83 EffectSubList *sublist;
84 ALuint lidx = (id-1) >> 6;
85 ALsizei slidx = (id-1) & 0x3f;
87 if(UNLIKELY(lidx >= VECTOR_SIZE(device->EffectList)))
88 return NULL;
89 sublist = &VECTOR_ELEM(device->EffectList, lidx);
90 if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
91 return NULL;
92 return sublist->Effects + slidx;
96 #define DO_UPDATEPROPS() do { \
97 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
98 UpdateEffectSlotProps(slot, context); \
99 else \
100 ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
101 } while(0)
104 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
106 ALCdevice *device;
107 ALCcontext *context;
108 ALeffectslot **tmpslots = NULL;
109 ALsizei cur;
110 ALenum err;
112 context = GetContextRef();
113 if(!context) return;
115 if(!(n >= 0))
116 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Generating %d effect slots", n);
117 tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
119 device = context->Device;
120 LockEffectSlotList(context);
121 if(device->AuxiliaryEffectSlotMax - VECTOR_SIZE(context->EffectSlotList) < (ALuint)n)
123 UnlockEffectSlotList(context);
124 SETERR_GOTO(context, AL_OUT_OF_MEMORY, done, "Exceeding %u auxiliary effect slot limit",
125 device->AuxiliaryEffectSlotMax);
127 for(cur = 0;cur < n;cur++)
129 ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
130 ALeffectslotPtr *end = VECTOR_END(context->EffectSlotList);
131 ALeffectslot *slot = NULL;
133 for(;iter != end;iter++)
135 if(!*iter)
136 break;
138 if(iter == end)
140 if(VECTOR_SIZE(context->EffectSlotList) >= INT_MAX)
142 UnlockEffectSlotList(context);
144 alDeleteAuxiliaryEffectSlots(cur, effectslots);
145 SETERR_GOTO(context, err, done, "Too many effect slot objects");
147 VECTOR_PUSH_BACK(context->EffectSlotList, NULL);
148 iter = &VECTOR_BACK(context->EffectSlotList);
150 slot = al_calloc(16, sizeof(ALeffectslot));
151 err = AL_OUT_OF_MEMORY;
152 if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
154 al_free(slot);
155 UnlockEffectSlotList(context);
157 alDeleteAuxiliaryEffectSlots(cur, effectslots);
158 SETERR_GOTO(context, err, done, "Effect slot object allocation failed");
160 aluInitEffectPanning(slot);
162 slot->id = (iter - VECTOR_BEGIN(context->EffectSlotList)) + 1;
163 *iter = slot;
165 tmpslots[cur] = slot;
166 effectslots[cur] = slot->id;
168 if(n > 0)
170 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
171 struct ALeffectslotArray *newarray = NULL;
172 ALsizei newcount = curarray->count + n;
173 ALCdevice *device;
175 newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
176 newarray->count = newcount;
177 memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
178 if(curarray)
179 memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
181 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
182 almemory_order_acq_rel);
183 device = context->Device;
184 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
185 althrd_yield();
186 al_free(newarray);
188 UnlockEffectSlotList(context);
190 done:
191 al_free(tmpslots);
192 ALCcontext_DecRef(context);
195 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
197 ALCcontext *context;
198 ALeffectslot *slot;
199 ALsizei i;
201 context = GetContextRef();
202 if(!context) return;
204 LockEffectSlotList(context);
205 if(!(n >= 0))
206 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d effect slots", n);
207 for(i = 0;i < n;i++)
209 if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
210 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u",
211 effectslots[i]);
212 if(ReadRef(&slot->ref) != 0)
213 SETERR_GOTO(context, AL_INVALID_NAME, done, "Deleting in-use effect slot %u",
214 effectslots[i]);
217 // All effectslots are valid
218 if(n > 0)
220 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
221 struct ALeffectslotArray *newarray = NULL;
222 ALsizei newcount = curarray->count - n;
223 ALCdevice *device;
224 ALsizei j, k;
226 assert(newcount >= 0);
227 newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
228 newarray->count = newcount;
229 for(i = j = 0;i < newarray->count;)
231 slot = curarray->slot[j++];
232 for(k = 0;k < n;k++)
234 if(slot->id == effectslots[k])
235 break;
237 if(k == n)
238 newarray->slot[i++] = slot;
241 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
242 almemory_order_acq_rel);
243 device = context->Device;
244 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
245 althrd_yield();
246 al_free(newarray);
249 for(i = 0;i < n;i++)
251 if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
252 continue;
253 VECTOR_ELEM(context->EffectSlotList, effectslots[i]-1) = NULL;
255 DeinitEffectSlot(slot);
257 memset(slot, 0, sizeof(*slot));
258 al_free(slot);
261 done:
262 UnlockEffectSlotList(context);
263 ALCcontext_DecRef(context);
266 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
268 ALCcontext *context;
269 ALboolean ret;
271 context = GetContextRef();
272 if(!context) return AL_FALSE;
274 LockEffectSlotList(context);
275 ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
276 UnlockEffectSlotList(context);
278 ALCcontext_DecRef(context);
280 return ret;
283 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
285 ALCdevice *device;
286 ALCcontext *context;
287 ALeffectslot *slot;
288 ALeffect *effect = NULL;
289 ALenum err;
291 context = GetContextRef();
292 if(!context) return;
294 WriteLock(&context->PropLock);
295 LockEffectSlotList(context);
296 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
297 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
298 switch(param)
300 case AL_EFFECTSLOT_EFFECT:
301 device = context->Device;
303 LockEffectList(device);
304 effect = (value ? LookupEffect(device, value) : NULL);
305 if(!(value == 0 || effect != NULL))
307 UnlockEffectList(device);
308 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Invalid effect ID %u", value);
310 err = InitializeEffect(context, slot, effect);
311 UnlockEffectList(device);
313 if(err != AL_NO_ERROR)
314 SETERR_GOTO(context, err, done, "Effect initialization failed");
315 break;
317 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
318 if(!(value == AL_TRUE || value == AL_FALSE))
319 SETERR_GOTO(context, AL_INVALID_VALUE, done,
320 "Effect slot auxiliary send auto out of range");
321 slot->AuxSendAuto = value;
322 break;
324 default:
325 SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid effect slot integer property 0x%04x",
326 param);
328 DO_UPDATEPROPS();
330 done:
331 UnlockEffectSlotList(context);
332 WriteUnlock(&context->PropLock);
333 ALCcontext_DecRef(context);
336 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
338 ALCcontext *context;
340 switch(param)
342 case AL_EFFECTSLOT_EFFECT:
343 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
344 alAuxiliaryEffectSloti(effectslot, param, values[0]);
345 return;
348 context = GetContextRef();
349 if(!context) return;
351 LockEffectSlotList(context);
352 if(LookupEffectSlot(context, effectslot) == NULL)
353 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
354 switch(param)
356 default:
357 alSetError(context, AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x",
358 param);
361 done:
362 UnlockEffectSlotList(context);
363 ALCcontext_DecRef(context);
366 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
368 ALCcontext *context;
369 ALeffectslot *slot;
371 context = GetContextRef();
372 if(!context) return;
374 WriteLock(&context->PropLock);
375 LockEffectSlotList(context);
376 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
377 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
378 switch(param)
380 case AL_EFFECTSLOT_GAIN:
381 if(!(value >= 0.0f && value <= 1.0f))
382 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Effect slot gain out of range");
383 slot->Gain = value;
384 break;
386 default:
387 SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid effect slot float property 0x%04x",
388 param);
390 DO_UPDATEPROPS();
392 done:
393 UnlockEffectSlotList(context);
394 WriteUnlock(&context->PropLock);
395 ALCcontext_DecRef(context);
398 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
400 ALCcontext *context;
402 switch(param)
404 case AL_EFFECTSLOT_GAIN:
405 alAuxiliaryEffectSlotf(effectslot, param, values[0]);
406 return;
409 context = GetContextRef();
410 if(!context) return;
412 LockEffectSlotList(context);
413 if(LookupEffectSlot(context, effectslot) == NULL)
414 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
415 switch(param)
417 default:
418 alSetError(context, AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x",
419 param);
422 done:
423 UnlockEffectSlotList(context);
424 ALCcontext_DecRef(context);
427 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
429 ALCcontext *context;
430 ALeffectslot *slot;
432 context = GetContextRef();
433 if(!context) return;
435 LockEffectSlotList(context);
436 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
437 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
438 switch(param)
440 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
441 *value = slot->AuxSendAuto;
442 break;
444 default:
445 alSetError(context, AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param);
448 done:
449 UnlockEffectSlotList(context);
450 ALCcontext_DecRef(context);
453 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
455 ALCcontext *context;
457 switch(param)
459 case AL_EFFECTSLOT_EFFECT:
460 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
461 alGetAuxiliaryEffectSloti(effectslot, param, values);
462 return;
465 context = GetContextRef();
466 if(!context) return;
468 LockEffectSlotList(context);
469 if(LookupEffectSlot(context, effectslot) == NULL)
470 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
471 switch(param)
473 default:
474 alSetError(context, AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x",
475 param);
478 done:
479 UnlockEffectSlotList(context);
480 ALCcontext_DecRef(context);
483 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
485 ALCcontext *context;
486 ALeffectslot *slot;
488 context = GetContextRef();
489 if(!context) return;
491 LockEffectSlotList(context);
492 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
493 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
494 switch(param)
496 case AL_EFFECTSLOT_GAIN:
497 *value = slot->Gain;
498 break;
500 default:
501 alSetError(context, AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param);
504 done:
505 UnlockEffectSlotList(context);
506 ALCcontext_DecRef(context);
509 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
511 ALCcontext *context;
513 switch(param)
515 case AL_EFFECTSLOT_GAIN:
516 alGetAuxiliaryEffectSlotf(effectslot, param, values);
517 return;
520 context = GetContextRef();
521 if(!context) return;
523 LockEffectSlotList(context);
524 if(LookupEffectSlot(context, effectslot) == NULL)
525 SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
526 switch(param)
528 default:
529 alSetError(context, AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x",
530 param);
533 done:
534 UnlockEffectSlotList(context);
535 ALCcontext_DecRef(context);
539 ALenum InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
541 ALCdevice *Device = Context->Device;
542 ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
543 struct ALeffectslotProps *props;
544 ALeffectState *State;
546 if(newtype != EffectSlot->Effect.Type)
548 ALeffectStateFactory *factory;
550 factory = getFactoryByType(newtype);
551 if(!factory)
553 ERR("Failed to find factory for effect type 0x%04x\n", newtype);
554 return AL_INVALID_ENUM;
556 State = V0(factory,create)();
557 if(!State) return AL_OUT_OF_MEMORY;
559 START_MIXER_MODE();
560 almtx_lock(&Device->BackendLock);
561 State->OutBuffer = Device->Dry.Buffer;
562 State->OutChannels = Device->Dry.NumChannels;
563 if(V(State,deviceUpdate)(Device) == AL_FALSE)
565 almtx_unlock(&Device->BackendLock);
566 LEAVE_MIXER_MODE();
567 ALeffectState_DecRef(State);
568 return AL_OUT_OF_MEMORY;
570 almtx_unlock(&Device->BackendLock);
571 END_MIXER_MODE();
573 if(!effect)
575 EffectSlot->Effect.Type = AL_EFFECT_NULL;
576 memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
578 else
580 EffectSlot->Effect.Type = effect->type;
581 EffectSlot->Effect.Props = effect->Props;
584 ALeffectState_DecRef(EffectSlot->Effect.State);
585 EffectSlot->Effect.State = State;
587 else if(effect)
588 EffectSlot->Effect.Props = effect->Props;
590 /* Remove state references from old effect slot property updates. */
591 props = ATOMIC_LOAD_SEQ(&Context->FreeEffectslotProps);
592 while(props)
594 if(props->State)
595 ALeffectState_DecRef(props->State);
596 props->State = NULL;
597 props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
600 return AL_NO_ERROR;
604 static void ALeffectState_IncRef(ALeffectState *state)
606 uint ref;
607 ref = IncrementRef(&state->Ref);
608 TRACEREF("%p increasing refcount to %u\n", state, ref);
611 void ALeffectState_DecRef(ALeffectState *state)
613 uint ref;
614 ref = DecrementRef(&state->Ref);
615 TRACEREF("%p decreasing refcount to %u\n", state, ref);
616 if(ref == 0) DELETE_OBJ(state);
620 void ALeffectState_Construct(ALeffectState *state)
622 InitRef(&state->Ref, 1);
624 state->OutBuffer = NULL;
625 state->OutChannels = 0;
628 void ALeffectState_Destruct(ALeffectState *UNUSED(state))
633 ALenum InitEffectSlot(ALeffectslot *slot)
635 ALeffectStateFactory *factory;
637 slot->Effect.Type = AL_EFFECT_NULL;
639 factory = getFactoryByType(AL_EFFECT_NULL);
640 if(!(slot->Effect.State=V0(factory,create)()))
641 return AL_OUT_OF_MEMORY;
643 slot->Gain = 1.0;
644 slot->AuxSendAuto = AL_TRUE;
645 ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_relaxed);
646 InitRef(&slot->ref, 0);
648 ATOMIC_INIT(&slot->Update, NULL);
650 slot->Params.Gain = 1.0f;
651 slot->Params.AuxSendAuto = AL_TRUE;
652 ALeffectState_IncRef(slot->Effect.State);
653 slot->Params.EffectState = slot->Effect.State;
654 slot->Params.RoomRolloff = 0.0f;
655 slot->Params.DecayTime = 0.0f;
656 slot->Params.DecayHFRatio = 0.0f;
657 slot->Params.DecayHFLimit = AL_FALSE;
658 slot->Params.AirAbsorptionGainHF = 1.0f;
660 return AL_NO_ERROR;
663 void DeinitEffectSlot(ALeffectslot *slot)
665 struct ALeffectslotProps *props;
667 props = ATOMIC_LOAD_SEQ(&slot->Update);
668 if(props)
670 if(props->State) ALeffectState_DecRef(props->State);
671 TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
672 al_free(props);
675 ALeffectState_DecRef(slot->Effect.State);
676 if(slot->Params.EffectState)
677 ALeffectState_DecRef(slot->Params.EffectState);
680 void UpdateEffectSlotProps(ALeffectslot *slot, ALCcontext *context)
682 struct ALeffectslotProps *props;
683 ALeffectState *oldstate;
685 /* Get an unused property container, or allocate a new one as needed. */
686 props = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
687 if(!props)
688 props = al_calloc(16, sizeof(*props));
689 else
691 struct ALeffectslotProps *next;
692 do {
693 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
694 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeEffectslotProps, &props, next,
695 almemory_order_seq_cst, almemory_order_acquire) == 0);
698 /* Copy in current property values. */
699 props->Gain = slot->Gain;
700 props->AuxSendAuto = slot->AuxSendAuto;
702 props->Type = slot->Effect.Type;
703 props->Props = slot->Effect.Props;
704 /* Swap out any stale effect state object there may be in the container, to
705 * delete it.
707 ALeffectState_IncRef(slot->Effect.State);
708 oldstate = props->State;
709 props->State = slot->Effect.State;
711 /* Set the new container for updating internal parameters. */
712 props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel);
713 if(props)
715 /* If there was an unused update container, put it back in the
716 * freelist.
718 ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
721 if(oldstate)
722 ALeffectState_DecRef(oldstate);
725 void UpdateAllEffectSlotProps(ALCcontext *context)
727 struct ALeffectslotArray *auxslots;
728 ALsizei i;
730 LockEffectSlotList(context);
731 auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
732 for(i = 0;i < auxslots->count;i++)
734 ALeffectslot *slot = auxslots->slot[i];
735 if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
736 UpdateEffectSlotProps(slot, context);
738 UnlockEffectSlotList(context);
741 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *context)
743 ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
744 ALeffectslotPtr *end = VECTOR_END(context->EffectSlotList);
745 size_t leftover = 0;
747 for(;iter != end;iter++)
749 ALeffectslot *slot = *iter;
750 if(!slot) continue;
751 *iter = NULL;
753 DeinitEffectSlot(slot);
755 memset(slot, 0, sizeof(*slot));
756 al_free(slot);
757 ++leftover;
759 if(leftover > 0)
760 WARN("(%p) Deleted "SZFMT" AuxiliaryEffectSlot%s\n", context, leftover, (leftover==1)?"":"s");