Browse Source

Merge branch 'v2' of github.com:VCVRack/Rack-private into v2

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
3ca8766c39
8 changed files with 84 additions and 29 deletions
  1. +12
    -3
      include/midi.hpp
  2. +1
    -0
      include/settings.hpp
  3. +2
    -6
      src/core/MIDI_CC.cpp
  4. +2
    -6
      src/core/MIDI_CV.cpp
  5. +2
    -6
      src/core/MIDI_Gate.cpp
  6. +2
    -6
      src/core/MIDI_Map.cpp
  7. +62
    -2
      src/midi.cpp
  8. +1
    -0
      src/settings.cpp

+ 12
- 3
include/midi.hpp View File

@@ -1,6 +1,5 @@
#pragma once
#include <vector>
#include <queue>
#include <set>

#include <jansson.h>
@@ -248,10 +247,20 @@ struct Input : Port {
};


/** An Input port that stores incoming MIDI messages and releases them when ready according to their frame timestamp.
*/
struct InputQueue : Input {
int queueMaxSize = 8192;
std::queue<Message> queue;
struct Internal;
Internal* internal;

InputQueue();
~InputQueue();
void onMessage(const Message& message) override;
/** Pops and returns the next message (by setting `messageOut`) if its frame timestamp is `maxFrame` or earlier.
Returns whether a message was returned.
*/
bool tryPop(Message* messageOut, int64_t maxFrame);
size_t size();
};




+ 1
- 0
include/settings.hpp View File

@@ -25,6 +25,7 @@ namespace settings {
extern std::string settingsPath;
extern bool devMode;
extern bool headless;
extern bool isPlugin;

// Persistent state, serialized to settings.json.



+ 2
- 6
src/core/MIDI_CC.cpp View File

@@ -71,13 +71,9 @@ struct MIDI_CC : Module {
}

void process(const ProcessArgs& args) override {
while (!midiInput.queue.empty()) {
const midi::Message& msg = midiInput.queue.front();
// Don't process MIDI message until we've reached its frame.
if (msg.frame > args.frame)
break;
midi::Message msg;
while (midiInput.tryPop(&msg, args.frame)) {
processMessage(msg);
midiInput.queue.pop();
}

int channels = mpeMode ? 16 : 1;


+ 2
- 6
src/core/MIDI_CV.cpp View File

@@ -125,13 +125,9 @@ struct MIDI_CV : Module {
}

void process(const ProcessArgs& args) override {
while (!midiInput.queue.empty()) {
const midi::Message& msg = midiInput.queue.front();
// Don't process MIDI message until we've reached its frame.
if (msg.frame > args.frame)
break;
midi::Message msg;
while (midiInput.tryPop(&msg, args.frame)) {
processMessage(msg);
midiInput.queue.pop();
}

outputs[PITCH_OUTPUT].setChannels(channels);


+ 2
- 6
src/core/MIDI_Gate.cpp View File

@@ -66,13 +66,9 @@ struct MIDI_Gate : Module {
}

void process(const ProcessArgs& args) override {
while (!midiInput.queue.empty()) {
const midi::Message& msg = midiInput.queue.front();
// Don't process MIDI message until we've reached its frame.
if (msg.frame > args.frame)
break;
midi::Message msg;
while (midiInput.tryPop(&msg, args.frame)) {
processMessage(msg);
midiInput.queue.pop();
}

int channels = mpeMode ? 16 : 1;


+ 2
- 6
src/core/MIDI_Map.cpp View File

@@ -82,13 +82,9 @@ struct MIDI_Map : Module {
if (!divider.process())
return;

while (!midiInput.queue.empty()) {
const midi::Message& msg = midiInput.queue.front();
// Don't process MIDI message until we've reached its frame.
if (msg.frame > args.frame)
break;
midi::Message msg;
while (midiInput.tryPop(&msg, args.frame)) {
processMessage(msg);
midiInput.queue.pop();
}

// Step channels


+ 62
- 2
src/midi.cpp View File

@@ -1,5 +1,6 @@
#include <map>
#include <utility>
#include <queue>

#include <midi.hpp>
#include <string.hpp>
@@ -273,13 +274,72 @@ std::vector<int> Input::getChannels() {
return channels;
}

////////////////////
// InputQueue
////////////////////

static const size_t InputQueue_maxSize = 8192;

struct InputQueue_Compare {
bool operator()(const Message& a, const Message& b) {
return a.frame > b.frame;
}
};

struct InputQueue_Queue : std::priority_queue<Message, std::vector<Message>, InputQueue_Compare> {
void reserve(size_t capacity) {
c.reserve(capacity);
}
void clear() {
// Messing with the protected container is dangerous, but completely clearing it should be fine.
c.clear();
}
};

struct InputQueue::Internal {
InputQueue_Queue queue;
};

InputQueue::InputQueue() {
internal = new Internal;
internal->queue.reserve(InputQueue_maxSize);
}

InputQueue::~InputQueue() {
delete internal;
}

void InputQueue::onMessage(const Message& message) {
if ((int) queue.size() >= queueMaxSize)
if (internal->queue.size() >= InputQueue_maxSize)
return;
// Push to queue
queue.push(message);
internal->queue.push(message);
}

bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) {
if (!internal->queue.empty()) {
const Message& msg = internal->queue.top();
if (msg.frame <= maxFrame) {
*messageOut = msg;
internal->queue.pop();
return true;
}

// If next MIDI message is too far in the future, clear the queue.
// This solves the issue of unconsumed messages getting stuck in the future when a DAW rewinds the engine frame.
int futureFrames = 2 * APP->engine->getBlockFrames();
if (msg.frame - maxFrame > futureFrames) {
internal->queue.clear();
}
}
return false;
}

size_t InputQueue::size() {
return internal->queue.size();
}


////////////////////
// Output
////////////////////


+ 1
- 0
src/settings.cpp View File

@@ -18,6 +18,7 @@ namespace settings {
std::string settingsPath;
bool devMode = false;
bool headless = false;
bool isPlugin = false;

std::string token;
bool windowMaximized = false;


Loading…
Cancel
Save