Search guides and the APICtrl K
  1. API reference
  2. MIDI and OSC

ump.h

Universal MIDI Packets: the MIDI 2.0 wire format.

#include <sonore/ump.h>
On this page

Design notes

What a UMP is

MIDI 1.0 is a byte stream where the length of a message is worked out from its status byte. MIDI 2.0 is a stream of 32-bit WORDS, and how many words a message occupies is read from the top nibble of the first one. That single change is what lets it carry a 32-bit controller value, sixteen groups of sixteen channels, and per-note controllers, without the receiver ever guessing.

This SDK already speaks the negotiation half of MIDI 2.0: midi_ci.h does discovery, profiles and property exchange. It could not speak the transport half at all, which is a strange place to stop -- a plugin could agree with a controller about what it supports and then have no way to receive it.

What is here, and what is deliberately not

Packet SIZING, MIDI 1.0 channel voice both directions, MIDI 2.0 channel voice down to MidiMessage, and SysEx7 assembly. That is the set a plugin actually meets: a host translating a MIDI 2.0 stream sends channel voice and SysEx, and everything else in the specification is stream configuration the host handles before the plugin sees anything.

Not here: Flex Data (score metadata), UMP Stream (endpoint discovery), and SysEx8 with the Mixed Data Set. Those are the 128-bit packets, and they live in ump128.h -- a plugin that is an endpoint in its own right needs them; one fed by a host that flattens MIDI 2.0 never sees them.

On losing precision, and saying so

MIDI 2.0 velocity is 16 bits and MidiMessage carries 7. Converting down LOSES information, and every function here that does it says so in its name or its comment. The alternative -- widening MidiMessage - would change the type every DSP in this SDK is written against, for a resolution no generated plugin has asked for yet. When one does, this is the file that records what was given up.

Types 1

Assembles a SysEx from the 64-bit packets that carry it.

UMP does not put a SysEx on the wire as bytes. It carries up to six data bytes per packet with a status nibble saying whether this is the whole thing, the start, the middle or the end -- so the reassembly is a different problem from the serial one in sysex.h, and shares only the rule that a partial message is never handed on.

The bytes carried are the PAYLOAD: the 0xF0 and 0xF7 that delimit a MIDI 1.0 SysEx are not transmitted. They are added back here, because every consumer in this SDK -- midi_ci.h included -- expects a complete MIDI 1.0 message.

One message in progress PER GROUP. UMP lets SysEx7 streams on different groups interleave packet by packet -- they are sixteen separate cables -- and a single buffer stitched two 13-byte messages on groups 0 and 1 into one 21-byte message made of parts of both.

A packet with a reserved status is ignored. One whose byte count is over six abandons the message open on its group, counted in dropped(): that message is missing the bytes the packet could not carry.

Functions 9

↑↓ to move↵ to openEvery public name in the headers, and every guide