MrityunjayBhardwaj/SonicWeb

Sonic Pi in the browser — same play, sleep, live_loop. SuperCollider synthesis via Supersonic. No install.

7

stars

341

commits

Jupyter Notebook

primary language

Jul 18, 2026

updated

sonicweb.cc/
art
audio
eduction
instrument
live-code
livecoding
music
synthesis
synthesizer
Browse cluster: Music Audio and Synthesis Tools

README

Sonic Web

Your Sonic Pi code, now portable.

Sonic Web — live coding in the browser

CI Deploy npm beta License: MIT

Try it now at sonicweb.cc

v1.5 is in beta — published under both the latest and beta npm tags during stabilization. npm install @mjayb/sonicweb gets you the current beta; pin with @1.5.0-beta.4 for a fixed version.


Make music with code. In your browser.

Sonic Web is a browser-native reimplementation of Sonic Pi's live coding engine. Same Ruby DSL. Same synths. Same samples. No install.

I built this because Sonic Pi changed how I think about music and code, and I wanted that experience to be one click away for anyone with a browser.

All thanks to:

  • Sonic Pi & Sam Aaron — for proving that code is a musical instrument
  • SuperSonic — the WebAssembly port of SuperCollider that makes real synthesis possible in the browser
  • AudioWorklet — the browser API that makes low-latency audio processing work
  • Algorave community — for building a culture where live coding is performance art

The core idea: sleep as a scheduler-controlled Promise

Ruby's sleep blocks the thread. JavaScript can't — block the main thread and the UI freezes. Previous browser ports either gave up on multi-loop timing or simulated it with setTimeout, which drifts under load.

The trick we landed on: sleep returns a Promise that only the VirtualTimeScheduler can resolve. User code awaits the sleep; the scheduler advances virtual time and resolves Promises in deterministic order. The result is cooperative concurrency with virtual time across any number of live_loops, with audio events scheduled ahead of the AudioWorklet callback so they stay sample-accurate.

This means the JS engine inherits Sonic Pi's full temporal model — sync, cue, time_warp, with_fx, hot-swap — not a simplified approximation.

  • Ruby DSL → JS via Tree-sitter. Your Sonic Pi code is parsed into an AST and transpiled to JavaScript builder chains. Full structural awareness of blocks, symbols, and Ruby semantics. No regex hacks.
  • Real SuperCollider synthesis. Audio runs through SuperSonic (scsynth compiled to WebAssembly via AudioWorklet). Same synth definitions, same sound — not a simplified approximation.
live_loop :drums do
  sample :bd_haus
  sleep 0.5
  sample :sn_dub
  sleep 0.5
end

Press Run. Now add this while the drums are playing:

live_loop :bass do
  use_synth :tb303
  play :e2, release: 0.3, cutoff: rrand(60, 120)
  sleep 0.25
end

The bass joins in. Change a number. Hit Run again. The music updates instantly. That's live coding.


What can I do with it?

Write Sonic Pi code — the same Ruby DSL you know from desktop. live_loop, play, sleep, sample, with_fx, use_synth, sync, cue — it all works.

Perform live — 10 buffers, hot-swap on Re-run, Alt+R/Alt+S shortcuts, fullscreen mode, spectrum visualizer. Built for the stage.

Teach — zero setup means students open a URL and start coding. Friendly error messages with line numbers. Built-in examples from simple beats to full compositions.

Embed anywhere — drop the engine into any web page, LMS, or creative coding tool as an npm package.


Getting Started

Option 1: Just open the website

sonicweb.cc — nothing to install.

Option 2: Run locally

npx @mjayb/sonicweb@beta

Option 3: Embed in your app

npm install @mjayb/sonicweb@beta
import { SonicPiEngine } from '@mjayb/sonicweb'

const engine = new SonicPiEngine()
await engine.init()
await engine.evaluate(`
  live_loop :beat do
    sample :bd_haus
    sleep 0.5
  end
`)
engine.play()

No wiring needed — the engine loads SuperSonic (the GPL scsynth WASM core, from CDN, never bundled), the tree-sitter transpiler, and its PRNG table itself. Using a <script type="module"> with no bundler? Import the self-contained browser entry instead: import { SonicPiEngine } from '@mjayb/sonicweb/browser'.


What's included

FeatureDetails
63 synths (3 upstream synthdefs missing from the WASM CDN)beep, saw, prophet, tb303, supersaw, blade, hollow, pluck, piano, and more
197 samplesKicks, snares, hats, loops, ambient, bass, electronic, tabla
38 FXreverb, echo, distortion, flanger, slicer, wobble, pitch_shift, gverb, krush, and more
~148 DSL functions (~87% of upstream)live_loop, with_fx, define, defonce, in_thread, sync/cue/sync_bpm, density, time_warp, use_osc/osc, run_code, with_synth_defaults, with_sample_defaults
Per-loop audio isolationEach live_loop gets its own analyser bus — first Sonic Pi implementation to ship this
Music theory30+ chord types, 50+ scales, rings, spreads, Euclidean rhythms
10 buffersSwitch between code tabs like desktop Sonic Pi
Scope visualizerMono, stereo, lissajous, mirror, spectrum — all 5 Desktop SP modes
Cue LogLive cue/sync event stream in a dedicated panel
Live mixerPre-amp and Amp sliders in Prefs push to scsynth on drag
RecordingCapture your session to WAV (raw float32, lossless)
18 examplesFrom "Hello Beep" to a full Blade Runner x Techno composition
AutocompleteCode hints with inline descriptions
Help panel311 entries — functions, synths, FX, and samples with params and examples
PreferencesAudio, visuals, editor, and performance settings
Resizable panelsDrag splitters to resize scope, log, cue log, and help panel
Custom samplesUpload your own WAV/MP3/OGG files
Save/LoadExport and import your code as files
Friendly errors20 error patterns with "did you mean?" suggestions and line highlighting
Report BugOne-click bug report with pre-filled GitHub issue
FX A/B inspector (npm run inspect)Side-by-side desktop ↔ web spectrograms for every FX, with MFCC parity scoring

Keyboard shortcuts

ShortcutAction
Ctrl+Enter / Alt+RRun code
Escape / Alt+SStop all
Ctrl+/Toggle comment
F11Fullscreen
A- / A+Font size

Tech stack

TypeScript, Vite, Vitest (1491 tests across 68 files), CodeMirror 6, Web Audio API, WebAssembly (SuperCollider scsynth via SuperSonic).


Compatibility with Desktop Sonic Pi

Parity is measured end-to-end — not from unit tests alone, but by running each composition on both engines and comparing the result. Real desktop Sonic Pi runs the same .rb file over OSC; web runs it through the full pipeline (Ruby → transpile → scheduler → scsynth-WASM → audio); a launch gate then grades the two outputs.

Parity scores (latest launch gate)

MetricScoreWhat it measures
Launch gatePASSOverall: roster pass + differential matrix green
Official roster34/34 (100%)Non-heavy official examples, PRNG-graded by per-synthdef /s_new event-parity (threshold ≥70%)
Differential matrix52/52 cellsDesktop ↔ web structure-match — 0 diverge / timing / empty / error
Event-parity sweep151 / 154Full fixture corpus: 151 EVENT-MATCH · 0 DIVERGE · 3 non-gradeable by design
Unit tests1491 / 1491Vitest, across 68 files (npx vitest run)

The 3 non-gradeable fixtures are excluded by design (a counter probe, a density isolation probe, and a deliberate web-only feature test), not failures. Regenerate the gate yourself with npx tsx tools/gate-report.ts; the full per-fixture breakdown lives in test_results/launch-gate.md.

Browse the parity dashboards

Every fixture is browsable in the live parity dashboard — one overview links the official roster, the differential matrix, per-/s_new event-diffs, the launch gate, and the FX A/B inspector, each with desktop ↔ web spectrograms.

Every Ruby snippet on the dashboards is playable in the browser — ▶ Run / ■ Stop through the same engine that powers the editor — and carries an ↗ open in sonicweb.cc link that loads it straight into the live editor. Locally, open test_results/index.html, or serve the dashboards with inline audio via npm run dashboard:serve.

Feature coverage

  • 63/66 synths working end-to-end (3 upstream WASM LOAD-FAIL: dark_sea_horn, singer, winwood_lead)
  • 197/197 samples
  • 38 FX wired end-to-end and A/B WAV-verified against desktop (tools/fx-sweep.ts). No FX produces silence or wrong audio — every wired FX routes signal; differences are level/spectral-shape, not engine bugs. (delay and chorus are excluded — the upstream SuperSonic WASM synthdef package doesn't ship them, #301.)
  • ~148/170 DSL functions (~87% of upstream's user-facing surface)

Identical to desktop: seeded PRNG (Mersenne Twister), synth definitions, sample library, music theory, timing semantics, hot-swap, sync/cue.

Different in the browser:

  • Audio output is calibrated for browser WASM headroom (Sonic Tau's gain staging, pre_amp=0.3, amp=0.8), not Desktop SP's driver-attenuated levels. Comparator tools should RMS-normalise before A/B.
  • OSC output requires a host-provided transport (hook-based) — browsers can't open raw UDP sockets.
  • MIDI is wired internally but the device-picker UI ships in v1.6 (Tier D). Web MIDI works for input.
  • No filesystem access — sample paths from directories, eval_file, and user samples from disk are out of scope until the browser sandbox model changes.

See KNOWN_LIMITATIONS.md for permanent constraints and KNOWN_ISSUES.md for current beta-blocker bugs.

How does this compare to Sonic Tau?

Sonic Tau is Sam Aaron's official next-gen Sonic Pi for the browser, built on Elixir + Phoenix LiveView. Sonic Web is an independent JS-native engine you can npm install and embed in any web page. Tau is the future of the Sonic Pi project; this is for embedding the live-coding model into your own apps, courses, and tools.


What's new in v1.5-beta

  • Engine audit pass: 33 bugs fixed since v1.4, including 4 hot-swap state bugs (SP78–SP81) caught by Playwright + WAV reproducers
  • Real-world corpus: 56 compositions verified — MagPi Essentials chapters, 15 wizard/sorcerer/magician examples, 13 community forum compositions
  • New DSL: use_sample_bpm, midi shorthand, use_osc/osc, with_fx reps:, with_synth_defaults, with_sample_defaults, use_density, use_debug, defonce, sync_bpm, run_code, live_audio :stop
  • Tooling: FX A/B inspector (npm run inspect), e2e parity suite (test_results/e2e.html), capture tool with audio recording
  • Mixer: live Pre-Amp / Amp sliders, gain staging aligned to Sonic Tau (browser-WASM safe headroom)
  • Per-loop audio isolation — first Sonic Pi implementation to ship this

Full changelog: Releases.


Coming next

  • Tier C/D DSL completion — remaining ~22 helpers (with_synth, use_arg_checks, sample_paths, MIDI device picker UI, midi_pc/midi_raw/midi_sysex)
  • Tutorial system port — desktop Sonic Pi's 50+ chapter tutorial adapted for the browser
  • Ableton Link — UDP-over-WebSocket relay
  • Cross-browser CI matrix — Firefox + Safari coverage

Check out these cool projects

  • Sonic Tau — Sam Aaron's official next-gen Sonic Pi for the browser. Built with Elixir + Phoenix LiveView. The future of Sonic Pi.
  • Strudel — Alex McLean's live coding pattern language for the browser. Different paradigm (TidalCycles-inspired), equally mind-blowing.
  • Tone.js — Web Audio framework for building interactive music in the browser.

Contributing

Issues and PRs welcome. Pick an issue from the SonicWeb Roadmap board — area: audio, area: scheduler, and area: transpiler labels are good entry points. See CONTRIBUTING.md for setup and workflow.

License

MIT. See LICENSE.

Contributors

MrityunjayBhardwaj/SonicWeb

Sonic Pi in the browser — same play, sleep, live_loop. SuperCollider synthesis via Supersonic. No install.

7

stars

341

commits

Jupyter Notebook

primary language

Jul 18, 2026

updated

sonicweb.cc/
art
audio
eduction
instrument
live-code
livecoding
music
synthesis
synthesizer
Browse cluster: Music Audio and Synthesis Tools

README

Sonic Web

Your Sonic Pi code, now portable.

Sonic Web — live coding in the browser

CI Deploy npm beta License: MIT

Try it now at sonicweb.cc

v1.5 is in beta — published under both the latest and beta npm tags during stabilization. npm install @mjayb/sonicweb gets you the current beta; pin with @1.5.0-beta.4 for a fixed version.


Make music with code. In your browser.

Sonic Web is a browser-native reimplementation of Sonic Pi's live coding engine. Same Ruby DSL. Same synths. Same samples. No install.

I built this because Sonic Pi changed how I think about music and code, and I wanted that experience to be one click away for anyone with a browser.

All thanks to:

  • Sonic Pi & Sam Aaron — for proving that code is a musical instrument
  • SuperSonic — the WebAssembly port of SuperCollider that makes real synthesis possible in the browser
  • AudioWorklet — the browser API that makes low-latency audio processing work
  • Algorave community — for building a culture where live coding is performance art

The core idea: sleep as a scheduler-controlled Promise

Ruby's sleep blocks the thread. JavaScript can't — block the main thread and the UI freezes. Previous browser ports either gave up on multi-loop timing or simulated it with setTimeout, which drifts under load.

The trick we landed on: sleep returns a Promise that only the VirtualTimeScheduler can resolve. User code awaits the sleep; the scheduler advances virtual time and resolves Promises in deterministic order. The result is cooperative concurrency with virtual time across any number of live_loops, with audio events scheduled ahead of the AudioWorklet callback so they stay sample-accurate.

This means the JS engine inherits Sonic Pi's full temporal model — sync, cue, time_warp, with_fx, hot-swap — not a simplified approximation.

  • Ruby DSL → JS via Tree-sitter. Your Sonic Pi code is parsed into an AST and transpiled to JavaScript builder chains. Full structural awareness of blocks, symbols, and Ruby semantics. No regex hacks.
  • Real SuperCollider synthesis. Audio runs through SuperSonic (scsynth compiled to WebAssembly via AudioWorklet). Same synth definitions, same sound — not a simplified approximation.
live_loop :drums do
  sample :bd_haus
  sleep 0.5
  sample :sn_dub
  sleep 0.5
end

Press Run. Now add this while the drums are playing:

live_loop :bass do
  use_synth :tb303
  play :e2, release: 0.3, cutoff: rrand(60, 120)
  sleep 0.25
end

The bass joins in. Change a number. Hit Run again. The music updates instantly. That's live coding.


What can I do with it?

Write Sonic Pi code — the same Ruby DSL you know from desktop. live_loop, play, sleep, sample, with_fx, use_synth, sync, cue — it all works.

Perform live — 10 buffers, hot-swap on Re-run, Alt+R/Alt+S shortcuts, fullscreen mode, spectrum visualizer. Built for the stage.

Teach — zero setup means students open a URL and start coding. Friendly error messages with line numbers. Built-in examples from simple beats to full compositions.

Embed anywhere — drop the engine into any web page, LMS, or creative coding tool as an npm package.


Getting Started

Option 1: Just open the website

sonicweb.cc — nothing to install.

Option 2: Run locally

npx @mjayb/sonicweb@beta

Option 3: Embed in your app

npm install @mjayb/sonicweb@beta
import { SonicPiEngine } from '@mjayb/sonicweb'

const engine = new SonicPiEngine()
await engine.init()
await engine.evaluate(`
  live_loop :beat do
    sample :bd_haus
    sleep 0.5
  end
`)
engine.play()

No wiring needed — the engine loads SuperSonic (the GPL scsynth WASM core, from CDN, never bundled), the tree-sitter transpiler, and its PRNG table itself. Using a <script type="module"> with no bundler? Import the self-contained browser entry instead: import { SonicPiEngine } from '@mjayb/sonicweb/browser'.


What's included

FeatureDetails
63 synths (3 upstream synthdefs missing from the WASM CDN)beep, saw, prophet, tb303, supersaw, blade, hollow, pluck, piano, and more
197 samplesKicks, snares, hats, loops, ambient, bass, electronic, tabla
38 FXreverb, echo, distortion, flanger, slicer, wobble, pitch_shift, gverb, krush, and more
~148 DSL functions (~87% of upstream)live_loop, with_fx, define, defonce, in_thread, sync/cue/sync_bpm, density, time_warp, use_osc/osc, run_code, with_synth_defaults, with_sample_defaults
Per-loop audio isolationEach live_loop gets its own analyser bus — first Sonic Pi implementation to ship this
Music theory30+ chord types, 50+ scales, rings, spreads, Euclidean rhythms
10 buffersSwitch between code tabs like desktop Sonic Pi
Scope visualizerMono, stereo, lissajous, mirror, spectrum — all 5 Desktop SP modes
Cue LogLive cue/sync event stream in a dedicated panel
Live mixerPre-amp and Amp sliders in Prefs push to scsynth on drag
RecordingCapture your session to WAV (raw float32, lossless)
18 examplesFrom "Hello Beep" to a full Blade Runner x Techno composition
AutocompleteCode hints with inline descriptions
Help panel311 entries — functions, synths, FX, and samples with params and examples
PreferencesAudio, visuals, editor, and performance settings
Resizable panelsDrag splitters to resize scope, log, cue log, and help panel
Custom samplesUpload your own WAV/MP3/OGG files
Save/LoadExport and import your code as files
Friendly errors20 error patterns with "did you mean?" suggestions and line highlighting
Report BugOne-click bug report with pre-filled GitHub issue
FX A/B inspector (npm run inspect)Side-by-side desktop ↔ web spectrograms for every FX, with MFCC parity scoring

Keyboard shortcuts

ShortcutAction
Ctrl+Enter / Alt+RRun code
Escape / Alt+SStop all
Ctrl+/Toggle comment
F11Fullscreen
A- / A+Font size

Tech stack

TypeScript, Vite, Vitest (1491 tests across 68 files), CodeMirror 6, Web Audio API, WebAssembly (SuperCollider scsynth via SuperSonic).


Compatibility with Desktop Sonic Pi

Parity is measured end-to-end — not from unit tests alone, but by running each composition on both engines and comparing the result. Real desktop Sonic Pi runs the same .rb file over OSC; web runs it through the full pipeline (Ruby → transpile → scheduler → scsynth-WASM → audio); a launch gate then grades the two outputs.

Parity scores (latest launch gate)

MetricScoreWhat it measures
Launch gatePASSOverall: roster pass + differential matrix green
Official roster34/34 (100%)Non-heavy official examples, PRNG-graded by per-synthdef /s_new event-parity (threshold ≥70%)
Differential matrix52/52 cellsDesktop ↔ web structure-match — 0 diverge / timing / empty / error
Event-parity sweep151 / 154Full fixture corpus: 151 EVENT-MATCH · 0 DIVERGE · 3 non-gradeable by design
Unit tests1491 / 1491Vitest, across 68 files (npx vitest run)

The 3 non-gradeable fixtures are excluded by design (a counter probe, a density isolation probe, and a deliberate web-only feature test), not failures. Regenerate the gate yourself with npx tsx tools/gate-report.ts; the full per-fixture breakdown lives in test_results/launch-gate.md.

Browse the parity dashboards

Every fixture is browsable in the live parity dashboard — one overview links the official roster, the differential matrix, per-/s_new event-diffs, the launch gate, and the FX A/B inspector, each with desktop ↔ web spectrograms.

Every Ruby snippet on the dashboards is playable in the browser — ▶ Run / ■ Stop through the same engine that powers the editor — and carries an ↗ open in sonicweb.cc link that loads it straight into the live editor. Locally, open test_results/index.html, or serve the dashboards with inline audio via npm run dashboard:serve.

Feature coverage

  • 63/66 synths working end-to-end (3 upstream WASM LOAD-FAIL: dark_sea_horn, singer, winwood_lead)
  • 197/197 samples
  • 38 FX wired end-to-end and A/B WAV-verified against desktop (tools/fx-sweep.ts). No FX produces silence or wrong audio — every wired FX routes signal; differences are level/spectral-shape, not engine bugs. (delay and chorus are excluded — the upstream SuperSonic WASM synthdef package doesn't ship them, #301.)
  • ~148/170 DSL functions (~87% of upstream's user-facing surface)

Identical to desktop: seeded PRNG (Mersenne Twister), synth definitions, sample library, music theory, timing semantics, hot-swap, sync/cue.

Different in the browser:

  • Audio output is calibrated for browser WASM headroom (Sonic Tau's gain staging, pre_amp=0.3, amp=0.8), not Desktop SP's driver-attenuated levels. Comparator tools should RMS-normalise before A/B.
  • OSC output requires a host-provided transport (hook-based) — browsers can't open raw UDP sockets.
  • MIDI is wired internally but the device-picker UI ships in v1.6 (Tier D). Web MIDI works for input.
  • No filesystem access — sample paths from directories, eval_file, and user samples from disk are out of scope until the browser sandbox model changes.

See KNOWN_LIMITATIONS.md for permanent constraints and KNOWN_ISSUES.md for current beta-blocker bugs.

How does this compare to Sonic Tau?

Sonic Tau is Sam Aaron's official next-gen Sonic Pi for the browser, built on Elixir + Phoenix LiveView. Sonic Web is an independent JS-native engine you can npm install and embed in any web page. Tau is the future of the Sonic Pi project; this is for embedding the live-coding model into your own apps, courses, and tools.


What's new in v1.5-beta

  • Engine audit pass: 33 bugs fixed since v1.4, including 4 hot-swap state bugs (SP78–SP81) caught by Playwright + WAV reproducers
  • Real-world corpus: 56 compositions verified — MagPi Essentials chapters, 15 wizard/sorcerer/magician examples, 13 community forum compositions
  • New DSL: use_sample_bpm, midi shorthand, use_osc/osc, with_fx reps:, with_synth_defaults, with_sample_defaults, use_density, use_debug, defonce, sync_bpm, run_code, live_audio :stop
  • Tooling: FX A/B inspector (npm run inspect), e2e parity suite (test_results/e2e.html), capture tool with audio recording
  • Mixer: live Pre-Amp / Amp sliders, gain staging aligned to Sonic Tau (browser-WASM safe headroom)
  • Per-loop audio isolation — first Sonic Pi implementation to ship this

Full changelog: Releases.


Coming next

  • Tier C/D DSL completion — remaining ~22 helpers (with_synth, use_arg_checks, sample_paths, MIDI device picker UI, midi_pc/midi_raw/midi_sysex)
  • Tutorial system port — desktop Sonic Pi's 50+ chapter tutorial adapted for the browser
  • Ableton Link — UDP-over-WebSocket relay
  • Cross-browser CI matrix — Firefox + Safari coverage

Check out these cool projects

  • Sonic Tau — Sam Aaron's official next-gen Sonic Pi for the browser. Built with Elixir + Phoenix LiveView. The future of Sonic Pi.
  • Strudel — Alex McLean's live coding pattern language for the browser. Different paradigm (TidalCycles-inspired), equally mind-blowing.
  • Tone.js — Web Audio framework for building interactive music in the browser.

Contributing

Issues and PRs welcome. Pick an issue from the SonicWeb Roadmap board — area: audio, area: scheduler, and area: transpiler labels are good entry points. See CONTRIBUTING.md for setup and workflow.

License

MIT. See LICENSE.

See what people are saying

Contributors

Languages

Jupyter Notebook

73.0%

HTML

14.7%

TypeScript

11.5%