usbMIDI.read() while or if?

lokki

Well-known member
I have several projects that use usbMIDI.read() and I see both versions in code online, reading out messages in an if statement and in a while loop.. for example:

Code:
  while(usbMIDI.read()) {
      uint8_t type =       usbMIDI.getType();
      uint8_t data1 =       usbMIDI.getData1();
      uint8_t data2 =       usbMIDI.getData2();
      uint8_t channel =     usbMIDI.getChannel();
      uint8_t cable =       usbMIDI.getCable();
    if (midibass >= 0){
    midilist[midibass]->send(type, data1, data2, channel, cable); 
    }
   /* if (tooro >= 0) {
      midilist[tooro]->send(type, data1, data2, channel, cable); 
    } */
    if (type == 0xB0) {
    int dmxChannel = (channel -1)*128 + data1; 
    led_channel(dmxChannel, data2*2);
  
    //update dmx--------------------------------------
 // leds_update();
    }
  }

when is it "better" to change the while to an if statement, or is the while always preferred since it makes sure the buffer gets empty before proceeding? My gut feeling tells me this could stall the rest of my code, so an if (usbMIDI.read()) { //insert code here...} might be preferred if i need the rest of my code to execute every loop on a regular basis. I would be glad for any insights on this..

also is the same true when reading from usb clients in a usbhost situation on the teensy or is while or if preferred in that scenario? for example:
Code:
while (midilist[midibass]->read()) {
      uint8_t type =       midilist[midibass]->getType();
      uint8_t data1 =      midilist[midibass]->getData1();
      uint8_t data2 =      midilist[midibass]->getData2();
      uint8_t channel =    midilist[midibass]->getChannel();
      uint8_t cable =      midilist[midibass]->getCable();
//do something here
 
It's almost always going to depend on your application ... the question is basically "I want to do something with string - what sort should I use, and how long should it be?"

I would recommend you make use of the handlers documented in the "Receiving Messages with Read & Callback Functions" section. That way you're spared reading in all the message parameters and then having a huge switch ... case to handle the different types; the library essentially handles all that for you. The minimal MIDI sketch then boils down to:
C++:
void setup()
{
    // set handlers
}

// handler functions

void loop()
{
    usbMIDI.read();
}
That will handle one message per iteration of loop(), which is "obviously" fine since nothing else needs to be done.

That's also a reasonable approach if you have other stuff you want to do, like implementing controls using analogue reads. If you have a display, that can take a while to update if you don't write your code carefully, e.g. to break up updates into fairly small steps. If things are likely to get complex, there's really no substitute for instrumenting your code from the start, so you keep on top of possible reasons for laggy response to MIDI messages, or indeed anything else.

If your handler functions are guaranteed to run very fast, then there's probably little to no harm in handling all messages once per loop, or a limited number:
Code:
void handleMIDI(int maxCommands)
{
    for (int i = 0; i < maxCommands && usbMIDI.read(); i++)
        ;
}

void loop()
{
    // do stuff, then...
    handleMIDI(10);
    // ...now do more stuff, and ...
    handleMIDI(5);
    // ... and so on
}
 
Back
Top