Rudel is a native Rust fork of Strudel (itself the JS port of TidalCycles): live-coded, algorithmic music patterns written in Strudel's own JavaScript, native audio, MIDI out, and SuperDirt-compatible OSC out.
Licensed under AGPL-3.0-or-later, the same as Strudel. Sound bank licensing follows the source samples you load.
| Crate | Role |
|---|---|
rudel-core |
Pure pattern engine: Pattern = State -> Vec<Hap>, exact rational time, combinators, controls, signals, sample transforms, tonal helpers, and scheduler-neutral event extraction. |
rudel-mini |
pest mini-notation parser ported from Strudel's krill.pegjs: sequences, groups, rests, alternation, stacks, choices, Euclidean rhythms, ranges, polymeter, degradation, and sample indices. |
rudel-dsp |
Offline-testable voices: synth oscillators, noise, built-in drums, sampler playback, filters, envelopes, panning, and per-voice post effects. |
rudel-audio |
Real-time audio engine: lookahead scheduler, cpal output, sample bank loading, mixer, delay, and fundsp reverb. |
rudel-lang |
JavaScript bindings (run by Boa) for Rudel patterns, controls, signals, factories, higher-order callbacks, sample transforms, and tonal operations. |
rudel-midi |
MIDI output: control-map to note/CC/program messages, timed windows, port wrapper, and real-time scheduler. |
rudel-osc |
SuperDirt OSC output: hand-rolled OSC 1.0 encoding, /dirt/play messages, UDP sender, and real-time scheduler. |
rudel-app |
Native egui editor with live JavaScript evaluation, audio/MIDI/OSC output selection, sample loading, and a one-cycle visualizer grouped by orbit. |
rudel-ffmpeg |
Small native video decoder; FFmpeg 9 is statically linked into Rudel. |
Release binaries include FFmpeg; video playback needs no separate installation.
For source builds, first build the pinned native libraries (cached under
target/ffmpeg):
zig run tools/build-ffmpeg.zigThis requires Python 3, Git, CMake, a C/C++ toolchain, and libclang for Rust
bindings. On Windows use Visual Studio's C++ build tools and LLVM; on macOS
use Xcode command-line tools (brew install cmake llvm nasm); on Linux install
build-essential cmake ninja-build nasm pkg-config libclang-dev alongside the
GUI/audio development libraries. Point LIBCLANG_PATH at LLVM's library
directory if bindgen cannot find it. The initial build downloads and compiles
FFmpeg 9.0.2, dav1d, zlib, and (outside Windows) OpenSSL; subsequent builds reuse
them. Rerun the script after changing vcpkg.json.
cargo run --release -p rudel-appType a pattern in the editor, press Ctrl+Enter to evaluate, then press Play:
stack(
s("bd ~ bd bd").gain(0.9),
s("~ sd ~ sd"),
s("hh*8").gain(0.5),
note("c4 e4 g4 b4").s("triangle").room(0.5),
note("c2 ~ g2 ~").s("saw").lpf("400 1600").gain(0.6).delay(0.3)
)The app starts with native audio. Use the output selector for MIDI or OSC; OSC
defaults to 127.0.0.1:57120 for local SuperDirt.
Strudel's visuals run natively, drawn behind the code as on strudel.cc or inline under the line that made them.
| Hydra | The draw canvas |
|---|---|
![]() |
![]() |
await initHydra(), then any hydra chain: osc(12, 0.08, 1.4).kaleid(5).out() |
.draw((haps, t) => …) paints with getDrawContext(), as upstream |
Inline widgets sit under their pattern: ._pianoroll(), ._punchcard(),
._spiral(), ._pitchwheel(), ._scope() and more, each in the pattern's
.color().
Mondo Notation is Strudel's
Lisp-like way of writing the same patterns, and Rudel speaks it. Put // mondo
on the first line and the whole script is read as mondo:
// mondo
$ s [bd rim [~ bd] rim] # bank tr707
$ n <0 2 4 [3 1] -1>*4 # scale C4:minor # jux rev # dec .2 # delay .5
Round parens call a function, # chains one call onto the last, and $
separates patterns into a stack. That is this, in JavaScript:
stack(
s("bd rim [~ bd] rim").bank("tr707"),
n("<0 2 4 [3 1] -1>*4").scale("C4:minor").jux(rev).dec(0.2).delay(0.5)
)To reach for mondo inside an otherwise-JavaScript script, tag a single pattern
with it instead: mondo`s hh*8`.
Mondo is compiled to JavaScript rather than interpreted, so every control, transform
and signal Rudel exposes is reachable from it. Its two limits — :/.. want
literal operands, and def binds values rather than functions — are in
docs/UNSUPPORTED.md.
Rudel can play a pattern on a Csound instrument instead of
one of its own voices, the way @strudel/csound does — loadCsound, loadOrc,
and the csound / csoundm outputs.
This is the one feature with an outside dependency. There is no pure-Rust Csound, and the WebAssembly build Strudel loads in the browser needs a browser to run, so Rudel uses the native library. Nothing links against it: Rudel builds and runs exactly as before without Csound, the library is opened only when a script first asks for it, and a script that asks when it is not there gets an error saying so while the rest of the pattern keeps playing.
To get started, install Csound (downloads; the 64-bit build, which is what the installers give you), then paste this in and press Play:
loadCsound`
instr Beep
asig = vco2(p5, p4)
asig *= linsegr:a(0, .01, 1, p3, 1, .1, 0)
out(asig, asig)
endin`
note("c3 e3 g3 c4").csound('Beep')loadOrc('github:user/repo/branch/some.orc') loads an orchestra from a URL
instead. An orchestra that will not compile reports Csound's own message — the
line number and the offending source — in the app's error panel.
Rudel looks for csound64.dll / libcsound64.so / libcsound64.dylib on the
usual library path, then in the default install locations. Set
RUDEL_CSOUND_LIB to a full path to override that, which is also all an
unpacked build needs. Details, including how Csound is mixed in, are in
docs/UNSUPPORTED.md.
cargo run -p rudel-audio --example play
cargo run -p rudel-audio --example live -- 'note("c e g").fast(2).room(0.4)'
cargo run -p rudel-audio --example samples -- path/to/samplesFor sample folders, immediate subdirectories become sound names and files inside them become sample indices.
use rudel_core::*;
let pat = note(seq([60, 64, 67, 71]))
.s("triangle")
.jux(|p| p.rev())
.every(4, |p| p.fast(2))
.gain(0.8);Install mini-notation when you want strings to parse like Strudel patterns. As in Strudel, double-quoted strings are mini-notation and single-quoted strings are plain strings:
rudel_mini::install();
let pat = note("c3 [e3 g3] <c4 e4>")
.s("saw")
.chop(4)
.room(0.4);Rudel has a usable native live-coding path today: pattern engine, mini-notation,
synth/drum/sample audio, effects, live JavaScript evaluation, an egui app, MIDI
out, and SuperDirt-compatible OSC out. The core, mini parser, transforms, audio
event scheduling, MIDI, OSC, and JavaScript bindings are covered by unit,
integration, and Strudel parity tests.
Still evolving: richer synth families, more Strudel sample-bank loading modes, MIDI input/clock-in, per-pattern routing helpers, deeper editor ergonomics, and the long tail of Strudel/Tidal compatibility.
Some Strudel packages bridge to browser-only platform APIs, and one — the
experimental TidalCycles interpreter — is an alternative source language rather
than a notation over the one Rudel has; these are intentionally not ported. See
docs/UNSUPPORTED.md for the authoritative list of
unsupported and intentionally different features.
Rudel queries patterns 4 to 8.5 times faster than Strudel. Querying is the work
the scheduler does continuously while music plays. Evaluating a script on
Ctrl+Enter takes 0.15–0.55 ms for typical patterns. That is up to 3.8 times
faster than Strudel, and up to 6 times faster than Rudel 0.21.0, the last Koto
release.
Scripts that do a lot of plain JavaScript work are the exception: Rudel's Boa
engine interprets JavaScript, where V8 in Strudel's browser compiles it. See
docs/PERFORMANCE.md for the measurements, the method
and the caveats.
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo bench -p rudel-lang # performance benchmarks over representative patternsCI (.github/workflows/ci.yml) runs the test +
clippy checks on every push and PR; the suite includes the parity drift guards
(reference surface, per-package API inventory, and mini/tonal goldens).
Parity oracle notes live in tools/oracle/README.md.
See CONTRIBUTING.md for setup, check commands, parity
oracle guidance, and contribution conventions.



