strictly unofficial polyfill for Web Audio API AudioWorklet
Switch branches/tags
Nothing to show
Clone or download
Latest commit 67f4947 Oct 6, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
LICENSE added license (MIT) Dec 10, 2017
README.md Fixed syntax highlighting issue Aug 26, 2018
audioworker.js audio io redesign and bug fixes Oct 5, 2018
audioworklet.js audio io redesign and bug fixes Oct 5, 2018

README.md

audioworklet-polyfill

Strictly unofficial polyfill for Web Audio API AudioWorklet. The processor runs in a Web Worker, which is connected via SharedArrayBuffer to a main thread ScriptProcessorNode.

edit: SharedArrayBuffers (SABs) are currently disabled in all major browsers due to security concerns. As a workaround, the polyfill falls back to transferable ArrayBuffers that are bounced back and forth between main thread and web worker. This requires double buffering, which increases latency (especially in Firefox it seems). The polyfill still works reasonably well even with this, in all tested user agents. But yeah, I do hope SABs get re-enabled rather sooner than later.

demos

https://webaudiomodules.org/wamsynths

Tested in stable Chrome 64, Firefox 57 and Safari 11. Edge test is still pending.

More info at webaudiomodules.org

usage

<script src="audioworklet.js"></script>
<script>
// audioworker.js should also reside at root
const context = new AudioContext();

AWPF.polyfill( context ).then( () => {
  // that's it, then just proceed 'normally'
  // const awn = new MyAudioWorkletNode( context );
  // ...
});
</script>

AWPF.polyfill() resolves immediately if polyfill is not required. Chrome 66 requires AudioContext activation via user gesture. This is reflected in the polyfill, which now accepts AudioContext instance as an argument.

description

audioworklet.js polyfills AudioWorkletNode and creates a web worker. Worker is initialized with audioworker.js script, which in turn polyfills AudioWorkletGlobalScope and AudioWorkletProcessor. audioWorklet.addModule() is thereby routed to web worker's importScript(), and raw audio processing takes place off main thread. Processed audio is put into a SAB (or transferable ArrayBuffer when SAB is unavailable), which is accessed in main thread ScriptProcessorNode (SPN) onaudioprocess() for audio output.

caveats

Due to SPN restrictions the number of input and output ports is limited to 1, and the minimum buffer length is 256. I've also cut corners here and there, so the polyfill does not accurately follow the spec in all details. Please raise an issue if you find an offending conflict.

AudioParams are still unsupported.

similar libraries

@developit has implemented a similar polyfill that uses an isolated main thread scope for audio processing.