A tiny, always-on-top Windows overlay that watches what your PC is actually playing (every app, mixed, via WASAPI loopback) and tracks your cumulative daily hearing dose using the NIOSH model — so you get a nudge before you've been loud for too long, not just when a peak happens.
Short loud moments are fine; sustained loudness is what damages hearing. So EarGuard stays calm on transient peaks and warns based on accumulated exposure over the day (resets at midnight, persists across restarts).
- LEVEL — estimated sound level in dB (green ≤ 75 / amber ≤ 85 / red above), with a live meter bar.
- TODAY'S DOSE — percent of your safe daily exposure used so far.
85 dB for 8 hours = 100%, using a 3 dB exchange rate (every +3 dB halves the safe time). Green under 100%, amber to 150%, red beyond.
When the dose crosses 100% you also get a single gentle Windows toast for the day, so you don't have to keep watching the overlay.
pip install -r requirements.txt
# or: pip install PyAudioWPatch numpyWindows only — it relies on WASAPI loopback capture. Python 3.9+.
python earguard.py- Left-drag the overlay to move it.
- Right-click for the menu: Calibrate, Reset dose, Toggle click-through, Compact mode, Quit.
- Click-through lets the mouse pass straight through the overlay so it never gets in your way. Because a click-through window can't be right-clicked, toggle it back off with the global hotkey Ctrl+Alt+E.
On first launch EarGuard drops a small Start-menu shortcut ("EarGuard") plus
an icon in %APPDATA%\EarGuard. This exists so the daily-dose toast shows up as
EarGuard with its own icon, instead of "Windows PowerShell" — a Windows toast
inherits the name and icon of the AppUserModelID
it's shown under, and a Start-menu shortcut carrying that ID is how you register
one for an unpackaged app. The shortcut also doubles as a no-console launcher
(pythonw.exe earguard.py). It's created once, best-effort, using only built-in
Windows APIs (no extra dependency). Don't want it? Delete
%APPDATA%\Microsoft\Windows\Start Menu\Programs\EarGuard.lnk and turn off the
warning by raising DOSE_WARN_PCT past your daily total.
Software can only read the digital level of the audio (dBFS). The actual loudness at your ears (dB SPL) depends on your headphones/speakers, DAC, and volume knob — EarGuard can't know that until you tell it once:
- Play music at your normal listening volume.
- Measure it with a phone SPL app (any free "decibel meter").
- Right-click → Calibrate and type the number the phone shows.
From then on the displayed dB tracks your setup. It's a single-point linear
calibration (one dBFS→SPL offset) — enough to keep you honest, not lab-grade.
Your calibration and dose are saved to %APPDATA%\EarGuard\state.json.
Re-calibrate if you flip the
A_WEIGHTINGoption (below), since weighting shifts the measured level.
EarGuard is an awareness tool, not a sound-level meter or a medical device. The number it shows is an estimate built on a single-point calibration and the assumption that your volume/output setup hasn't changed since you calibrated. Change your headphones, your DAC, or your Windows volume and the estimate drifts until you re-calibrate. Phone SPL apps themselves are only roughly accurate. Treat the dose as a helpful "you've been loud for a while" signal, not a precise measurement — and if you have any hearing concerns, see a professional.
Everything is in the CONFIG block at the top of earguard.py:
A_WEIGHTING(default on) — applies an IEC 61672 A-weighting filter before the RMS so readings track phone SPL meters (dBA) more closely. Set toFalsefor a raw broadband RMS. (Changing this changes the level, so re-calibrate.)REF_LEVEL/REF_HOURS/EXCHANGE— the NIOSH dose model (85 dB / 8 h / 3 dB). Not OSHA's 90 dB / 5 dB — NIOSH is the more protective standard.DOSE_FLOOR_SPL— levels below this are treated as silence for dose.SAVE_EVERY_SEC— how often the dose is checkpointed to disk.- Colors, size, opacity, smoothing, etc.
- Capture: PyAudioWPatch opens the default output device's
[Loopback]twin and reads the mixed int16 stream in a background thread. - Level: de-interleaved, optionally A-weighted, then broadband RMS → dBFS, plus your calibration offset → estimated dB SPL.
- Dose: each audio block adds
block_time / NIOSH_allowed_time(level)to the daily total. The audio thread accumulates under a lock; the tkinter UI polls, renders, and checkpoints on a throttle.
MIT — see LICENSE.