Is it possible for usbMIDI.sendNoteOff() to fail?

Status
Not open for further replies.

yeahtuna

Well-known member
When recording lots of MIDI data (1 packet / 5 ms or so) in Cubase, occasionally a NoteOff message will be missing which results in very long notes that never end until recording stops.

I've been able to confirm that sendNoteOff() is being called for every sendNoteOn(), so I reason that the issue has to be in some very low level USB code.

Is there some sort of low level buffer that can get filled such that there's no room left for the NoteOff packet? Where might I look to troubleshoot this?
 
If an incoming NoteOff is missed you get a "stuck" note and is easy to hear when you get one.

If some other Midi message say a NoteOff or a CC is missed then you may not notice it unless you go looking.

As far as Midi is concerned, a DAW, like a hardware Synth needs to proccess incoming messages wrt the Midi "heartbeat" so messages may get missed if they arrive too fast.
 
In most applications you certainly would hear a stuck note. In my application it's a drum trigger to MIDI interface, so you don't hear the problem because of the relatively short decay of drum sounds.

A lot of traffic (MIDI /HID) is moving in and out of my device. I'll try to reduce that and hopefully the issue goes away.
 
Its a bit of a design omission with MIDI I think - they probably should have specified a version of aftertouch
message to mean "not released yet", and added a time-out for noteOn - this would have reduced the
impact of the problem of missing noteOff's.
 
I think what's actually happening, is that two NoteOn messages are being sent. Here's a look at the data recorded by Cubase:
midiOverlapped.png

And then if I move the overlapped MIDI events, you can see that there are two at exactly the same moment.
midiOverlapped2.png

Again, I've already confirmed that usbMIDI.sendNoteOff() is being called for every call to usbMIDI.sendNoteOn(). Furthermore, I'm also calling MIDI.sendNoteOff() and MIDI.sendNoteOn() at the same time, and the UART MIDI does not show this duplicated noteOn message.
 
Here's the code I use to ensure that my code is called usbMIDI.sendNoteOff() for every usbMIDI.sendNoteOn(). If a double NoteOn message is sent from within my code, the device should stop sending NoteOn messages, which of course isn't happening in my tests.
Code:
   uint8_t doubleNoteOnDetected = 0;
   uint8_t noteIsOn[256];

   void sendNoteOff(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) 
   {
        noteIsOn[note] = 0;
	send(0x80, note, velocity, channel, cable);
   }

   void sendNoteOn(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) __attribute__((always_inline))
   {		
	if (noteIsOn[note]) doubleNoteOnDetected = 1;
	noteIsOn[note] = 1;

	if (doubleNoteOnDetected) return;

	send(0x90, note, velocity, channel, cable);
   }
 
Actaully, with a little more effort, I was able to reproduce the issue. The problem seems to be with usbMIDI.send_now(). If I remove that call, there are no issues. Here's the simplest sketch to reproduce the problem. The extra NoteOn message typically comes every 30 seconds or so.

Code:
int nextStartWait = 0;
int noteLength = 0;
bool noteIsOn = false;

elapsedMicros timer;

void setup() {

}

void loop() {

  if (!noteIsOn && timer > nextStartWait) {

    nextStartWait = random(100,10000);
    noteLength = random(5000, 35000);

    usbMIDI.sendNoteOn(35, 5, 10);
    usbMIDI.send_now();
    noteIsOn = true;
    timer = 0;
  }

  if (noteIsOn && timer > noteLength) {
    usbMIDI.sendNoteOff(35, 5, 10);
    noteIsOn = false;
    timer = 0;
  }
}
 
Status
Not open for further replies.
Back
Top