import test from 'node:test'; import assert from 'node:assert/strict'; import { analyzeSpectrum } from '../src/analysis.js'; test('silence produces finite zero features and no peaks', () => { const f = analyzeSpectrum(new Float32Array(32).fill(-Infinity), new Float32Array(64), 48000); for (const key of ['rms', 'centroid', 'spread', 'entropy', 'flatness']) assert.equal(f[key], 0); assert.deepEqual(f.peaks, []); }); test('a single spectral tone has its exact frequency and zero spread and entropy', () => { const db = new Float32Array(32).fill(-Infinity); db[4] = -6; const f = analyzeSpectrum(db, new Float32Array([0.5, -0.5]), 48000); assert.equal(f.centroid, 3000); assert.equal(f.spread, 0); assert.equal(f.entropy, 0); assert.equal(f.rms, 0.5); assert.equal(f.peaks[0].frequency, 3000); }); test('uniform spectral power has maximum normalized entropy and flatness', () => { const f = analyzeSpectrum(new Float32Array(32).fill(-20), new Float32Array(64), 48000); assert.ok(Math.abs(f.entropy - 1) < 1e-10); assert.ok(Math.abs(f.flatness - 1) < 1e-10); assert.ok(Math.abs(f.centroid - 11625) < 1e-8); }); test('centroid weights spectral power, not decibel values', () => { const db = new Float32Array(4).fill(-Infinity); db[1] = 0; db[3] = -10; const f = analyzeSpectrum(db, new Float32Array(8), 8000); assert.ok(Math.abs(f.centroid - 1300 / 1.1) < 1e-7); }); test('nonfinite inputs cannot contaminate 3D coordinates', () => { const f = analyzeSpectrum(new Float32Array([NaN, Infinity, -Infinity, -30]), new Float32Array([NaN, 0]), 48000); for (const key of ['rms', 'centroid', 'spread', 'entropy', 'flatness']) assert.ok(Number.isFinite(f[key])); });