'use strict'; const { test } = require('node:test'); const assert = require('node:assert'); globalThis.LOUDNESS_WASM_B64 = require('./loudness-wasm.js'); const L = require('./loudness'); const sine = (amp, freq, fs, secs) => { const a = new Float32Array(fs * secs); for (let i = 0; i < a.length; i++) a[i] = amp * Math.sin(2 * Math.PI * freq * i / fs); return a; }; const dbfs = (db) => Math.pow(10, db / 20); test('EBU Tech 3341 case: 1 kHz stereo sine at -23 dBFS measures -23.0 LUFS (wasm and js)', () => { for (const fs of [48000, 44100, 22050]) { const s = sine(dbfs(-23), 1000, fs, 20); const w = L.measureChannels([s, s], fs); const j = L.measureChannels([s, s], fs, { prefer: 'js' }); assert.ok(Math.abs(w - -23) < 0.1, `wasm ${fs}: ${w}`); assert.ok(Math.abs(j - w) < 1e-6, `js ${j} vs wasm ${w}`); } assert.strictEqual(L.engineName(), 'wasm'); }); test('EBU Tech 3341 case: -33 dBFS measures -33.0 LUFS', () => { const s = sine(dbfs(-33), 1000, 48000, 20); assert.ok(Math.abs(L.measureChannels([s, s], 48000) - -33) < 0.1); }); test('gating ignores silence around the music', () => { const fs = 48000, s = sine(dbfs(-23), 1000, fs, 10); const padded = new Float32Array(fs * 30); padded.set(s, fs * 10); // 20 s of silence would read about -27.8 ungated; only the partial 400 ms // blocks at the tone's edges still count, which is correct R128 behaviour. assert.ok(Math.abs(L.measureChannels([padded, padded], fs) - -23) < 0.2); }); test('silence is null', () => { const z = new Float32Array(48000 * 5); assert.strictEqual(L.measureChannels([z, z], 48000), null); });