A codec library upgrade landed as a routine dependency bump — the kind of change that usually gets a quick listen and a shrug. It shouldn’t have been notable at all.
The change that looked routine
The upgrade was three minor versions ahead of what the pipeline had been running, pulled in as part of a broader dependency refresh. Nothing in the changelog mentioned audio behavior. The listening pass — a quick A/B on a handful of representative files — came back clean; nothing sounded obviously wrong. It would have shipped on that basis alone if the nightly comparison hadn’t run.
What the report showed
The nightly wavelens comparison against the previous build’s reference output came back FAIL, with exactly one check marked:
Level Fidelity · consistent +1.4 dB offset across the full file duration — Spectral Fidelity, Distortion, and Loudness all reported PASS.
That pattern narrowed the search immediately. Not a quality regression — Spectral Fidelity and Distortion were both clean, so nothing had introduced new artifacts or reshaped the frequency response. Just amplitude, and consistently across the whole file rather than in one section, which pointed at something structural in the encode path rather than a one-off glitch.
Finding the cause
A few minutes into the codec library’s changelog turned up the actual cause: a default had changed for an internal gain-normalization option, three versions back, buried in a “behavior changes” section rather than called out as a breaking change. The previous codec version hadn’t applied it; the new one did, silently, unless explicitly disabled.
+1.4 dB applied consistently across an entire file is genuinely hard to catch by ear in a quick listening pass — especially without an A/B reference playing at the exact same moment, which a quick spot-check pass usually doesn’t set up. It’s exactly the class of change a level-fidelity check is built to catch and a human review pass is built to miss.
What changed after
The fix was a one-line configuration change to pin the old gain-normalization behavior. The more lasting change was to the release checklist: the nightly wavelens analyze comparison against the previous release’s output, which had been an informational step someone occasionally glanced at, became a required gate with wavsummary blocking the build on any failure.
$ wavelens analyze --ref previous_release.wav --dut candidate_build.wav --out reports/nightly.html --json $ wavsummary ./reports --json || exit 1
Not a replacement for listening — a catch for the class of regression a listening pass reliably won’t flag on its own.
See it for yourself.
WaveLens compares a reference file against a processed copy and shows you exactly where they diverge — down to the sample — not just whether they still sound the same. One command, one report you can point at.