Midi NoteOn Velocity 0 wrong channel

I’ve got midi working fine with devices that use NoteOn and NoteOff message types. However, when I use a device that sends NoteOn Velocity 0 instead of NoteOff, I have problems. I see there is a if statement in midi_parser.cpp on line 143 that appears to handle this case:

//velocity 0 NoteOns are NoteOffs
                if(running_status_ == NoteOn && incoming_message_.data[1] == 0)
                {
                    incoming_message_.type = NoteOff;
                }

However, when I send midi data that uses NoteOn Velocity 0 for note offs, I find that, while they do get parsed as NoteOffs, I get the wrong channel on NoteOff messages from my program:

// Listen to MIDI for new changes
         midi.Listen();

         // When there are messages waiting in the queue...
         while (midi.HasEvents()) {
             // Pull the oldest one from the list...
             auto msg = midi.PopEvent();
             /* if(msg.channel != midiChannel){
                break;
             } */
             switch (msg.type) {
                 case NoteOn: {
                    auto note_msg = msg.AsNoteOn();
                    voiceManager.OnNoteOn(note_msg.note, note_msg.velocity);  
                    mLog(MIDI, "on channel: %d", note_msg.channel);
                    break;
                 }
                 case NoteOff:{
                    auto note_msg = msg.AsNoteOff();
                    voiceManager.OnNoteOff(note_msg.note, note_msg.velocity);
                    mLog(MIDI, "off channel: %d", note_msg.channel);
                    break;
                 }
                 
                 default:
                     break;
             }
         }

You can see I ran into this when I tried to add a midi channel filter (commented out). With the usual midi device (proper NoteOffs sent) I would get this output:

on channel: 3
off channel: 3
on channel: 3
off channel: 3
on channel: 3
off channel: 3

etc.

But with a velocity 0 noteons I get this:

on channel: 3
off channel: 8
on channel: 8
off channel: 8
on channel: 3
off channel: 8
on channel: 3
off channel: 8
on channel: 8
off channel: 8
on channel: 3
off channel: 8
on channel: 3
off channel: 8
on channel: 8

You’ll notice that not only do the off notes have the wrong channel, but something gets mixed up enough to occasionally assign the wrong channel to note ons too.

I would say this is a bug with libDaisy but I wanted to get some feedback here first before I just submit an issue and hope.

I tried to debug the midi parser class but all I can see as being different when I use velocity 0 NoteOns instead of NoteOffs is the that line 143. I thought the channel might be getting reset there but this fix attempt changes nothing:

                //velocity 0 NoteOns are NoteOffs
                if(running_status_ == NoteOn && incoming_message_.data[1] == 0)
                {
                    int channelWas = incoming_message_.channel;
                    incoming_message_.type = NoteOff;
                    incoming_message_.channel = channelWas;
                }

I don’t to rule out its something in my code but I can’t see I’ve done anything too crazy here and it all seems isolated to the midi code I pasted from my project.

Please let me know what you think. Thank you.

Looks from here like libDaisy is (wrongly) only handling ‘note on velocity 0’ for Running Status.

Do you mean to change it to something like this? To make the handling more universal?

//velocity 0 NoteOns are NoteOffs
                if(incoming_message_.type == NoteOn && incoming_message_.data[1] == 0)
                {
                    incoming_message_.type = NoteOff;
                }

Midi channels still coming in wrong with that applied. I’m probably not understanding

I’m not suggesting a solution, but libDaisy looks wrong on this.
It might be as simple as you suggest. Or might not. I haven’t studied the parser code.

1 Like

Ah I have found the issue. There is nothing wrong with the midi parser per se. I was sending midi from a device that also sends midi clock. And I was using a different device for the note off testing which doesn’t send clock. It is stated in the MidiEvent.h file that only 3-byte messages can be handled at this time. Clock is a 1-byte message so the parser was getting confused. Now to figure out how to block midi clock messages. However, midi clock should definitely be supported.

And assuming that ‘velocity 0 = note off’ is only for Running Status is still wrong.

It actually works fine with treating velocity 0 note ons as note offs as long as there isn’t any clock in the midi signal. Though it didn’t seem as though my “fix” after your first comment hampered its ability to do this anyways. So maybe just a strange choice of variable to check but its doing its job. I made an issue about clock in though. I think clock in is actually supported? But it corrupts midi in in any case

Ah, I see now. That’s why I needed to read it more carefully, since running_status_ always contains the most recent Channel Voice or Channel Mode Status byte.