class PCMPlayerProcessor extends AudioWorkletProcessor { constructor() { super(); this.queue = []; this.offset = 0; this.bufferedSamples = 0; this.started = false; this.startThreshold = Math.round(sampleRate * 0.25); this.port.onmessage = (event) => { if (event.data.type === "reset") { this.queue = []; this.offset = 0; this.bufferedSamples = 0; this.started = false; return; } if (event.data.type === "audio") { const samples = new Float32Array(event.data.samples); this.queue.push(samples); this.bufferedSamples += samples.length; } }; } process(_inputs, outputs) { const output = outputs[0][0]; output.fill(0); if (!this.started) { this.started = this.bufferedSamples >= this.startThreshold; if (!this.started) { return true; } } let outputOffset = 0; while (outputOffset < output.length && this.queue.length) { const current = this.queue[0]; const count = Math.min(output.length - outputOffset, current.length - this.offset); output.set(current.subarray(this.offset, this.offset + count), outputOffset); outputOffset += count; this.offset += count; this.bufferedSamples -= count; if (this.offset === current.length) { this.queue.shift(); this.offset = 0; } } if (this.started && outputOffset < output.length) { this.port.postMessage({ type: "underrun" }); } return true; } } registerProcessor("audex-pcm-player", PCMPlayerProcessor);