# JUCE 8.0.12 USB-MIDI implementation

**URL:** <https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127>\
**Category:** General JUCE discussion\
**Created:** [February 3, 2026, 2:10pm UTC](https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127 "2026-02-03T14:10:48Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![andreamaracci](https://avatars.discourse-cdn.com/v4/letter/a/e47774/32.png) [@andreamaracci](https://forum.juce.com/u/andreamaracci)\
**Post date:** [February 3, 2026, 2:10pm UTC](https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127/1 "2026-02-03T14:10:49Z")

</div>

I am encountering an issue related to SysEx packetization when sending data from a JUCE application to external hardware.

With JUCE 8.0.12 running on Sequoia 15.3.1, a 21-byte SysEx message is incorrectly packetized. The first two packets (corresponding to the first six bytes of the SysEx message) use the correct 0x04 type byte. The third packet, however, uses a 0x0F type byte and contains only the 9th byte, followed by two zero bytes. The fourth packet then returns to a 0x04 type byte and carries the 10th, 11th, and 12th bytes. This behavior breaks the SysEx message.

The snoize midi monitor display the message correctly.

I do not observe this issue with JUCE 8.0.8. and I have not tested the intermediate versions.

Is this a known issue? Is anyone else experiencing the same problem?

---

<div class="post-metadata">

**Author:** ![ddv](https://avatars.discourse-cdn.com/v4/letter/d/4bbf92/32.png) [@ddv](https://forum.juce.com/u/ddv)\
**Post date:** [September 16, 2026, 3:37pm UTC](https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127/2 "2026-09-16T15:37:35Z")

</div>

I’ve been fighting what looks like the same problem on macOS, and your description gives it away. A 0x0F packet in the middle of a SysEx is exactly what Apple’s class-compliant USB-MIDI driver does in this case.

USB-MIDI packs SysEx into 3-byte packets (CIN 0x4, then 0x5/0x6/0x7 for the last one). If the driver gets a buffer from CoreMIDI that stops partway through a SysEx and its length isn’t a multiple of 3, it doesn’t hold onto the leftover 1 or 2 bytes until the next buffer arrives. It sends them straight away as single-byte packets (CIN 0xF). A lot of interfaces and synths don’t handle that and drop or garble the message. Others handle it fine, which is why it only shows up with some hardware.

That’s also why MIDI Monitor shows your message as correct. It sees the byte stream at the CoreMIDI level, before the driver breaks it into USB packets, so the data really is correct at that point.

This is an old one. There’s a JUCE thread from 2013 where every 256th byte went missing because JUCE sent SysEx in 256-byte chunks (256 = 3×85 + 1), and changing it to 255 fixed it:

> [@Problem with Sysex transfer over USB MIDI on Mac](https://forum.juce.com/t/problem-with-sysex-transfer-over-usb-midi-on-mac/9830):
>
> Moin, I have a problem sending Sysex dumps of a moderate length of 1330 bytes over USB on a Mac. Looking into sendMessageNow() I see that Sysex is split into chunks with max 256 bytes that are sent individually. On the receiving end, every 256th byte is lost. This is not very surprising: According to the USB Midi specification, sysex is sent in event packets with three bytes payload each. There are special codes for ending on 1st, 2nd or 3rd byte, but not for transmitting a single sysex b…

Kurt Revis explains the same thing and works around it in SysEx Librarian. He sends each buffer as its own packet, rounds the buffer size down to a multiple of 3, and paces them at about 3125 bytes/sec (see `SysExSendRequest.swift` in [GitHub - krevis/MIDIApps: MIDI apps for Mac OS X: MIDI Monitor and SysEx Librarian. · GitHub](https://github.com/krevis/MIDIApps)).

I can’t tell you exactly what changed between 8.0.8 and 8.0.12. The send code in `juce_CoreMidi_mac.mm` looks basically the same in both. Since 8.0.8 is fine, though, something upstream must now be splitting the SysEx at a point that isn’t a multiple of 3, whether that’s the UMP conversion or how the message gets chunked before it reaches CoreMIDI. On macOS 11+ JUCE sends through `MIDISendEventList`, so the bytes the driver finally sees also depend on CoreMIDI’s own UMP-to-bytestream conversion. If you can, try the same message on 8.0.8 and 8.0.12 on the same Mac, and send it from SysEx Librarian to the same hardware. That should tell you whether it’s JUCE or the OS.

For what it’s worth, I hit this in Max, which has its own MIDI output code, and fixed it with a small external that calls `MIDISend` directly with 255-byte buffers. It’s been solid on the interfaces that were failing, so if you need a workaround now, controlling the buffer sizes yourself should work.

---

<div class="post-metadata">

**Author:** ![stenzel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/stenzel/32/11737_2.png) [@stenzel](https://forum.juce.com/u/stenzel)\
**Post date:** [September 16, 2026, 4:21pm UTC](https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127/3 "2026-09-16T16:21:12Z")

</div>

I reported this bug in 2013 and it still exists in Juce 9, the fix is easy:

juce\_CoreMidi\_mac.mm, near line 1600:

`if (isSysEx)`  
`{`  
`const int maxPacketSize = 256;`

change to:  
`const int maxPacketSize = 384;	//must be divisible by three.`

Please?

---

<div class="post-metadata">

**Author:** ![ddv](https://avatars.discourse-cdn.com/v4/letter/d/4bbf92/32.png) [@ddv](https://forum.juce.com/u/ddv)\
**Post date:** [September 16, 2026, 4:34pm UTC](https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127/4 "2026-09-16T16:34:19Z")

</div>

Good call on the multiple-of-3 fix. That’s exactly the cause. One catch, though: in current JUCE that 256-byte chunking is only used on macOS 10.x. On macOS 11+ juce\_CoreMidi\_mac.mm always takes the onlyNew path, which sends UMP through MIDISendEventList, so that line never runs on Sequoia. The 8.0.12 problem must come from how the new path splits SysEx before CoreMIDI converts it back to bytes for the USB driver. I’d still change 256 to 255 for older systems.

---

<div class="post-metadata">

**Author:** ![andreamaracci](https://avatars.discourse-cdn.com/v4/letter/a/e47774/32.png) [@andreamaracci](https://forum.juce.com/u/andreamaracci)\
**Post date:** [September 16, 2026, 8:38pm UTC](https://forum.juce.com/t/juce-8-0-12-usb-midi-implementation/68127/5 "2026-09-16T20:38:15Z")

</div>

I posted this also as a response in another post and the question went forward:

> [@JUCE 8.0.11 MIDI PORT NAME](https://forum.juce.com/t/juce-8-0-11-midi-port-name/67745):
>
> Compared to JUCE 8.0.10, this version completely changes the naming of MIDI ports. For example: Array\<MidiDeviceInfo\> itemsIn = MidiInput::getAvailableDevices(); for (const auto& item : itemsIn) { DBG(item.name); } Previously the device was listed as “MY PORT”, but now it appears as “MY : PORT”. Does anyone know why? Is this a JUCE-introduced bug, maybe related to MIDI 2.0 compatibility? I can confirm that the colon is added only for MIDI 2.0 devices.
