aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2022-01-08 23:21:35 -0800
committerChris Robinson <[email protected]>2022-01-08 23:21:35 -0800
commita2c5ffd9bcbe6e0fec17fd085b713593a4cb4127 (patch)
tree22e566d54465215bcf455e67323d6a265246aab7
parente32c214e9c8f2c1a9aab06ebd2bad8475c12949c (diff)
Slightly improve handling of stopping voices
-rw-r--r--core/voice.cpp46
1 files changed, 27 insertions, 19 deletions
diff --git a/core/voice.cpp b/core/voice.cpp
index 16117d4a..07400b07 100644
--- a/core/voice.cpp
+++ b/core/voice.cpp
@@ -564,6 +564,11 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
* to a multiple of 4 samples to maintain alignment.
*/
DstBufferSize = static_cast<uint>(DataSize64) & ~3u;
+ /* If the voice is stopping, only one mixing iteration will
+ * be done, so ensure it fades out completely this mix.
+ */
+ if(unlikely(vstate == Stopping))
+ Counter = std::min(Counter, DstBufferSize);
}
ASSUME(DstBufferSize > 0);
}
@@ -571,13 +576,13 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
if(unlikely(!BufferListItem))
{
+ const size_t srcOffset{(increment*DstBufferSize + DataPosFrac)>>MixerFracBits};
auto prevSamples = mPrevSamples.data();
SrcBufferSize = SrcBufferSize - PostPadding + MaxResamplerEdge;
for(auto *chanbuffer : MixingSamples)
{
auto srcend = std::copy_n(prevSamples->data(), MaxResamplerPadding,
chanbuffer-MaxResamplerEdge);
- ++prevSamples;
/* When loading from a voice that ended prematurely, only take
* the samples that get closest to 0 amplitude. This helps
@@ -588,6 +593,10 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
auto srciter = std::min_element(chanbuffer, srcend, abs_lt);
std::fill(srciter+1, chanbuffer + SrcBufferSize, *srciter);
+
+ std::copy_n(chanbuffer-MaxResamplerEdge+srcOffset, prevSamples->size(),
+ prevSamples->data());
+ ++prevSamples;
}
}
else
@@ -701,6 +710,10 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
parms.Gains.Current.data(), TargetGains, Counter, OutPos);
}
}
+ /* If the voice is stopping, we're now done. */
+ if(unlikely(vstate == Stopping))
+ break;
+
/* Update positions */
DataPosFrac += increment*DstBufferSize;
const uint SrcSamplesDone{DataPosFrac>>MixerFracBits};
@@ -739,24 +752,19 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
}
else if(mFlags.test(VoiceIsCallback))
{
- /* Don't use up the stored callback samples when stopping (pausing)
- * since they'll be replayed when resuming.
- */
- if(likely(vstate == Playing))
+ /* Handle callback buffer source */
+ if(SrcSamplesDone < mNumCallbackSamples)
{
- if(SrcSamplesDone < mNumCallbackSamples)
- {
- const size_t byteOffset{SrcSamplesDone*mFrameSize};
- const size_t byteEnd{mNumCallbackSamples*mFrameSize};
- al::byte *data{BufferListItem->mSamples};
- std::copy(data+byteOffset, data+byteEnd, data);
- mNumCallbackSamples -= SrcSamplesDone;
- }
- else
- {
- BufferListItem = nullptr;
- mNumCallbackSamples = 0;
- }
+ const size_t byteOffset{SrcSamplesDone*mFrameSize};
+ const size_t byteEnd{mNumCallbackSamples*mFrameSize};
+ al::byte *data{BufferListItem->mSamples};
+ std::copy(data+byteOffset, data+byteEnd, data);
+ mNumCallbackSamples -= SrcSamplesDone;
+ }
+ else
+ {
+ BufferListItem = nullptr;
+ mNumCallbackSamples = 0;
}
}
else
@@ -773,7 +781,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const uint SamplesToDo
if(!BufferListItem) BufferListItem = BufferLoopItem;
} while(BufferListItem);
}
- } while(OutPos < SamplesToDo && likely(vstate == Playing));
+ } while(OutPos < SamplesToDo);
mFlags.set(VoiceIsFading);