Loudness result & errors
dsp-audio-metrics deliberately keeps error handling small and predictable.
Loudness functions
integratedLufs(audio, sampleRate)— the gated program loudness.shortTermLufs(audio, sampleRate)— returns{ lkfs: Float64Array, startTimes: Float64Array }of 3 s windows, refreshed every 100 ms. Silence yields empty arrays.loudnessRange(audio, sampleRate)— the LRA in LU;NaNwhen no valid short-term blocks.truePeakDb(audio, sampleRate)— peak of the 4×-oversampled reconstruction in dBTP.normalizeLoudness(audio, sampleRate, targetLufs)— returns a new Float64Array scaled so the integrated loudness equals the target. Leave the original untouched.
Silent / degenerate inputs
These are values, not errors — a mastering tool needs to show "-Inf" in its meter rather than crash:
| Condition | Value |
|---|---|
All-silent input, integratedLufs | -Infinity |
All-silent input, truePeakDb | -Infinity |
No valid short-term blocks, loudnessRange | NaN |
Mono (or zero-mid) content, stereoWidthDb | -Infinity |
measure propagates the same conventions, and its JSON form (bin) never emits NaN.
Real errors
| Signature | When | Error type |
|---|---|---|
sampleRate not a positive integer | any loudness / analysis call | RangeError |
| Empty / zero-length audio | any loudness / analysis call | TypeError |
| CLI: missing or unreadable file | bin/dsp-audio-metrics | exit code 2 |
Why NaN for LRA?
LRA is a statistic over short-term loudness blocks. If the signal is shorter than one 3 s window, or every block falls outside the range where the distribution is computed, the spread is undefined — so it is NaN, exactly like a median of an empty set.
Comparing with the CLI
measure() returns the same numbers the CLI prints: the CLI is a thin wrapper that decodes the WAV (16-bit PCM) and calls measure with the header's sample rate.
