The switch statement is faster and to me it just looks cleaner than a cascade of ifs .
Here is the call stack that is run within each of the if branches:
msg.isWhatever() -> getRawData() -> getData() -> isHeapAllocated()
I would prefer to fetch the status only once at the start of the branching statement.
After some time you’ll probably find out that a noteOff might be disguised as noteOn w/ velocity 0 or you’ll find it wise to also check for isAllSoundOff or isAllNotesOff messages or endoftrack messages or isSustainPedalOn or any other message that you need to check additional bytes from getRawData() and then your switch statement won’t no longer look cleaner than cascaded if/else statements. Not to mention the increased chance for errors…
And bearing in mind that audio processing is done at 44 100 times per second (or even more), you’ll have to play really, really fast midi to notice any benefits from your switch optimisation. If there are any at all that is, after the compiler have optimised the code.
Both the if and switch functions produce identical code, at least at -O3, using clang and gcc. Of course, the above example is all inlined, but the MidiMessage code should be optimised away by modern compilers. Even isHeapAllocated() should be a non-issue unless you have significant sysex data interleaving with your note and controller data since the branch predictor should corectly predict that isHeapAllocated() is almost always false.