← Back to Blog

Embedded Gunshot Detection: Offline Gunshot Recognition SDK for Public SafetyNEW

The Value of Gunshot Detection: Scenarios and Workflow

In public safety, every second between an incident and a response matters. Gunshots carry a unique acoustic fingerprint — and unlike cameras, microphones work in darkness, around corners, and across open spaces. From a single campus to a whole city, acoustic sensing adds a continuous awareness layer where eyes are sparse.

City street sensing scene
Sensing nodes, event location estimate, and command linkage

The Signature of a Gunshot

Gunshot signature vs similar blasts
Instant transient + echo tail vs fireworks and backfires

Below is a real gunshot recording (including multiple shots) — waveform (top) and Mel spectrogram (bottom). The millisecond-scale spikes and broadband vertical streaks are clearly visible:

Real gunshot sample: waveform and spectrum
Real gunshot sample: waveform (top) + Mel spectrogram (bottom)

Audio samples (real recordings — press play):

🔊 Gunshot (real sample)

🔊 Another gunshot recording

Millisecond-scale onset — — the leading edge of the shock is virtually instant; energetic analysis of the onset is the first piece of evidence

Echo tail — — the blast reflects off buildings and terrain; the decaying echo pattern is a second, environment-based signature

Discrimination from lookalikes — — fireworks rise more slowly with whistle-like tails; car backfires form clean pulse trains without complex echoes

An industry honesty note: firecrackers are acoustically close to gunshots — a well-known hard problem. Multi-microphone cooperation and event aggregation across nodes are the practical ways to raise reliability.

How Recognition Works: Preprocessing → Features → Algorithms

Detection and linkage flow
Transient verification, optional localization, and platform linkage

1. Shock event — onset-triggered detection

2. Feature verification — transient fingerprint plus echo structure

3. Multi-microphone localization (optional) — arrival-time differences across nodes estimate the event location

4. Push and platform linkage — command center pop-ups, map pins, camera retrieval, ticket creation

All decisions run on the edge device; audio stays on-device by default.

City-Scale Deployment

Deploying across a city is a system engineering problem — the six-step path:

Deployment flow
Site survey to daily operations

1. Site survey — priority areas and ambient noise profiling

2. Device selection and installation — height, orientation, power

3. Acoustic calibration — per-site baseline and sensitivity

4. Networking and commissioning — private network or cellular backhaul

5. Platform integration — event APIs, map, ticketing

6. Operations — uptime monitoring, false-alarm review, site refinement

Start with a pilot cluster, validate, then scale.

Four-layer architecture
Edge, network, platform, application

Edge sensing layer — — on-device gunshot decision and uplink policy

Network layer — — wired / 4G / 5G backhaul, cache-and-forward on outage

Platform layer (private deployment capable) — — event aggregation, multi-site correlation, storage, open interfaces

Application layer — — command platform, guard desks, ticketing, dashboards

Site layout scene
Intersections, schools, commercial districts and the platform dashboard

Sites cluster around intersections, schools and commercial districts — typical installation 4–6 m height, away from strong noise sources, spacing planned per coverage tier.

Deployment metrics and phases
Uptime, delivery latency, and pilot-to-city phases (illustrative)

Phase P1 pilot (2–4 weeks) → P2 expansion (2–3 months) → P3 city-wide and long-term operations. Node uptime target ≥99%; event-to-platform delivery ≤5 s.

Campus and Commercial District Solutions

Campuses and commercial districts share a structural gap: vast open areas cannot be permanently watched by human eyes.

Campus acoustic coverage
Perimeter, playground and key buildings with a guard desk
Guard response flow
Discover, verify, respond, close the loop

1. Acoustic event — edge decision with location pin

2. Guard desk pop-up — time, location, clip reference

3. Visual verification — nearest camera auto-retrieved

4. Plan activation — patrol dispatch, broadcast, alarm linkage

5. On-site handling — status reported back

6. Record and review — archive for drills

"Verify before dispatch" keeps guard resources from chasing false alarms.

Deployment points by scenario
Gates, playgrounds, perimeter walls, key buildings
Discovery time comparison
Manual patrol vs acoustic sensing (illustrative)

Manual discovery takes minutes to tens of minutes; acoustic sensing delivers events within seconds — plus traceable records for drills.

Accuracy and Performance

Detection key metrics
Coverage tiers and response latency (illustrative)
Item
Spec
Detection rate
95%+ (typical quiet conditions, illustrative)
False alarm strategy
Multi-mic cooperation + event aggregation
Model size
0.2–1 MB (INT8), edge inference
Sample rate
16 kHz
Platforms
ARM Linux / MIPS / x86_64; SVP / Magik pre-adapted
Deployment
Edge devices, private network, optional clip uplink

Platform and Hardware Requirements

Sensing nodes run the model on-device within 0.2–1 MB (INT8); nodes are typically pole-mounted with PoE or solar/battery power; networking over private fiber/LTE/5G.

C API and Embedded Integration

The gunshot 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 event callbacks.

Full interface declaration (gunshot_detect.h):

gunshot_detect.hc
/**
 * gunshot_detect.h — 枪声识别统一接口
 *
 * 封装 Mel 预处理 + 推理引擎 + 报警策略, 内部模型消费线程处理音频。
 * 与录音模块 (audio_capture.h) 相互独立: 调用者自行决定音频来源
 * (录音回调 / wav 文件 / 网络流), 通过 gunshot_detect_feed 送入, 数据任意大小。
 *
 * 用法 (实时录音模式):
 *   gunshot_detect_t *d = gunshot_detect_create(mgk_path, NULL, NULL);
 *   gunshot_detect_set_listener(d, on_frame, on_onset, on_offset, NULL);
 *   gunshot_detect_start(d);                          // 启动内部模型消费线程
 *   audio_capture_start(rec, capture_cb, d);        // 录音回调里调 gunshot_detect_feed
 *   ...
 *   gunshot_detect_stop(d);                           // 排空缓冲, 停止线程
 *   gunshot_detect_destroy(d);
 *
 * 用法 (wav 文件模式):
 *   gunshot_detect_t *d = gunshot_detect_create(mgk_path, NULL, NULL);
 *   gunshot_detect_set_listener(d, on_frame, on_onset, on_offset, NULL);
 *   gunshot_detect_start(d);
 *   循环读文件: gunshot_detect_feed(d, pcm, n);       // 任意数据大小
 *   gunshot_detect_stop(d);
 *   gunshot_detect_destroy(d);
 */

#ifndef GUNSHOT_DETECT_H
#define GUNSHOT_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;      /* 事件持续帧数 */
} gunshot_detect_event_t;

/* 帧级回调: 每帧识别结果 (模型线程内执行) */
typedef void (*gunshot_detect_frame_cb_t)(float gunshot_prob, float timestamp,
                                        void *user_data);

/* 事件开始回调: 策略判定枪声事件开始, 只有开始时间 */
typedef void (*gunshot_detect_onset_cb_t)(float start_time, void *user_data);

/* 事件结束回调: 策略判定枪声事件结束 (或停止识别时未结束的事件), 完整事件信息 */
typedef void (*gunshot_detect_offset_cb_t)(const gunshot_detect_event_t *event,
                                         void *user_data);

typedef struct gunshot_detect_s gunshot_detect_t;

/* 创建/销毁; alarm_name/alarm_params 可传 NULL (用默认策略及参数) */
gunshot_detect_t *gunshot_detect_create(const char *mgk_path,      /* 模型文件路径 (必填) */
                                    const char *alarm_name,    /* 报警策略名, NULL=默认 */
                                    const char *alarm_params); /* 策略参数 key=val,key=val, NULL=默认 */
void gunshot_detect_destroy(gunshot_detect_t *det);

/* 设置事件回调 (create 后调用, 也可在运行中调整); 不需要的回调传 NULL */
void gunshot_detect_set_listener(gunshot_detect_t *det,
                               gunshot_detect_frame_cb_t  on_frame,
                               gunshot_detect_onset_cb_t  on_onset,
                               gunshot_detect_offset_cb_t on_offset,
                               void *user_data);

/* 启动/停止识别: 启动内部模型消费线程 / 排空缓冲后停止线程 */
int  gunshot_detect_start(gunshot_detect_t *det);
void gunshot_detect_stop(gunshot_detect_t *det);
int  gunshot_detect_is_running(gunshot_detect_t *det);

/* 设置事件识别策略 (可在运行中调整) */
int gunshot_detect_set_alarm(gunshot_detect_t *det, const char *alarm_name,
                           const char *alarm_params);

/* 送入 PCM 数据 (16bit 单声道 16kHz), 线程安全, 任意数据大小 */
int gunshot_detect_feed(gunshot_detect_t *det, const int16_t *pcm, int num_samples);

#ifdef __cplusplus
}
#endif

#endif /* GUNSHOT_DETECT_H */

A minimal WAV-inference demo (excerpt; the full file ships at src/gunshotDetect/c/gunshot_demo.c):

gunshot_demo.cc
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "gunshot_detect.h"

#define DEFAULT_MGK  "gunshot_detect_v7.mgk"  /* 模型文件 */
#define DEFAULT_WAV  "test_gunshot.wav"       /* 16kHz 单声道 16bit PCM */
#define FEED_CHUNK   16000                  /* 每次送入 1 秒音频 */

/* 帧级回调: 每帧输出枪声概率 (约 1 秒一帧) */
static void on_frame(float gunshot_prob, float timestamp, void *user_data)
{
    (void)user_data;
    printf("%8.2fs  gunshot=%.4f\n", timestamp, gunshot_prob);
}

/* 事件开始回调: 策略判定枪声事件开始 */
static void on_onset(float start_time, void *user_data)
{
    (void)user_data;
    printf("[EVENT] gunshot start at %.2fs\n", start_time);
}

/* 事件结束回调: 应用层可据此做后续统计或分级响应 */
static void on_offset(const gunshot_detect_event_t *ev, void *user_data)
{
    (void)user_data;
    printf("[EVENT] gunshot 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)
{
    gunshot_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 = gunshot_detect_create(DEFAULT_MGK, NULL, NULL);
    if (!det) return 1;

    /* 2. 注册回调 (均为可选) */
    gunshot_detect_set_listener(det, on_frame, on_onset, on_offset, NULL);

    /* 3. 启动内部模型消费线程 */
    gunshot_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;
        gunshot_detect_feed(det, pcm + pos, n);
    }

    /* 5. 停止并销毁 */
    gunshot_detect_stop(det);
    gunshot_detect_destroy(det);
    free(pcm);
    return 0;
}

Build and run:

buildbash
$(CC) gunshot_demo.c -I. -L. -lgunshotdetect -lpthread -lm -o gunshot_demo
./gunshot_demo

Conclusion

Gunshot detection is transient recognition at its hardest — and its most valuable. If you are building public-safety, campus or city sensing solutions, an online trial with deployment methodology support is available.