Browse Source

Carla: Continue work on internal API

tags/v0.9.0
falkTX 13 years ago
parent
commit
7232b4d914
7 changed files with 820 additions and 59 deletions
  1. +714
    -1
      c++/carla-backend/carla_native.cpp
  2. +1
    -1
      c++/carla-backend/dssi.cpp
  3. +20
    -10
      c++/carla-backend/plugins/bypass.c
  4. +6
    -5
      c++/carla-backend/plugins/carla_native.h
  5. +73
    -34
      c++/carla-backend/plugins/carla_nativemm.h
  6. +4
    -6
      c++/carla-backend/plugins/midi-split.cpp
  7. +2
    -2
      c++/carla-backend/vst.cpp

+ 714
- 1
c++/carla-backend/carla_native.cpp View File

@@ -80,6 +80,18 @@ public:


descriptor = nullptr; descriptor = nullptr;
handle = nullptr; handle = nullptr;

host.handle = this;
host.get_buffer_size = carla_host_get_buffer_size;
host.get_sample_rate = carla_host_get_sample_rate;
host.get_time_info = carla_host_get_time_info;
host.write_midi_event = carla_host_write_midi_event;

isProcessing = false;

midiEventCount = 0;
memset(midiEvents, 0, sizeof(::MidiEvent) * MAX_MIDI_EVENTS * 2);
memset(midiEventOffsets, 0, sizeof(uint32_t) * MAX_MIDI_EVENTS * 2);
} }


~NativePlugin() ~NativePlugin()
@@ -695,6 +707,629 @@ public:
qDebug("NativePlugin::reload() - end"); qDebug("NativePlugin::reload() - end");
} }


void reloadPrograms(const bool init)
{
qDebug("NativePlugin::reloadPrograms(%s)", bool2str(init));
uint32_t i, oldCount = midiprog.count;

// Delete old programs
if (midiprog.count > 0)
{
for (i=0; i < midiprog.count; i++)
{
if (midiprog.data[i].name)
free((void*)midiprog.data[i].name);
}

delete[] midiprog.data;
}

midiprog.count = 0;
midiprog.data = nullptr;

// Query new programs
midiprog.count = descriptor->midiProgramCount;

if (midiprog.count > 0)
midiprog.data = new midi_program_t[midiprog.count];

// Update data
for (i=0; i < midiprog.count; i++)
{
const MidiProgram* const mpDesc = &descriptor->midiPrograms[i];
Q_ASSERT(mpDesc->program < 128);
Q_ASSERT(mpDesc->name);

midiprog.data[i].bank = mpDesc->bank;
midiprog.data[i].program = mpDesc->program;
midiprog.data[i].name = strdup(mpDesc->name);
}

#ifndef BUILD_BRIDGE
// Update OSC Names
if (x_engine->isOscControllerRegisted())
{
x_engine->osc_send_control_set_midi_program_count(m_id, midiprog.count);

for (i=0; i < midiprog.count; i++)
x_engine->osc_send_control_set_midi_program_data(m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.data[i].name);
}
#endif

if (init)
{
if (midiprog.count > 0)
setMidiProgram(0, false, false, false, true);
}
else
{
x_engine->callback(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0);

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

if (midiprog.count == oldCount+1)
{
// one midi program added, probably created by user
midiprog.current = oldCount;
programChanged = true;
}
else if (midiprog.current >= (int32_t)midiprog.count)
{
// current midi program > count
midiprog.current = 0;
programChanged = true;
}
else if (midiprog.current < 0 && midiprog.count > 0)
{
// programs exist now, but not before
midiprog.current = 0;
programChanged = true;
}
else if (midiprog.current >= 0 && midiprog.count == 0)
{
// programs existed before, but not anymore
midiprog.current = -1;
programChanged = true;
}

if (programChanged)
setMidiProgram(midiprog.current, true, true, true, true);
}
}

// -------------------------------------------------------------------
// Plugin processing

void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset)
{
uint32_t i, k;

double aInsPeak[2] = { 0.0 };
double aOutsPeak[2] = { 0.0 };

// reset MIDI
midiEventCount = 0;
memset(midiEvents, 0, sizeof(::MidiEvent) * MAX_MIDI_EVENTS * 2);
memset(midiEventOffsets, 0, sizeof(uint32_t) * MAX_MIDI_EVENTS * 2);

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Input VU

if (aIn.count > 0)
{
if (aIn.count == 1)
{
for (k=0; k < frames; k++)
{
if (abs(inBuffer[0][k]) > aInsPeak[0])
aInsPeak[0] = abs(inBuffer[0][k]);
}
}
else if (aIn.count > 1)
{
for (k=0; k < frames; k++)
{
if (abs(inBuffer[0][k]) > aInsPeak[0])
aInsPeak[0] = abs(inBuffer[0][k]);

if (abs(inBuffer[1][k]) > aInsPeak[1])
aInsPeak[1] = abs(inBuffer[1][k]);
}
}
}

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Parameters Input [Automation]

if (param.portCin && m_active && m_activeBefore)
{
bool allNotesOffSent = false;

const CarlaEngineControlEvent* cinEvent;
uint32_t time, nEvents = param.portCin->getEventCount();

uint32_t nextBankId = 0;
if (midiprog.current >= 0 && midiprog.count > 0)
nextBankId = midiprog.data[midiprog.current].bank;

for (i=0; i < nEvents; i++)
{
cinEvent = param.portCin->getEvent(i);

if (! cinEvent)
continue;

time = cinEvent->time - framesOffset;

if (time >= frames)
continue;

// Control change
switch (cinEvent->type)
{
case CarlaEngineEventNull:
break;

case CarlaEngineEventControlChange:
{
double value;

// Control backend stuff
if (cinEvent->channel == m_ctrlInChannel)
{
if (MIDI_IS_CONTROL_BREATH_CONTROLLER(cinEvent->controller) && (m_hints & PLUGIN_CAN_DRYWET) > 0)
{
value = cinEvent->value;
setDryWet(value, false, false);
postponeEvent(PluginPostEventParameterChange, PARAMETER_DRYWET, 0, value);
continue;
}

if (MIDI_IS_CONTROL_CHANNEL_VOLUME(cinEvent->controller) && (m_hints & PLUGIN_CAN_VOLUME) > 0)
{
value = cinEvent->value*127/100;
setVolume(value, false, false);
postponeEvent(PluginPostEventParameterChange, PARAMETER_VOLUME, 0, value);
continue;
}

if (MIDI_IS_CONTROL_BALANCE(cinEvent->controller) && (m_hints & PLUGIN_CAN_BALANCE) > 0)
{
double left, right;
value = cinEvent->value/0.5 - 1.0;

if (value < 0.0)
{
left = -1.0;
right = (value*2)+1.0;
}
else if (value > 0.0)
{
left = (value*2)-1.0;
right = 1.0;
}
else
{
left = -1.0;
right = 1.0;
}

setBalanceLeft(left, false, false);
setBalanceRight(right, false, false);
postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
continue;
}
}

// Control plugin parameters
for (k=0; k < param.count; k++)
{
if (param.data[k].midiChannel != cinEvent->channel)
continue;
if (param.data[k].midiCC != cinEvent->controller)
continue;
if (param.data[k].type != PARAMETER_INPUT)
continue;

if (param.data[k].hints & PARAMETER_IS_AUTOMABLE)
{
if (param.data[k].hints & PARAMETER_IS_BOOLEAN)
{
value = cinEvent->value < 0.5 ? param.ranges[k].min : param.ranges[k].max;
}
else
{
value = cinEvent->value * (param.ranges[k].max - param.ranges[k].min) + param.ranges[k].min;

if (param.data[k].hints & PARAMETER_IS_INTEGER)
value = rint(value);
}

setParameterValue(k, value, false, false, false);
postponeEvent(PluginPostEventParameterChange, k, 0, value);
}
}

break;
}

case CarlaEngineEventMidiBankChange:
if (cinEvent->channel == m_ctrlInChannel)
nextBankId = rint(cinEvent->value);
break;

case CarlaEngineEventMidiProgramChange:
if (cinEvent->channel == m_ctrlInChannel)
{
uint32_t nextProgramId = rint(cinEvent->value);

for (k=0; k < midiprog.count; k++)
{
if (midiprog.data[k].bank == nextBankId && midiprog.data[k].program == nextProgramId)
{
setMidiProgram(k, false, false, false, false);
postponeEvent(PluginPostEventMidiProgramChange, k, 0, 0.0);
break;
}
}
}
break;

case CarlaEngineEventAllSoundOff:
if (cinEvent->channel == m_ctrlInChannel)
{
if (midi.portMin && ! allNotesOffSent)
sendMidiAllNotesOff();

if (descriptor->deactivate)
{
descriptor->deactivate(handle);
//if (h2) ldescriptor->deactivate(h2);
}

if (descriptor->activate)
{
descriptor->activate(handle);
//if (h2) ldescriptor->activate(h2);
}

allNotesOffSent = true;
}
break;

case CarlaEngineEventAllNotesOff:
if (cinEvent->channel == m_ctrlInChannel)
{
if (midi.portMin && ! allNotesOffSent)
sendMidiAllNotesOff();

allNotesOffSent = true;
}
break;
}
}
} // End of Parameters Input

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// MIDI Input

if (mIn.count > 0 && m_active && m_activeBefore)
{
// ----------------------------------------------------------------------------------------------------
// MIDI Input (External)

{
engineMidiLock();

for (i=0; i < MAX_MIDI_EVENTS && midiEventCount < MAX_MIDI_EVENTS; i++)
{
if (extMidiNotes[i].channel < 0)
break;

::MidiEvent* const midiEvent = &midiEvents[midiEventCount];
memset(midiEvent, 0, sizeof(::MidiEvent));

midiEvent->data[0] = uint8_t(extMidiNotes[i].velo ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) + extMidiNotes[i].channel;
midiEvent->data[1] = extMidiNotes[i].note;
midiEvent->data[2] = extMidiNotes[i].velo;
midiEvent->size = 3;

extMidiNotes[i].channel = -1; // mark as invalid
midiEventCount += 1;
}

engineMidiUnlock();

} // End of MIDI Input (External)

CARLA_PROCESS_CONTINUE_CHECK;

// ----------------------------------------------------------------------------------------------------
// MIDI Input (System)

{
const CarlaEngineMidiEvent* minEvent;
uint32_t time, nEvents = midi.portMin->getEventCount();

for (i=0; i < nEvents && midiEventCount < MAX_MIDI_EVENTS; i++)
{
minEvent = midi.portMin->getEvent(i);

if (! minEvent)
continue;

time = minEvent->time - framesOffset;

if (time >= frames)
continue;

uint8_t status = minEvent->data[0];
uint8_t channel = status & 0x0F;

// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(status) && minEvent->data[2] == 0)
status -= 0x10;

::MidiEvent* const midiEvent = &midiEvents[midiEventCount];
memset(midiEvent, 0, sizeof(::MidiEvent));

midiEvent->size = minEvent->size;
midiEvent->time = minEvent->time;

if (MIDI_IS_STATUS_NOTE_OFF(status))
{
uint8_t note = minEvent->data[1];

midiEvent->data[0] = status;
midiEvent->data[1] = note;

postponeEvent(PluginPostEventNoteOff, channel, note, 0.0);
}
else if (MIDI_IS_STATUS_NOTE_ON(status))
{
uint8_t note = minEvent->data[1];
uint8_t velo = minEvent->data[2];

midiEvent->data[0] = status;
midiEvent->data[1] = note;
midiEvent->data[2] = velo;

postponeEvent(PluginPostEventNoteOn, channel, note, velo);
}
else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
{
uint8_t note = minEvent->data[1];
uint8_t pressure = minEvent->data[2];

midiEvent->data[0] = status;
midiEvent->data[1] = note;
midiEvent->data[2] = pressure;
}
else if (MIDI_IS_STATUS_AFTERTOUCH(status))
{
uint8_t pressure = minEvent->data[1];

midiEvent->data[0] = status;
midiEvent->data[1] = pressure;
}
else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
{
uint8_t lsb = minEvent->data[1];
uint8_t msb = minEvent->data[2];

midiEvent->data[0] = status;
midiEvent->data[1] = lsb;
midiEvent->data[2] = msb;
}
else
continue;

midiEventCount += 1;
}
} // End of MIDI Input (System)

} // End of MIDI Input

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Plugin processing

uint32_t midiEventCountBefore = midiEventCount;

if (m_active)
{
if (! m_activeBefore)
{
if (mIn.count > 0 && m_ctrlInChannel >= 0 && m_ctrlInChannel < 16)
{
memset(&midiEvents[0], 0, sizeof(::MidiEvent));
midiEvents[0].data[0] = MIDI_STATUS_CONTROL_CHANGE + m_ctrlInChannel;
midiEvents[0].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
midiEvents[0].size = 2;

memset(&midiEvents[1], 0, sizeof(::MidiEvent));
midiEvents[1].data[0] = MIDI_STATUS_CONTROL_CHANGE + m_ctrlInChannel;
midiEvents[1].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
midiEvents[1].size = 2;

midiEventCount = 2;
}

if (descriptor->activate)
{
descriptor->activate(handle);
//if (h2) descriptor->activate(h2);
}
}

isProcessing = true;
descriptor->process(handle, inBuffer, outBuffer, frames, midiEventCountBefore, midiEvents);
//if (h2) descriptor->process(h2, inBuffer, outBuffer, frames, midiEventCount, midiEvents);
isProcessing = false;
}
else
{
if (m_activeBefore)
{
if (descriptor->deactivate)
{
descriptor->deactivate(handle);
//if (h2) descriptor->deactivate(h2);
}
}
}

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Post-processing (dry/wet, volume and balance)

if (m_active)
{
bool do_drywet = (m_hints & PLUGIN_CAN_DRYWET) > 0 && x_dryWet != 1.0;
bool do_volume = (m_hints & PLUGIN_CAN_VOLUME) > 0 && x_volume != 1.0;
bool do_balance = (m_hints & PLUGIN_CAN_BALANCE) > 0 && (x_balanceLeft != -1.0 || x_balanceRight != 1.0);

double bal_rangeL, bal_rangeR;
float oldBufLeft[do_balance ? frames : 0];

for (i=0; i < aOut.count; i++)
{
// Dry/Wet
if (do_drywet)
{
for (k=0; k < frames; k++)
{
if (aOut.count == 1)
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet));
else
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet));
}
}

// Balance
if (do_balance)
{
if (i%2 == 0)
memcpy(&oldBufLeft, outBuffer[i], sizeof(float)*frames);

bal_rangeL = (x_balanceLeft+1.0)/2;
bal_rangeR = (x_balanceRight+1.0)/2;

for (k=0; k < frames; k++)
{
if (i%2 == 0)
{
// left output
outBuffer[i][k] = oldBufLeft[k]*(1.0-bal_rangeL);
outBuffer[i][k] += outBuffer[i+1][k]*(1.0-bal_rangeR);
}
else
{
// right
outBuffer[i][k] = outBuffer[i][k]*bal_rangeR;
outBuffer[i][k] += oldBufLeft[k]*bal_rangeL;
}
}
}

// Volume
if (do_volume)
{
for (k=0; k < frames; k++)
outBuffer[i][k] *= x_volume;
}

// Output VU
for (k=0; i < 2 && k < frames; k++)
{
if (abs(outBuffer[i][k]) > aOutsPeak[i])
aOutsPeak[i] = abs(outBuffer[i][k]);
}
}
}
else
{
// disable any output sound if not active
for (i=0; i < aOut.count; i++)
memset(outBuffer[i], 0.0f, sizeof(float)*frames);

aOutsPeak[0] = 0.0;
aOutsPeak[1] = 0.0;

} // End of Post-processing

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// MIDI Output

if (mOut.count > 0 && m_active)
{
uint8_t data[3] = { 0 };

for (uint32_t i = midiEventCountBefore; i < midiEventCount; i++)
{
data[0] = midiEvents[i].data[0];
data[1] = midiEvents[i].data[1];
data[2] = midiEvents[i].data[2];

// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(data[0]) && data[2] == 0)
data[0] -= 0x10;

const uint32_t portOffset = midiEventOffsets[i];

if (portOffset < mOut.count)
mOut.ports[portOffset]->writeEvent(midiEvents[i].time, data, 3);
}

} // End of MIDI Output

// --------------------------------------------------------------------------------------------------------
// Control Output

if (param.portCout && m_active)
{
double value, valueControl;

for (k=0; k < param.count; k++)
{
if (param.data[k].type == PARAMETER_OUTPUT)
{
value = descriptor->get_parameter_value(handle, param.data[k].rindex);

if (param.data[k].midiCC > 0)
{
valueControl = (value - param.ranges[k].min) / (param.ranges[k].max - param.ranges[k].min);
param.portCout->writeEvent(CarlaEngineEventControlChange, framesOffset, param.data[k].midiChannel, param.data[k].midiCC, valueControl);
}
}
}
} // End of Control Output

CARLA_PROCESS_CONTINUE_CHECK;

// --------------------------------------------------------------------------------------------------------
// Peak Values

x_engine->setInputPeak(m_id, 0, aInsPeak[0]);
x_engine->setInputPeak(m_id, 1, aInsPeak[1]);
x_engine->setOutputPeak(m_id, 0, aOutsPeak[0]);
x_engine->setOutputPeak(m_id, 1, aOutsPeak[1]);

m_activeBefore = m_active;
}

// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Cleanup // Cleanup


@@ -769,6 +1404,77 @@ public:


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


uint32_t handleGetBufferSize()
{
return x_engine->getBufferSize();
}

double handleGetSampleRate()
{
return x_engine->getSampleRate();
}

const TimeInfo* handleGetTimeInfo()
{
// TODO
return nullptr;
}

bool handleWriteMidiEvent(uint32_t portOffset, MidiEvent* event)
{
Q_ASSERT(m_enabled);
Q_ASSERT(mOut.count > 0);
Q_ASSERT(isProcessing);
Q_ASSERT(event);

if (! m_enabled)
return false;

if (mOut.count == 0)
return false;

if (! isProcessing)
{
qCritical("NativePlugin::handleWriteMidiEvent(%i, %p) - received MIDI out events outside audio thread, ignoring", portOffset, event);
return false;
}

if (midiEventCount >= MAX_MIDI_EVENTS*2)
return false;

memcpy(&midiEvents[midiEventCount], event, sizeof(::MidiEvent));
midiEventOffsets[midiEventCount] = portOffset;
midiEventCount += 1;

return true;
}

static uint32_t carla_host_get_buffer_size(HostHandle handle)
{
Q_ASSERT(handle);
return ((NativePlugin*)handle)->handleGetBufferSize();
}

static double carla_host_get_sample_rate(HostHandle handle)
{
Q_ASSERT(handle);
return ((NativePlugin*)handle)->handleGetSampleRate();
}

static const TimeInfo* carla_host_get_time_info(HostHandle handle)
{
Q_ASSERT(handle);
return ((NativePlugin*)handle)->handleGetTimeInfo();
}

static bool carla_host_write_midi_event(HostHandle handle, uint32_t port_offset, MidiEvent* event)
{
Q_ASSERT(handle);
return ((NativePlugin*)handle)->handleWriteMidiEvent(port_offset, event);
}

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

static size_t getPluginCount() static size_t getPluginCount()
{ {
return pluginDescriptors.size(); return pluginDescriptors.size();
@@ -819,7 +1525,7 @@ public:
// --------------------------------------------------------------- // ---------------------------------------------------------------
// initialize plugin // initialize plugin


handle = descriptor->instantiate((struct _PluginDescriptor*)descriptor, nullptr); // TODO - host
handle = descriptor->instantiate((struct _PluginDescriptor*)descriptor, &host);


if (! handle) if (! handle)
{ {
@@ -852,10 +1558,17 @@ public:
private: private:
const PluginDescriptor* descriptor; const PluginDescriptor* descriptor;
PluginHandle handle; PluginHandle handle;
HostDescriptor host;

bool isProcessing;


NativePluginMidiData mIn; NativePluginMidiData mIn;
NativePluginMidiData mOut; NativePluginMidiData mOut;


uint32_t midiEventCount;
::MidiEvent midiEvents[MAX_MIDI_EVENTS*2];
uint32_t midiEventOffsets[MAX_MIDI_EVENTS*2];

static std::vector<const PluginDescriptor*> pluginDescriptors; static std::vector<const PluginDescriptor*> pluginDescriptors;
}; };




+ 1
- 1
c++/carla-backend/dssi.cpp View File

@@ -1032,7 +1032,7 @@ public:
memset(midiEvent, 0, sizeof(snd_seq_event_t)); memset(midiEvent, 0, sizeof(snd_seq_event_t));


midiEvent->type = extMidiNotes[i].velo ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; midiEvent->type = extMidiNotes[i].velo ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
midiEvent->data.note.channel = m_ctrlInChannel;
midiEvent->data.note.channel = extMidiNotes[i].channel;
midiEvent->data.note.note = extMidiNotes[i].note; midiEvent->data.note.note = extMidiNotes[i].note;
midiEvent->data.note.velocity = extMidiNotes[i].velo; midiEvent->data.note.velocity = extMidiNotes[i].velo;




+ 20
- 10
c++/carla-backend/plugins/bypass.c View File

@@ -21,9 +21,11 @@
#include <string.h> #include <string.h>


enum ByPassPorts { enum ByPassPorts {
PORT_IN,
PORT_OUT,
PORT_MAX
PORT_IN1 = 0,
PORT_IN2 = 1,
PORT_OUT1 = 2,
PORT_OUT2 = 3,
PORT_MAX = 4
}; };


void bypass_init(struct _PluginDescriptor* _this_) void bypass_init(struct _PluginDescriptor* _this_)
@@ -31,13 +33,21 @@ void bypass_init(struct _PluginDescriptor* _this_)
_this_->portCount = PORT_MAX; _this_->portCount = PORT_MAX;
_this_->ports = malloc(sizeof(PluginPort) * PORT_MAX); _this_->ports = malloc(sizeof(PluginPort) * PORT_MAX);


_this_->ports[PORT_IN].type = PORT_TYPE_AUDIO;
_this_->ports[PORT_IN].hints = 0;
_this_->ports[PORT_IN].name = "in";
_this_->ports[PORT_IN1].type = PORT_TYPE_AUDIO;
_this_->ports[PORT_IN1].hints = 0;
_this_->ports[PORT_IN1].name = "in1";


_this_->ports[PORT_OUT].type = PORT_TYPE_AUDIO;
_this_->ports[PORT_OUT].hints = PORT_HINT_IS_OUTPUT;
_this_->ports[PORT_OUT].name = "out";
_this_->ports[PORT_IN2].type = PORT_TYPE_AUDIO;
_this_->ports[PORT_IN2].hints = 0;
_this_->ports[PORT_IN2].name = "in2";

_this_->ports[PORT_OUT1].type = PORT_TYPE_AUDIO;
_this_->ports[PORT_OUT1].hints = PORT_HINT_IS_OUTPUT;
_this_->ports[PORT_OUT1].name = "out1";

_this_->ports[PORT_OUT2].type = PORT_TYPE_AUDIO;
_this_->ports[PORT_OUT2].hints = PORT_HINT_IS_OUTPUT;
_this_->ports[PORT_OUT2].name = "out2";
} }


void bypass_fini(struct _PluginDescriptor* _this_) void bypass_fini(struct _PluginDescriptor* _this_)
@@ -62,7 +72,7 @@ void bypass_process(PluginHandle handle, float** inBuffer, float** outBuffer, ui
{ {
float* input1 = inBuffer[0]; float* input1 = inBuffer[0];
float* input2 = inBuffer[1]; float* input2 = inBuffer[1];
float* output1 = outBuffer[1];
float* output1 = outBuffer[0];
float* output2 = outBuffer[1]; float* output2 = outBuffer[1];


memcpy(output1, input1, sizeof(float)*frames); memcpy(output1, input1, sizeof(float)*frames);


+ 6
- 5
c++/carla-backend/plugins/carla_native.h View File

@@ -27,6 +27,7 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>


typedef void* HostHandle;
typedef void* PluginHandle; typedef void* PluginHandle;


const uint32_t PLUGIN_IS_SYNTH = 1 << 0; const uint32_t PLUGIN_IS_SYNTH = 1 << 0;
@@ -103,10 +104,11 @@ typedef struct _TimeInfo {
} TimeInfo; } TimeInfo;


typedef struct _HostDescriptor { typedef struct _HostDescriptor {
uint32_t (*get_buffer_size)();
double (*get_sample_rate)();
const TimeInfo* (*get_time_info)();
bool (*write_midi_event)(uint32_t port_offset, MidiEvent* event);
HostHandle handle;
uint32_t (*get_buffer_size)(HostHandle handle);
double (*get_sample_rate)(HostHandle handle);
const TimeInfo* (*get_time_info)(HostHandle handle);
bool (*write_midi_event)(HostHandle handle, uint32_t port_offset, MidiEvent* event);
} HostDescriptor; } HostDescriptor;


typedef struct _PluginPortScalePoint { typedef struct _PluginPortScalePoint {
@@ -157,7 +159,6 @@ typedef struct _PluginDescriptor {
// TODO - ui_set_* // TODO - ui_set_*


void (*process)(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents); void (*process)(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents);
// TODO - midi stuff^


void* _singleton; void* _singleton;
void (*_init)(struct _PluginDescriptor* _this_); void (*_init)(struct _PluginDescriptor* _this_);


+ 73
- 34
c++/carla-backend/plugins/carla_nativemm.h View File

@@ -23,50 +23,90 @@


class PluginDescriptorClass { class PluginDescriptorClass {
public: public:
PluginDescriptorClass()
PluginDescriptorClass(const PluginDescriptorClass* master)
{ {
desc.category = PLUGIN_CATEGORY_NONE;
desc.hints = 0;
desc.name = nullptr;
desc.label = nullptr;
desc.maker = nullptr;
desc.copyright = nullptr;
if (master)
{
desc.category = master->desc.category;
desc.hints = master->desc.hints;
desc.name = master->desc.name;
desc.label = master->desc.label;
desc.maker = master->desc.maker;
desc.copyright = master->desc.copyright;


desc.portCount = 0;
desc.ports = nullptr;
desc.portCount = master->desc.portCount;
desc.ports = master->desc.ports;


desc.midiProgramCount = 0;
desc.midiPrograms = nullptr;
desc.midiProgramCount = master->desc.midiProgramCount;
desc.midiPrograms = master->desc.midiPrograms;

host = master->host;
}
else
{
desc.category = PLUGIN_CATEGORY_NONE;
desc.hints = 0;
desc.name = nullptr;
desc.label = nullptr;
desc.maker = nullptr;
desc.copyright = nullptr;


host = nullptr;
desc.portCount = 0;
desc.ports = nullptr;

desc.midiProgramCount = 0;
desc.midiPrograms = nullptr;

host = nullptr;
}


_initDescriptor(); _initDescriptor();
} }


PluginDescriptorClass(PluginDescriptorClass* that)
virtual ~PluginDescriptorClass()
{ {
desc.category = that->desc.category;
desc.hints = that->desc.hints;
desc.name = that->desc.name;
desc.label = that->desc.label;
desc.maker = that->desc.maker;
desc.copyright = that->desc.copyright;
}


desc.portCount = that->desc.portCount;
desc.ports = that->desc.ports;
uint32_t getBufferSize() const
{
Q_ASSERT(host);


desc.midiProgramCount = that->desc.midiProgramCount;
desc.midiPrograms = that->desc.midiPrograms;
if (host)
return host->get_buffer_size(host->handle);


host = that->host;
return 0;
}


_initDescriptor();
double getSampleRate() const
{
Q_ASSERT(host);

if (host)
return host->get_sample_rate(host->handle);

return 0.0;
} }


virtual ~PluginDescriptorClass()
const TimeInfo* getTimeInfo() const
{ {
Q_ASSERT(host);

if (host)
return host->get_time_info(host->handle);

return nullptr;
} }


void writeMidiEvent(uint32_t portOffset, MidiEvent* event)
{
Q_ASSERT(host);

if (host)
host->write_midi_event(host->handle, portOffset, event);
}

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

PluginDescriptor* descriptorInit() PluginDescriptor* descriptorInit()
{ {
desc.category = getCategory(); desc.category = getCategory();
@@ -243,7 +283,6 @@ private:


void _initDescriptor() void _initDescriptor()
{ {

desc.instantiate = _instantiate; desc.instantiate = _instantiate;
desc.activate = _activate; desc.activate = _activate;
desc.deactivate = _deactivate; desc.deactivate = _deactivate;
@@ -270,9 +309,9 @@ private:


static PluginHandle _instantiate(struct _PluginDescriptor* _this_, HostDescriptor* host) static PluginHandle _instantiate(struct _PluginDescriptor* _this_, HostDescriptor* host)
{ {
PluginDescriptorClass* handle = ((PluginDescriptorClass*)_this_->_singleton)->createMe();
handle->host = host;
return handle;
PluginDescriptorClass* singleton = (PluginDescriptorClass*)_this_->_singleton;
singleton->host = host;
return singleton->createMe();
} }


static void _activate(PluginHandle handle) static void _activate(PluginHandle handle)
@@ -342,15 +381,15 @@ private:


static void _init(PluginDescriptor* const _this_) static void _init(PluginDescriptor* const _this_)
{ {
((PluginDescriptorClass*)_this_->_singleton)->handleInit();
((PluginDescriptorClass*)_this_->_singleton)->_handleInit();
} }


static void _fini(PluginDescriptor* const _this_) static void _fini(PluginDescriptor* const _this_)
{ {
((PluginDescriptorClass*)_this_->_singleton)->handleFini();
((PluginDescriptorClass*)_this_->_singleton)->_handleFini();
} }


void handleInit()
void _handleInit()
{ {
desc.portCount = getPortCount(); desc.portCount = getPortCount();


@@ -379,7 +418,7 @@ private:
} }
} }


void handleFini()
void _handleFini()
{ {
if (desc.midiProgramCount > 0 && desc.midiPrograms) if (desc.midiProgramCount > 0 && desc.midiPrograms)
delete[] desc.midiPrograms; delete[] desc.midiPrograms;


+ 4
- 6
c++/carla-backend/plugins/midi-split.cpp View File

@@ -22,12 +22,10 @@
class MidiSplitPlugin : public PluginDescriptorClass class MidiSplitPlugin : public PluginDescriptorClass
{ {
public: public:
MidiSplitPlugin() : PluginDescriptorClass()
{
}

MidiSplitPlugin(PluginDescriptorClass* that) : PluginDescriptorClass(that)
MidiSplitPlugin(const PluginDescriptorClass* master) : PluginDescriptorClass(master)
{ {
if (! master)
return;
} }


~MidiSplitPlugin() ~MidiSplitPlugin()
@@ -199,6 +197,6 @@ private:
MidiEvent events[MAX_MIDI_EVENTS]; MidiEvent events[MAX_MIDI_EVENTS];
}; };


static MidiSplitPlugin midiSplitPlugin;
static MidiSplitPlugin midiSplitPlugin(nullptr);


CARLA_REGISTER_NATIVE_PLUGIN_MM(midiSplit, midiSplitPlugin) CARLA_REGISTER_NATIVE_PLUGIN_MM(midiSplit, midiSplitPlugin)

+ 2
- 2
c++/carla-backend/vst.cpp View File

@@ -1038,7 +1038,7 @@ public:


midiEvent->type = kVstMidiType; midiEvent->type = kVstMidiType;
midiEvent->byteSize = sizeof(VstMidiEvent); midiEvent->byteSize = sizeof(VstMidiEvent);
midiEvent->midiData[0] = m_ctrlInChannel + extMidiNotes[i].velo ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
midiEvent->midiData[0] = uint8_t(extMidiNotes[i].velo ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) + extMidiNotes[i].channel;
midiEvent->midiData[1] = extMidiNotes[i].note; midiEvent->midiData[1] = extMidiNotes[i].note;
midiEvent->midiData[2] = extMidiNotes[i].velo; midiEvent->midiData[2] = extMidiNotes[i].velo;


@@ -1295,7 +1295,7 @@ public:


if (midi.portMout && m_active) if (midi.portMout && m_active)
{ {
uint8_t data[4] = { 0 };
uint8_t data[3] = { 0 };


for (int32_t i = midiEventCount; i < events.numEvents; i++) for (int32_t i = midiEventCount; i < events.numEvents; i++)
{ {


Loading…
Cancel
Save