Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

need delay to send messages reliably #44

Open
chriswatrous opened this issue Feb 19, 2018 · 5 comments
Open

need delay to send messages reliably #44

chriswatrous opened this issue Feb 19, 2018 · 5 comments
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@chriswatrous
Copy link

chriswatrous commented Feb 19, 2018

Board: Arduino Due
OS: Windows 10

I'm learning how to use this library and I'm having trouble getting messages sent in quick succession to send reliably. It seems I need to add a delay in between each message.

Is this expected behavior? Or is this a bug?

This is what I would expect to work:

#include <MIDIUSB.h>

void noteOn(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
}

void setup() {
}

void loop() {
    noteOn(0, 52, 100);
    noteOn(0, 53, 100);
    noteOn(0, 57, 100);
    noteOn(0, 60, 100);
    MidiUSB.flush();
    delay(200);

    noteOff(0, 52, 100);
    noteOff(0, 53, 100);
    noteOff(0, 57, 100);
    noteOff(0, 60, 100);
    MidiUSB.flush();
    delay(200);
}

But only the first message of each group sends reliably. (recorded in FL Studio):
image

I tried adding a flush after each event:

#include <MIDIUSB.h>

void noteOn(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
    MidiUSB.flush();
}

void noteOff(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
    MidiUSB.flush();
}

void setup() {
}

void loop() {
    noteOn(0, 52, 100);
    noteOn(0, 53, 100);
    noteOn(0, 57, 100);
    noteOn(0, 60, 100);
    delay(200);

    noteOff(0, 52, 100);
    noteOff(0, 53, 100);
    noteOff(0, 57, 100);
    noteOff(0, 60, 100);
    delay(200);
}

Same result:
image

If I add a 50 microsecond delay it works.

#include <MIDIUSB.h>

void noteOn(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
    delayMicroseconds(50);
}

void noteOff(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
    delayMicroseconds(50);
}

void setup() {
}

void loop() {
    noteOn(0, 52, 100);
    noteOn(0, 53, 100);
    noteOn(0, 57, 100);
    noteOn(0, 60, 100);
    MidiUSB.flush();
    delay(200);

    noteOff(0, 52, 100);
    noteOff(0, 53, 100);
    noteOff(0, 57, 100);
    noteOff(0, 60, 100);
    MidiUSB.flush();
    delay(200);
}

image

25 microseconds is not quite enough:
image

Thanks for your help.

@chriswatrous
Copy link
Author

I also looked at the messages in MIDI-OX and it confirmed what I saw in FL Studio.

@facchinm
Copy link
Contributor

Hi @chriswatrous, it is probably related to the USB controller that drops (or, better, doesn't accept) data packets if they are too fast. Due is not our main dev target and its clock almost doubles the Zero family so probably the behaviour was unnoticed until now.

@SorenAndreasen
Copy link

Same issue here, also with a Due and Win 10. Putting a 50 microseconds delay in between each message is better, but it's still not 100% reliable. such a shame

@Helguli
Copy link

Helguli commented Mar 10, 2021

A workaround for this issue is sending multiple event packets at the same time with MidiUSB.write(*buffer, size).

Working code:

void sendNotes(midiEventPacket_t events[], size_t size) {
    uint8_t data[4 * size];
    for (unsigned int i = 0; i < size; i++) {
        data[0 + i * 4] = events[i].header;
        data[1 + i * 4] = events[i].byte1;
        data[2 + i * 4] = events[i].byte2;
        data[3 + i * 4] = events[i].byte3;
    }
    MidiUSB.write(data, 4*size);
}

@ivanmart
Copy link

ivanmart commented Mar 20, 2022

I've tried everything: flush after each sendMIDI, flush after several sendMIDI, delay 500 microseconds, delay 1 millisecond, delay 10 milliseconds. But there was always more or less missing note-off events, though the debug messages stated that sendMIDI method have been invoked. It seems to be the library is not useable for Due at all for some reason.

Update: Even with simple Serial.write and Hairless midi<->serial bridge it works without any glitches, no need any delays... Why would a library won't do that?

@per1234 per1234 added type: imperfection Perceived defect in any part of project topic: code Related to content of the project itself labels Mar 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

No branches or pull requests

6 participants