← All work

SnoreLog

Snoring Detection in Sleep Environments

Detecting snoring patterns in noisy sleep environments.

  • Acoustic Signal Processing
  • Audio Classification
  • Temporal Pattern Analysis
Year
2026
Role
Solo — concept, audio pipeline, app
Status
In development

How three approaches evolved to better detect snoring in real-world recordings.

A real 20-second bedroom recording as a mel spectrogram with five snores outlined, and below it what V1, V2 and V3 each flagged: V1 one long event, V2 four one-second runs, V3 the five snores plus three short false sounds
  • V1 — Amplitude-based: simple, but mistakes background noise for snoring.
  • V2 — CNN: 99.3% test accuracy, undone by sampling-rate bias, evaluation flaws and poor real-world generalization.
  • V3 — Acoustic + temporal: a two-stage algorithm that checks how a sound looks and whether it repeats like breathing.

TL;DR

Developed a snoring detection system for real-world sleep environments, exploring amplitude-based detection, CNN classification, and acoustic signal processing.

Despite achieving 99.3% initial test accuracy, the CNN failed in real-world conditions. Further investigation revealed a sampling-rate bias and flaws in the evaluation pipeline.

To address these limitations, I developed a two-stage detection algorithm combining acoustic features and temporal regularity, which identified repetitive snoring patterns in real-world recordings.

01

Research Objective

Background

I wanted to record and monitor my own snoring during sleep, particularly to identify significant snoring episodes without listening to hours of recordings.

However, real-world sleep environments contain many interfering sounds — clocks, conversations, birds, appliances and other ambient noise.

The challenge was not simply to record sound, but to distinguish snoring from background noise and identify meaningful snoring patterns.

Research Question

How can snoring be reliably told apart from other sounds in noisy, real-world sleep environments?

Objectives

  1. Research — Snore Detection

    Distinguish snoring from non-snoring sounds in real-world bedroom recordings.

  2. Service — Snoring Monitoring (Not covered on this page. Built into the SnoreLog app.)

    Measure nightly snoring levels and track changes over time.

Five minutes of a real night: sound level over time, with 67 snores marked by ear in green and 15 other sounds in red; 14 of the other sounds are louder than the quietest snore and five are louder than every snore
Sleep environments are rarely silent, making it difficult to distinguish snoring from other sounds based on loudness alone.

02

Development Journey

Three approaches were explored, each addressing limitations identified in the previous iteration.

01Amplitude-Based DetectionLimitedIdentified the limitations of amplitude-based detection in noisy environments.Threshold Detection

Hypothesis

Snoring could be identified as relatively loud acoustic events.

Methodology

Implemented a simple threshold-based detector. The app sampled the recording's amplitude every 200 ms and treated anything above a fixed threshold as a potential snoring event.

Sounds that came back within 10 seconds were merged into the same event, so that one snore was not counted many times.

Results

In use, the detector fired on many environmental sounds — clocks, conversations and birds — because they also crossed the threshold. Measured on real recordings, it failed in both directions:

  • False positives: three of four recordings of clinking sounds were logged as snoring.
  • Missed snoring: in a quieter 15-minute stretch of a real night, the threshold fired once — on a sound that was not snoring — and missed every snore below it.
  • Merged snoring: breaths are 3–5 s apart, always inside the 10-second merge window, so continuous snoring collapsed into a single event and the night scored 95, "Great".
Five minutes of a real night with V1's fixed threshold as a dashed line: 67 snores marked by ear sit around or below it, a few peaks cross it briefly, and V1 records no event
V1's fixed threshold on five labelled minutes of a real night. Short peaks cross the line but never stay above it for the 0.5 s V1 requires, so 67 snores produce no event and the night scores 95, "Great".
Two recordings under the V1 threshold: real snoring and clinking each produce exactly one snoring event
Real snoring and a clinking sound look the same to V1: one event each.

Limitations

A single threshold measures how loud the room is, not what made the sound. It cannot adapt when the background changes, and it has no notion of a snore's shape.

Takeaway

Amplitude alone is insufficient for distinguishing snoring from environmental noise.

The next iteration focused on the acoustic characteristics of snoring rather than signal intensity.

02CNN-Based ClassificationInvalidatedUncovered a sampling-rate bias and evaluation flaws behind 99.3% initial test accuracy.PyTorch · CNN · Mel Spectrogram

Hypothesis

A convolutional neural network could learn the distinctive time-frequency patterns of snoring and classify them more accurately than amplitude thresholding.

Methodology

1. Dataset

Used a public snoring dataset from Kaggle (Khan, 2019): one-second clips, split 70 / 15 / 15 into training, validation and test sets.

CategoryClips
Snoring500
Non-snoring500
Total1,000

2. Feature extraction

Converted each clip into a 64-band mel spectrogram. The pipeline assumed every recording was 48 kHz — an assumption later found to be wrong.

ParameterValue
Assumed sampling rate48 kHz
FFT size1,024 (21 ms)
Hop length256 (5.3 ms)
Mel bands64
Input dimension64 × 188
A one-second snoring clip as a waveform, and the same clip as a 64 by 188 mel spectrogram
One second of audio becomes a 64 × 188 image: 64 mel bands by 188 time frames.

3. Model architecture

Designed a lightweight CNN for eventual on-device use. Six channel configurations were compared, prioritising low computational cost.

ParameterValue
ArchitectureLightweight CNN + global average pooling
Channels12 → 12
Parameters1,489
Model size~6 KB
CNN architecture: a 64 by 188 spectrogram input, two convolution blocks of 12 channels, global average pooling, and a single snoring probability output

4. Data augmentation

TechniqueConfiguration
Noise injectionSNR 10–30 dB
Pitch shifting±2 semitones
Time shifting±20%
Volume scaling0.1–1.5×

Each of the 700 training clips gained four augmented copies. The final training set held 3,720 clips: these 3,500, plus 22 one-second segments of my own clinking recordings (as non-snoring) and matching extra snoring copies, each with their augmentations. Augmentation was applied only after the split, so no test clip had a copy in training.

Results

99.3%
initial test accuracy (149 of 150)
98.2%
mean test accuracy across 30 training runs
1 / 900 s
classified as snoring in a real 15-minute night

On a real 15-minute sleep recording, the model labelled only one of 900 seconds as snoring. In the same segment, the final detector (V3) found 32 snoring events; these have not yet been confirmed by manual annotation.

This discrepancy motivated a deeper investigation into the training and evaluation pipeline.

Failure Analysis

1. Spurious correlation — sampling-rate bias

The dataset mixes 44.1 kHz and 48 kHz recordings, and the pipeline treated all of them as 48 kHz without resampling. A 44.1 kHz clip therefore ended in 0.08 s of padded silence and had its frequencies read about 9% too high. More importantly, the sampling rate was strongly correlated with the label.

Class44.1 kHz48 kHz
Non-snoring45050
Snoring58442

A rule using only the sampling rate would score about 89% on the full dataset. The CNN might have learned this preprocessing artifact rather than relying only on acoustic characteristics.

Stacked bars: 90% of non-snoring clips are 44.1 kHz and 88% of snoring clips are 48 kHz

Controlled experiment

All 150 test clips were properly resampled to 48 kHz and evaluated with the already-trained model.

Evaluation conditionAccuracy
Original preprocessing99.3%
Correct sampling rate at inference68.7%
Accuracy falls from 99.3% to 68.7% after resampling; snoring recall stays at 98.7% while correctly rejected non-snoring clips fall from 100% to 38.7%
Snoring recall is unchanged; the drop comes from non-snoring clips, which the model had learned to recognise partly by their 44.1 kHz artifacts.

The model is sensitive to preprocessing artifacts. The 68.7% is not the expected performance of a model retrained on a corrected pipeline.

2. Model selection bias

The test set was used to choose the final architecture among six candidates, which compromised the independence of the final test score.

A checkpoint bug compounded this: a shallow copy of the model's state dictionary kept changing as training continued, so the "best" snapshot was not preserved. Some earlier figures — including a 100% result — cannot be treated as independent estimates of generalisation.

3. Real-world generalisation

The CNN continued to perform poorly on real sleep recordings. Differences in background noise, distance to the microphone, sound intensity and room acoustics plausibly contributed, but the experiments did not isolate domain shift from the preprocessing and evaluation problems.

Takeaway

High benchmark accuracy does not guarantee real-world performance.

Unintended correlations, inconsistent preprocessing and evaluation design can significantly distort reported performance. This motivated an approach built on domain-specific acoustic characteristics and temporal context.

03Acoustic & Temporal AnalysisPromisingDeveloped a two-stage detection algorithm for repetitive snoring patterns.FFT · Temporal Analysis

Hypothesis

Snoring is characterised not only by its acoustic properties but also by its temporal relationship to breathing: snores recur with each breath, while most bedroom noises happen once. Requiring both a snore-like sound and a breathing-like rhythm should therefore separate snoring from one-off noises.

Methodology

A lightweight, two-stage rule-based detector that runs on the phone. Stage 1 finds sounds with snore-like acoustics; Stage 2 checks whether they repeat like breathing.

Pipeline: audio, adaptive noise floor, event detection, Stage 1 acoustic features, Stage 2 temporal validation, snoring

Stage 1 — Acoustic feature analysis

Adaptive noise floor. Instead of a fixed threshold, the background level is estimated from the quietest moments (15th percentile) of a rolling 90-second window, so the detection threshold follows changes in the room.

Feature extraction. Six characteristics from FFT-based spectral analysis and timing:

FeatureCriterionWeight
Low-frequency energyShare of energy in 60–300 Hz0.28
TonalityNot flat like noise (spectral flatness)0.18
High-frequency energyLittle energy in 1–8 kHz0.15
DurationAbout one breath (0.7–2.5 s)0.15
HarmonicityHarmonic peak structure0.14
OnsetAttack pattern0.10

Snore score = Σ (feature score × weight)

Events scoring at least 0.55 pass Stage 1. Two hard rules reject sounds with excessive high-frequency energy or a noise-like flat spectrum. A sweep over 0.30–0.95 on nine real recordings showed 0.55 to be the strictest value that still keeps every snoring recording.

Average spectra of 88 snores marked by ear, 82 other bedroom sounds and 7 clinking sounds; all three put most of their energy below 300 Hz
Average spectra of sounds labelled by ear. Snores, other bedroom sounds and clinking all put most of their energy below 300 Hz, so spectral shape alone does not separate them.

Stage 2 — Temporal pattern validation

Stage 1 judges each sound alone, and non-snoring sounds can share its acoustics. Stage 2 examines the timing between candidates.

ParameterCriterion
Inter-event interval1.2–10 seconds
Minimum repetitions4 events
Coefficient of variation≤ 0.35

CV = standard deviation of intervals / mean interval

A lower CV means more consistent repetition. Four events are required because three unrelated sounds can land at even spacing by chance; four means three intervals must agree.

Stage 2 on real recordings: snores marked by ear arrive every 3.7 s with interval CV 0.10; three clinking sounds are evenly spaced (CV 0.02) but too few to confirm
Stage 2 on real recordings. Snores marked by ear arrive every 3.7 s (CV 0.10) and are confirmed after four. The clinking sounds were evenly spaced too (CV 0.02), but there were only three, so they were never confirmed.

Results

Stage 1 — Public dataset

On the 1,000 Kaggle clips, Stage 1 alone reached 80.0% accuracy (78.7% on the CNN's 150-clip test split) without any supervised training. Most misses came from clips filled with sound from start to end, which leave the adaptive floor no quiet moment to measure against.

Full system — Real recordings

The Kaggle clips are isolated one-second recordings, so they cannot test Stage 2, which needs a sequence of events. The complete system was therefore evaluated on real recordings.

RecordingsAmplitude (V1)Stage 1 onlyBoth stages (V3)
9 short clips (5 snoring, 4 clinking)6 / 96 / 99 / 9
15 minutes of a real night1 event58 candidates32 snores in 2 bouts
Five labelled minutes of a real night in three rows: the snores marked by ear, what Stage 1 passed, and what V3 confirmed, green where it matches a real snore and red where it does not
V3 against five minutes labelled by ear. It finds 62 of the 67 snores; 11 of its 73 calls are other sounds, most of them around minute 4.

These results are promising, but the night has not been manually annotated, so precision and recall on real recordings are not yet measured. The detector costs about 0.039% of one CPU core — roughly 11 seconds of compute for an eight-hour night (measured on a laptop, not yet on a phone).

Limitations

  1. Isolated snoring events. At least four consecutive events are required, so isolated or highly irregular snoring may be missed — acceptable for the current goal of finding sustained episodes rather than every single snore.
  2. Periodic environmental noise. Regular sounds such as a ticking clock could still satisfy the temporal criteria; none were among the test recordings.
  3. Quantitative validation. Manually annotated real-world recordings are needed to measure precision, recall and F1-score. The weights were set by hand from a few recordings.

Takeaway

Temporal context provides information that individual acoustic features cannot.

Combining frequency-domain analysis with temporal validation identified repetitive snoring in real recordings without a trained neural network.

03

Key Findings

  1. 01

    Data quality matters more than benchmark accuracy

    The CNN reached 99.3% test accuracy, but the sampling rate was correlated with the labels. Preprocessing and methodology have to be validated before a score can be interpreted.

  2. 02

    Real-world generalisation requires careful evaluation

    Performance on isolated clips did not carry over to continuous recordings of real nights. Evaluation must reflect the acoustic conditions and temporal structure of the application.

  3. 03

    Temporal context can improve detection

    Single sounds can be hard to tell from environmental noise — a clinking sound had a snore's spectrum. How sounds repeat over time adds the missing information.

  4. 04

    Algorithm design should reflect the application

    Rather than maximising a public benchmark, the final approach targets meaningful snoring episodes in continuous recordings, which led to a lightweight, task-specific detector.

04

Future Work

  1. Quantitative evaluation

    Build a manually annotated set of real sleep recordings and measure precision, recall and F1-score for the complete system.

  2. Hybrid detection

    Combine acoustic features, a lightweight neural network retrained on a corrected pipeline, and temporal validation to improve robustness across recording environments.

  3. Snoring intensity estimation

    Estimate the relative acoustic intensity of detected episodes from energy, duration and spectral characteristics — kept separate from clinical measures of sleep-disordered breathing.

  4. On-device monitoring

    Validate whole nights on a phone, including battery consumption, and generate automatic recording summaries.

Conclusion

This project began as an attempt to monitor my own snoring and evolved into an investigation of audio classification, dataset bias and real-world detection.

Across three iterations, I explored the limits of amplitude-based detection, found hidden weaknesses in a CNN's evaluation, and built a lightweight algorithm that combines acoustic features with temporal regularity.

Reliable systems require not only effective algorithms, but also rigorous evaluation and a clear understanding of the environments in which they operate.

Built with

  • Python
  • PyTorch
  • torchaudio
  • NumPy
  • FFT
  • CNN
  • Dart
  • Flutter

Deep dives

Individual pieces of this project, written up on their own.