Browse Source

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

tags/1.9.4
falkTX 11 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 <unistd.h>

#define PROGRAM_COUNT 16

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

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

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

} AudioFilePool;

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

typedef struct _AudioFileInstance {
HostDescriptor* host;

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

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

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

static bool gADInitiated = false;

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

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

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

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

ad_seek(handlePtr->filePtr, lastFrame);
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[1][i] = tmpData[j];
i++;
}
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;
@@ -157,12 +165,15 @@ void audiofile_load_filename(AudioFileInstance* const handlePtr, const char* con
}
ad_clear_nfo(&handlePtr->fileNfo);

if (filename == NULL)
return;

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

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)
{
@@ -191,11 +202,15 @@ static void audiofile_thread_idle(void* ptr)
usleep(50*1000);
}

pthread_exit(0);
pthread_exit(NULL);
}

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

static bool gADInitiated = false;

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

static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDescriptor* host)
{
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.startFrame = 0;
handlePtr->pool.size = 0;
handlePtr->programs.current = 0;

handlePtr->loopMode = true;
handlePtr->needsRead = false;
handlePtr->doProcess = false;
handlePtr->doQuit = false;
@@ -226,14 +243,26 @@ static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDe
ad_clear_nfo(&handlePtr->fileNfo);
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
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[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);
return NULL;
}
@@ -243,12 +272,6 @@ static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDe

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;

// unused
@@ -277,14 +300,145 @@ static void audiofile_cleanup(PluginHandle handle)
if (handlePtr->pool.buffer[1] != NULL)
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);
}

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)
{
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);
}

@@ -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", "");

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);
}
@@ -387,7 +547,7 @@ static const PluginDescriptor audiofileDesc = {
.audioOuts = 2,
.midiIns = 0,
.midiOuts = 0,
.parameterIns = 0,
.parameterIns = 1,
.parameterOuts = 0,
.name = "Audio File",
.label = "audiofile",
@@ -397,16 +557,16 @@ static const PluginDescriptor audiofileDesc = {
.instantiate = audiofile_instantiate,
.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_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,

.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_plugin.c"


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

@@ -822,7 +822,8 @@ public:
void reloadPrograms(const bool 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
kData->midiprog.clear();
@@ -868,8 +869,6 @@ public:
}
else
{
kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);

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

@@ -879,27 +878,34 @@ public:
kData->midiprog.current = oldCount;
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
kData->midiprog.current = 0;
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
kData->midiprog.current = 0;
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
kData->midiprog.current = -1;
programChanged = true;
}
else
{
// no change
kData->midiprog.current = current;
}

if (programChanged)
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);
}

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

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

@@ -927,7 +933,8 @@ public:
void reloadPrograms(const bool 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
kData->midiprog.clear();
@@ -970,8 +977,6 @@ public:
}
else
{
kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);

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

@@ -981,27 +986,34 @@ public:
kData->midiprog.current = oldCount;
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
kData->midiprog.current = 0;
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
kData->midiprog.current = 0;
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
kData->midiprog.current = -1;
programChanged = true;
}
else
{
// no change
kData->midiprog.current = current;
}

if (programChanged)
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)
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)
@@ -1623,7 +1636,8 @@ public:
if (index >= kData->midiprog.count)
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)


Loading…
Cancel
Save