Skip to content

Export MIDI

midi_export() writes notes to a .mid file for a DAW or notation software. Its signature, and what the file contains, are in the audio reference. To bounce sound instead, see Render a Project.

Give the pattern and the number of cycles:

let melody = [C4^80 E4^110 G4 C5];
midi_export(melody, 4);

The file is written to renders/<title>_<date>_<time>/export.mid in the project. A note with a ^ velocity keeps it; any other note gets velocity 100.

Pass the track instead. Its output’s channel (channel 1 for a track with no output), default velocity, velocity modulation and CC lanes go into the file:

use "std/signals" { Sine };
let bass = MidiTrack("bass").set_velocity(90);
bass >> MidiOutput("synth", 2);
bass << [C2 E2 G2 C3];
bass.cc(74) << Sine(0.25).range(0, 127);
midi_export(bass, 4);

The file is named after the track: bass.mid.

A velocity signal or a signal-driven CC is rendered, not sampled once, so a slow envelope writes the curve you hear. While it renders, the export owns the engine and playback pauses, then resumes. An export with nothing to render — plain patterns and fixed CC values — does not interrupt playback.

Pass an array of tracks:

let bass = MidiTrack("bass").set_velocity(80);
let lead = MidiTrack("lead").set_velocity(110);
bass >> MidiOutput("synth", 1);
lead >> MidiOutput("synth", 2);
bass << [C2 E2 G2];
lead << [C5 E5 G5 C6];
midi_export(#[bass, lead], 8);

Each track becomes its own track in the file. A track in the array with no pattern is skipped and named in the output; a single track with no pattern is an error.

Add a path as the last argument. A relative path is relative to the project, wherever you run from; an absolute path is used as written. Every form returns the path it wrote:

let path = midi_export([C4 E4 G4 C5], 4, "melody.mid");
print(path);