import {ToneDetector} from './test-signals.js'; // Explicit paired-signal mode only. Bounded numeric observations; never PCM. class PairedSignals extends AudioWorkletProcessor { constructor() { super();this.detector=new ToneDetector(sampleRate); this.frames=0;this.inputFrames=0;this.zeros=0;this.energy=0;this.peak=0; this.events=[];this.overflow=0;this.credit=true;this.next=0;this.stopped=false; this.port.onmessage=({data})=>{if(data==='ack')this.credit=true;if(data==='stop')this.stopped=true;}; } process(inputs,outputs) { if(this.stopped||this.frames>=sampleRate*125)return false; this.frames+=outputs[0]?.[0]?.length??128; const samples=inputs[0]?.[0]; if(samples) { for(const x of samples){this.inputFrames++;this.energy+=x*x;this.peak=Math.max(this.peak,Math.abs(x));if(x===0)this.zeros++;} for(const event of this.detector.process(samples,currentFrame)) { if(this.events.length<32)this.events.push(event);else this.overflow++; } } if(this.credit&&this.frames>=this.next) { this.port.postMessage({activity:{inputFrames:this.inputFrames,processedFrames:this.frames, exactZeroFrames:this.zeros,rms:this.inputFrames?Math.sqrt(this.energy/this.inputFrames):0, peak:this.peak,sampleRate},signals:this.events,overflow:this.overflow}); this.events=[];this.credit=false;this.next=this.frames+sampleRate; } // Browser initializes every output block to zero. No mic monitoring. return true; } } registerProcessor('av-paired-signals',PairedSignals);