From 874b44e6f374d6aa6ca7497a29d8c452e40cb9fb Mon Sep 17 00:00:00 2001 From: lathoub Date: Sat, 21 Mar 2020 19:51:53 +0100 Subject: [PATCH] Fixed "FML" case: fall down here with an overflown SysEx.. Splitting larger incoming messages into smaller SysEx packets - using an RrtpMidi trick: // first: 0xF0 .... 0xF0 // midlle: 0xF7 .... 0xF0 // last: 0xF7 .... 0xF7 see: https://tools.ietf.org/html/rfc4695#section-3.2 (Understanding this is not part of the original MIDI spec, but does allow for receiving very very large SysEx messages on a small footprint (does require some 'handy' parsing)) SysExMaxSize in Settings can be reduced significatly (16bytes works fine - pending use case) --- src/MIDI.hpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/MIDI.hpp b/src/MIDI.hpp index b35e5fc..9cd234c 100644 --- a/src/MIDI.hpp +++ b/src/MIDI.hpp @@ -711,8 +711,8 @@ inline bool MidiInterface::read(Channel inChannel return false; handleNullVelocityNoteOnAsNoteOff(); + const bool channelMatch = inputFilter(inChannel); - if (channelMatch) launchCallback(); @@ -938,12 +938,34 @@ bool MidiInterface::parse() // Now we are going to check if we have reached the end of the message if (mPendingMessageIndex >= (mPendingMessageExpectedLength - 1)) { - // "FML" case: fall down here with an overflown SysEx.. - // This means we received the last possible data byte that can fit - // the buffer. If this happens, try increasing MidiMessage::sSysExMaxSize. - if (mPendingMessage[0] == SystemExclusive) + // SysEx larger than the allocated buffer size, + // Split SysEx like so: + // first: 0xF0 .... 0xF0 + // midlle: 0xF7 .... 0xF0 + // last: 0xF7 .... 0xF7 + if ((mPendingMessage[0] == SystemExclusiveStart) + || (mPendingMessage[0] == SystemExclusiveEnd)) { - resetInput(); + auto lastByte = mMessage.sysexArray[DefaultSettings::SysExMaxSize - 1]; + mMessage.sysexArray[DefaultSettings::SysExMaxSize - 1] = SystemExclusiveStart; + mMessage.type = SystemExclusive; + + // Get length + mMessage.data1 = DefaultSettings::SysExMaxSize & 0xff; // LSB + mMessage.data2 = byte(DefaultSettings::SysExMaxSize >> 8); // MSB + mMessage.channel = 0; + mMessage.length = DefaultSettings::SysExMaxSize; + mMessage.valid = true; + + // No need to check against the inputChannel, + // SysEx ignores input channel + launchCallback(); + + mMessage.sysexArray[0] = SystemExclusiveEnd; + mMessage.sysexArray[1] = lastByte; + + mPendingMessageIndex = 2; + return false; }