Skip to content

Send MIDI to a Synth or DAW

A MidiTrack plays its pattern out of a MIDI port on one channel, chosen with >>. Every method is in the MIDI reference; the port keys are in Preferences.

Ports belong to the machine, so they are declared in ~/.resonon/preferences.toml, not in the piece. The piece names a port by its alias:

[[midi.outputs]]
alias = "synth"
port = "IAC Driver Bus 1"

resonon --list-ports prints a ready-to-paste entry for every attached device, and resonon setup writes the entries for you. The port name matches exactly, then as a substring, so "IAC" finds "IAC Driver Bus 1". Run reload_preferences() to put a change in force without restarting.

Create a track, route it to the port with >>, and send it a pattern with <<:

let lead = MidiTrack("lead");
lead >> MidiOutput("synth");
lead << [C4 E4 G4 E4];
PLAY;

The track plays on channel 1 at velocity 100. A new track has no output — Live’s “No Output” — so until the >> line runs it sends nothing. Send it another pattern at any time; the new one starts on the next cycle.

Give MidiOutput a channel as its second argument. A multi-timbral synth or a DAW plays each channel with its own sound:

let lead = MidiTrack("lead");
let bass = MidiTrack("bass").set_velocity(80);
let drums = MidiTrack("drums").set_velocity(110);
lead >> MidiOutput("synth", 1);
bass >> MidiOutput("synth", 2);
drums >> MidiOutput("synth", 10);
lead << [E5 D5 C5 D5];
bass << [C3 _ C3 G2];
drums << [C2 _ D2 _];
PLAY;

Channel 10 is General MIDI drums.

Declare a port per destination, each under its own alias:

[[midi.outputs]]
alias = "daw"
port = "IAC Driver Bus 1"
[[midi.outputs]]
alias = "synth"
port = "Prophet Rev2"
optional = true

optional = true marks gear that is not always plugged in; its absence is expected instead of reported. Route each track to its alias, and move it with another >>:

let pad = MidiTrack("pad");
let lead = MidiTrack("lead");
pad >> MidiOutput("synth");
lead >> MidiOutput("daw", 2); // to the DAW, channel 2
lead >> MidiOutput("synth", 5); // to the synth, channel 5
lead >> nowhere; // no output: the track keeps its pattern and sends nothing

A track playing a pattern moves to the new port or channel on the next cycle, with its CC and input thru.

.set_velocity() sets the velocity for every note without a ^ velocity of its own. Give it a number, a pattern, or a signal:

use "std/signals" { Sine };
let melody = MidiTrack("melody");
melody >> MidiOutput("synth");
melody << [C4^100 D4 E4 F4^50];
melody.set_velocity(80); // fixed
melody.set_velocity([100 60 80 120]); // one value per step
melody.set_velocity(Sine(0.5).range(60, 127)); // read as each note fires

The last call wins. The ^ velocities on C4 and F4 always stay.

  1. Enable a virtual port. On macOS, open Audio MIDI Setup, choose Window → Show MIDI Studio, double-click IAC Driver, and check Device is online.
  2. Declare it as an output, as above.
  3. In the DAW, enable the port as a MIDI input, create an instrument track, set its MIDI input to the port, and turn on input monitoring.
  4. Play a track from resonon. To record it as a MIDI clip, arm the DAW track and record.

For several instruments, create one DAW track per channel, all listening to the same port.

print(midi_ports()); // every output port on the system
print(midi_connected()); // {alias: port} for each connected port
midi_routing_report(); // ports, tracks and clock, in one summary