| @@ -29,7 +29,7 @@ struct CCMidiOutput : midi::Output { | |||||
| m.setStatus(0xb); | m.setStatus(0xb); | ||||
| m.setNote(cc); | m.setNote(cc); | ||||
| m.setValue(value); | m.setValue(value); | ||||
| m.frame = frame; | |||||
| m.setFrame(frame); | |||||
| sendMessage(m); | sendMessage(m); | ||||
| } | } | ||||
| @@ -83,7 +83,7 @@ struct CV_CC : Module { | |||||
| else | else | ||||
| return; | return; | ||||
| midiOutput.setFrame(args.frame + APP->engine->getBlockFrames()); | |||||
| midiOutput.setFrame(args.frame); | |||||
| for (int i = 0; i < 16; i++) { | for (int i = 0; i < 16; i++) { | ||||
| int value = (int) std::round(inputs[CC_INPUTS + i].getVoltage() / 10.f * 127); | int value = (int) std::round(inputs[CC_INPUTS + i].getVoltage() / 10.f * 127); | ||||
| @@ -30,7 +30,7 @@ struct GateMidiOutput : midi::Output { | |||||
| m.setStatus(0x8); | m.setStatus(0x8); | ||||
| m.setNote(note); | m.setNote(note); | ||||
| m.setValue(0); | m.setValue(0); | ||||
| m.frame = frame; | |||||
| m.setFrame(frame); | |||||
| sendMessage(m); | sendMessage(m); | ||||
| lastGates[note] = false; | lastGates[note] = false; | ||||
| } | } | ||||
| @@ -47,7 +47,7 @@ struct GateMidiOutput : midi::Output { | |||||
| m.setStatus(0x9); | m.setStatus(0x9); | ||||
| m.setNote(note); | m.setNote(note); | ||||
| m.setValue(vels[note]); | m.setValue(vels[note]); | ||||
| m.frame = frame; | |||||
| m.setFrame(frame); | |||||
| sendMessage(m); | sendMessage(m); | ||||
| } | } | ||||
| else if (!gate && lastGates[note]) { | else if (!gate && lastGates[note]) { | ||||
| @@ -56,7 +56,7 @@ struct GateMidiOutput : midi::Output { | |||||
| m.setStatus(0x8); | m.setStatus(0x8); | ||||
| m.setNote(note); | m.setNote(note); | ||||
| m.setValue(vels[note]); | m.setValue(vels[note]); | ||||
| m.frame = frame; | |||||
| m.setFrame(frame); | |||||
| sendMessage(m); | sendMessage(m); | ||||
| } | } | ||||
| lastGates[note] = gate; | lastGates[note] = gate; | ||||
| @@ -107,7 +107,7 @@ struct CV_Gate : Module { | |||||
| } | } | ||||
| void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
| midiOutput.setFrame(args.frame + APP->engine->getBlockFrames()); | |||||
| midiOutput.setFrame(args.frame); | |||||
| for (int i = 0; i < 16; i++) { | for (int i = 0; i < 16; i++) { | ||||
| int note = learnedNotes[i]; | int note = learnedNotes[i]; | ||||
| @@ -76,7 +76,7 @@ struct CV_MIDI : Module { | |||||
| if (rateLimiterTriggered) | if (rateLimiterTriggered) | ||||
| rateLimiterTimer.time -= rateLimiterPeriod; | rateLimiterTimer.time -= rateLimiterPeriod; | ||||
| midiOutput.setFrame(args.frame + APP->engine->getBlockFrames()); | |||||
| midiOutput.setFrame(args.frame); | |||||
| for (int c = 0; c < inputs[PITCH_INPUT].getChannels(); c++) { | 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); | int vel = (int) std::round(inputs[VEL_INPUT].getNormalPolyVoltage(10.f * 100 / 127, c) / 10.f * 127); | ||||
| @@ -173,7 +173,7 @@ struct MIDI_CV : Module { | |||||
| } | } | ||||
| void processMessage(const midi::Message& msg) { | 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()) { | switch (msg.getStatus()) { | ||||
| // note off | // note off | ||||
| @@ -55,14 +55,12 @@ void InputDevice::onMessage(const Message& message) { | |||||
| contextSet(input->context); | contextSet(input->context); | ||||
| // Set timestamp to now if unset | // Set timestamp to now if unset | ||||
| if (message.frame < 0) { | |||||
| if (message.getFrame() < 0) { | |||||
| double deltaTime = system::getTime() - APP->engine->getBlockTime(); | 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 | // Filter channel if message is not a system MIDI message | ||||
| @@ -282,7 +280,7 @@ static const size_t InputQueue_maxSize = 8192; | |||||
| struct InputQueue_Compare { | struct InputQueue_Compare { | ||||
| bool operator()(const Message& a, const Message& b) { | 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) { | bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) { | ||||
| if (!internal->queue.empty()) { | if (!internal->queue.empty()) { | ||||
| const Message& msg = internal->queue.top(); | const Message& msg = internal->queue.top(); | ||||
| if (msg.frame <= maxFrame) { | |||||
| if (msg.getFrame() <= maxFrame) { | |||||
| *messageOut = msg; | *messageOut = msg; | ||||
| internal->queue.pop(); | internal->queue.pop(); | ||||
| return true; | 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. | // 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. | // 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(); | int futureFrames = 2 * APP->engine->getBlockFrames(); | ||||
| if (msg.frame - maxFrame > futureFrames) { | |||||
| if (msg.getFrame() - maxFrame > futureFrames) { | |||||
| internal->queue.clear(); | internal->queue.clear(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -144,15 +144,18 @@ struct RtMidiOutputDevice : midi::OutputDevice { | |||||
| void sendMessage(const midi::Message& message) override { | void sendMessage(const midi::Message& message) override { | ||||
| // If frame is undefined, send message immediately | // If frame is undefined, send message immediately | ||||
| if (message.frame < 0) { | |||||
| if (message.getFrame() < 0) { | |||||
| sendMessageNow(message); | sendMessageNow(message); | ||||
| return; | return; | ||||
| } | } | ||||
| // Schedule message to be sent by worker thread | // Schedule message to be sent by worker thread | ||||
| MessageSchedule ms; | MessageSchedule ms; | ||||
| ms.message = message; | 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 | // 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; | ms.timestamp = APP->engine->getBlockTime() + deltaTime; | ||||
| std::lock_guard<decltype(mutex)> lock(mutex); | std::lock_guard<decltype(mutex)> lock(mutex); | ||||