Browse Source

Fix MIDI status and channel bitwise mixups

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
f9917a95e9
8 changed files with 106 additions and 68 deletions
  1. +20
    -4
      include/midi.hpp
  2. +32
    -32
      src/Core/CV_MIDI.cpp
  3. +2
    -2
      src/Core/MIDICCToCVInterface.cpp
  4. +14
    -14
      src/Core/MIDIToCVInterface.cpp
  5. +5
    -5
      src/Core/MIDITriggerToCVInterface.cpp
  6. +9
    -9
      src/Core/QuadMIDIToCVInterface.cpp
  7. +1
    -1
      src/app/MidiWidget.cpp
  8. +23
    -1
      src/midi.cpp

+ 20
- 4
include/midi.hpp View File

@@ -15,18 +15,30 @@ struct Message {
uint8_t data1 = 0x00;
uint8_t data2 = 0x00;

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

////////////////////
@@ -102,6 +114,7 @@ struct IO {
virtual std::string getDeviceName(int deviceId) = 0;
virtual void setDeviceId(int deviceId) = 0;

virtual std::vector<int> getChannels() = 0;
std::string getChannelName(int channel);
void setChannel(int channel);

@@ -120,6 +133,8 @@ struct Input : IO {
std::vector<int> getDeviceIds() override;
std::string getDeviceName(int deviceId) override;
void setDeviceId(int deviceId) override;
std::vector<int> getChannels() override;

virtual void onMessage(Message message) {}
};

@@ -143,6 +158,7 @@ struct Output : IO {
std::vector<int> getDeviceIds() override;
std::string getDeviceName(int deviceId) override;
void setDeviceId(int deviceId) override;
std::vector<int> getChannels() override;

void sendMessage(Message message);
};


+ 32
- 32
src/Core/CV_MIDI.cpp View File

@@ -45,9 +45,9 @@ struct PolyphonicMidiOutput : midi::Output {
for (int note = 0; note <= 127; note++) {
// Note off
midi::Message m;
m.cmd = 0x8;
m.data1 = note;
m.data2 = 0;
m.setStatus(0x8);
m.setNote(note);
m.setValue(0);
sendMessage(m);
}
}
@@ -71,17 +71,17 @@ struct PolyphonicMidiOutput : midi::Output {
if (changedNote || enabledGate) {
// Note on
midi::Message m;
m.cmd = 0x9;
m.data1 = notes[c];
m.data2 = vels[c];
m.setStatus(0x9);
m.setNote(notes[c]);
m.setValue(vels[c]);
sendMessage(m);
}
if (changedNote || disabledGate) {
// Note off
midi::Message m;
m.cmd = 0x8;
m.data1 = lastNotes[c];
m.data2 = vels[c];
m.setStatus(0x8);
m.setNote(lastNotes[c]);
m.setValue(vels[c]);
sendMessage(m);
}
lastNotes[c] = notes[c];
@@ -94,9 +94,9 @@ struct PolyphonicMidiOutput : midi::Output {
lastAfts[c] = aft;
// Polyphonic key pressure
midi::Message m;
m.cmd = 0xa;
m.data1 = notes[c];
m.data2 = aft;
m.setStatus(0xa);
m.setNote(notes[c]);
m.setValue(aft);
sendMessage(m);
}

@@ -106,9 +106,9 @@ struct PolyphonicMidiOutput : midi::Output {
lastPw = pw;
// Pitch wheel
midi::Message m;
m.cmd = 0xe;
m.data1 = pw & 0x7f;
m.data2 = (pw >> 7) & 0x7f;
m.setStatus(0xe);
m.setNote(pw & 0x7f);
m.setValue((pw >> 7) & 0x7f);
sendMessage(m);
}

@@ -118,9 +118,9 @@ struct PolyphonicMidiOutput : midi::Output {
lastMw = mw;
// CC Mod wheel
midi::Message m;
m.cmd = 0xb;
m.data1 = 0x01;
m.data2 = mw;
m.setStatus(0xb);
m.setNote(0x01);
m.setValue(mw);
sendMessage(m);
}

@@ -131,8 +131,8 @@ struct PolyphonicMidiOutput : midi::Output {
if (clk) {
// Timing clock
midi::Message m;
m.cmd = 0xf;
m.data1 = 0x8;
m.setStatus(0xf);
m.setChannel(0x8);
sendMessage(m);
}
}
@@ -143,9 +143,9 @@ struct PolyphonicMidiOutput : midi::Output {
lastVol = vol;
// CC Volume
midi::Message m;
m.cmd = 0xb;
m.data1 = 0x07;
m.data2 = vol;
m.setStatus(0xb);
m.setNote(0x07);
m.setValue(vol);
sendMessage(m);
}

@@ -155,9 +155,9 @@ struct PolyphonicMidiOutput : midi::Output {
lastPan = pan;
// CC Pan
midi::Message m;
m.cmd = 0xb;
m.data1 = 0x0a;
m.data2 = pan;
m.setStatus(0xb);
m.setNote(0x0a);
m.setValue(pan);
sendMessage(m);
}

@@ -168,8 +168,8 @@ struct PolyphonicMidiOutput : midi::Output {
if (start) {
// Start
midi::Message m;
m.cmd = 0xf;
m.data1 = 0xa;
m.setStatus(0xf);
m.setChannel(0xa);
sendMessage(m);
}
}
@@ -181,8 +181,8 @@ struct PolyphonicMidiOutput : midi::Output {
if (stop) {
// Stop
midi::Message m;
m.cmd = 0xf;
m.data1 = 0xb;
m.setStatus(0xf);
m.setChannel(0xb);
sendMessage(m);
}
}
@@ -194,8 +194,8 @@ struct PolyphonicMidiOutput : midi::Output {
if (cont) {
// Continue
midi::Message m;
m.cmd = 0xf;
m.data1 = 0xc;
m.setStatus(0xf);
m.setChannel(0xc);
sendMessage(m);
}
}


+ 2
- 2
src/Core/MIDICCToCVInterface.cpp View File

@@ -70,10 +70,10 @@ struct MIDICCToCVInterface : Module {
}

void processMessage(midi::Message msg) {
switch (msg.status()) {
switch (msg.getStatus()) {
// cc
case 0xb: {
uint8_t cc = msg.note();
uint8_t cc = msg.getNote();
// Learn
if (learningId >= 0 && values[cc] != msg.data2) {
ccs[learningId] = cc;


+ 14
- 14
src/Core/MIDIToCVInterface.cpp View File

@@ -166,28 +166,28 @@ struct MIDIToCVInterface : Module {
}

void processMessage(midi::Message msg) {
// DEBUG("MIDI: %01x %01x %02x %02x", msg.status(), msg.channel(), msg.note(), msg.value());
// DEBUG("MIDI: %01x %01x %02x %02x", msg.getStatus(), msg.channel(), msg.getNote(), msg.getValue());

switch (msg.status()) {
switch (msg.getStatus()) {
// note off
case 0x8: {
releaseNote(msg.note());
releaseNote(msg.getNote());
} break;
// note on
case 0x9: {
if (msg.value() > 0) {
noteData[msg.note()].velocity = msg.value();
pressNote(msg.note());
if (msg.getValue() > 0) {
noteData[msg.getNote()].velocity = msg.getValue();
pressNote(msg.getNote());
}
else {
// For some reason, some keyboards send a "note on" event with a velocity of 0 to signal that the key has been released.
releaseNote(msg.note());
releaseNote(msg.getNote());
}
} break;
// channel aftertouch
case 0xa: {
uint8_t note = msg.note();
noteData[note].aftertouch = msg.value();
uint8_t note = msg.getNote();
noteData[note].aftertouch = msg.getValue();
} break;
// cc
case 0xb: {
@@ -195,7 +195,7 @@ struct MIDIToCVInterface : Module {
} break;
// pitch wheel
case 0xe: {
pitch = msg.value() * 128 + msg.note();
pitch = msg.getValue() * 128 + msg.getNote();
} break;
case 0xf: {
processSystem(msg);
@@ -205,14 +205,14 @@ struct MIDIToCVInterface : Module {
}

void processCC(midi::Message msg) {
switch (msg.note()) {
switch (msg.getNote()) {
// mod
case 0x01: {
mod = msg.value();
mod = msg.getValue();
} break;
// sustain
case 0x40: {
if (msg.value() >= 64)
if (msg.getValue() >= 64)
pressPedal();
else
releasePedal();
@@ -222,7 +222,7 @@ struct MIDIToCVInterface : Module {
}

void processSystem(midi::Message msg) {
switch (msg.channel()) {
switch (msg.getChannel()) {
// Timing
case 0x8: {
if (clock % divisions[0] == 0) {


+ 5
- 5
src/Core/MIDITriggerToCVInterface.cpp View File

@@ -89,19 +89,19 @@ struct MIDITriggerToCVInterface : Module {
}

void processMessage(midi::Message msg) {
switch (msg.status()) {
switch (msg.getStatus()) {
// note off
case 0x8: {
releaseNote(msg.note());
releaseNote(msg.getNote());
} break;
// note on
case 0x9: {
if (msg.value() > 0) {
pressNote(msg.note(), msg.value());
if (msg.getValue() > 0) {
pressNote(msg.getNote(), msg.getValue());
}
else {
// Many stupid keyboards send a "note on" command with 0 velocity to mean "note release"
releaseNote(msg.note());
releaseNote(msg.getNote());
}
} break;
default: break;


+ 9
- 9
src/Core/QuadMIDIToCVInterface.cpp View File

@@ -258,24 +258,24 @@ struct QuadMIDIToCVInterface : Module {
}

void processMessage(midi::Message msg) {
switch (msg.status()) {
switch (msg.getStatus()) {
// note off
case 0x8: {
releaseNote(msg.note());
releaseNote(msg.getNote());
} break;
// note on
case 0x9: {
if (msg.value() > 0) {
noteData[msg.note()].velocity = msg.value();
pressNote(msg.note());
if (msg.getValue() > 0) {
noteData[msg.getNote()].velocity = msg.getValue();
pressNote(msg.getNote());
}
else {
releaseNote(msg.note());
releaseNote(msg.getNote());
}
} break;
// channel aftertouch
case 0xa: {
noteData[msg.note()].aftertouch = msg.value();
noteData[msg.getNote()].aftertouch = msg.getValue();
} break;
// cc
case 0xb: {
@@ -286,10 +286,10 @@ struct QuadMIDIToCVInterface : Module {
}

void processCC(midi::Message msg) {
switch (msg.note()) {
switch (msg.getNote()) {
// sustain
case 0x40: {
if (msg.value() >= 64)
if (msg.getValue() >= 64)
pressPedal();
else
releasePedal();


+ 1
- 1
src/app/MidiWidget.cpp View File

@@ -112,7 +112,7 @@ struct MidiChannelChoice : LedDisplayChoice {

Menu *menu = createMenu();
menu->addChild(createMenuLabel("MIDI channel"));
for (int channel = -1; channel < 16; channel++) {
for (int channel : midiWidget->midiIO->getChannels()) {
MidiChannelItem *item = new MidiChannelItem;
item->midiIO = midiWidget->midiIO;
item->channel = channel;


+ 23
- 1
src/midi.cpp View File

@@ -30,7 +30,7 @@ void InputDevice::unsubscribe(Input *input) {
void InputDevice::onMessage(Message message) {
for (Input *input : subscribed) {
// Filter channel
if (input->channel < 0 || message.status() == 0xf || message.channel() == input->channel) {
if (input->channel < 0 || message.getStatus() == 0xf || message.getChannel() == input->channel) {
input->onMessage(message);
}
}
@@ -127,6 +127,7 @@ void IO::fromJson(json_t *rootJ) {
////////////////////

Input::Input() {
channel = -1;
// Set first driver as default
if (driverIds.size() >= 1) {
setDriverId(driverIds[0]);
@@ -166,6 +167,14 @@ void Input::setDeviceId(int deviceId) {
}
}

std::vector<int> Input::getChannels() {
std::vector<int> channels;
for (int c = -1; c < 16; c++) {
channels.push_back(c);
}
return channels;
}

void InputQueue::onMessage(Message message) {
// Push to queue
if ((int) queue.size() < queueMaxSize)
@@ -188,6 +197,7 @@ bool InputQueue::shift(Message *message) {
////////////////////

Output::Output() {
channel = 0;
// Set first driver as default
if (driverIds.size() >= 1) {
setDriverId(driverIds[0]);
@@ -227,7 +237,19 @@ void Output::setDeviceId(int deviceId) {
}
}

std::vector<int> Output::getChannels() {
std::vector<int> channels;
for (int c = 0; c < 16; c++) {
channels.push_back(c);
}
return channels;
}

void Output::sendMessage(Message message) {
// Set channel
if (message.getStatus() != 0xf) {
message.setChannel(channel);
}
// DEBUG("sendMessage %02x %02x %02x", message.cmd, message.data1, message.data2);
if (outputDevice) {
outputDevice->sendMessage(message);


Loading…
Cancel
Save