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

midi_sequence.h

MIDI as a timeline rather than as one block's worth.

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

Design notes

MidiBuffer is what a plugin sees: the events inside THIS block, offset in samples from its start. That is the right shape for processing and the wrong one for everything else. An arpeggiator pattern, a MIDI file being played back, a phrase an editor is drawing: all of them are a whole piece of music at once, in seconds, and none of them fits in a buffer that ends after 128 samples.

The half that is genuinely awkward is PAIRING. A note-on and its note-off are two unrelated events in a flat list, and almost everything worth doing needs them joined: how long is this note, what is sounding at bar 3, drag this note later and take its end with it. Pairing looks trivial until two notes of the same pitch overlap on the same channel (a legato repeat, or a sustain pedal part written badly), and then a naive "find the next note-off for this pitch" gives the first note the second note's ending and leaves the second unmatched for ever.

Types 2

One message at a point in time, in SECONDS from the start of the sequence.

Seconds, not ticks and not samples. Ticks need a tempo map to mean anything and samples need a rate, and a sequence outlives both -- the session's rate can change under it and the music must not move.

A piece of music, in order.

Kept sorted by time. Insertion is allowed to break that, and everything that depends on order calls sort() first rather than assuming -- a sequence that is quietly out of order gives an event iterator that skips things, which looks like dropped notes and is diagnosed as anything else.

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