Browse Source

Properly handle internal plugins with multi MIDI inputs

Fixes #635
tags/v1.9.9
falkTX FilipeCSnuk 7 years ago
parent
commit
8b1fd1f537
2 changed files with 90 additions and 20 deletions
  1. +80
    -17
      source/backend/plugin/CarlaPluginNative.cpp
  2. +10
    -3
      source/native-plugins/midi-join.c

+ 80
- 17
source/backend/plugin/CarlaPluginNative.cpp View File

@@ -94,25 +94,38 @@ CARLA_BACKEND_START_NAMESPACE
// -------------------------------------------------------------------
// Fallback data

static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
static const EngineEvent kNullEngineEvent = { kEngineEventTypeNull, 0, 0, {} };

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

struct NativePluginMidiData {
struct MultiPortData {
uint32_t cachedEventCount;
uint32_t usedIndex;

MultiPortData()
: cachedEventCount(0),
usedIndex(0) {}
};

uint32_t count;
uint32_t* indexes;
CarlaEngineEventPort** ports;
MultiPortData* multiportData;

NativePluginMidiData() noexcept
: count(0),
indexes(nullptr),
ports(nullptr) {}
ports(nullptr),
multiportData(nullptr) {}

~NativePluginMidiData() noexcept
{
CARLA_SAFE_ASSERT_INT(count == 0, count);
CARLA_SAFE_ASSERT(indexes == nullptr);
CARLA_SAFE_ASSERT(ports == nullptr);
CARLA_SAFE_ASSERT(multiportData == nullptr);
}

void createNew(const uint32_t newCount)
@@ -122,19 +135,23 @@ struct NativePluginMidiData {
CARLA_SAFE_ASSERT_RETURN(ports == nullptr,);
CARLA_SAFE_ASSERT_RETURN(newCount > 0,);

indexes = new uint32_t[newCount];
ports = new CarlaEngineEventPort*[newCount];
count = newCount;

for (uint32_t i=0; i < newCount; ++i)
indexes[i] = 0;
indexes = new uint32_t[newCount];
ports = new CarlaEngineEventPort*[newCount];
multiportData = new MultiPortData[newCount];
count = newCount;

for (uint32_t i=0; i < newCount; ++i)
ports[i] = nullptr;
carla_zeroStructs(indexes, newCount);
carla_zeroStructs(ports, newCount);
}

void clear() noexcept
{
if (multiportData != nullptr)
{
delete[] multiportData;
multiportData = nullptr;
}

if (ports != nullptr)
{
for (uint32_t i=0; i < count; ++i)
@@ -163,8 +180,13 @@ struct NativePluginMidiData {
{
for (uint32_t i=0; i < count; ++i)
{
carla_zeroStruct(multiportData[i]);

if (ports[i] != nullptr)
{
ports[i]->initBuffer();
multiportData[i].cachedEventCount = ports[i]->getEventCount();
}
}
}

@@ -1371,6 +1393,50 @@ public:
}
}

const EngineEvent& findNextEvent(const uint32_t index)
{
if (fMidiIn.count == 1)
{
if (index >= fMidiIn.multiportData[0].cachedEventCount)
return kNullEngineEvent;

return fMidiIn.ports[0]->getEvent(index);
}

uint32_t lowestSampleTime = 9999999;
uint32_t portMatching = 0;
bool found = false;

// process events in order for multiple ports
for (uint32_t m=0; m < fMidiIn.count; ++m)
{
CarlaEngineEventPort* const eventPort(fMidiIn.ports[m]);
NativePluginMidiData::MultiPortData& multiportData(fMidiIn.multiportData[m]);

if (multiportData.usedIndex == multiportData.cachedEventCount)
continue;

const EngineEvent& event(eventPort->getEventUnchecked(multiportData.usedIndex));

if (event.time < lowestSampleTime)
{
lowestSampleTime = event.time;
portMatching = m;
found = true;
}
}

if (found)
{
CarlaEngineEventPort* const eventPort(fMidiIn.ports[portMatching]);
NativePluginMidiData::MultiPortData& multiportData(fMidiIn.multiportData[portMatching]);

return eventPort->getEvent(multiportData.usedIndex++);
}

return kNullEngineEvent;
}

void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
{
// --------------------------------------------------------------------------------------------------------
@@ -1503,13 +1569,12 @@ public:
else
nextBankId = 0;

for (uint32_t m=0, max=jmax(1U, fMidiIn.count); m < max; ++m)
for (uint32_t i=0;; ++i)
{
CarlaEngineEventPort* const eventPort(m == 0 ? pData->event.portIn : fMidiIn.ports[m]);
const EngineEvent& event(findNextEvent(i));

for (uint32_t i=0, numEvents=eventPort->getEventCount(); i < numEvents; ++i)
{
const EngineEvent& event(eventPort->getEvent(i));
if (event.type == kEngineEventTypeNull)
break;

uint32_t eventTime = event.time;
CARLA_SAFE_ASSERT_CONTINUE(eventTime < frames);
@@ -1812,8 +1877,6 @@ public:
if (frames > timeOffset)
processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset);

} // eventPort

} // End of Event Input and Processing

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


+ 10
- 3
source/native-plugins/midi-join.c View File

@@ -1,6 +1,6 @@
/*
* Carla Native Plugins
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-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
@@ -57,13 +57,20 @@ static void midijoin_process(NativePluginHandle handle, float** inBuffer, float*
const NativeMidiEvent* const midiEvent = &midiEvents[i];

if (midiEvent->port >= MAX_MIDI_CHANNELS)
{
printf("Assertion error: midiEvent->port:%u >= MAX_MIDI_CHANNELS\n", midiEvent->port);
continue;
}

const uint8_t status = (uint8_t)MIDI_GET_STATUS_FROM_DATA(midiEvent->data);
const uint8_t statusByte = midiEvent->data[0];

if (MIDI_IS_CHANNEL_MESSAGE(statusByte))
tmpEvent.data[0] = (uint8_t)((statusByte & MIDI_STATUS_BIT) | (midiEvent->port & MIDI_CHANNEL_BIT));
else
tmpEvent.data[0] = statusByte;

tmpEvent.port = 0;
tmpEvent.time = midiEvent->time;
tmpEvent.data[0] = (uint8_t)(status | (midiEvent->port & MIDI_CHANNEL_BIT));
tmpEvent.data[1] = midiEvent->data[1];
tmpEvent.data[2] = midiEvent->data[2];
tmpEvent.data[3] = midiEvent->data[3];


Loading…
Cancel
Save