Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Noise Sentinel: Laptop Noise Pattern Detector

Noise Sentinel is a local, single-laptop acoustic anomaly detection project. It detects short, loud, low-frequency burst events from demo audio, uploaded WAV files, or optional laptop microphone capture. It stores event records in SQLite, estimates a time-of-day event rate lambda(t), and scores whether recent activity is unusual under a Poisson model.

The first version is intentionally scoped to one laptop. It answers:

  • When do loud burst-like events tend to happen?
  • How many events were detected?
  • Is the latest activity unusual compared with the learned baseline?
  • What is the probability of at least one event in the next time window?

It does not claim route prediction yet. A single fixed microphone cannot infer direction or road movement without more sensors.

Workflow Illustration

flowchart LR
    A["Audio input<br/>Demo, WAV upload, optional mic"] --> B["Signal processing<br/>Windows, FFT, spectrogram"]
    B --> C["Feature extraction<br/>dBFS, low band, high band, burstiness"]
    C --> D["Event detection<br/>Score + robust z threshold"]
    D --> E["Event merge<br/>Nearby frames become one event"]
    E --> F["SQLite storage<br/>data/events.sqlite"]
    F --> G["Time model<br/>Circular KDE estimates lambda(t)"]
    G --> H["Poisson model<br/>Expected counts and anomaly score"]
    H --> I["Streamlit dashboard<br/>Charts, tables, forecast"]
    F -. "Future multi-sensor data" .-> J["Spatial upgrade<br/>Hotspots, corridors, route prediction"]
Loading

What This Version Can Do

  • Generate synthetic noisy-bike-like demo audio.
  • Load uploaded .wav files.
  • Optionally record from the laptop microphone if sounddevice is installed.
  • Convert raw audio into interpretable acoustic features.
  • Detect possible burst events using loudness, low-frequency energy, high-frequency energy, and sudden energy rise.
  • Merge nearby candidate frames into one event.
  • Store event logs in data/events.sqlite.
  • Export events to data/events_export.csv.
  • Estimate time-of-day intensity lambda(t) with circular kernel smoothing.
  • Forecast the probability of at least one event in the next configurable time window.
  • Score recent activity using a Poisson upper-tail anomaly test.
  • Show the workflow in a Streamlit dashboard.

What This Version Does Not Claim

  • It does not estimate calibrated real-world SPL unless the microphone is calibrated. The app uses dBFS, a relative digital audio level.
  • It does not triangulate direction or position.
  • It does not predict road routes with one laptop.
  • It does not identify people or vehicles. It only detects acoustic patterns that look like loud burst events.

Project Structure

noisy_pattern_detect/
|-- app.py                              # Streamlit dashboard
|-- pyproject.toml                      # Project metadata
|-- requirements.txt                    # Python dependencies
|-- run_dashboard.ps1                   # Windows helper script
|-- README.md                           # Project documentation
|-- data/
|   `-- README.md                       # Local generated data lives here
|-- noisy_pattern_detect/
|   |-- __init__.py
|   |-- audio_capture.py                # WAV loading and optional microphone capture
|   |-- config.py                       # Detection and model parameters
|   |-- demo.py                         # Synthetic demo audio generator
|   |-- detection.py                    # Event scoring and event merging
|   |-- models.py                       # KDE, Poisson, forecasting, anomalies
|   |-- pipeline.py                     # End-to-end analysis helper
|   |-- reporting.py                    # Summary helpers
|   |-- signal_processing.py            # FFT features and spectrograms
|   `-- storage.py                      # SQLite persistence
`-- tests/
    `-- test_pipeline.py                # Basic demo pipeline test

Run the Dashboard

From PowerShell:

cd "C:\Users\22246\Downloads\Jobs\noisy_pattern_detect"
python -m streamlit run app.py

Or:

cd "C:\Users\22246\Downloads\Jobs\noisy_pattern_detect"
.\run_dashboard.ps1

Live microphone capture is optional. Install it only if you want live recording:

pip install sounddevice

The rest of the app works with demo audio and uploaded WAV files.

Completed Workflow

Stage Input Processing Output
1. Audio capture Demo audio, uploaded WAV, optional microphone Normalize to mono float audio and resample Short audio stream
2. Signal processing Raw waveform Windowing, FFT, band-energy extraction, spectrogram Frequency/time features
3. Event detection Spectral features Detection score plus robust z-score threshold Possible noisy-burst event records
4. Event storage Event records SQLite insert data/events.sqlite
5. Time modelling Event timestamps Circular KDE over hour-of-day Expected arrival rate lambda(t)
6. Anomaly detection Observed vs expected counts Poisson upper-tail probability Unusual activity score
7. Dashboard Audio, events, models Streamlit tabs and Plotly charts Interactive local interface
8. Future upgrade Multiple sensors Spatial KDE, DBSCAN, Markov/HMM route model Hotspot and route prediction

Theory

Audio waveform

The microphone or WAV file produces a discrete signal:

x[n], n = 0, 1, 2, ...

If the sample rate is 22050 Hz, one second contains 22050 samples. The waveform gives amplitude over time, but not directly which frequencies are present.

Short-time frequency analysis

The app splits audio into overlapping frames:

window_seconds = 0.50
hop_seconds    = 0.25

Each frame is multiplied by a Hann window and transformed with the real FFT:

X[k] = sum(x[n] * w[n] * exp(-j * 2*pi*k*n/N))
P[k] = |X[k]|^2

Intuition: this turns a sound chunk into "how much energy exists at each frequency".

Band energy features

For each frame:

total_power     = sum(P[k])
low_band_power  = sum(P[k]) for 80 Hz <= f < 500 Hz
high_band_power = sum(P[k]) for 500 Hz <= f < 3000 Hz

The ratios are:

low_band_ratio  = low_band_power / total_power
high_band_ratio = high_band_power / total_power

Intuition:

  • 80-500 Hz captures boom and rumble energy.
  • 500-3000 Hz captures sharper mechanical/acoustic texture.
  • Ratios help avoid treating every loud broadband sound as the same thing.

Relative loudness

The app computes RMS level:

RMS = sqrt(mean(x[n]^2))
dBFS = 20 * log10(RMS)

dBFS is a relative digital level, not calibrated real-world dB SPL.

Burstiness

The detector compares the log energy of each frame with the previous frame:

burstiness = max(0, log_energy[t] - log_energy[t-1])

Intuition: a sudden rise is more event-like than a steady background hum.

Detection score

The frame score is:

score =
    level_score
  + burst_score
  + 1.8 * low_band_ratio
  + 0.8 * high_band_ratio

A frame becomes a candidate if:

dBFS >= min_dbfs
low_band_ratio >= min_low_band_ratio
and either:
    robust_z(score) >= z_threshold
    or score >= absolute_score_threshold

Robust z-score

The detector uses the median and median absolute deviation:

z = 0.6745 * (score - median(score)) / MAD

This is less sensitive to outliers than a mean/std z-score.

Event merging

Candidate frames close together are merged:

merge_gap_seconds = 2.0

This counts one acoustic pass as one event rather than many overlapping frames.

Time-of-day intensity model

Events are converted into hour-of-day values:

23.5 = 11:30 PM
0.25 = 12:15 AM

The app estimates a smooth circular intensity curve:

lambda_hat(t) = (1 / days) * sum(GaussianCircular(t - t_i, bandwidth))

Circular smoothing means an event near midnight influences both late-night and just-after-midnight estimates.

Poisson anomaly model

Let K be the number of detected events in a time window:

P(K = k) = (lambda * t)^k * exp(-lambda * t) / k!

For recent activity, the app compares:

observed_count
expected_count from lambda(t)

The upper-tail probability is:

P(K >= observed_count)

The anomaly score is:

anomaly_score = -log10(P(K >= observed_count))

Interpretation:

Score Meaning
near 0 ordinary
around 1 uncommon
around 2 rare
3+ very unusual under the current model

Forecasting

For a future window of length dt hours:

expected_count = lambda(current_time) * dt
P(at least one event) = 1 - exp(-expected_count)

Main Parameters

Parameter Default Meaning
target_sample_rate 22050 Audio sample rate used by the pipeline
window_seconds 0.50 Duration of each FFT analysis frame
hop_seconds 0.25 Step between frames
low_band_hz 80-500 Frequency band used for boom/rumble energy
high_band_hz 500-3000 Frequency band used for sharper acoustic energy
min_dbfs -38.0 Minimum relative digital loudness for candidate frames
min_low_band_ratio 0.12 Required fraction of power in the low band
z_threshold 3.5 Adaptive robust z-score threshold
absolute_score_threshold 1.15 Absolute fallback score threshold
merge_gap_seconds 2.0 Merge nearby candidate frames into one event
kde_bandwidth_hours 1.0 Smoothing width for lambda(t)
forecast_minutes 30 Forecast horizon
anomaly_window_hours 1.0 Recent window used for anomaly scoring

Function Map

Workflow stage Files/functions
Audio capture audio_capture.load_wav_bytes, audio_capture.record_microphone, demo.generate_demo_audio
Signal processing signal_processing.extract_features, signal_processing.compute_spectrogram
Event detection detection.add_detection_scores, detection.detect_events
Event storage storage.init_db, storage.insert_events, storage.load_events, storage.export_events_csv
Time modelling models.circular_kde_intensity, models.hourly_counts
Anomaly detection models.poisson_anomaly, models.recent_window_anomaly
Forecasting models.forecast_next_window
Dashboard app.py

Future Spatial and Route Upgrade

To move from "when does noise happen?" to "where is it going?", each event must include spatial context:

event_time, sensor_id, latitude, longitude, confidence

With multiple sensors, the project can add:

  • spatial KDE for heatmaps
  • DBSCAN for repeated corridors
  • a transition matrix such as P(next_sensor = j | current_sensor = i)
  • road-graph Markov chains such as P(segment_j | segment_i)
  • Hidden Markov Model / Viterbi decoding when the true road segment is uncertain

The current version builds the detection, storage, time-modelling, anomaly, and dashboard foundation first.

About

Noise Sentinel: a fixed-location acoustic anomaly detector

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages