警报声检测:嵌入式离线警报识别 SDK 与分级守护新增
警报声检测的价值(场景、流程)
摄像头能看见烟,却听不见无人在家时正在鸣响的烟感警报。警报声检测把被动记录器变成主动守护者——但"警报"不是一种声音:烟感、CO、汽车警报各有独特的声学模式,识别是哪一种警报,远比识别"有警报"重要。
场景族:家居安全摄像头、老人看护设备、车载与户外监测、商铺安防——共用同一套引擎。
三类警报的特点
下图为一条真实警报声音频——上为波形图、下为梅尔频谱图,可见高强度持续音与规则的谐波条纹(警报身份的典型指纹):

试听素材(真实样本,点击播放):
🔊 真实警报声样本
🔊 另一段警报声样本
烟感警报 — ——单频强脉冲,持续数秒;国际上常见 T3/T4 标准节奏
CO 报警 — ——规律脉冲模式(如四短脉冲 + 停顿的 T4 模式);节奏本身就是身份特征
汽车警报 — ——扫频"wail"或长鸣,频率连续变化,与固定脉冲模式明显不同
这些模式就是关键证据:检测先验证"这是警报模式",再识别具体类别。
识别方法:预处理 → 特征提取 → 算法
引擎走标准管线(自适应降噪、分帧、时频特征),并以"模式"为核心做判定:单频持续音、规律脉冲串、扫频轨迹,是三种可分离的时频轨迹。相对能量判断让检测从安静室内到嘈杂厨房保持稳定。主要混淆源(音乐、铃声、说话声)通过多类别负样本训练处理。
分级通知:规则怎么定
1. 警报声事件——模式验证通过
2. 类别识别——烟感 / CO / 汽车 / 其他
3. 分级通知——烟感或 CO + 无人在家为最高优先级(推送 + 电话外呼);汽车警报为常规提醒
4. 用户处理——查看、联系家人、或标记误报
通知渠道与分级规则可按产品与家庭配置。
老人看护:听见,就是保护
对听力下降或行动不便的老人,警报多响几分钟,风险就多积累几分。能"听见"家中警报的看护设备,补上的正是摄像头覆盖不了的一层。
四类声音最值得关注:
1. 烟感警报——最常见触发是忘记关火;最高优先级
2. CO 报警——无色无味,独居时风险更高;最高优先级
3. 水壶/厨具笛音——及时发现干烧与溢出,避免升级为火情
4. 门铃与电话铃声——行动不便时辅助提醒
响应链:警报声检测 → 类别与置信度 → 场景判断(老人在家?) → 立即通知(推送 + 电话外呼子女) → 无响应升级(邻居、物业、紧急联系人) → 事件记录。升级等待时长与通知对象完整可配。
警报发生集中在烹饪时段——也正是看护最需要留意的窗口。响应指标:推送秒级送达、平均查看分钟级、等待窗口后可配置升级。
定位说明:这是加快人工响应的照护辅助工具,不替代紧急服务。
准确率与性能
家庭场景中烟感警报占比最高;在厨房噪声与街道背景下检出率仍在 93% 以上。
注:文中性能指标基于内部测试环境,实际表现取决于硬件配置与使用场景。
运行平台与硬件要求
从 100MHz 主频级芯片起步;与设备主业务共享 SoC 资源;适合电池供电的看护设备。
C 接口与嵌入式集成
「警报声」识别库提供简洁的流式 C 接口:调用方只需持续送入 16kHz 单声道 PCM,拼帧、Mel 预处理与模型推理全部在内部完成,帧级概率经报警策略聚合成「警报事件」回调输出。
完整接口声明(alarm_detect.h):
/**
* alarm_detect.h — 警报声识别统一接口
*
* 封装 Mel 预处理 + 推理引擎 + 报警策略, 内部模型消费线程处理音频。
* 与录音模块 (audio_capture.h) 相互独立: 调用者自行决定音频来源
* (录音回调 / wav 文件 / 网络流), 通过 alarm_detect_feed 送入, 数据任意大小。
*
* 用法 (实时录音模式):
* alarm_detect_t *d = alarm_detect_create(mgk_path, NULL, NULL);
* alarm_detect_set_listener(d, on_frame, on_onset, on_offset, NULL);
* alarm_detect_start(d); // 启动内部模型消费线程
* audio_capture_start(rec, capture_cb, d); // 录音回调里调 alarm_detect_feed
* ...
* alarm_detect_stop(d); // 排空缓冲, 停止线程
* alarm_detect_destroy(d);
*
* 用法 (wav 文件模式):
* alarm_detect_t *d = alarm_detect_create(mgk_path, NULL, NULL);
* alarm_detect_set_listener(d, on_frame, on_onset, on_offset, NULL);
* alarm_detect_start(d);
* 循环读文件: alarm_detect_feed(d, pcm, n); // 任意数据大小
* alarm_detect_stop(d);
* alarm_detect_destroy(d);
*/
#ifndef ALARM_DETECT_H
#define ALARM_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; /* 事件持续帧数 */
} alarm_detect_event_t;
/* 帧级回调: 每帧识别结果 (模型线程内执行) */
typedef void (*alarm_detect_frame_cb_t)(float alarm_prob, float timestamp,
void *user_data);
/* 事件开始回调: 策略判定警报事件开始, 只有开始时间 */
typedef void (*alarm_detect_onset_cb_t)(float start_time, void *user_data);
/* 事件结束回调: 策略判定警报事件结束 (或停止识别时未结束的事件), 完整事件信息 */
typedef void (*alarm_detect_offset_cb_t)(const alarm_detect_event_t *event,
void *user_data);
typedef struct alarm_detect_s alarm_detect_t;
/* 创建/销毁; alarm_name/alarm_params 可传 NULL (用默认策略及参数) */
alarm_detect_t *alarm_detect_create(const char *mgk_path, /* 模型文件路径 (必填) */
const char *alarm_name, /* 报警策略名, NULL=默认 */
const char *alarm_params); /* 策略参数 key=val,key=val, NULL=默认 */
void alarm_detect_destroy(alarm_detect_t *det);
/* 设置事件回调 (create 后调用, 也可在运行中调整); 不需要的回调传 NULL */
void alarm_detect_set_listener(alarm_detect_t *det,
alarm_detect_frame_cb_t on_frame,
alarm_detect_onset_cb_t on_onset,
alarm_detect_offset_cb_t on_offset,
void *user_data);
/* 启动/停止识别: 启动内部模型消费线程 / 排空缓冲后停止线程 */
int alarm_detect_start(alarm_detect_t *det);
void alarm_detect_stop(alarm_detect_t *det);
int alarm_detect_is_running(alarm_detect_t *det);
/* 设置事件识别策略 (可在运行中调整) */
int alarm_detect_set_alarm(alarm_detect_t *det, const char *alarm_name,
const char *alarm_params);
/* 送入 PCM 数据 (16bit 单声道 16kHz), 线程安全, 任意数据大小 */
int alarm_detect_feed(alarm_detect_t *det, const int16_t *pcm, int num_samples);
#ifdef __cplusplus
}
#endif
#endif /* ALARM_DETECT_H */
最简 wav 推理示例(节选,完整文件位于 SDK 的 src/alarmDetect/c/alarm_demo.c):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "alarm_detect.h"
#define DEFAULT_MGK "alarm_detect_v7.mgk" /* 模型文件 */
#define DEFAULT_WAV "test_alarm.wav" /* 16kHz 单声道 16bit PCM */
#define FEED_CHUNK 16000 /* 每次送入 1 秒音频 */
/* 帧级回调: 每帧输出警报声概率 (约 1 秒一帧) */
static void on_frame(float alarm_prob, float timestamp, void *user_data)
{
(void)user_data;
printf("%8.2fs alarm=%.4f\n", timestamp, alarm_prob);
}
/* 事件开始回调: 策略判定警报事件开始 */
static void on_onset(float start_time, void *user_data)
{
(void)user_data;
printf("[EVENT] alarm start at %.2fs\n", start_time);
}
/* 事件结束回调: 应用层可据此做后续统计或分级响应 */
static void on_offset(const alarm_detect_event_t *ev, void *user_data)
{
(void)user_data;
printf("[EVENT] alarm 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)
{
alarm_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. 创建识别器: 模型文件 + 默认报警策略 (NULL) */
det = alarm_detect_create(DEFAULT_MGK, NULL, NULL);
if (!det) return 1;
/* 2. 注册回调 (均为可选) */
alarm_detect_set_listener(det, on_frame, on_onset, on_offset, NULL);
/* 3. 启动内部模型消费线程 */
alarm_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;
alarm_detect_feed(det, pcm + pos, n);
}
/* 5. 停止并销毁 */
alarm_detect_stop(det);
alarm_detect_destroy(det);
free(pcm);
return 0;
}
编译与运行(示例):
$(CC) alarm_demo.c -I. -L. -lalarmdetect -lpthread -lm -o alarm_demo
./alarm_demo结语
听懂警报,意味着听懂是哪一种警报、以及它应当触发什么。我们提供在线试用与完整的技术支持。