WebAssembly
The target that lets a patch run in a browser — and what the runtime learns from the manifest.
Anyone who wants a patch on a web page.
./build/polec fx.pole --emit=web --out=fxAn object targeting wasm32, plus a JSON manifest. Link the object with
wasm-ld and the manifest tells the browser everything the C header would have
told C.
This is what the runnable blocks on this site are. Press Run on an oscillator and the real compiler produces a real wasm module, which a real AudioWorklet runs.
Compile, link, then host#
There are three steps between a Pole file and sound from a web page:
- Compile the patch into a wasm-targeted object and a manifest.
- Link that object into a
.wasmmodule, resolving its maths functions. - Host the module in an audio runtime that supplies memory, controls and an audio callback.
From tools/pole, with wasi-sdk available, the repository's linker helper
performs the second step:
./build/polec examples/gain.pole --emit=web --out=/tmp/gain-web
python3 scripts/link_wasm.py /tmp/gain-web| File | Purpose |
|---|---|
gain-web.o | Intermediate wasm object, not yet the browser-loadable module. |
gain-web.json | Manifest describing symbols, storage and controls. |
gain-web.wasm | Linked module loaded by the browser runtime. |
Set POLE_WASI_SDK to your SDK directory if it is outside the helper's usual
locations. Exporting these files does not create a finished web player. This
site supplies that player through its AudioWorklet and the runtime in
tools/pole/web/pole-runtime.mjs.
The manifest is the interface#
The browser runtime learns all of it from the manifest: entry symbols, parameter ranges, state size and seeds, per-node state offsets, externals, handlers, event routes and buffer offsets.
Nothing on the browser side parses the C header, and nothing should: a runtime that parsed C would break the day the header's formatting changed.
What it needs to build#
- wasi-sdk, for
wasm-ldand the wasm32libm.
Two traps that cost real time:
- wasi-libc merges libm into
libc.a. Itslibm.ais an empty stub, so linking the file whose name says libm fails withundefined symbol: expf. - Do not install Homebrew's
lldforwasm-ld. It upgrades Homebrew's LLVM, which breaks Pole's version pin for everything on the machine. wasi-sdk carries its own and touches nothing.
How close is it to native?#
24 of 29 examples render bit-identically between the JIT and the browser runtime — see the C header for the five that do not and why.
What it cannot do yet#
- Sample-accurate event timing. Events are applied at block boundaries, so a note lands within about 3 ms of where it was asked for rather than on the frame it was stamped at.
- Graphs with feedback, which are rendered node by node rather than fused.
- Show what is happening inside a patch. The scopes here analyse what comes out; the IDE's displays are fed by telemetry ports declared in the patch.