BG
Tools & hardwarePython

Noise Meter

A real-time sound level meter in the browser: live dB dial, sound source recognition with YAMNet, spectrum and third-octave bands, noise dose, EU and Bulgarian norms, recordings and printable reports.

README

The noise meter gauge in action

Noise Meter

A sound level meter in the browser, with EU and Bulgarian noise regulations, room acoustics and machine learning.

A Python backend listens to the computer's microphone (or a phone's), and the interface opens anywhere on the same network. Useful for a noise complaint about neighbours, workplace noise assessment, room acoustics or machine monitoring.

Python FastAPI Tailwind CSS SQLite LiteRT PWA License: MIT

Български · English

Quick start · Features · Standards · Machine learning · Calibration · How it works · API


Screenshots

Level section
Level – gauge, “sounds like”, live noise scale and what can be heard
Analysis section
Analysis – sound recognition, spectrum, third-octaves, NR/NC
Norms section
Norms – workplace (LEX,8h), environment (Lden), NIOSH/OSHA dose
Room section
Room – reverberation time RT60 per ISO 3382-2
Recording report
Records – report with Ln, SEL, interval LAeq, comparison with regulations
Dashboard
Dashboard – when it’s loud, 24 h forecast, compare two recordings
Sounds section
Sounds – your own sounds, anomaly detection, audio clips
Printable report
Report – A4 for printing or PDF, modelled on ISO 1996-2

Level on a phone    Norms on a phone
On a phone the sections are in a bottom bar, the rest under “More”. It can be installed as an app.

Quick start

Python 3.10 or newer is required.

git clone https://github.com/Krumqnkata/noise-measure-tool.git
cd noise-measure-tool
python -m venv .venv

Activate the environment – on Windows (PowerShell):

.venv\Scripts\Activate.ps1

on Linux / macOS:

source .venv/bin/activate

Install and run:

pip install -r requirements.txt
python backend/main.py

Open http://localhost:8000. No microphone? Demo mode simulates talking, hum, loud bangs and a clap for RT60:

python backend/main.py --demo

Sound recognition and machine learning are optional – they need one library (Google’s official TFLite runtime). The YAMNet model (~16 MB) downloads itself into models/:

pip install -r requirements-ml.txt
Flag Default Description
--demo off simulated signal instead of a microphone
--port 8000 port
--host 0.0.0.0 address to listen on
--db noise.db database file with the recordings
--config config.json settings file
--no-classifier on no sound recognition
--https off https with a self-signed certificate – for a phone’s mic

Tip

On start the server prints the addresses to open from a phone on the same network. On Windows allow Python through the firewall on first run. On Linux you may need PortAudio: sudo apt install libportaudio2.

Features

Seven sections, each with its own address (/#norms, /#records/5, /#records/dashboard…). Light and dark theme (or follow the system), Bulgarian and English.

Keys: Space start/stop · 1–7 section · F full screen · R reset · S snapshot · T theme.

🎚️ Level

  • 0–140 dB gauge; A / C / Z frequency weighting and Fast / Slow / Impulse time weighting;
  • “Sounds like” and a live noise scale – 15 familiar sounds from a whisper to a jet engine;
  • “Hearing” – what the model recognises right now;
  • minimum, Leq, maximum, L10 / L50 / L90, peak; last-minute chart; full screen and snapshot.

📊 Analysis

  • noise source recognition – 12 groups: 🗣️ people · 🎵 music · 🐕 dog · 🐾 animals · 🚗 traffic · 🔨 construction · 🚨 siren · 🌧️ nature · 🏠 household · 💥 bangs · 〰️ hum · 🔇 silence (plus your own sounds);
  • 20 Hz – 20 kHz spectrum, 31 third-octave bands (IEC 61260), spectrogram, waveform;
  • NR and NC of background noise in a room – the octave spectrum over the curves.

🛡️ Norms

  • Workplace per Directive 2003/10/EC and Bulgarian Ordinance No. 6/2005: live LEX,8h and LCpeak, a traffic light for the lower (80 dB(A) / 135 dB(C)), upper (85 / 137) and limit value (87 / 140) and what each requires;
  • Environment per Directive 2002/49/EC and Ordinance No. 6/2006: Lday, Levening, Lnight and Lden against the limits for the selected type of area or room;
  • NIOSH and OSHA dosimeter: dose, TWA, 8 h projection and how much longer is safe.

🎙️ Records

  • every second: LAeq, LAFmax, LAFmin, LAImax, LCeq, LCpeak, LZeq, LZpeak and the recognised source;
  • scheduled (e.g. every night 23:00–07:00) – plus a morning sleep report: Lnight and events above 45 dB(A) per the WHO guidelines (2018), with source and clip;
  • report: L1…L99, SEL, LAeq per 1 / 5 / 15 / 60 min, time above threshold, histogram, sources, dose, LEX,8h, comparison with the regulations, low-frequency noise, events with clips;
  • printable report / PDF (A4) – measurement details, indicators, comparison with limits, signature;
  • dashboard: day × hour heat map, forecast for the next 24 h (median and 10–90 %, from at least 7 days of data), source by hour, compare two recordings; CSV export.

🧠 Sounds

  • your own sounds – record 2–3 examples (“the neighbour’s dog”, a lift) and the app recognises them and notifies you;
  • anomaly detection – learns what “normal” sounds like for a room or a machine and warns about unusual sound (the idea behind predictive maintenance);
  • audio clips – 3 s before and 5 s after each event, optionally no clips with speech, storage limit.

🏠 Room

  • RT60 per ISO 3382-2 (engineering method): a clap or a balloon → Schroeder curve, T20 and T30 for the 125 Hz – 4 kHz octaves, dynamic range check and guidance for bedroom, classroom, office, hall.

⚙️ Settings

  • the computer’s microphone or a phone’s; separate calibration for each (manual, typical or against a reference meter);
  • alarm: threshold, duration, sound, browser notifications and a list of events;
  • recognition model: fast YAMNet or accurate PANNs CNN14.

📱 Phone and PWA

  • the phone’s microphone – audio is streamed to the server without auto gain or noise suppression, and everything else (norms, records, recognition) works as with the computer’s mic;
  • browsers only allow the microphone over https – start with --https and accept the self-signed certificate warning;
  • install as an app (PWA) – home screen icon, opens in its own window.

Standards and regulations

What Document In the app
A/C weighting, Fast/Slow/Impulse, peak IEC 61672-1 audio.py – digital filters and detectors
Third-octave bands IEC 61260 31 bands, 20 Hz – 20 kHz
Workplace noise Directive 2003/10/EC, Ordinance No. 6/2005 LEX,8h, LCpeak, three action values
Noise dose NIOSH REL, OSHA 29 CFR 1910.95 85 dB / 3 dB and 90 dB / 5 dB
Environmental noise Directive 2002/49/EC, Ordinance No. 6/2006 Lday, Levening, Lnight, Lden, limit values
Night noise WHO Environmental Noise Guidelines (2018) events above 45 dB(A) in the bedroom
Background noise in rooms NR (ISO R1996), NC (ANSI S12.2) rating from the octave spectrum
Reverberation ISO 3382-2 T20, T30 per octave
Measurement report ISO 1996-2 printable report / PDF

The limit values of Ordinance No. 6/2006 were checked against the official text and its 2021 amendment (which only renames some of the area types). All numbers live in one place – backend/norms.py, with the source in a comment.

Warning

A laptop or phone microphone is not a certified class 1 or 2 instrument. The results are good as a guide and as a supplement to a complaint, but do not replace an official measurement by an accredited lab.

Machine learning

Model What it does Size Accuracy (AudioSet mAP) License
YAMNet (Google) recognition every second + embeddings (1024) ~16 MB ~0.31 Apache 2.0
PANNs CNN14 (Kong et al., 2020) more accurate recognition every 2 s, optional ~160 MB 0.43 weights CC-BY-4.0, code Apache 2.0
  • Both models run on the same ai-edge-litert library – no PyTorch or TensorFlow. CNN14 is the LiteRT copy from litert-community, pinned to a revision and checked with SHA-256 on download.
  • Your own sounds – each example recording is cut into ~1 s windows and YAMNet’s embedding is kept for each. A new sound is compared with the examples by cosine similarity (mean of the three closest); the threshold for “unknown” is computed from the examples themselves with leave-one-out.
  • Anomalies – a profile keeps the embeddings of “normal”. The score is the distance to the closest of them divided by the threshold (99.5th percentile during learning × 1.2) – above 1.0 is unusual. An unusually loud sound is an anomaly too, even if it sounds normal: more than 6 dB above the 99th percentile of the learning level pushes the score over 1.0.
  • Events from your own sounds and anomalies go into records, notifications and clips just like alarm events.

Calibration

A sound card measures relative to its maximum (dBFS). To get dB SPL, a calibration offset is added – 120 dB by default, typical for MEMS microphones in phones and laptops (−26 dBFS at 94 dB SPL).

For more accurate values use Settings → Using a reference meter: put a real sound level meter (or a 94 dB calibrator) next to the microphone, play a steady noise, enter its reading and press “Calibrate”. The offset is kept separately for each microphone – the computer’s and every connected phone.

Warning

Built-in microphones often have automatic gain control, which distorts the result. Turn it off in the system’s sound settings if possible.

How it works

flowchart LR
    mic["🎤 Computer microphone<br/>or demo signal"] --> audio
    phone["📱 Phone microphone<br/>AudioWorklet → /ws/mic"] --> audio
    audio["<b>audio.py</b><br/>A/C filters · F/S/I<br/>FFT · third-octaves · NR/NC<br/>12 s buffer"]
    audio -- "20 frames/s" --> ws["WebSocket /ws"]
    audio -- "1 row/s" --> db[("SQLite<br/>noise.db")]
    audio -- "LAF" --> alarm["alarm"] --> db
    audio -- "audio" --> cls["<b>classifier.py</b><br/>YAMNet · PANNs"]
    cls --> ml["<b>ml.py</b><br/>own sounds · anomalies<br/>clips"]
    ml --> db
    cls -- "1/s" --> ws
    audio -- "clap" --> room["<b>room.py</b><br/>RT60"]
    db --> api["REST API<br/>reports · dashboard · CSV"]
    ws --> ui["🖥️ Browser / PWA<br/>7 sections"]
    api --> ui
Loading
  • A and C weighting – digital filters from the analogue IEC 61672 curves via the bilinear transform.
  • Fast / Slow / Impulse – exponential averaging of the squared signal with τ = 125 ms / 1 s; Impulse is an asymmetric detector with 35 ms rise and 1.5 s decay.
  • LAeq, Ln, SEL – from the one-second values; LAE = LAeq,T + 10·lg(T / 1 s).
  • LEX,8h = LAeq,Te + 10·lg(Te / 8 h); Lden = 10·lg((12·10^(Ld/10) + 4·10^((Le+5)/10) + 8·10^((Ln+10)/10)) / 24).
  • RT60 – octave filter, Schroeder backward integration, a line through −5…−25 dB (T20) and −5…−35 dB (T30).
  • Recognition – YAMNet once a second on the last 0.975 s at 16 kHz; CNN14 every ~2 s on the last 2.5 s at 32 kHz (repeated to 10 s – the model’s input). Classes are grouped into 12 categories.

Layout

backend/
  main.py        FastAPI: page, API, WebSocket, alarm, recording, schedules, https
  audio.py       capture / demo / phone audio, filters, levels, spectra, NR/NC
  norms.py       regulations and standards: limits, LEX,8h, Lden, NR/NC curves
  room.py        RT60 (ISO 3382-2)
  scheduler.py   scheduled recordings
  classifier.py  recognition (YAMNet) and model choice
  panns.py       the more accurate PANNs CNN14 model
  custom.py      own sounds and anomalies (numpy)
  ml.py          machine learning events and audio clips
  db.py          SQLite with migrations: recordings, measurements, events, reports, dashboard
  certs.py       self-signed certificate for --https
static/
  index.html     the shell and seven sections, colours of both themes
  common.js      formatting, chart helpers, errors
  i18n.js        translations (the key is the Bulgarian text)
  meter.js · norms.js · analysis.js · records.js · dashboard.js · room.js · sounds.js
  mic.js         the phone microphone (AudioWorklet)
  report.html    the printable report / PDF
  sw.js · manifest.webmanifest · icons/   PWA
tests/           pytest – formulas, regulations, RT60, database, machine learning
scripts/
  screenshots.py the screenshots in docs/screenshots
  make_icons.py  PWA icons

Tests and screenshots:

pip install -r requirements-dev.txt
python -m pytest
python scripts/screenshots.py

API

Path Method Description
/ws WS data (~20/s), sound (~1/s), status, alarm, ml_event, clip, schedule_done
/ws/mic WS audio from the browser (PCM float32) – the phone’s microphone
/api/status GET state: measuring, source, offset, alarm, model
/api/devices, /api/device GET, POST input devices / select {"index": 3}
/api/calibration POST {"offset": 92.5} – for the current source
/api/start, /api/stop POST start / stop measuring
/api/alarm POST {"enabled": true, "threshold": 85, "duration": 3}
/api/events?limit=20 GET events: alarm, own sound, anomaly (with clip_id)
/api/norms GET the regulation tables (one place for the numbers)
/api/room/rt60 POST waits for a clap and returns RT60 per octave
/api/recording/start, /stop POST {"name": "Bedroom, night"}
/api/schedules GET, POST schedules; PUT, DELETE /api/schedules/{id}
/api/sessions GET all recordings
/api/sessions/{id} GET, PATCH, DELETE report / name and note / delete
/api/sessions/{id}/csv GET measurements as CSV
/report/{id} GET printable report / PDF
/api/dashboard?days=30 GET heat map, forecast, sources by hour
/api/custom-sounds GET, POST own sounds; PATCH, DELETE /api/custom-sounds/{id}
/api/custom-sounds/{id}/examples POST, DELETE {"seconds": 4} – record an example / delete the examples
/api/anomaly GET profiles and the active one
/api/anomaly/learn POST {"name": "Pump", "minutes": 2}
/api/anomaly/active POST {"id": 3} or {"id": null}; DELETE /api/anomaly/{id}
/api/clips, /api/clips/{id} GET, DELETE list / WAV file / delete
/api/clips/settings POST {"enabled", "on", "skip_speech", "max_mb"}
/api/classifier/model POST {"model": "yamnet"} or {"model": "panns"}

Errors come as a code ({"detail": {"code": "not_found"}}) and the interface translates them.

Ideas for the future

  • the phone’s microphone and installing as an app (PWA)
  • scheduled recordings with a sleep report
  • source recognition, own sounds, anomaly detection
  • comparing two recordings and a PDF report
  • Telegram or Discord notifications on alarm
  • several microphones at once (e.g. room and street) and the difference between them
  • a noise map from measurements in different places

License

MIT © 2026 Krumqnkata

The models are not part of the repository; they download into models/ when needed: