嵌入式(audio/ECNR/BT/Wi-Fi,高通 8295 车舱)转 AI 的实践记录。把传统 DSP 链路里的 NS 换成神经网络(RNNoise),AEC/AGC 仍用 WebRTC,各取所长,最终封装成单库 SDK。
- NS 该用神经网络:RNNoise NS 去噪(BAK +2.2)、少削语音,全面优于 WebRTC 自带 NS。
- 最佳链路 = WebRTC AEC + RNNoise NS + WebRTC AGC(各取所长,业界趋势)。
- 顺序不能乱:AEC → NS → AGC(NS 在 AEC 前会破坏回声路径估计)。
ecnr/
├── sdk/ # ★ 单库 SDK:一个头 + 一个自包含 .so + 配置
│ ├── tokei_audio.h # C API(extern "C")
│ ├── tokei_audio.cpp # 实现:两个 APM(AEC 级/AGC 级)夹 RNNoise
│ ├── demo.c # 命令行 demo(wav 进 wav 出)
│ ├── tokei_audio.conf # key=value 配置(运行时读)
│ ├── Makefile # 全静态链接出 libtokei_audio
│ └── README.md
├── versions/ # 实验版本记录
│ ├── v1-rnnoise-ns/ # RNNoise 单独 NS
│ ├── v2-webrtc-aec-12s/ # WebRTC 全链路 AEC→NS→AGC
│ ├── v3-ns-comparison/ # ★NS 对比:WebRTC vs RNNoise(DNSMOS)
│ ├── score.py # 客观评测(DNSMOS+AECMOS+ERLE+PESQ/STOI)
│ └── README.md
├── SOLUTION.md # 完整代码方案(架构/代码位置/产物/移植)
├── rnnoise/ # submodule:https://github.com/xiph/rnnoise
├── webrtc-audio-processing/# submodule:freedesktop v2.1
├── LICENSE # MIT(自有代码)+ 第三方许可说明
└── .gitignore
git clone --recursive <本仓> ecnr && cd ecnr
# 1) 编上游依赖(一次性)
cd rnnoise && ./autogen.sh && ./configure --enable-examples && make -j4 && ./download_model.sh && cd ..
cd webrtc-audio-processing && meson setup builddir_static --default-library=static && ninja -C builddir_static && cd ..
# 2) 编 SDK
cd sdk && make # → libtokei_audio.dylib(Mac)/.so(Linux)
# 3) 跑 demo
DYLD_LIBRARY_PATH=. ./tokei_demo tokei_audio.conf far.wav mic.wav out.wav
make UNAME_S=Linux出.so(8295/ARM);依赖路径可用WEBRTC_ROOT=... RNNOISE_ROOT=...覆盖。
TokeiAudioConfig cfg = tokei_audio_default_config();
tokei_audio_load_config("tokei_audio.conf", &cfg); // 可选
TokeiAudio *ta = tokei_audio_create(&cfg);
tokei_audio_process(ta, far/*扬声器参考*/, mic, out, 480); // 每帧 10ms
tokei_audio_destroy(ta);整链 48k/mono/int16,WebRTC APM 原生 48k 故无中间重采样。详见 sdk/README.md。
pip install numpy scipy librosa soundfile speechmos pesq pystoi onnxruntime
python versions/score.py mic.wav out.wav [far_ref.wav] [clean_near.wav]DNSMOS 免参考(直接评)、AECMOS 需扬声器参考、PESQ/STOI 需干净近端。
真实车舱录音(含 mic/ref 及派生 wav)不入本仓——.gitignore 已忽略
versions/*-real*/*.wav。如需用真实 8295 数据验证,请用自己有权限的录音,
按 16k/12ch pcm(ch0-3=mic、ch4-11=ref)格式解交错后跑 score.py,产物留在本地即可。
- AEC3 双讲在合成/冷启动数据上可能过抑近端;真实持续运行 + 正确
render_delay_ms显著缓解。 - AEC 客观评测(ERLE/PESQ/STOI)在合成数据上不可信,最终以真实不削波录音为准。
- RNNoise 权重 78MB(
rnnoise_data.c,生成不入 git);8295 上可量化压缩。