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
)
113 context
= GetContextRef();
117 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Generating %d effect slots", n
);
118 if(n
== 0) goto done
;
120 LockEffectSlotList(context
);
121 device
= context
->Device
;
122 if(device
->AuxiliaryEffectSlotMax
- VECTOR_SIZE(context
->EffectSlotList
) < (ALuint
)n
)
124 UnlockEffectSlotList(context
);
125 SETERR_GOTO(context
, AL_OUT_OF_MEMORY
, done
, "Exceeding %u auxiliary effect slot limit",
126 device
->AuxiliaryEffectSlotMax
);
128 for(cur
= 0;cur
< n
;cur
++)
130 ALeffectslotPtr
*iter
= VECTOR_BEGIN(context
->EffectSlotList
);
131 ALeffectslotPtr
*end
= VECTOR_END(context
->EffectSlotList
);
132 ALeffectslot
*slot
= NULL
;
133 ALenum err
= AL_OUT_OF_MEMORY
;
135 for(;iter
!= end
;iter
++)
142 VECTOR_PUSH_BACK(context
->EffectSlotList
, NULL
);
143 iter
= &VECTOR_BACK(context
->EffectSlotList
);
145 slot
= al_calloc(16, sizeof(ALeffectslot
));
146 if(!slot
|| (err
=InitEffectSlot(slot
)) != AL_NO_ERROR
)
149 UnlockEffectSlotList(context
);
151 alDeleteAuxiliaryEffectSlots(cur
, effectslots
);
152 SETERR_GOTO(context
, err
, done
, "Effect slot object allocation failed");
154 aluInitEffectPanning(slot
);
156 slot
->id
= (iter
- VECTOR_BEGIN(context
->EffectSlotList
)) + 1;
159 effectslots
[cur
] = slot
->id
;
161 AddActiveEffectSlots(effectslots
, n
, context
);
162 UnlockEffectSlotList(context
);
165 ALCcontext_DecRef(context
);
168 AL_API ALvoid AL_APIENTRY
alDeleteAuxiliaryEffectSlots(ALsizei n
, const ALuint
*effectslots
)
174 context
= GetContextRef();
177 LockEffectSlotList(context
);
179 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Deleting %d effect slots", n
);
180 if(n
== 0) goto done
;
184 if((slot
=LookupEffectSlot(context
, effectslots
[i
])) == NULL
)
185 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u",
187 if(ReadRef(&slot
->ref
) != 0)
188 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Deleting in-use effect slot %u",
192 // All effectslots are valid
193 RemoveActiveEffectSlots(effectslots
, n
, context
);
196 if((slot
=LookupEffectSlot(context
, effectslots
[i
])) == NULL
)
198 VECTOR_ELEM(context
->EffectSlotList
, effectslots
[i
]-1) = NULL
;
200 DeinitEffectSlot(slot
);
202 memset(slot
, 0, sizeof(*slot
));
207 UnlockEffectSlotList(context
);
208 ALCcontext_DecRef(context
);
211 AL_API ALboolean AL_APIENTRY
alIsAuxiliaryEffectSlot(ALuint effectslot
)
216 context
= GetContextRef();
217 if(!context
) return AL_FALSE
;
219 LockEffectSlotList(context
);
220 ret
= (LookupEffectSlot(context
, effectslot
) ? AL_TRUE
: AL_FALSE
);
221 UnlockEffectSlotList(context
);
223 ALCcontext_DecRef(context
);
228 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint value
)
233 ALeffect
*effect
= NULL
;
236 context
= GetContextRef();
239 almtx_lock(&context
->PropLock
);
240 LockEffectSlotList(context
);
241 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
242 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
245 case AL_EFFECTSLOT_EFFECT
:
246 device
= context
->Device
;
248 LockEffectList(device
);
249 effect
= (value
? LookupEffect(device
, value
) : NULL
);
250 if(!(value
== 0 || effect
!= NULL
))
252 UnlockEffectList(device
);
253 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Invalid effect ID %u", value
);
255 err
= InitializeEffect(context
, slot
, effect
);
256 UnlockEffectList(device
);
258 if(err
!= AL_NO_ERROR
)
259 SETERR_GOTO(context
, err
, done
, "Effect initialization failed");
262 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
263 if(!(value
== AL_TRUE
|| value
== AL_FALSE
))
264 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
,
265 "Effect slot auxiliary send auto out of range");
266 slot
->AuxSendAuto
= value
;
270 SETERR_GOTO(context
, AL_INVALID_ENUM
, done
, "Invalid effect slot integer property 0x%04x",
276 UnlockEffectSlotList(context
);
277 almtx_unlock(&context
->PropLock
);
278 ALCcontext_DecRef(context
);
281 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, const ALint
*values
)
287 case AL_EFFECTSLOT_EFFECT
:
288 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
289 alAuxiliaryEffectSloti(effectslot
, param
, values
[0]);
293 context
= GetContextRef();
296 LockEffectSlotList(context
);
297 if(LookupEffectSlot(context
, effectslot
) == NULL
)
298 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
302 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot integer-vector property 0x%04x",
307 UnlockEffectSlotList(context
);
308 ALCcontext_DecRef(context
);
311 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat value
)
316 context
= GetContextRef();
319 almtx_lock(&context
->PropLock
);
320 LockEffectSlotList(context
);
321 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
322 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
325 case AL_EFFECTSLOT_GAIN
:
326 if(!(value
>= 0.0f
&& value
<= 1.0f
))
327 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Effect slot gain out of range");
332 SETERR_GOTO(context
, AL_INVALID_ENUM
, done
, "Invalid effect slot float property 0x%04x",
338 UnlockEffectSlotList(context
);
339 almtx_unlock(&context
->PropLock
);
340 ALCcontext_DecRef(context
);
343 AL_API ALvoid AL_APIENTRY
alAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, const ALfloat
*values
)
349 case AL_EFFECTSLOT_GAIN
:
350 alAuxiliaryEffectSlotf(effectslot
, param
, values
[0]);
354 context
= GetContextRef();
357 LockEffectSlotList(context
);
358 if(LookupEffectSlot(context
, effectslot
) == NULL
)
359 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
363 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot float-vector property 0x%04x",
368 UnlockEffectSlotList(context
);
369 ALCcontext_DecRef(context
);
372 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSloti(ALuint effectslot
, ALenum param
, ALint
*value
)
377 context
= GetContextRef();
380 LockEffectSlotList(context
);
381 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
382 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
385 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
386 *value
= slot
->AuxSendAuto
;
390 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot integer property 0x%04x", param
);
394 UnlockEffectSlotList(context
);
395 ALCcontext_DecRef(context
);
398 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotiv(ALuint effectslot
, ALenum param
, ALint
*values
)
404 case AL_EFFECTSLOT_EFFECT
:
405 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
:
406 alGetAuxiliaryEffectSloti(effectslot
, param
, values
);
410 context
= GetContextRef();
413 LockEffectSlotList(context
);
414 if(LookupEffectSlot(context
, effectslot
) == NULL
)
415 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
419 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot integer-vector property 0x%04x",
424 UnlockEffectSlotList(context
);
425 ALCcontext_DecRef(context
);
428 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotf(ALuint effectslot
, ALenum param
, ALfloat
*value
)
433 context
= GetContextRef();
436 LockEffectSlotList(context
);
437 if((slot
=LookupEffectSlot(context
, effectslot
)) == NULL
)
438 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
441 case AL_EFFECTSLOT_GAIN
:
446 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot float property 0x%04x", param
);
450 UnlockEffectSlotList(context
);
451 ALCcontext_DecRef(context
);
454 AL_API ALvoid AL_APIENTRY
alGetAuxiliaryEffectSlotfv(ALuint effectslot
, ALenum param
, ALfloat
*values
)
460 case AL_EFFECTSLOT_GAIN
:
461 alGetAuxiliaryEffectSlotf(effectslot
, param
, values
);
465 context
= GetContextRef();
468 LockEffectSlotList(context
);
469 if(LookupEffectSlot(context
, effectslot
) == NULL
)
470 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid effect slot ID %u", effectslot
);
474 alSetError(context
, AL_INVALID_ENUM
, "Invalid effect slot float-vector property 0x%04x",
479 UnlockEffectSlotList(context
);
480 ALCcontext_DecRef(context
);
484 ALenum
InitializeEffect(ALCcontext
*Context
, ALeffectslot
*EffectSlot
, ALeffect
*effect
)
486 ALCdevice
*Device
= Context
->Device
;
487 ALenum newtype
= (effect
? effect
->type
: AL_EFFECT_NULL
);
488 struct ALeffectslotProps
*props
;
489 ALeffectState
*State
;
491 if(newtype
!= EffectSlot
->Effect
.Type
)
493 EffectStateFactory
*factory
;
495 factory
= getFactoryByType(newtype
);
498 ERR("Failed to find factory for effect type 0x%04x\n", newtype
);
499 return AL_INVALID_ENUM
;
501 State
= EffectStateFactory_create(factory
);
502 if(!State
) return AL_OUT_OF_MEMORY
;
505 almtx_lock(&Device
->BackendLock
);
506 State
->OutBuffer
= Device
->Dry
.Buffer
;
507 State
->OutChannels
= Device
->Dry
.NumChannels
;
508 if(V(State
,deviceUpdate
)(Device
) == AL_FALSE
)
510 almtx_unlock(&Device
->BackendLock
);
512 ALeffectState_DecRef(State
);
513 return AL_OUT_OF_MEMORY
;
515 almtx_unlock(&Device
->BackendLock
);
520 EffectSlot
->Effect
.Type
= AL_EFFECT_NULL
;
521 memset(&EffectSlot
->Effect
.Props
, 0, sizeof(EffectSlot
->Effect
.Props
));
525 EffectSlot
->Effect
.Type
= effect
->type
;
526 EffectSlot
->Effect
.Props
= effect
->Props
;
529 ALeffectState_DecRef(EffectSlot
->Effect
.State
);
530 EffectSlot
->Effect
.State
= State
;
533 EffectSlot
->Effect
.Props
= effect
->Props
;
535 /* Remove state references from old effect slot property updates. */
536 props
= ATOMIC_LOAD_SEQ(&Context
->FreeEffectslotProps
);
540 ALeffectState_DecRef(props
->State
);
542 props
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
549 static void ALeffectState_IncRef(ALeffectState
*state
)
552 ref
= IncrementRef(&state
->Ref
);
553 TRACEREF("%p increasing refcount to %u\n", state
, ref
);
556 void ALeffectState_DecRef(ALeffectState
*state
)
559 ref
= DecrementRef(&state
->Ref
);
560 TRACEREF("%p decreasing refcount to %u\n", state
, ref
);
561 if(ref
== 0) DELETE_OBJ(state
);
565 void ALeffectState_Construct(ALeffectState
*state
)
567 InitRef(&state
->Ref
, 1);
569 state
->OutBuffer
= NULL
;
570 state
->OutChannels
= 0;
573 void ALeffectState_Destruct(ALeffectState
*UNUSED(state
))
578 static void AddActiveEffectSlots(const ALuint
*slotids
, ALsizei count
, ALCcontext
*context
)
580 struct ALeffectslotArray
*curarray
= ATOMIC_LOAD(&context
->ActiveAuxSlots
,
581 almemory_order_acquire
);
582 struct ALeffectslotArray
*newarray
= NULL
;
583 ALsizei newcount
= curarray
->count
+ count
;
584 ALCdevice
*device
= context
->Device
;
587 /* Insert the new effect slots into the head of the array, followed by the
590 newarray
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, newcount
));
591 newarray
->count
= newcount
;
592 for(i
= 0;i
< count
;i
++)
593 newarray
->slot
[i
] = LookupEffectSlot(context
, slotids
[i
]);
594 for(j
= 0;i
< newcount
;)
595 newarray
->slot
[i
++] = curarray
->slot
[j
++];
596 /* Remove any duplicates (first instance of each will be kept). */
597 for(i
= 1;i
< newcount
;i
++)
601 if(UNLIKELY(newarray
->slot
[i
] == newarray
->slot
[--j
]))
604 for(j
= i
;j
< newcount
;j
++)
605 newarray
->slot
[j
] = newarray
->slot
[j
+1];
612 /* Reallocate newarray if the new size ended up smaller from duplicate
615 if(UNLIKELY(newcount
< newarray
->count
))
617 struct ALeffectslotArray
*tmpnewarray
= al_calloc(DEF_ALIGN
,
618 FAM_SIZE(struct ALeffectslotArray
, slot
, newcount
));
619 memcpy(tmpnewarray
, newarray
, FAM_SIZE(struct ALeffectslotArray
, slot
, newcount
));
621 newarray
= tmpnewarray
;
622 newarray
->count
= newcount
;
625 curarray
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, newarray
, almemory_order_acq_rel
);
626 while((ATOMIC_LOAD(&device
->MixCount
, almemory_order_acquire
)&1))
631 static void RemoveActiveEffectSlots(const ALuint
*slotids
, ALsizei count
, ALCcontext
*context
)
633 struct ALeffectslotArray
*curarray
= ATOMIC_LOAD(&context
->ActiveAuxSlots
,
634 almemory_order_acquire
);
635 struct ALeffectslotArray
*newarray
= NULL
;
636 ALCdevice
*device
= context
->Device
;
639 /* Don't shrink the allocated array size since we don't know how many (if
640 * any) of the effect slots to remove are in the array.
642 newarray
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, curarray
->count
));
644 for(i
= 0;i
< curarray
->count
;i
++)
646 /* Insert this slot into the new array only if it's not one to remove. */
647 ALeffectslot
*slot
= curarray
->slot
[i
];
648 for(j
= count
;j
!= 0;)
650 if(slot
->id
== slotids
[--j
])
653 newarray
->slot
[newarray
->count
++] = slot
;
657 /* TODO: Could reallocate newarray now that we know it's needed size. */
659 curarray
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, newarray
, almemory_order_acq_rel
);
660 while((ATOMIC_LOAD(&device
->MixCount
, almemory_order_acquire
)&1))
666 ALenum
InitEffectSlot(ALeffectslot
*slot
)
668 EffectStateFactory
*factory
;
670 slot
->Effect
.Type
= AL_EFFECT_NULL
;
672 factory
= getFactoryByType(AL_EFFECT_NULL
);
673 slot
->Effect
.State
= EffectStateFactory_create(factory
);
674 if(!slot
->Effect
.State
) return AL_OUT_OF_MEMORY
;
677 slot
->AuxSendAuto
= AL_TRUE
;
678 ATOMIC_FLAG_TEST_AND_SET(&slot
->PropsClean
, almemory_order_relaxed
);
679 InitRef(&slot
->ref
, 0);
681 ATOMIC_INIT(&slot
->Update
, NULL
);
683 slot
->Params
.Gain
= 1.0f
;
684 slot
->Params
.AuxSendAuto
= AL_TRUE
;
685 ALeffectState_IncRef(slot
->Effect
.State
);
686 slot
->Params
.EffectState
= slot
->Effect
.State
;
687 slot
->Params
.RoomRolloff
= 0.0f
;
688 slot
->Params
.DecayTime
= 0.0f
;
689 slot
->Params
.DecayLFRatio
= 0.0f
;
690 slot
->Params
.DecayHFRatio
= 0.0f
;
691 slot
->Params
.DecayHFLimit
= AL_FALSE
;
692 slot
->Params
.AirAbsorptionGainHF
= 1.0f
;
697 void DeinitEffectSlot(ALeffectslot
*slot
)
699 struct ALeffectslotProps
*props
;
701 props
= ATOMIC_LOAD_SEQ(&slot
->Update
);
704 if(props
->State
) ALeffectState_DecRef(props
->State
);
705 TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props
);
709 ALeffectState_DecRef(slot
->Effect
.State
);
710 if(slot
->Params
.EffectState
)
711 ALeffectState_DecRef(slot
->Params
.EffectState
);
714 void UpdateEffectSlotProps(ALeffectslot
*slot
, ALCcontext
*context
)
716 struct ALeffectslotProps
*props
;
717 ALeffectState
*oldstate
;
719 /* Get an unused property container, or allocate a new one as needed. */
720 props
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
722 props
= al_calloc(16, sizeof(*props
));
725 struct ALeffectslotProps
*next
;
727 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
728 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context
->FreeEffectslotProps
, &props
, next
,
729 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
732 /* Copy in current property values. */
733 props
->Gain
= slot
->Gain
;
734 props
->AuxSendAuto
= slot
->AuxSendAuto
;
736 props
->Type
= slot
->Effect
.Type
;
737 props
->Props
= slot
->Effect
.Props
;
738 /* Swap out any stale effect state object there may be in the container, to
741 ALeffectState_IncRef(slot
->Effect
.State
);
742 oldstate
= props
->State
;
743 props
->State
= slot
->Effect
.State
;
745 /* Set the new container for updating internal parameters. */
746 props
= ATOMIC_EXCHANGE_PTR(&slot
->Update
, props
, almemory_order_acq_rel
);
749 /* If there was an unused update container, put it back in the
752 ATOMIC_REPLACE_HEAD(struct ALeffectslotProps
*, &context
->FreeEffectslotProps
, props
);
756 ALeffectState_DecRef(oldstate
);
759 void UpdateAllEffectSlotProps(ALCcontext
*context
)
761 struct ALeffectslotArray
*auxslots
;
764 LockEffectSlotList(context
);
765 auxslots
= ATOMIC_LOAD(&context
->ActiveAuxSlots
, almemory_order_acquire
);
766 for(i
= 0;i
< auxslots
->count
;i
++)
768 ALeffectslot
*slot
= auxslots
->slot
[i
];
769 if(!ATOMIC_FLAG_TEST_AND_SET(&slot
->PropsClean
, almemory_order_acq_rel
))
770 UpdateEffectSlotProps(slot
, context
);
772 UnlockEffectSlotList(context
);
775 ALvoid
ReleaseALAuxiliaryEffectSlots(ALCcontext
*context
)
777 ALeffectslotPtr
*iter
= VECTOR_BEGIN(context
->EffectSlotList
);
778 ALeffectslotPtr
*end
= VECTOR_END(context
->EffectSlotList
);
781 for(;iter
!= end
;iter
++)
783 ALeffectslot
*slot
= *iter
;
787 DeinitEffectSlot(slot
);
789 memset(slot
, 0, sizeof(*slot
));
794 WARN("(%p) Deleted "SZFMT
" AuxiliaryEffectSlot%s\n", context
, leftover
, (leftover
==1)?"":"s");