Browse Source

Working loop-mode for audio-file plugin, turn it on by default

tags/v1.9.11
falkTX 6 years ago
parent
commit
3248f8019d
3 changed files with 147 additions and 86 deletions
  1. +23
    -0
      source/native-plugins/_data.base.cpp
  2. +113
    -79
      source/native-plugins/audio-base.hpp
  3. +11
    -7
      source/native-plugins/audio-file.cpp

+ 23
- 0
source/native-plugins/_data.base.cpp View File

@@ -164,6 +164,29 @@ static const NativePluginDescriptor sNativePluginDescriptors[] = {
DESCFUNCS
},

// --------------------------------------------------------------------------------------------------------------------
// Audio file

{
/* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
|NATIVE_PLUGIN_HAS_UI
|NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE
|NATIVE_PLUGIN_USES_TIME),
/* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING,
/* audioIns */ 0,
/* audioOuts */ 2,
/* midiIns */ 0,
/* midiOuts */ 0,
/* paramIns */ 1,
/* paramOuts */ 0,
/* name */ "Audio File",
/* label */ "audiofile",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
DESCFUNCS
},

// --------------------------------------------------------------------------------------------------------------------
// MIDI sequencer



+ 113
- 79
source/native-plugins/audio-base.hpp View File

@@ -1,6 +1,6 @@
/*
* Carla Native Plugins
* Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -64,7 +64,7 @@ struct AudioFilePool {
CARLA_ASSERT(startFrame == 0);
CARLA_ASSERT(size == 0);

size = srate * 5;
size = srate * 8;
sampleRate = srate;

buffer[0] = new float[size];
@@ -118,9 +118,13 @@ public:
AudioFileThread(AbstractAudioPlayer* const player, const double sampleRate)
: CarlaThread("AudioFileThread"),
kPlayer(player),
fLoopingMode(true),
fNeedsRead(false),
fQuitNow(true),
fFilePtr(nullptr)
fFilePtr(nullptr),
fMaxPlayerFrame(0),
fPollTempData(nullptr),
fPollTempSize(0)
{
CARLA_ASSERT(kPlayer != nullptr);

@@ -143,7 +147,17 @@ public:
CARLA_ASSERT(! isThreadRunning());

if (fFilePtr != nullptr)
{
ad_close(fFilePtr);
fFilePtr = nullptr;
}

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

fPool.destroy();
}
@@ -166,20 +180,25 @@ public:
fPool.reset();
}

uint32_t getMaxFrame() const
uint32_t getMaxFrame() const noexcept
{
return fMaxPlayerFrame;
}

void setLoopingMode(const bool on) noexcept
{
return fFileNfo.frames > 0 ? fFileNfo.frames : 0;
fLoopingMode = on;
}

void setNeedsRead()
void setNeedsRead() noexcept
{
fNeedsRead = true;
}

bool loadFilename(const char* const filename)
{
CARLA_ASSERT(! isThreadRunning());
CARLA_ASSERT(filename != nullptr);
CARLA_SAFE_ASSERT_RETURN(! isThreadRunning(), false);
CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);

fPool.startFrame = 0;

@@ -189,6 +208,13 @@ public:
ad_close(fFilePtr);
fFilePtr = nullptr;
}
if (fPollTempData != nullptr)
{
delete[] fPollTempData;
fPollTempData = nullptr;
fPollTempSize = 0;
fMaxPlayerFrame = 0;
}

ad_clear_nfo(&fFileNfo);

@@ -200,16 +226,30 @@ public:

ad_dump_nfo(99, &fFileNfo);

if (fFileNfo.frames == 0)
carla_stderr("L: filename \"%s\" has 0 frames", filename);

// Fix for misinformation using libsndfile
if (fFileNfo.frames % fFileNfo.channels)
--fFileNfo.frames;

if (fFileNfo.frames <= 0)
carla_stderr("L: filename \"%s\" has 0 frames", filename);

if ((fFileNfo.channels == 1 || fFileNfo.channels == 2) && fFileNfo.frames > 0)
{
// valid
const size_t pollTempSize = std::min(static_cast<uint>(fFileNfo.frames),
fPool.size * fFileNfo.channels);

try {
fPollTempData = new float[pollTempSize];
} catch (...) {
ad_close(fFilePtr);
fFilePtr = nullptr;
return false;
}

fMaxPlayerFrame = fFileNfo.frames/fFileNfo.channels;
fPollTempSize = pollTempSize;

readPoll();
return true;
}
@@ -255,24 +295,12 @@ public:

if (lastFrame >= maxFrame)
{
#if 0
if (false)
//if (handlePtr->loopMode)
if (fLoopingMode)
{
carla_stderr("R: DEBUG read loop, lastFrame:%i, maxFrame:%i", lastFrame, maxFrame);

if (maxFrame >= static_cast<int64_t>(fPool.size))
{
readFrame %= maxFrame;
}
else
{
readFrame = 0;
lastFrame -= lastFrame % maxFrame;
}
carla_debug("R: transport out of bounds for loop");
readFrame %= fMaxPlayerFrame;
}
else
#endif
{
carla_stderr("R: transport out of bounds");
fNeedsRead = false;
@@ -281,10 +309,7 @@ public:
}

// temp data buffer
const size_t tmpSize = fPool.size * fFileNfo.channels;

float tmpData[tmpSize];
carla_zeroFloats(tmpData, tmpSize);
carla_zeroFloats(fPollTempData, fPollTempSize);

{
carla_debug("R: poll data - reading at %li:%02li", readFrame/fPool.sampleRate/60, (readFrame/fPool.sampleRate) % 60);
@@ -292,71 +317,73 @@ public:
ad_seek(fFilePtr, readFrame);
size_t i = 0;
ssize_t j = 0;
ssize_t rv = ad_read(fFilePtr, tmpData, tmpSize);
ssize_t rv = ad_read(fFilePtr, fPollTempData, fPollTempSize);

if (rv < 0)
{
carla_stderr("R: ad_read failed");
fNeedsRead = false;
return;
}

// see if we can read more
if (readFrame + rv >= static_cast<ssize_t>(fFileNfo.frames) && static_cast<size_t>(rv) < fPollTempSize)
{
carla_debug("R: from start");
ad_seek(fFilePtr, 0);
rv += ad_read(fFilePtr, fPollTempData+rv, fPollTempSize-rv);
}

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

for (; i < fPool.size && j < rv; ++j)
{
if (fFileNfo.channels == 1)
{
fPool.buffer[0][i] = tmpData[j];
fPool.buffer[1][i] = tmpData[j];
i++;
}
else
do {
for (; i < fPool.size && j < rv; ++j)
{
if (j % 2 == 0)
if (fFileNfo.channels == 1)
{
fPool.buffer[0][i] = tmpData[j];
}
else
{
fPool.buffer[1][i] = tmpData[j];
fPool.buffer[0][i] = fPollTempData[j];
fPool.buffer[1][i] = fPollTempData[j];
i++;
}
}
}

#if 0
if (false)
//if (handlePtr->loopMode && i < fPool.size)
{
while (i < fPool.size)
{
for (j=0; i < fPool.size && j < rv; ++j)
else
{
if (fFileNfo.channels == 1)
if (j % 2 == 0)
{
fPool.buffer[0][i] = tmpData[j];
fPool.buffer[1][i] = tmpData[j];
i++;
fPool.buffer[0][i] = fPollTempData[j];
}
else
{
if (j % 2 == 0)
{
fPool.buffer[0][i] = tmpData[j];
}
else
{
fPool.buffer[1][i] = tmpData[j];
i++;
}
fPool.buffer[1][i] = fPollTempData[j];
i++;
}
}
}
}
else
#endif
{
for (; i < fPool.size; ++i)

if (i >= fPool.size)
break;

if (rv == fFileNfo.frames)
{
fPool.buffer[0][i] = 0.0f;
fPool.buffer[1][i] = 0.0f;
// full file read
j = 0;
carla_debug("R: full file was read, filling buffers again");
}
}
else
{
carla_debug("read break, not enough space");

// FIXME use carla_zeroFloats
for (; i < fPool.size; ++i)
{
fPool.buffer[0][i] = 0.0f;
fPool.buffer[1][i] = 0.0f;
}

break;
}

} while (i < fPool.size);

fPool.startFrame = lastFrame;
}
@@ -369,9 +396,10 @@ protected:
{
while (! fQuitNow)
{
const uint32_t lastFrame(kPlayer->getLastFrame());
const uint32_t lastFrame = kPlayer->getLastFrame();
const uint32_t loopedFrame = fLoopingMode ? lastFrame % fMaxPlayerFrame : lastFrame;

if (fNeedsRead || lastFrame < fPool.startFrame || (lastFrame - fPool.startFrame >= fPool.size*3/4 && lastFrame < fFileNfo.frames))
if (fNeedsRead || lastFrame < fPool.startFrame || (lastFrame - fPool.startFrame >= fPool.size*3/4 && loopedFrame < fMaxPlayerFrame))
readPoll();
else
carla_msleep(50);
@@ -381,12 +409,18 @@ protected:
private:
AbstractAudioPlayer* const kPlayer;

bool fLoopingMode;
bool fNeedsRead;
bool fQuitNow;

void* fFilePtr;
ADInfo fFileNfo;

uint32_t fMaxPlayerFrame;

float* fPollTempData;
size_t fPollTempSize;

AudioFilePool fPool;
CarlaMutex fMutex;
};


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

@@ -1,6 +1,6 @@
/*
* Carla Native Plugins
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -29,7 +29,7 @@ public:
AudioFilePlugin(const NativeHostDescriptor* const host)
: NativePluginClass(host),
AbstractAudioPlayer(),
fLoopMode(false),
fLoopMode(true),
fDoProcess(false),
fLastFrame(0),
fMaxFrame(0),
@@ -55,7 +55,7 @@ protected:

uint32_t getParameterCount() const override
{
return 0; // TODO - loopMode
return 1;
}

const NativeParameter* getParameterInfo(const uint32_t index) const override
@@ -67,7 +67,7 @@ protected:

param.name = "Loop Mode";
param.unit = nullptr;
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_BOOLEAN);
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMABLE|NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_BOOLEAN);
param.ranges.def = 1.0f;
param.ranges.min = 0.0f;
param.ranges.max = 1.0f;
@@ -102,6 +102,7 @@ protected:
return;

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

@@ -149,9 +150,12 @@ protected:
fThread.tryPutData(fPool);

// out of reach
if (timePos->frame + frames < fPool.startFrame || timePos->frame >= fMaxFrame) /*&& ! loopMode)*/
if (timePos->frame + frames < fPool.startFrame || (timePos->frame >= fMaxFrame && !fLoopMode))
{
//carla_stderr("P: out of reach");
if (fLoopMode) {
carla_stderr("P: out of reach");
}

fLastFrame = timePos->frame;

if (timePos->frame + frames < fPool.startFrame)
@@ -254,7 +258,7 @@ static const NativePluginDescriptor audiofileDesc = {
/* audioOuts */ 2,
/* midiIns */ 0,
/* midiOuts */ 0,
/* paramIns */ 0, // TODO - loopMode
/* paramIns */ 1,
/* paramOuts */ 0,
/* name */ "Audio File",
/* label */ "audiofile",


Loading…
Cancel
Save