effectcraft/apps/effectcraft-web/web/audio-worklet.js

45 lines
1.3 KiB
JavaScript

// EffectCraft audio output (AudioWorklet): plays interleaved stereo blocks posted by the page
// (src/audio.rs feeds them from the preview mixdown). Running dry plays silence, reported back
// as underrun frames.
class EffectcraftOutput extends AudioWorkletProcessor {
constructor() {
super();
this.queue = [];
this.offset = 0;
this.stopped = false;
this.port.onmessage = (e) => {
if (e.data === "stop") this.stopped = true;
else this.queue.push(e.data);
};
}
process(_inputs, outputs) {
const out = outputs[0];
const l = out[0];
const r = out[1] ?? out[0];
let i = 0;
while (i < l.length && this.queue.length) {
const b = this.queue[0];
const n = Math.min(l.length - i, (b.length - this.offset) >> 1);
for (let k = 0; k < n; k++) {
l[i + k] = b[this.offset + 2 * k];
r[i + k] = b[this.offset + 2 * k + 1];
}
i += n;
this.offset += 2 * n;
if (this.offset >= b.length) {
this.queue.shift();
this.offset = 0;
}
}
if (i < l.length) {
l.fill(0, i);
r.fill(0, i);
if (!this.stopped) this.port.postMessage({ underrun: l.length - i });
}
return !this.stopped;
}
}
registerProcessor("effectcraft-output", EffectcraftOutput);