A language for writing synths and effects.
You write how a sound is made, in a few lines of code. Pole turns that into fast machine code that goes straight into your plugin, with nothing extra to install and no compiler inside. It also runs in a web page, which is how the patch below plays.
Pole powers every block in Patchhaus, and it works on its own too, in your own plugin code. It will be open source.
Made by Sinuslabs, for Patchhaus
processor Pluck
{
input stream float pitch;
input stream float gate;
output stream float out;
param float decay = 0.4f [0.05f, 2.0f];
param float tone = 0.4f [0.05f, 0.95f];
float phase = 0.0f;
float env = 0.0f;
float lp = 0.0f;
void main()
{
loop
{
if (gate > 0.5f) { env = 1.0f; }
else { env = env * (1.0f - 1.0f / (decay * 48000.0f)); }
let saw = phase * 2.0f - 1.0f;
lp = lp + tone * (saw - lp);
out <- lp * env * 0.3f;
phase = phase + pitch / 48000.0f;
if (phase >= 1.0f) { phase = phase - 1.0f; }
advance();
}
}
}One patch, two places to run it.
In your plugin
Pole compiles the patch into machine code for your computer's processor. It goes into your plugin as two small files, and nothing else has to come along: no compiler, no Pole library.
In a web page
The same patch compiles to WebAssembly, the code format browsers run. That is how every example on this page plays, with nothing to install.
The same sound
The plugin runs the exact code you heard while you wrote the patch, not a rewrite of it. A test compares the two, sample for sample.
Press play.
Eight Patchhaus blocks wired into one Pole DSP patch, compiled to WebAssembly for this page. Drag them around, turn them, rewire them: every cable you can draw is already in the patch, and drawing it switches that route on.
two fingers move · tap a port, then another
The same blocks, knobs and displays as the app. To write a block of your own in Pole DSP, open the playground.
How it runs in a plugin.
The browser is where Pole is easiest to try. The native object is what ends up in your plugin, and this is how it behaves there.
$ polec home-modules.pole --emit=export --out=home-modulespolec: wrote home-modules.o (7 functions, target arm64-apple-darwin25.0.0)polec: wrote home-modules.h$ wc -c home-modules.o 24904 home-modules.o$ nm -u home-modules.o_expf_sinf_tanf_tanhf$ export-check home-modules.pole OK identity: 1500 blocks of 64 frames, 3 side channels, 33 MIDI events, 24 parameter writes -- 0 block(s) differ, largest difference 0export-check: the plugin sounds like the editorA real session, 2026-09-17 · export-check trimmed to its last two lines
Compiled before it ships
The patch becomes machine code for the processor before the plugin is built. Nothing compiles while it plays.
--emit=export → an object file and a C header
Nothing but math
The compiled code does arithmetic and calls a few math functions. While audio runs it never asks for memory, waits for another thread, or calls the operating system, the things that usually cause clicks in audio code.
all 30 examples: libm only, three import nothing
State in one block
Everything the patch remembers lives in one block of memory of a known size. The plugin sets it aside once, when it loads, so nothing grows while it plays.
reverb.h: POLE_REVERB_STATE = 10253 floats
What you heard is what ships
On every patch we test, the exported plugin plays exactly the samples the editor played. A test plays both with chords, retriggered and released notes, and knob moves, and compares every block.
30 graph patches, 0 blocks differ
Sixteen voices on 0.6% of one core.
Faster than real time, by this much. These are exported Pole objects, the same code a plugin ships, each timed on one core of an Apple M1 Pro.
Sixteen voices
167×
Each voice is a saw, a filter its envelope sweeps, and tanh drive. A second of audio takes 6 ms.
A wavetable oscillator
7,389×
A 1,024-point table, read every sample with linear interpolation.
A feedback delay
6,422×
A 16,384-sample line with one-pole damping inside the loop.
tools/webbench/native.mjs · 48 kHz · 128-frame blocks · best of 9 runs
Measured, not estimated.
Every figure here was produced by running the thing that produces it, on the commit this page was written from.
1,944 bytes
a reverb, compiled.
polec --emit=export on examples/reverb.pole. The header beside it is 4.3 KB.
One
function it borrows from the system.
_expf, from the C math library the operating system already has. The compiled code needs nothing else to run.
21–27 ms
to compile a patch.
Median of eleven runs each for gain, filter, synth, and reverb, to an object and a header.
24 of 29
examples sound exactly the same in the browser, sample for sample.
check_wasm.py · 4,096 frames · 48 kHz
- adsr
- bounded_search
- delay
- filter
- fuzz
- gain
- modmatrix
- octave_up
- poly_graph
- poly_simple
- poly_synth
- poly_voices
- reverb
- saw_gate
- shaper
- sine
- soft_clip
- stereo_chorus
- stereo_width
- synth
- wavefolder
- wavetable
- wt_load
- wt_synth
- fft93 of 4,096 samples differ, by −150.5 dBFS at most
- fx_chain2 of 4,096 samples differ, by −156.5 dBFS at most
- spectral923 of 4,096 samples differ, by −138.5 dBFS at most
- wt_osc532 of 4,096 samples differ, by −138.5 dBFS at most
- feedback_lfoa feedback graph, which cannot run in a browser yet
- poly_eventsneeds notes, which the check does not play
Every example is rendered as native code and in the browser, then compared sample for sample by scripts/check_wasm.py. The four that differ all use sin, cos, exp, pow, or log, which macOS and the browser each calculate with their own math library.
Where it runs.
Compile, render, export
- macOS
- Verified
- Linux
- Verified
- Windows
- Not built
WebAssembly output
- macOS
- Verified
- Linux
- Verified
- Windows
- Not built
Live audio and MIDI
- macOS
- Verified
- Linux
- No backend
- Windows
- No backend
| macOS | Linux | Windows | |
|---|---|---|---|
| Compile, render, export | Verified | Verified | Not built |
| WebAssembly output | Verified | Verified | Not built |
| Live audio and MIDI | Verified | No backend | No backend |
“Not built” means exactly that: the compiler core has no platform headers and no reason not to build on Windows, but nobody has built it, so this table does not say it works. The platforms page has the detail.
Start anywhere.
Write your first patch.
Start in the playground, with nothing to install and the same compiler. Then take the patch wherever you need it.