A virtual Hammond B3 organ with drawbars, a Leslie rotary speaker, percussion, vibrato/chorus and tube overdrive โ written in pure Rust, playable natively and in your browser via WebAssembly.
โถ๏ธ Play the live demo โ no install, runs in your browser
- ๐๏ธ Nine drawbars (
16' 5โ ' 8' 4' 2โ ' 2' 1โ ' 1โ ' 1') with authentic tonewheel foldback - ๐ Leslie rotary speaker โ independent horn & drum rotors, Doppler pitch shift, amplitude swell, stereo micing, and inertial slow / fast / brake ramps
- ๐ฅ Percussion โ single-triggered 2nd / 3rd harmonic, soft / normal, fast / slow decay
- ใฐ๏ธ Vibrato / Chorus scanner โ the classic
V1โV3/C1โC3selector - ๐๏ธ Tube overdrive with a musical soft-limiter on the output
- ๐ Key click and tonewheel leakage for that vintage grit
- ๐พ Presets in human-editable TOML (four factory patches included)
- ๐น MIDI input (desktop) + an on-screen / computer-keyboard so the web demo needs no hardware
- ๐ฆ One pure-Rust DSP engine shared by the native app and the WebAssembly build
A skeuomorphic wood-and-brass cabinet inspired by the classic B3 console: coloured drawbars, tab switches, a Leslie control and a playable manual โ rendered with egui.
cargo run --releasePlug in a MIDI controller (auto-connects to the first port) or play with your computer keyboard.
cargo install trunk
rustup target add wasm32-unknown-unknown
trunk serve # open http://127.0.0.1:8080Every push to main also auto-deploys the demo to GitHub Pages via .github/workflows/pages.yml.
๐ Web audio notes. Browsers keep audio muted until you interact โ so the demo starts its audio engine on your first key press / click. On the web the audio callback shares the browser's main thread, so the engine uses a shared sine wavetable and the UI repaints at a capped ~30 fps to keep the sound smooth. If you ever hear crackling, close other heavy tabs โ desktop (
cargo run) always has the lowest, cleanest latency.
| Action | How |
|---|---|
| Play notes | On-screen keyboard, computer keys A W S E D F T G Y H U J K, or MIDI |
| Change octave | Octave โ/+ buttons |
| Drawbars | Drag each bar up/down (0โ8) |
| Leslie | Brake / Slow / Fast |
| Percussion | On, 2nd/3rd, Fast/Slow |
| Vibrato/Chorus | OFF ยท V-1 ยท V-2 ยท V-3 ยท C-1 ยท C-2 ยท C-3 |
| Presets | Pick + Load, or name + Save |
Factory presets live in presets/ as editable TOML:
name = "Full Jazz"
drawbars = [8, 8, 8, 0, 0, 0, 0, 0, 0]
vibrato = "c3"
leslie = "slow"
overdrive = 0.1
volume = 0.8
[percussion]
on = true
soft = false
fast = true
third = trueRegenerate them from code with cargo run --example export_presets --no-default-features.
tonewheels ร drawbars โโ
percussion โโโโโโโโโโโโโคโ vibrato/chorus โ overdrive โ Leslie โ soft-limit โ stereo out
key click + leakage โโโโ
| Module | Responsibility |
|---|---|
engine |
Free-running tonewheel bank, drawbars, voices, percussion, key click, vibrato, overdrive |
leslie |
Two-rotor rotary-speaker simulation |
preset |
Patch data model + TOML (de)serialization + factory presets |
params |
Lock-free-ish state shared between UI/MIDI and the real-time audio thread |
audio |
[cpal] output stream (native + WebAudio) |
midi |
[midir] MIDI input (desktop) |
app |
[egui]/[eframe] GUI + on-screen keyboard |
The audio callback never allocates or blocks: it tries to read the latest patch and drains a small event queue each block.
cargo test --no-default-features # fast engine tests (no system deps)
cargo clippy --all-targets -- -D warnings
cargo fmt --allMIT ยฉ gpasquero
Topics: rust ยท hammond ยท hammond-b3 ยท organ ยท tonewheel ยท synthesizer ยท synth ยท virtual-instrument ยท leslie ยท rotary-speaker ยท drawbars ยท audio ยท dsp ยท audio-synthesis ยท music ยท midi ยท webassembly ยท wasm ยท egui ยท cpal ยท real-time-audio ยท vst-alternative ยท music-production
Built with ๐ฆ Rust, ๐๏ธ cpal, ๐น midir and ๐ผ๏ธ egui.