Browse Source

Move the MIDI queue outside of VST

pull/212/head
Jean Pierre Cimalando 6 years ago
parent
commit
f904fee84b
2 changed files with 106 additions and 71 deletions
  1. +100
    -0
      distrho/src/DistrhoPluginInternal.hpp
  2. +6
    -71
      distrho/src/DistrhoPluginVST.cpp

+ 100
- 0
distrho/src/DistrhoPluginInternal.hpp View File

@@ -19,6 +19,10 @@

#include "../DistrhoPlugin.hpp"

#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
# include "extra/Mutex.hpp"
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
@@ -672,6 +676,102 @@ private:
DISTRHO_PREVENT_HEAP_ALLOCATION
};

#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
// -----------------------------------------------------------------------
// Midi queue class

/**
Single-consumer, single-producer FIFO queue of short MIDI messages, intended
for UI-to-DSP messaging in case of VST or similar plugin formats.
The access is guarded by mutex, using try-lock on the receiving side.
*/
class SimpleMidiQueue
{
public:
SimpleMidiQueue()
: fMidiStorage(nullptr),
fMidiCount(0),
fWriterIndex(0)
{
fMidiStorage = new ShortMessage[kMidiStorageCapacity];
}

virtual ~SimpleMidiQueue()
{
delete[] fMidiStorage;
fMidiStorage = nullptr;
}

void clear()
{
const MutexLocker locker(fMutex);
fMidiCount = 0;
}

void send(const uint8_t midiData[3])
{
const MutexLocker locker(fMutex);

uint32_t count = fMidiCount;
if (count == kMidiStorageCapacity)
return;

uint32_t index = fWriterIndex;
ShortMessage &msg = fMidiStorage[index];
std::memcpy(msg.data, midiData, 3);

fMidiCount = count + 1;
fWriterIndex = (index + 1) % kMidiStorageCapacity;
}

uint32_t receive(MidiEvent *events, uint32_t eventCount)
{
if (fMidiCount == 0)
return eventCount;

const MutexTryLocker locker(fMutex);
if (locker.wasNotLocked())
return eventCount;

// preserve the ordering of frame times according to messages before us
uint32_t frame = 0;
if (eventCount > 0)
frame = events[eventCount - 1].frame;

uint32_t countAvailable = fMidiCount;
uint32_t readerIndex = (fWriterIndex + kMidiStorageCapacity - countAvailable) % kMidiStorageCapacity;
for (; countAvailable > 0 && eventCount < kMaxMidiEvents; --countAvailable)
{
ShortMessage msg = fMidiStorage[readerIndex];
MidiEvent &event = events[eventCount++];
event.frame = frame;
event.size = 3;
std::memcpy(event.data, msg.data, sizeof(uint8_t)*3);
readerIndex = (readerIndex + 1) % kMaxMidiEvents;
}

fMidiCount = countAvailable;
return eventCount;
}

protected:
enum
{
kMidiStorageCapacity = 256,
};

struct ShortMessage
{
uint8_t data[3];
};

ShortMessage *fMidiStorage;
volatile uint32_t fMidiCount;
uint32_t fWriterIndex;
Mutex fMutex;
};
#endif

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

END_NAMESPACE_DISTRHO


+ 6
- 71
distrho/src/DistrhoPluginVST.cpp View File

@@ -23,9 +23,6 @@

#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
# include "extra/Mutex.hpp"
# endif
#endif

#ifndef __cdecl
@@ -164,87 +161,25 @@ public:
class MidiSendFromEditorHelper
{
public:
MidiSendFromEditorHelper()
: fMidiStorage(nullptr),
fMidiCount(0),
fWriterIndex(0)
{
fMidiStorage = new ShortMessage[kMidiStorageCapacity];
}

virtual ~MidiSendFromEditorHelper()
{
delete[] fMidiStorage;
fMidiStorage = nullptr;
}
virtual ~MidiSendFromEditorHelper() {}

void clearEditorMidi()
{
const MutexLocker locker(fMutex);
fMidiCount = 0;
fQueue.clear();
}

void sendEditorMidi(const uint8_t midiData[3])
{
const MutexLocker locker(fMutex);

uint32_t count = fMidiCount;
if (count == kMidiStorageCapacity)
return;

uint32_t index = fWriterIndex;
ShortMessage &msg = fMidiStorage[index];
std::memcpy(msg.data, midiData, 3);

fMidiCount = count + 1;
fWriterIndex = (index + 1) % kMidiStorageCapacity;
fQueue.send(midiData);
}

uint32_t receiveEditorMidi(MidiEvent *events, uint32_t eventCount)
{
if (fMidiCount == 0)
return eventCount;

const MutexTryLocker locker(fMutex);
if (locker.wasNotLocked())
return eventCount;

// preserve the ordering of frame times according to messages before us
uint32_t frame = 0;
if (eventCount > 0)
frame = events[eventCount - 1].frame;

uint32_t countAvailable = fMidiCount;
uint32_t readerIndex = (fWriterIndex + kMidiStorageCapacity - countAvailable) % kMidiStorageCapacity;
for (; countAvailable > 0 && eventCount < kMaxMidiEvents; --countAvailable)
{
ShortMessage msg = fMidiStorage[readerIndex];
MidiEvent &event = events[eventCount++];
event.frame = frame;
event.size = 3;
std::memcpy(event.data, msg.data, sizeof(uint8_t)*3);
readerIndex = (readerIndex + 1) % kMaxMidiEvents;
}

fMidiCount = countAvailable;
return eventCount;
return fQueue.receive(events, eventCount);
}

protected:
enum
{
kMidiStorageCapacity = 256,
};

struct ShortMessage
{
uint8_t data[3];
};

ShortMessage *fMidiStorage;
volatile uint32_t fMidiCount;
uint32_t fWriterIndex;
Mutex fMutex;
private:
SimpleMidiQueue fQueue;
};
#endif



Loading…
Cancel
Save