Browse Source

Delay output MIDI message by an Engine block in the MIDI driver, instead of in CV-MIDI etc.

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
59facf4ced
6 changed files with 21 additions and 20 deletions
  1. +2
    -2
      src/core/CV_CC.cpp
  2. +4
    -4
      src/core/CV_Gate.cpp
  3. +1
    -1
      src/core/CV_MIDI.cpp
  4. +1
    -1
      src/core/MIDI_CV.cpp
  5. +8
    -10
      src/midi.cpp
  6. +5
    -2
      src/rtmidi.cpp

+ 2
- 2
src/core/CV_CC.cpp View File

@@ -29,7 +29,7 @@ struct CCMidiOutput : midi::Output {
m.setStatus(0xb);
m.setNote(cc);
m.setValue(value);
m.frame = frame;
m.setFrame(frame);
sendMessage(m);
}

@@ -83,7 +83,7 @@ struct CV_CC : Module {
else
return;

midiOutput.setFrame(args.frame + APP->engine->getBlockFrames());
midiOutput.setFrame(args.frame);

for (int i = 0; i < 16; i++) {
int value = (int) std::round(inputs[CC_INPUTS + i].getVoltage() / 10.f * 127);


+ 4
- 4
src/core/CV_Gate.cpp View File

@@ -30,7 +30,7 @@ struct GateMidiOutput : midi::Output {
m.setStatus(0x8);
m.setNote(note);
m.setValue(0);
m.frame = frame;
m.setFrame(frame);
sendMessage(m);
lastGates[note] = false;
}
@@ -47,7 +47,7 @@ struct GateMidiOutput : midi::Output {
m.setStatus(0x9);
m.setNote(note);
m.setValue(vels[note]);
m.frame = frame;
m.setFrame(frame);
sendMessage(m);
}
else if (!gate && lastGates[note]) {
@@ -56,7 +56,7 @@ struct GateMidiOutput : midi::Output {
m.setStatus(0x8);
m.setNote(note);
m.setValue(vels[note]);
m.frame = frame;
m.setFrame(frame);
sendMessage(m);
}
lastGates[note] = gate;
@@ -107,7 +107,7 @@ struct CV_Gate : Module {
}

void process(const ProcessArgs& args) override {
midiOutput.setFrame(args.frame + APP->engine->getBlockFrames());
midiOutput.setFrame(args.frame);

for (int i = 0; i < 16; i++) {
int note = learnedNotes[i];


+ 1
- 1
src/core/CV_MIDI.cpp View File

@@ -76,7 +76,7 @@ struct CV_MIDI : Module {
if (rateLimiterTriggered)
rateLimiterTimer.time -= rateLimiterPeriod;

midiOutput.setFrame(args.frame + APP->engine->getBlockFrames());
midiOutput.setFrame(args.frame);

for (int c = 0; c < inputs[PITCH_INPUT].getChannels(); c++) {
int vel = (int) std::round(inputs[VEL_INPUT].getNormalPolyVoltage(10.f * 100 / 127, c) / 10.f * 127);


+ 1
- 1
src/core/MIDI_CV.cpp View File

@@ -173,7 +173,7 @@ struct MIDI_CV : Module {
}

void processMessage(const midi::Message& msg) {
// DEBUG("MIDI: %ld %s", msg.frame, msg.toString().c_str());
// DEBUG("MIDI: %ld %s", msg.getFrame(), msg.toString().c_str());

switch (msg.getStatus()) {
// note off


+ 8
- 10
src/midi.cpp View File

@@ -55,14 +55,12 @@ void InputDevice::onMessage(const Message& message) {
contextSet(input->context);

// Set timestamp to now if unset
if (message.frame < 0) {
if (message.getFrame() < 0) {
double deltaTime = system::getTime() - APP->engine->getBlockTime();
int deltaFrames = std::floor(deltaTime * APP->engine->getSampleRate());
int64_t nextBlockFrame = APP->engine->getBlockFrame() + APP->engine->getBlockFrames();
msg.frame = nextBlockFrame + deltaFrames;
}
else {
msg.frame = message.frame;
int64_t deltaFrames = std::floor(deltaTime * APP->engine->getSampleRate());
// Delay message by current Engine block size
deltaFrames += APP->engine->getBlockFrames();
msg.setFrame(APP->engine->getBlockFrame() + deltaFrames);
}

// Filter channel if message is not a system MIDI message
@@ -282,7 +280,7 @@ static const size_t InputQueue_maxSize = 8192;

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

@@ -319,7 +317,7 @@ void InputQueue::onMessage(const Message& message) {
bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) {
if (!internal->queue.empty()) {
const Message& msg = internal->queue.top();
if (msg.frame <= maxFrame) {
if (msg.getFrame() <= maxFrame) {
*messageOut = msg;
internal->queue.pop();
return true;
@@ -328,7 +326,7 @@ bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) {
// 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) {
if (msg.getFrame() - maxFrame > futureFrames) {
internal->queue.clear();
}
}


+ 5
- 2
src/rtmidi.cpp View File

@@ -144,15 +144,18 @@ struct RtMidiOutputDevice : midi::OutputDevice {

void sendMessage(const midi::Message& message) override {
// If frame is undefined, send message immediately
if (message.frame < 0) {
if (message.getFrame() < 0) {
sendMessageNow(message);
return;
}
// Schedule message to be sent by worker thread
MessageSchedule ms;
ms.message = message;
int64_t deltaFrames = message.getFrame() - APP->engine->getBlockFrame();
// Delay message by current Engine block size
deltaFrames += APP->engine->getBlockFrames();
// Compute time in next Engine block to send message
double deltaTime = (message.frame - APP->engine->getBlockFrame()) * APP->engine->getSampleTime();
double deltaTime = deltaFrames * APP->engine->getSampleTime();
ms.timestamp = APP->engine->getBlockTime() + deltaTime;

std::lock_guard<decltype(mutex)> lock(mutex);


Loading…
Cancel
Save