diff --git a/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h b/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h index fa8080fa42..c7f7f4f63a 100644 --- a/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h +++ b/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h @@ -33,79 +33,68 @@ namespace juce class MidiDataConcatenator { public: - //============================================================================== MidiDataConcatenator (int initialBufferSize) - : pendingData ((size_t) initialBufferSize) + : pendingSysexData ((size_t) initialBufferSize) { } void reset() { - pendingBytes = 0; - runningStatus = 0; - pendingDataTime = 0; + currentMessageLen = 0; + pendingSysexSize = 0; + pendingSysexTime = 0; } template void pushMidiData (const void* inputData, int numBytes, double time, UserDataType* input, CallbackType& callback) { - const uint8* d = static_cast (inputData); + auto d = static_cast (inputData); while (numBytes > 0) { - if (pendingBytes > 0 || d[0] == 0xf0) + auto nextByte = *d; + + if (pendingSysexSize != 0 || nextByte == 0xf0) { processSysex (d, numBytes, time, input, callback); - runningStatus = 0; + currentMessageLen = 0; + continue; } - else - { - int len = 0; - uint8 data[3]; - - while (numBytes > 0) - { - // If there's a realtime message embedded in the middle of - // the normal message, handle it now.. - if (*d >= 0xf8 && *d <= 0xfe) - { - callback.handleIncomingMidiMessage (input, MidiMessage (*d++, time)); - --numBytes; - } - else - { - if (len == 0 && *d < 0x80 && runningStatus >= 0x80) - data[len++] = runningStatus; - - data[len++] = *d++; - --numBytes; - const uint8 firstByte = data[0]; + ++d; + --numBytes; - if (firstByte < 0x80 || firstByte == 0xf7) - { - len = 0; - break; // ignore this malformed MIDI message.. - } + if (nextByte >= 0xf8 && nextByte <= 0xfe) // realtime message + { + callback.handleIncomingMidiMessage (input, MidiMessage (nextByte, time)); + // These can be embedded in the middle of a normal message, so we won't + // reset the currentMessageLen here. + continue; + } - if (len >= MidiMessage::getMessageLengthFromFirstByte (firstByte)) - break; - } + if (nextByte < 0x80) + { + if (currentMessageLen == 3) + { + currentMessageLen = 0; // message is too long - abandon it and start again with the next byte + continue; } - if (len > 0) - { - int used = 0; - const MidiMessage m (data, len, used, 0, time); + currentMessage[currentMessageLen++] = nextByte; + } + else + { + currentMessage[0] = nextByte; + currentMessageLen = 1; + } - if (used <= 0) - break; // malformed message.. + auto expectedLength = MidiMessage::getMessageLengthFromFirstByte (currentMessage[0]); - jassert (used == len); - callback.handleIncomingMidiMessage (input, m); - runningStatus = data[0]; - } + if (expectedLength == currentMessageLen) + { + callback.handleIncomingMidiMessage (input, MidiMessage (currentMessage, expectedLength)); + currentMessageLen = 1; // reset, but leave the first byte to use as the running status byte } } } @@ -117,22 +106,22 @@ private: { if (*d == 0xf0) { - pendingBytes = 0; - pendingDataTime = time; + pendingSysexSize = 0; + pendingSysexTime = time; } - pendingData.ensureSize ((size_t) (pendingBytes + numBytes), false); - uint8* totalMessage = static_cast (pendingData.getData()); - uint8* dest = totalMessage + pendingBytes; + pendingSysexData.ensureSize ((size_t) (pendingSysexSize + numBytes), false); + auto totalMessage = static_cast (pendingSysexData.getData()); + auto dest = totalMessage + pendingSysexSize; do { - if (pendingBytes > 0 && *d >= 0x80) + if (pendingSysexSize > 0 && *d >= 0x80) { if (*d == 0xf7) { *dest++ = *d++; - ++pendingBytes; + ++pendingSysexSize; --numBytes; break; } @@ -145,7 +134,7 @@ private: } else { - pendingBytes = 0; + pendingSysexSize = 0; int used = 0; const MidiMessage m (d, numBytes, used, 0, time); @@ -162,30 +151,32 @@ private: else { *dest++ = *d++; - ++pendingBytes; + ++pendingSysexSize; --numBytes; } } while (numBytes > 0); - if (pendingBytes > 0) + if (pendingSysexSize > 0) { - if (totalMessage [pendingBytes - 1] == 0xf7) + if (totalMessage [pendingSysexSize - 1] == 0xf7) { - callback.handleIncomingMidiMessage (input, MidiMessage (totalMessage, pendingBytes, pendingDataTime)); - pendingBytes = 0; + callback.handleIncomingMidiMessage (input, MidiMessage (totalMessage, pendingSysexSize, pendingSysexTime)); + pendingSysexSize = 0; } else { - callback.handlePartialSysexMessage (input, totalMessage, pendingBytes, pendingDataTime); + callback.handlePartialSysexMessage (input, totalMessage, pendingSysexSize, pendingSysexTime); } } } - MemoryBlock pendingData; - double pendingDataTime = 0; - int pendingBytes = 0; - uint8 runningStatus = 0; + uint8 currentMessage[3] = {}; + int currentMessageLen = 0; + + MemoryBlock pendingSysexData; + double pendingSysexTime = 0; + int pendingSysexSize = 0; JUCE_DECLARE_NON_COPYABLE (MidiDataConcatenator) };