Browse Source

audiofile: use host idle to read file, instead of custom thread

tags/v2.3.0-RC1
falkTX 3 years ago
parent
commit
c41f73f437
2 changed files with 74 additions and 81 deletions
  1. +38
    -64
      source/native-plugins/audio-base.hpp
  2. +36
    -17
      source/native-plugins/audio-file.cpp

+ 38
- 64
source/native-plugins/audio-base.hpp View File

@@ -99,16 +99,14 @@ struct AudioFilePool {
CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool) CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool)
}; };


class AudioFileThread : public CarlaThread
class AudioFileReader
{ {
public: public:
AudioFileThread()
: CarlaThread("AudioFileThread"),
fEntireFileLoaded(false),
AudioFileReader()
: fEntireFileLoaded(false),
fLoopingMode(true), fLoopingMode(true),
fNeedsFrame(0), fNeedsFrame(0),
fNeedsRead(false), fNeedsRead(false),
fQuitNow(true),
fFilePtr(nullptr), fFilePtr(nullptr),
fFileNfo(), fFileNfo(),
fMaxFrame(0), fMaxFrame(0),
@@ -118,9 +116,9 @@ public:
fResampleTempData(nullptr), fResampleTempData(nullptr),
fResampleTempSize(0), fResampleTempSize(0),
fPool(), fPool(),
fMutex(),
fSignal(),
fResampler()
fResampler(),
fPoolMutex(),
fReaderMutex()
{ {
static bool adInitiated = false; static bool adInitiated = false;


@@ -133,11 +131,8 @@ public:
ad_clear_nfo(&fFileNfo); ad_clear_nfo(&fFileNfo);
} }


~AudioFileThread() override
~AudioFileReader()
{ {
CARLA_ASSERT(fQuitNow);
CARLA_ASSERT(! isThreadRunning());

cleanup(); cleanup();
} }


@@ -168,27 +163,14 @@ public:
fPool.destroy(); 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; fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
fQuitNow = true;

fSignal.signal();
stopThread(1000);


const CarlaMutexLocker cml(fMutex);
fPool.reset(); fPool.reset();
} }


@@ -224,14 +206,14 @@ public:


fNeedsFrame = frame; fNeedsFrame = frame;
fNeedsRead = true; fNeedsRead = true;
fSignal.signal();
} }


bool loadFilename(const char* const filename, const uint32_t sampleRate) 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); CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);


const CarlaMutexLocker cml(fReaderMutex);

cleanup(); cleanup();
ad_clear_nfo(&fFileNfo); ad_clear_nfo(&fFileNfo);


@@ -316,7 +298,7 @@ public:
? static_cast<uint32_t>(static_cast<double>(fileNumFrames) * fResampleRatio + 0.5) ? static_cast<uint32_t>(static_cast<double>(fileNumFrames) * fResampleRatio + 0.5)
: fileNumFrames; : fileNumFrames;


readPoll();
fNeedsRead = true;
return true; return true;
} }
else else
@@ -333,14 +315,14 @@ public:
{ {
CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,); CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,);


const CarlaMutexLocker cml(fMutex);
const CarlaMutexLocker cml(fPoolMutex);


pool.startFrame = fPool.startFrame; pool.startFrame = fPool.startFrame;
carla_copyFloats(pool.buffer[0], fPool.buffer[0], fPool.numFrames); carla_copyFloats(pool.buffer[0], fPool.buffer[0], fPool.numFrames);
carla_copyFloats(pool.buffer[1], fPool.buffer[1], 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); CARLA_SAFE_ASSERT_RETURN(fPool.numFrames != 0, false);


@@ -356,9 +338,9 @@ public:
const uint64_t numFramesNearEnd = fPool.numFrames*3/4; const uint64_t numFramesNearEnd = fPool.numFrames*3/4;


#if 1 #if 1
const CarlaMutexLocker cml(fMutex);
const CarlaMutexLocker cml(fPoolMutex);
#else #else
const CarlaMutexTryLocker cmtl(fMutex);
const CarlaMutexTryLocker cmtl(fPoolMutex);
if (! cmtl.wasLocked()) if (! cmtl.wasLocked())
{ {
for (int i=0; i<5; ++i) for (int i=0; i<5; ++i)
@@ -376,6 +358,7 @@ public:
{ {
if (fPool.startFrame + fPool.numFrames <= fMaxFrame) if (fPool.startFrame + fPool.numFrames <= fMaxFrame)
{ {
needsRead = true;
setNeedsRead(framePos); setNeedsRead(framePos);
return false; return false;
} }
@@ -384,6 +367,7 @@ public:


if (frameDiff + frames >= fPool.numFrames) if (frameDiff + frames >= fPool.numFrames)
{ {
needsRead = true;
setNeedsRead(framePos); setNeedsRead(framePos);
return false; return false;
} }
@@ -397,6 +381,7 @@ public:


if (frameDiff + frames >= fPool.numFrames) if (frameDiff + frames >= fPool.numFrames)
{ {
needsRead = true;
setNeedsRead(framePos); setNeedsRead(framePos);
return false; return false;
} }
@@ -406,7 +391,10 @@ public:
} }


if (frameDiff > numFramesNearEnd) if (frameDiff > numFramesNearEnd)
{
needsRead = true;
setNeedsRead(framePos + frames); setNeedsRead(framePos + frames);
}


return true; return true;
} }
@@ -452,17 +440,16 @@ public:


{ {
// lock, and put data asap // 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) if (j % 2 == 0)
{ {
@@ -487,6 +474,8 @@ public:


void readPoll() void readPoll()
{ {
const CarlaMutexLocker cml(fReaderMutex);

if (fMaxFrame == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr) if (fMaxFrame == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr)
{ {
carla_debug("R: no song loaded"); carla_debug("R: no song loaded");
@@ -589,7 +578,7 @@ public:
} }


// lock, and put data asap // lock, and put data asap
const CarlaMutexLocker cml(fMutex);
const CarlaMutexLocker cml(fPoolMutex);


do { do {
if (isMonoFile) if (isMonoFile)
@@ -639,27 +628,11 @@ public:
fNeedsRead = false; fNeedsRead = false;
} }


protected:
void run() override
{
while (! fQuitNow)
{
if (fNeedsRead)
readPoll();

if (fQuitNow)
break;

fSignal.wait();
}
}

private: private:
bool fEntireFileLoaded; bool fEntireFileLoaded;
bool fLoopingMode; bool fLoopingMode;
volatile uint64_t fNeedsFrame; volatile uint64_t fNeedsFrame;
volatile bool fNeedsRead; volatile bool fNeedsRead;
volatile bool fQuitNow;


void* fFilePtr; void* fFilePtr;
ADInfo fFileNfo; ADInfo fFileNfo;
@@ -674,11 +647,12 @@ private:
size_t fResampleTempSize; size_t fResampleTempSize;


AudioFilePool fPool; AudioFilePool fPool;
CarlaMutex fMutex;
CarlaSignal fSignal;
Resampler fResampler; Resampler fResampler;


CARLA_DECLARE_NON_COPY_STRUCT(AudioFileThread)
CarlaMutex fPoolMutex;
CarlaMutex fReaderMutex;

CARLA_DECLARE_NON_COPY_STRUCT(AudioFileReader)
}; };


#endif // AUDIO_BASE_HPP_INCLUDED #endif // AUDIO_BASE_HPP_INCLUDED

+ 36
- 17
source/native-plugins/audio-file.cpp View File

@@ -57,9 +57,10 @@ public:
fLoopMode(true), fLoopMode(true),
fDoProcess(false), fDoProcess(false),
fWasPlayingBefore(false), fWasPlayingBefore(false),
fNeedsFileRead(false),
fMaxFrame(0), fMaxFrame(0),
fPool(), fPool(),
fThread(),
fReader(),
fPrograms(hostGetFilePath("audio"), audiofilesWildcard) fPrograms(hostGetFilePath("audio"), audiofilesWildcard)
#ifndef __MOD_DEVICES__ #ifndef __MOD_DEVICES__
, fInlineDisplay() , fInlineDisplay()
@@ -69,7 +70,7 @@ public:


~AudioFilePlugin() override ~AudioFilePlugin() override
{ {
fThread.stopNow();
fReader.reset();
fPool.destroy(); fPool.destroy();
} }


@@ -126,7 +127,7 @@ protected:
return; return;


fLoopMode = b; fLoopMode = b;
fThread.setLoopingMode(b);
fReader.setLoopingMode(b);
} }


void setCustomData(const char* const key, const char* const value) override void setCustomData(const char* const key, const char* const value) override
@@ -148,6 +149,7 @@ protected:


float* out1 = outBuffer[0]; float* out1 = outBuffer[0];
float* out2 = outBuffer[1]; float* out2 = outBuffer[1];
bool needsIdleRequest = false;


if (! fDoProcess) if (! fDoProcess)
{ {
@@ -162,7 +164,7 @@ protected:
{ {
// carla_stderr("P: not playing"); // carla_stderr("P: not playing");
if (timePos->frame == 0 && fWasPlayingBefore) if (timePos->frame == 0 && fWasPlayingBefore)
fThread.setNeedsRead(timePos->frame);
fReader.setNeedsRead(timePos->frame);


carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);
@@ -178,7 +180,11 @@ protected:
if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !fLoopMode) if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !fLoopMode)
{ {
if (timePos->frame < fPool.startFrame) if (timePos->frame < fPool.startFrame)
fThread.setNeedsRead(timePos->frame);
{
needsIdleRequest = true;
fNeedsFileRead = true;
fReader.setNeedsRead(timePos->frame);
}


carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);
@@ -192,14 +198,18 @@ protected:
} }
if (fInlineDisplay.pending == InlineDisplayNotPending) if (fInlineDisplay.pending == InlineDisplayNotPending)
{ {
needsIdleRequest = true;
fInlineDisplay.pending = InlineDisplayNeedRequest; fInlineDisplay.pending = InlineDisplayNeedRequest;
hostRequestIdle();
} }
#endif #endif

if (needsIdleRequest)
hostRequestIdle();

return; return;
} }


if (fThread.isEntireFileLoaded())
if (fReader.isEntireFileLoaded())
{ {
// NOTE: timePos->frame is always < fMaxFrame (or looping) // NOTE: timePos->frame is always < fMaxFrame (or looping)
uint32_t targetStartFrame = static_cast<uint32_t>(fLoopMode ? timePos->frame % fMaxFrame : timePos->frame); uint32_t targetStartFrame = static_cast<uint32_t>(fLoopMode ? timePos->frame % fMaxFrame : timePos->frame);
@@ -237,11 +247,13 @@ protected:
} }
else else
{ {
if (! fThread.tryPutData(out1, out2, timePos->frame, frames))
if (! fReader.tryPutData(out1, out2, timePos->frame, frames, needsIdleRequest))
{ {
carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);
} }
if (needsIdleRequest)
fNeedsFileRead = true;
} }


#ifndef __MOD_DEVICES__ #ifndef __MOD_DEVICES__
@@ -253,10 +265,13 @@ protected:
} }
if (fInlineDisplay.pending == InlineDisplayNotPending) if (fInlineDisplay.pending == InlineDisplayNotPending)
{ {
needsIdleRequest = true;
fInlineDisplay.pending = InlineDisplayNeedRequest; fInlineDisplay.pending = InlineDisplayNeedRequest;
hostRequestIdle();
} }
#endif #endif

if (needsIdleRequest)
hostRequestIdle();
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -288,6 +303,9 @@ protected:
{ {
NativePluginWithMidiPrograms<FileAudio>::idle(); NativePluginWithMidiPrograms<FileAudio>::idle();


if (fNeedsFileRead)
fReader.readPoll();

#ifndef __MOD_DEVICES__ #ifndef __MOD_DEVICES__
if (fInlineDisplay.pending == InlineDisplayNeedRequest) if (fInlineDisplay.pending == InlineDisplayNeedRequest)
{ {
@@ -415,11 +433,12 @@ private:
bool fLoopMode; bool fLoopMode;
bool fDoProcess; bool fDoProcess;
bool fWasPlayingBefore; bool fWasPlayingBefore;
bool fNeedsFileRead;


uint32_t fMaxFrame; uint32_t fMaxFrame;


AudioFilePool fPool; AudioFilePool fPool;
AudioFileThread fThread;
AudioFileReader fReader;


NativeMidiPrograms fPrograms; NativeMidiPrograms fPrograms;


@@ -464,7 +483,7 @@ private:
CARLA_ASSERT(filename != nullptr); CARLA_ASSERT(filename != nullptr);
carla_debug("AudioFilePlugin::loadFilename(\"%s\")", filename); carla_debug("AudioFilePlugin::loadFilename(\"%s\")", filename);


fThread.stopNow();
fReader.reset();
fPool.destroy(); fPool.destroy();


if (filename == nullptr || *filename == '\0') if (filename == nullptr || *filename == '\0')
@@ -474,15 +493,15 @@ private:
return; return;
} }


if (fThread.loadFilename(filename, static_cast<uint32_t>(getSampleRate())))
if (fReader.loadFilename(filename, static_cast<uint32_t>(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 else
fThread.startNow();
fReader.readPoll();


fDoProcess = true; fDoProcess = true;
} }


Loading…
Cancel
Save