Shipping

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=fx

An 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.

There are three steps between a Pole file and sound from a web page:

  1. Compile the patch into a wasm-targeted object and a manifest.
  2. Link that object into a .wasm module, resolving its maths functions.
  3. 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
FilePurpose
gain-web.oIntermediate wasm object, not yet the browser-loadable module.
gain-web.jsonManifest describing symbols, storage and controls.
gain-web.wasmLinked 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-ld and the wasm32 libm.

Two traps that cost real time:

  • wasi-libc merges libm into libc.a. Its libm.a is an empty stub, so linking the file whose name says libm fails with undefined symbol: expf.
  • Do not install Homebrew's lld for wasm-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.