aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-01-08 07:31:01 -0800
committerChris Robinson <[email protected]>2020-01-08 07:31:01 -0800
commit6608e5dd9f1834e0b0809c5b586019764f9dd7a4 (patch)
tree884c882a2a24e78ce2f42c72f02ac80c8ff49d2e /alc
parent45e82379a417e7c9f16c0367e32d749d867f5e89 (diff)
Make sure unassociated voices give back their update structs
Diffstat (limited to 'alc')
-rw-r--r--alc/alu.cpp54
1 files changed, 29 insertions, 25 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp
index 77a37593..25e36973 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -1563,7 +1563,17 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A
void CalcSourceParams(ALvoice *voice, ALCcontext *context, bool force)
{
ALvoiceProps *props{voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel)};
- if(!props && !force) return;
+ if(voice->mSourceID.load(std::memory_order_relaxed) == 0)
+ {
+ /* Don't update voices that no longer have a source. But make sure any
+ * update struct it has is returned to the free list.
+ */
+ if UNLIKELY(props)
+ AtomicReplaceHead(context->mFreeVoiceProps, props);
+ return;
+ }
+ if(!props && !force)
+ return;
if(props)
{
@@ -1592,14 +1602,10 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray &slots,
force |= CalcListenerParams(ctx);
force = std::accumulate(slots.begin(), slots.end(), force,
[ctx](const bool f, ALeffectslot *slot) -> bool
- { return CalcEffectSlotParams(slot, ctx) | f; }
- );
+ { return CalcEffectSlotParams(slot, ctx) | f; });
auto calc_params = [ctx,force](ALvoice &voice) -> void
- {
- if(voice.mSourceID.load(std::memory_order_acquire) != 0)
- CalcSourceParams(&voice, ctx, force);
- };
+ { CalcSourceParams(&voice, ctx, force); };
std::for_each(voices.begin(), voices.end(), calc_params);
}
IncrementRef(ctx->mUpdateCount);
@@ -1621,17 +1627,15 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo)
{
for(auto &buffer : slot->MixBuffer)
std::fill_n(buffer.begin(), SamplesToDo, 0.0f);
- }
- );
+ });
/* Process voices that have a playing source. */
- std::for_each(voices.begin(), voices.end(),
- [SamplesToDo,ctx](ALvoice &voice) -> void
- {
- const ALvoice::State vstate{voice.mPlayState.load(std::memory_order_acquire)};
- if(vstate != ALvoice::Stopped) voice.mix(vstate, ctx, SamplesToDo);
- }
- );
+ auto mix_voice = [SamplesToDo,ctx](ALvoice &voice) -> void
+ {
+ const ALvoice::State vstate{voice.mPlayState.load(std::memory_order_acquire)};
+ if(vstate != ALvoice::Stopped) voice.mix(vstate, ctx, SamplesToDo);
+ };
+ std::for_each(voices.begin(), voices.end(), mix_voice);
/* Process effects. */
if(auxslots.empty()) return;
@@ -1643,18 +1647,19 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo)
*/
auto sorted_slots = const_cast<ALeffectslot**>(slots_end);
auto sorted_slots_end = sorted_slots;
- auto in_chain = [](const ALeffectslot *slot1, const ALeffectslot *slot2) noexcept -> bool
- {
- while((slot1=slot1->Params.Target) != nullptr) {
- if(slot1 == slot2) return true;
- }
- return false;
- };
*sorted_slots_end = *slots;
++sorted_slots_end;
while(++slots != slots_end)
{
+ auto in_chain = [](const ALeffectslot *slot1, const ALeffectslot *slot2) noexcept -> bool
+ {
+ while((slot1=slot1->Params.Target) != nullptr) {
+ if(slot1 == slot2) return true;
+ }
+ return false;
+ };
+
/* If this effect slot targets an effect slot already in the list (i.e.
* slots outputs to something in sorted_slots), directly or indirectly,
* insert it prior to that element.
@@ -1674,8 +1679,7 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo)
{
EffectState *state{slot->Params.mEffectState};
state->process(SamplesToDo, slot->Wet.Buffer, state->mOutTarget);
- }
- );
+ });
}