Context: live performance needs immediate, single-key triggers for the common moves (intro / drop / breakdown / fills / mute a voice / random tweak), AND mid-set the operator may need to reboot just the Node web server without touching sclang or the audio engine. The previous commit added scsynth and sclang reboots but not web. Approach: a new Live tab dedicated to performance. 30 pads laid out on a 10x3 grid that mirrors the QWERTY rows physically — top row (qwertyuiop) = chains, home row (asdfghjkl;) = one-shots, bottom row (zxcvbnm,./) = mutes + FX. Each pad shows a big label, a small kind hint and the bound key in a kbd-style badge at the bottom right. When the Live tab is active a capture-phase keydown listener wins against the global keymap, so 'r' fires Buildup ×4 instead of 'refresh catalogues' etc. — non-Live tabs keep the global behavior. Mute pads are stateful : they toggle /control/mute and /control/unmute based on a local Set, and visually invert (red, 🔇 prefix) when active. The ⟳ web button writes ~/.av-live-restart-web ; the launcher's sentinel watcher restarts the Node server without touching sclang. Changes: - web/public/control/index.html : * new tab Live between Transport and Album * new tabpane #livePads (filled by JS), with header hint listing the three sections * three reboot buttons in the topbar (⟳ sc small / ⟳ web small / ⟳ sclang big) - web/public/control/app.js : * LIVE_PADS array (30 entries, key/label/sub/kind/arg/voice) * firePad(pad, padEl) dispatcher : chain / playAll / stopAll / synth / fn / tap / ping / unsolo / muteToggle * initLivePads() builds the 30 buttons, attaches click + capture-phase keydown listener that only fires when Live tab is active, with .hit pulse animation feedback * makeArmedButton binding for #btnRebootWeb sending /control/rebootWeb - web/public/control/style.css : * .live-grid 10-col CSS grid (5-col under 1200px, 2-col under 720px) * .live-pad with hover/active microinteractions and section-coloured .live-pad-{chain,shot,mute} variants * .live-pad.muted state (red tint, 🔇 prefix) * .live-pad-key kbd-style badge bottom-right - web_bridge.scd : * /control/rebootWeb : writes ~/.av-live-restart-web sentinel * /control/triggerSynth <name> : safe Synth(<name>, [\decay 2, \amp 0.5]) * /control/snareFill : ~snareFill.value * /control/tomFill : ~tomFill.value * /control/randomTweak : ~randomTweak.value - launcher/ProcessManager.swift : * webWantsRestart flag + restartWeb() helper * web terminationHandler now respawns 0.4s later if wantsRestart * startSentinelWatcher() now also watches ~/.av-live-restart-web Impact: switch to the Live tab and trigger any of the 30 commands by clicking or by tapping the corresponding key on the keyboard. Mute toggles persist visually. ⟳ web restarts the Node server in ~1 second without disturbing sclang/scsynth or the WS clients (which auto- reconnect).
AV-Live
Audio-visual live performance monorepo for solo or small-ensemble live coding sets.
Three components, one launcher :
| Path | Role | Tech |
|---|---|---|
sound_algo/ |
Sound engine — 1099 SynthDef palette, tracks, web bridge OSC↔WebSocket | SuperCollider 3.13+ |
oscope-of/ |
Oscilloscope visualizer driven by audio + Hantek 6022BL USB capture | openFrameworks 0.12+ |
launcher/ |
macOS menubar app : start/stop each component, unified logs | SwiftUI |
Quick start (macOS)
# 1. Clone
git clone https://github.com/electron-rare/AV-Live.git
cd AV-Live
# 2. Install dependencies
brew install --cask supercollider
# openFrameworks : download 0.12+ from https://openframeworks.cc/download/
# 3. Build the launcher
cd launcher && xcodebuild -scheme AVLiveLauncher -configuration Release
open build/Release/AVLiveLauncher.app
# 4. Or run components manually
sclang sound_algo/00_load.scd # boots scsynth + loads palette + serves :8080
cd oscope-of && make && bin/oscope-of # opens the visualizer
Architecture
┌─────────────────────────────────────────┐
│ AVLiveLauncher.app (macOS menubar) │
│ start / stop / logs / status │
└────────┬─────────────┬──────────────────┘
│ │
┌──────────────────▼─┐ ┌───▼──────────────────┐
│ sclang + scsynth │ │ oscope-of (oF .app) │
│ sound_algo/ │ │ src/main.cpp │
│ │ │ │
│ audio :57110 OSC │ ────► │ OSC :57123 in │
│ web :8080 HTTP │ │ Hantek USB capture │
│ WebSocket :57121 │ │ GPU-accel render │
└────────────────────┘ └──────────────────────┘
Components
sound_algo/
Live coding SuperCollider system (forked from electron-rare/supercollider-live refonte-v2 branch). Auto-loads 1099 SynthDef across drums/bass/lead/pad/world/master + fx categories. Provides 5-namespace live API (~kk/~mm/~ff/~cc/~p). 23 pre-composed tracks. Web UI on :8080. OSC relay to oscope-of on :57123.
See sound_algo/CLAUDE.md for live coding workflow.
oscope-of/
openFrameworks application. Three visualizers : Lissajous (CRT phosphor), spectrogram (perceptual freq mapping), reactive (8-voice shader). Lock-free SPSC ringbuffer for USB→UI thread. FFT with Hann windowing. Optional Hantek 6022BL hardware input.
See oscope-of/README.md for build details.
launcher/ (macOS only)
SwiftUI menubar app bundle (.app). Manages process tree of sclang/scsynth/oscope-of. Unified log viewer. Clean shutdown on quit.
License
GPL-3.0-or-later (see LICENSE).
Author
L'Electron Rare — https://github.com/electron-rare