A real-time modular synthesizer desktop app with a JavaScript DSL for live-coding audio patches, built with Electron and a Rust DSP engine.
- JavaScript DSL - Expressive, fluent API with
$-prefixed functions for building synthesis patches - Real-time Audio - Low-latency audio processing in Rust via N-API, running directly in-process
- Live Coding - Update patches on-the-fly with Alt+Enter
- Monaco Editor - Full-featured code editor with autocomplete, inline error highlighting, and oscilloscope overlays
- UI Sliders - Bind real-time UI sliders to signal parameters with
$slider() - Module Library - Oscillators, filters, effects, sequencers, envelopes, and more
- Rust (latest stable)
- Node.js 24.12+
- Yarn (latest)
Note: This project uses Volta to manage the Node.js version. If you have Volta installed, it will automatically use the correct version pinned in
package.json.
Ensure that you've fetched the git submodules:
git submodule update --init --recursiveNote: Failure to do so will produce an error along the lines of:
error: failed to load manifest for workspace member `/projects/operator/crates/modular_core`
referenced by workspace at `/projects/operator/Cargo.toml`
yarn install
yarn startThis builds the native Rust audio module and launches the Electron app.
- Launch the app with
yarn start - Write a patch using the JavaScript DSL (see examples below)
- Press Alt+Enter to execute and hear the result
- Press Alt+. to stop audio
Simple Sine Wave:
$sine('440hz').out();Musical Note:
$sine('a3').out();FM Synthesis:
const mod = $sine('220hz');
const carrier = $sine('440hz').phase(mod.amplitude(0.5));
carrier.out();With a UI Slider:
const shape = $slider('Shape', 0, 0, 5);
$saw('a3', { shape }).out();modular/
├── crates/
│ ├── modular_core/ # Core DSP engine (Rust)
│ ├── modular/ # N-API bindings + audio thread (Rust)
│ └── modular_derive/ # Proc macros for the module system (Rust)
├── src/
│ ├── main/ # Electron main process (TypeScript)
│ │ └── dsl/ # DSL executor, factories, type generation
│ ├── renderer/ # React renderer (TypeScript)
│ ├── preload/ # Electron preload scripts
│ └── shared/ # Shared types between main and renderer
└── docs/ # Documentation
- modular_core - Audio DSP engine: oscillators, filters, effects, sequencers, envelopes
- modular - N-API bindings exposing the engine to Node.js; runs the audio callback via cpal; streams scope data back to the renderer
- modular_derive - Proc macros for the module output system
- DSL Runtime - Executes JavaScript patches via
new Function(...), generatesPatchGraphJSON - Editor - Monaco-based editor with autocomplete, inline error display, and waveform overlays
- IPC - Patch graphs are sent from the renderer to the main process over Electron IPC, which forwards them to the Rust synthesizer
After modifying Rust N-API types, regenerate the DSL type definitions:
yarn generate-lib# Build native Rust module only
yarn build-native
# Build and launch the full app
yarn start# Rust DSP unit tests
yarn test:rust
# JavaScript unit/integration tests (Vitest)
yarn test:unit
# End-to-end tests (Playwright + Electron)
yarn test:e2e
# All tests
yarn test:allSee TESTING.md for more details on the test infrastructure.
AGPL-3.0