Audio lens
Local, on-device audio toolbox for AI agents: voice-clone TTS, instrumental music, and audio verification — three installable Agent Skills.
npx -y skills add bman654/audio-forge --skill audio-lensAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Verify audio you (or a model) generated WITHOUT being able to hear it. Renders and inspects sound as numbers plus a screenshot-readable spectrogram PNG. Answers: is it in tune (what note / cents off)? right tempo (BPM)? clipping (distorted/too loud)? silent or empty? what is the spectral centroid (bright vs dull)? Use whenever you produce or receive a WAV — from TTS, music/SFX generation, synthesis, DSP code, or a recording — and need to CHECK it instead of trusting it blind. Trigger keywords: verify audio, check audio, is this in tune, what note, what pitch, what frequency, detect tempo / BPM, is it clipping, is it distorted, is it silent, analyze a WAV, spectrogram, waveform, RMS / loudness, audio QA. Zero-dependency Node CLI; no install.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
7.7 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it
Audio Lens
The concept (read this first)
You cannot hear. When you generate or receive audio, you are otherwise flying blind — you can't tell a perfect A4 from one a half-step flat, a clean beat from a clipped mess, or real sound from four seconds of silence. Audio Lens is the screenshot-equivalent for sound: it turns a sound into numbers you can branch on, and into a spectrogram PNG you can literally view and read.
Reach for it whenever audio is output you need to trust — TTS, generated music/SFX, a synthesis routine, DSP code under test, or a file someone handed you. Don't guess; measure.
It is a verification lens, not a music-library analyzer. It is reliable for: pitch/note of a tone, clipping, silence, spectral centroid (bright vs dull), and tempo of clean rhythmic signals. It deliberately does not do key detection and won't beat librosa on messy real-world music — don't oversell tempo on noisy audio.
The tool is at the repo root. Commands below assume you're in that directory; if
not, use the absolute path to bin/audio-lens.js. node --version must be ≥ 18.
Step 1 — trust it before you trust its numbers
Run the self-test. It synthesizes signals with KNOWN ground truth and asserts the analyzers recover them (a seeded PRNG makes even the noise tests deterministic).
node bin/audio-lens.js self-test
Expect a table ending in 12/12 passed — all green and exit code 0. If it's
not 12/12, stop — the install or environment is wrong; don't trust analyses. For a
machine-readable gate: node bin/audio-lens.js self-test --json → {"ok":true,...}.
Step 2 — the one-shot queries (the common case)
These print just the answer so you can parse or branch on it immediately. Point
them at a WAV file, or at a built-in signal with --signal <id>. Add --human for a
terse string instead of JSON.
# Is this in tune? What note?
node bin/audio-lens.js analyze voice.wav --pitch
# → {"f0":440.1,"note":"A4","cents":0} (cents = how far off; ±50 = halfway to next note)
node bin/audio-lens.js analyze voice.wav --pitch --human
# → A4 +0c (440.1 Hz) (or "none" if no stable pitch)
# Is it clipping / distorted / too hot?
node bin/audio-lens.js analyze render.wav --clips
# → {"clips":true,"clipPct":53.61,"clipped":94560} (clips:false when clean)
# Is it silent / empty?
node bin/audio-lens.js analyze out.wav --silence-ratio
# → {"silenceRatio":1.0,"silenceDb":-60} (1.0 = entirely silent; ~0 = full of signal)
# What tempo? (clean rhythmic audio only)
node bin/audio-lens.js analyze beat.wav --tempo
# → {"tempo":120.2,"onsets":7} (or {"tempo":null} if no clear beat)
# Other quick reads
node bin/audio-lens.js analyze x.wav --peak # {"peakDb":-1.94} loudest sample
node bin/audio-lens.js analyze x.wav --rms # {"meanRms":-4.95} average loudness
node bin/audio-lens.js analyze x.wav --centroid # {"centroid":440,...} brightness (Hz)
node bin/audio-lens.js analyze x.wav --peaks # top-3 tones as notes (chord check)
node bin/audio-lens.js analyze x.wav --peaks --human # → A4+0c C#5+3c E5+3c
You can combine queries — the JSON objects merge:
node bin/audio-lens.js analyze x.wav --pitch --clips --rms
How to read the answers
- pitch / note:
centsis the tuning error in cents (100 cents = one semitone).±30cis "noticeably off but recognizable";±5cis "in tune".{"f0":null}means no stable monophonic pitch (noise, silence, or a dense chord). - clips:
trueif >1% of samples hit full scale (≥0.999). Real clipping = audible distortion; if you generated this, lower the gain and re-render. - silenceRatio: fraction of samples below the threshold (default −60 dBFS). Near 1.0 means the file is effectively empty — a common generation failure.
- centroid: the spectral "center of mass" in Hz. Low = dull/dark, high = bright/hiss.
- tempo: only meaningful for clean, percussive/rhythmic audio. Trust
null.
Step 3 — see it (emit a spectrogram PNG, then view it)
When numbers aren't enough, render a spectrogram and read the image. It's the most information-dense view: x = time, y = log frequency (40 Hz → Nyquist), brightness = loudness (magma colormap, dark = quiet, bright = loud).
node bin/audio-lens.js analyze mystery.wav --spectrogram /tmp/spec.png
Then open/view /tmp/spec.png and interpret it:
- one flat horizontal line → a steady tone (pure note).
- several stacked horizontal lines → a chord / harmonics.
- a line sweeping up or down → a pitch glide / chirp.
- evenly spaced vertical streaks → clicks/beats (count them for rhythm).
- a broad wash filling the height → noise / broadband content.
- mostly black → silence.
(Headless PNGs have faint frequency gridline rows but no text labels — no font.)
Other images:
node bin/audio-lens.js analyze x.wav --waveform /tmp/wave.png # amplitude vs time
node bin/audio-lens.js analyze x.wav --rms-png /tmp/rms.png # loudness curve over time
Built-in signals (no file needed)
Great for sanity-checking the tool or demonstrating an expected reading. Ids:
sine440 sine1000 triad clicks chirp noise clipped.
node bin/audio-lens.js analyze --signal sine440 --pitch # → A4
node bin/audio-lens.js analyze --signal clicks --tempo # → ~120 BPM
node bin/audio-lens.js analyze --signal chirp --spectrogram /tmp/chirp.png # rising diagonal
Full readout & flags
analyze <file.wav> with no query flag prints the full JSON (duration, sample
counts, peak/clipping, RMS, centroid + first/second-half, onsets+times, tempo, pitch,
top-3 peaks, silenceRatio). Add --human for a labeled text block.
--fft <1024|2048|4096> FFT size (default 2048) --hop <256|512|1024> (default 512)
--silence-db <dBFS> silence threshold (default -60) --resample <hz> opt-in resample
--json (default) | --human
Important constraints
- WAV only. Reads PCM int 16/24/32-bit and IEEE float32, any channel count
(downmixed to mono), at the file's native sample rate. For mp3/flac/ogg/etc.,
transcode first:
ffmpeg -i in.mp3 out.wav(or-c:a pcm_s16leto force 16-bit). Compressed/ADPCM WAV and too-short inputs (< one FFT frame) error clearly. - Exit codes:
self-testexits nonzero on any failure; bad flags/files exit nonzero with a one-lineaudio-lens: …message on stderr. Branch on these. - Don't oversell tempo or pitch on messy/polyphonic real music — prefer
nullover a confident wrong number, and say so.
When NOT to use this
- You need genre/key/mood/instrument classification on real music → use librosa.
- The input isn't WAV and you can't transcode → convert first or use another tool.
- You actually need to listen for subjective quality → this measures, it doesn't judge taste.
What ships with it: 21 files
219.7 KB alongside SKILL.md, 10 of them executable
bin/
- audio-lens.jsruns13.8 KB
docs/
- cli.md8.1 KB
examples/
- chirp-spectrogram.png48.8 KB
- clicks-spectrogram.png14.4 KB
- clipped-waveform.png821 B
- sine440-waveform.png820 B
- triad-spectrogram.png41.5 KB
src/
- analyzers.jsruns10.6 KB
- colormap.jsruns736 B
- fft.jsruns2.8 KB
- generators.jsruns4.7 KB
- png.jsruns4.5 KB
- render.jsruns4.6 KB
- wav.jsruns6.5 KB
test/
- io-tests.jsruns5.4 KB
- self-tests.jsruns7.2 KB
web/
- index.html38.3 KB
- .gitignore14 B
- LICENSE1.0 KB
- package.json763 B
- README.md4.3 KB