npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@audio/measure-lossy

v0.1.1

Published

Lossy-transcode detection — spectral-cutoff estimation + source classification (Spek / aucdtect class)

Readme

@audio/measure-lossy npm MIT

Lossy-transcode detection — spectral-cutoff estimation + source classification (Spek / aucdtect class)

npm install @audio/measure-lossy
import lossy from '@audio/measure-lossy'

Is this "lossless" file really a lossless master, or an upsampled/transcoded MP3, AAC, Vorbis or Opus source relabelled as WAV/FLAC? Reads the file's long-term average spectrum (Welch, via @audio/spectral-ltas) plus a per-frame max-hold spectrum, finds where content stops (a sustained dB drop, not a notch), measures how steep that edge is, and counts the "swiss cheese" spectral holes and the MP3-specific ~16 kHz scalefactor-band notch that give away a lossy source. This is the numeric form of the manual "look at the spectrogram" method popularised by Spek and aucdtect/"Fakin' the Funk" guessers — the same heuristics (spectrogram cutoff, sfb21 notch), just measured instead of eyeballed.

let r = lossy(data, { fs: 44100 })
r.cutoff      // Hz — estimated content bandwidth
r.lossy       // boolean verdict
r.confidence  // 0..1, heuristic — not a calibrated probability
r.source      // best guess: 'mp3-128', 'opus-96', 'lossless', 'upsampled', 'unknown', …
r.evidence    // the numbers behind the verdict (see below)
r.spectrum    // { freqs, db } — the LTAS used, for plotting

data is a mono Float32Array, or Float32Array[] (one per channel — mixed down internally).

| Option | Default | | |---|---|---| | fs | 44100 | sample rate, Hz | | frameSize | 4096 | Welch/STFT analysis window, samples | | hop | frameSize / 2 | frame hop, samples | | floorDb | -90 | bins at or below this level count as "empty" | | minDrop | 20 | dB drop that counts as a spectral cutoff | | maxSeconds | 120 | analyse at most this much, evenly sampled across the file |

evidence:

| Field | | | |---|---|---| | cutoffDb | number | dB drop from the reference band to the cutoff bin | | sfb21 | boolean | MP3's ~16 kHz scalefactor-band starvation notch, independent of the overall cutoff | | cutoffSharpness | number | slope at the edge, dB/octave — a codec lowpass is steep (>60), a natural roll-off is gentle | | holes | number | persistent 4-16 kHz spectral holes per second ("swiss cheese" — low-bitrate MP3 signature) | | upsampled | boolean | cutoff sits at a clean fraction of fs — a sample-rate upsample, not a codec lowpass | | bandwidthRatio | number | cutoff / (fs / 2) |

Method (cited in full in lossy.js): LTAS + max-hold spectra over the analysed span; the highest frequency where the (smoothed) LTAS drops minDrop dB relative to the band 2 kHz below and stays down to Nyquist is the cutoff — max-hold arbitrates, extending the estimate toward Nyquist when transients demonstrably punch past what looked like a wall, but never resetting a genuine low cutoff back up on one loud click. Spectral holes and the MP3 sfb21 notch follow Hennequin et al. ("Codec-independent lossy audio compression detection", ICASSP 2017) and Yang et al. ("Detecting MP3 compression history", 2008); the bitrate→cutoff source table is LAME's/aoTuVb's/Opus's published defaults, with citations and measured caveats in lossy.js.

This method loses power above roughly 128-160 kbps — that's a documented, known limit of spectral-cutoff detection generally (aucdtect and Spek-based "guessers" share it), not specific to this implementation: well-tuned psychoacoustic encoders at moderate-to-high bitrates can be spectrally near-transparent. It is also fooled the other way by naturally band-limited material — a cassette dub, a narrow-band mic, an aggressive de-esser, or plain speech (see the audio-lena/raw test in test.js) can read exactly like a lossy cutoff. evidence exposes every number precisely so a caller/UI can judge instead of trusting a single boolean; confidence is a heuristic score, not a calibrated probability.

Also exported as an audio.js stat manifest (./audio — a.stat('lossy'), no pre-fold needed since the kernel already accepts multichannel input).

Use when: verifying a purchased/downloaded "lossless" file is what it claims to be; auditing a library for mislabelled transcodes; flagging upsampled masters before mastering/distribution.


Part of @audio/measure — the measure family umbrella.

MIT © audiojs