home/ modules/ debugging-and-recovery-in-strudel

Debugging and recovery in Strudel

  • learner can identify the five silent-failure patterns in Strudel — wrong sample names, locked AudioContext, missing .analyze('hydra'), orbit sharing, and gain clipping — and apply the correct fix for each
  • learner can distinguish error-throwing failures (shown in #err, old pattern kept playing) from silent failures (no exception, no audio or no reactivity) and choose the right diagnostic step for each surface
  • learner can write correct mini-notation using * vs !, polymeter {…}%n, and pattern/signal arguments in place of thunks, and read tempo correctly via setcpm
  • learner can recover a broken or runaway Strudel mix live — using hush() then a minimal synth-only AV groove — and explain why failed evaluates leave the previous pattern running

Take a seeded Strudel session file containing at least ten bugs — an unknown sample name (silent, no exception), a locked-AudioContext startup sequence, a missing .analyze('hydra') tag, a thunk passed where a signal is required, a * / ! notation swap that changes the rhythm, a polymeter {…} group missing its %n suffix so it inherits the wrong step count, an unbalanced mini-notation bracket that throws in #err while the old pattern keeps playing, a crush call using a 0–1 value instead of a 1–16 bit-depth, a setcpm call set to raw BPM, and a multi-voice session where all orbits share a single bus — and, without looking up solutions, diagnose each failure using the two-surface model (check #err first, then reason from symptom), classifying each as throwing vs silent. Fix every bug by re-saving edits into the gaplessly re-evaluating session (never restarting the page), then write a complete panic recovery block: hush() followed by a minimal three-voice groove (synth bass, hi-hat, pad) at the correct tempo with each voice on its own $: line, independent orbits, gain in the 0.6–0.8 range, and the audio-reactive voice tagged with .analyze('hydra'). Annotate each fix and each line of the panic block with the rule it satisfies, and explain why a failed evaluate leaves the previous pattern running rather than cutting audio.

This module is built around one professional reality: silence is ambiguous. In a Strudel session — at an algorave, a classroom, a bedroom stream — a voice that plays nothing gives you no error, no dialog box, no stack trace. It might be a wrong sample name, a still-locked AudioContext, a missing .analyze('hydra') tag, a method that received a thunk instead of a signal, or a mix gone quiet because gain staging collapsed. Knowing which silent-failure pattern you are in, and what the diagnostic step is for each, is the fluency that separates a working browser performer from someone who restarts the page.

The twenty-one atoms here span two interlocking layers. The first (L1 gotchas) covers failures you hit in the first hour of Strudel: sample names that must match exact folder names in the dirt-samples bank (bd not kick; cp not clap); the browser autoplay policy that keeps audio silent until the first user click; the Strudel→Hydra FFT bridge that reads zero unless the driving pattern carries .analyze('hydra'); mini-notation traps where * speeds hits into one step while ! replicates across steps, or where a polymeter {…} group silently adopts the wrong step count without the %n suffix; the cross-DSL mistake of passing a thunk () => … where Strudel expects a pattern or signal (sine.range(200, 2000)); the tempo trap of calling setcpm(120) and getting a very fast two-cycles-per-second pulse instead of a 30-BPM feel; orbit sharing where all voices default to orbit(0) and accidentally pool their reverb and delay sends; and multiplicative gain stacking that clips silently as voices accumulate.

The second layer (L5 debug) teaches you to use the error surface systematically. Strudel errors split into two classes: those that throw — a syntax error, an undefined method, unbalanced mini-notation brackets — and those that do not. Throwing errors appear in the on-page #err element as strudel: <message>; the previous pattern keeps playing and nothing is installed. Silent failures (unknown sample, locked AudioContext, missing bridge tag) throw nothing — #err stays clear, but a voice is mute or a visual is static. The diagnostic loop is short: check #err first; if clear, match the symptom to the five known silent-failure patterns. “Check #err first; if empty, reason from symptom” is the complete procedure.

Panic recovery enters as a first-class skill. When the mix is unrecoverable — runaway gain, wrong samples, broken patterns all firing at once — hush() stops every registered voice immediately, the equivalent of stopping all live_loops in Sonic Pi. The canonical recovery sequence is hush() followed by a minimal synth-only groove (no sample bank dependency) with .analyze('hydra') so the visual bridge stays alive through the reset. This sequence can be typed in under ten seconds and should be drilled until automatic.

The capstone exercises all four objectives together under no-scaffold conditions. The learner receives a seeded bug file, must work through the two-surface diagnostic loop without hints, fix every bug, and write their own panic block from memory. The annotation requirement forces explicit reasoning: each fix names the failure class and the rule it violates; each line of the panic block names the constraint it satisfies. That documentation becomes a personal recovery protocol the performer can revisit before any set.

Atoms in this module

Required — these gate the capstone

Strudel sample names must match folders in the loaded bank — s("kick"), s("clap"), s("snare") are silent because the real folder names are bd, cp, sd
Fact L1 Foundations F
Strudel produces no sound until the first user click unlocks the browser AudioContext — silence at startup is autoplay policy, not a bug
Fact L1 Foundations F
Strudel patterns must include .analyze('hydra') for visuals to receive FFT data — an untagged pattern plays audio but the visuals see a.fft = 0
Fact L1 Foundations FJ
Strudel mini-notation * speeds hits into one step's time while ! replicates across steps — mixing them changes the rhythm
Concept L1 Foundations F
Strudel polymeter with {…} requires the %n step-count suffix; without it the first group's length sets the step count for all groups
Concept L1 Foundations F
Strudel takes patterns/signals as arguments (not thunks like Hydra) — .lpf(sine.range(200,2000)) is correct; .lpf(() => ...) is a cross-DSL mistake
Misconception L1 Foundations F
Strudel's setcpm is cycles-per-minute not BPM — setcpm(120) is very fast; use setcpm(BPM/4) for the standard 4-beats-per-cycle feel
Fact L1 Foundations F
All Strudel voices default to orbit(0), so their reverb and delay sends share one bus — split voices with .orbit(n) for independent wet levels
Concept L1 Foundations F
Strudel gain stacks multiplicatively and clips — several loud voices distort, so keep per-voice gain well under 1
Concept L1 Foundations F
Strudel's crush takes a bit-depth (1–16), not a 0–1 knob — crush(4) is heavy, crush(16) is nearly clean
Fact L1 Foundations F
Strudel re-evaluates on save without cutting audio — a syntax error keeps the previous pattern playing while the edit is not applied
Fact L1 Foundations F
A failed Strudel evaluate leaves the previously running pattern playing rather than stopping audio
Concept L5 Voice F
An unknown Strudel sample name produces silence with no exception rather than an error
Misconception L5 Voice F
Unbalanced mini-notation brackets in Strudel throw a parse error that shows in #err while keeping the old pattern playing
Fact L5 Voice F
Strudel method parameters accept patterns and signals, not JavaScript arrow functions — use sine/saw/rand for movement
Principle L5 Voice F
Strudel audio requires a user gesture to unlock the AudioContext — code cannot force it
Fact L5 Voice F
Adding .analyze('hydra') to a Strudel voice feeds it to the a.fft array that Hydra's audio-reactive mapping reads
Principle L5 Voice FJ
Stacked loud Strudel voices or high delay feedback cause clipping — lower .gain toward 0.6-0.8 and reduce feedback
Principle L5 Voice F
Strudel's setcpm takes cycles per minute, not BPM — use setcpm(bpm/4) for 4-beat cycles
Fact L5 Voice F
Each independent Strudel voice in a multi-pattern session must be on its own $: prefixed line
Fact L5 Voice F
hush() immediately silences every Strudel voice — it is the first step of autonomous recovery from a broken mix
Procedure L5 Voice F

Supporting — enrichment, not gating

Strudel spaces every element of a pattern evenly within one fixed-length cycle
Concept L1 Foundations F
The $: prefix declares an independent pattern that plays simultaneously with other $: patterns
Procedure L1 Foundations F
Strudel audio effects are chainable methods that accept patterned values
Concept L1 Foundations F
Standard two-letter abbreviations map to drum kit sounds in Strudel's default sample set
Fact L1 Foundations F
bank() repoints a pattern's drum abbreviations at a named drum-machine sample set
Procedure L1 Foundations F