diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 64713bf37..88f7c8f14 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -503,6 +503,8 @@ enum { MIDI_MINIMAL_LATENCY_MS = 1 }; +constexpr size_t TimeQueueGrainSize = 2000; + #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT #include "tracks/ui/Scrubbing.h" @@ -2001,6 +2003,7 @@ int AudioIO::StartStream(const TransportTracks &tracks, mPlaybackMixers.reset(); mCaptureBuffers.reset(); mResample.reset(); + mTimeQueue.mData.reset(); #ifdef EXPERIMENTAL_MIDI_OUT streamStartTime = 0; @@ -2277,6 +2280,8 @@ bool AudioIO::AllocateBuffers( mMinCaptureSecsToCopy = 0.2 + 0.2 * std::min(size_t(16), mCaptureTracks.size()); + mTimeQueue.mHead = {}; + mTimeQueue.mTail = {}; bool bDone; do { @@ -2321,6 +2326,11 @@ bool AudioIO::AllocateBuffers( mPlaybackBuffers[i] = std::make_unique(floatSample, playbackBufferSize); + const auto timeQueueSize = + (playbackBufferSize + TimeQueueGrainSize - 1) + / TimeQueueGrainSize; + mTimeQueue.mData.reinit( timeQueueSize ); + mTimeQueue.mSize = timeQueueSize; // use track time for the end time, not real time! WaveTrackConstArray mixTracks; @@ -2419,6 +2429,7 @@ void AudioIO::StartStreamCleanup(bool bOnlyBuffers) mPlaybackMixers.reset(); mCaptureBuffers.reset(); mResample.reset(); + mTimeQueue.mData.reset(); if(!bOnlyBuffers) { @@ -2767,6 +2778,7 @@ void AudioIO::StopStream() { mPlaybackBuffers.reset(); mPlaybackMixers.reset(); + mTimeQueue.mData.reset(); } // diff --git a/src/AudioIO.h b/src/AudioIO.h index 7d211e951..e59c876bc 100644 --- a/src/AudioIO.h +++ b/src/AudioIO.h @@ -984,6 +984,21 @@ private: void RealTimeRestart(); } mPlaybackSchedule; + + // Another circular buffer + // Holds track time values corresponding to every nth sample in the playback + // buffers, for some large n + struct TimeQueue { + Doubles mData; + size_t mSize{ 0 }; + // These need not be updated atomically, because we rely on the atomics + // in the playback ring buffers to supply the synchronization. Still, + // align them to avoid false sharing. + alignas(64) struct Cursor { + size_t mIndex {}; + size_t mRemainder {}; + } mHead, mTail; + } mTimeQueue; }; #endif