MIDI Note at position 0 prematurely cut off by all notes off call

I’m having an issue where the first note at position 0 on a MIDI track does not play properly when calling TransportControl::play. It starts to play but then is cut off immediately before its end. When played in a loop, it plays when it wraps around just fine. Other notes play fine also. Monitoring the MIDI, I see that the note is cut off early and an all notes off is also sent:

 14:0   Note on                 0, note 60, velocity 63      // 1) my note on
 14:0   Note off                0, note 60, velocity 0       // 2) note cut off early
 14:0   Control change          0, controller 123, value 0   // 3) all notes off
 14:0   Note off                0, note 60, velocity 0       // 4) my note's actual end

The first note on and last note off are my note. But in between, after the initial note on message, MidiNoteDispatcher::hiResTimerCallback calls MidiOutputDevice::sendNoteOffMessages() and sends the early note off and all notes off messages (messages 2 and 3 above).

If I change the code in MidiNoteDispatcher::hiResTimerCallback from

if (buffer.isAllNotesOff)
	midiOut.sendNoteOffMessages();

to

if (buffer.isAllNotesOff) {
    buffer.isAllNotesOff = false;
    midiOut.sendNoteOffMessages();
}

Then the note plays normally and I get just the midi note on and off messages that I expect:

 14:0   Note on                 0, note 60, velocity 63
 14:0   Note off                0, note 60, velocity 0

I’m not sure if this is the right fix or what other consequences this change might have. I’m looking for a way to make sure the note is not cut off after it starts by MidiOutputDevice::sendNoteOffMessages(). This could perhaps be some race condition or MidiOutputDevice::sendNoteOffMessages() is expected to be called before playing actually starts but is called after since it is called multiple times when starting to play (I counted 6 though it may vary).

Is your note 0 length?

Just looking at the code, it looks like the all-note-off messages should be sent before the note-on event? If that happens, then the note on should happen after the all-note-off message and you won’t get a note-off for the one you’re about to start…

Can you see where your note-on is being added to the buffer?

The note is a 1/16th note. I agree that it makes sense for it to work this way. In the buffer in this function, messagesToSend, I can see my note on and note off and it seems identical on the first play as when it loops. I don’t see anything else in there except SPP, Start, and MIDI Clock messages. I’m not sure where the messages are added to d->buffer the device buffer that fills the messagesToSend buffer though. Not sure where to look for that. Any ideas? I’m basically just adding them to a MidiList and copying them into the MidiClip’s sequence:

auto& seq = midiClip->getSequence();
seq.copyFrom(*list, &undoManager);

The erroneous note off and all notes off are not in either of these buffers but sent directly from MidiOutputDevice::sendNoteOffMessages.