// Known synthetic signatures only. No PCM/frame retention or content upload. export class VideoContinuity { constructor(){this.frames=0;this.bad=0;this.duplicates=0;this.missing=0;this.ambiguous=0;this.previous=null;} observe(rgba,timeMs) { // Waiting for the known source is not a scored part of the test. const reject=()=>{if(this.previous){this.frames++;this.bad++;}}; if(!rgba||rgba.length!==80||!Number.isFinite(timeMs)){reject();return;} const bits=[]; for(let i=0;i<20;i++) { const rgb=Array.from(rgba.slice(i*4,i*4+3)); if(rgb.some(x=>!Number.isFinite(x)||x<0||x>255)||Math.max(...rgb)-Math.min(...rgb)>35) {reject();return;} const mean=rgb.reduce((a,b)=>a+b,0)/3; if(mean>70&&mean<185){reject();return;} bits.push(mean>=185?1:0); } const value=bits.slice(2,18).reduce((n,b)=>(n<<1)|b,0); const parity=bits.slice(2,18).reduce((a,b)=>a^b,0); if(bits[0]!==1||bits[1]!==0||bits[18]!==parity||bits[19]===parity||value>=16) {reject();return;} this.frames++; if(this.previous) { const gap=timeMs-this.previous.time,delta=(value-this.previous.value+16)%16; // Large time/sequence gaps can hide wraps. Unknown is never zero. if(gap<=0||gap>100||delta>8)this.ambiguous++; else if(delta===0)this.duplicates++; else this.missing+=delta-1; } this.previous={time:timeMs,value}; } summary() { return {frames:this.frames,badMarkers:this.bad,ambiguousGaps:this.ambiguous, duplicateFraction:this.frames&&!this.ambiguous?this.duplicates/this.frames:null, missingFraction:this.frames&&!this.ambiguous?this.missing/(this.frames+this.missing):null}; } } export class AudioPilot { constructor(rate) { if(!Number.isFinite(rate)||rate<16000||rate>192000)throw new RangeError('sample rate'); this.rate=rate;this.size=Math.round(rate*.01);this.coeff=2*Math.cos(2*Math.PI*7000/rate); this.q1=0;this.q2=0;this.count=0;this.windows=0;this.missing=0;this.pending=0; this.maxGap=0;this.first=null;this.last=null;this.expected=null;this.discontinuities=0; } process(samples,frame) { if(this.expected!==null&&frame!==this.expected) { this.discontinuities++;this.q1=0;this.q2=0;this.count=0; } this.expected=frame+samples.length; for(let i=0;i=.008; const now=(frame+i+1)/this.rate*1000; if(present) { if(this.first===null)this.first=now-this.size/this.rate*1000; this.last=now;this.windows+=1+this.pending;this.missing+=this.pending; this.maxGap=Math.max(this.maxGap,this.pending*10);this.pending=0; } else if(this.first!==null)this.pending++; this.q1=0;this.q2=0;this.count=0; } } summary() { return {windows:this.windows,firstMs:this.first,lastMs:this.last, missingFraction:this.windows&&!this.discontinuities?this.missing/this.windows:null, gapMaxMs:this.windows&&!this.discontinuities?this.maxGap:null, trailingGapMs:this.pending*10,discontinuities:this.discontinuities}; } }