home/ modules/ chuck-debugging-and-live-recovery

ChucK debugging and live recovery: from silent failures to panic patches

  • learner can identify and fix ChucK's four silent-failure modes — no time advance, broken dac path, un-triggered envelope, and clipping gain — before any sound leaves the speaker
  • learner can classify a ChucK error as compile-time, runtime, or silent failure and apply the correct recovery action for each class without stopping the set
  • learner can hand-roll pitch, scale, and rhythmic structures using `Std.mtof`, `int[]` arrays, and `dur` arithmetic to work around ChucK's absent higher-level primitives
  • learner can deploy a minimal panic patch via `Machine.replace` to restore a stable drone within seconds of a catastrophic shred failure

Given a deliberately broken ChucK session — containing at least one silent infinite loop, one disconnected UGen chain, one un-triggered ADSR, one mis-cased UGen class name, one integer-division timing bug, and voices summed hot enough to clip — diagnose each failure class (compile-time vs runtime vs silent), apply targeted fixes in the running VM without restarting ChucK, then replace the session with a self-contained five-voice texture that uses hand-rolled scale quantization, sporked shreds with correct lifetimes, event-based synchronisation between voices, safe gain staging across all voices, and a tested panic patch swappable at any point via Machine.replace.

This module teaches ChucK from the angle that matters most in a live performance context: not what the language can do in theory, but why it silently fails in practice, and how to recover without stopping the set. ChucK’s strongly-timed model is a source of both its power and its most persistent bugs — the same => now idiom that gives sample-accurate control also means any loop without it pins the CPU and emits nothing, with no error to find. By the end of this module, learners have a systematic mental model of every common failure mode and a practiced recovery protocol.

The arc begins with the mechanics layer — the twelve L1 facts that encode ChucK’s distinctive rules. Before you can debug, you must know that => is context-sensitive (patch, assign, or control depending on operand types); that the DAC must be transitively reached or nothing plays; that integer literals divide as integers (1/2 == 0); that dur and time are typed and cannot mix with bare floats; that UGen class names are exact CamelCase checked against names/ugens.txt; that raw MIDI integers sent to .freq play that many Hz (use Std.mtof); and that ChucK has no native scale, chord, or euclidean primitive — these must be hand-rolled. This is the grammar of silence: knowing each rule is knowing one more way a program can be inexplicably quiet.

The middle arc introduces the debug classification framework from chuck-error-surface-modes: compile-time errors (shred never added, existing voices unaffected), runtime errors (offending shred removed, others survive), and silent failures (no error at all — the hardest class). The four canonical silent failure modes are then practised in isolation:

  1. No time advancechuck-silent-failure-no-time-advance: the VM appears frozen at 100% CPU.
  2. Broken dac pathchuck-dac-path-required: a beautifully-patched voice that the dac never sees.
  3. Un-triggered envelopechuck-envelope-needs-gate-trigger: ADSR or STK instrument stays closed until keyOn/noteOn.
  4. Gain clippingchuck-gain-staging-no-master-limiter: three voices at full gain sum to distortion with no warning.

These are practised first on minimal isolated patches (single-bug drills), then in combination on a “sabotaged session” — a provided set of three to five intentionally broken .ck files. Each drill has a diagnosis step (classify the failure mode, locate the line) and a repair step (apply the minimal fix, verify audio restores).

The shred-lifecycle cluster (chuck-shred-lifecycle, chuck-sporked-shred-lifetime, chuck-event-signal-vs-broadcast) is introduced in a concurrent-voices exercise: building a drum texture from sporked shreds that broadcast a shared downbeat event. Learners discover that sporked children die with their parent — so long-running voices must be sporked from a persistent top-level shred — and practise signal() versus broadcast() to selectively mute one voice without killing others.

The chuck-no-native-scale-chord atom drives the compositional section: learners hand-roll a pentatonic scale as an int[] of MIDI degrees, use Std.mtof for frequency lookup, and build a simple euclidean onset array for rhythmic placement. This is deliberately low-level — the point is that ChucK forces explicit data structures where Strudel offers one-liners, and that awareness prevents the mistake of looking for a function that does not exist.

The capstone synthesises every thread. A provided broken session contains exactly one instance of each silent failure class, plus an integer-division timing bug and a sporked-shred lifetime error. Learners diagnose and fix each in the running VM (using Machine.add, Machine.replace, Machine.remove) without restarting ChucK. They then rebuild the session as a five-voice texture — two melodic voices using hand-rolled scales, one percussion voice using a euclidean array, one event-synchronised accent voice, and one ambient drone — with gain staging across all voices verified to remain below clipping. The final step is writing and testing the panic patch: a minimal SinOsc => dac with a timed loop, no sample dependencies, and low gain, swappable via Machine.replace at any moment. The panic patch must survive all four silent-failure modes by design — its existence as a tested fallback is what makes live performance in ChucK sustainable.

The supporting atoms (chuck-strongly-timed, chuck-ugen-chuck-operator, chuck-shreds-sporking) are not gated by the capstone but are referenced throughout the narrative as the deeper conceptual grounding beneath the debug rules. Learners who reach this module without prior ChucK exposure should work through those atoms first.

Atoms in this module

Required — these gate the capstone

In ChucK, a loop with no `=> now` computes in zero logical time and emits no sound
Misconception L1 Foundations F
ChucK's `=>` operator means patch, control, or assign depending on the operand types
Concept L1 Foundations F
A ChucK UGen only produces audio if it is chucked transitively to `dac`
Principle L1 Foundations F
ChucK STK instruments stay silent until `.noteOn()`, and an ADSR stays closed until `keyOn()`
Misconception L1 Foundations F
ChucK sums every UGen chucked to `dac` with no master limiter, so stacked voices clip
Principle L1 Foundations FD
Sporked ChucK shreds die when their parent shred ends
Fact L1 Foundations F
ChucK's `signal()` wakes one waiting shred while `broadcast()` wakes all
Fact L1 Foundations F
In ChucK, dividing two integer literals gives integer division, truncating toward zero
Misconception L1 Foundations F
In ChucK `dur`/`time` are typed and cannot mix with bare numbers — units need the `::` operator
Concept L1 Foundations F
ChucK UGen class names are CamelCase-exact and must be verified against `names/ugens.txt`
Fact L1 Foundations F
In ChucK a raw MIDI integer sent to `.freq` plays that many Hz — use `Std.mtof` to convert
Misconception L1 Foundations F
ChucK has no hot-reload path in this rig and runs as a separate process
Fact L1 Foundations FN
ChucK compile errors block shred addition while runtime errors remove only the offending shred
Concept L5 Voice F
A ChucK while-loop without a time-advance silently hangs the VM at 100% CPU with no audio
Misconception L5 Voice F
ChucK UGen names are exact CamelCase and must be verified against the rig's ugens list
Fact L5 Voice F
A ChucK voice that never reaches dac produces silence with no error
Misconception L5 Voice F
A ChucK ADSR envelope or STK instrument stays silent until its gate is opened with keyOn/noteOn
Misconception L5 Voice F
ChucK sporked child shreds are killed the moment their parent shred exits
Concept L5 Voice F
Integer division in ChucK silently truncates: 1/2 evaluates to 0, not 0.5
Misconception L5 Voice F
ChucK has no default master limiter, so many voices summed to dac clip unless gain is kept low
Principle L5 Voice F
A minimal ChucK panic patch uses SinOsc-to-dac with a timed while-loop and no sample files
Procedure L5 Voice F
ChucK has no native scale, chord, or euclidean primitive; these must be hand-rolled from arrays and Std.mtof
Fact L5 Voice F

Supporting — enrichment, not gating

ChucK is strongly-timed: advancing 'now' drives synthesis with sample-accurate control
Concept L2 First instrument FB
ChucK wires Unit Generators into a signal chain with the ChucK operator =>
Procedure L2 First instrument FB
ChucK shreds are sample-synchronous concurrent processes spawned with spork ~
Concept L3 Craft FB