Midi note-off messages not sent during editing

• Sep 24, 2019 - 02:01
Reported version
3.2
Type
Functional
Frequency
Few
Severity
S4 - Minor
Reproducibility
Always
Status
PR created
Regression
No
Workaround
No
Project

Steps to reproduce the behavior:

1) Play notes when editing should be set to "ON"
2) Midi output should be sending midi to any external synth engine of your choice (software or hardware will both have the same result)
3) Add notes to a staff

Resulting behavior:
When adding notes to the staff or editing existing notes, the notes will send note-on messages but do note send any note-off messages, resulting in any connected synth holding the notes forever as a note cluster

Expected behavior:
A midi note-off message should be sent after a period of time as specified in the setting "Default duration" (which is typically set to 300ms)

Please see an earlier post from someone else about this same issue:
https://musescore.org/en/node/288601


Comments

I've been doing some digging on this issue, and this might be an issue with JACK, not with MuseScore.

When playing a single note, MuseScore is set to stop all notes from playing after a short period of time. Seq::startNote(5 arg overload) calls Seq::startNoteTimer(), which then calls Seq::stopNotes().
https://github.com/musescore/MuseScore/blob/3.4/mscore/seq.cpp#L1229

This then queues the putEvent() method of the currently running driver, which for JACK is JackAudio::putEvent().
https://github.com/musescore/MuseScore/blob/3.4/mscore/jackaudio.cpp#L5…

The MIDI specification for stopping all notes is bn (n being the midi channel) 7B, 00.
https://www.midi.org/specifications-old/item/table-1-summary-of-midi-me…

The problem is, MuseScore does exactly what it's supposed to do, JackAudio::putEvent() gets called and sends the right events (through jack_midi_event_reserve()), yet for some reason, this specific message gets lost, but only sometimes. I've gotten the message to send correctly in Visual Studio, while debugging with breakpoints. Maybe an issue with QTimer?

edit: Another problem is that Seq::stopNotes() should send stop to all channels when -1 is passed, yet it only stops channel 0 (1).

edit2: Found the problem. It's not MuseScore, or JACK, it's that All Notes Off is not a well supported MIDI message, at least not with the applications I tried.

I was doing some reading, and it seems modern approach for some devices/applications is to turn off all MIDI notes in a channel iteratively, so I replaced the event in stopNotes() with a for-loop that turns off all 128 notes in a channel, and it works... it's not ideal, but at least it's functioning now. The only thing left to do is fix the -1 channels issue, when that's done I'll submit a PR.

On a related note, I did some experimenting pairing PortMidi output with a virtual MIDI device, created by loopMIDI, and this seems like a much better alternative to JACK for Windows systems. It's easier to setup, and will probably work better with most applications.