Embedded Snore Detection: Offline Snore Recognition SDK for Sleep HealthNEW
The Value of Snore Detection: Scenarios and Workflow
Roughly one in three people snore during sleep — over 50% among middle-aged men. Snoring is not just a nuisance: it can signal simple snoring, upper airway resistance syndrome, or sleep apnea (SAS/OSAS), a condition affecting hundreds of millions worldwide. For device makers, snore recognition is the step from "recording sleep" to "understanding sleep".
Three scenario families:
Medical & health monitoring — — snore analysis combined with heart-rate variability (HRV) and blood-oxygen (SpO₂) data supports apnea-event screening. Key indicators logged: snore index (events/hour), duration per event, intensity distribution, frequency characteristics — compiled into professional sleep-quality reports for clinicians
Smart home — — smart mattresses adjust head elevation in real time; smart pillows inflate to reposition the sleeper; smart AC systems tune temperature, humidity and fresh-air flow
Mobile apps — — a phone alone provides low-cost overnight monitoring, automatically flags anomalies and connects to professional diagnosis when needed
A full overnight loop: continuous capture → snore event detection → overnight statistics (duration / count / share) → severity grading → sleep report and (for moderate cases) anti-snore intervention. Everything runs on-device; audio never leaves it.
The Signature of Snoring: Time and Frequency
Time-domain traits
Periodicity synchronized with breathing — — 2–4 seconds per cycle; inspiratory and expiratory phases carry different energy
Quasi-periodic envelope — — amplitude changes gently between neighboring cycles
Single event 0.5–2 seconds — — with a characteristic three-stage energy shape: fast rise → stable middle → slow decay
Frequency-domain traits
Fundamental around 80–120 Hz — — main energy concentrated in **100–850 Hz**, with high-frequency components up to 2,000 Hz
3–5 visible harmonics — — energy decays level by level with frequency
Band distribution — — low band 40–60%, mid band 30–40%, high band under 10%
Below is a real snoring recording — waveform (top) and Mel spectrogram (bottom). The periodic events synchronized with breathing and the low-frequency energy concentration are clearly visible:

Audio samples (real recordings — press play):
🔊 Snore (real sample)
🔊 Another snore recording
These traits define the approach: not "hearing something like snoring", but recognizing a series of events synchronized with the breathing rhythm.
How Recognition Works: Preprocessing → Features → Algorithms
Signal preprocessing
Denoise the raw audio first, then frame it for analysis:
Frame length 25 ms — — short-time stationarity
Frame hop 10 ms — — information continuity between frames
Hamming window — — reduces spectral leakage
Feature extraction
Time domain — — short-time energy (intensity changes), zero-crossing rate (frequency character), autocorrelation (periodicity)
Frequency domain — — MFCC (human-hearing-inspired cepstrum), spectral centroid (distribution center), band energy ratios (energy shape)
Recognition algorithms
The engine works in "events", not per-frame labels:
1. Locate events first — detect energy bursts, output onset/offset and intensity per snore
2. Periodicity verification — true snore events arrive in sequences following the breathing rhythm; isolated bursts (turning, coughing, bed-frame noise) form no sequence and are rejected
3. Generalize across people — training covers age, gender and body-type variation while sustained noise (AC, fans, rain) is suppressed
The hard parts
Individual variability is large; sustained background noise is constant; and snoring must be separated from breathing sounds, movement and bed noise. Event-based analysis plus targeted negative training handles all three.
Accuracy and Performance
Note: performance figures are based on internal test environments; actual results depend on hardware and deployment scenarios.
System and Data Presentation
The engine outputs an event stream (time markers and intensity); the application layer aggregates overnight statistics, grades severity, and renders the sleep report.
A sleep report typically shows: an overnight timeline of events, total duration and count against baseline, and weekly trends — the long-term view that makes changes meaningful.
Product Forms
Bedside monitors (acoustic-first, contact-free), smart mattresses and pillows (sleep data plus physical intervention), wearables (screening on the wrist), and dedicated anti-snore devices (real-time detection driving the intervention).
Platform and Hardware Requirements
The model runs on the low-power platforms common to sleep products — from 100 MHz-class chips upward, within 0.2–1 MB (INT8) — and shares the SoC with the device's main workload.
C API and Embedded Integration
The snore detection library exposes a concise streaming C API: the caller just keeps feeding 16 kHz mono PCM; framing, Mel preprocessing and model inference run internally, and frame-level probabilities are aggregated by the alarm strategy into snore-event callbacks.
Full interface declaration (snore_detect.h):
/**
* snore_detect.h — 鼾声识别统一接口
*
* 封装 Mel 预处理 + 推理引擎 + 报警策略, 内部模型消费线程处理音频。
* 与录音模块 (audio_capture.h) 相互独立: 调用者自行决定音频来源
* (录音回调 / wav 文件 / 网络流), 通过 snore_detect_feed 送入, 数据任意大小。
*
* 用法 (实时录音模式):
* snore_detect_t *d = snore_detect_create(mgk_path, NULL, NULL);
* snore_detect_set_listener(d, on_frame, on_onset, on_offset, NULL);
* snore_detect_start(d); // 启动内部模型消费线程
* audio_capture_start(rec, capture_cb, d); // 录音回调里调 snore_detect_feed
* ...
* snore_detect_stop(d); // 排空缓冲, 停止线程
* snore_detect_destroy(d);
*
* 用法 (wav 文件模式):
* snore_detect_t *d = snore_detect_create(mgk_path, NULL, NULL);
* snore_detect_set_listener(d, on_frame, on_onset, on_offset, NULL);
* snore_detect_start(d);
* 循环读文件: snore_detect_feed(d, pcm, n); // 任意数据大小
* snore_detect_stop(d);
* snore_detect_destroy(d);
*/
#ifndef SNORE_DETECT_H
#define SNORE_DETECT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* 识别事件 (报警策略输出, 用于事件结束回调) */
typedef struct {
float start_time; /* 事件开始时间 (秒) */
float end_time; /* 事件结束时间 (秒) */
float confidence; /* 事件置信度 */
float max_confidence; /* 事件内最大帧置信度 */
int frame_count; /* 事件持续帧数 */
} snore_detect_event_t;
/* 帧级回调: 每帧识别结果 (模型线程内执行) */
typedef void (*snore_detect_frame_cb_t)(float snore_prob, float timestamp,
void *user_data);
/* 事件开始回调: 策略判定鼾声事件开始, 只有开始时间 */
typedef void (*snore_detect_onset_cb_t)(float start_time, void *user_data);
/* 事件结束回调: 策略判定鼾声事件结束 (或停止识别时未结束的事件), 完整事件信息 */
typedef void (*snore_detect_offset_cb_t)(const snore_detect_event_t *event,
void *user_data);
typedef struct snore_detect_s snore_detect_t;
/* 创建/销毁; alarm_name/alarm_params 可传 NULL (用默认策略及参数) */
snore_detect_t *snore_detect_create(const char *mgk_path, /* 模型文件路径 (必填) */
const char *alarm_name, /* 报警策略名, NULL=默认 */
const char *alarm_params); /* 策略参数 key=val,key=val, NULL=默认 */
void snore_detect_destroy(snore_detect_t *det);
/* 设置事件回调 (create 后调用, 也可在运行中调整); 不需要的回调传 NULL */
void snore_detect_set_listener(snore_detect_t *det,
snore_detect_frame_cb_t on_frame,
snore_detect_onset_cb_t on_onset,
snore_detect_offset_cb_t on_offset,
void *user_data);
/* 启动/停止识别: 启动内部模型消费线程 / 排空缓冲后停止线程 */
int snore_detect_start(snore_detect_t *det);
void snore_detect_stop(snore_detect_t *det);
int snore_detect_is_running(snore_detect_t *det);
/* 设置事件识别策略 (可在运行中调整) */
int snore_detect_set_alarm(snore_detect_t *det, const char *alarm_name,
const char *alarm_params);
/* 送入 PCM 数据 (16bit 单声道 16kHz), 线程安全, 任意数据大小 */
int snore_detect_feed(snore_detect_t *det, const int16_t *pcm, int num_samples);
#ifdef __cplusplus
}
#endif
#endif /* SNORE_DETECT_H */A minimal WAV-inference demo (excerpt; the full file ships at src/snoreDetect/c/snore_demo.c):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "snore_detect.h"
#define DEFAULT_MGK "snore_detect_v7.mgk" /* 模型文件 */
#define DEFAULT_WAV "test_snore.wav" /* 16kHz 单声道 16bit PCM */
#define FEED_CHUNK 16000 /* 每次送入 1 秒音频 */
/* 帧级回调: 每帧输出鼾声概率 (约 1 秒一帧) */
static void on_frame(float snore_prob, float timestamp, void *user_data)
{
(void)user_data;
printf("%8.2fs snore=%.4f\n", timestamp, snore_prob);
}
/* 事件开始回调: 策略判定鼾声事件开始 */
static void on_onset(float start_time, void *user_data)
{
(void)user_data;
printf("[EVENT] snore start at %.2fs\n", start_time);
}
/* 事件结束回调: 应用层可据此做整夜统计或分级响应 */
static void on_offset(const snore_detect_event_t *ev, void *user_data)
{
(void)user_data;
printf("[EVENT] snore end at %.2fs (dur=%.2fs, conf=%.3f, frames=%d)\n",
ev->end_time, ev->end_time - ev->start_time,
ev->confidence, ev->frame_count);
}
static int read_wav_pcm(const char *path, int16_t **pcm, int *n, int *sr); /* 完整实现见源文件 */
int main(void)
{
snore_detect_t *det;
int16_t *pcm = NULL;
int num_samples = 0, sample_rate = 0;
int pos;
if (read_wav_pcm(DEFAULT_WAV, &pcm, &num_samples, &sample_rate) != 0)
return 1;
/* 1. 创建识别器: .mgk 模型 + 默认报警策略 (NULL) */
det = snore_detect_create(DEFAULT_MGK, NULL, NULL);
if (!det) return 1;
/* 2. 注册回调 (均为可选) */
snore_detect_set_listener(det, on_frame, on_onset, on_offset, NULL);
/* 3. 启动内部模型消费线程 */
snore_detect_start(det);
/* 4. 分块送入 PCM; 实时录音时改在录音回调里 feed */
for (pos = 0; pos < num_samples; pos += FEED_CHUNK) {
int n = num_samples - pos;
if (n > FEED_CHUNK) n = FEED_CHUNK;
snore_detect_feed(det, pcm + pos, n);
}
/* 5. 停止并销毁 */
snore_detect_stop(det);
snore_detect_destroy(det);
free(pcm);
return 0;
}Build and run:
$(CC) snore_demo.c -I. -L. -lsnoredetect -lpthread -lm -o snore_demo
./snore_demoConclusion
The value of snore recognition is turning a night of breathing events into readable health data — and, when needed, into real intervention. If you are evaluating snore detection for a sleep product, an online trial with full technical support is available.
Want to try the detection yourself?