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
29 #include "alAuxEffectSlot.h"
31 #include "alListener.h"
34 #include "fpu_modes.h"
38 extern inline void LockEffectSlotList(ALCcontext
*context
);
39 extern inline void UnlockEffectSlotList(ALCcontext
*context
);
41 static void AddActiveEffectSlots(const ALuint
*slotids
, ALsizei count
, ALCcontext
*context
);
42 static void RemoveActiveEffectSlots(const ALuint
*slotids
, ALsizei count
, ALCcontext
*context
);
46 EffectStateFactory
* (*GetFactory
)(void);
48 { AL_EFFECT_NULL
, NullStateFactory_getFactory
},
49 { AL_EFFECT_EAXREVERB
, ReverbStateFactory_getFactory
},
50 { AL_EFFECT_REVERB
, ReverbStateFactory_getFactory
},
51 { AL_EFFECT_CHORUS
, ChorusStateFactory_getFactory
},
52 { AL_EFFECT_COMPRESSOR
, CompressorStateFactory_getFactory
},
53 { AL_EFFECT_DISTORTION
, DistortionStateFactory_getFactory
},
54 { AL_EFFECT_ECHO
, EchoStateFactory_getFactory
},
55 { AL_EFFECT_EQUALIZER
, EqualizerStateFactory_getFactory
},
56 { AL_EFFECT_FLANGER
, FlangerStateFactory_getFactory
},
57 { AL_EFFECT_RING_MODULATOR
, ModulatorStateFactory_getFactory
},
58 { AL_EFFECT_DEDICATED_DIALOGUE
, DedicatedStateFactory_getFactory
},
59 { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
, DedicatedStateFactory_getFactory
}
62 static inline EffectStateFactory
*getFactoryByType(ALenum type
)
65 for(i
= 0;i
< COUNTOF(FactoryList
);i
++)
67 if(FactoryList
[i
].Type
== type
)
68 return FactoryList
[i
].GetFactory();
73 static void ALeffectState_IncRef(ALeffectState
*state
);
76 static inline ALeffectslot
*LookupEffectSlot(ALCcontext
*context
, ALuint id
)
79 if(UNLIKELY(id
>= VECTOR_SIZE(context
->EffectSlotList
)))
81 return VECTOR_ELEM(context
->EffectSlotList
, id
);
84 static inline ALeffect
*LookupEffect(ALCdevice
*device
, ALuint id
)
86 EffectSubList
*sublist
;
87 ALuint lidx
= (id
-1) >> 6;
88 ALsizei slidx
= (id
-1) & 0x3f;
90 if(UNLIKELY(lidx
>= VECTOR_SIZE(device
->EffectList
)))
92 sublist
= &VECTOR_ELEM(device
->EffectList
, lidx
);
93 if(UNLIKELY(sublist
->FreeMask
& (U64(1)<<slidx
)))
95 return sublist
->Effects
+ slidx
;
99 #define DO_UPDATEPROPS() do { \
100 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
101 UpdateEffectSlotProps(slot, context); \
103 ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
107 AL_API ALvoid AL_APIENTRY
alGenAuxiliaryEffectSlots(ALsizei n
, ALuint
*effectslots
)
114 context
= GetContextRef();
118 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Generating %d effect slots", n
);
119 if(n
== 0) goto done
;
121 LockEffectSlotList(context
);
122 device
= context
->Device
;
123 if(device
->AuxiliaryEffectSlotMax
- VECTOR_SIZE(context
->EffectSlotList
) < (ALuint
)n
)
125 UnlockEffectSlotList(context
);
126 SETERR_GOTO(context
, AL_OUT_OF_MEMORY
, done
, "Exceeding %u auxiliary effect slot limit",
127 device
->AuxiliaryEffectSlotMax
);
129 for(cur
= 0;cur
< n
;cur
++)
131 ALeffectslotPtr
*iter
= VECTOR_BEGIN(context
->EffectSlotList
);
132 ALeffectslotPtr
*end
= VECTOR_END(context
->EffectSlotList
);
133 ALeffectslot
*slot
= NULL
;
135 for(;iter
!= end
;iter
++)
142 if(VECTOR_SIZE(context
->EffectSlotList
) >= INT_MAX
)
144 UnlockEffectSlotList(context
);
146 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
147 SETERR_GOTO(context
, err
, done
, "Too many effect slot objects");
149 VECTOR_PUSH_BACK(context
->EffectSlotList
, NULL
);
150 iter
= &VECTOR_BACK(context
->EffectSlotList
);
152 slot
= al_calloc(16, sizeof(ALeffectslot
));
153 err
= AL_OUT_OF_MEMORY
;
154 if(!slot
|| (err
=InitEffectSlot(slot
)) != AL_NO_ERROR
)
157 UnlockEffectSlotList(context
);
159 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
160 SETERR_GOTO(context
, err
, done
, "Effect slot object allocation failed");
162 aluInitEffectPanning(slot
);
164 slot
->id
= (iter
- VECTOR_BEGIN(context
->EffectSlotList
)) + 1;
167 effectslots
[cur
] = slot
->id
;
169 AddActiveEffectSlots(effectslots
, n
, context
);
170 UnlockEffectSlotList(context
);
173 ALCcontext_DecRef(context
);
176 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, const ALuint
*effectslots
)
182 context
= GetContextRef();
185 LockEffectSlotList(context
);
187 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Deleting %d effect slots", n
);
188 if(n
== 0) goto done
;
192 if((slot
=LookupEffectSlot(context
, effectslots
[i
])) == NULL
)
193 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u",
195 if(ReadRef(&slot
->ref
) != 0)
196 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Deleting in-use effect slot %u",
200 // All effectslots are valid
201 RemoveActiveEffectSlots(effectslots
, n
, context
);
204 if((slot
=LookupEffectSlot(context
, effectslots
[i
])) == NULL
)
206 VECTOR_ELEM(context
->EffectSlotList
, effectslots
[i
]-1) = NULL
;
208 DeinitEffectSlot(slot
);
210 memset(slot
, 0, sizeof(*slot
));
215 UnlockEffectSlotList(context
);
216 ALCcontext_DecRef(context
);
219 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
224 context
= GetContextRef();
225 if(!context
) return AL_FALSE
;
227 LockEffectSlotList(context
);
228 ret
= (LookupEffectSlot(context
, effectslot
) ? AL_TRUE
: AL_FALSE
);
229 UnlockEffectSlotList(context
);
231 ALCcontext_DecRef(context
);
236 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint value
)
241 ALeffect
*effect
= NULL
;
244 context
= GetContextRef();
247 almtx_lock(&context
->PropLock
);
248 LockEffectSlotList(context
);
249 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
250 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
253 case AL_EFFECTSLOT_EFFECT
:
254 device
= context
->Device
;
256 LockEffectList(device
);
257 effect
= (value
? LookupEffect(device
, value
) : NULL
);
258 if(!(value
== 0 || effect
!= NULL
))
260 UnlockEffectList(device
);
261 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Invalid effect ID %u", value
);
263 err
= InitializeEffect(context
, slot
, effect
);
264 UnlockEffectList(device
);
266 if(err
!= AL_NO_ERROR
)
267 SETERR_GOTO(context
, err
, done
, "Effect initialization failed");
270 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
271 if(!(value
== AL_TRUE
|| value
== AL_FALSE
))
272 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
,
273 "Effect slot auxiliary send auto out of range");
274 slot
->AuxSendAuto
= value
;
278 SETERR_GOTO(context
, AL_INVALID_ENUM
, done
, "Invalid effect slot integer property 0x%04x",
284 UnlockEffectSlotList(context
);
285 almtx_unlock(&context
->PropLock
);
286 ALCcontext_DecRef(context
);
289 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, const ALint
*values
)
295 case AL_EFFECTSLOT_EFFECT
:
296 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
297 alAuxiliaryEffectSloti(effectslot
, param
, values
[0]);
301 context
= GetContextRef();
304 LockEffectSlotList(context
);
305 if(LookupEffectSlot(context
, effectslot
) == NULL
)
306 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
310 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot integer-vector property 0x%04x",
315 UnlockEffectSlotList(context
);
316 ALCcontext_DecRef(context
);
319 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat value
)
324 context
= GetContextRef();
327 almtx_lock(&context
->PropLock
);
328 LockEffectSlotList(context
);
329 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
330 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
333 case AL_EFFECTSLOT_GAIN
:
334 if(!(value
>= 0.0f
&& value
<= 1.0f
))
335 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Effect slot gain out of range");
340 SETERR_GOTO(context
, AL_INVALID_ENUM
, done
, "Invalid effect slot float property 0x%04x",
346 UnlockEffectSlotList(context
);
347 almtx_unlock(&context
->PropLock
);
348 ALCcontext_DecRef(context
);
351 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, const ALfloat
*values
)
357 case AL_EFFECTSLOT_GAIN
:
358 alAuxiliaryEffectSlotf(effectslot
, param
, values
[0]);
362 context
= GetContextRef();
365 LockEffectSlotList(context
);
366 if(LookupEffectSlot(context
, effectslot
) == NULL
)
367 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
371 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot float-vector property 0x%04x",
376 UnlockEffectSlotList(context
);
377 ALCcontext_DecRef(context
);
380 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*value
)
385 context
= GetContextRef();
388 LockEffectSlotList(context
);
389 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
390 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
393 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
394 *value
= slot
->AuxSendAuto
;
398 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot integer property 0x%04x", param
);
402 UnlockEffectSlotList(context
);
403 ALCcontext_DecRef(context
);
406 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*values
)
412 case AL_EFFECTSLOT_EFFECT
:
413 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
414 alGetAuxiliaryEffectSloti(effectslot
, param
, values
);
418 context
= GetContextRef();
421 LockEffectSlotList(context
);
422 if(LookupEffectSlot(context
, effectslot
) == NULL
)
423 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
427 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot integer-vector property 0x%04x",
432 UnlockEffectSlotList(context
);
433 ALCcontext_DecRef(context
);
436 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*value
)
441 context
= GetContextRef();
444 LockEffectSlotList(context
);
445 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
446 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
449 case AL_EFFECTSLOT_GAIN
:
454 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot float property 0x%04x", param
);
458 UnlockEffectSlotList(context
);
459 ALCcontext_DecRef(context
);
462 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*values
)
468 case AL_EFFECTSLOT_GAIN
:
469 alGetAuxiliaryEffectSlotf(effectslot
, param
, values
);
473 context
= GetContextRef();
476 LockEffectSlotList(context
);
477 if(LookupEffectSlot(context
, effectslot
) == NULL
)
478 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
482 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot float-vector property 0x%04x",
487 UnlockEffectSlotList(context
);
488 ALCcontext_DecRef(context
);
492 ALenum
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
494 ALCdevice
*Device
= Context
->Device
;
495 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
496 struct ALeffectslotProps
*props
;
497 ALeffectState
*State
;
499 if(newtype
!= EffectSlot
->Effect
.Type
)
501 EffectStateFactory
*factory
;
503 factory
= getFactoryByType(newtype
);
506 ERR("Failed to find factory for effect type 0x%04x\n", newtype
);
507 return AL_INVALID_ENUM
;
509 State
= EffectStateFactory_create(factory
);
510 if(!State
) return AL_OUT_OF_MEMORY
;
513 almtx_lock(&Device
->BackendLock
);
514 State
->OutBuffer
= Device
->Dry
.Buffer
;
515 State
->OutChannels
= Device
->Dry
.NumChannels
;
516 if(V(State
,deviceUpdate
)(Device
) == AL_FALSE
)
518 almtx_unlock(&Device
->BackendLock
);
520 ALeffectState_DecRef(State
);
521 return AL_OUT_OF_MEMORY
;
523 almtx_unlock(&Device
->BackendLock
);
528 EffectSlot
->Effect
.Type
= AL_EFFECT_NULL
;
529 memset(&EffectSlot
->Effect
.Props
, 0, sizeof(EffectSlot
->Effect
.Props
));
533 EffectSlot
->Effect
.Type
= effect
->type
;
534 EffectSlot
->Effect
.Props
= effect
->Props
;
537 ALeffectState_DecRef(EffectSlot
->Effect
.State
);
538 EffectSlot
->Effect
.State
= State
;
541 EffectSlot
->Effect
.Props
= effect
->Props
;
543 /* Remove state references from old effect slot property updates. */
544 props
= ATOMIC_LOAD_SEQ(&Context
->FreeEffectslotProps
);
548 ALeffectState_DecRef(props
->State
);
550 props
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
557 static void ALeffectState_IncRef(ALeffectState
*state
)
560 ref
= IncrementRef(&state
->Ref
);
561 TRACEREF("%p increasing refcount to %u\n", state
, ref
);
564 void ALeffectState_DecRef(ALeffectState
*state
)
567 ref
= DecrementRef(&state
->Ref
);
568 TRACEREF("%p decreasing refcount to %u\n", state
, ref
);
569 if(ref
== 0) DELETE_OBJ(state
);
573 void ALeffectState_Construct(ALeffectState
*state
)
575 InitRef(&state
->Ref
, 1);
577 state
->OutBuffer
= NULL
;
578 state
->OutChannels
= 0;
581 void ALeffectState_Destruct(ALeffectState
*UNUSED(state
))
586 static void AddActiveEffectSlots(const ALuint
*slotids
, ALsizei count
, ALCcontext
*context
)
588 struct ALeffectslotArray
*curarray
= ATOMIC_LOAD(&context
->ActiveAuxSlots
,
589 almemory_order_acquire
);
590 struct ALeffectslotArray
*newarray
= NULL
;
591 ALsizei newcount
= curarray
->count
+ count
;
592 ALCdevice
*device
= context
->Device
;
595 /* Insert the new effect slots into the head of the array, followed by the
598 newarray
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, newcount
));
599 newarray
->count
= newcount
;
600 for(i
= 0;i
< count
;i
++)
601 newarray
->slot
[i
] = LookupEffectSlot(context
, slotids
[i
]);
602 for(j
= 0;i
< newcount
;)
603 newarray
->slot
[i
++] = curarray
->slot
[j
++];
604 /* Remove any duplicates (first instance of each will be kept). */
605 for(i
= 1;i
< newcount
;i
++)
609 if(newarray
->slot
[i
] == newarray
->slot
[--j
])
615 for(j
= i
;j
< newcount
;j
++)
616 newarray
->slot
[j
] = newarray
->slot
[j
+1];
620 newarray
->count
= newcount
;
622 curarray
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, newarray
, almemory_order_acq_rel
);
623 while((ATOMIC_LOAD(&device
->MixCount
, almemory_order_acquire
)&1))
628 static void RemoveActiveEffectSlots(const ALuint
*slotids
, ALsizei count
, ALCcontext
*context
)
630 struct ALeffectslotArray
*curarray
= ATOMIC_LOAD(&context
->ActiveAuxSlots
,
631 almemory_order_acquire
);
632 struct ALeffectslotArray
*newarray
= NULL
;
633 ALsizei newcount
= curarray
->count
- count
;
634 ALCdevice
*device
= context
->Device
;
637 assert(newcount
>= 0);
638 newarray
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, newcount
));
639 newarray
->count
= newcount
;
640 for(i
= j
= 0;i
< newarray
->count
;)
642 ALeffectslot
*slot
= curarray
->slot
[j
++];
646 if(slot
->id
== slotids
[--k
])
650 newarray
->slot
[i
++] = slot
;
653 curarray
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, newarray
, almemory_order_acq_rel
);
654 while((ATOMIC_LOAD(&device
->MixCount
, almemory_order_acquire
)&1))
660 ALenum
InitEffectSlot(ALeffectslot
*slot
)
662 EffectStateFactory
*factory
;
664 slot
->Effect
.Type
= AL_EFFECT_NULL
;
666 factory
= getFactoryByType(AL_EFFECT_NULL
);
667 slot
->Effect
.State
= EffectStateFactory_create(factory
);
668 if(!slot
->Effect
.State
) return AL_OUT_OF_MEMORY
;
671 slot
->AuxSendAuto
= AL_TRUE
;
672 ATOMIC_FLAG_TEST_AND_SET(&slot
->PropsClean
, almemory_order_relaxed
);
673 InitRef(&slot
->ref
, 0);
675 ATOMIC_INIT(&slot
->Update
, NULL
);
677 slot
->Params
.Gain
= 1.0f
;
678 slot
->Params
.AuxSendAuto
= AL_TRUE
;
679 ALeffectState_IncRef(slot
->Effect
.State
);
680 slot
->Params
.EffectState
= slot
->Effect
.State
;
681 slot
->Params
.RoomRolloff
= 0.0f
;
682 slot
->Params
.DecayTime
= 0.0f
;
683 slot
->Params
.DecayHFRatio
= 0.0f
;
684 slot
->Params
.DecayHFLimit
= AL_FALSE
;
685 slot
->Params
.AirAbsorptionGainHF
= 1.0f
;
690 void DeinitEffectSlot(ALeffectslot
*slot
)
692 struct ALeffectslotProps
*props
;
694 props
= ATOMIC_LOAD_SEQ(&slot
->Update
);
697 if(props
->State
) ALeffectState_DecRef(props
->State
);
698 TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props
);
702 ALeffectState_DecRef(slot
->Effect
.State
);
703 if(slot
->Params
.EffectState
)
704 ALeffectState_DecRef(slot
->Params
.EffectState
);
707 void UpdateEffectSlotProps(ALeffectslot
*slot
, ALCcontext
*context
)
709 struct ALeffectslotProps
*props
;
710 ALeffectState
*oldstate
;
712 /* Get an unused property container, or allocate a new one as needed. */
713 props
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
715 props
= al_calloc(16, sizeof(*props
));
718 struct ALeffectslotProps
*next
;
720 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
721 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context
->FreeEffectslotProps
, &props
, next
,
722 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
725 /* Copy in current property values. */
726 props
->Gain
= slot
->Gain
;
727 props
->AuxSendAuto
= slot
->AuxSendAuto
;
729 props
->Type
= slot
->Effect
.Type
;
730 props
->Props
= slot
->Effect
.Props
;
731 /* Swap out any stale effect state object there may be in the container, to
734 ALeffectState_IncRef(slot
->Effect
.State
);
735 oldstate
= props
->State
;
736 props
->State
= slot
->Effect
.State
;
738 /* Set the new container for updating internal parameters. */
739 props
= ATOMIC_EXCHANGE_PTR(&slot
->Update
, props
, almemory_order_acq_rel
);
742 /* If there was an unused update container, put it back in the
745 ATOMIC_REPLACE_HEAD(struct ALeffectslotProps
*, &context
->FreeEffectslotProps
, props
);
749 ALeffectState_DecRef(oldstate
);
752 void UpdateAllEffectSlotProps(ALCcontext
*context
)
754 struct ALeffectslotArray
*auxslots
;
757 LockEffectSlotList(context
);
758 auxslots
= ATOMIC_LOAD(&context
->ActiveAuxSlots
, almemory_order_acquire
);
759 for(i
= 0;i
< auxslots
->count
;i
++)
761 ALeffectslot
*slot
= auxslots
->slot
[i
];
762 if(!ATOMIC_FLAG_TEST_AND_SET(&slot
->PropsClean
, almemory_order_acq_rel
))
763 UpdateEffectSlotProps(slot
, context
);
765 UnlockEffectSlotList(context
);
768 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*context
)
770 ALeffectslotPtr
*iter
= VECTOR_BEGIN(context
->EffectSlotList
);
771 ALeffectslotPtr
*end
= VECTOR_END(context
->EffectSlotList
);
774 for(;iter
!= end
;iter
++)
776 ALeffectslot
*slot
= *iter
;
780 DeinitEffectSlot(slot
);
782 memset(slot
, 0, sizeof(*slot
));
787 WARN("(%p) Deleted "SZFMT
" AuxiliaryEffectSlot%s\n", context
, leftover
, (leftover
==1)?"":"s");