Demo · 2026

Modular audio synthesis,
built in Rust.

A node-based graph editor for constructing real-time audio processing pipelines - lock-free, sample-accurate, built from the signal up.

Download for macOS
The patch you're about to hear, scripted in Rhai. Drag nodes or write Rhai. Same graph.
// ══════════════════════════════════════════════
// Lo-Fi Chill Demo - scripted patch build
// ══════════════════════════════════════════════
//
// Three acts:
//   1. Build the lo-fi patch from scratch (~45s)
//   2. Card flip activity monitor (~20s)
//   3. Mode3D drop (~30s)
//
// 75 BPM, 32 bars (~102s), C major / Dm
// Composition: Pattern D (mixed)
//   - Keys, drums, bass, vinyl: global sequencer with arranger Fade
//   - Melody: gated sequencer (8 bars, Loop)
//
// Structure:
//   Intro    bars 1-8   : rhodes chords + vinyl crackle
//   Groove A bars 9-16  : boom-bap drums + warm sub bass
//   Groove B bars 17-24 : dreamy pluck melody floats in
//   Outro    bars 25-32 : melody fades, drums thin, drift off

// ── Setup ────────────────────────────────────

toast("Setting up lofi-chill", "info", "center");

graph_clear();
autolayout(true);
// autozoom(true);
set_tempo(75.0);
set_key("C");
zoom_to_fit();
sleep(600);

// ══════════════════════════════════════════════
//  ACT 1: BUILD THE PATCH
// ══════════════════════════════════════════════

// ── Master bus ───────────────────────────────

let sink = AudioSink.first();

let master = Mixer.add("master");
master.inputs(7);
master.master_gain(0.80);
sleep(300);

let comp = Compressor.add("glue");
comp.threshold_db(-14.0);
comp.ratio(2.5);
comp.attack_ms(15.0);
comp.release_ms(100.0);
comp.auto_makeup(true);
sleep(250);

let space = Reverb.add("space");
space.room_size(0.65);
space.damping(0.55);
space.pre_delay_ms(20.0);
space.width(1.0);
space.mix(0.22);
sleep(250);

let panner = StereoPanner.add("panner");
panner.pan_a(-0.8);
panner.width_a(0.6);
panner.pan_b(0.8);
panner.width_b(0.6);
sleep(200);

let out_gain = Gain.add("out_gain");
out_gain.set("Gain", 0.5);
sleep(200);

master.output("Output").port().connect(comp.input("Audio In").port());
comp.output("Audio Out").port().connect(space.input("Input").port());
space.output("Output").port().connect(panner.input("Audio A").port());
space.output("Output").port().connect(panner.input("Audio B").port());
panner.output("Audio Out").port().connect(out_gain.input("Audio In").port());
out_gain.output("Audio Out").port().connect(sink.input("Audio In").port());
sleep(200);

let spectrum = SpectrumAnalyzer.add("spectrum");
spectrum.averaging_mode("Exponential");
master.output("Output").port().connect(spectrum.input("Audio In").port());
sleep(200);

zoom_to_fit();
sleep(400);

// ── Arranger - section gating ────────────────

let arr_edit = ArrangerEditor.add("arr_edit");
arr_edit.tempo(75.0);
arr_edit.bars(32);
sleep(250);

let arr = Arranger.add("arr");
arr.set("Loop", true);
arr_edit.output("Arrangement").port().connect(arr.input("Config In").port());
arr_edit.output("Timing").port().connect(arr.input("Timing").port());
sleep(300);

let t_keys = arr_edit.add_track("Keys");
let r = t_keys.add_region(0.0, 128.0);
r.fade_in(8.0);
r.fade_out(8.0);
sleep(200);

let t_drums = arr_edit.add_track("Drums");
let r = t_drums.add_region(32.0, 96.0);
r.set_level(0.8);
r.fade_in(8.0);
r.fade_out(8.0);
sleep(200);

let t_bass = arr_edit.add_track("Bass");
let r = t_bass.add_region(32.0, 96.0);
r.set_level(0.9);
r.fade_in(4.0);
r.fade_out(4.0);
sleep(200);

let t_melody = arr_edit.add_track("Melody");
let r = t_melody.add_region(64.0, 48.0);
r.fade_in(4.0);
r.fade_out(8.0);
sleep(200);

let t_vinyl = arr_edit.add_track("Vinyl");
let r = t_vinyl.add_region(0.0, 128.0);
r.set_level(1.0);
sleep(200);

zoom_to_fit();
sleep(400);

// ── Keys - warm triangle chords, lo-fi ───────

let keys = PolysynthV2.add("keys");
keys.waveform("Triangle");
keys.shape(adsr(0.05, 0.4, 0.6, 0.8));
sleep(250);

let keys_filt = Biquad.add("keys_filt");
keys_filt.filter_type("Lowpass");
keys_filt.frequency(2800.0);
keys_filt.q(0.8);
sleep(200);

let keys_chorus = Chorus.add("keys_chorus");
keys_chorus.num_voices(3);
keys_chorus.rate(0.3);
keys_chorus.depth(2.0);
keys_chorus.mix(0.18);
sleep(200);

let keys_crush = Distortion.add("keys_crush");
keys_crush.distortion_type("Bitcrush");
keys_crush.drive(1.5);
keys_crush.mix(0.15);
keys_crush.bits(12);
sleep(200);

let keys_fade = Fade.add("keys_fade");
keys_fade.fade_in(200.0);
keys_fade.fade_out(300.0);
sleep(150);

keys.output("Audio Out").port().connect(keys_filt.input("Audio In").port());
keys_filt.output("Audio Out").port().connect(keys_chorus.input("Input").port());
keys_chorus.output("Output").port().connect(keys_crush.input("Audio In").port());
keys_crush.output("Audio Out").port().connect(keys_fade.input("Audio In").port());
arr.output(t_keys.level_port()).port().connect(keys_fade.input("Level").port());
keys_fade.output("Audio Out").port().connect(master.input("Input 0").port());
master.input("Input 0").gain(0.55);
sleep(300);

zoom_to_fit();
sleep(400);

// ── Bass - warm sine sub ─────────────────────

let bass = PolysynthV2.add("bass");
bass.waveform("Sine");
bass.shape(adsr(0.02, 0.2, 0.7, 0.3));
sleep(250);

let bass_filt = Biquad.add("bass_filt");
bass_filt.filter_type("Lowpass");
bass_filt.frequency(800.0);
bass_filt.q(1.0);
sleep(200);

let bass_sc = Compressor.add("bass_sc");
bass_sc.threshold_db(-18.0);
bass_sc.ratio(4.0);
bass_sc.attack_ms(2.0);
bass_sc.release_ms(60.0);
sleep(200);

let bass_fade = Fade.add("bass_fade");
bass_fade.fade_in(50.0);
bass_fade.fade_out(150.0);
sleep(150);

bass.output("Audio Out").port().connect(bass_filt.input("Audio In").port());
bass_filt.output("Audio Out").port().connect(bass_sc.input("Audio In").port());
bass_sc.output("Audio Out").port().connect(bass_fade.input("Audio In").port());
arr.output(t_bass.level_port()).port().connect(bass_fade.input("Level").port());
bass_fade.output("Audio Out").port().connect(master.input("Input 1").port());
master.input("Input 1").gain(0.60);
sleep(300);

zoom_to_fit();
sleep(300);

// ── Drums - boom-bap kit ─────────────────────

let kick = DrumVoice.add("kick");
kick.mode("Kick");
kick.pitch(-0.2);
kick.decay(0.4);
kick.tone(0.3);
kick.snap(0.2);
sleep(250);

let kick_fade = Fade.add("kick_fade");
kick_fade.fade_in(5.0);
kick_fade.fade_out(30.0);
kick.output("Audio Out").port().connect(kick_fade.input("Audio In").port());
arr.output(t_drums.level_port()).port().connect(kick_fade.input("Level").port());
kick_fade.output("Audio Out").port().connect(master.input("Input 2").port());
master.input("Input 2").gain(0.40);
kick.output("Audio Out").port().connect(bass_sc.input("Sidechain").port());
sleep(250);

zoom_to_fit();

let snare = DrumVoice.add("snare");
snare.mode("Rimshot");
snare.pitch(0.1);
snare.decay(0.2);
snare.tone(0.35);
snare.snap(0.3);
sleep(200);

let snare_fade = Fade.add("snare_fade");
snare_fade.fade_in(5.0);
snare_fade.fade_out(30.0);
snare.output("Audio Out").port().connect(snare_fade.input("Audio In").port());
arr.output(t_drums.level_port()).port().connect(snare_fade.input("Level").port());
snare_fade.output("Audio Out").port().connect(master.input("Input 3").port());
master.input("Input 3").gain(0.22);
sleep(250);

let hat = DrumVoice.add("hat");
hat.mode("Hihat");
hat.pitch(0.0);
hat.decay(0.08);
hat.tone(0.4);
sleep(200);

let hat_fade = Fade.add("hat_fade");
hat_fade.fade_in(5.0);
hat_fade.fade_out(30.0);
hat.output("Audio Out").port().connect(hat_fade.input("Audio In").port());
arr.output(t_drums.level_port()).port().connect(hat_fade.input("Level").port());
hat_fade.output("Audio Out").port().connect(master.input("Input 4").port());
master.input("Input 4").gain(0.12);
sleep(250);

zoom_to_fit();
sleep(300);

// ── Melody - soft electric piano + tape delay ─

let melody = PolysynthV2.add("melody");
melody.waveform("Triangle");
melody.shape(adsr(0.01, 0.3, 0.4, 0.6));
sleep(250);

let melody_filt = Biquad.add("melody_filt");
melody_filt.filter_type("Lowpass");
melody_filt.frequency(3500.0);
melody_filt.q(0.7);
sleep(200);

let melody_delay = Delay.add("melody_delay");
melody_delay.delay_time(0.6);
melody_delay.feedback(0.35);
melody_delay.mix(0.30);
sleep(200);

let melody_fade = Fade.add("melody_fade");
melody_fade.fade_in(50.0);
melody_fade.fade_out(300.0);
sleep(150);

melody.output("Audio Out").port().connect(melody_filt.input("Audio In").port());
melody_filt.output("Audio Out").port().connect(melody_delay.input("Audio In").port());
melody_delay.output("Audio Out").port().connect(melody_fade.input("Audio In").port());
arr.output(t_melody.level_port()).port().connect(melody_fade.input("Level").port());
melody_fade.output("Audio Out").port().connect(master.input("Input 5").port());
master.input("Input 5").gain(0.30);
sleep(250);

// ── Melody gated sequencer (clip-launcher) ───

let mel_edit = SequencerEditor.add("mel_seq_edit");
let mel_seq = Sequencer.add("mel_seq");
mel_edit.output("Sequencer Out").port().connect(mel_seq.input("Config In").port());
mel_edit.output("Timing").port().connect(mel_seq.input("Timing").port());
mel_edit.bpm(75.0);
mel_edit.bars(8);
mel_edit.timesig(4, 4);
mel_seq.gating("Loop");
arr.output(t_melody.gate_port()).port().connect(mel_seq.input("Gate In").port());
sleep(250);

zoom_to_fit();

let t_mel = mel_edit.add_track("Melody", channel(1));
t_mel.add_notes([
    ["A4",  0.0, 1.0, 80],
    ["D5",  1.5, 0.8, 75],
    ["C5",  3.0, 0.5, 70],
    ["A4",  4.0, 1.5, 85],
    ["F4",  6.0, 1.0, 70],
    ["G4",  8.0, 1.0, 75],
    ["B4",  9.5, 0.8, 80],
    ["D5",  11.0, 1.5, 85],
    ["C5",  13.0, 0.5, 70],
    ["A4",  14.0, 1.0, 75],
    ["E5",  16.0, 1.5, 90],
    ["D5",  18.0, 0.8, 75],
    ["C5",  19.0, 0.5, 70],
    ["G4",  20.0, 2.0, 80],
    ["A4",  24.0, 1.0, 80],
    ["C5",  25.5, 0.8, 75],
    ["F4",  27.0, 0.5, 65],
    ["E4",  28.0, 2.0, 70],
    ["D4",  30.5, 1.0, 75],
]);
mel_seq.output(t_mel.track_port()).port().connect(melody.input("MIDI In").port());
sleep(300);

zoom_to_fit();
sleep(300);

// ── Vinyl - pink noise hiss ──────────────────

let vinyl = Noise.add("vinyl");
vinyl.noise_type("Pink");
vinyl.amplitude(0.08);
sleep(200);

let vinyl_filt = Biquad.add("vinyl_filt");
vinyl_filt.filter_type("Lowpass");
vinyl_filt.frequency(600.0);
vinyl_filt.q(0.5);
sleep(200);

let vinyl_fade = Fade.add("vinyl_fade");
vinyl_fade.fade_in(500.0);
vinyl_fade.fade_out(500.0);
sleep(150);

vinyl.output("Audio Out").port().connect(vinyl_filt.input("Audio In").port());
vinyl_filt.output("Audio Out").port().connect(vinyl_fade.input("Audio In").port());
arr.output(t_vinyl.level_port()).port().connect(vinyl_fade.input("Level").port());
vinyl_fade.output("Audio Out").port().connect(master.input("Input 6").port());
master.input("Input 6").gain(0.10);
sleep(250);

zoom_to_fit();
sleep(400);

// ── Sequencer - 32 bars ──────────────────────

let edit = SequencerEditor.add("seq_edit");
let seq = Sequencer.add("seq");
edit.output("Sequencer Out").port().connect(seq.input("Config In").port());
edit.output("Timing").port().connect(seq.input("Timing").port());
edit.bpm(75.0);
edit.bars(32);
edit.timesig(4, 4);
edit.set_loop(true);
sleep(300);

edit.activate();
edit.scroll_to_note("F3");

zoom_to_fit();

// ── Keys: Dm7 - G7 - Cmaj7 - Fmaj7 ─────────

let t_keys_seq = edit.add_track("Keys", channel(1));
let keys_notes = [];
let rep = 0;
while rep < 4 {
    let base = rep * 32.0;
    keys_notes.push(["D3",  base, 7.5, 70]);
    keys_notes.push(["F3",  base, 7.5, 60]);
    keys_notes.push(["A3",  base, 7.5, 55]);
    keys_notes.push(["C4",  base, 7.5, 50]);
    keys_notes.push(["G2",  base + 8.0, 7.5, 70]);
    keys_notes.push(["B2",  base + 8.0, 7.5, 60]);
    keys_notes.push(["D3",  base + 8.0, 7.5, 55]);
    keys_notes.push(["F3",  base + 8.0, 7.5, 50]);
    keys_notes.push(["C3",  base + 16.0, 7.5, 70]);
    keys_notes.push(["E3",  base + 16.0, 7.5, 60]);
    keys_notes.push(["G3",  base + 16.0, 7.5, 55]);
    keys_notes.push(["B3",  base + 16.0, 7.5, 50]);
    keys_notes.push(["F2",  base + 24.0, 7.5, 70]);
    keys_notes.push(["A2",  base + 24.0, 7.5, 60]);
    keys_notes.push(["C3",  base + 24.0, 7.5, 55]);
    keys_notes.push(["E3",  base + 24.0, 7.5, 50]);
    rep += 1;
}
t_keys_seq.add_notes(keys_notes);
sleep(200);

// ── Bass: laid-back roots with walk to fifth ─

let t_bass_seq = edit.add_track("Bass", channel(2));
let bass_notes = [];
let roots = ["D2", "G1", "C2", "F1"];
let fifths = ["A2", "D2", "G2", "C2"];
let rep = 0;
while rep < 4 {
    let base = rep * 32.0;
    let chord = 0;
    while chord < 4 {
        let start = base + chord * 8.0;
        let root = roots[chord];
        let fifth = fifths[chord];
        bass_notes.push([root, start, 1.2, 100]);
        bass_notes.push([root, start + 2.0, 1.0, 90]);
        bass_notes.push([root, start + 3.5, 0.3, 65]);
        bass_notes.push([root, start + 4.0, 1.0, 95]);
        bass_notes.push([fifth, start + 6.0, 1.0, 85]);
        bass_notes.push([root, start + 7.5, 0.3, 60]);
        chord += 1;
    }
    rep += 1;
}
t_bass_seq.add_notes(bass_notes);
sleep(200);

// ── Kick: lo-fi boom bap ─────────────────────

let t_kick_seq = edit.add_track("Kick", channel(3));
let kick_notes = [];
let bar = 0;
while bar < 32 {
    let b = bar * 4.0;
    kick_notes.push(["C2", b, 0.3, 110]);
    kick_notes.push(["C2", b + 1.5, 0.3, 80]);
    if bar % 4 != 3 {
        kick_notes.push(["C2", b + 2.0, 0.3, 95]);
    }
    if bar % 4 == 3 {
        kick_notes.push(["C2", b + 2.5, 0.2, 85]);
        kick_notes.push(["C2", b + 3.0, 0.2, 90]);
    }
    bar += 1;
}
t_kick_seq.add_notes(kick_notes);
sleep(200);

// ── Snare: rimshot on 2 and 4 ────────────────

let t_snare_seq = edit.add_track("Snare", channel(4));
let snare_notes = [];
let bar = 0;
while bar < 32 {
    let b = bar * 4.0;
    snare_notes.push(["C3", b + 1.0, 0.2, 90]);
    snare_notes.push(["C3", b + 3.0, 0.2, 95]);
    if bar % 2 == 1 {
        snare_notes.push(["C3", b + 2.5, 0.1, 45]);
    }
    if bar % 4 == 2 {
        snare_notes.push(["C3", b + 0.5, 0.1, 40]);
    }
    bar += 1;
}
t_snare_seq.add_notes(snare_notes);
sleep(200);

// ── Hihat: 8th notes with groove ─────────────

let t_hat_seq = edit.add_track("Hihat", channel(5));
let hat_notes = [];
let beat = 0.0;
while beat < 128.0 {
    let vel = if beat % 2.0 < 0.01 { 60 }
        else if beat % 1.0 < 0.01 { 45 }
        else { 30 };
    hat_notes.push(["C4", beat, 0.1, vel]);
    beat += 0.5;
}
t_hat_seq.add_notes(hat_notes);
sleep(200);

zoom_to_fit();

// ── Wire sequencer → instruments ─────────────

seq.output(t_keys_seq.track_port()).port().connect(keys.input("MIDI In").port());
seq.output(t_bass_seq.track_port()).port().connect(bass.input("MIDI In").port());
sleep(200);

let kick_cv = MidiToCv.add("kick_cv");
seq.output(t_kick_seq.track_port()).port().connect(kick_cv.input("MIDI In").port());
kick_cv.output("Gate").port().connect(kick.input("Gate In").port());
sleep(200);

let snare_cv = MidiToCv.add("snare_cv");
seq.output(t_snare_seq.track_port()).port().connect(snare_cv.input("MIDI In").port());
snare_cv.output("Gate").port().connect(snare.input("Gate In").port());
sleep(200);

let hat_cv = MidiToCv.add("hat_cv");
seq.output(t_hat_seq.track_port()).port().connect(hat_cv.input("MIDI In").port());
hat_cv.output("Gate").port().connect(hat.input("Gate In").port());
sleep(200);

zoom_to_fit();
sleep(500);

// ── Start playback ───────────────────────────

play();
toast("Lo-Fi Chill - 75 BPM", "info", "center");
sleep(2000);

toggle("console", false);
zoom_to_fit();

// Let the intro breathe - keys + vinyl fade in (bars 1-8)
sleep(10000);

// Warm up Mode3D early - spawns the scene invisibly so shaders
// compile while we build the patch. The actual toggle is instant.
toggle("preload_3d", "graph");

// Groove A kicks in - drums + bass (bars 9-16)
sleep(10000);

// ══════════════════════════════════════════════
//  ACT 2: ACTIVITY MONITOR
// ══════════════════════════════════════════════

autozoom(false);
zoom_to_fit();
sleep(1000);

toggle("activity");
sleep(3000);

// Zoom into master so the stats are readable on camera
melody.zoom();
sleep(5000);

// ══════════════════════════════════════════════
//  ACT 3: MODE3D
// ══════════════════════════════════════════════

toggle("activity");
sleep(1500);


toast("Space time!", "info", "center");
sleep(1000);

melody.select();
toggle("3d", "graph");
toggle("ship");

// Groove B - melody floats in over the 3D visuals
sleep(23000);

stop();
Graph Engine
Lock-free audio graph with typed ports, sample-accurate scheduling, and zero-copy audio routing.
Live Editor
Immediate-mode UI. Patch, tweak, and audition without ever stopping the audio thread.
Scripting
Rhai layer for composition, sequencing, and procedural patch generation from code.
MIDI
Configure virtual devices once, then route them to any MIDI-aware node in the graph.
Granular
Modular grain pipeline - scheduler, voice splitter, sources, mixer. Build your own engine.
Arrangement
Clip launchers, sequencers, and gated sequencers for linear and non-linear composition.