OPEN SDK · BROWSER DAW EXTENSIONS

BUILD AUDIO PLUGINS.

Extend WAVR PRO with instruments, effects, and generators. Pure JavaScript. Zero dependencies. No build step. Runs entirely in the browser.

3
SDK FILES
0
DEPENDENCIES
8
SYNTH INSTRUMENTS
PLUGINS POSSIBLE
SCROLL
DRUM MACHINE ARPEGGIATOR CHORD PADS STEP SEQUENCER GRANULAR SYNTH REVERB ENGINE SAMPLE SLICER BEAT GENERATOR MIDI TO AUDIO LOOPER DRUM MACHINE ARPEGGIATOR CHORD PADS STEP SEQUENCER GRANULAR SYNTH REVERB ENGINE SAMPLE SLICER BEAT GENERATOR MIDI TO AUDIO LOOPER
WHAT IS THIS

A plugin system
for the browser DAW.

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.

Extend without forking
Plugins load at runtime from a single .js file. No touching the DAW source. No pull requests required to ship a new instrument.
Pure JavaScript contract
Extend WavrPlugin, implement four methods, use the provided helpers. The host handles the chrome, session save/load, and transport sync for you.
Bounce to track
Call this.emitBuffer(audioBuffer) and your plugin's output lands on a new DAW track instantly. No glue code, no wiring, one line.
State lives with the session
Return your state from getState() and it's automatically saved to IndexedDB with the session. Restored on load. Zero config.
Transport-aware
Override onTransportStart, onTransportStop, and onPlayheadTick to sync your sequencer or effect to the DAW playhead in real time.
Framework-free core
The plugin class is plain JavaScript — no React, no bundler, no toolchain. Drop WavrPlugin.js in a <script> tag and start building.
HOW IT WORKS

Five methods.
Infinite possibilities.

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.

1
Declare your identity
Set the static metadata fields — pluginId, pluginName, pluginColor. These tell the DAW what to show in the topbar and how to style your chrome.
2
Build your UI in mount()
The host calls mount(el) with a DOM element. Build your entire interface inside it. Vanilla JS, canvas, whatever you like — no framework required.
3
Render audio & emit
Use OfflineAudioContext to render audio offline, then call this.emitBuffer(buffer). The DAW places it on a new track at the current playhead position.
4
Persist with getState / setState
Return a plain object from getState(). The host saves it to the session automatically. setState() is called on reload — you get your state back exactly as you left it.
5
Register once
One 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();
  }
}
INCLUDED PLUGINS

Ship-ready from day one.

The SDK ships with a full-featured first-party plugin and a minimal example to copy from. Both are open source.

INSTRUMENT
Drum Machine
A 16/32-step sequencer with 8 fully synthesized instruments. Transport-synced, session-persistent, and immediately usable in WAVR PRO.
Kick, Snare, Clap, HH Open & Closed, Tom Hi & Mid, Ride
16 or 32 steps with per-step velocity
Swing control 0–75%
Mute, solo, and per-instrument volume
4 genre presets + randomize
Bounces a full loop to any DAW track
Try it live →
EXAMPLE
Chord Pad
A minimal 120-line plugin showing the complete lifecycle. Pick a key, pick a bar count, bounce a chord loop. The recommended starting point for new plugin authors.
Demonstrates all four required methods
Shows state persistence and BPM sync
emitBuffer, emitStateChange, notify usage
OfflineAudioContext synthesis pattern
View source →
YOUR PLUGIN
What will you build?
Arpeggiator, granular synthesizer, reverb unit, beat slicer, looper, vocoder, FM synth — anything you can build with Web Audio can be a WAVR plugin.
Start from ExamplePlugin.js
No dependencies to install
Submit to the community gallery
Get started →
API REFERENCE

Small surface.
Full control.

The complete plugin API — what you implement, what the host gives you, and what you call to send audio back.

Methods to implement REQUIRED
mount(el: HTMLElement)
Build UI into el. Store as this._el.
destroy()
Clean up. Call super.destroy() last.
getState() → object
Return JSON-serialisable plugin state.
setState(state: object)
Restore from a previous getState() snapshot.
Transport hooks OPTIONAL
onBpmChange(bpm: number)
Call super first. Keeps this.bpm in sync.
onTransportStart(beat, ctxTime)
DAW playback started at this beat position.
onTransportStop()
DAW playback stopped.
onPlayheadTick(beat: number)
Called ~60×/sec while playing. Keep it cheap.
Host-injected properties READ ONLY
this.ctx: AudioContext
The shared DAW audio context. Do not close it.
this.bpm: number
Current host BPM. Updated by onBpmChange().
this.options: object
Options passed at plugin registration time.
Helpers to call NEVER OVERRIDE
emitBuffer(buf, label?)
Send rendered audio to a new DAW track.
emitStateChange()
Mark session dirty. Call when state changes.
notify(msg, level?)
Show a DAW toast. Levels: info success warn error.
b2s(beats) / s2b(seconds)
Time conversion at the current host BPM.

Build something.
Share it.

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.

pluginId is unique and hyphenated
Four required methods implemented
super.destroy() called last
this.ctx used, not a new AudioContext
CSS classes prefixed with pluginId
getState() returns only plain JSON