wavscan doesn’t compare two files the way wavelens does — it inspects one file on its own, no reference needed. But its “peaks” aren’t the sample peak or RMS level you’d read off a level meter. They are peaks in the frequency spectrum at one chosen moment, and reading them as anything else leads to the wrong conclusion.
Running it
You give wavscan a file and one moment in it — a timestamp with --at, or an exact sample index with --at-sample. Here, a file holding three tones at 500, 2000 and 8000 Hz:
$ wavscan --input multitone.wav --at 2.5 --top 3
query time 2.500s (sample 120,000 @ 48000Hz)
window 4096 samples (85.3ms, resolution 11.7Hz/bin)
channel 0:
dominant peak 2009.8 Hz @ -12.6 dB
top 3 peaks:
1. 2009.8 Hz -12.6 dB
2. 509.8 Hz -12.6 dB
3. 8009.8 Hz -18.6 dB
No --ref, no verdict, no pass/fail: a measurement of what frequencies are present at that instant, and how loud each one is. Every channel in the file is reported unless you restrict the query with --channel.
What a “peak” means here
A peak is a local maximum in the magnitude spectrum — a frequency where energy is concentrated. The dominant peak is the loudest one. A single tone gives one peak; the file above gives three. None of these numbers is the loudest sample in the file, or an average level.
Two gates decide which peaks are reported. A candidate below the noise floor (--noise-floor-db, -80 dB by default) is never picked. And two candidates closer together than a minimum separation count as one, so one tone’s spectral leakage into the neighboring bins isn’t reported as several peaks. You can ask for up to --top N peaks, and a quiet or narrowband signal may return fewer. Finding none is a valid result, not an error.
The window decides what you see
The analysis takes a window of samples centered on your query point, applies a Hann window, and computes the spectrum from that. The default window is 4096 samples; --window-samples accepts 1024 up to 32768. The window size trades time against frequency: at 48 kHz, 4096 samples gives bins about 11.7 Hz wide, and frequencies are reported to within that resolution, which is why 2000 Hz reads as 2009.8 Hz above. A larger window separates close tones more cleanly but averages over more time. A smaller one pins down the instant but blurs the frequency.
Jumping to the point a report flagged
wavscan is most useful when you already know where to look. A wavelens analyze report names the worst point it found — a sample, a frame, a frequency — and --at-sample takes that sample index directly, so you can see the actual frequency content at the spot that tripped the check, in the DUT and in the reference.
Getting the output into a script
Text is the default. --json and --csv print machine-readable output instead, and --html FILE also writes a self-contained report with the peaks labeled.
What wavscan doesn’t tell you
wavscan doesn’t report a file’s overall peak level, RMS level, crest factor or loudness. For those, the Loudness card in a wavelens report lists integrated loudness, loudness range, true peak and sample peak for both files (see BS.1770 loudness, explained), and wavelens plot draws one file’s waveform and spectrum with no reference needed.
And wavscan is no substitute for wavelens analyze once you have a reference to compare against. A spectrum at one instant can’t tell you whether this file still matches that one, which is the question a real comparison answers.
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.