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

midi_file.h

Standard MIDI Files.

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

Design notes

The interchange format for patterns: what an arpeggiator exports, what a chord generator imports, what a user drags out of a DAW and into a plugin. Reading and writing SMF format 0 and 1.

Two things in this format break every naive parser, and both are handled explicitly below:

VARIABLE-LENGTH QUANTITIES: delta times are 7 bits per byte with the top
bit meaning "another byte follows". Assuming one byte works on short
patterns and silently derails on anything longer than 127 ticks.

RUNNING STATUS: a data byte where a status byte was expected means
"reuse the previous status". A parser that does not implement it reads
garbage from the moment a file uses it, which most real files do.

Offline by design, like wav.h: this allocates and does file IO.

Types 4

One event at an absolute position, in ticks from the start of its track.

A tempo change, so a reader can convert ticks to seconds honestly rather than assuming 120 BPM the way a lazy importer does.

One track of a file: its name (the 0x03 meta event) and its channel messages in tick order. Only channel messages travel either way: a read skips SysEx and every meta event but the name and tempo (tempo goes to MidiFileData::tempoChanges), and a write leaves out anything else it is handed.

A Standard MIDI File in memory: the tick resolution, the tracks, and one tempo map merged from all of them. What readMidiFile() fills and writeMidiFile() writes -- format 0 for one track, format 1 for more, with the tempo map on the first track.

Plain data, and offline: reading and writing allocate and do file I/O, so neither belongs on the audio thread. Times are ticks; tickToSeconds() follows the tempo map. A file timed in SMPTE frames is refused, not read.

Functions 10

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