Skip to content

MIDI

MIDI tracks are the hardware counterpart of audio tracks: instead of playing an instrument inside Resonon, a MidiTrack sends notes to an external synth, DAW, or plugin host. Patterns are assigned with the same track << pattern statement. MidiTrack and all midi_* functions are built into the language — no import needed — and every example here runs without connected hardware.

For guided walkthroughs, see the chapters on MIDI output, input & CC, clock sync, and export & MPE.

MidiTrack methodReturnsMeaning
output(alias, channel?)MidiTrackRoute to an output port (and channel)
input(port, channel?)MidiTrackListen to an input port, or "all"
monitor(mode)MidiTrackThru-play: "off", "in", "auto"
velocity(v)MidiTrackDefault velocity: number, signal, or pattern
cc(number)CcOutputHandle for CC automation via <<
tuning(bend_range?)MidiTrackMicrotonal output via pitch bend
mpe(bend_range?, zone_lo?, zone_hi?)MidiTrackMPE per-note channels
scale(scale, root)MidiTrackPer-track scale for degrees & quantization
FunctionReturnsMeaning
midi_ports()ArrayList available output ports
midi_connect(port, alias?)BooleanConnect an output port
midi_disconnect(alias?)NulDisconnect an output
midi_connected()variesCurrent output connections
midi_input_ports()ArrayList available input ports
midi_input_connect(port, alias)BooleanConnect an input port
midi_input_disconnect(alias)NulDisconnect an input
midi_clock_send(enabled)BooleanSend MIDI clock as master
midi_clock_follow(alias | false)BooleanFollow external MIDI clock
midi_delay(ms?)NumberGet/set global MIDI output delay
midi_clock_offset(ms?)NumberGet/set clock-only timing offset
midi_clock_status()NulPrint clock source, BPM, transport
midi_routing()NulPrint the full MIDI routing overview
midi_export(subject, cycles, path?)StringWrite a Standard MIDI File

MidiTrack(channel, velocity?, port_alias?, name?)

Section titled “MidiTrack(channel, velocity?, port_alias?, name?)”

Create a MIDI track. Only the channel is required.

ParameterRange / typeDefault
channel1–16
velocity0–127100
port_aliasString"default"
nameString (for logs; duplicates auto-numbered)"unnamed"
use "std/signals" { Sine };
let bass = MidiTrack(1);
let lead = MidiTrack(2, 110, "default", "lead");
bass << [C2 E2 G2 C3];

Route the track to a different output port by alias (see midi_connect()), optionally changing the channel too. A warning is logged if the alias isn’t connected yet — notes flow once it is.

lead.output("default");
lead.output("default", 3);

Listen to a connected MIDI input: pass an input alias, or "all" for every connected input. The optional channel (1–16) filters incoming messages; without it, all channels pass.

lead.input("all");
lead.input("all", 2);

Control thru-play of the track’s input: "off" (never), "in" (always forward input to the output), or "auto".

lead.monitor("in");
lead.monitor("off");

Set the track’s default velocity (0–127). Also accepts a Signal or a Pattern for moving dynamics. Per-note @ velocity in mini-notation always wins over the track default.

bass.velocity(90);
bass.velocity(Sine(0.5).range(60, 127));

Enable microtonal output: fractional note values are rendered with pitch-bend messages. bend_range is in semitones and defaults to 2 — match it to the bend range configured on the receiving synth.

lead.tuning();
lead.tuning(12);

Enable MPE: each voice gets its own member channel for independent pitch bend. bend_range defaults to 48 semitones; the member-channel zone defaults to channels 2–16. The MPE Configuration Message is sent automatically before the first note.

lead.mpe();
lead.mpe(48, 2, 8);

Attach a scale to the track, anchored at a root note: degree notation in patterns resolves through it, and out-of-scale notes are quantized. Accepts a scale name string, a Scale value (including microtonal scales), or an interval array.

lead.scale("minor", C3);
lead.scale(Scale(#[0, 2, 3.5, 5, 7, 8.5, 10]), C3);

Return a CcOutput handle for a controller number (0–127) on the track’s channel and port. Bind a Signal or Pattern to it with <<; values are rounded and clamped to 0–127, so scale signals into that range. Repeated values are deduplicated before sending.

lead.cc(74) << Sine(0.25).range(20, 120); // filter sweep
lead.cc(1) << [0 32 64 127]; // stepped mod wheel

For reading CC from a controller, see Cc() and Cc_learn() in the signals reference.

Set how often a CC binding samples its signal, in messages per second (above 0, at most 1000; default 30). Returns a new CcOutput, so chain it at bind time.

lead.cc(74).send_rate(60) << Sine(2).range(0, 127);

Connections map physical ports to aliases; tracks refer to aliases, so a set re-runs cleanly even when port names change. The implicit alias "default" is where every track sends unless told otherwise.

List the names of all available MIDI output ports.

PRINT midi_ports();

Connect an output port. The name matches by substring, so "IAC" finds "IAC Driver Bus 1". Without an alias, the connection becomes "default". Returns true on success; errors if no port matches.

midi_connect("IAC Driver Bus 1"); // becomes "default"
midi_connect("Elektron", "digitone"); // named alias

Disconnect an output by alias ("default" if omitted). Safe to call when nothing is connected.

midi_disconnect();
midi_disconnect("digitone");

Query current output connections: false when nothing is connected, the port name string when only "default" is connected, or a dict of alias → port name for multiple connections.

PRINT midi_connected();

List the names of all available MIDI input ports.

PRINT midi_input_ports();

Connect an input port under a unique alias (substring matching as with outputs). Returns true on success. Tracks subscribe via input(); signals read controllers via Cc().

midi_input_connect("Launchkey", "keys");

Disconnect an input by alias. All Notes Off is sent to the outputs first, so nothing hangs.

midi_input_disconnect("keys");

Act as clock master: send 24-PPQ MIDI clock plus Start/Stop/Continue to all connected output ports. Mutually exclusive with clock follow.

midi_clock_send(true);
midi_clock_send(false);

Sync Resonon’s tempo to incoming MIDI clock from a connected input alias; a soft PLL smooths the incoming tempo. Pass false to stop following. Mutually exclusive with clock send.

midi_input_connect("DAW out", "daw");
midi_clock_follow("daw");
midi_clock_follow(false);

Get or set a global delay applied to all MIDI output (notes and clock) — use it to line up external synths with Resonon’s internal audio.

midi_delay(12);
PRINT midi_delay(); // 12

Get or set a timing offset applied to clock messages only, independent of midi_delay(). Positive values delay the clock; negative values send it earlier.

midi_clock_offset(-5);
PRINT midi_clock_offset(); // -5

Print the current clock state: source (internal, sending, or following), BPM, transport state, and PLL diagnostics when following.

midi_clock_status();

Print the complete MIDI picture: output ports, input ports, active track/CC slots, and the clock mode.

midi_routing();

Render a pattern or MIDI track set to a Standard MIDI File and return the written path. Without a path, the file lands in the project output directory. Notes, velocities, CC automation, channels, tempo, and track names are exported.

SubjectFile type
PatternType 0, single track
TimelineType 0, single track
MidiTrackType 1, conductor + track
Array of MidiTracksType 1, multi-track
midi_export([C4 E4 G4 C5], 4); // pattern, default path
midi_export([C4 E4 G4 C5], 4, "melody.mid");
let synth = MidiTrack(2, 100);
synth << [C4 E4 G4 C5];
synth.cc(74) << Sine(0.25).range(20, 120);
midi_export(synth, 8, "synth.mid"); // includes CC automation
let bass = MidiTrack(1, 90);
bass << [C2 E2 G2 C3];
midi_export(#[bass, synth], 8, "multi_track.mid"); // multi-track SMF