/* PCM capture/playback processors for the optional low-latency voice path. */ 'use strict'; class AtlasPcmCaptureProcessor extends AudioWorkletProcessor { constructor(){ super(); this.pending=[]; this.pendingLength=0; this.port.onmessage=(event)=>{ if((event.data||{}).type!=='flush') return; this.flush(); this.port.postMessage({type:'flushed'}); }; } flush(){ if(!this.pendingLength) return; const samples=new Float32Array(this.pendingLength); let offset=0; this.pending.forEach(function(chunk){samples.set(chunk,offset);offset+=chunk.length;}); this.pending=[]; this.pendingLength=0; this.port.postMessage({type:'pcm',samples:samples.buffer},[samples.buffer]); } process(inputs){ const input=inputs[0]&&inputs[0][0]; if(!input||!input.length) return true; this.pending.push(new Float32Array(input)); this.pendingLength+=input.length; if(this.pendingLength>=1024){ this.flush(); } return true; } } class AtlasPcmPlaybackProcessor extends AudioWorkletProcessor { constructor(){ super(); this.queue=[]; this.queueOffset=0; this.phase=0; this.sourceRate=22050; this.ended=false; this.cancelled=false; this.queuedFrames=0; this.reportCountdown=0; this.drainedSent=false; this.port.onmessage=(event)=>{ const data=event.data||{}; if(data.type==='push'&&data.samples){ const pcm=new Int16Array(data.samples); const samples=new Float32Array(pcm.length); for(let index=0;index=this.queue[0].length){ this.queue.shift(); this.queueOffset=0; } return this.queue.length?this.queue[0][this.queueOffset]:null; } nextSample(){ if(!this.queue.length) return null; if(this.queueOffset+11&&this.queue[1].length?this.queue[1][0]:this.queue[0][this.queueOffset]; } advance(){ if(!this.queue.length) return; this.queueOffset+=1; this.queuedFrames=Math.max(0,this.queuedFrames-1); if(this.queueOffset>=this.queue[0].length){this.queue.shift();this.queueOffset=0;} } process(_inputs,outputs){ const output=outputs[0]&&outputs[0][0]; if(!output) return !this.cancelled; output.fill(0); if(this.cancelled) return false; const ratio=this.sourceRate/sampleRate; for(let index=0;index=1){this.advance();this.phase-=1;} } this.reportCountdown-=1; if(this.reportCountdown<=0){ this.reportCountdown=20; this.port.postMessage({type:'buffer',frames:this.queuedFrames}); } if(this.ended&&!this.queue.length&&!this.drainedSent){ this.drainedSent=true; this.port.postMessage({type:'drained'}); } return true; } } registerProcessor('atlas-pcm-capture',AtlasPcmCaptureProcessor); registerProcessor('atlas-pcm-playback',AtlasPcmPlaybackProcessor);