import numpy as np, sys
from scipy.io import wavfile
from scipy.signal import resample
from numpy.fft import rfft, irfft

SR = 4000
def load(p):
    sr,x = wavfile.read(p); assert sr==SR
    return x.astype(np.float64)

sus = load(sys.argv[1]); ref = load(sys.argv[2]); label = sys.argv[3]
S = sus - sus.mean()
N = len(S)
# cumulative energy for local window normalization
cum = np.concatenate([[0.0], np.cumsum(S*S)])
# precompute FFT of S at a fixed fast length big enough for template up to ~ chunk
NFFT = 1<<int(np.ceil(np.log2(N + SR*60)))
FS = rfft(S, NFFT)

def ncc_best(t):
    t = t - t.mean(); n = np.linalg.norm(t)
    if n==0: return (0.0,0)
    t = t/n; L=len(t)
    FT = rfft(t[::-1], NFFT)
    corr = irfft(FS*FT, NFFT)[L-1:N]      # valid lags 0..N-L
    we = cum[L:N+1]-cum[0:N-L+1]
    ncc = corr/np.sqrt(np.maximum(we,1e-9))
    k=int(np.argmax(ncc)); return (float(ncc[k]),k)

fracs=[0.15,0.30,0.45,0.60,0.75,0.90]
chunk=int(45*SR)
speeds=np.round(np.arange(1.00,1.351,0.01),3)
print(f"=== {label} ===",flush=True)
results=[]
for fr in fracs:
    st=int(fr*len(ref)); base=ref[st:st+chunk]
    if len(base)<chunk*0.9: continue
    best=(-1,None,None)
    for k in speeds:
        tmpl=resample(base,max(8,int(round(len(base)/k))))
        ncc,lag=ncc_best(tmpl)
        if ncc>best[0]: best=(ncc,k,lag)
    ncc,k,lag=best
    results.append((st/SR,k,ncc,lag/SR))
    print(f" ref@{st/SR:6.1f}s -> k={k:.3f}  ncc={ncc:.3f}  suspect@{lag/SR:7.1f}s",flush=True)
# summary: for high-confidence matches (ncc>0.35) report weighted speed
good=[r for r in results if r[2]>0.35]
if good:
    ks=np.array([r[1] for r in good]); ws=np.array([r[2] for r in good])
    print(f" >> MATCHED chunks: {len(good)}/{len(results)}  speed k = {np.average(ks,weights=ws):.4f}  (min {ks.min():.3f} max {ks.max():.3f})",flush=True)
else:
    print(" >> no confident match",flush=True)
