Extend WAVR PRO with instruments, effects, and generators. Pure JavaScript. Zero dependencies. No build step. Runs entirely in the browser.
WAVR PRO is a full-featured DAW running entirely in the browser. This SDK gives anyone the tools to extend it — instruments, effects, generators, anything you can synthesize with Web Audio.
.js file. No
touching the DAW source. No pull requests required to ship a new
instrument.
WavrPlugin, implement four methods, use the
provided helpers. The host handles the chrome, session save/load,
and transport sync for you.
this.emitBuffer(audioBuffer) and your plugin's
output lands on a new DAW track instantly. No glue code, no wiring,
one line.
getState() and it's
automatically saved to IndexedDB with the session. Restored on load.
Zero config.
onTransportStart,
onTransportStop, and onPlayheadTick to
sync your sequencer or effect to the DAW playhead in real time.
WavrPlugin.js in a
<script> tag and start building.
The entire plugin contract fits in a single class. Four required methods, four optional transport hooks, and a handful of helpers. That's the whole API surface.
pluginId,
pluginName, pluginColor. These tell
the DAW what to show in the topbar and how to style your chrome.
mount(el) with a DOM element. Build
your entire interface inside it. Vanilla JS, canvas, whatever
you like — no framework required.
OfflineAudioContext to render audio offline,
then call this.emitBuffer(buffer). The DAW places
it on a new track at the current playhead position.
getState(). The host
saves it to the session automatically.
setState() is called on reload — you get your state
back exactly as you left it.
pluginManager.register(MyPlugin) call in
WavrPro. The framework generates the topbar button, modal
chrome, and lifecycle management automatically.
class MyPlugin extends WavrPlugin { // ── Identity ────────────────────────── static pluginId = "my-plugin"; static pluginName = "My Plugin"; static pluginColor = "#6c5ce7"; static pluginMode = "modal"; constructor(hostAPI, options = {}) { super(hostAPI, options); this._state = { gain: 1.0 }; } // ── UI ───────────────────────────────── mount(el) { this._el = el; el.innerHTML = `<button id="go">Bounce</button>`; el.querySelector("#go") .addEventListener("click", async () => { const buf = await this._render(); this.emitBuffer(buf); // → new DAW track this.notify("Done!", "success"); }); } // ── Cleanup ──────────────────────────── destroy() { super.destroy(); } // ── State ────────────────────────────── getState() { return { ...this._state }; } setState(s) { this._state = { ...this._state, ...s }; } // ── Transport hooks ──────────────────── onBpmChange(bpm) { super.onBpmChange(bpm); } onTransportStart() { /* sync sequencer */ } onTransportStop() { /* stop sequencer */ } // ── Audio synthesis ──────────────────── async _render() { const dur = this.b2s(4); // 4 beats → seconds const off = new OfflineAudioContext( 2, Math.ceil(this.ctx.sampleRate * dur), this.ctx.sampleRate ); // ... build audio graph ... return off.startRendering(); } }
The SDK ships with a full-featured first-party plugin and a minimal example to copy from. Both are open source.
The complete plugin API — what you implement, what the host gives you, and what you call to send audio back.
We want to see what people build. Submit your plugin to the community gallery — working plugins with a test page and clear description get featured.