import test from "node:test"; import assert from "node:assert/strict"; import { Stft, fft } from "../src/analysis/spectrogram.ts"; import { encodeWav, scaleForPlayback } from "../src/audio/player.ts"; test("FFT of a sine peaks at the right bin", () => { const n = 1024, re = new Float32Array(n), im = new Float32Array(n); for (let i = 0; i < n; i++) re[i] = Math.sin((2 * Math.PI * 64 * i) / n); fft(re, im); let best = 0; for (let b = 1; b < n / 2; b++) if (Math.hypot(re[b], im[b]) > Math.hypot(re[best], im[best])) best = b; assert.equal(best, 64); assert.ok(Math.abs(Math.hypot(re[64], im[64]) - n / 2) < 1e-2); }); test("incremental STFT tracks a chirp's centroid", () => { const fs = 44100, st = new Stft(fs, 1024, 256); const sig = new Float32Array(fs); for (let i = 0; i < fs; i++) { const t = i / fs; sig[i] = Math.sin(2 * Math.PI * (500 * t + 2000 * t * t)); } let cols = 0; for (let s = 0; s < fs; s += 1000) cols += st.push(sig.subarray(s, Math.min(fs, s + 1000))); assert.equal(cols, st.columns.length); assert.ok(cols > 150); const early = st.centroid[5], late = st.centroid[cols - 5]; assert.ok(early > 400 && early < 1200 && late > 3500 && late < 5500, `${early} ${late}`); }); test("WAV encoding and playback scaling", () => { const p = new Float32Array([0, 2, -4, 1]); const s = scaleForPlayback(p, true); assert.ok(Math.abs(Math.max(...Array.from(s).map(Math.abs)) - 0.9) < 1e-6); const blob = encodeWav(s, 44100); assert.equal(blob.size, 44 + 8); });