32 lines
1.6 KiB
JavaScript

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);