Browse Source

Rework audio file plugin a bit, clean midi file ignore list

tags/v2.3.0-RC1
falkTX 4 years ago
parent
commit
6d00a6d090
6 changed files with 162 additions and 109 deletions
  1. +5
    -3
      source/backend/engine/CarlaEngineDummy.cpp
  2. +21
    -2
      source/bridges-plugin/CarlaBridgePlugin.cpp
  3. +108
    -47
      source/native-plugins/audio-base.hpp
  4. +17
    -33
      source/native-plugins/audio-file.cpp
  5. +6
    -24
      source/native-plugins/midi-file.cpp
  6. +5
    -0
      source/utils/CarlaMutex.hpp

+ 5
- 3
source/backend/engine/CarlaEngineDummy.cpp View File

@@ -232,9 +232,11 @@ protected:
carla_zeroFloats(audioIns[1], bufferSize);
carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);

int64_t oldTime, newTime;

while (! shouldThreadExit())
{
const int64_t oldTime = getTimeInMicroseconds();
oldTime = getTimeInMicroseconds();

const PendingRtEventsRunner prt(this, bufferSize, true);

@@ -244,7 +246,7 @@ protected:

pData->graph.process(pData, audioIns, audioOuts, bufferSize);

const int64_t newTime = getTimeInMicroseconds();
newTime = getTimeInMicroseconds();
CARLA_SAFE_ASSERT_CONTINUE(newTime >= oldTime);

const int64_t remainingTime = cycleTime - (newTime - oldTime);
@@ -267,7 +269,7 @@ protected:
std::free(audioOuts[0]);
std::free(audioOuts[1]);

carla_stdout("CarlaEngineDummy audio thread finished");
carla_stdout("CarlaEngineDummy audio thread finished with %u Xruns", pData->xruns);
}

// -------------------------------------------------------------------


+ 21
- 2
source/bridges-plugin/CarlaBridgePlugin.cpp View File

@@ -68,6 +68,7 @@
#include "jackbridge/JackBridge.hpp"

#include "water/files/File.h"
#include "water/misc/Time.h"

using CarlaBackend::CarlaEngine;
using CarlaBackend::EngineCallbackOpcode;
@@ -281,6 +282,15 @@ public:

gIsInitiated = true;

const bool testing = std::getenv("CARLA_BRIDGE_TESTING") != nullptr;
int64_t timeToEnd;

if (testing)
{
timeToEnd = water::Time::currentTimeMillis() + 10 * 1000;
fEngine->transportPlay();
}

#if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
# ifndef CARLA_OS_WIN
static const int argc = 0;
@@ -298,6 +308,8 @@ public:
# else
carla_msleep(5);
# endif
if (testing && timeToEnd - water::Time::currentTimeMillis() < 0)
break;
}
#endif

@@ -332,7 +344,7 @@ protected:
}

private:
const CarlaEngine* fEngine;
CarlaEngine* fEngine;

#ifdef USING_JUCE
const juce::ScopedJuceInitialiser_GUI fJuceInitialiser;
@@ -649,7 +661,14 @@ int main(int argc, char* argv[])

if (const CarlaPluginInfo* const pluginInfo = carla_get_plugin_info(gHostHandle, 0))
{
if (pluginInfo->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
if (itype == CarlaBackend::PLUGIN_INTERNAL && (std::strcmp(label, "audiofile") == 0 || std::strcmp(label, "midifile") == 0))
{
if (file.exists())
carla_set_custom_data(gHostHandle, 0,
CarlaBackend::CUSTOM_DATA_TYPE_STRING,
"file", file.getFullPathName().toRawUTF8());
}
else if (pluginInfo->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
{
#ifdef HAVE_X11
if (std::getenv("DISPLAY") != nullptr)


+ 108
- 47
source/native-plugins/audio-base.hpp View File

@@ -97,21 +97,14 @@ struct AudioFilePool {
CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool)
};

class AbstractAudioPlayer
{
public:
virtual ~AbstractAudioPlayer() {}
virtual uint64_t getLastFrame() const = 0;
};

class AudioFileThread : public CarlaThread
{
public:
AudioFileThread(AbstractAudioPlayer* const player)
AudioFileThread()
: CarlaThread("AudioFileThread"),
kPlayer(player),
fEntireFileLoaded(false),
fLoopingMode(true),
fNeedsFrame(0),
fNeedsRead(false),
fQuitNow(true),
fFilePtr(nullptr),
@@ -120,10 +113,9 @@ public:
fPollTempData(nullptr),
fPollTempSize(0),
fPool(),
fMutex()
fMutex(),
fSignal()
{
CARLA_ASSERT(kPlayer != nullptr);

static bool adInitiated = false;

if (! adInitiated)
@@ -168,16 +160,19 @@ public:
if (fPollTempData == nullptr)
return;

fNeedsRead = true;
fNeedsFrame = 0;
fNeedsRead = false;
fQuitNow = false;
startThread();
}

void stopNow()
{
fNeedsFrame = 0;
fNeedsRead = false;
fQuitNow = true;

fSignal.signal();
stopThread(1000);

const CarlaMutexLocker cml(fMutex);
@@ -209,9 +204,14 @@ public:
fLoopingMode = on;
}

void setNeedsRead() noexcept
void setNeedsRead(const uint64_t frame) noexcept
{
if (fEntireFileLoaded)
return;

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

bool loadFilename(const char* const filename, const uint32_t sampleRate)
@@ -295,24 +295,73 @@ public:
carla_copyFloats(pool.buffer[1], fPool.buffer[1], fPool.numFrames);
}

bool tryPutData(AudioFilePool& pool, const uint64_t framePos, const uint32_t frames)
bool tryPutData(float* const out1, float* const out2, uint64_t framePos, const uint32_t frames)
{
CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames, false);
CARLA_SAFE_ASSERT_RETURN(fPool.numFrames != 0, false);

if (framePos >= fPool.numFrames)
return false;
if (framePos >= fNumFileFrames)
{
if (fLoopingMode)
framePos %= fNumFileFrames;
else
return false;
}

uint64_t frameDiff;
const uint64_t numFramesNearEnd = fPool.numFrames*3/4;

#if 1
const CarlaMutexLocker cml(fMutex);
/*
#else
const CarlaMutexTryLocker cmtl(fMutex);
if (! cmtl.wasLocked())
return false;
*/
{
for (int i=0; i<5; ++i)
{
pthread_yield();
if (cmtl.tryAgain())
break;
if (i == 4)
return false;
}
}
#endif

pool.startFrame = fPool.startFrame;
if (framePos < fPool.startFrame)
{
if (fPool.startFrame + fPool.numFrames <= fNumFileFrames)
{
setNeedsRead(framePos);
return false;
}

carla_copyFloats(pool.buffer[0] + framePos, fPool.buffer[0] + framePos, frames);
carla_copyFloats(pool.buffer[1] + framePos, fPool.buffer[1] + framePos, frames);
frameDiff = framePos + (fNumFileFrames - fPool.startFrame);

if (frameDiff + frames >= fPool.numFrames)
{
setNeedsRead(framePos);
return false;
}

carla_copyFloats(out1, fPool.buffer[0] + frameDiff, frames);
carla_copyFloats(out2, fPool.buffer[1] + frameDiff, frames);
}
else
{
frameDiff = framePos - fPool.startFrame;

if (frameDiff + frames >= fPool.numFrames)
{
setNeedsRead(framePos);
return false;
}

carla_copyFloats(out1, fPool.buffer[0] + frameDiff, frames);
carla_copyFloats(out2, fPool.buffer[1] + frameDiff, frames);
}

if (frameDiff > numFramesNearEnd)
setNeedsRead(framePos + frames);

return true;
}
@@ -372,17 +421,19 @@ public:
if (fNumFileFrames == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr)
{
carla_debug("R: no song loaded");
fNeedsFrame = 0;
fNeedsRead = false;
return;
}
if (fPollTempData == nullptr)
{
carla_debug("R: nothing to poll");
fNeedsFrame = 0;
fNeedsRead = false;
return;
}

uint64_t lastFrame = kPlayer->getLastFrame();
uint64_t lastFrame = fNeedsFrame;
int64_t readFrameCheck;

if (lastFrame >= fNumFileFrames)
@@ -398,6 +449,7 @@ public:
else
{
carla_debug("R: transport out of bounds");
fNeedsFrame = 0;
fNeedsRead = false;
return;
}
@@ -428,6 +480,7 @@ public:
if (rv < 0)
{
carla_stderr("R: ad_read failed");
fNeedsFrame = 0;
fNeedsRead = false;
return;
}
@@ -442,36 +495,46 @@ public:
rv += ad_read(fFilePtr, fPollTempData+urv, fPollTempSize-urv);
}

carla_debug("R: reading %li frames at frame %lu", rv, readFrameCheck);

// local copy
const uint32_t poolNumFrame = 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];
const float* const tmpbuf = fPollTempData;

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

do {
for (; i < fPool.numFrames && j < rv; ++j)
for (; i < poolNumFrame && j < rv; ++j)
{
if (fFileNfo.channels == 1)
if (isMonoFile)
{
fPool.buffer[0][i] = fPollTempData[j];
fPool.buffer[1][i] = fPollTempData[j];
pbuffer0[i] = pbuffer1[i] = tmpbuf[j];
i++;
}
else
{
if (j % 2 == 0)
{
fPool.buffer[0][i] = fPollTempData[j];
pbuffer0[i] = tmpbuf[j];
}
else
{
fPool.buffer[1][i] = fPollTempData[j];
i++;
pbuffer1[i] = tmpbuf[j];
++i;
}
}
}

if (i >= fPool.numFrames)
if (i >= poolNumFrame) {
break;
}

if (rv == fFileNfo.frames)
if (rv == fileFrames)
{
// full file read
j = 0;
@@ -481,14 +544,14 @@ public:
{
carla_debug("read break, not enough space");

carla_zeroFloats(fPool.buffer[0] + i, fPool.numFrames - i);
carla_zeroFloats(fPool.buffer[1] + i, fPool.numFrames - i);
carla_zeroFloats(pbuffer0, poolNumFrame - i);
carla_zeroFloats(pbuffer1, poolNumFrame - i);
break;
}

} while (i < fPool.numFrames);
} while (i < poolNumFrame);

fPool.startFrame = lastFrame;
fPool.startFrame = readFrame;
}

fNeedsRead = false;
@@ -497,25 +560,22 @@ public:
protected:
void run() override
{
const uint64_t numFramesNearEnd = fPool.numFrames*3/4;
uint64_t lastFrame;

while (! fQuitNow)
{
lastFrame = kPlayer->getLastFrame();

if (fNeedsRead || lastFrame < fPool.startFrame || lastFrame - fPool.startFrame >= numFramesNearEnd)
if (fNeedsRead)
readPoll();

carla_msleep(50);
if (fQuitNow)
break;

fSignal.wait();
}
}

private:
AbstractAudioPlayer* const kPlayer;

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

@@ -529,6 +589,7 @@ private:

AudioFilePool fPool;
CarlaMutex fMutex;
CarlaSignal fSignal;

CARLA_DECLARE_NON_COPY_STRUCT(AudioFileThread)
};


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

@@ -46,11 +46,9 @@ static const char* const audiofilesWildcard =
// -----------------------------------------------------------------------

#ifdef HAVE_PYQT
class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>,
public AbstractAudioPlayer
class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>
#else
class AudioFilePlugin : public NativePluginClass,
public AbstractAudioPlayer
class AudioFilePlugin : public NativePluginClass
#endif
{
public:
@@ -60,13 +58,12 @@ public:
#else
: NativePluginClass(host),
#endif
AbstractAudioPlayer(),
fLoopMode(true),
fDoProcess(false),
fLastFrame(0),
fWasPlayingBefore(false),
fMaxFrame(0),
fPool(),
fThread(this)
fThread()
#ifdef HAVE_PYQT
, fPrograms(hostGetFilePath("audio"), audiofilesWildcard),
fInlineDisplay()
@@ -80,11 +77,6 @@ public:
fPool.destroy();
}

uint64_t getLastFrame() const override
{
return fLastFrame;
}

protected:
// -------------------------------------------------------------------
// Plugin parameter calls
@@ -139,7 +131,6 @@ protected:

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

void setCustomData(const char* const key, const char* const value) override
@@ -166,8 +157,7 @@ protected:

if (! fDoProcess)
{
//carla_stderr("P: no process");
fLastFrame = timePos->frame;
// carla_stderr("P: no process");
carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames);
return;
@@ -176,23 +166,26 @@ protected:
// not playing
if (! timePos->playing)
{
//carla_stderr("P: not playing");
if (timePos->frame == 0 && fLastFrame > 0)
fThread.setNeedsRead();
// carla_stderr("P: not playing");
if (timePos->frame == 0 && fWasPlayingBefore)
fThread.setNeedsRead(timePos->frame);

fLastFrame = timePos->frame;
carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames);
fWasPlayingBefore = false;
return;
}
else
{
fWasPlayingBefore = true;
}

// out of reach
if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !fLoopMode)
{
if (timePos->frame < fPool.startFrame)
fThread.setNeedsRead();
fThread.setNeedsRead(timePos->frame);

fLastFrame = timePos->frame;
carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames);

@@ -251,15 +244,7 @@ protected:
}
else
{
// NOTE: timePos->frame is always >= fPool.startFrame
const uint64_t poolStartFrame = timePos->frame - fThread.getPoolStartFrame();

if (fThread.tryPutData(fPool, poolStartFrame, frames))
{
carla_copyFloats(out1, fPool.buffer[0]+poolStartFrame, frames);
carla_copyFloats(out2, fPool.buffer[1]+poolStartFrame, frames);
}
else
if (! fThread.tryPutData(out1, out2, timePos->frame, frames))
{
carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames);
@@ -277,11 +262,10 @@ protected:
if (! fInlineDisplay.pending)
{
fInlineDisplay.pending = true;
// FIXME this is not supposed to be here, but in some idle callback
hostQueueDrawInlineDisplay();
}
#endif

fLastFrame = timePos->frame;
}

// -------------------------------------------------------------------
@@ -428,8 +412,8 @@ protected:
private:
bool fLoopMode;
bool fDoProcess;
bool fWasPlayingBefore;

volatile uint64_t fLastFrame;
uint32_t fMaxFrame;

AudioFilePool fPool;


+ 6
- 24
source/native-plugins/midi-file.cpp View File

@@ -205,35 +205,17 @@ private:
CARLA_SAFE_ASSERT_CONTINUE(midiEventHolder != nullptr);

const MidiMessage& midiMessage(midiEventHolder->message);
//const double time(track->getEventTime(i)*sampleRate);
const int dataSize(midiMessage.getRawDataSize());

const int dataSize = midiMessage.getRawDataSize();
if (dataSize <= 0 || dataSize > MAX_EVENT_DATA_SIZE)
continue;
if (midiMessage.isActiveSense())
continue;
if (midiMessage.isMetaEvent())
continue;
if (midiMessage.isMidiStart())
continue;
if (midiMessage.isMidiContinue())
continue;
if (midiMessage.isMidiStop())
continue;
if (midiMessage.isMidiClock())
continue;
if (midiMessage.isSongPositionPointer())
continue;
if (midiMessage.isQuarterFrame())
continue;
if (midiMessage.isFullFrame())
continue;
if (midiMessage.isMidiMachineControlMessage())
continue;
if (midiMessage.isSysEx())

const uint8_t* const data = midiMessage.getRawData();
if (! MIDI_IS_CHANNEL_MESSAGE(data[0]))
continue;

const double time(midiMessage.getTimeStamp()*sampleRate);
const double time = midiMessage.getTimeStamp() * sampleRate;
// const double time = track->getEventTime(i) * sampleRate;
CARLA_SAFE_ASSERT_CONTINUE(time >= 0.0);

fMidiOut.addRaw(static_cast<uint64_t>(time), midiMessage.getRawData(), static_cast<uint8_t>(dataSize));


+ 5
- 0
source/utils/CarlaMutex.hpp View File

@@ -325,6 +325,11 @@ public:
return !fLocked;
}

bool tryAgain() const noexcept
{
return fMutex.tryLock();
}

private:
const Mutex& fMutex;
const bool fLocked;


Loading…
Cancel
Save