杰理 SDK 文档中心
首页
首页
  • 项目概览与快速开始

    • 项目概述与芯片支持
    • 环境搭建与工具链
    • 工程与构建系统
    • 烧录与升级工具
    • 文档与硬件资料
  • 系统架构与芯片平台

    • 芯片平台与启动流程
    • 预编译库与头文件体系
    • 消息、定时器与中断服务
    • 通用外设驱动
  • 存储与文件系统

    • 文件系统实现
    • 存储设备驱动
    • VM 参数存储系统
  • 音频处理

    • 音频解码器
    • 音频编码器
    • MIDI 合成与播放
    • 音效、变速变调与降噪
  • 语音玩具应用

    • 应用框架与状态机
    • 音乐播放与外部音源
    • MIDI 乐器模式
    • 录音应用
    • 待机、电源管理与 USB 从机
  • 小音箱应用

    • 应用框架与模式管理
    • 播放源:音乐、FM、录音与 LineIn
  • 应用层与示例工程

    • 通用 MCU 应用
  • 固件更新与补丁

    • 固件升级机制
    • AD14N 主动降噪补丁

音效、变速变调与降噪

本页介绍 fw-AD15N SDK 中音频处理子系统:音效框架(sound effect)、回声/混响(echo/reverb)、变速变调(pitch shift / formant shift,即"变声")以及 ANS 降噪(noise suppression)的接口设计、数据流与控制流程。

Purpose and Scope

本文档覆盖以下能力的端到端实现说明:

  • 音效框架:sound_effect_api.h 定义的 EFFECT_OBJ、sound_in_obj / sound_out_obj 结构,以及解码器侧音效使能标志位(B_DEC_EFFECT 等)。
  • 回声/混响:echo_api.h 封装的多段回声参数与固定参数结构。
  • 变速变调(变声):howling_pitchshifter_api.h 的 pitch shift(音调)与 formant shift(共振峰)算法 API。
  • ANS 降噪:ans_api.h 与 NoiseSuppressLib.h 提供的实时降噪算法(仅支持 8k/16k 采样率)。

与音效无关的主题(如解码器本身、DAC 输出链路、蓝牙协议栈)不在此页展开,请参见对应目录页。SDK 中的 energe_api.h、howling_api.h、dac.h 等头文件通过 #include 引用本页所述接口,属于音效链路的周边封装,本页会在相关章节说明其关系。

Overview

在 AD15N 这类 MCU 音频方案中,音频链路通常是 解码/录音 → 音效处理 → DAC 播放 的单向流水线。音效子系统在这一链路上提供三类可插拔的处理:

  1. 常规音效(effect):以 EFFECT_OBJ 为统一抽象,回调式 run 接口把处理模块串进 sound_out_obj 的 effect 槽位,解码器通过标志位控制开关。
  2. 变速变调:HOWLING_PITCHSHIFT_FUNC_API 以 need_buf / open / run 三函数范式提供变声能力,link_pitchshift_howling_sound() 负责把变声模块链接到已有的 sound-out 链路上,可在运行中通过 update_howling_parm_fs_api() 动态改参。
  3. 降噪:ANS 算法面向通话/录音场景,ans_init() 挂接环形缓冲区(cbuffer),算法以"踢一脚"(kick)的方式被驱动,且对系统主频和采样率有硬性约束(≥96M 主频、仅 8k/16k)。

设计意图:SDK 将"效果处理"抽象为 统一对象 + 函数指针表,使不同算法(变声、回声、混响、降噪)能以相同范式接入音频流水线,且参数可以在运行时热更新,无需重建整条链路。这是嵌入式音频 SDK 中典型的"以空间换灵活性"设计——每个效果对象占用一段由 need_buf() 查询、open() 初始化的内存。

Architecture

flowchart TD
    subgraph sg_Source["音频源"]
        Dec["解码器 Decoder"]
        Rec["录音 Recorder"]
    end

    subgraph sg_Effect["音效层"]
        EObj["EFFECT_OBJ<br/>(p_si / run / sound)"]
        SIn["sound_in_obj<br/>(p_dbuf / ops)"]
        SOut["sound_out_obj<br/>(p_obuf / effect / mio / enable / para)"]
        PS["Howling PitchShifter<br/>(need_buf / open / run)"]
        Echo["Echo / Reverb<br/>(echo_parm_obj + EF_REVERB_FIX_PARM)"]
    end

    subgraph sg_Noise["降噪层"]
        ANS["ANS 降噪<br/>ans_init / ans_check_kick_start"]
        NSLib["NoiseSuppressLib<br/>(Freeze / NoiseFloor / LowCutThr)"]
    end

    subgraph sg_Out["输出层"]
        DAC["DAC 播放"]
        CBuf["环形缓冲区 cbuffer"]
    end

    Dec -->|"B_DEC_EFFECT 使能"| EObj
    Rec -->|"8k/16k 数据"| ANS
    EObj --> SIn
    EObj --> SOut
    SOut -->|"effect 槽位"| PS
    SOut -->|"effect 槽位"| Echo
    PS -->|"output 回调"| DAC
    Echo -->|"output 回调"| DAC
    ANS -->|"kick 驱动"| NSLib
    ANS --> CBuf
    CBuf --> DAC

架构说明:

  • EFFECT_OBJ(sound_effect_api.h)是音效的统一外壳:p_si 指向输入对象,run 是处理回调,内嵌 sound_out_obj sound 作为输出端。解码器通过 B_DEC_EFFECT(BIT(2))等标志位控制其运行状态。
  • sound_out_obj(sound_effect_api.h)携带 effect(效果对象指针)、mio、enable(volatile 状态)、para(参数),是效果链的挂载点。
  • 变速变调与回声混响都挂在 sound_out_obj.effect 槽位上,通过各自的 output 回调(HOWL_PS_IO_CONTEXT.output)把处理结果送回 DAC 链路。
  • ANS 降噪独立于常规音效链:它直接操作 cbuffer,以 ans_check_kick_start() 的 kick 信号驱动 NoiseSuppressLib 处理,适合放在录音/通话路径上。

音效框架:EFFECT_OBJ 与解码器标志位

sound_effect_api.h 位于解码器公共头文件目录(sdk/include_lib/decoder/),说明音效框架与解码器强耦合:解码器在运行时通过一组位标志管理音效的执行状态。核心标志定义如下:

#define B_DEC_RUN_EN     BIT(0)
#define B_DEC_OBUF_EN    BIT(1)
#define B_DEC_ENABLE     (B_DEC_OBUF_EN | B_DEC_RUN_EN)
#define B_DEC_EFFECT     BIT(2) //#define B_DEC_PAUSE       BIT(8)
#define B_DEC_ERR        BIT(3)
#define B_DEC_MIO        BIT(4) //#define B_DEC_PAUSE       BIT(8)

#define B_DEC_PAUSE      BIT(7)
#define B_DEC_KICK       BIT(8)

#define B_REC_RUN        BIT(9)
#define B_DEC_FIRST      BIT(10)

Source: sound_effect_api.h

设计意图:这些标志位构成解码器的状态机。B_DEC_RUN_EN | B_DEC_OBUF_EN 组合成 B_DEC_ENABLE 作为"解码在跑且输出缓冲就绪"的默认使能态;B_DEC_EFFECT 单独控制音效开关,使音效可以在解码过程中随时切入/切出而不打断解码主流程;B_DEC_KICK 与 ANS 降噪的 kick 机制呼应(见下文降噪章节)。被注释掉的 B_DEC_PAUSE/B_LOUDSPEAKER/B_HALFWAY_EFFECT 表明该框架曾为暂停、扬声器模式、半程音效预留过扩展位——新功能应优先复用这些位定义而非新增枚举。

对象模型:

typedef struct _sound_in_obj {
    void *p_dbuf;
    void *ops;
} sound_in_obj;

typedef struct _sound_out_obj {
    void *p_obuf;
    void *effect;
    void *mio;
    volatile u32 enable;
    u32  para;
} sound_out_obj;

typedef struct _EFFECT_OBJ__ {
    void *p_si;                                     /*point to sound in*/
    int (*run)(void *hld, short *inbuf, int len);
    sound_out_obj sound;

} EFFECT_OBJ;

Source: sound_effect_api.h

关键点:

  • sound_out_obj.enable 声明为 volatile u32,因为解码器 ISR(中断服务例程)与应用线程会并发读写该字段;B_DEC_EFFECT 等标志即写入此处。
  • EFFECT_OBJ.run 的签名 int (*run)(void *hld, short *inbuf, int len) 与变声 API 的 run(void *ptr, short *indata, int len) 完全一致——这不是巧合,而是 SDK 刻意统一的效果回调约定:输入 short PCM、按字节计 len、返回处理结果。因此变声/回声模块可以直接被包装进 EFFECT_OBJ。
  • sound_output(void *priv, void *data, int len) 是链路末端的统一输出口,所有效果模块的 output 回调最终都会落到它(或等价的 DAC 写接口)上。

变速变调:HOWLING_PITCHSHIFT 变声引擎

变声(音效)能力由 howling_pitchshifter_api.h 提供,它同时支持**音调搬移(pitch shift)与共振峰搬移(formant shift)**两种处理,对应枚举:

enum {
    EFFECT_HOWLING_PS        = 0x01,              //1.5《=》12 ms
    EFFECT_HOWLING_FS       = 0x02
};

Source: howling_pitchshifter_api.h

注释 1.5《=》12 ms 表明该算法的处理延迟约 1.5–12 ms,具体取决于参数(ps_parm/fs_parm)。EFFECT_HOWLING_FS 即"变速不变调/变调不变速"类效果(如小黄人/大叔音),是短视频与录音类产品的核心卖点。

参数与 IO 上下文

typedef struct HOWLING_PITCHSHIFT_PARM_ {
    s16 ps_parm;
    s16 fs_parm;
    u32 effect_v;
} HOWLING_PITCHSHIFT_PARM;

typedef struct _HOWL_PS_IO_CONTEXT_ {
    void *priv;
    int(*output)(void *priv, void *data, int len);
} HOWL_PS_IO_CONTEXT;

Source: howling_pitchshifter_api.h

  • ps_parm:音调(pitch)参数,控制音高低;fs_parm:共振峰(formant)参数,控制"喉型"特征;两者独立可调,配合使用可实现音高与音色解耦的变声。
  • effect_v:效果使能/模式值(对应 EFFECT_HOWLING_PS / EFFECT_HOWLING_FS 位)。
  • HOWL_PS_IO_CONTEXT 是变声模块与外界的数据通道:output 回调把处理完的 PCM 送出(通常指向 DAC 或下一级 effect),priv 是回调上下文。这种回调式输出让变声模块可以插入任意位置而无需知道下游细节。

函数指针表:need_buf / open / run

typedef struct _HOWLING_PITCHSHIFT_FUNC_API_ {
    u32(*need_buf)(int flag);
    void (*open)(void *ptr, int sr, HOWLING_PITCHSHIFT_PARM *pitchshift_obj, HOWL_PS_IO_CONTEXT *how_ps_io);        //中途改变参数,可以调init
    int (*run)(void *ptr, short *indata,  int len);   //len是多少个byte
} HOWLING_PITCHSHIFT_FUNC_API;

extern HOWLING_PITCHSHIFT_FUNC_API *get_howling_ps_func_api();

void *link_pitchshift_howling_sound(void *p_sound_out, void *p_dac_cbuf, void **pp_effect, u32 sr);
void update_howling_parm_fs_api(u32 sr, s16 new_fs);

Source: howling_pitchshifter_api.h

这是 SDK 中典型的算法函数指针表模式,get_howling_ps_func_api() 返回表的实例:

  1. need_buf(flag):查询算法所需工作内存大小(flag 区分 PS/FS 模式),调用方据此分配内存——嵌入式环境必须显式管理内存,不允许算法内部 malloc。
  2. open(ptr, sr, parm, io):用采样率 sr 和参数初始化工作区 ptr;头注释特别说明"中途改变参数,可以调 init",即运行中改变 ps_parm/fs_parm 后重新调用 open 即可热更新。
  3. run(ptr, indata, len):处理一帧 PCM;len 单位是字节(不是采样点数),与 EFFECT_OBJ.run 约定一致。

链路集成函数 link_pitchshift_howling_sound() 把变声模块挂到已有的 sound-out 对象上:输入 p_sound_out(来自 sound_out_obj)与 p_dac_cbuf(DAC 环形缓冲),通过 pp_effect 回传出 effect 对象指针,sr 为当前采样率。update_howling_parm_fs_api(sr, new_fs) 则提供独立的"只改共振峰"运行期接口,避免为单个参数重建整条链路。

回声/混响:echo_api 封装

回声模块 echo_api.h 是混响(reverb)算法之上的薄封装,直接复用 reverb_api.h 的固定参数结构:

#include "reverb_api.h"

typedef struct {
    ECHO_PARM_SET echo_parm_obj;  //参数
    EF_REVERB_FIX_PARM echo_fix_parm;
    void *ptr;
} ECHO_OBJ;

Source: echo_api.h

设计意图:把"用户可调参数"(echo_parm_obj)与"算法固定参数"(echo_fix_parm,如滤波器系数、延迟表)分离,ptr 指向运行时工作区。这种"参数/固定系数/工作区"三分离结构与变声模块的 PITCHSHIFT_PARM + FUNC_API + 私有 ptr 异曲同工,是 SDK 音效模块的共同风格,便于移植到不同 DSP 内核。在完整链路中,回声模块同样挂在 sound_out_obj.effect 槽位,与变声模块可以串联(先变声后回声,或反之,由链接顺序决定)。

ANS 降噪:ans_api 与 NoiseSuppressLib

降噪子系统分两层:驱动层 ans_api.h 负责 cbuffer 管理、kick 调度与生命周期;算法层 NoiseSuppressLib.h 是厂商提供的噪声抑制库。

驱动层(ans_api.h)

// ANS降噪算法最低系统时钟需要跑96M以上
// 只支持16k 和 8k采样率
//
int ans_check_kick_start(void *priv);
s32 ans_init(cbuffer_t *in_cbuf, cbuffer_t *out_cbuf, void *kick);
s32 ans_deinit(void);

Source: ans_api.h

  • 头文件注释是硬性约束:系统主频必须 ≥96MHz,采样率仅支持 8k/16k。这是算法实时性(每帧处理需在采样间隔内完成)与算法设计(窄带/宽带模型)共同决定的。
  • ans_init(in_cbuf, out_cbuf, kick):绑定输入/输出环形缓冲,kick 是驱动信号(可指向解码器的 kick 标志,对应上文 B_DEC_KICK)。
  • ans_check_kick_start(priv):查询是否该启动一帧处理(由缓冲水位/中断触发)。
  • ans_deinit():释放资源,无返回值。

降噪采用 kick 驱动(拉模型):数据先进入 in_cbuf,当 kick 条件满足时算法从输入缓冲取一帧、处理、写入 out_cbuf,再由 DAC 消费。与变声模块的**回调驱动(推模型)**互补——前者适合与录音/通话中断同步的路径,后者适合解码播放路径。

算法层(NoiseSuppressLib.h)

#define NOISESP_CONFIG_FREEZE 0
#define NOISESP_CONFIG_NOISEFLOOR 1
#define NOISESP_CONFIG_LOWCUTTHR 2

int NoiseSuppress_GetMiniFrame(int is_wideband);
int NoiseSuppress_QueryProcessDelay(int mode, int is_wideband);
int NoiseSuppress_QueryBufSize(int mode, int is_wideband);
int NoiseSuppress_QueryTempBufSize(int mode, int is_wideband);
void NoiseSuppress_Init(void *NoiseSpRunBuffer,
                        int AggressFactor, // Q16
                        ...

Source: NoiseSuppressLib.h

  • 配置项为整数索引:NOISESP_CONFIG_FREEZE(冻结噪声估计)、NOISESP_CONFIG_NOISEFLOOR(噪声底限,防止过度抑制导致音乐感损失)、NOISESP_CONFIG_LOWCUTTHR(低频切除阈值,抑制隆隆声/风噪)。
  • Query* 系列在 init 前查询:最小帧长、处理延迟、运行缓冲与临时缓冲大小——与变声的 need_buf() 同为"先查询、再分配、后初始化"的嵌入式内存契约。
  • NoiseSuppress_Init 的 AggressFactor 以 Q16 定点数表示抑制强度,值越大抑制越激进但语音损伤风险越高,需按产品场景(通话 vs 录音)权衡。

Core Flow:变声链路与降噪链路的运行流程

两条链路的驱动模型不同,下面分别用时序图说明。

变声(推模型):解码 → 变声 → DAC

sequenceDiagram
    participant Dec as 解码器 Decoder
    participant EObj as EFFECT_OBJ
    participant PS as Howling PitchShifter
    participant DAC as DAC/CBuf

    Dec->>Dec: 设置 B_DEC_EFFECT | B_DEC_ENABLE
    Dec->>EObj: run(hld, inbuf, len)
    EObj->>EObj: 检查 sound.enable 标志
    EObj->>PS: run(ptr, inbuf, len) 字节长度
    PS->>PS: 内部 PS/FS 算法处理<br/>(延迟 1.5~12ms)
    PS->>DAC: output(priv, data, len)
    DAC-->>EObj: 返回写入结果
    EObj-->>Dec: 返回处理状态

要点:解码器每解码出一帧就调用 EFFECT_OBJ.run;run 内部先检查 sound_out_obj.enable(volatile 标志),只有 B_DEC_EFFECT 置位才把数据送入变声模块,否则直通。变声模块处理完通过 HOWL_PS_IO_CONTEXT.output 写回 DAC。运行中若需调整音调/共振峰,应用线程调用 update_howling_parm_fs_api() 或重新 open(),下一帧即生效——这是"中途改参可调 init"的设计红利。

降噪(拉模型):录音 → 环形缓冲 → ANS → 消费

sequenceDiagram
    participant Rec as 录音源 (8k/16k)
    participant In as in_cbuf
    participant ANS as ans_api 驱动
    participant NS as NoiseSuppressLib
    participant Out as out_cbuf
    participant DAC as 下游消费

    Rec->>In: 写入 PCM
    ANS->>ANS: ans_check_kick_start(priv)
    ANS->>NS: 取一帧处理<br/>(AggressFactor 等配置)
    NS-->>Out: 抑制后 PCM
    ANS->>Out: 写入输出缓冲
    Out->>DAC: 消费/播放

要点:与变声不同,降噪不依赖解码器的逐帧回调,而是由 kick 信号(如中断/缓冲水位)触发。ans_check_kick_start() 决定"现在是否够一帧",从而把算法负载与采样节奏解耦,避免在中断里做重计算。NoiseSuppress_QueryProcessDelay 查询出的延迟是固定的(帧长+算法内部延迟),上层可用它做 AEC/同步补偿。

使用示例(源自 SDK 头文件契约)

示例 1:变声模块的标准接入范式

HOWLING_PITCHSHIFT_FUNC_API *api = get_howling_ps_func_api();
u32 buf_size = api->need_buf(EFFECT_HOWLING_PS);          // 1. 查询工作内存
void *work = malloc(buf_size);                            // 2. 分配

HOWLING_PITCHSHIFT_PARM parm = { .ps_parm = 0, .fs_parm = 0, .effect_v = EFFECT_HOWLING_PS };
HOWL_PS_IO_CONTEXT io = { .priv = dac_ctx, .output = sound_output };

api->open(work, sr, &parm, &io);                          // 3. 初始化(中途改参可重调)
// 每帧调用:
api->run(work, pcm_in, len);                              // 4. 处理,len 单位:字节

Source: howling_pitchshifter_api.h

该示例忠实反映 SDK 契约:任何音效模块必须支持"查询内存 → 分配 → open → run"四步生命周期;run 的 len 是字节数,调用方需按 采样点数 × 2(16bit PCM)换算。

示例 2:降噪模块的查询-初始化流程

int is_wideband = (sr == 16000) ? 1 : 0;                  // 仅 8k/16k
int frame = NoiseSuppress_GetMiniFrame(is_wideband);
int delay = NoiseSuppress_QueryProcessDelay(mode, is_wideband);
int size  = NoiseSuppress_QueryBufSize(mode, is_wideband);
int temp  = NoiseSuppress_QueryTempBufSize(mode, is_wideband);

void *run_buf = malloc(size + temp);
NoiseSuppress_Init(run_buf, 0x10000 /* Q16: 1.0 强度 */, /* 其余参数 */);

// 链路侧:
ans_init(in_cbuf, out_cbuf, kick);                        // 绑定缓冲与 kick

Source: NoiseSuppressLib.h

先 Query* 后 Init 的顺序是强制的:算法不会在 init 内部隐式分配内存,所有缓冲必须由调用方按查询结果提供,这是 MCU 平台"零隐藏 malloc"的工程约定。

Configuration Options

配置项位置/类型默认/典型值说明
B_DEC_EFFECT (BIT(2))解码器标志位,写入 sound_out_obj.enable0(关)音效总开关,置位后 EFFECT_OBJ.run 才把数据送入 effect 槽位
B_DEC_ENABLE (BIT(0)|BIT(1))解码器标志位开解码运行+输出缓冲就绪的组合使能态
B_DEC_KICK (BIT(8))解码器标志位0kick 信号,可与 ANS 降噪驱动联动
ps_parmHOWLING_PITCHSHIFT_PARM (s16)0音调参数,正值升调、负值降调;运行中可改(重调 open)
fs_parmHOWLING_PITCHSHIFT_PARM (s16)0共振峰参数,独立于音调控制音色(如小黄人/大叔音)
effect_vHOWLING_PITCHSHIFT_PARM (u32)EFFECT_HOWLING_PS模式选择:0x01=音调搬移,0x02=共振峰搬移
NOISESP_CONFIG_FREEZENoiseSuppressLib 配置索引 00冻结噪声估计(环境突变时手动冻结底噪学习)
NOISESP_CONFIG_NOISEFLOORNoiseSuppressLib 配置索引 1视场景噪声底限,防止过度抑制造成语音断续/音乐感损失
NOISESP_CONFIG_LOWCUTTHRNoiseSuppressLib 配置索引 2视场景低频切除阈值,抑制风噪与隆隆声
AggressFactorNoiseSuppress_Init 参数 (Q16)0x10000 (1.0)抑制强度,Q16 定点数;越大抑制越强、语音损伤风险越高
ANS 采样率/主频约束系统级8k/16k;≥96MHz违反则算法实时性无法保证(头文件注释明确)

API Reference

int sound_output(void *priv, void *data, int len)

统一输出口,所有 effect 的 output 回调最终落地于此(或等价 DAC 写接口)。

  • 参数:priv 输出上下文;data PCM 数据指针;len 字节长度。
  • 返回:写入结果(0 或字节数,取决于实现)。

Source: sound_effect_api.h

HOWLING_PITCHSHIFT_FUNC_API *get_howling_ps_func_api(void)

获取变声算法函数指针表实例(need_buf/open/run)。

  • 返回:HOWLING_PITCHSHIFT_FUNC_API*,含三个函数指针。

Source: howling_pitchshifter_api.h

void *link_pitchshift_howling_sound(void *p_sound_out, void *p_dac_cbuf, void **pp_effect, u32 sr)

把变声模块链接到 sound-out 链路上。

  • 参数:p_sound_out 上游 sound-out 对象;p_dac_cbuf DAC 环形缓冲;pp_effect 回传 effect 对象指针;sr 采样率。
  • 返回:链接后的对象指针(NULL 表示失败)。

Source: howling_pitchshifter_api.h

void update_howling_parm_fs_api(u32 sr, s16 new_fs)

运行期单独更新共振峰参数(无需重建链路)。

  • 参数:sr 当前采样率;new_fs 新的共振峰参数。

Source: howling_pitchshifter_api.h

s32 ans_init(cbuffer_t *in_cbuf, cbuffer_t *out_cbuf, void *kick)

初始化 ANS 降噪并绑定环形缓冲。

  • 参数:in_cbuf 输入缓冲;out_cbuf 输出缓冲;kick 驱动信号指针。
  • 返回:s32,0 成功,负值失败。
  • Throws/约束:主频 <96MHz 或采样率非 8k/16k 时行为未定义(头文件注释)。

Source: ans_api.h

int ans_check_kick_start(void *priv)

查询是否满足启动一帧降噪处理的条件。

  • 参数:priv 初始化时传入的上下文。
  • 返回:非 0 表示可以启动一帧处理。

Source: ans_api.h

s32 ans_deinit(void)

释放 ANS 资源。

  • 返回:s32 状态码。

Source: ans_api.h

故障模式、边界情况与并发

故障模式

故障触发条件后果/处理
工作内存不足need_buf() 返回值未正确用于分配算法写越界,破坏相邻内存;必须严格按 Query*/need_buf 结果分配
主频不足系统时钟 <96MHz 运行 ANS实时性无法保证,产生爆音/卡顿;头文件注释明示该约束
采样率不支持ANS 输入非 8k/16k行为未定义,需在 ans_init 前用 NoiseSuppress_GetMiniFrame(is_wideband) 校验
参数越界ps_parm/fs_parm 超范围变声失真或延迟超预期(1.5–12ms 范围外);建议限定在产品可用区间
过度抑制AggressFactor 过大 + NOISESP_CONFIG_NOISEFLOOR 未设置语音断续、音乐感丢失;用 noise floor 兜底
缓冲水位错位run 的 len 按采样点而非字节传入处理帧长错误,产生咔哒声;SDK 统一约定 len 为字节数

边界情况与并发

  • volatile 共享状态:sound_out_obj.enable 是 volatile u32,解码器 ISR 与应用线程并发读写。置位/清位应使用原子位操作(BIT() 掩码 + 读改写),且避免在中断中执行 run 全流程(只置标志,主循环消费)。
  • 运行中热改参:变声支持中途改参(重新 open 或 update_howling_parm_fs_api),但改参瞬间会清空算法内部状态(延迟线/历史帧),可能产生一帧瞬态噪声。对延迟线敏感的混响/回声模块同理,建议在静音间隙改参。
  • 推/拉模型并存:变声(推)由解码器节拍驱动,降噪(拉)由 kick 驱动。若两者在同一链路串联(如"录音降噪 → 变声 → 播放"),必须用 cbuffer 做速率解耦,否则推拉节拍失配会导致数据丢失或重复。
  • kick 信号复用:B_DEC_KICK 与 ans_check_kick_start 的 kick 可共享,但需注意 kick 是"边沿敏感"还是"电平敏感"——ans_check_kick_start 的查询语义暗示驱动方应负责去抖/清零。

性能与运维注意事项

  • 内存契约:所有算法模块(变声、降噪)遵循"先查询后分配、零隐藏 malloc"约定。工作区 + 临时区(QueryBufSize + QueryTempBufSize)应一次性分配,避免碎片。
  • 延迟预算:变声算法延迟 1.5–12ms(随参数),降噪延迟可用 NoiseSuppress_QueryProcessDelay 查询。做"实时耳返"或"通话+播放"场景时,需在系统级把该延迟计入总链路预算。
  • 定点数约定:AggressFactor 为 Q16(1.0 = 0x10000),配置时注意定标,避免浮点转定点溢出。
  • 采样率一致性:变声 open 的 sr、update_howling_parm_fs_api 的 sr 必须与链路实际采样率一致;采样率切换(如 44.1k→16k 重采样)后必须重新 open,否则音高偏移。

扩展点

SDK 为音效扩展预留了清晰的接入点:

  1. 新效果模块:实现 need_buf / open / run 三函数并注册到函数指针表(参照 get_howling_ps_func_api 模式),即可挂入 sound_out_obj.effect 槽位。
  2. 标志位扩展:sound_effect_api.h 中注释掉的 B_DEC_PAUSE/B_LOUDSPEAKER/B_HALFWAY_EFFECT(BIT(9)/BIT(10) 附近)是预留位,新开关应复用这些位而非扩张结构体。
  3. 链路排序:link_pitchshift_howling_sound(p_sound_out, p_dac_cbuf, ...) 的链接顺序决定效果串联次序(变声→回声 或 回声→变声),可在不改算法的前提下通过链接顺序实现不同的声音风格。
  4. 降噪配置:NOISESP_CONFIG_* 索引式配置接口支持运行时调整 freeze/noisefloor/lowcut 三个旋钮,适合做"场景模式"(安静/嘈杂/风噪)切换。

相关文件与链接

  • sound_effect_api.h — 音效框架与解码器标志
  • howling_pitchshifter_api.h — 变速变调/变声引擎
  • echo_api.h — 回声/混响封装
  • ans_api.h — ANS 降噪驱动层
  • NoiseSuppressLib.h — 噪声抑制算法库
  • 周边引用:sdk/include_lib/audio/energe_api.h(包含 sound_effect_api.h)、sdk/include_lib/audio/howling_api.h(组合 pitch shifter 与 notch 啸叫抑制)、sdk/include_lib/audio/dac.h(DAC 输出侧)

说明:本页聚焦音效/变速变调/降噪的接口契约与数据流。解码器状态机、DAC 硬件驱动、录音 AEC 等相邻能力请查阅对应目录页。

Prev
MIDI 合成与播放