Skip to content
Snippets Groups Projects
Commit daf0004c authored by Andreas Horn's avatar Andreas Horn
Browse files

fixes bug with some keyboards that do send mysterious note-off events

parent b8bc54f3
No related branches found
No related tags found
No related merge requests found
#include "MIDIUSB.h"
#include "MIDIUSB.h" // see https://github.com/arduino-libraries/MIDIUSB
#include <math.h>
#define DEBUG
......@@ -14,10 +14,10 @@
int16_t notes[NUM_VALVES] = {-1, -1, -1};
// array of the length of the tone period required to create the tone
uint16_t period[NUM_VALVES] = {0, 0, 0};
uint16_t periods[NUM_VALVES] = {0, 0, 0};
// array of the current state of the valve pins (for tone periods)
uint8_t state[NUM_VALVES] = {0, 0, 0};
uint8_t states[NUM_VALVES] = {0, 0, 0};
// array for the period timer helpers
uint64_t lastNoteMicros[NUM_VALVES] = {0, 0, 0};
......@@ -66,22 +66,32 @@ uint16_t midi2frq(uint8_t number) {
}
// puts the note into the notes array or removes it if already present
uint8_t putNote(int8_t note) {
int8_t putNote(int8_t note, uint8_t state) {
// set note
for (int8_t i = 0; i < NUM_VALVES; i++) {
if (notes[i] == -1) { // note on
for (uint8_t i = 0; i < NUM_VALVES; i++) {
if (notes[i] == -1 && state == 1) { // note on
notes[i] = note;
return i;
} else if (notes[i] == note) { // note off
notes[i] = -1;
for (int8_t j = i; j < NUM_VALVES - 1; j++) {
} else if (notes[i] == note && state == 0) { // note off
//notes[i] = -1;
for (uint8_t j = i; j < NUM_VALVES - 1; j++) {
notes[j] = notes[j + 1];
periods[j] = periods[j + 1];
states[j] = states[j + 1];
lastNoteMicros[j] = lastNoteMicros[j + 1];
}
notes[NUM_VALVES - 1] = -1;
periods[NUM_VALVES - 1] = 0;
states[NUM_VALVES - 1] = 0;
lastNoteMicros[NUM_VALVES - 1] = 0;
return i;
}
}
if (state == 0) {
return -1;
}
// remove oldest note and shift other notes
for (int8_t i = 0; i < NUM_VALVES - 1; i++) {
notes[i] = notes[i + 1];
......@@ -92,9 +102,10 @@ uint8_t putNote(int8_t note) {
}
void loop() {
// handle USB MIDI IN
midiEventPacket_t rx;
rx = MidiUSB.read();
if (rx.header != 0) {
if (rx.byte1 != 0) {
#ifdef DEBUG
char buffer[256];
sprintf(buffer, "header: 0x%X b1: %d b2: %d b3: %d", rx.header, rx.byte1,
......@@ -102,24 +113,24 @@ void loop() {
Serial.println(buffer);
#endif
if ((rx.header & 0x09) == 0x09) { // handle note on
uint8_t noteIdx = putNote(rx.byte2);
if ((rx.byte1 & 0xF0) == 0x90 && rx.byte3 > 0) { // handle note on
int8_t noteIdx = putNote(rx.byte2, 1);
uint16_t frq = midi2frq(rx.byte2);
period[noteIdx] = 1000000 / frq / 2;
periods[noteIdx] = 1000000 / frq / 2;
#ifdef DEBUG
Serial.println("ONNNNNNN " + String(rx.byte2) + " @ " + String(noteIdx));
#endif
} else if ((rx.header & 0x08) == 0x08) { // handle note off
} else if ((rx.byte1 & 0xF0) == 0x80 || ((rx.byte1 & 0xF0) == 0x90 && rx.byte3 == 0)) { // handle note off
#ifdef DEBUG
int8_t idx = 0;
#endif
for (int8_t i = 0; i < NUM_VALVES; i++) {
if (notes[i] != -1 && notes[i] == rx.byte2) {
putNote(rx.byte2);
period[i] = 0;
putNote(rx.byte2, 0);
//periods[i] = 0;
#ifdef DEBUG
idx = i;
......@@ -147,10 +158,10 @@ void loop() {
// check for notes that require attention
for (uint8_t i = 0; i < NUM_VALVES; i++) {
if (lastNoteMicros[i] + period[i] < nowMicros && notes[i] != -1) {
if (lastNoteMicros[i] + periods[i] < nowMicros && notes[i] != -1) {
lastNoteMicros[i] = nowMicros;
state[i] ^= 1;
digitalWrite(valves[i], state[i]);
states[i] ^= 1;
digitalWrite(valves[i], states[i]);
} else if (notes[i] == -1) { // be sure to end notes that should be ended
digitalWrite(valves[i], LOW);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment