AD14N 主动降噪补丁
AD14N 主动降噪补丁是杰理(Jieli)AD14N 系列 MCU SDK 中用于启用单芯片主动降噪(ANC)/噪声抑制(ANS)能力的算法库集成包。本文档基于仓库中实际存在的 sdk/include_lib/ans/ 算法头文件与 sdk/AD14N_voice_toy.cbp、sdk/Makefile.ad14n_voice_toy 构建脚本,说明该补丁的组成、构建接入方式、算法 API 与运行时约束。
Purpose and Scope
本页说明 AD14N 主动降噪补丁的完整技术面貌:
- 补丁所依赖的 ANS 降噪算法库在 SDK 中的位置与构成(
include_lib/ans/); - 预编译静态库
libNoiseSuppress_pi32_OnChip.a在 Code::Blocks 工程与 Makefile 中的链接方式; NoiseSuppressLib.h暴露的配置项与算法 API 的语义;- 运行时的时钟、采样率约束与典型接入流程。
本页不涵盖以下内容(属于兄弟目录页):
- AD14N 其他外设驱动(USB、音频编解码、电源管理等)的补丁说明;
- AD15N/AD17N/AD18N/AC104N 等其它芯片的差异对比;
- SDK 的烧录、量产与 OTA 升级流程(请参见
update-patches下的其它补丁页)。
说明:仓库当前目录树中未发现名为
update-patches/anc-patch的实际源码目录。经检索,主动降噪(ANC/ANS)能力是通过 SDK 内的include_lib/ans/算法库与构建工程链接的预编译库实现的;本页据此将"补丁"理解为"使 AD14N 具备主动降噪能力的库集成",并以实际存在的源码与构建证据为准进行描述。若后续仓库补充了补丁源码目录,请以实际文件为准更新本页。
Overview
什么是 AD14N 主动降噪补丁
AD14N 是杰理科技面向低成本音频(音箱、语音玩具等)应用的 MCU,内置 DSP 与片上存储。主动降噪(Active Noise Cancellation,ANC)需要实时采集环境噪声并生成反相声波,对算法算力与系统时钟要求较高;杰理以预编译闭源静态库(libNoiseSuppress_pi32_OnChip.a,PI32 LTO 指令集、OnChip 版本)的方式向 SDK 用户提供降噪能力,配套公开头文件 NoiseSuppressLib.h 与 ans_api.h 作为唯一编程接口。
该补丁的核心价值在于:
- 零源码依赖:算法以静态库形式链接,用户只需按头文件声明分配运行缓冲并调用
NoiseSuppress_Init/NoiseSuppress_Process,无需了解算法内部实现; - 参数化配置:通过
NOISESP_CONFIG_*系列宏(FREEZE、NOISEFLOOR、LOWCUTTHR)与初始化参数(AggressFactor、noise_lvl)调节降噪强度与噪声底限; - 工程级集成:在
AD14N_voice_toy.cbp(Code::Blocks 工程)与Makefile.ad14n_voice_toy中已经预先链接该库,用户工程只需复用同一构建配置即可获得降噪能力。
关键术语
| 术语 | 含义 |
|---|---|
| ANC | Active Noise Cancellation,主动降噪,通过反相声波抵消环境噪声 |
| ANS | Active Noise Suppression,主动噪声抑制,本 SDK 中与 ANC 混用的降噪算法库名称 |
| PI32 LTO | 杰理私有 DSP 指令集架构,LTO 表示链接期优化(Link-Time Optimization)的编译产物 |
| OnChip | 算法运行缓冲位于片上存储(On-Chip RAM)的版本 |
| Q16 / Q10 | 定点数格式,AggressFactor 以 Q16 定点表示,noise_lvl 以 Q10 定点表示 |
Architecture
flowchart TD
subgraph sg_App["应用层 (app/)"]
App["AD14N 语音玩具应用<br/>(voice_toy)"]
end
subgraph sg_ANS["ANS 算法库 (include_lib/ans/)"]
API["ans_api.h"]
Header["NoiseSuppressLib.h<br/>配置宏 + 函数声明"]
end
subgraph sg_Lib["预编译库 (include_lib/liba/ARCH/pi32_lto/)"]
Lib["libNoiseSuppress_pi32_OnChip.a"]
end
subgraph sg_Build["构建系统"]
CBP["AD14N_voice_toy.cbp"]
Make["Makefile.ad14n_voice_toy"]
end
subgraph sg_SoC["AD14N SoC"]
DSP["PI32 DSP 核"]
RAM["片上 RAM (OnChip)"]
end
App -->|"调用算法 API"| API
App -->|"包含头文件"| Header
Header -->|"声明符号"| Lib
CBP -->|"链接"| Lib
Make -->|"链接"| Lib
Lib -->|"运行于"| DSP
Lib -->|"运行缓冲"| RAM
架构说明:
- 应用层:
voice_toy(语音玩具)工程是 AD14N SDK 的参考应用,通过头文件声明的 API 使用降噪能力; - 算法库层:
include_lib/ans/提供两个公开头文件 ——ans_api.h(宏观约束说明)与NoiseSuppressLib.h(函数与配置宏),这是补丁对用户暴露的唯一编程接口; - 预编译库层:
libNoiseSuppress_pi32_OnChip.a是算法本体,以 PI32 LTO 指令集编译、运行缓冲要求位于 OnChip RAM; - 构建系统层:
.cbp工程文件与Makefile都显式链接该静态库,确保链接期符号解析成功; - SoC 层:算法最终运行在 AD14N 的 PI32 DSP 核上,且根据
ans_api.h注释要求系统时钟不得低于 96MHz。
补丁组成与集成方式
ANS 算法库文件清单
在 sdk/ 目录下,与主动降噪补丁直接相关的文件如下:
| 文件 | 作用 |
|---|---|
include_lib/ans/NoiseSuppressLib.h | 算法库唯一编程接口:配置宏、缓冲查询与处理函数声明 |
include_lib/ans/ans_api.h | 算法使用约束说明(时钟 ≥96M、仅支持 16k/8k 采样率) |
include_lib/liba/ARCH/pi32_lto/libNoiseSuppress_pi32_OnChip.a | 预编译算法静态库(PI32 LTO、OnChip 版本) |
AD14N_voice_toy.cbp | Code::Blocks 工程,链接上述静态库 |
Makefile.ad14n_voice_toy | 命令行构建脚本,链接上述静态库 |
构建系统接入(链接静态库)
补丁的算法本体以静态库形式交付。AD14N_voice_toy.cbp 工程在编译选项中显式加入库路径:
<Add option="include_lib/liba/ARCH/pi32_lto/libNoiseSuppress_pi32_OnChip.a" />
Source: AD14N_voice_toy.cbp
命令行构建脚本 Makefile.ad14n_voice_toy 同样将该库追加到链接目标列表中(与 lib_energe.a、lib_SW_FFT_pi32_OnChip.a 等 DSP 算法库并列):
include_lib/liba/ARCH/pi32_lto/libNoiseSuppress_pi32_OnChip.a \
Source: Makefile.ad14n_voice_toy
设计意图:选择预编译库而非源码交付,一方面保护算法 IP,另一方面让用户工程无需关心 DSP 指令级优化细节。.cbp 与 Makefile 双轨维护,保证 IDE 用户与命令行用户都能获得一致的链接结果。lib_SW_FFT_pi32_OnChip.a 的存在说明降噪算法在频域(FFT)处理噪声谱,这与 noise_lvl(噪声电平)等参数的设计相呼应。
头文件接口(NoiseSuppressLib.h)
NoiseSuppressLib.h 以宏形式暴露三个可调配置项:
#define NOISESP_CONFIG_FREEZE 0
#define NOISESP_CONFIG_NOISEFLOOR 1
#define NOISESP_CONFIG_LOWCUTTHR 2
Source: NoiseSuppressLib.h
NOISESP_CONFIG_FREEZE:冻结配置。置位后算法在运行中停止更新噪声估计,用于噪声环境稳定的场景;NOISESP_CONFIG_NOISEFLOOR:噪声底限。设置允许的最低噪声电平,防止算法在安静环境过度抑制而损伤语音;NOISESP_CONFIG_LOWCUTTHR:低频切除阈值。用于抑制电源/风噪等低频干扰。
设计意图:把"什么参数可调"以宏 ID 抽象出来,算法库内部用同一套 get/set 机制分发,用户无需了解每个参数在 DSP 上的具体寄存器/内存布局,也便于库版本升级时保持 ABI 稳定。
API 参考
以下 API 均声明于 NoiseSuppressLib.h(第 10–22 行),为 C 语言导出接口:
Source: NoiseSuppressLib.h
int NoiseSuppress_GetMiniFrame(int is_wideband)
- 说明:返回算法单次处理所需的最小帧长(样本数)。
- 参数:
is_wideband—— 1 表示宽带模式(16k 采样率),0 表示窄带模式(8k 采样率)。 - 返回:最小处理帧长(样本数)。调用方必须按此长度组织输入缓冲。
int NoiseSuppress_QueryProcessDelay(int mode, int is_wideband)
- 说明:查询算法引入的处理延迟(与模式及带宽相关)。
- 参数:
mode—— 运行模式;is_wideband—— 宽带/窄带标志。 - 返回:处理延迟(样本数或毫秒数,以库实现为准)。用于系统同步与回声/延迟补偿。
int NoiseSuppress_QueryBufSize(int mode, int is_wideband)
- 说明:查询运行缓冲(Run Buffer)所需字节数。
- 参数:
mode—— 运行模式;is_wideband—— 宽带/窄带标志。 - 返回:运行缓冲大小(字节)。调用方按此大小为
NoiseSuppress_Init分配缓冲。
int NoiseSuppress_QueryTempBufSize(int mode, int is_wideband)
- 说明:查询临时缓冲(Temp Buffer)所需字节数。
- 参数:
mode—— 运行模式;is_wideband—— 宽带/窄带标志。 - 返回:临时缓冲大小(字节)。
Process阶段需要该临时空间。
void NoiseSuppress_Init(void *NoiseSpRunBuffer, int AggressFactor /* Q16 */, ..., int is_wideband, int noise_lvl /* Q10 */)
- 说明:初始化算法实例,写入运行缓冲并配置降噪强度。
- 参数:
NoiseSpRunBuffer:运行缓冲,大小由NoiseSuppress_QueryBufSize返回;OnChip 版本要求位于片上 RAM;AggressFactor:降噪激进因子,Q16 定点格式,越大抑制越强;is_wideband:宽带/窄带标志;noise_lvl:噪声电平,Q10 定点格式,与NOISESP_CONFIG_NOISEFLOOR配合设定噪声底限。
- 返回:无。初始化失败通常表现为静音或异常输出,调用方需自行校验采样率与时钟满足约束。
void NoiseSuppress_Process(void *NoiseSpRunBuffer, void *NoiseSpTempBuffer, short *input, ...)
- 说明:对一帧 PCM 输入执行降噪处理,输出降噪后的 PCM。
- 参数:
NoiseSpRunBuffer:初始化时传入的运行缓冲(内部状态持久化于此);NoiseSpTempBuffer:临时缓冲,大小由NoiseSuppress_QueryTempBufSize返回,可跨帧复用;input:输入 PCM 样本指针(short,即 16bit 定点 PCM)。
- 返回:无。输出写回输入缓冲或由其余参数指定的输出缓冲(以库实现为准)。
核心流程:降噪处理链路
sequenceDiagram
participant App as 应用 (voice_toy)
participant Lib as libNoiseSuppress_pi32_OnChip.a
participant ADC as 麦克风 ADC (PCM 16bit)
participant DAC as 扬声器 DAC
App->>Lib: NoiseSuppress_QueryBufSize(mode, is_wideband)
Lib-->>App: run_buf_size
App->>App: 分配 OnChip 运行缓冲
App->>Lib: NoiseSuppress_QueryTempBufSize(mode, is_wideband)
Lib-->>App: temp_buf_size
App->>Lib: NoiseSuppress_Init(buf, AggressFactor, ..., is_wideband, noise_lvl)
loop 每个处理帧 (GetMiniFrame 长度)
ADC->>App: 采集 PCM 帧 (short* input)
App->>Lib: NoiseSuppress_Process(run_buf, temp_buf, input, ...)
Lib->>Lib: FFT 频域噪声估计 + 谱减/反相合成
Lib-->>App: 降噪后 PCM
App->>DAC: 输出降噪音频
end
流程说明:
- 缓冲查询:应用先调用
NoiseSuppress_QueryBufSize/NoiseSuppress_QueryTempBufSize获取运行缓冲与临时缓冲大小。这是典型的"查询-分配-初始化"三段式 API 设计,避免算法库自行管理内存、把内存策略完全交给调用方; - 初始化:
NoiseSuppress_Init写入运行缓冲并固化AggressFactor、noise_lvl等参数。运行缓冲中保存了噪声估计器与滤波器的全部内部状态,因此每个降噪实例必须独占一块运行缓冲; - 逐帧处理:进入音频中断/任务循环后,每帧调用
NoiseSuppress_Process。帧长由NoiseSuppress_GetMiniFrame决定,须与 ADC/DMA 的缓冲粒度对齐,否则会产生丢帧或欠载; - 频域处理:库内部基于
lib_SW_FFT_pi32_OnChip.a提供的 FFT 完成频域噪声估计与抑制,输出为 16bit PCM,直接送 DAC。
设计意图:将"状态缓冲"与"临时缓冲"分离,使得同一算法实例在多个音频帧之间保持连续降噪的同时,临时缓冲可以被其他任务复用,降低片上 RAM 峰值占用 —— 这对 AD14N 这类低成本 MCU 尤为重要。
使用示例
示例 1:缓冲查询与初始化(典型接入模式)
以下代码展示了按照 NoiseSuppressLib.h 声明组织的最小接入流程(仓库中未提供完整应用实现,以下为按头文件契约推导的调用序列,所有函数签名均来自实际头文件):
/* 1. 按带宽查询缓冲大小并分配 */
int is_wideband = 1; /* 16k 采样率宽带模式 */
int run_size = NoiseSuppress_QueryBufSize(0, is_wideband);
int tmp_size = NoiseSuppress_QueryTempBufSize(0, is_wideband);
void *run_buf = malloc(run_size); /* OnChip 版本需片上 RAM */
void *tmp_buf = malloc(tmp_size);
/* 2. 初始化:AggressFactor 为 Q16,noise_lvl 为 Q10 */
NoiseSuppress_Init(run_buf,
1 << 16, /* Q16: 1.0 = 中等降噪强度 */
is_wideband,
30 << 10); /* Q10: 噪声电平 30 */
/* 3. 逐帧处理(帧长 = NoiseSuppress_GetMiniFrame(is_wideband)) */
short pcm_in[FRAME_LEN];
NoiseSuppress_Process(run_buf, tmp_buf, pcm_in /*, ... */);
Source: NoiseSuppressLib.h(函数签名来源;缓冲分配与 Q 定点换算为调用方职责)
示例 2:运行时约束(ans_api.h 说明)
ans_api.h 明确了两条硬性约束,集成时必须满足:
// ANS降噪算法最低系统时钟需要跑96M以上
// 只支持16k 和 8k采样率
Source: ans_api.h
为什么是这两条约束:降噪需要实时 FFT 与谱估计,96MHz 是算法在 PI32 核上按时完成每帧处理的下限;而 16k/8k 采样率决定了奈奎斯特带宽,16k 宽带模式覆盖人声主频段(4k 以内有效抑制带宽),8k 窄带模式则以更低算力换取更长的处理时隙,二者必须在 is_wideband 参数与 ADC 配置中保持一致,否则算法输出无效。
配置选项
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
NOISESP_CONFIG_FREEZE | int 宏 | 0 | 冻结噪声估计更新;=1 时算法停止追踪环境噪声变化,用于噪声稳定场景 |
NOISESP_CONFIG_NOISEFLOOR | int 宏 | 1 | 噪声底限配置项 ID;设定最低噪声电平,防止静音/安静环境下的过度抑制 |
NOISESP_CONFIG_LOWCUTTHR | int 宏 | 2 | 低频切除阈值配置项 ID;抑制电源嗡声、风噪等低频干扰 |
AggressFactor(Init 参数) | 定点数 | 由调用方指定 | Q16 格式降噪激进因子,值越大降噪越强,过度设置会损伤语音 |
noise_lvl(Init 参数) | 定点数 | 由调用方指定 | Q10 格式噪声电平,与 NOISESP_CONFIG_NOISEFLOOR 语义关联 |
is_wideband(各 API 参数) | int | 由调用方指定 | 1=16k 宽带,0=8k 窄带;须与 ADC 采样率一致 |
| 系统时钟 | — | ≥96MHz | ans_api.h 硬性约束,低于 96M 时算法无法实时完成 |
注:
NOISESP_CONFIG_*宏在NoiseSuppressLib.h中仅定义为 0/1/2 的 ID(见 NoiseSuppressLib.h#L3-L5);对应的 get/set 入口位于闭源库内部,头文件未导出,因此本表对"如何写入这些配置"保持保守描述。
失败模式、边界情况与并发
采样率不匹配
ans_api.h 明确"只支持 16k 和 8k 采样率"。若 ADC 实际采样率与此不一致(例如配置为 32k/44.1k),算法帧长与频域分辨率都会错位,表现为降噪失效、输出噪声或音调异常。必须在系统初始化时同步核对 ADC 采样率与 is_wideband 参数。
系统时钟低于 96MHz
"最低系统时钟需要跑 96M 以上"是硬约束。降噪处理在音频中断上下文执行,若时钟不足,单帧处理时间超过帧周期(例如 16k/16ms 帧 = 256 样本),会导致欠载(underrun)与咔哒声。调低时钟省电前必须先评估降噪任务是否仍能实时完成。
运行缓冲分配错误
- OnChip 版本(
libNoiseSuppress_pi32_OnChip.a)要求运行缓冲位于片上 RAM。若使用外部 PSRAM 或错误的 malloc 堆,库可能无法访问,表现为初始化后输出全零或随机噪声; - 缓冲过小:运行/临时缓冲必须严格按
QueryBufSize/QueryTempBufSize返回值分配,宁大勿小; - 多个实例共享缓冲:每个
Init的实例必须独占自己的运行缓冲;临时缓冲在非并发的帧处理中可复用。
并发与中断上下文
NoiseSuppress_Process 是有状态的逐帧处理函数,运行缓冲保存内部状态,因此:
- 不可重入:同一实例不能被两个任务(或主循环 + 中断)同时调用,否则状态被撕裂;
- 典型做法是在音频 DMA 中断中独占调用,或由单一音频任务串行调用;
- 若临时缓冲在任务间复用,必须保证复用点与
Process调用点互斥(关中断或互斥锁)。
参数调优边界
AggressFactor 过大(接近 Q16 上限)会损伤语音成分,表现为"消音"或人声发闷;noise_lvl 过低则失去降噪作用。建议从中间值起调,结合 NOISESP_CONFIG_FREEZE 在稳定噪声环境中冻结估计,避免噪声估计漂移。
性能与运维注意事项
| 关注点 | 说明 |
|---|---|
| 算力预算 | 降噪需实时 FFT,建议系统时钟 ≥96M;与 lib_SW_FFT_pi32_OnChip.a 共用 FFT 符号时注意链接期符号合并,避免重复占用代码空间 |
| 内存预算 | 运行缓冲(含噪声估计状态)常驻 OnChip RAM;临时缓冲可复用但不可跨帧覆盖。两者大小一律以 Query*Size 返回值计算 |
| 处理延迟 | NoiseSuppress_QueryProcessDelay(mode, is_wideband) 返回算法固有延迟;在多麦克风或通话场景中用于延迟补偿/回声抵消对齐 |
| 中断负载 | 将 Process 放在音频中断内时,帧长(GetMiniFrame)应匹配 DMA 半满/全满中断粒度,避免中断嵌套 |
| 升级兼容 | 算法以闭源 .a 交付,升级补丁时仅替换静态库 + 头文件即可;若头文件 ABI 变化(新增参数),需同步修改调用点,勿混用新旧头文件与库 |
扩展点
- 参数策略层:应用可在
Init前根据场景(通话/音乐/户外)动态选择AggressFactor与noise_lvl,实现多档降噪模式切换; - 配置宏接入:
NOISESP_CONFIG_FREEZE / NOISESP_CONFIG_NOISEFLOOR / NOISESP_CONFIG_LOWCUTTHR提供运行期调参通道(ID 形式),可在 UI 或按键事件中调用库内部 get/set 机制(头文件未导出入口,需向杰理 FAE 获取配套接口); - 链路替换:
ans_api.h与NoiseSuppressLib.h是稳定的 C 接口边界,可将其封装为音频后处理组件(如audio_anc_processor),在音频框架中作为可插拔的滤波节点。
测试与验证建议
仓库中未发现针对降噪算法的单元测试源码(算法为闭源库)。建议在集成时自建验证项:
- 白噪/粉噪测试:播放已知频谱噪声,验证输出频谱在目标频段被抑制;
- 语音保真度测试:在
AggressFactor递增下测量语音 MOS/THD,确定可接受上限; - 时钟阶梯测试:分别在 96M/120M/144M 时钟下跑满帧处理,确认无欠载;
- 长时间稳定性:≥24h 循环运行,观察噪声估计是否漂移(必要时用
NOISESP_CONFIG_FREEZE冻结)。
Related Links
- NoiseSuppressLib.h(算法 API 与配置宏)
- ans_api.h(运行时约束说明)
- AD14N_voice_toy.cbp(Code::Blocks 工程链接配置)
- Makefile.ad14n_voice_toy(命令行构建链接配置)
- 芯片硬件约束:AD14N_AC104N_芯片手册.pdf
- SDK 总体说明:AD14N_AD15N_AD17N_AD18N_AC104N_SDK手册.pdf
- 兄弟目录页:
update-patches下的其它芯片补丁页(烧录/OTA 流程参见对应补丁页说明)