Updated:
Tested on: macOS 27.0 (IAC Driver, 2026-09-23); the same behavior was seen earlier on MIDI 2.0 input ports

On a MIDIFabric input port set up to receive MIDI 2.0, each NRPN value arrived twice, and the first one was wrong.

Core MIDI converted the NRPN as soon as CC 6 arrived, before the low part of the value was available. It sent an incomplete value first, then the full value when CC 38 arrived. This conversion affects MIDI 2.0 receivers; it does not occur on an input that receives MIDI 1.0.

The NRPN sequence in this test consists of four MIDI 1.0 messages: CC 99 and 98 select the parameter, and CC 6 and 38 carry the high and low parts of the value. Core MIDI converts the sequence to MIDI 2.0 controller messages.

How we noticed

An earlier version of MIDIFabric created its Core MIDI input ports with the MIDI 2.0 protocol. That is where we saw MIDI 1.0 NRPNs arrive once before the low part of the value was in, and we switched to creating input ports with the MIDI 1.0 protocol.

Later, when we found that IAC Driver buses are MIDI 2.0 (Is the IAC Driver MIDI 2.0?), we checked the same thing again through IAC.

What we observed

We sent an NRPN in MIDI 1.0 to an IAC bus and received it with an app that reads MIDI 2.0. The parameter was 1:2 and the value 0x1234:

MIDI 1.0 sentMIDI 2.0 received
CC 99 = 1, CC 98 = 2nothing yet
CC 6 = 0x24 (high part)Assignable Controller 1:2 with 0x48000000, the value with only its high part
CC 38 = 0x34 (low part)Assignable Controller 1:2 again, with 0x48D00000, the full value

The first message is not a duplicate of the second: it carries a different, incomplete value.

This is the same behavior we had seen in the earlier version of MIDIFabric. We believe it is not specific to IAC, and happens wherever Core MIDI converts MIDI 1.0 into MIDI 2.0 for an app.

RPN and MIDI 1.0 receivers

  • RPN lets CC 101 through first. An RPN in MIDI 1.0 (CC 101, 100, 6) arrived as the raw CC 101, followed by the converted RPN message.
  • MIDI 1.0 receivers on IAC can see repeats. Because IAC converts to MIDI 2.0 internally and back, an app receiving MIDI 1.0 from IAC got the NRPN as CC 99, 98, 6, 6, 38, and the RPN with CC 101 twice. See Is the IAC Driver MIDI 2.0?.

What it affects

  • A control in the app jumps to a wrong value for a moment before settling.
  • Recorded automation can contain an extra point at the incomplete value.
  • MIDI learn or a logger may record the incomplete value, or two messages for one change.
  • For parameters that react immediately (pitch, filter cutoff), the jump can be audible.

Checking only the final value can miss the intermediate one. Inspect the sequence of received values when testing rapid NRPN changes or parameters that respond immediately.

How to avoid it

For users:

  • If the app lets you choose how it receives MIDI, receiving MIDI 1.0 avoids this.
  • Between apps on the same Mac, the IAC Driver itself is MIDI 2.0, so an app that reads MIDI 2.0 from IAC is affected even if everything else is MIDI 1.0.

For app developers:

  • Create your input port with the MIDI 1.0 protocol and assemble NRPN yourself from CC 99, 98, 6 and 38, waiting for CC 38 (or a short timeout) before using the value.
  • If you need MIDI 2.0 input, treat an Assignable Controller that is quickly followed by another for the same parameter as one change, or ignore the low part until it arrives.
  • If you send to a MIDI 2.0 destination, send the MIDI 2.0 controller message directly instead of an NRPN in MIDI 1.0.

About MIDIFabric

MIDIFabric receives MIDI 1.0 devices with the MIDI 1.0 protocol and groups CC 99, 98, 6 and 38 into one NRPN entry itself, so its monitor shows one change with the final value and lets you expand it to the four messages.

← All developer notes