Browse Source

Multi-file support in audiofile; Fix Native+DSSI reloadPrograms()

tags/1.9.4
falkTX 12 years ago
parent
commit
8c35597a23
3 changed files with 251 additions and 71 deletions
  1. +217
    -57
      source/backend/native/audiofile.c
  2. +12
    -6
      source/backend/plugin/DssiPlugin.cpp
  3. +22
    -8
      source/backend/plugin/NativePlugin.cpp

+ 217
- 57
source/backend/native/audiofile.c View File

@@ -25,17 +25,31 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>


#define PROGRAM_COUNT 16

#ifdef _WIN32
# define OS_SEP '\\'
#else
# define OS_SEP '/'
#endif

typedef struct adinfo ADInfo; typedef struct adinfo ADInfo;
typedef pthread_mutex_t Mutex; typedef pthread_mutex_t Mutex;
typedef pthread_t Thread; typedef pthread_t Thread;


typedef struct _AudioFilePool { typedef struct _AudioFilePool {
float* buffer[2];
float* buffer[2];
uint32_t startFrame; uint32_t startFrame;
uint32_t size; uint32_t size;


} AudioFilePool; } AudioFilePool;


typedef struct _AudioFilePrograms {
uint32_t current;
const char* fullNames[PROGRAM_COUNT];
const char* shortNames[PROGRAM_COUNT];
} AudioFilePrograms;

typedef struct _AudioFileInstance { typedef struct _AudioFileInstance {
HostDescriptor* host; HostDescriptor* host;


@@ -45,7 +59,9 @@ typedef struct _AudioFileInstance {
uint32_t lastFrame; uint32_t lastFrame;
uint32_t maxFrame; uint32_t maxFrame;
AudioFilePool pool; AudioFilePool pool;
AudioFilePrograms programs;


bool loopMode;
bool needsRead; bool needsRead;
bool doProcess; bool doProcess;
bool doQuit; bool doQuit;
@@ -57,10 +73,6 @@ typedef struct _AudioFileInstance {


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


static bool gADInitiated = false;

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

void zeroFloat(float* data, unsigned size) void zeroFloat(float* data, unsigned size)
{ {
for (unsigned i=0; i < size; ++i) for (unsigned i=0; i < size; ++i)
@@ -76,11 +88,11 @@ void audiofile_read_poll(AudioFileInstance* const handlePtr)
return; return;
} }


int64_t lastFrame = handlePtr->lastFrame;
const int64_t lastFrame = handlePtr->lastFrame;


if (lastFrame >= handlePtr->maxFrame) if (lastFrame >= handlePtr->maxFrame)
{ {
//fprintf(stderr, "R: transport out of bounds\n");
fprintf(stderr, "R: transport out of bounds\n");
handlePtr->needsRead = false; handlePtr->needsRead = false;
return; return;
} }
@@ -96,47 +108,43 @@ void audiofile_read_poll(AudioFileInstance* const handlePtr)


ad_seek(handlePtr->filePtr, lastFrame); ad_seek(handlePtr->filePtr, lastFrame);
ssize_t i, j, rv = ad_read(handlePtr->filePtr, tmpData, tmpSize); ssize_t i, j, rv = ad_read(handlePtr->filePtr, tmpData, tmpSize);
i = j = 0;


{
// lock, and put data asap
pthread_mutex_lock(&handlePtr->mutex);
// lock, and put data asap
pthread_mutex_lock(&handlePtr->mutex);


//zeroFloat(handlePtr->pool.buffer[0], handlePtr->pool.size);
//zeroFloat(handlePtr->pool.buffer[1], handlePtr->pool.size);

for (i=0, j=0; i < handlePtr->pool.size && j < rv; j++)
for (; i < handlePtr->pool.size && j < rv; j++)
{
if (handlePtr->fileNfo.channels == 1)
{
handlePtr->pool.buffer[0][i] = tmpData[j];
handlePtr->pool.buffer[1][i] = tmpData[j];
i++;
}
else
{ {
if (handlePtr->fileNfo.channels == 1)
if (j % 2 == 0)
{ {
handlePtr->pool.buffer[0][i] = tmpData[j]; handlePtr->pool.buffer[0][i] = tmpData[j];
handlePtr->pool.buffer[1][i] = tmpData[j];
i++;
} }
else else
{ {
if (j % 2 == 0)
{
handlePtr->pool.buffer[0][i] = tmpData[j];
}
else
{
handlePtr->pool.buffer[1][i] = tmpData[j];
i++;
}
handlePtr->pool.buffer[1][i] = tmpData[j];
i++;
} }
} }
}


for (; i < handlePtr->pool.size; i++)
{
handlePtr->pool.buffer[0][i] = 0.0f;
handlePtr->pool.buffer[1][i] = 0.0f;
}
for (; i < handlePtr->pool.size; i++)
{
handlePtr->pool.buffer[0][i] = 0.0f;
handlePtr->pool.buffer[1][i] = 0.0f;
}


handlePtr->pool.startFrame = lastFrame;
handlePtr->pool.startFrame = lastFrame;


// done
pthread_mutex_unlock(&handlePtr->mutex);
}
// done
pthread_mutex_unlock(&handlePtr->mutex);
} }


handlePtr->needsRead = false; handlePtr->needsRead = false;
@@ -157,12 +165,15 @@ void audiofile_load_filename(AudioFileInstance* const handlePtr, const char* con
} }
ad_clear_nfo(&handlePtr->fileNfo); ad_clear_nfo(&handlePtr->fileNfo);


if (filename == NULL)
return;

// open new // open new
handlePtr->filePtr = ad_open(filename, &handlePtr->fileNfo); handlePtr->filePtr = ad_open(filename, &handlePtr->fileNfo);


if (handlePtr->filePtr != NULL) if (handlePtr->filePtr != NULL)
{ {
ad_dump_nfo(1, &handlePtr->fileNfo);
ad_dump_nfo(99, &handlePtr->fileNfo);


if (handlePtr->fileNfo.channels == 1 || handlePtr->fileNfo.channels == 2) if (handlePtr->fileNfo.channels == 1 || handlePtr->fileNfo.channels == 2)
{ {
@@ -191,11 +202,15 @@ static void audiofile_thread_idle(void* ptr)
usleep(50*1000); usleep(50*1000);
} }


pthread_exit(0);
pthread_exit(NULL);
} }


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


static bool gADInitiated = false;

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

static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDescriptor* host) static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDescriptor* host)
{ {
AudioFileInstance* const handlePtr = (AudioFileInstance*)malloc(sizeof(AudioFileInstance)); AudioFileInstance* const handlePtr = (AudioFileInstance*)malloc(sizeof(AudioFileInstance));
@@ -218,7 +233,9 @@ static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDe
handlePtr->pool.buffer[1] = NULL; handlePtr->pool.buffer[1] = NULL;
handlePtr->pool.startFrame = 0; handlePtr->pool.startFrame = 0;
handlePtr->pool.size = 0; handlePtr->pool.size = 0;
handlePtr->programs.current = 0;


handlePtr->loopMode = true;
handlePtr->needsRead = false; handlePtr->needsRead = false;
handlePtr->doProcess = false; handlePtr->doProcess = false;
handlePtr->doQuit = false; handlePtr->doQuit = false;
@@ -226,14 +243,26 @@ static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDe
ad_clear_nfo(&handlePtr->fileNfo); ad_clear_nfo(&handlePtr->fileNfo);
pthread_mutex_init(&handlePtr->mutex, NULL); pthread_mutex_init(&handlePtr->mutex, NULL);


for (uint32_t i=0; i < PROGRAM_COUNT; i++)
{
handlePtr->programs.fullNames[i] = NULL;
handlePtr->programs.shortNames[i] = NULL;
}

// create audio pool // create audio pool
handlePtr->pool.size = host->get_sample_rate(host->handle) * 6; // 6 secs
handlePtr->pool.size = host->get_sample_rate(host->handle) * 6; // 6 secs


handlePtr->pool.buffer[0] = (float*)malloc(sizeof(float) * handlePtr->pool.size); handlePtr->pool.buffer[0] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
handlePtr->pool.buffer[1] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
if (handlePtr->pool.buffer[0] == NULL)
{
free(handlePtr);
return NULL;
}


if (handlePtr->pool.buffer[0] == NULL || handlePtr->pool.buffer[1] == NULL)
handlePtr->pool.buffer[1] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
if (handlePtr->pool.buffer[1] == NULL)
{ {
free(handlePtr->pool.buffer[0]);
free(handlePtr); free(handlePtr);
return NULL; return NULL;
} }
@@ -243,12 +272,6 @@ static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDe


pthread_create(&handlePtr->thread, NULL, (void*)&audiofile_thread_idle, handlePtr); pthread_create(&handlePtr->thread, NULL, (void*)&audiofile_thread_idle, handlePtr);


// load file, TESTING
// wait for jack processing to end
handlePtr->doProcess = false;
pthread_mutex_lock(&handlePtr->mutex);
pthread_mutex_unlock(&handlePtr->mutex);

return handlePtr; return handlePtr;


// unused // unused
@@ -277,14 +300,145 @@ static void audiofile_cleanup(PluginHandle handle)
if (handlePtr->pool.buffer[1] != NULL) if (handlePtr->pool.buffer[1] != NULL)
free(handlePtr->pool.buffer[1]); free(handlePtr->pool.buffer[1]);


for (uint32_t i=0; i < PROGRAM_COUNT; i++)
{
if (handlePtr->programs.fullNames[i] != NULL)
free((void*)handlePtr->programs.fullNames[i]);
if (handlePtr->programs.shortNames[i] != NULL)
free((void*)handlePtr->programs.shortNames[i]);
}

free(handlePtr); free(handlePtr);
} }


static uint32_t audiofile_get_parameter_count(PluginHandle handle)
{
return 1;

// unused
(void)handle;
}

static const Parameter* audiofile_get_parameter_info(PluginHandle handle, uint32_t index)
{
if (index != 0)
return NULL;

static Parameter param;

param.name = "Loop Mode";
param.unit = NULL;
param.hints = PARAMETER_IS_ENABLED|PARAMETER_IS_BOOLEAN;
param.ranges.def = 1.0f;
param.ranges.min = 0.0f;
param.ranges.max = 1.0f;
param.ranges.step = 1.0f;
param.ranges.stepSmall = 1.0f;
param.ranges.stepLarge = 1.0f;
param.scalePointCount = 0;
param.scalePoints = NULL;

return &param;

// unused
(void)handle;
}

static float audiofile_get_parameter_value(PluginHandle handle, uint32_t index)
{
AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;

if (index != 0)
return 0.0f;

return handlePtr->loopMode ? 1.0f : 0.0f;

// unused
(void)handle;
}

static uint32_t audiofile_get_program_count(PluginHandle handle)
{
return PROGRAM_COUNT;
}

const MidiProgram* audiofile_get_program_info(PluginHandle handle, uint32_t index)
{
AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;

if (index >= PROGRAM_COUNT)
return NULL;

static MidiProgram midiProgram;

midiProgram.bank = 0;
midiProgram.program = index;
midiProgram.name = handlePtr->programs.shortNames[index];

if (midiProgram.name == NULL)
midiProgram.name = "";

return &midiProgram;
}

static void audiofile_set_parameter_value(PluginHandle handle, uint32_t index, float value)
{
AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;

if (index != 0)
return;

handlePtr->loopMode = (value > 0.5f);
}

static void audiofile_set_program(PluginHandle handle, uint32_t bank, uint32_t program)
{
AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;

if (bank != 0 || program >= PROGRAM_COUNT)
return;

if (handlePtr->programs.current != program)
{
audiofile_load_filename(handlePtr, handlePtr->programs.fullNames[program]);
handlePtr->programs.current = program;
}
}

static void audiofile_set_custom_data(PluginHandle handle, const char* key, const char* value) static void audiofile_set_custom_data(PluginHandle handle, const char* key, const char* value)
{ {
AudioFileInstance* const handlePtr = (AudioFileInstance*)handle; AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;


if (strcmp(key, "file") == 0)
if (strncmp(key, "file", 4) != 0)
return;
if (key[4] < '0' || key[4] > '9')
return;
if (key[5] < '0' || key[5] > '9')
return;

uint8_t tens = key[4]-'0';
uint8_t nums = key[5]-'0';

uint32_t program = tens*10 + nums;

if (program >= PROGRAM_COUNT)
return;

if (handlePtr->programs.fullNames[program] != NULL)
free((void*)handlePtr->programs.fullNames[program]);
if (handlePtr->programs.shortNames[program] != NULL)
free((void*)handlePtr->programs.shortNames[program]);

handlePtr->programs.fullNames[program] = strdup(value);

{
const char* shortName1 = strrchr(value, OS_SEP)+1;
//const char* shortName2 = strchr(shortName1, '.');

handlePtr->programs.shortNames[program] = strdup(shortName1);
}

if (handlePtr->programs.current == program)
audiofile_load_filename(handlePtr, value); audiofile_load_filename(handlePtr, value);
} }


@@ -298,7 +452,13 @@ static void audiofile_ui_show(PluginHandle handle, bool show)
const char* const filename = handlePtr->host->ui_open_file(handlePtr->host->handle, false, "Open Audio File", ""); const char* const filename = handlePtr->host->ui_open_file(handlePtr->host->handle, false, "Open Audio File", "");


if (filename != NULL) if (filename != NULL)
handlePtr->host->ui_custom_data_changed(handlePtr->host->handle, "file", filename);
{
char fileStr[4+2+1] = { 'f', 'i', 'l', 'e', 0, 0, 0 };
fileStr[4] = '0' + (handlePtr->programs.current / 10);
fileStr[5] = '0' + (handlePtr->programs.current % 10);

handlePtr->host->ui_custom_data_changed(handlePtr->host->handle, fileStr, filename);
}


handlePtr->host->ui_closed(handlePtr->host->handle); handlePtr->host->ui_closed(handlePtr->host->handle);
} }
@@ -387,7 +547,7 @@ static const PluginDescriptor audiofileDesc = {
.audioOuts = 2, .audioOuts = 2,
.midiIns = 0, .midiIns = 0,
.midiOuts = 0, .midiOuts = 0,
.parameterIns = 0,
.parameterIns = 1,
.parameterOuts = 0, .parameterOuts = 0,
.name = "Audio File", .name = "Audio File",
.label = "audiofile", .label = "audiofile",
@@ -397,16 +557,16 @@ static const PluginDescriptor audiofileDesc = {
.instantiate = audiofile_instantiate, .instantiate = audiofile_instantiate,
.cleanup = audiofile_cleanup, .cleanup = audiofile_cleanup,


.get_parameter_count = NULL,
.get_parameter_info = NULL,
.get_parameter_value = NULL,
.get_parameter_count = audiofile_get_parameter_count,
.get_parameter_info = audiofile_get_parameter_info,
.get_parameter_value = audiofile_get_parameter_value,
.get_parameter_text = NULL, .get_parameter_text = NULL,


.get_midi_program_count = NULL,
.get_midi_program_info = NULL,
.get_midi_program_count = audiofile_get_program_count,
.get_midi_program_info = audiofile_get_program_info,


.set_parameter_value = NULL,
.set_midi_program = NULL,
.set_parameter_value = audiofile_set_parameter_value,
.set_midi_program = audiofile_set_program,
.set_custom_data = audiofile_set_custom_data, .set_custom_data = audiofile_set_custom_data,


.ui_show = audiofile_ui_show, .ui_show = audiofile_ui_show,
@@ -429,7 +589,7 @@ void carla_register_native_plugin_audiofile()
} }


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// amagamated build
// amalgamated build


#include "audio_decoder/ad_ffmpeg.c" #include "audio_decoder/ad_ffmpeg.c"
#include "audio_decoder/ad_plugin.c" #include "audio_decoder/ad_plugin.c"


+ 12
- 6
source/backend/plugin/DssiPlugin.cpp View File

@@ -822,7 +822,8 @@ public:
void reloadPrograms(const bool init) void reloadPrograms(const bool init)
{ {
carla_debug("DssiPlugin::reloadPrograms(%s)", bool2str(init)); carla_debug("DssiPlugin::reloadPrograms(%s)", bool2str(init));
uint32_t i, oldCount = kData->midiprog.count;
uint32_t i, oldCount = kData->midiprog.count;
const int32_t current = kData->midiprog.current;


// Delete old programs // Delete old programs
kData->midiprog.clear(); kData->midiprog.clear();
@@ -868,8 +869,6 @@ public:
} }
else else
{ {
kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);

// Check if current program is invalid // Check if current program is invalid
bool programChanged = false; bool programChanged = false;


@@ -879,27 +878,34 @@ public:
kData->midiprog.current = oldCount; kData->midiprog.current = oldCount;
programChanged = true; programChanged = true;
} }
else if (kData->midiprog.current >= static_cast<int32_t>(kData->midiprog.count))
else if (current >= static_cast<int32_t>(kData->midiprog.count))
{ {
// current midi program > count // current midi program > count
kData->midiprog.current = 0; kData->midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (kData->midiprog.current < 0 && kData->midiprog.count > 0)
else if (current < 0 && kData->midiprog.count > 0)
{ {
// programs exist now, but not before // programs exist now, but not before
kData->midiprog.current = 0; kData->midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (kData->midiprog.current >= 0 && kData->midiprog.count == 0)
else if (current >= 0 && kData->midiprog.count == 0)
{ {
// programs existed before, but not anymore // programs existed before, but not anymore
kData->midiprog.current = -1; kData->midiprog.current = -1;
programChanged = true; programChanged = true;
} }
else
{
// no change
kData->midiprog.current = current;
}


if (programChanged) if (programChanged)
setMidiProgram(kData->midiprog.current, true, true, true); setMidiProgram(kData->midiprog.current, true, true, true);

kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
} }
} }




+ 22
- 8
source/backend/plugin/NativePlugin.cpp View File

@@ -454,6 +454,12 @@ public:
fDescriptor->ui_set_custom_data(fHandle, key, value); fDescriptor->ui_set_custom_data(fHandle, key, value);
} }


if (std::strlen(key) == 6 && std::strncmp(key, "file", 4) == 0)
{
const ScopedDisabler sd(this);
reloadPrograms(false);
}

CarlaPlugin::setCustomData(type, key, value, sendGui); CarlaPlugin::setCustomData(type, key, value, sendGui);
} }


@@ -927,7 +933,8 @@ public:
void reloadPrograms(const bool init) void reloadPrograms(const bool init)
{ {
carla_debug("NativePlugin::reloadPrograms(%s)", bool2str(init)); carla_debug("NativePlugin::reloadPrograms(%s)", bool2str(init));
uint32_t i, oldCount = kData->midiprog.count;
uint32_t i, oldCount = kData->midiprog.count;
const int32_t current = kData->midiprog.current;


// Delete old programs // Delete old programs
kData->midiprog.clear(); kData->midiprog.clear();
@@ -970,8 +977,6 @@ public:
} }
else else
{ {
kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);

// Check if current program is invalid // Check if current program is invalid
bool programChanged = false; bool programChanged = false;


@@ -981,27 +986,34 @@ public:
kData->midiprog.current = oldCount; kData->midiprog.current = oldCount;
programChanged = true; programChanged = true;
} }
else if (kData->midiprog.current >= static_cast<int32_t>(kData->midiprog.count))
else if (current >= static_cast<int32_t>(kData->midiprog.count))
{ {
// current midi program > count // current midi program > count
kData->midiprog.current = 0; kData->midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (kData->midiprog.current < 0 && kData->midiprog.count > 0)
else if (current < 0 && kData->midiprog.count > 0)
{ {
// programs exist now, but not before // programs exist now, but not before
kData->midiprog.current = 0; kData->midiprog.current = 0;
programChanged = true; programChanged = true;
} }
else if (kData->midiprog.current >= 0 && kData->midiprog.count == 0)
else if (current >= 0 && kData->midiprog.count == 0)
{ {
// programs existed before, but not anymore // programs existed before, but not anymore
kData->midiprog.current = -1; kData->midiprog.current = -1;
programChanged = true; programChanged = true;
} }
else
{
// no change
kData->midiprog.current = current;
}


if (programChanged) if (programChanged)
setMidiProgram(kData->midiprog.current, true, true, true); setMidiProgram(kData->midiprog.current, true, true, true);

kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
} }
} }


@@ -1607,7 +1619,8 @@ public:
if (index >= kData->param.count) if (index >= kData->param.count)
return; return;


fDescriptor->ui_set_parameter_value(fHandle, index, value);
if (fDescriptor->ui_set_parameter_value != nullptr)
fDescriptor->ui_set_parameter_value(fHandle, index, value);
} }


void uiMidiProgramChange(const uint32_t index) void uiMidiProgramChange(const uint32_t index)
@@ -1623,7 +1636,8 @@ public:
if (index >= kData->midiprog.count) if (index >= kData->midiprog.count)
return; return;


fDescriptor->ui_set_parameter_value(fHandle, kData->midiprog.data[index].bank, kData->midiprog.data[index].program);
if (fDescriptor->ui_set_midi_program != nullptr)
fDescriptor->ui_set_midi_program(fHandle, kData->midiprog.data[index].bank, kData->midiprog.data[index].program);
} }


void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)


Loading…
Cancel
Save