Browse Source

send audiofile preview as lv2 vector

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.3.0-RC1
falkTX 4 years ago
parent
commit
8afab56952
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 151 additions and 41 deletions
  1. +2
    -1
      source/includes/CarlaNative.h
  2. +7
    -0
      source/includes/CarlaNative.hpp
  3. +28
    -6
      source/native-plugins/audio-base.hpp
  4. +13
    -4
      source/native-plugins/audio-file.cpp
  5. +98
    -30
      source/plugin/carla-lv2.cpp
  6. +3
    -0
      source/utils/CarlaLv2Utils.hpp

+ 2
- 1
source/includes/CarlaNative.h View File

@@ -117,7 +117,8 @@ typedef enum {
NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER = 10, /** uses index, value as bool */
NATIVE_HOST_OPCODE_REQUEST_IDLE = 11, /** nothing */
NATIVE_HOST_OPCODE_GET_FILE_PATH = 12, /** uses ptr as string for file type */
NATIVE_HOST_OPCODE_UI_RESIZE = 13 /** uses index and value */
NATIVE_HOST_OPCODE_UI_RESIZE = 13, /** uses index and value */
NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA = 14 /** uses index as type, value as size, and ptr */
} NativeHostDispatcherOpcode;

/* ------------------------------------------------------------------------------------------------------------


+ 7
- 0
source/includes/CarlaNative.hpp View File

@@ -250,6 +250,13 @@ protected:
0.0f);
}

void hostSendPreviewBufferData(const char type, const uint32_t size, const void* const buffer)
{
CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);

pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA, type, size, (void*)buffer, 0.0f);
}

// -------------------------------------------------------------------
// Plugin parameter calls



+ 28
- 6
source/native-plugins/audio-base.hpp View File

@@ -271,7 +271,8 @@ public:
fNeedsRead = true;
}

bool loadFilename(const char* const filename, const uint32_t sampleRate)
bool loadFilename(const char* const filename, const uint32_t sampleRate,
const uint32_t previewDataSize, float* previewData)
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);

@@ -329,6 +330,15 @@ public:
readEntireFileIntoPool(needsResample);
ad_close(fFilePtr);
fFilePtr = nullptr;

const float fileNumFramesF = static_cast<float>(fileNumFrames);
const float previewDataSizeF = static_cast<float>(previewDataSize);
for (uint i=0; i<previewDataSize; ++i)
{
const float stepF = static_cast<float>(i)/previewDataSizeF * fileNumFramesF;
const uint step = carla_fixedValue(0U, fileNumFrames-1U, static_cast<uint>(stepF + 0.5f));
previewData[i] = fPool.buffer[0][step];
}
}
else
{
@@ -337,6 +347,8 @@ public:
const uint pollTempSize = poolNumFrames * fFileNfo.channels;
uint resampleTempSize = 0;

carla_zeroFloats(previewData, 300);

fPool.create(poolNumFrames, true);

try {
@@ -392,14 +404,24 @@ public:
}
}

void putAllData(AudioFilePool& pool)
void putAndSwapAllData(AudioFilePool& pool)
{
const water::GenericScopedLock<water::SpinLock> gsl(fPool.mutex);
CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,);
const water::GenericScopedLock<water::SpinLock> gsl1(fPool.mutex);
const water::GenericScopedLock<water::SpinLock> gsl2(pool.mutex);
CARLA_SAFE_ASSERT_RETURN(fPool.numFrames != 0,);
CARLA_SAFE_ASSERT_RETURN(pool.numFrames == 0,);
CARLA_SAFE_ASSERT_RETURN(fPool.tmpbuf[0] == nullptr,);
CARLA_SAFE_ASSERT_RETURN(pool.tmpbuf[0] == nullptr,);

pool.startFrame = fPool.startFrame;
carla_copyFloats(pool.buffer[0], fPool.buffer[0], fPool.numFrames);
carla_copyFloats(pool.buffer[1], fPool.buffer[1], fPool.numFrames);
pool.numFrames = fPool.numFrames;
pool.buffer[0] = fPool.buffer[0];
pool.buffer[1] = fPool.buffer[1];

fPool.startFrame = 0;
fPool.numFrames = 0;
fPool.buffer[0] = nullptr;
fPool.buffer[1] = nullptr;
}

bool tryPutData(float* const out1,


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

@@ -75,7 +75,8 @@ public:
fMaxFrame(0),
fPool(),
fReader(),
fPrograms(hostGetFilePath("audio"), audiofilesWildcard)
fPrograms(hostGetFilePath("audio"), audiofilesWildcard),
fPreviewData()
#ifndef __MOD_DEVICES__
, fInlineDisplay()
#endif
@@ -551,6 +552,7 @@ private:
AudioFileReader fReader;

NativeMidiPrograms fPrograms;
float fPreviewData[300];

#ifndef __MOD_DEVICES__
struct InlineDisplay : NativeInlineDisplayImageSurfaceCompat {
@@ -603,17 +605,24 @@ private:
return;
}

if (fReader.loadFilename(filename, static_cast<uint32_t>(getSampleRate())))
const uint32_t previewDataSize = sizeof(fPreviewData)/sizeof(float);

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

if (fReader.isEntireFileLoaded())
fReader.putAllData(fPool);
{
fReader.putAndSwapAllData(fPool);
}
else
{
fPool.create(fReader.getPoolNumFrames(), false);
fReader.readPoll();
}

fDoProcess = true;
hostSendPreviewBufferData('f', previewDataSize, fPreviewData);
}
else
{


+ 98
- 30
source/plugin/carla-lv2.cpp View File

@@ -34,6 +34,19 @@ void Lv2PluginBaseClass<NativeTimeInfo>::clearTimeData() noexcept
carla_zeroStruct(fTimeInfo);
}

struct PreviewData {
char type;
uint32_t size;
const void* buffer;
bool shouldSend;

PreviewData()
: type(0),
size(0),
buffer(nullptr),
shouldSend(false) {}
};

// --------------------------------------------------------------------------------------------------------------------
// Carla Internal Plugin API exposed as LV2 plugin

@@ -58,6 +71,7 @@ public:
fMidiEventCount(0),
fLastProjectPath(),
fLoadedFile(),
fPreviewData(),
fNeedsNotifyFileChanged(false),
fPluginNeedsIdle(0),
fWorkerUISignal(0)
@@ -298,6 +312,8 @@ public:
{
if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE)
fNeedsNotifyFileChanged = true;
if (fPreviewData.buffer != nullptr)
fPreviewData.shouldSend = true;
}
continue;
}
@@ -328,51 +344,88 @@ public:
}
}

if (fNeedsNotifyFileChanged)
if (fNeedsNotifyFileChanged || fPreviewData.shouldSend)
{
fNeedsNotifyFileChanged = false;

uint8_t atomBuf[4096];
LV2_Atom_Forge atomForge = fAtomForge;
lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));

LV2_Atom_Forge_Frame forgeFrame;
lv2_atom_forge_object(&atomForge, &forgeFrame, 0, fURIs.patchSet);
const int numEvents = fNeedsNotifyFileChanged && fPreviewData.shouldSend ? 2 : 1;

if (fNeedsNotifyFileChanged)
{
fNeedsNotifyFileChanged = false;

LV2_Atom_Forge_Frame forgeFrame;
lv2_atom_forge_object(&atomForge, &forgeFrame, 0, fURIs.patchSet);

lv2_atom_forge_key(&atomForge, fURIs.patchProperty);

lv2_atom_forge_key(&atomForge, fURIs.patchProperty);
/* */ if (std::strcmp(fDescriptor->label, "audiofile") == 0) {
lv2_atom_forge_urid(&atomForge, fURIs.carlaFileAudio);
} else if (std::strcmp(fDescriptor->label, "midifile") == 0) {
lv2_atom_forge_urid(&atomForge, fURIs.carlaFileMIDI);
} else {
lv2_atom_forge_urid(&atomForge, fURIs.carlaFile);
}

lv2_atom_forge_key(&atomForge, fURIs.patchValue);
lv2_atom_forge_path(&atomForge,
fLoadedFile.buffer(),
static_cast<uint32_t>(fLoadedFile.length()+1));

/* */ if (std::strcmp(fDescriptor->label, "audiofile") == 0) {
lv2_atom_forge_urid(&atomForge, fURIs.carlaFileAudio);
} else if (std::strcmp(fDescriptor->label, "midifile") == 0) {
lv2_atom_forge_urid(&atomForge, fURIs.carlaFileMIDI);
} else {
lv2_atom_forge_urid(&atomForge, fURIs.carlaFile);
lv2_atom_forge_pop(&atomForge, &forgeFrame);
}

lv2_atom_forge_key(&atomForge, fURIs.patchValue);
lv2_atom_forge_path(&atomForge,
fLoadedFile.buffer(),
static_cast<uint32_t>(fLoadedFile.length()+1));
if (fPreviewData.shouldSend)
{
const char ptype = fPreviewData.type;
const uint32_t psize = fPreviewData.size;
const void* const pbuffer = fPreviewData.buffer;
fPreviewData.shouldSend = false;

LV2_Atom_Forge_Frame forgeFrame;
lv2_atom_forge_object(&atomForge, &forgeFrame, 0, fURIs.patchSet);

lv2_atom_forge_pop(&atomForge, &forgeFrame);
lv2_atom_forge_key(&atomForge, fURIs.patchProperty);
lv2_atom_forge_urid(&atomForge, fURIs.carlaPreview);

lv2_atom_forge_key(&atomForge, fURIs.patchValue);

switch (ptype)
{
case 'f':
lv2_atom_forge_vector(&atomForge, sizeof(float), fURIs.atomFloat, psize, pbuffer);
break;
default:
carla_stderr2("Preview data buffer has wrong type '%c' (and size %u)", ptype, psize);
break;
}

LV2_Atom* const atom = (LV2_Atom*)atomBuf;
lv2_atom_forge_pop(&atomForge, &forgeFrame);
}

LV2_Atom* atom = (LV2_Atom*)atomBuf;
LV2_Atom_Sequence* const seq = fPorts.eventsOut[0];
Ports::EventsOutData& mData(fPorts.eventsOutData[0]);

if (sizeof(LV2_Atom_Event) + atom->size <= mData.capacity - mData.offset)
for (int i=0; i<numEvents; ++i)
{
LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq) + mData.offset);
if (sizeof(LV2_Atom_Event) + atom->size <= mData.capacity - mData.offset)
{
LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq) + mData.offset);

aev->time.frames = 0;
aev->body.size = atom->size;
aev->body.type = atom->type;
std::memcpy(LV2_ATOM_BODY(&aev->body), atom + 1, atom->size);

aev->time.frames = 0;
aev->body.size = atom->size;
aev->body.type = atom->type;
std::memcpy(LV2_ATOM_BODY(&aev->body), atom + 1, atom->size);
const uint32_t size = lv2_atom_pad_size(static_cast<uint32_t>(sizeof(LV2_Atom_Event) + atom->size));
mData.offset += size;
seq->atom.size += size;
}

const uint32_t size = lv2_atom_pad_size(static_cast<uint32_t>(sizeof(LV2_Atom_Event) + atom->size));
mData.offset += size;
seq->atom.size += size;
atom = (LV2_Atom*)(atomBuf + lv2_atom_total_size(atom));
}
}
}
@@ -940,6 +993,14 @@ protected:
// nothing here
}

void handlePreviewBufferData(const char type, const uint32_t size, const void* const buffer) noexcept
{
fPreviewData.type = type;
fPreviewData.size = size;
fPreviewData.buffer = buffer;
fPreviewData.shouldSend = true;
}

void handleUiCustomDataChanged(const char* const key, const char* const value) const
{
carla_stdout("TODO: handleUiCustomDataChanged %s %s", key, value);
@@ -1039,14 +1100,20 @@ protected:
CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
handleUiResize(static_cast<uint32_t>(index), static_cast<uint32_t>(value));
break;

case NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA:
CARLA_SAFE_ASSERT_RETURN(index != 0, 0);
CARLA_SAFE_ASSERT_RETURN(index >= 'a', 0);
CARLA_SAFE_ASSERT_RETURN(index <= 'z', 0);
CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
handlePreviewBufferData(static_cast<char>(index), static_cast<uint32_t>(value), (const void*)ptr);
break;
}

return ret;

// unused for now
(void)index;
(void)value;
(void)ptr;
(void)opt;
}

@@ -1084,6 +1151,7 @@ private:

CarlaString fLastProjectPath;
CarlaString fLoadedFile;
PreviewData fPreviewData;
volatile bool fNeedsNotifyFileChanged;
volatile int fPluginNeedsIdle;



+ 3
- 0
source/utils/CarlaLv2Utils.hpp View File

@@ -1522,6 +1522,7 @@ protected:
LV2_URID carlaFile;
LV2_URID carlaFileAudio;
LV2_URID carlaFileMIDI;
LV2_URID carlaPreview;
LV2_URID midiEvent;
LV2_URID patchProperty;
LV2_URID patchGet;
@@ -1553,6 +1554,7 @@ protected:
carlaFile(0),
carlaFileAudio(0),
carlaFileMIDI(0),
carlaPreview(0),
midiEvent(0),
patchProperty(0),
patchGet(0),
@@ -1585,6 +1587,7 @@ protected:
carlaFile = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file");
carlaFileAudio = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file/audio");
carlaFileMIDI = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file/midi");
carlaPreview = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/preview");
midiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
patchProperty = uridMap->map(uridMap->handle, LV2_PATCH__property);
patchGet = uridMap->map(uridMap->handle, LV2_PATCH__Get);


Loading…
Cancel
Save