Browse Source

Correctly handle MIDI messages with less than 3 bytes.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
b066025ed1
6 changed files with 42 additions and 36 deletions
  1. +10
    -11
      include/midi.hpp
  2. +4
    -0
      src/Core/CV_MIDI.cpp
  3. +7
    -6
      src/Core/MIDI_CC.cpp
  4. +1
    -1
      src/gamepad.cpp
  5. +8
    -6
      src/keyboard.cpp
  6. +12
    -12
      src/rtmidi.cpp

+ 10
- 11
include/midi.hpp View File

@@ -15,33 +15,32 @@ namespace midi {


struct Message {
uint8_t cmd = 0x00;
uint8_t data1 = 0x00;
uint8_t data2 = 0x00;
uint8_t size = 3;
uint8_t bytes[3] = {};

uint8_t getChannel() {
return cmd & 0xf;
return bytes[0] & 0xf;
}
void setChannel(uint8_t channel) {
cmd = (cmd & 0xf0) | (channel & 0xf);
bytes[0] = (bytes[0] & 0xf0) | (channel & 0xf);
}
uint8_t getStatus() {
return (cmd >> 4) & 0xf;
return (bytes[0] >> 4) & 0xf;
}
void setStatus(uint8_t status) {
cmd = (cmd & 0xf) | ((status << 4) & 0xf0);
bytes[0] = (bytes[0] & 0xf) | ((status << 4) & 0xf0);
}
uint8_t getNote() {
return data1 & 0x7f;
return bytes[1] & 0x7f;
}
void setNote(uint8_t note) {
data1 = note & 0x7f;
bytes[1] = note & 0x7f;
}
uint8_t getValue() {
return data2 & 0x7f;
return bytes[2] & 0x7f;
}
void setValue(uint8_t value) {
data2 = value & 0x7f;
bytes[2] = value & 0x7f;
}
};



+ 4
- 0
src/Core/CV_MIDI.cpp View File

@@ -131,6 +131,7 @@ struct PolyphonicMidiOutput : midi::Output {
if (clk) {
// Timing clock
midi::Message m;
m.size = 1;
m.setStatus(0xf);
m.setChannel(0x8);
sendMessage(m);
@@ -168,6 +169,7 @@ struct PolyphonicMidiOutput : midi::Output {
if (start) {
// Start
midi::Message m;
m.size = 1;
m.setStatus(0xf);
m.setChannel(0xa);
sendMessage(m);
@@ -181,6 +183,7 @@ struct PolyphonicMidiOutput : midi::Output {
if (stop) {
// Stop
midi::Message m;
m.size = 1;
m.setStatus(0xf);
m.setChannel(0xb);
sendMessage(m);
@@ -194,6 +197,7 @@ struct PolyphonicMidiOutput : midi::Output {
if (cont) {
// Continue
midi::Message m;
m.size = 1;
m.setStatus(0xf);
m.setChannel(0xc);
sendMessage(m);


+ 7
- 6
src/Core/MIDI_CC.cpp View File

@@ -82,16 +82,17 @@ struct MIDI_CC : Module {

void processCC(midi::Message msg) {
uint8_t cc = msg.getNote();
// Allow CC to be negative if the 8th bit is set.
// The gamepad driver abuses this, for example.
// Cast uint8_t to int8_t
int8_t value = msg.bytes[2];
value = clamp(value, -127, 127);
// Learn
if (learningId >= 0 && values[cc] != msg.data2) {
if (learningId >= 0 && values[cc] != value) {
learnedCcs[learningId] = cc;
learningId = -1;
}
// Allow CC to be negative if the 8th bit is set.
// The gamepad driver abuses this, for example.
// Cast uint8_t to int8_t
int8_t value = msg.data2;
values[cc] = clamp(value, -127, 127);
values[cc] = value;
}

json_t *dataToJson() override {


+ 1
- 1
src/gamepad.cpp View File

@@ -52,7 +52,7 @@ struct InputDevice : midi::InputDevice {
msg.setStatus(0xb);
msg.setNote(i);
// Allow 8th bit to be set
msg.data2 = cc;
msg.bytes[2] = cc;
onMessage(msg);
}
}


+ 8
- 6
src/keyboard.cpp View File

@@ -78,10 +78,11 @@ struct InputDevice : midi::InputDevice {
if (note > 127)
return;

// MIDI note on
midi::Message msg;
msg.cmd = 0x9 << 4;
msg.data1 = note;
msg.data2 = 127;
msg.setStatus(0x9);
msg.setNote(note);
msg.setValue(127);
onMessage(msg);

pressedNotes[key] = note;
@@ -91,10 +92,11 @@ struct InputDevice : midi::InputDevice {
auto it = pressedNotes.find(key);
if (it != pressedNotes.end()) {
int note = it->second;
// MIDI note off
midi::Message msg;
msg.cmd = 0x8 << 4;
msg.data1 = note;
msg.data2 = 127;
msg.setStatus(0x8);
msg.setNote(note);
msg.setValue(127);
onMessage(msg);

pressedNotes.erase(it);


+ 12
- 12
src/rtmidi.cpp View File

@@ -30,17 +30,21 @@ struct RtMidiInputDevice : midi::InputDevice {
}

static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) {
if (!message) return;
if (!userData) return;
if (!message)
return;
if (!userData)
return;

RtMidiInputDevice *midiInputDevice = (RtMidiInputDevice*) userData;
if (!midiInputDevice) return;
if (message->size() < 3) return;
if (!midiInputDevice)
return;

assert(message->size() <= 3);
midi::Message msg;
msg.cmd = (*message)[0];
msg.data1 = (*message)[1];
msg.data2 = (*message)[2];
msg.size = message->size();
for (int i = 0; i < msg.size; i++) {
msg.bytes[i] = (*message)[i];
}
midiInputDevice->onMessage(msg);
}
};
@@ -61,11 +65,7 @@ struct RtMidiOutputDevice : midi::OutputDevice {
}

void sendMessage(midi::Message message) override {
unsigned char msg[3];
msg[0] = message.cmd;
msg[1] = message.data1;
msg[2] = message.data2;
rtMidiOut->sendMessage(msg, 3);
rtMidiOut->sendMessage(message.bytes, message.size);
}
};



Loading…
Cancel
Save