diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index fc904d138..996269d00 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -2102,7 +2102,7 @@ bool AudioIoCallback::FillOutputBuffers( // Do realtime effects if( !dropQuickly && len > 0 ) { if (pScope) - pScope->Process(mTrackChannelsBuffer[0], mAudioScratchBuffers.data(), len); + pScope->Process(mTrackChannelsBuffer[0], mAudioScratchBuffers.data(), mScratchPointers.data(), len); // Mix the results with the existing output (software playthrough) and // apply panning. If post panning effects are desired, the panning would // need to be be split out from the mixing and applied in a separate step. diff --git a/src/effects/RealtimeEffectManager.cpp b/src/effects/RealtimeEffectManager.cpp index 23ca98863..c785128b9 100644 --- a/src/effects/RealtimeEffectManager.cpp +++ b/src/effects/RealtimeEffectManager.cpp @@ -173,8 +173,8 @@ void RealtimeEffectManager::ProcessStart() // This will be called in a different thread than the main GUI thread. // size_t RealtimeEffectManager::Process(Track *track, - float **buffers, - size_t numSamples) + float *const *buffers, float *const *scratch, + size_t numSamples) { using namespace std::chrono; @@ -197,15 +197,13 @@ size_t RealtimeEffectManager::Process(Track *track, static_cast(alloca(chans * sizeof(float *))); const auto obuf = static_cast(alloca(chans * sizeof(float *))); - const auto scratch = - static_cast(alloca(numSamples * sizeof(float))); // And populate the input with the buffers we've been given while allocating // NEW output buffers for (unsigned int i = 0; i < chans; i++) { ibuf[i] = buffers[i]; - obuf[i] = static_cast(alloca(numSamples * sizeof(float))); + obuf[i] = scratch[i]; } // Now call each effect in the chain while swapping buffer pointers to feed the @@ -218,8 +216,7 @@ size_t RealtimeEffectManager::Process(Track *track, if (bypassed) return; - state.Process(track, chans, ibuf, obuf, scratch, numSamples); - + state.Process(track, chans, ibuf, obuf, scratch[chans], numSamples); for (auto i = 0; i < chans; ++i) std::swap(ibuf[i], obuf[i]); called++; diff --git a/src/effects/RealtimeEffectManager.h b/src/effects/RealtimeEffectManager.h index 6d679f409..aa81bd86c 100644 --- a/src/effects/RealtimeEffectManager.h +++ b/src/effects/RealtimeEffectManager.h @@ -86,7 +86,9 @@ class TENACITY_DLL_API RealtimeEffectManager final friend RealtimeEffects::ProcessingScope; void ProcessStart(); - size_t Process(Track *track, float **buffers, size_t numSamples); + /*! @copydoc ProcessScope::Process */ + size_t Process(Track *track, + float *const *buffers, float *const *scratch, size_t numSamples); void ProcessEnd() noexcept; RealtimeEffectManager(const RealtimeEffectManager&) = delete; @@ -196,11 +198,17 @@ class ProcessingScope { RealtimeEffectManager::Get(*pProject).ProcessEnd(); } - size_t Process(Track *track, float **buffers, size_t numSamples) + size_t Process(Track *track, + float *const *buffers, /*!< Assume as many buffers, as channels were + specified in the AddTrack call */ + float *const *scratch, /*!< As many temporary buffers as in buffers, + plus one more */ + size_t numSamples //!< length of each buffer + ) { if (auto pProject = mwProject.lock()) return RealtimeEffectManager::Get(*pProject) - .Process(track, buffers, numSamples); + .Process(track, buffers, scratch, numSamples); else return numSamples; // consider them trivially processed }