home/ modules/ sonic-pi-concurrency-and-sync

Sonic Pi: concurrent live_loops and sync

  • learner can run multiple live_loops as concurrent threads without duplicate-instance bugs
  • learner can phase-align loops with cue/sync and Time State
  • learner can redefine named functions live to restructure a running piece

Live-code a Sonic Pi set with three concurrent named live_loops kept in phase via cue/sync and Time State, and restructure it mid-performance by redefining a function without stopping the audio.

A real Sonic Pi set — the kind you’d play at an algorave or stream from a bedroom rig — is never one loop. It is a drum part, a bassline, and a melodic layer running at once, staying locked to a shared groove while you rewrite the music underneath the audience’s feet. This module builds exactly that skill: keeping three concurrent voices in phase and restructuring the piece live, with the audio never stopping.

The arc starts from the beginner’s wall: writing two infinite loops in sequence and hearing only the first. Understanding why sequential loops fail motivates everything after. From there, a first supported exercise layers parts with “in_thread do … end launches a concurrent execution path” and discovers the Run-button mechanic — each press adds a thread rather than restarting. That immediately exposes the duplicate-instance trap, solved by named threads, which are also the conceptual bridge to live_loop’s hot-swap behaviour. A second exercise deliberately lets two loops drift, then repairs them using “cue broadcasts a named event and sync blocks until the next occurrence” and the auto-generated cue events every live_loop emits. Time State (get/set) then replaces fragile shared variables so loops can coordinate deterministically. Finally, the define/redefine pattern — swap a function’s body while a loop keeps calling it — gives you live restructuring.

The required atoms gate the capstone directly: you cannot run three loops, phase-align them, or hot-swap a function without them, and the drills (cue/sync, loop-to-loop sync, redefine-while-running) must be automatic under performance pressure. Supporting atoms enrich the same territory — the race-condition misconception explains why Time State exists, Reich-style phasing turns drift into an aesthetic, control of SynthNode references enables post-trigger parameter gestures, and the MIDI/OSC atoms extend sync to external hardware for a bigger rig.

Runnable examples

Generated from the context/ instrument corpus by concept (redistributable idioms only). Do not edit — regenerate with gen-module-examples.mjs.

live-hot-swap

live_loop :x do; play 60; sleep 1; end

sonicpi-0048 · CC0

Ndef(\a, { SinOsc.ar(220) * 0.1 }).play

supercollider-0037 · CC0

event-driven-sync

live_loop :hats, sync: :tick do; sample :drum_cymbal_closed; sleep 0.25; end

sonicpi-0049 · CC0

Event e; fun void hit(){ e => now; <<<"go">>>; }
spork ~ hit(); spork ~ hit(); 1::ms => now; e.broadcast();

chuck-0014 · MIT

Atoms in this module

Required — these gate the capstone

Pressing Run in Sonic Pi adds a new concurrent thread without stopping existing threads
Concept L2 First instrument F
Named threads in Sonic Pi prevent duplicate instances when Run is pressed multiple times
Concept L2 First instrument F
in_thread do ... end launches a concurrent execution path while the main thread continues
Procedure L2 First instrument F
Two infinite loops written in sequence can never both run, because the first loops forever and the second is never reached
Concept L2 First instrument FN
cue broadcasts a named event and sync blocks until the next occurrence of that event
Procedure L2 First instrument F
live_loops auto-generate cue events that other live_loops can sync on for phase alignment
Procedure L3 Craft F
Sonic Pi's Time State (get/set) provides deterministic shared state across live_loops
Concept L3 Craft F
sync in Sonic Pi always blocks until a future Time State event is inserted
Concept L3 Craft F
define :name do ... end creates reusable code blocks that persist and can be redefined between runs
Procedure L2 First instrument F
Redefining a named function while a named thread loops is the foundational Sonic Pi live-coding pattern
Procedure L3 Craft F

Supporting — enrichment, not gating

play, synth, and sample return a SynthNode reference that enables post-trigger parameter changes
Concept L3 Craft F
Sharing mutable variables across Sonic Pi threads causes non-deterministic race conditions
Misconception L2 First instrument F
Two live_loops with slightly different sleep times produce Steve Reich-style phasing
Procedure L3 Craft FA
Sonic Pi's Time State paths support OSC-style wildcard pattern matching for sync and get
Concept L3 Craft F
Sonic Pi listens on port 4560 for OSC messages and routes them into Time State automatically
Procedure L3 Craft F
Sonic Pi auto-inserts incoming MIDI events into Time State, enabling sync and get on them
Procedure L3 Craft F
Sonic Pi sends MIDI messages in sync with music via midi, midi_note_on, and related functions
Procedure L3 Craft F
use_real_time removes Sonic Pi's scheduling look-ahead for MIDI and OSC-driven live loops
Procedure L3 Craft F
Live coding systems achieve progressive evaluation through external grounding, internal grounding, temporal recursion, or hybrid state management
Concept L3 Craft FN
Event-driven sync lets a concurrent voice block on a named cue and be woken by a broadcast — distinct from time-grid quantization
Concept L2 First instrument FA
Live hot-swap — replacing a running pattern or voice definition live without stopping audio — is the single most portable concept in the registry
Principle L1 Foundations FA