Skip to content

Commit a9d6e3d

Browse files
committed
Fix serial MIDI parser to handle Running Status
1 parent 9829331 commit a9d6e3d

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

src/kernel.cpp

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -366,20 +366,38 @@ void CKernel::UpdateSerialMIDI()
366366
switch (mSerialMIDIState)
367367
{
368368
case 0:
369-
// Channel voice message
370-
MIDIRestart:
371-
if (data >= 0x80 && data <= 0xEF)
372-
mSerialMIDIMessage[mSerialMIDIState++] = data;
373-
374-
// System real-time message - single byte, handle immediately
375-
else if (data >= 0xF8)
376-
MIDIPacketHandler(0, &data, 1);
369+
// Is it a status byte?
370+
if (data & 0x80)
371+
{
372+
RestartStatus:
373+
// System real-time message - single byte, handle immediately
374+
if (data >= 0xF8)
375+
MIDIPacketHandler(0, &data, 1);
376+
377+
// System Common or Exclusive
378+
else if (data >= 0xF0 && data <= 0xF7)
379+
{
380+
// Start of SysEx message
381+
if (data == 0xF0)
382+
{
383+
mSerialMIDIState = 4;
384+
mSysExMessage.push_back(data);
385+
}
386+
387+
// Clear status byte
388+
mSerialMIDIMessage[0] = 0;
389+
}
390+
391+
// Channel message
392+
else if (data >= 0x80 && data <= 0xEF)
393+
mSerialMIDIMessage[mSerialMIDIState++] = data;
394+
}
377395

378-
// SysEx
379-
else if (data == 0xF0)
396+
// Data byte, Running Status
397+
else if (mSerialMIDIMessage[0] & 0x80)
380398
{
381-
mSerialMIDIState = 4;
382-
mSysExMessage.push_back(data);
399+
mSerialMIDIState = 2;
400+
mSerialMIDIMessage[1] = data;
383401
}
384402
break;
385403

@@ -391,24 +409,27 @@ void CKernel::UpdateSerialMIDI()
391409
mLogger.Write("midi", LogWarning, "Expected parameter, received status");
392410
LCDLog("MIDI restart");
393411
mSerialMIDIState = 0;
394-
goto MIDIRestart;
412+
goto RestartStatus;
395413
}
396414

397415
mSerialMIDIMessage[mSerialMIDIState++] = data;
398416

399-
// MIDI message is complete if we receive 3 bytes, or 2 bytes if it was a Control/Program change
417+
// MIDI message is complete if we receive 3 bytes
400418
if (mSerialMIDIState == 3)
401419
{
402420
MIDIPacketHandler(0, mSerialMIDIMessage, 3);
403421
mSerialMIDIState = 0;
404422
}
423+
424+
// Or 2 bytes if it's a program change or channel pressure/aftertouch
405425
else if (mSerialMIDIState == 2 && (mSerialMIDIMessage[0] >= 0xC0 && mSerialMIDIMessage[0] <= 0xDF))
406426
{
407427
MIDIPacketHandler(0, mSerialMIDIMessage, 2);
408428
mSerialMIDIState = 0;
409429
}
410430
break;
411431

432+
// SysEx state
412433
case 4:
413434
mSysExMessage.push_back(data);
414435
if (data == 0xF7)

0 commit comments

Comments
 (0)