From c41f73f437c4004545dd5b9a2dd5aeba096b43ca Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 30 Dec 2020 03:54:02 +0000 Subject: [PATCH] audiofile: use host idle to read file, instead of custom thread --- source/native-plugins/audio-base.hpp | 102 ++++++++++----------------- source/native-plugins/audio-file.cpp | 53 +++++++++----- 2 files changed, 74 insertions(+), 81 deletions(-) diff --git a/source/native-plugins/audio-base.hpp b/source/native-plugins/audio-base.hpp index 86c02dad7..42b9a8687 100644 --- a/source/native-plugins/audio-base.hpp +++ b/source/native-plugins/audio-base.hpp @@ -99,16 +99,14 @@ struct AudioFilePool { CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool) }; -class AudioFileThread : public CarlaThread +class AudioFileReader { public: - AudioFileThread() - : CarlaThread("AudioFileThread"), - fEntireFileLoaded(false), + AudioFileReader() + : fEntireFileLoaded(false), fLoopingMode(true), fNeedsFrame(0), fNeedsRead(false), - fQuitNow(true), fFilePtr(nullptr), fFileNfo(), fMaxFrame(0), @@ -118,9 +116,9 @@ public: fResampleTempData(nullptr), fResampleTempSize(0), fPool(), - fMutex(), - fSignal(), - fResampler() + fResampler(), + fPoolMutex(), + fReaderMutex() { static bool adInitiated = false; @@ -133,11 +131,8 @@ public: ad_clear_nfo(&fFileNfo); } - ~AudioFileThread() override + ~AudioFileReader() { - CARLA_ASSERT(fQuitNow); - CARLA_ASSERT(! isThreadRunning()); - cleanup(); } @@ -168,27 +163,14 @@ public: fPool.destroy(); } - void startNow() + void reset() { - if (fPollTempData == nullptr) - return; - - fNeedsFrame = 0; - fNeedsRead = false; - fQuitNow = false; - startThread(); - } + const CarlaMutexLocker cml1(fPoolMutex); + const CarlaMutexLocker cml2(fReaderMutex); - void stopNow() - { fNeedsFrame = 0; fNeedsRead = false; - fQuitNow = true; - - fSignal.signal(); - stopThread(1000); - const CarlaMutexLocker cml(fMutex); fPool.reset(); } @@ -224,14 +206,14 @@ public: fNeedsFrame = frame; fNeedsRead = true; - fSignal.signal(); } bool loadFilename(const char* const filename, const uint32_t sampleRate) { - CARLA_SAFE_ASSERT_RETURN(! isThreadRunning(), false); CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false); + const CarlaMutexLocker cml(fReaderMutex); + cleanup(); ad_clear_nfo(&fFileNfo); @@ -316,7 +298,7 @@ public: ? static_cast(static_cast(fileNumFrames) * fResampleRatio + 0.5) : fileNumFrames; - readPoll(); + fNeedsRead = true; return true; } else @@ -333,14 +315,14 @@ public: { CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,); - const CarlaMutexLocker cml(fMutex); + const CarlaMutexLocker cml(fPoolMutex); pool.startFrame = fPool.startFrame; carla_copyFloats(pool.buffer[0], fPool.buffer[0], fPool.numFrames); carla_copyFloats(pool.buffer[1], fPool.buffer[1], fPool.numFrames); } - bool tryPutData(float* const out1, float* const out2, uint64_t framePos, const uint32_t frames) + bool tryPutData(float* const out1, float* const out2, uint64_t framePos, const uint32_t frames, bool& needsRead) { CARLA_SAFE_ASSERT_RETURN(fPool.numFrames != 0, false); @@ -356,9 +338,9 @@ public: const uint64_t numFramesNearEnd = fPool.numFrames*3/4; #if 1 - const CarlaMutexLocker cml(fMutex); + const CarlaMutexLocker cml(fPoolMutex); #else - const CarlaMutexTryLocker cmtl(fMutex); + const CarlaMutexTryLocker cmtl(fPoolMutex); if (! cmtl.wasLocked()) { for (int i=0; i<5; ++i) @@ -376,6 +358,7 @@ public: { if (fPool.startFrame + fPool.numFrames <= fMaxFrame) { + needsRead = true; setNeedsRead(framePos); return false; } @@ -384,6 +367,7 @@ public: if (frameDiff + frames >= fPool.numFrames) { + needsRead = true; setNeedsRead(framePos); return false; } @@ -397,6 +381,7 @@ public: if (frameDiff + frames >= fPool.numFrames) { + needsRead = true; setNeedsRead(framePos); return false; } @@ -406,7 +391,10 @@ public: } if (frameDiff > numFramesNearEnd) + { + needsRead = true; setNeedsRead(framePos + frames); + } return true; } @@ -452,17 +440,16 @@ public: { // lock, and put data asap - const CarlaMutexLocker cml(fMutex); + const CarlaMutexLocker cml(fPoolMutex); - for (ssize_t i=0, j=0; j < rv; ++j) + if (numChannels == 1) { - if (numChannels == 1) - { - fPool.buffer[0][i] = rbuffer[j]; - fPool.buffer[1][i] = rbuffer[j]; - ++i; - } - else + for (ssize_t i=0, j=0; j < rv; ++i, ++j) + fPool.buffer[0][i] = fPool.buffer[1][i] = rbuffer[j]; + } + else + { + for (ssize_t i=0, j=0; j < rv; ++j) { if (j % 2 == 0) { @@ -487,6 +474,8 @@ public: void readPoll() { + const CarlaMutexLocker cml(fReaderMutex); + if (fMaxFrame == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr) { carla_debug("R: no song loaded"); @@ -589,7 +578,7 @@ public: } // lock, and put data asap - const CarlaMutexLocker cml(fMutex); + const CarlaMutexLocker cml(fPoolMutex); do { if (isMonoFile) @@ -639,27 +628,11 @@ public: fNeedsRead = false; } -protected: - void run() override - { - while (! fQuitNow) - { - if (fNeedsRead) - readPoll(); - - if (fQuitNow) - break; - - fSignal.wait(); - } - } - private: bool fEntireFileLoaded; bool fLoopingMode; volatile uint64_t fNeedsFrame; volatile bool fNeedsRead; - volatile bool fQuitNow; void* fFilePtr; ADInfo fFileNfo; @@ -674,11 +647,12 @@ private: size_t fResampleTempSize; AudioFilePool fPool; - CarlaMutex fMutex; - CarlaSignal fSignal; Resampler fResampler; - CARLA_DECLARE_NON_COPY_STRUCT(AudioFileThread) + CarlaMutex fPoolMutex; + CarlaMutex fReaderMutex; + + CARLA_DECLARE_NON_COPY_STRUCT(AudioFileReader) }; #endif // AUDIO_BASE_HPP_INCLUDED diff --git a/source/native-plugins/audio-file.cpp b/source/native-plugins/audio-file.cpp index 584acda27..76338730d 100644 --- a/source/native-plugins/audio-file.cpp +++ b/source/native-plugins/audio-file.cpp @@ -57,9 +57,10 @@ public: fLoopMode(true), fDoProcess(false), fWasPlayingBefore(false), + fNeedsFileRead(false), fMaxFrame(0), fPool(), - fThread(), + fReader(), fPrograms(hostGetFilePath("audio"), audiofilesWildcard) #ifndef __MOD_DEVICES__ , fInlineDisplay() @@ -69,7 +70,7 @@ public: ~AudioFilePlugin() override { - fThread.stopNow(); + fReader.reset(); fPool.destroy(); } @@ -126,7 +127,7 @@ protected: return; fLoopMode = b; - fThread.setLoopingMode(b); + fReader.setLoopingMode(b); } void setCustomData(const char* const key, const char* const value) override @@ -148,6 +149,7 @@ protected: float* out1 = outBuffer[0]; float* out2 = outBuffer[1]; + bool needsIdleRequest = false; if (! fDoProcess) { @@ -162,7 +164,7 @@ protected: { // carla_stderr("P: not playing"); if (timePos->frame == 0 && fWasPlayingBefore) - fThread.setNeedsRead(timePos->frame); + fReader.setNeedsRead(timePos->frame); carla_zeroFloats(out1, frames); carla_zeroFloats(out2, frames); @@ -178,7 +180,11 @@ protected: if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !fLoopMode) { if (timePos->frame < fPool.startFrame) - fThread.setNeedsRead(timePos->frame); + { + needsIdleRequest = true; + fNeedsFileRead = true; + fReader.setNeedsRead(timePos->frame); + } carla_zeroFloats(out1, frames); carla_zeroFloats(out2, frames); @@ -192,14 +198,18 @@ protected: } if (fInlineDisplay.pending == InlineDisplayNotPending) { + needsIdleRequest = true; fInlineDisplay.pending = InlineDisplayNeedRequest; - hostRequestIdle(); } #endif + + if (needsIdleRequest) + hostRequestIdle(); + return; } - if (fThread.isEntireFileLoaded()) + if (fReader.isEntireFileLoaded()) { // NOTE: timePos->frame is always < fMaxFrame (or looping) uint32_t targetStartFrame = static_cast(fLoopMode ? timePos->frame % fMaxFrame : timePos->frame); @@ -237,11 +247,13 @@ protected: } else { - if (! fThread.tryPutData(out1, out2, timePos->frame, frames)) + if (! fReader.tryPutData(out1, out2, timePos->frame, frames, needsIdleRequest)) { carla_zeroFloats(out1, frames); carla_zeroFloats(out2, frames); } + if (needsIdleRequest) + fNeedsFileRead = true; } #ifndef __MOD_DEVICES__ @@ -253,10 +265,13 @@ protected: } if (fInlineDisplay.pending == InlineDisplayNotPending) { + needsIdleRequest = true; fInlineDisplay.pending = InlineDisplayNeedRequest; - hostRequestIdle(); } #endif + + if (needsIdleRequest) + hostRequestIdle(); } // ------------------------------------------------------------------- @@ -288,6 +303,9 @@ protected: { NativePluginWithMidiPrograms::idle(); + if (fNeedsFileRead) + fReader.readPoll(); + #ifndef __MOD_DEVICES__ if (fInlineDisplay.pending == InlineDisplayNeedRequest) { @@ -415,11 +433,12 @@ private: bool fLoopMode; bool fDoProcess; bool fWasPlayingBefore; + bool fNeedsFileRead; uint32_t fMaxFrame; AudioFilePool fPool; - AudioFileThread fThread; + AudioFileReader fReader; NativeMidiPrograms fPrograms; @@ -464,7 +483,7 @@ private: CARLA_ASSERT(filename != nullptr); carla_debug("AudioFilePlugin::loadFilename(\"%s\")", filename); - fThread.stopNow(); + fReader.reset(); fPool.destroy(); if (filename == nullptr || *filename == '\0') @@ -474,15 +493,15 @@ private: return; } - if (fThread.loadFilename(filename, static_cast(getSampleRate()))) + if (fReader.loadFilename(filename, static_cast(getSampleRate()))) { - fPool.create(fThread.getPoolNumFrames()); - fMaxFrame = fThread.getMaxFrame(); + fPool.create(fReader.getPoolNumFrames()); + fMaxFrame = fReader.getMaxFrame(); - if (fThread.isEntireFileLoaded()) - fThread.putAllData(fPool); + if (fReader.isEntireFileLoaded()) + fReader.putAllData(fPool); else - fThread.startNow(); + fReader.readPoll(); fDoProcess = true; }