T
ThePrimeagen
#Strudel.cc#Live Coding#JavaScript

Strudel.cc: Live Code Music with JavaScript & Vim

Learn how to create live electronic music using Strudel.cc, a JavaScript-based live coding environment. This guide covers basic sound generation, pattern creation, and advanced music programming techniques.

5 min readAI Guide

Introduction

Strudel.cc is a powerful JavaScript-based live coding environment that allows developers to create music in real-time directly within a web browser. It provides an interactive Read-Eval-Print Loop (REPL) for immediate auditory feedback, making it an accessible tool for combining programming skills with musical expression.

Configuration Checklist

Element Version / Link
Language / Runtime JavaScript (for Strudel), Lua (for Vim integration), Bun (for server)
Main library Strudel.cc, Playwright, curl, Nvim
Required APIs Strudel REPL, Playwright API
Keys / credentials needed None for Strudel.cc directly. Twitch API keys would be needed for Twitch chat integration (not explicitly detailed in the video's implementation).

Step-by-Step Guide to Live Coding Music with Strudel.cc

Step 1 — Setting up the Strudel Environment

To begin, navigate to the Strudel.cc website. The platform provides an interactive REPL where you can type and execute code to generate sounds instantly. This immediate feedback loop is crucial for live coding.

Step 2 — Generating Basic Sounds

Strudel operates on cycles, similar to musical timing. To create a simple high-hat sound that repeats, use the sound function with the "hh" string. This will play the high-hat sound continuously.

sound("hh") // Plays a high-hat sound repeatedly in cycles

Step 3 — Controlling Tempo with Cycles Per Minute (CPM)

To adjust the overall tempo of your music, use the setcpm() function. This sets the number of cycles that occur per minute, allowing you to speed up or slow down your patterns.

setcpm(20) // Sets the tempo to 20 cycles per minute
sound("hh") // The high-hat will now play at the new tempo

Step 4 — Creating Rhythmic Patterns with Mini-Notation

Strudel's mini-notation allows for more complex rhythmic patterns. You can introduce rests using the ~ character and group sounds into sub-patterns using square brackets []. Wrapping a group with carets < > ensures each subgroup plays for one cycle, enabling intricate rhythms.

sound("hh hh hh hh") // Four high-hats per cycle
sound("hh ~ hh hh ~ hh") // High-hats with rests for varied rhythm
sound(" [hh ~ hh ~] [hh ~ hh hh] [hh ~ hh ~] [hh hh hh hh] ") // Sub-grouping for complex patterns

Step 5 — Importing and Stacking Sounds

You can define different sound patterns (like high-hats, kick drums, and basslines) and then combine them using the stack() function. This allows multiple patterns to play simultaneously, building up your musical arrangement.

// Define high-hat pattern
var hh = sound(' <[hh ~ hh ~] [hh ~ hh hh] [hh ~ hh ~] [hh hh hh hh]> ')

// Define kick drum pattern
var kick = sound(' [bd ~ bd ~] [bd ~ ~ ~] [bd ~ ~ bd] [bd ~ ~ ~] ')

// Define bassline using notes and effects
let bass = note("<[a1 a2 g2] ~ [~ e2] ~ [d2 c2 a1] [e2 g2]>")
  .sound("gm_synth_bass_2") // Use a general MIDI synth bass sound
  .room(0.5) // Add some reverb
  .lpf(sine.range(300, 800).slow(8)) // Apply a low-pass filter with a slowly changing frequency

// Stack the sounds to play them together
stack(hh, kick, bass)

Step 6 — Arranging Sections with arrange()

The arrange() function allows you to sequence different musical sections over a specified number of cycles. This is essential for structuring a full song, letting you introduce or remove instruments and patterns at specific times.

// Arrange the bassline, kick, and high-hats over different cycles
arrange(
  [2, bass], // Play only the bassline for 2 cycles
  [2, stack(bass, kick)], // Play bass and kick for 2 cycles
  [8, stack(bass, kick, hh)] // Play bass, kick, and high-hats for 8 cycles
).play() // Start playing the arrangement

Step 7 — Advanced Sound Manipulation and Effects

Strudel provides a rich set of functions for manipulating sounds, including adding structure, clipping, strumming, reverberation, filtering, and delays. These can be chained together to create unique and evolving soundscapes.

let melody = note("<[a3, e3, c4, g4] [c4, e4, g4, a4] [d4, f#4, a4, c5]>" ) // Define a melody with notes
  .struct("[<[x ~] * 2 [4 2]> <[~ x] * 2 [x * 4] x>] ") // Add rhythmic structure
  .mask("<1@1000>") // Apply a mask for rhythmic variation
  .clip(rand.range(.2, .4)) // Randomly clip out parts of the sound
  .ply("<2@3 [2 4] 2@3 [2 4]>" ) // Add strumming effect
  .room(0.25) // Add reverberation
  .lpf(sine.range(500, 1400).slow(8)).lpq(5) // Apply a low-pass filter with resonance
  .sound("supersaw") // Use a supersaw waveform for the sound
  .delay(sine.range(0.1, 1).slow(8)) // Add a delay effect with a slowly changing range

melody // Play the manipulated melody

Step 8 — Integrating Vim with Strudel.cc for an Enhanced Workflow

For advanced users, integrating Vim with Strudel.cc allows for a highly efficient live coding setup. This involves running a local server (e.g., with Bun and Playwright) that listens for code changes from Vim and updates the Strudel.cc browser instance.

  1. Start a Bun server with Playwright: This server will control a browser instance where Strudel.cc is running.
    
    

bun run src/server.ts --ozone-platform=wayland
```
* bun run src/server.ts: Executes the TypeScript server file using Bun.
* --ozone-platform=wayland: Specifies the Wayland platform for Playwright, common in Linux environments.

  1. Send code from Vim to the server: Use a curl command within Vim (e.g., via Lua scripting) to post the current buffer's content to your local server. The server then injects this code into Strudel.cc.
    
    

local ok = pcall(curl.post, "http://localhost:3000/update", {
body = table.concat(result, "\n"), -- The code from your Vim buffer
headers = {}, -- Any necessary HTTP headers
callback = function() print("Updated!") end, -- Callback after successful update
})
```
* pcall(curl.post, ...): Safely calls a curl.post function (assuming curl is a Lua module or function available in Vim).
* "http://localhost:3000/update": The endpoint on your local Bun server that receives the code.
* body = table.concat(result, "\n"): The content of the Vim buffer, joined by newlines, sent as the request body.

This setup allows you to write and modify your Strudel.cc music code directly in Vim, leveraging Vim's powerful editing capabilities, and instantly hear the changes in the browser.

⚠️ Common Mistakes & Pitfalls

  1. Underestimating JavaScript: Many programmers might dismiss JavaScript for music creation. However, Strudel.cc demonstrates its capability for complex audio synthesis and live performance when used with specialized libraries and a REPL.
  2. Ignoring Cycle-Based Timing: Strudel.cc operates on musical cycles, not traditional event loops. Misunderstanding this can lead to incorrect timing and synchronization issues. Always think in terms of beats and cycles when structuring your patterns.
  3. Repetitive Patterns: Beginners often create simple, repetitive patterns. Utilize Strudel's mini-notation features like rests (~), sub-grouping ([]), and caret-wrapped groups (< >) to introduce variation and complexity into your rhythms and melodies.
  4. Lack of Structure: Without proper arrangement, live-coded music can sound chaotic. Employ the arrange() function to sequence different musical ideas and build a coherent song structure, introducing and removing elements dynamically.

Glossary

REPL: A Read-Eval-Print Loop is an interactive programming environment that takes single user inputs, executes them, and returns the result to the user.
Strudel.cc: A JavaScript-based live coding environment designed for real-time music creation and performance in a web browser.
Mini-notation: A compact, string-based syntax used within Strudel.cc to define rhythmic and melodic patterns, including notes, rests, and grouping.

Key Takeaways

  • Strudel.cc offers a unique platform for live coding electronic music using JavaScript in an interactive browser environment.
  • Its REPL provides instant auditory feedback, accelerating the creative process for musical programming.
  • The mini-notation system simplifies the creation of complex rhythmic and melodic patterns with concise syntax.
  • Advanced integration with text editors like Vim and tools like Playwright can significantly enhance the live coding workflow.
  • Live coding music is a powerful way to combine programming skills with musical artistry, allowing for dynamic and expressive performances.

Resources