1e29264cymsimweb: WebGPU companion of cymsim with YAML/form editor, live spectrogram and playbackJeremy Magland 1import test from "node:test";
2import assert from "node:assert/strict";
3import { Stft, fft } from "../src/analysis/spectrogram.ts";
4import { encodeWav, scaleForPlayback } from "../src/audio/player.ts";
6test("FFT of a sine peaks at the right bin", () => {
7 const n = 1024, re = new Float32Array(n), im = new Float32Array(n);
8 for (let i = 0; i < n; i++) re[i] = Math.sin((2 * Math.PI * 64 * i) / n);
9 fft(re, im);
10 let best = 0;
11 for (let b = 1; b < n / 2; b++) if (Math.hypot(re[b], im[b]) > Math.hypot(re[best], im[best])) best = b;
12 assert.equal(best, 64);
13 assert.ok(Math.abs(Math.hypot(re[64], im[64]) - n / 2) < 1e-2);
14});
16test("incremental STFT tracks a chirp's centroid", () => {
17 const fs = 44100, st = new Stft(fs, 1024, 256);
18 const sig = new Float32Array(fs);
19 for (let i = 0; i < fs; i++) { const t = i / fs; sig[i] = Math.sin(2 * Math.PI * (500 * t + 2000 * t * t)); }
20 let cols = 0;
21 for (let s = 0; s < fs; s += 1000) cols += st.push(sig.subarray(s, Math.min(fs, s + 1000)));
22 assert.equal(cols, st.columns.length);
23 assert.ok(cols > 150);
24 const early = st.centroid[5], late = st.centroid[cols - 5];
25 assert.ok(early > 400 && early < 1200 && late > 3500 && late < 5500, `${early} ${late}`);
26});
28test("WAV encoding and playback scaling", () => {
29 const p = new Float32Array([0, 2, -4, 1]);
30 const s = scaleForPlayback(p, true);
31 assert.ok(Math.abs(Math.max(...Array.from(s).map(Math.abs)) - 0.9) < 1e-6);
32 const blob = encodeWav(s, 44100);
33 assert.equal(blob.size, 44 + 8);
34});