// AudioWorklet processor — accumulates 4096 samples (~256ms at 16kHz) before sending class PCMProcessor extends AudioWorkletProcessor { constructor() { super(); this._chunks = []; this._total = 0; this._target = 4096; } process(inputs) { const ch = inputs[0] && inputs[0][0]; if (ch && ch.length > 0) { this._chunks.push(ch.slice()); this._total += ch.length; if (this._total >= this._target) { const out = new Float32Array(this._total); let offset = 0; for (const c of this._chunks) { out.set(c, offset); offset += c.length; } this._chunks = []; this._total = 0; this.port.postMessage(out.buffer, [out.buffer]); } } return true; } } registerProcessor('pcm-processor', PCMProcessor);