sprout-garden-sound-engine
Sprout Garden: Sound Engine
The garden plays music. Strudel makes it happen.
The Vision
The garden isn't just accompanied by music - the garden IS the composition.
- Sprouts flowing through plots = notes triggering
- Loops = rhythmic patterns
- Parallel paths = polyphony
- Transforms = timbral changes
- The visualization IS the sequencer
Strudel Integration
Strudel is TidalCycles for the browser - live coding music through patterns. It's the perfect audio engine for Sprout Garden because both are fundamentally about patterns.
Why Strudel?
| Feature | Benefit |
|---|---|
| Browser-native | No installation, works in same context as game |
| Pattern-based | Same mental model as garden flow |
| Web Audio API | High performance, low latency |
| TidalCycles heritage | Battle-tested pattern language |
| Open source | Can embed and extend |
The Mapping
Garden Event → Strudel Pattern
─────────────────────────────────────────
Sprout enters plot → Note triggers
Plot type → Sound/instrument
Sprout color → Pitch or filter
Sprout shape → Sample or synth
Loop iteration → Pattern cycle
Fork (1→many) → Chord / polyphony
Grafter (many→1) → Note cluster
Tick → Beat subdivisionExample Flow
Garden path:
🌱 → → ⚙️ → → 🎨 → → 🎯Strudel pattern equivalent:
s("spring:emit vine vine gear:transform vine vine bloom:transform vine harvest:arrive")
.sound("piano")
.scale("C:pentatonic")Each plot type maps to a note in the scale. The sequence of plots = the melody.
Architecture
Option 1: Event-Driven
Garden emits events, Strudel plays them:
// Garden simulation emits
garden.on('sprout:enter', (sprout, plot) => {
strudel.trigger({
sound: plotSounds[plot.type],
note: colorToNote[sprout.color],
duration: '8n'
});
});
garden.on('sprout:transform', (sprout, before, after) => {
strudel.trigger({
sound: 'transform',
note: shapeToNote[after.shape],
fx: 'filter:sweep'
});
});Option 2: Pattern Generation
Garden generates Strudel pattern strings:
function gardenToPattern(path) {
const notes = path.map(step => plotToNote(step.plot));
return `s("${notes.join(' ')}")`;
}
// Execute the pattern
strudel.repl(gardenToPattern(sprout.lineage));Option 3: Hybrid (Best)
- Background pad: Strudel pattern loops based on garden structure
- Event triggers: Individual sounds on sprout events
- Generative: Pattern evolves as garden changes
// Background: garden structure → looping pattern
const backgroundPattern = generateBackgroundPattern(garden);
strudel.repl(backgroundPattern);
// Events: sprout movement → triggers
garden.on('tick', (sprouts) => {
for (const sprout of sprouts) {
triggerSproutSound(sprout);
}
});Sound Design
Plot → Sound Mapping
| Plot | Sound | Character |
|---|---|---|
| Spring 🌱 | Pluck/bell | Beginning, bright |
| Vine → | Quick blip | Movement, passing |
| Form Grower ⚙️ | Mechanical click + tone | Transformation |
| Color Bloomer 🎨 | Chime/shimmer | Color = pitch |
| Delay ⏱️ | Sustained pad | Held note |
| Gate 🚧 | Pass: ding / Block: thunk | Success/fail |
| Fork ⑂ | Chord (split) | One becomes many |
| Grafter ⊕ | Resolution chord | Many become one |
| Harvest 🎯 | Resolution/arrival | Completion |
Color → Pitch
| Color | Note | Feeling |
|---|---|---|
| Red 🔴 | C | Root, grounded |
| Green 🟢 | E | Third, warmth |
| Blue 🔵 | G | Fifth, open |
| Yellow 🟡 | A | Sixth, bright |
Pentatonic - can't hit a wrong note.
Shape → Instrument/Timbre
| Shape | Instrument | Texture |
|---|---|---|
| Circle ● | Sine/pad | Smooth, round |
| Square ■ | Square wave | Edgy, digital |
| Triangle ▲ | Triangle wave | Hollow, flute-like |
| Star ★ | Bell/pluck | Bright, sparkly |
Loop → Rhythm
A loop in the garden creates a rhythmic pattern:
⊕ → ⚙️ → 🎨 → ❓
↑ ↓
└───────────────┘This is literally a musical loop. Each iteration = one bar/cycle.
Strudel pattern:
s("merge gear bloom check").loop()Soundpacks
Same garden, different vibes:
| Pack | Aesthetic | Use Case |
|---|---|---|
| Cartoon | Boings, bloops | Fun, kids |
| Chiptune | 8-bit | Retro game |
| Glass | Crystal bells | Ambient, calm |
| Nature | Water, birds | Zen garden |
| Synth | Analog pads | Focus mode |
| Orchestra | Strings, woodwinds | Elegant |
| Techno | Kicks, hats | Daddy mode 🎧 |
Switch soundpack = same garden plays different genre.
Implementation Path
Phase 1: Basic Triggers
- Load Strudel as dependency
- Map plot types to sounds
- Trigger on sprout events
- Volume/mute control
Phase 2: Generative Background
- Generate pattern from garden structure
- Background pad based on garden "shape"
- Tempo tied to tick rate
Phase 3: Full Integration
- Garden edits = pattern edits (live coding!)
- Export garden as Strudel pattern
- Import Strudel pattern as garden (!)
- Visualize sound patterns as garden paths
Phase 4: The Reverse
Parse Strudel patterns into gardens.
s("bd sd bd sd")Becomes:
🌱 → 🔵 → 🟢 → 🔵 → 🟢 → 🎯
kick snare kick snareThe pattern IS the garden. The garden IS the pattern.
Research Links
- Strudel REPL - Try it live
- Strudel Getting Started
- TidalCycles - The original
- Strudel on Codeberg - Source
- CDM article on Strudel
- Hackaday: Live Coding Techno
The Dream
A kid builds a garden. The garden plays music. They don't know they're composing.
An adult builds a workflow. The workflow plays music. They debug by ear.
A musician plays music. The music draws gardens. They compose visually.
Same thing. Different entry points.
🌱 = 🎵 = 🚂 = 📊
Tags
sprout-garden, sound-design, strudel, tidalcycles, generative-music, live-coding, web-audio
Slots
North
slots:
- sprout-gardenSouth
slots: []East
slots: []West
slots: []