Browse Source

audiofile: reduce lock time and use a spinlock as guard

tags/v2.3.0-RC1
falkTX 3 years ago
parent
commit
222a350701
2 changed files with 53 additions and 38 deletions
  1. +51
    -36
      source/native-plugins/audio-base.hpp
  2. +2
    -2
      source/native-plugins/audio-file.cpp

+ 51
- 36
source/native-plugins/audio-base.hpp View File

@@ -25,18 +25,22 @@ extern "C" {
#include "audio_decoder/ad.h" #include "audio_decoder/ad.h"
} }


#include "water/threads/ScopedLock.h"
#include "water/threads/SpinLock.h"
#include "zita-resampler/resampler.h" #include "zita-resampler/resampler.h"


typedef struct adinfo ADInfo; typedef struct adinfo ADInfo;


struct AudioFilePool { struct AudioFilePool {
float* buffer[2]; float* buffer[2];
float* tmpbuf[2];
uint32_t numFrames; uint32_t numFrames;
volatile uint64_t startFrame; volatile uint64_t startFrame;


#ifdef CARLA_PROPER_CPP11_SUPPORT #ifdef CARLA_PROPER_CPP11_SUPPORT
AudioFilePool() noexcept AudioFilePool() noexcept
: buffer{nullptr}, : buffer{nullptr},
tmpbuf{nullptr},
numFrames(0), numFrames(0),
startFrame(0) {} startFrame(0) {}
#else #else
@@ -45,6 +49,7 @@ struct AudioFilePool {
startFrame(0) startFrame(0)
{ {
buffer[0] = buffer[1] = nullptr; buffer[0] = buffer[1] = nullptr;
tmpbuf[0] = tmpbuf[1] = nullptr;
} }
#endif #endif


@@ -53,10 +58,12 @@ struct AudioFilePool {
destroy(); destroy();
} }


void create(const uint32_t desiredNumFrames)
void create(const uint32_t desiredNumFrames, const bool withTempBuffers)
{ {
CARLA_ASSERT(buffer[0] == nullptr); CARLA_ASSERT(buffer[0] == nullptr);
CARLA_ASSERT(buffer[1] == nullptr); CARLA_ASSERT(buffer[1] == nullptr);
CARLA_ASSERT(tmpbuf[0] == nullptr);
CARLA_ASSERT(tmpbuf[1] == nullptr);
CARLA_ASSERT(startFrame == 0); CARLA_ASSERT(startFrame == 0);
CARLA_ASSERT(numFrames == 0); CARLA_ASSERT(numFrames == 0);


@@ -64,6 +71,12 @@ struct AudioFilePool {
buffer[0] = new float[numFrames]; buffer[0] = new float[numFrames];
buffer[1] = new float[numFrames]; buffer[1] = new float[numFrames];


if (withTempBuffers)
{
tmpbuf[0] = new float[numFrames];
tmpbuf[1] = new float[numFrames];
}

reset(); reset();
} }


@@ -81,6 +94,18 @@ struct AudioFilePool {
buffer[1] = nullptr; buffer[1] = nullptr;
} }


if (tmpbuf[0] != nullptr)
{
delete[] tmpbuf[0];
tmpbuf[0] = nullptr;
}

if (tmpbuf[1] != nullptr)
{
delete[] tmpbuf[1];
tmpbuf[1] = nullptr;
}

startFrame = 0; startFrame = 0;
numFrames = 0; numFrames = 0;
} }
@@ -93,6 +118,11 @@ struct AudioFilePool {
{ {
carla_zeroFloats(buffer[0], numFrames); carla_zeroFloats(buffer[0], numFrames);
carla_zeroFloats(buffer[1], numFrames); carla_zeroFloats(buffer[1], numFrames);

if (tmpbuf[0] != nullptr)
carla_zeroFloats(tmpbuf[0], numFrames);
if (tmpbuf[1] != nullptr)
carla_zeroFloats(tmpbuf[1], numFrames);
} }
} }


@@ -165,8 +195,8 @@ public:


void reset() void reset()
{ {
const CarlaMutexLocker cml1(fPoolMutex);
const CarlaMutexLocker cml2(fReaderMutex);
const water::GenericScopedLock<water::SpinLock> gsl(fPoolMutex);
const CarlaMutexLocker cml(fReaderMutex);


fNeedsFrame = 0; fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
@@ -256,7 +286,7 @@ public:
if (fileNumFrames <= poolNumFrames) if (fileNumFrames <= poolNumFrames)
{ {
// entire file fits in a small pool, lets read it now // entire file fits in a small pool, lets read it now
fPool.create(resampleNumFrames != 0 ? resampleNumFrames : fileNumFrames);
fPool.create(resampleNumFrames != 0 ? resampleNumFrames : fileNumFrames, false);
readEntireFileIntoPool(resampleNumFrames != 0); readEntireFileIntoPool(resampleNumFrames != 0);
ad_close(fFilePtr); ad_close(fFilePtr);
fFilePtr = nullptr; fFilePtr = nullptr;
@@ -264,7 +294,7 @@ public:
else else
{ {
// file is too big for our audio pool, we need an extra buffer // file is too big for our audio pool, we need an extra buffer
fPool.create(poolNumFrames);
fPool.create(poolNumFrames, true);


const size_t pollTempSize = poolNumFrames * fFileNfo.channels; const size_t pollTempSize = poolNumFrames * fFileNfo.channels;
const size_t resampleTempSize = resampleNumFrames * fFileNfo.channels; const size_t resampleTempSize = resampleNumFrames * fFileNfo.channels;
@@ -315,7 +345,7 @@ public:
{ {
CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,); CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,);


const CarlaMutexLocker cml(fPoolMutex);
const water::GenericScopedLock<water::SpinLock> gsl(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);
@@ -337,22 +367,7 @@ public:
uint64_t frameDiff; uint64_t frameDiff;
const uint64_t numFramesNearEnd = fPool.numFrames*3/4; const uint64_t numFramesNearEnd = fPool.numFrames*3/4;


#if 1
const CarlaMutexLocker cml(fPoolMutex);
#else
const CarlaMutexTryLocker cmtl(fPoolMutex);
if (! cmtl.wasLocked())
{
for (int i=0; i<5; ++i)
{
pthread_yield();
if (cmtl.tryAgain())
break;
if (i == 4)
return false;
}
}
#endif
const water::GenericScopedLock<water::SpinLock> gsl(fPoolMutex);


if (framePos < fPool.startFrame) if (framePos < fPool.startFrame)
{ {
@@ -431,7 +446,7 @@ public:
fResampler.inp_data = buffer; fResampler.inp_data = buffer;
fResampler.out_data = rbuffer; fResampler.out_data = rbuffer;
fResampler.process(); fResampler.process();
CARLA_ASSERT_INT(fResampler.inp_count == 0, fResampler.inp_count);
CARLA_ASSERT_INT(fResampler.inp_count <= 1, fResampler.inp_count);
} }
else else
{ {
@@ -440,7 +455,7 @@ public:


{ {
// lock, and put data asap // lock, and put data asap
const CarlaMutexLocker cml(fPoolMutex);
const water::GenericScopedLock<water::SpinLock> gsl(fPoolMutex);


if (numChannels == 1) if (numChannels == 1)
{ {
@@ -559,10 +574,8 @@ public:


// local copy // local copy
const uint32_t poolNumFrames = fPool.numFrames; const uint32_t poolNumFrames = fPool.numFrames;
const int64_t fileFrames = fFileNfo.frames;
const bool isMonoFile = fFileNfo.channels == 1;
float* const pbuffer0 = fPool.buffer[0];
float* const pbuffer1 = fPool.buffer[1];
float* const pbuffer0 = fPool.tmpbuf[0];
float* const pbuffer1 = fPool.tmpbuf[1];
const float* tmpbuf = fPollTempData; const float* tmpbuf = fPollTempData;


// resample as needed // resample as needed
@@ -574,14 +587,11 @@ public:
fResampler.inp_data = fPollTempData; fResampler.inp_data = fPollTempData;
fResampler.out_data = fResampleTempData; fResampler.out_data = fResampleTempData;
fResampler.process(); fResampler.process();
CARLA_ASSERT_INT(fResampler.inp_count == 0, fResampler.inp_count);
CARLA_ASSERT_INT(fResampler.inp_count <= 1, fResampler.inp_count);
} }


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

do { do {
if (isMonoFile)
if (fFileNfo.channels == 1)
{ {
for (; i < poolNumFrames && j < rv; ++i, ++j) for (; i < poolNumFrames && j < rv; ++i, ++j)
pbuffer0[i] = pbuffer1[i] = tmpbuf[j]; pbuffer0[i] = pbuffer1[i] = tmpbuf[j];
@@ -605,7 +615,7 @@ public:
if (i >= poolNumFrames) if (i >= poolNumFrames)
break; break;


if (rv == fileFrames)
if (rv == fFileNfo.frames)
{ {
// full file read // full file read
j = 0; j = 0;
@@ -622,6 +632,11 @@ public:


} while (i < poolNumFrames); } while (i < poolNumFrames);


// lock, and put data asap
const water::GenericScopedLock<water::SpinLock> gsl(fPoolMutex);

carla_copyFloats(fPool.buffer[0], pbuffer0, poolNumFrames);
carla_copyFloats(fPool.buffer[1], pbuffer1, poolNumFrames);
fPool.startFrame = static_cast<uint64_t>(readFrame); fPool.startFrame = static_cast<uint64_t>(readFrame);
} }


@@ -649,8 +664,8 @@ private:
AudioFilePool fPool; AudioFilePool fPool;
Resampler fResampler; Resampler fResampler;


CarlaMutex fPoolMutex;
CarlaMutex fReaderMutex;
water::SpinLock fPoolMutex;
CarlaMutex fReaderMutex;


CARLA_DECLARE_NON_COPY_STRUCT(AudioFileReader) CARLA_DECLARE_NON_COPY_STRUCT(AudioFileReader)
}; };


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

@@ -45,7 +45,7 @@ class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>
{ {
public: public:
#ifndef __MOD_DEVICES__ #ifndef __MOD_DEVICES__
typedef enum PendingInlineDisplay : uint8_t {
typedef enum _PendingInlineDisplay : uint8_t {
InlineDisplayNotPending, InlineDisplayNotPending,
InlineDisplayNeedRequest, InlineDisplayNeedRequest,
InlineDisplayRequesting InlineDisplayRequesting
@@ -495,7 +495,7 @@ private:


if (fReader.loadFilename(filename, static_cast<uint32_t>(getSampleRate()))) if (fReader.loadFilename(filename, static_cast<uint32_t>(getSampleRate())))
{ {
fPool.create(fReader.getPoolNumFrames());
fPool.create(fReader.getPoolNumFrames(), false);
fMaxFrame = fReader.getMaxFrame(); fMaxFrame = fReader.getMaxFrame();


if (fReader.isEntireFileLoaded()) if (fReader.isEntireFileLoaded())


Loading…
Cancel
Save