lathoub / Arduino-AppleMIDI-Library

Send and receive MIDI messages over Ethernet (rtpMIDI or AppleMIDI)
Other
306 stars 66 forks source link

Teensy 4.1 dropping info when reading from multiple channels. #144

Closed glasscake closed 2 years ago

glasscake commented 2 years ago

Describe your project and what you expect to happen:

I'm using a single teensy 4.1 to read two midi channels so that I can control an instrument that has duplicate keys individually. Channel 3 controls the right-hand side channel 4 controls the left; the instrument overlaps in midi notes 53-81. The desired effect is when the teensy get a midi command to play the right-hand midi 55 key only the right-hand plays key 55 vise versa.

Describe your problem (what does not work):

When running my code with channel 3 I get flawless execution and fast response. After I uncomment reading channels 4 & 3 I get delayed readings, dropped commands, and crashes.

Steps to reproduce

I run a midi file that turns on some note every second for a second (ie note 55) and I report in a serial output what was received. when running with just reading channel 3 every note comes in. when running the code with both channels 3/4 I get a random assortment of note on/off. it is not consistent from what I can tell. I never get any additional note on or offs I only lose/drop commands. This midi file does not have any information on ch 4 other than control changes.

Comments:

I couldn't find anything else like this but i did find this thread: inspiredacoustics.com/en/MIDI_note_numbers_and_center_frequencies would this be the appropriate solution? I'd prefer to have a single instance and read separate channels

Code: //inclusions

include

include

include

//end inclusions byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEC}; byte ip[] = {169,254,142,145};

APPLEMIDI_CREATE_INSTANCE(EthernetUDP, MIDI, "Accordion", 5004);

define RHC 3 //right hand channel

define LHC 4 //left hand channel

elapsedMillis CurrentMillis;

void setup() { Serial.begin(115200); Ethernet.begin(mac, ip); MIDI.begin(); //setup handlers for RTP midi commands MIDI.setHandleNoteOff(MidiNoteOff); MIDI.setHandleNoteOn(MidiNoteOn); MIDI.setHandleControlChange(MidiControlChange); }

void loop() { //start loop MIDI.read(RHC); //read any midi messages on the third channel in the que for the piano/right hand MIDI.read(LHC); //Read any midi messages on the fourth channel in the que for the bass/left hand //end loop }

void MidiNoteOn(byte channel, byte note, byte velocity) //function called when receving a note { Serial.print("CT:");Serial.print(CurrentMillis);Serial.print(" MidiNoteOn: ");Serial.print(channel);Serial.print(", ");Serial.println(note); }

void MidiNoteOff(byte channel, byte note, byte velocity) //function called when ending a note { Serial.print("CT:");Serial.print(CurrentMillis);Serial.print(" MidiNoteOff: ");Serial.print(channel);Serial.print(", ");Serial.println(note); }

void MidiControlChange(byte channel, byte control, byte value) //other midi commands { Serial.print("CT:");Serial.print(CurrentMillis);Serial.print("CH: ");Serial.print(channel);Serial.print(" control: ");Serial.print(control);Serial.print(" value: ");Serial.println(value); }

attached is the serial output I did not get a log.txt from RTPmidi Serial OUt.txt

also since i am using a teensy i have to use the "native ethernet" wrapper for the ethernet library. Ive done the enable large buffer but it also has some different definitions in it. Is there any way to check if it is compiling with the larger buffer?

native eth.txt

Arduino file: PlayerAccordion.txt

lathoub commented 2 years ago

Hi @glasscake Thank you for the elaborate description, much appreciated.

I believe your issues is with the multiple reads from channel 3 and 4. A single read, without the channel will solve your issue.

Can you try:

//start loop
MIDI.read(RHC); //read any midi messages on the third channel in the que for the piano/right hand
MIDI.read(LHC); //Read any midi messages on the fourth channel in the que for the bass/left hand
//end loop

replace with

//start loop
MIDI.read();
//end loop

reason:

Your first read(RHC), the inputFilter will ignore incoming notes from LHC, the second read will read notes that came in after the previous read.

Solution:

  1. Replace double read with a single read as indicated above
  2. Put an if-statement in your MidiNoteOn/MidiNoteOff function to put the notes in the queue for piano and bass.
  3. Also, use MIDI.begin(MIDI_CHANNEL_OMNI);, in stead of MIDI.begin(); (By default, the underlying lib will listen to channel 1)

Let me know if this helps. Good luck!

glasscake commented 2 years ago

I will get through this later tonight and let you know. Will reading all of the channels cause buffer overflows? Some of my midi files will have upwards of 6 channels.

lathoub commented 2 years ago

Very good - let me know.

Will reading all of the channels cause buffer overflows?

No, buffers will be fine, the teensy 4.1 your UDP buffers are large enough (with the W5500 you have to be careful, see here)

glasscake commented 2 years ago

The above fix works flawlessly, thank you very much.