From a8b6c0e12ffd87fac58c2ff39b3efacd28ba0bca Mon Sep 17 00:00:00 2001 From: probonopd Date: Sun, 11 May 2025 20:34:05 +0200 Subject: [PATCH] MIDI message reassemby; we can play notes over rtpMIDI again! --- src/mididevice.cpp | 4 --- src/serialmididevice.cpp | 19 ++++++++---- src/udpmididevice.cpp | 67 +++++++++++++++++++++++++++++++--------- src/udpmididevice.h | 4 +++ 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 09d2c50..7f7d388 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -238,12 +238,8 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign // Handle MiniDexed performance SysEx messages if (pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN && pMessage[1] == 0x7D ) { - LOGNOTE("MiniDexed SysEx handler entered, nLength=%u", nLength); - // Update: Pass m_pSynthesizer to handle_performance_sysex for synth/GUI update handle_performance_sysex(pMessage, this, m_pSynthesizer, nCable); return; - } else { - LOGNOTE("MiniDexed SysEx handler NOT entered, nLength=%u", nLength); } // Master Volume is set using a MIDI SysEx message as follows: diff --git a/src/serialmididevice.cpp b/src/serialmididevice.cpp index 239cfd6..3c97aac 100644 --- a/src/serialmididevice.cpp +++ b/src/serialmididevice.cpp @@ -85,15 +85,22 @@ void CSerialMIDIDevice::Process (void) m_SysExLen = 0; } if (m_SysExActive) { - if (m_SysExLen < MAX_MIDI_MESSAGE) { - m_SysExBuffer[m_SysExLen++] = uchData; - } - if (uchData == 0xF7 || m_SysExLen >= MAX_MIDI_MESSAGE) { - MIDIMessageHandler(m_SysExBuffer, m_SysExLen, 0); + if ((uchData & 0x80) && uchData != 0xF0 && uchData != 0xF7) { + // Abort SysEx on new status byte (except 0xF0/0xF7) m_SysExActive = false; m_SysExLen = 0; + // Process this byte as normal MIDI below + } else { + if (m_SysExLen < MAX_MIDI_MESSAGE) { + m_SysExBuffer[m_SysExLen++] = uchData; + } + if (uchData == 0xF7 || m_SysExLen >= MAX_MIDI_MESSAGE) { + MIDIMessageHandler(m_SysExBuffer, m_SysExLen, 0); + m_SysExActive = false; + m_SysExLen = 0; + } + if (m_SysExActive) continue; } - continue; } // System Real Time messages may appear anywhere in the byte stream, so handle them specially diff --git a/src/udpmididevice.cpp b/src/udpmididevice.cpp index 57b87c3..f656f2e 100644 --- a/src/udpmididevice.cpp +++ b/src/udpmididevice.cpp @@ -76,6 +76,35 @@ boolean CUDPMIDIDevice::Initialize (void) return true; } +void CUDPMIDIDevice::UdpMidiReassembly(uint8_t byte, unsigned cable) { + // System Real Time messages (single byte) + if (byte == 0xF8 || byte == 0xFA || byte == 0xFB || byte == 0xFC || byte == 0xFE || byte == 0xFF) { + MIDIMessageHandler(&byte, 1, cable); + return; + } + // Status byte + if ((byte & 0x80) == 0x80 && (byte & 0xF0) != 0xF0) { + m_udpMidiMsg[0] = byte; + m_udpMidiState = 1; + return; + } + // Data byte + if (m_udpMidiState > 0) { + m_udpMidiMsg[m_udpMidiState++] = byte; + if ((m_udpMidiMsg[0] & 0xE0) == 0xC0 || (m_udpMidiMsg[0] & 0xF0) == 0xD0) { + // Program Change or Channel Pressure (2 bytes) + if (m_udpMidiState == 2) { + MIDIMessageHandler(m_udpMidiMsg, 2, cable); + m_udpMidiState = 0; + } + } else if (m_udpMidiState == 3) { + // All other channel messages (3 bytes) + MIDIMessageHandler(m_udpMidiMsg, 3, cable); + m_udpMidiState = 0; + } + } +} + // Methods to handle MIDI events void CUDPMIDIDevice::OnAppleMIDIDataReceived(const u8* pData, size_t nSize) @@ -87,17 +116,22 @@ void CUDPMIDIDevice::OnAppleMIDIDataReceived(const u8* pData, size_t nSize) m_SysExLen = 0; } if (m_SysExActive) { - if (m_SysExLen < MAX_MIDI_MESSAGE) { - m_SysExBuffer[m_SysExLen++] = byte; - } - if (byte == 0xF7 || m_SysExLen >= MAX_MIDI_MESSAGE) { - MIDIMessageHandler(m_SysExBuffer, m_SysExLen, VIRTUALCABLE); + if ((byte & 0x80) && byte != 0xF0 && byte != 0xF7) { m_SysExActive = false; m_SysExLen = 0; + } else { + if (m_SysExLen < MAX_MIDI_MESSAGE) { + m_SysExBuffer[m_SysExLen++] = byte; + } + if (byte == 0xF7 || m_SysExLen >= MAX_MIDI_MESSAGE) { + MIDIMessageHandler(m_SysExBuffer, m_SysExLen, VIRTUALCABLE); + m_SysExActive = false; + m_SysExLen = 0; + } + if (m_SysExActive) continue; } - continue; } - MIDIMessageHandler(&byte, 1, VIRTUALCABLE); + UdpMidiReassembly(byte, VIRTUALCABLE); } } @@ -120,17 +154,22 @@ void CUDPMIDIDevice::OnUDPMIDIDataReceived(const u8* pData, size_t nSize) m_SysExLen = 0; } if (m_SysExActive) { - if (m_SysExLen < MAX_MIDI_MESSAGE) { - m_SysExBuffer[m_SysExLen++] = byte; - } - if (byte == 0xF7 || m_SysExLen >= MAX_MIDI_MESSAGE) { - MIDIMessageHandler(m_SysExBuffer, m_SysExLen, VIRTUALCABLE); + if ((byte & 0x80) && byte != 0xF0 && byte != 0xF7) { m_SysExActive = false; m_SysExLen = 0; + } else { + if (m_SysExLen < MAX_MIDI_MESSAGE) { + m_SysExBuffer[m_SysExLen++] = byte; + } + if (byte == 0xF7 || m_SysExLen >= MAX_MIDI_MESSAGE) { + MIDIMessageHandler(m_SysExBuffer, m_SysExLen, VIRTUALCABLE); + m_SysExActive = false; + m_SysExLen = 0; + } + if (m_SysExActive) continue; } - continue; } - MIDIMessageHandler(&byte, 1, VIRTUALCABLE); + UdpMidiReassembly(byte, VIRTUALCABLE); } } diff --git a/src/udpmididevice.h b/src/udpmididevice.h index 3c399f8..40d83e5 100644 --- a/src/udpmididevice.h +++ b/src/udpmididevice.h @@ -62,6 +62,10 @@ private: uint8_t m_SysExBuffer[MAX_MIDI_MESSAGE]; size_t m_SysExLen = 0; bool m_SysExActive = false; + + void UdpMidiReassembly(uint8_t byte, unsigned cable); + uint8_t m_udpMidiMsg[4] = {0}; + uint8_t m_udpMidiState = 0; }; #endif