A faithful, browser-based RB-338/TB-303-style monosynth with step sequencer—authentic slide/legato, accent behavior, filter drive/response, and an RB‑338‑inspired UI. The project ships Phase‑1 as a single‑file HTML demo, then evolves to a modular codebase.
Primary target: Chrome/Edge desktop (latest). Secondary: Firefox. Mobile: best effort.
Option A (fastest): built-in server
npm start → open http://localhost:5173 (serves demos/phase-1-singlefile/ via scripts/serve.js)
Option B: any static server (AudioWorklet needs secure context)
- Python:
python -m http.server 8000→http://localhost:8000/demos/phase-1-singlefile/ - Node:
npx http-server -c-1 -p 5173→http://localhost:5173/demos/phase-1-singlefile/
Start Audio → Play: Click Start Audio, then Play in the sequencer. Use Drone or Auto‑retrig for audition. Keyboard: Z/S/X/…, Space=gate, Shift=accent.
- Sound: convincing 303/RB‑338 character—resonant sizzle, envelope snap, accent punch, legato slide feel.
- UX: RB‑338 panel fidelity, responsive, accessible, keyboard shortcuts.
- Sequencer: practical pattern editing (rest, tie, slide), banks, chain, export/import.
- Interop: MIDI in/clock (optional), render to WAV.
Non-goals (for now): polyphony; FX; Mobile Safari perfection; DAW integration.
- Phase 1 — Engine Demo (single file): polyBLEP saw/square, 3‑pole TPT LPF + soft clip, decay‑only envs, basic sequencer, RMS meter.
- Phase 2 — Sound & Sequencer parity: true legato slide, accent coupling (VCA/VCF + decay trim), pre‑filter drive + gain‑comp, REST & TIE, tests.
- Phase 3 — Pattern mgmt & Banks: 4×8 patterns, copy/paste/clear/randomize, chain, export/import
.rb338.json, localStorage. - Phase 4 — RB‑338 Skin & UX polish: labels/order, SVG knobs, LED grid, accessibility.
- Phase 5 — Interop & Render (opt): MIDI note/clock, 24 PPQN, offline render to WAV.
See docs/ROADMAP.md and docs/SPEC.md.
- Outer page: ES5 only (no classes/arrow funcs).
- Audio engine: AudioWorklet source built from a single template string via
buildWorkletCode()to avoid stray comma/quote bugs. - Oscillators: polyBLEP saw & square (with tiny duty micro‑offset vs freq in Phase 2).
- Filter: 3‑pole TPT low‑pass with resonance; pre‑filter drive (P2) and post‑filter soft‑clip with gain‑comp.
- Envelopes: decay‑only VCA + filter env; accent inflates VCA level and VCF env depth; accented notes slightly shorten amp decay.
- Sequencer: 16 steps, Gate/Accent/Slide/Pitch (+ REST/TIE in P2), BPM, Gate %, Swing %, Play/Stop.
- Timing: initial UI scheduler with swing, migrating to AudioContext‑time look‑ahead (P2/P3).
- Self‑tests: environment checks; param mapping; UI rows; RMS energy; new parity tests in P2.
Deeper explanation in docs/ARCHITECTURE.md.
- Keyboard: docs/KEYBOARD_SHORTCUTS.md
- DSP: docs/DSP_NOTES.md
- UI Guide: docs/UI_GUIDE.md
- Releases & Pages: docs/RELEASE.md
- GitHub Pages workflow:
.github/workflows/pages.yml(deploysdemos/phase-1-singlefile/) - CI smoke:
.github/workflows/ci.yml
rb338/
├─ demos/
│ └─ phase-1-singlefile/
│ └─ index.html # “Rb-338 Phase-1 Engine — Single-file Html Demo”
├─ packages/
│ ├─ rb338-engine/ # (Phase 3+) Worklet builder + engine modules
│ │ └─ src/
│ │ ├─ buildWorkletCode.js # returns single template string
│ │ ├─ TB303Processor.js # the processor (string within builder)
│ │ └─ dsp/
│ │ ├─ osc_polyblep.js
│ │ ├─ tpt_lpf3.js
│ │ └─ env_decay.js
│ └─ rb338-ui/ # (Phase 3+) UI and sequencer modules
│ └─ src/
│ ├─ sequencer.js
│ ├─ keyboard.js
│ └─ panel.js
├─ docs/
│ ├─ ARCHITECTURE.md
│ ├─ SPEC.md
│ ├─ TESTS.md
│ ├─ ROADMAP.md
│ ├─ CODING_STANDARDS.md
│ ├─ CONTRIBUTING.md
│ ├─ CODE_OF_CONDUCT.md
│ └─ CHANGELOG.md
├─ .github/
│ ├─ ISSUE_TEMPLATE/
│ │ ├─ bug_report.md
│ │ └─ feature_request.md
│ └─ PULL_REQUEST_TEMPLATE.md
├─ scripts/
│ ├─ serve.js # optional tiny static server (or use http-server)
│ └─ verify-self-tests.js # placeholder
├─ .editorconfig
├─ .gitignore
├─ LICENSE
└─ README.md
This layout preserves Phase‑1 single‑file while staging a clean modular split for Phase‑3.
- Keep outer script ES5; only the worklet internals can use modern syntax (inside the template string).
- When rebuilding sequencer UI, clear
#seq.innerHTMLfirst to avoid duplicates. - Keyboard handlers must be bound once (guard with a boolean).
- On silence: check RMS, verify param mapping, and resume the audio context after a user gesture.
- Tests are mandatory for each new feature—see docs/TESTS.md.
- Open a feature request or bug report using the templates in
.github/ISSUE_TEMPLATE/. - Follow docs/CODING_STANDARDS.md and docs/CONTRIBUTING.md.
- Add/extend self‑tests with every change. Never weaken an existing test unless it’s objectively wrong—add new tests.
MIT — see LICENSE.
Project lead: Greg Karsten.
ChatGPT assistant: GPT‑5 Thinking (“Alex”).
Inspired by the sound & workflow of ReBirth RB‑338 and the Roland TB‑303 (trademarks belong to their respective owners).