Downloads · 30 days
0
resoajoe/audio-health-nano
audio-health-nano is a audio classification model from resoajoe. Use it for the audio classification task on the model card, and read the license before you ship it in a product. The card lists the license as mit.
47,094 parameters. 188 KB. Six audio faults, one forward pass, multi-label.
Downloads · 30 days
0
Access
Public
Updated Sep 3, 2026
Repo size
392 KB
Likes
0
Public
Click a slice to open those files.
.pt200 KB · 48%
From the Hugging Face model README
47,094 parameters. 188 KB. Six audio faults, one forward pass, multi-label.
clipped · dropout · dc_offset · hum · bandwidth_loss · hiss
Domain measured / deployment domain tested: measured on ESC-50 clips with synthetic defects, plus 20 s of real office ambience; deployment domain: no real defective broadcast or call audio tested. (Fifth line of the card standard, added 2026-09-02: a number is only as good as the domain it was measured in.)
Audio defect detection is a solved problem at full model scale. The direct reference point is Higham et al., A No-Reference Model for Detecting Audio Artifacts using Pretrained Audio Neural Networks, WACV workshops 2022 (Amazon) — 1-second segments classified as No Defect / Hum / Hiss / Distortion / Clicks at 0.986 balanced accuracy, using a modified PANN-CNN6 (~4.8M parameters) on log-mel spectrograms. Broadcast QC tools have detected hum, clipping and dropouts for decades, some of it patented.
Their 0.986 is the reference for what a full-size, pretrained model does. This does not match it and does not claim to. What differs:
| Higham et al. 2022 | this model | |
|---|---|---|
| parameters | ~4.8M (PANN-CNN6) | 47K, ~100× smaller |
| pretraining | AudioSet-pretrained | none |
| output | single-label, 5 classes | multi-label, 6 faults — real recordings carry several at once |
| faults | hum, hiss, distortion, clicks | adds bandwidth loss and DC offset |
| reporting | balanced accuracy | per-fault margin over a single-threshold baseline, plus a cross-corpus transfer test |
Use theirs if you want accuracy. Use this if you need something that runs in 188 KB on a CPU thread, and you want to see which heads actually earn a model.
| fault | accuracy | majority | lift | best scalar | margin | recall |
|---|---|---|---|---|---|---|
dc_offset | 0.905 | 0.711 | +0.195 | 0.718 | +0.187 | 0.925 |
hum | 0.877 | 0.689 | +0.189 | 0.686 | +0.191 | 0.755 |
hiss | 0.901 | 0.697 | +0.204 | 0.886 | +0.015 | 0.984 |
bandwidth_loss | 0.905 | 0.714 | +0.192 | 0.882 | +0.023 | 0.684 |
clipped | 0.831 | 0.687 | +0.144 | 0.736 | +0.095 | 0.838 |
dropout | 0.793 | 0.695 | +0.098 | 0.750 | +0.043 | 0.719 |
hiss and bandwidth_loss do not reliably beat a single threshold. Both are broad
spectral-shape changes that one statistic captures well. Across repeated runs hiss has scored
anywhere from +0.015 to −0.068 against a standard-deviation threshold — that is, sometimes
worse than the threshold. Treat both as free riders on a shared forward pass, not as reasons to
use a model. If you only need those two, use a threshold.
Trained on ESC-50, evaluated on 20 s of real office ambience from a webcam microphone — a genuinely different source. The scalar baseline here is a threshold fitted on ESC-50 and transferred, which is what a deployed threshold actually is.
| fault | ESC-50 | rig microphone | transferred scalar | margin |
|---|---|---|---|---|
dropout | 0.824 | 0.899 | 0.763 | +0.136 |
clipped | 0.812 | 0.875 | 0.848 | +0.028 |
bandwidth_loss | 0.906 | 0.914 | 0.912 | +0.002 |
hiss | 0.908 | 0.904 | 0.894 | +0.010 |
dc_offset | 0.912 | 0.799 | 0.696 | +0.104 |
hum | 0.837 | 0.433 | 0.693 | −0.260 |
hum scoring below chance is a labelling artefact, not a model failureThe office recording already contains mains hum. Measured against its own broadband noise floor:
| frequency | peak above floor |
|---|---|
| 50 Hz | +28.8 dB |
| 60 Hz | +27.7 dB |
| 100 Hz | +33.2 dB |
| 120 Hz | +27.0 dB |
| 150 Hz | +30.9 dB |
| 180 Hz | +30.6 dB |
Every "no hum" example in that test is a recording with 30 dB of hum in it. The head is detecting hum that is genuinely present, against a label saying it is absent. In any environment with mains equipment, the negative class for hum does not exist, and a cross-corpus number measured there is meaningless.
This generalises: an operation the acquisition environment already performs cannot be detected as applied-versus-not. The same effect kills sharpening and denoising detectors on webcam frames, because the camera's own pipeline already sharpens and denoises.
dropout — the only head passing a strict cross-corpus gate. Use it.dc_offset, clipped — strong in-corpus, positive but modest across corpora. Use with a
validation set from your own material.hum — use on media files where a clean negative exists. Do not evaluate it on live
room audio from a mains-powered environment.hiss, bandwidth_loss — a threshold does nearly as well. Use them because they come free
with the forward pass, not because they need a network.For: media QC triage, archive ingest checks, flagging recordings for human review, and monitoring capture chains on hardware too small for a pretrained audio network.
Not for:
dropout recall is 0.719 in-corpus — it misses about a quarter of cases while being the
most transferable head.import numpy as np, cv2, onnxruntime as ort
from scipy import signal as sg
SR = 16000
FAULTS = ["clipped", "dropout", "dc_offset", "hum", "bandwidth_loss", "hiss"]
def spec(x): # x: 1 s of mono float audio at 16 kHz
f, t, S = sg.stft(x, SR, nperseg=256, noverlap=192)
P = np.log10(np.abs(S) + 1e-8)
P = np.clip((P + 8) / 8.0, -1, 3) # ABSOLUTE level preserved -- see note below
return cv2.resize(P.astype(np.float32), (64, 64), interpolation=cv2.INTER_AREA)
so = ort.SessionOptions()
so.intra_op_num_threads = 1
so.add_session_config_entry("session.intra_op.allow_spinning", "0")
sess = ort.InferenceSession("audio_health.onnx", sess_options=so,
providers=["CPUExecutionProvider"])
probs = 1 / (1 + np.exp(-sess.run(None, {"spectrogram": spec(x)[None, None]})[0][0]))
print({f: round(float(p), 3) for f, p in zip(FAULTS, probs)})
Do not per-window standardise the spectrogram. Sibling models in this family do, and it deletes
absolute level — which is exactly what clipping is. With standardisation the clipped head sits at
0.503, chance; keeping absolute level takes it to 0.828. The scaling above is deliberate.
ONNX Runtime sizes its intra-op pool to the core count and those workers spin-wait between
inferences, burning about 1.9 cores to serve 0.28 ms inferences. With intra_op_num_threads=1 and
allow_spinning=0, measured idle CPU dropped from 192% to 16.5% of one core, throughput unchanged.
7,000 train windows from ESC-50 folds 1–3, 2,400 test from folds 4–5 · faults sampled independently at p=0.30 so mixtures occur naturally · log-STFT (nperseg 256, noverlap 192), absolute level scaled to a fixed range, resized to 64×64 · 4 conv layers (16→32→48→64) · BCE with positive weighting capped at 10× · Adam 3e-3, 20 epochs.
Same architecture as resoajoe/alarm-nano, resoajoe/camera-health-nano and
resoajoe/blockgrid-nano, unchanged.
ONNX vs PyTorch, both CPU, 256 inputs: max relative logit difference 2.8e-07, 100% threshold agreement.
Every margin quoted here is against a stated baseline, because a margin without one is not a measurement. The baseline is the best single-threshold classifier over ten cheap statistics, fitted optimistically:
mean · std · lapvar (Laplacian variance) · hf (high-frequency energy ratio) ·
grad (Sobel magnitude) · entropy · centre_edge · radial_slope · row_fft_peak ·
col_fft_peak
The last four are spatially aware, and they were added after an earlier six-statistic baseline — all global aggregates — was found to systematically overstate model value on spatially structured tasks. A baseline that cannot see where anything is loses to a CNN by default. On one test task that flaw inflated an apparent margin from +0.060 to +0.261.
Two different questions are asked with it:
ESC-50 (public, CC BY-NC) plus 20 s of the author's own office ambience. No speech, no identifiable people, no personal data.