# Machine fault diagnosis via acoustic baseline > Machines hum in patterns; Sonarish lets you save a healthy baseline and compare later — acoustic diagnosis without cloud AI. 2025-11-28 · 20 min read · sonarish · by ntan (ntan) for uranashel Canonical HTML: https://uranashel.com/blog/machine-fault-baseline.html --- Rotating machinery sings in tones. A healthy induction motor produces a fundamental frequency tied to shaft speed, with harmonics stacked at integer multiples above it. Bearings add their own signature once races develop pits or cages loosen. Mounting hardware rattles when bolts fatigue. Trained vibration analysts chase all of this with accelerometers bolted to bearing housings and years of catalogued fault frequencies. Sonarish offers something humbler that still earns its keep: record a spectrum while the machine is known good, store it as a baseline on your phone, and compare later recordings to see which frequency bins grew louder. No audio leaves the device. No cloud service promises magical diagnosis. The method is acoustic fingerprinting, not full physics simulation. Nobody here solves Newton's equations for a drum assembly. The question is narrower: does today's sound carry more energy at 87 Hz than the baseline captured 18 months ago, back when the washing machine still spun smoothly. A microphone, an FFT, and honest diff math can settle that. ## Why machines hum where they do Start from the nameplate. 600 RPM means the shaft turns `f_r = 600/60 = 10` revolutions per second, so the lowest mechanical tone sits near 10 Hz. Simple imbalance pumps exactly that line, once per revolution. Misalignment tends to feed the 2nd harmonic at 20 Hz. Every panel bolted to the frame can resonate at whichever multiple matches its own stiffness, which is why a worn machine sounds like a chord. Bearings are the interesting part. A rolling-element bearing holds `N_b` balls between an inner race spinning at shaft speed and a fixed outer race, spaced by a cage. The cage revolves slower than the shaft, because each ball rolls between two surfaces moving at different speeds. Work through the rolling-contact geometry and the cage rate comes out as `FTF = (f_r/2)·(1 − (d/D)·cos φ)`, where d is ball diameter, D is pitch diameter, and φ the contact angle. A pit in the outer race gets struck once per passing ball; the impacts repeat at `BPFO = (N_b/2)·f_r·(1 − (d/D)·cos φ)`. Swap the minus for a plus and you have the inner-race frequency. For a common 8-ball geometry with d/D near 0.2, BPFO lands around 3.2 times shaft speed, and its harmonics climb from there. These formulas explain the shape of a machine spectrum. Sonarish does not plug numbers into them. It cannot: the app has no idea how many balls your drum bearing carries or what its pitch diameter is, and neither do you, unless you enjoy disassembling washing machines considerably more than I do. ## A repeatable workflow in the field Consistency beats clever algorithms. Place the phone at the same standoff distance every time; 0.5–1 m is typical. Use the same surface if possible; a rubber mat on a metal panel reduces extraneous vibration paths. Record 30–60 s of steady-state operation after the machine has warmed up, never the startup transient, when currents surge and everything is briefly louder. Tag the capture as a baseline with a human-readable machine name. In 18 months, a file called Recording 47 will mean nothing. We measured what sloppy placement costs. Bench note: 1 phone, 1 workshop compressor, 12 re-placements across one afternoon, position marked with tape on the floor. With the tape mark, per-bin spread below 2 kHz stayed within about ±2 dB. Freehand placement roughly doubled that spread, and a 30 cm distance error alone shifted broadband level by about 3 dB. Half the alarm threshold, spent before the machine changed at all. Tape is cheap. Months later, repeat the geometry as closely as you can and record again. Everything past that point is arithmetic. ## The diff, bin by bin The analysis chain runs 4096-sample Hann windows on 48 kHz microphone PCM at 50% overlap — twice the window length of the live spectrum view, trading update speed for a true 11.7 Hz resolution, the setup our [FFT for mortals](https://uranashel.com/blog/fft-made-readable.html) post walks through. Bin spacing works out to 48000/4096 ≈ 11.7 Hz. A 60 s capture with a 2048-sample hop yields about 1,400 windows, and averaging each bin across 1,400 windows squeezes the random wobble of the estimate well under 1 dB. The alarm threshold sits at +6 dB. Measurement noise is not what trips it. Sonarish converts the averaged magnitudes to decibels and subtracts the stored baseline spectrum bin by bin. The diff view highlights sustained rises above about 6 dB. Transient clicks from solenoids or relays can be suppressed with an optional median filter: take the per-bin median across time instead of the mean and a click occupying 3 windows out of 1,400 simply vanishes, so one-off events do not paint false alarms across the spectrum. ``` // per capture, off the audio thread S = stft(pcm48k, window = hann(4096), hop = 2048) for each bin b: level[b] = median(|S[:, b]|) // median beats mean: clicks vanish db[b] = 20·log10(level[b] + eps) + calib_offset if capture is BASELINE: store(machine_name, db, date, device_model) else: base = load(machine_name) for each bin b: diff[b] = db[b] − base.db[b] // bin-by-bin subtraction flag bins where diff[b] > +6 dB and rise spans ≥ 2 adjacent bins // lone spikes ignored ``` The 11.7 Hz bins carry one consequence worth naming. A 10 Hz shaft fundamental sits below the first usable bin center and smears into the spectrum's DC shoulder. Low-speed machines are read through their harmonic stacks instead, and those land comfortably inside the resolved range. ## Reading a diff without pretending to be an oracle Suppose a front-loading washer spins at 600 RPM during the extract cycle. 600 revolutions per minute equals 10 revolutions per second, so you expect strong energy near 10 Hz and its harmonics. After a year and a half of service, the diff view might show +12 dB near 87 Hz and at nearby multiples. That frequency may line up with a ball-pass frequency calculation for the drum bearing. It may equally be a loose counterweight. Sonarish does not auto-label the fault. It shows the change clearly enough that you can search bearing frequency formulas, call a technician, or decide the noise is still acceptable. That restraint is intentional. False confidence destroys trust faster than any raw graph could. We would rather be the instrument you carry down to the basement than the app that confidently mislabels a belt squeal as catastrophic bearing failure. ## What we tried and discarded Version one had an auto-diagnosis table. Feed the strongest diff peaks into a lookup of fault classes and print a verdict: imbalance, misalignment, outer race, inner race. It demoed beautifully on our own bench compressor. On any other machine it needed the bearing geometry from the formulas above, which no user has, so the classifier fell back on generic frequency ratios and produced confident nonsense often enough to scare us. Discarded. Cepstrum analysis came next. The cepstrum (an FFT of the log spectrum) collapses a whole harmonic family into a single peak and is standard practice in industrial vibration monitoring. It works. It may still ship someday. Every interface draft died at the same spot, though: explaining a quefrency axis to someone standing next to a rattling dryer. Parked. Full-spectrum level normalization we shipped and then partly removed. Early builds rescaled each new capture so its broadband level matched the baseline before diffing, to forgive distance errors. That also silently erased genuine growth in overall loudness, and for a wearing bearing the overall trend is half the story. Current builds apply the calibration offset, diff honestly, and report the broadband delta as its own number. ## Limits you should respect Microphone saturation ruins everything. Press the phone against a vibrating metal panel and the analog front end clips. The clipped waveform looks louder in the time domain but its spectrum lies — harmonics appear that were never physically present, right in the region where you hunt for bearing tones. Keep the phone at the marked standoff, in air, and re-record any capture that touched full scale. Low frequencies bring their own trap. Phone microphones are built for voice. Bench note: 5 phones, swept sine from a sealed speaker at 0.5 m, one evening in the lab — every mic was at least 10 dB down by 30 Hz, and two had lost 20 dB. A 10 Hz fundamental is effectively invisible to the hardware, so slow machinery gets diagnosed through the harmonics the mic still passes. Background room noise changes between sessions when HVAC seasons shift or a door stands open, so check what the room was doing before trusting a small diff. Different phone models have different frequency responses, and comparing a Pixel capture against an iPhone baseline mixes two unknown curves into the result; track a given machine on the same device across the years. For what the level numbers themselves mean, and why the display always says approximate SPL, see [A-weighting and decibels explained](https://uranashel.com/blog/a-weighting-decibels.html). ## Where this fits in the uranashel stack Baseline comparison is the feature that turned Sonarish from a party trick decibel meter into something I keep installed next to the fuse panel. It shares FFT parameters with the live spectrum view, uses the same approximate SPL calibration, and stores sessions in the app sandbox, following the [on-device architecture](https://uranashel.com/blog/on-device-first.html) the whole studio runs on. No account, no upload, no model trained on your washing machine humming at odd hours. The capture path also obeys the studio's audio rules: nothing allocates on the audio thread, as documented in [life on the audio thread](https://uranashel.com/blog/dsp-audio-thread.html), while the heavy averaging runs afterwards, where a slow millisecond costs nobody anything. If you want to see raw spectra before diffing, Phyzix exposes a live microphone analyzer suitable for classroom demos. The payoff of the whole discipline is boring in the best way. When the diff stays flat for months, you have evidence the repair held. When it creeps upward, you have a timestamped graph to show a technician instead of vague words about “sounding rougher lately.” --- uranashel · [Home](https://uranashel.com/) · [Apps](https://uranashel.com/apps.html) · [Lab](https://uranashel.com/lab.html) · [About](https://uranashel.com/about.html) · [Blog](https://uranashel.com/blog/) · [Developers](https://uranashel.com/developers/) · [API docs](https://uranashel.com/docs/) · [Privacy](https://uranashel.com/privacy.html) Machine-readable: [llms.txt](https://uranashel.com/llms.txt) · [sitemap.xml](https://uranashel.com/sitemap.xml) · [openapi.json](https://uranashel.com/openapi.json) · [API](https://uranashel.com/api/v1/)