杰理 SDK 文档中心
首页
首页
  • 项目概览

    • AD16N 系列芯片与 SDK 能力总览
  • 快速开始

    • 环境搭建与编译工具链
    • 编译构建指南
    • 烧录与固件升级
  • SDK 工程架构

    • SDK 目录结构与模块分层
    • 构建系统与批处理工具
    • BSP 板级支持包
  • mbox_flash 小音箱应用

    • 应用初始化与启动流程
    • 应用配置系统
    • 按键、UI 与用户交互
  • 音频子系统

    • 音频解码框架与调度
    • 音频格式解码器实现
    • MIDI 合成与播放
    • 音频编码与录音
    • EQ/DRC 与音效处理
    • DAC/ADC 音频接口与采样
  • 存储与文件系统

    • 媒体 IO 抽象层 MIO
    • 存储设备驱动
    • 文件系统支持
  • 平台系统库

    • 系统基础服务
    • CPU 平台与运行库
    • 固件升级与更新机制
    • 蓝牙与扩展连接接口
  • 电源与低功耗管理

    • 电源管理与低功耗设计
    • 锂电池充电管理
  • 硬件与文档参考

    • SDK 文档中心与版本发布记录
    • 芯片数据手册与硬件设计参考

EQ/DRC 与音效处理

EQ/DRC 与音效处理是 AD16N 音频子系统中负责对音频信号进行频响修正、动态范围压缩及人声/音乐美化效果处理的核心能力层。本文档基于 audio_eq.h、audio_eq_api.c、effects_adj.h 等实际源码,完整阐述 EQ/DRC 的效果 ID 体系、EQ 处理链路、参数切换机制与在线调试流程。

Purpose and Scope

本文档覆盖 AD16N 音频子系统中与 EQ(均衡器)、DRC(动态范围压缩)及其他音效处理相关的完整能力,包括:

  • 效果 ID 体系(effects_adj.h):MIC、PHONE/AEC、MUSIC、AUX 各通路的 EQ、DRC、混响、变声、噪声门等效果枚举;
  • EQ 处理链路(audio_eq.h / audio_eq_api.c):EQ 运行结构、EQ API 操作集、EQ 的初始化/运行/释放流程;
  • EQ 参数模式切换(eq_mode_sw)与在线 EQ 助手参数更新(eq_online_sw);
  • EQ 配置产物(eq_cfg.bin、dir_eq 目录、eqbin2dir.bat 转换脚本)。

以下内容属于兄弟页面,不在本文档展开:音频解码器(Decoder)、DAC/ADC 硬件通路、音频流管理(sound_mge)、降噪/AEC 算法本体。DRC 与 EQ 共享同一套效果框架,故 DRC 的 ID 定义与挂载方式在此一并说明,但其算法库(audio_eq_lib.a 预编译库)内部实现不在此展开。

Overview

在嵌入式音频系统中,扬声器/麦克风/功放的频响曲线不平直、音量过大导致削波、人声与伴奏比例失衡等问题都需要在数字域进行补偿与美化。AD16N 通过一套统一的"效果对象"(EFFECT_OBJ)框架,把 EQ、DRC、混响、变声、噪声门等效果串联进音频数据流中:每个效果都是一个可插入 sound_out_obj 链表的节点,输入 PCM 短整型数据、输出处理后的 PCM 数据。

EQ/DRC 处理的几个关键设计点:

  1. 统一效果 ID 体系:每个效果(EQ 段、DRC、混响等)都有唯一的 16 位 ID(如 EFF_MUSIC_EQ = 0x2001),按通路(MIC/PHONE/AEC/MUSIC/AUX)分组,便于调音工具与固件按 ID 定位参数。
  2. EQ 段(segment)模型:EQ 由最多 EQ_SECTION_MAX(10)个 IIR 滤波段组成,每段指定滤波器类型(如带通)、中心频率、增益与 Q 值;music_eq_tool 结构体承载整组 EQ 参数。
  3. 参数在线热切换:EQ_CMD_SWITCH_TAB 命令允许在运行中替换系数表(切模式/调音),配合 fade-in/fade-out 防爆音。
  4. 预编译库 + 薄封装:EQ 算法本体以 audio_eq_lib.a 预编译库提供(get_eq_context() 返回操作集),SDK 侧仅提供挂载、参数管理与在线调试封装,兼顾性能与灵活性。
flowchart TD
    subgraph sg_App["应用层"]
        APP["应用/调音工具"]
        MUSIC_TOOL["music_eq_tool_online<br/>(在线EQ参数)"]
    end

    subgraph sg_Api["EQ 封装层 (audio_eq_api.c)"]
        LINK["link_eq_sound()"]
        EQMODE["eq_mode_sw()"]
        EQONLINE["eq_online_sw()"]
        EQAPI["eq_api() 创建EQ句柄"]
    end

    subgraph sg_Framework["效果框架 (audio_eq.h)"]
        EHDL["EQ_HDL"]
        EOBJ["EFFECT_OBJ + sound_in_obj"]
        EIO["EQ_IO_CONTEXT"]
        EBUFF["EQ_BUFF (含fade)"]
    end

    subgraph sg_Lib["预编译库 (audio_eq_lib.a)"]
        OPS["EQ_STUCT_API<br/>need_buf/open/run/config"]
        HW["hw_eq 硬件EQ"]
    end

    subgraph sg_Cfg["参数存储"]
        CFGBIN["eq_cfg.bin"]
        DIR["dir_eq 目录"]
        BATCH["eqbin2dir.bat"]
    end

    APP --> LINK
    APP --> EQMODE
    APP --> EQONLINE
    MUSIC_TOOL --> LINK
    MUSIC_TOOL --> EQMODE
    LINK --> EQAPI
    EQAPI --> EHDL
    EHDL --> EOBJ
    EHDL --> EIO
    EOBJ --> EBUFF
    EQAPI --> OPS
    OPS --> HW
    EQMODE --> CFGBIN
    CFGBIN --> DIR
    BATCH --> DIR
    EQONLINE --> OPS

说明:EQ 封装层负责把 music_eq_tool_online 中的参数通过 eq_api() 创建为 EQ_HDL 句柄并挂入音效链表;运行时 EQ_STUCT_API 操作集指向预编译库中的算法实现;模式切换时从 eq_cfg.bin 读取参数组并下发 EQ_CMD_SWITCH_TAB。

效果 ID 体系(effects_adj.h)

所有音效的枚举 ID 定义在 effects_adj.h,按"通路 + 效果类型"编码:

ID 区间通路典型效果
0x1001 ~ 0x101aMIC(麦克风)EQ0~EQ4、DRC0~DRC4、板混响、回声、噪声门、啸叫抑制、变声
0x1101 ~ 0x1108PHONE / AEC宽带/窄带 EQ 与 DRC(通话场景)
0x2001 ~ 0x2069MUSIC(音乐)主 EQ、低/中/高/整段 DRC、分频器、动态 EQ、虚拟低音、环绕、声道交换
0x2030 ~ 0x2032AUX(Line-in)独立 EQ、DRC、增益

示例(节选自 effects_adj.h#L55-L65):

EFF_MUSIC_EQ          = 0x2001,
EFF_MUSIC_LOW_DRC     = 0x2002,
EFF_MUSIC_FR_EQ       = 0x2003,
EFF_MUSIC_MID_DRC     = 0x2011,
EFF_MUSIC_HIGH_DRC    = 0x2012,
EFF_MUSIC_WHOLE_DRC   = 0x2013,
EFF_MUSIC_CROSSOVER   = 0x2014,
EFF_MUSIC_DYNAMIC_EQ  = 0x2015,
EFF_MUSIC_EQ2         = 0x2016,
EFF_MUSIC_GAIN        = 0x2017,

设计意图:ID 前缀(0x10xx 麦克风 / 0x11xx 通话 / 0x20xx 音乐)让调音工具(EQ 在线调试助手)无需理解内部实现即可按场景定位效果;2.1/2.2 声道场景中 EFF_MUSIC_RL_*、EFF_MUSIC_RR_*、EFF_MUSIC_FR_* 系列(0x2005~0x2069)为每个物理声道单独挂 EQ/DRC/分频器,体现多声道独立调音能力。

除效果 ID 外,该头文件还定义了在线调试协议相关常量:

  • EFF_ONLINE_PACKET:{cmd, data[64]} 结构,承载在线调音命令与 64 个 int 参数;
  • EFF_CFG_FILE_ID = 0x3:音效配置项源文件 ID;
  • 命令字:EFF_CMD_INQUIRE(0x4) 查询、EFF_CMD_GETVER(0x5) 版本、EFF_CMD_FILE_SIZE(0xB) 文件大小、EFF_CMD_FILE(0xC) 文件内容、EFF_CMD_CHANGE_MODE(0xE) 切模式、EFF_CMD_RESYNC_PARM_BEGIN/END(0x30/0x28) 参数重同步边界。

EQ 数据模型与 API 结构

EQ 的核心数据结构定义在 audio_eq.h,其设计围绕"参数表可热替换"展开:

结构体职责
EQ_PARA_STRUCT运行参数:段表指针(seg/next_seg)、全局增益(global_gain)、采样率、最大段数、声道数
EQ_STUCT_API算法操作集:need_buf 计算内存、open 打开实例、run 处理 PCM、config 动态配置
EQ_BUFF运行缓冲:IO 上下文、操作集、参数、fade 对象、系数缓存表
EQ_UPDATE更新命令载荷:新段表指针 + 全局增益 + EQ 模式
EQ_HDL效果句柄:内嵌 EFFECT_OBJ、sound_in_obj、EQ_IO_CONTEXT、EQ_BUFF
music_eq_tool调音参数载体:全局增益 + 段数 + 使能段 + 段表(最多 10 段)

关键常量(audio_eq.h#L7-L19):

#define EQ_MAX_POINT    (128)
#define EQ_SECTION_MAX  10
#define EQ_COEFF_BASE   (0x2F0000)

#define EQ_RUN_MODE         NORMAL
#define EQ_IN_FORMAT        DATI_SHORT
#define EQ_OUT_FORMAT       DATO_SHORT
#define EQ_DATA_IN_MODE     SEQUENCE_DAT_IN
#define EQ_DATA_OUT_MODE    SEQUENCE_DAT_OUT

#define B_EQ_START          BIT(0)
#define B_EQ_FADE_IN        BIT(1)
#define B_EQ_FADE_OUT       BIT(2)

设计意图:EQ 输入/输出格式固定为 DATI_SHORT/DATO_SHORT(16 位 PCM),运行模式为 NORMAL,数据按 SEQUENCE_DAT_IN/OUT 顺序组织——这意味着 EQ 直接内嵌在标准音频链路中,不改变前后级的数据格式约定。B_EQ_FADE_IN/OUT 标志配合 EQ_BUFF 内的 sound_fade_obj 实现参数切换时的渐变,避免系数跳变产生爆音。

EQ 操作集 EQ_STUCT_API 的四个函数指针(audio_eq.h#L36-L41)是整个 EQ 的抽象边界:

typedef struct  _EQ_STUCT_API_ {
    unsigned int(*need_buf)(int max_eq_seg, int ch);
    int *(*open)(unsigned int *ptr, EQ_PARA_STRUCT *para, EQ_IO_CONTEXT *rsio);
    int (*run)(unsigned int *ptr, short *inbuf, int len);
    u32(*config)(void *work_buf, u32 cmd, void *parm);
} EQ_STUCT_API;
  • need_buf:按最大段数与声道数返回所需 RAM(源码注释:单路 EQ 需 344 字节;多路每路需 344 + 64×最大段数 字节);
  • open:初始化实例,返回工作缓冲;
  • run:处理一段 short PCM 数据;
  • config:执行 EQ_CMD_SWITCH_TAB(切换系数表)或 EQ_GET_CURR_MODE(查询当前模式)。

EQ 处理链路实现(audio_eq_api.c)

audio_eq_api.c 在 AUDIO_HW_EQ_EN 宏开启时编译,是 EQ 在 SDK 中的唯一封装层。它同时定义了两个编译期常量(audio_eq_api.c#L16-L18):

const int config_hw_single_eq = 1;      // 仅使用一路EQ,省RAM
const int config_eq_fade_enbale = 1;    // 使能EQ淡入淡出
const int config_eq_fade_step = 128;    // 淡入淡出步长

默认在线调音参数 music_eq_tool_online(audio_eq_api.c#L20-L36)预置了 10 个 1/3 倍频程带通滤波器段(31Hz~16kHz,Q=0.7),增益全为 0——即默认平直响应:

struct music_eq_tool music_eq_tool_online = {
    .global_gain = 0x0,
    .seg_num = EQ_SECTION_MAX,
    .enable_section = 0x0,
    .seg = {
        {0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f},
        {1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f},
        {2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f},
        {3, EQ_IIR_TYPE_BAND_PASS, 250, 0, 0.7f},
        {4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f},
        {5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f},
        {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f},
        {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f},
        {8, EQ_IIR_TYPE_BAND_PASS, 8000, 0, 0.7f},
        {9, EQ_IIR_TYPE_BAND_PASS, 16000, 0, 0.7f},
    },
};

设计意图:段表条目为 {段序号, 滤波器类型, 中心频率, 增益, Q值}。预置 10 段等间隔倍频程带通 + 0 增益,保证"出厂默认无音染";enable_section=0 配合段级使能位可在不重建段表的情况下关闭部分滤波段,节省算力。

链路挂载:link_eq_sound()

link_eq_sound()(audio_eq_api.c#L40-L68)把 EQ 实例插入 sound_out_obj 输出链表:

void *link_eq_sound(void *p_sound_out, void *p_dac_cbuf, void **pp_effect, u32 sr, u8 ch)
{
    sound_out_obj *p_next_sound = 0;
    sound_out_obj *p_curr_sound = p_sound_out;
    if (NULL == pp_effect) {
        log_info("eq init err\n");
        return p_curr_sound;
    }
    /* EQ参数配置 */
    EQ_PARA_STRUCT para;
    para.sample_rate = sr;
    para.ch = ch;
    para.seg = music_eq_tool_online.seg;
    para.global_gain = music_eq_tool_online.global_gain;
    para.max_nsection = music_eq_tool_online.seg_num;
    p_curr_sound->effect = eq_api(p_curr_sound->p_obuf, &para, (void **)&p_next_sound);
    if (NULL != p_curr_sound->effect) {
        *pp_effect = p_curr_sound->effect;
        p_curr_sound->enable |= B_DEC_EFFECT;
        p_curr_sound = p_next_sound;
        p_curr_sound->p_obuf = p_dac_cbuf;
        log_info("audio eq init succ\n");
    } else {
        log_info("audio eq init fail\n");
    }
    return p_curr_sound;
}

执行流程:用当前采样率/声道数/在线参数构造 EQ_PARA_STRUCT → 调用 eq_api() 创建效果对象 → 把 p_curr_sound->effect 指向新 EQ 对象并置 B_DEC_EFFECT 位 → 将下一级输出缓冲指向 DAC 环形缓冲,形成"解码器 → EQ → DAC"的串接。EQ 初始化失败时返回原节点,系统仍可无 EQ 出声(容错设计)。

实例创建:eq_api()

eq_api()(audio_eq_api.c#L146-L172)是 EQ 实例的构造函数,展示了一个效果对象如何被组织:

static void *eq_api(void *obuf, EQ_PARA_STRUCT *p_para, void **ppsound)
{
    u32 buff_len, i;
    EQ_STUCT_API *ops = (EQ_STUCT_API *)get_eq_context();
    buff_len = ops->need_buf(p_para->max_nsection, p_para->ch);
    EQ_HDL *p_eq_hdl = eq_hld_malloc(buff_len);
    if (NULL == p_eq_hdl) {
        log_error("eq malloc fail, need buff_len:%d\n", buff_len);
        return 0;
    }
    memset((void *)p_eq_hdl, 0, buff_len);
    ops->open((unsigned int *)&p_eq_hdl->buff, p_para, (void *)&p_eq_hdl->io);

    EFFECT_OBJ *p_eq_obj = &p_eq_hdl->obj;
    p_eq_hdl->io.priv = &p_eq_obj->sound;
    p_eq_hdl->io.output = sound_output;
    p_eq_hdl->si.ops = ops;
    p_eq_hdl->si.p_dbuf = &p_eq_hdl->buff;
    p_eq_hdl->obj.p_si = &p_eq_hdl->si;
    p_eq_hdl->obj.run = eq_run_api;
    p_eq_hdl->obj.sound.p_obuf = obuf;

    *ppsound = &p_eq_obj->sound;
    return p_eq_obj;
}

关键点:

  1. get_eq_context() 返回预编译库中的 EQ_STUCT_API 操作集(need_buf/open/run/config);
  2. need_buf 计算所需内存,eq_hld_malloc()(内部走 my_malloc(malloc_size, MM_EQ))从 EQ 内存池分配——MM_EQ 说明 EQ 有独立内存分区管理;
  3. ops->open() 完成算法实例初始化,EQ_IO_CONTEXT.output 指向 sound_output,使 EQ 处理完的数据能继续向后级输出;
  4. EQ_HDL 把"算法缓冲(p_dbuf)+ 操作集(ops)+ 运行回调(run)+ 输出对象(sound)"统一封装为 EFFECT_OBJ,从而可以被标准音频框架调度。

运行时回调:eq_run_api()

static int eq_run_api(void *hld, short *inbuf, int len)
{
    sound_in_obj *p_si = (sound_in_obj *)hld;
    EQ_STUCT_API *ops = (EQ_STUCT_API *)p_si->ops;
    return ops->run(p_si->p_dbuf, inbuf, len);
}

每次音频帧到来,框架调用 EFFECT_OBJ.run,即 eq_run_api:取出句柄内的操作集与算法缓冲,转调库中的 run 处理 len 个 short 采样。这是整个 EQ 处理的热路径,不涉及锁与动态分配,保证实时性。

参数切换与在线调音

EQ 参数支持两种运行时更新途径,都通过 EQ_STUCT_API.config(..., EQ_CMD_SWITCH_TAB, &update_parm) 下发新段表。

模式切换:eq_mode_sw()

eq_mode_sw()(audio_eq_api.c#L89-L124)用于切换预置 EQ 模式(例如"流行/摇滚/古典"):

void eq_mode_sw(void *parm)
{
    EFFECT_OBJ *e_obj = (EFFECT_OBJ *)parm;
    if (NULL == e_obj) {
        return ;
    }
    /* 切换eq参数组 */
    eq_mode++;
    if (eq_mode >= get_eq_mode_total_num()) {
        eq_mode = 0;
    }
    /* 获取名字 */
    void *ret_name = NULL;
    ret_name = get_eq_mode_name_api(eq_mode);
    log_info("now eq_mode is %d , eq_mode_name is  %s  ", eq_mode, ret_name);

    /* 读取eq_cfg.bin文件,获取对应eq参数组参数 */
    u32 ret = ext_eff_file_analyze_api(eq_mode, &music_eq_tool_online, sizeof(struct music_eq_tool));
    if (ret != 0) {
        log_info("ext_eff_file_analyze ret %d ", ret);
        return ;
    }
    /* 配置eq */
    EQ_UPDATE update_parm;
    memset(&update_parm, 0, sizeof(update_parm));
    update_parm.seg = music_eq_tool_online.seg;
    update_parm.global_gain = music_eq_tool_online.global_gain;

    sound_in_obj *p_src_si = e_obj->p_si;
    EQ_STUCT_API *p_ops =  p_src_si->ops;
    p_ops->config(p_src_si->p_dbuf, EQ_CMD_SWITCH_TAB, (void *)&update_parm);
}

流程:模式号 eq_mode 循环递增 → 通过 get_eq_mode_name_api() 获取模式名(用于日志/UI)→ ext_eff_file_analyze_api() 从 eq_cfg.bin 解析对应参数组写入 music_eq_tool_online → 构造 EQ_UPDATE 下发 EQ_CMD_SWITCH_TAB。eq_mode 是全局变量,注释明确指出"EQ 模式参数由应用层管理",即 SDK 只提供机制,模式数量与参数内容由应用侧的 eq_cfg.bin 决定。

在线 EQ 助手:eq_online_sw()

eq_online_sw()(audio_eq_api.c#L71-L85)是"AD16N 在线 EQ 调试助手"(仓库 post_build/uc03/eq_tool/AD16N在线EQ调试助手.jlxproj)拖拽曲线时的回调:调音工具改写 music_eq_tool_online 后调用本函数,将新段表/增益通过 EQ_CMD_SWITCH_TAB 热更新到运行中的 EQ,实现听感即时反馈,无需重新编译固件。

资源释放:eq_reless()

void eq_reless(void **ppeffect)
{
    EFFECT_OBJ *p_eobj = *ppeffect;
    log_info("eq free : 0x%x", (u32) p_eobj);
    if (NULL != p_eobj) {
        *ppeffect = my_free(p_eobj);
    }
}

停止播放/关闭 EQ 时调用,释放 EQ 句柄内存(归还 MM_EQ 池)。释放后 *ppeffect 置 NULL 防止悬垂指针。

核心流程

sequenceDiagram
    participant APP as 应用/调音工具
    participant LINK as link_eq_sound()
    participant API as eq_api()/EQ_HDL
    participant OPS as EQ_STUCT_API (audio_eq_lib.a)
    participant CFG as eq_cfg.bin

    APP->>LINK: 初始化链路 (sr, ch, music_eq_tool_online)
    LINK->>API: 构造 EQ_PARA_STRUCT
    API->>OPS: need_buf(max_nsection, ch)
    OPS-->>API: 所需RAM大小
    API->>API: eq_hld_malloc() 分配 MM_EQ 内存
    API->>OPS: open(buff, para, io)
    API->>API: 组装 EFFECT_OBJ / sound_in_obj / EQ_IO_CONTEXT
    LINK-->>APP: 返回新 sound_out_obj 节点

    loop 每帧音频
        APP->>API: eq_run_api() 回调
        API->>OPS: run(p_dbuf, inbuf, len)
        OPS-->>API: 处理后PCM
        API->>API: io.output() 向后级输出
    end

    APP->>CFG: eq_mode_sw() → ext_eff_file_analyze_api(eq_mode)
    CFG-->>APP: 参数组写入 music_eq_tool_online
    APP->>OPS: config(EQ_CMD_SWITCH_TAB, EQ_UPDATE)
    Note over OPS: 系数表热替换 + fade 渐变防爆音

配置选项

配置项类型默认值说明
AUDIO_HW_EQ_EN编译宏—EQ 功能总开关,关闭时整个 audio_eq_api.c 不参与编译
config_hw_single_eqconst int1仅使用一路 EQ(省 RAM);多路时每路需额外 64×段数字节
config_eq_fade_enbaleconst int1使能 EQ 淡入淡出(防爆音)
config_eq_fade_stepconst int128淡入淡出步长
EQ_SECTION_MAX宏10最大 EQ 段数
EQ_MAX_POINT宏128单次处理最大采样点数
EQ_COEFF_BASE宏0x2F0000系数表存储基地址
EFF_CFG_FILE_ID宏0x3音效配置项源文件 ID(eq_cfg.bin)

API Reference

link_eq_sound(void *p_sound_out, void *p_dac_cbuf, void **pp_effect, u32 sr, u8 ch): void *

将 EQ 实例挂入输出音效链。参数:p_sound_out 当前输出对象、p_dac_cbuf DAC 环形缓冲、pp_effect 返回效果对象指针、sr 采样率、ch 声道数。返回:下一个 sound_out_obj(失败时返回原节点,系统降级为无 EQ 输出)。位置:audio_eq_api.c#L40

eq_mode_sw(void *parm): void

切换到下一个 EQ 参数组(模式号循环)。参数:parm 为 EFFECT_OBJ *。副作用:从 eq_cfg.bin 解析新参数并热更新运行中的 EQ;eq_cfg.bin 解析失败时仅打日志并返回,保持原参数不变。位置:audio_eq_api.c#L89

eq_online_sw(void *parm): void

在线调音工具改参后的热更新入口。参数:parm 为 EFFECT_OBJ *。位置:audio_eq_api.c#L71

eq_api(void *obuf, EQ_PARA_STRUCT *p_para, void **ppsound): void *

创建 EQ 效果对象(内部函数,经 link_eq_sound 调用)。返回:EFFECT_OBJ *;内存分配失败返回 0。位置:audio_eq_api.c#L146

eq_hld_malloc(u32 malloc_size): void * / eq_reless(void **ppeffect): void

EQ 内存的分配/释放钩子,使用 my_malloc(..., MM_EQ) 与 my_free()。位置:audio_eq_api.c#L127、audio_eq_api.c#L131

EQ_STUCT_API 操作集(由 get_eq_context() 提供,预编译库实现)

  • need_buf(max_eq_seg, ch):返回所需 RAM 字节数;
  • open(ptr, para, rsio):初始化 EQ 实例,返回工作缓冲指针;
  • run(ptr, inbuf, len):处理 len 个 short PCM 采样,返回处理结果;
  • config(work_buf, cmd, parm):支持 EQ_CMD_SWITCH_TAB(切换系数表)与 EQ_GET_CURR_MODE(查询当前模式)。

失败模式与边界情况

  • EQ 内存不足:eq_api() 中 need_buf 计算后 eq_hld_malloc 失败会 log_error 并返回 0,link_eq_sound 判定 effect==NULL 走 "init fail" 分支——音频链路保持无 EQ 直通,系统不崩溃(降级容错)。
  • 空句柄:eq_online_sw / eq_mode_sw 入口对 NULL 效果对象直接 return,避免对未初始化链路下发参数。
  • eq_cfg.bin 解析失败:ext_eff_file_analyze_api() 返回非 0 时 eq_mode_sw 提前返回,运行中的 EQ 参数不受影响(上次成功参数继续生效),但模式号已递增,下次调用将尝试下一组。
  • 参数热切换爆音:系数表跳变会引起输出突变,因此 EQ_BUFF 内嵌 sound_fade_obj,B_EQ_FADE_IN/OUT 标志 + config_eq_fade_step 步长实现渐变;config_eq_fade_enbale 可整体关闭。
  • 并发/重入:EQ 的 run 在音频中断/音频任务上下文中被逐帧调用,参数切换(config)由应用层发起。二者共享 music_eq_tool_online 全局参数,SDK 未在源码层加锁——参数切换应避免在音频帧处理中途执行,或由应用层保证时序(注释明确"EQ 模式参数由应用层管理")。

性能与运维

  • RAM 预算:单路 EQ 固定 344 字节;多路每路增加 64 × 最大段数 字节,config_hw_single_eq=1 即面向省 RAM 场景(源码注释给出明确公式)。
  • 热路径:eq_run_api → ops->run 每帧调用,无锁、无动态分配,算法为定点/浮点 IIR 段级联,段数(seg_num)与使能段(enable_section)决定实际算力消耗。
  • 调音产物:EQ 参数固化于 eq_cfg.bin,发布前用 eqbin2dir.bat 转成 dir_eq 目录格式烧录(仓库 post_build/uc03/ 下可见 eq_tool/eq_cfg.bin 与 dir_eq);运行期 eq_mode_sw 按 EFF_CFG_FILE_ID(0x3) 读取。
  • 在线调音:配合 AD16N在线EQ调试助手.jlxproj 工程与 EFF_ONLINE_PACKET 协议(EFF_CMD_INQUIRE/GETVER/FILE/CHANGE_MODE/RESYNC_PARM_*)可在不重刷固件的前提下改曲线、切模式。

扩展点

  • 新增 EQ 模式:在 eq_cfg.bin 中追加参数组,模式总数由 get_eq_mode_total_num() 返回,eq_mode_sw 自动循环,无需改 SDK 代码。
  • 多声道独立调音:EFF_MUSIC_RL_EQ/RR_EQ/FR_EQ、EFF_MUSIC_*_DRC、EFF_MUSIC_*_CROSSOVER 系列 ID 表明 2.1/2.2 声道方案已预留每声道独立 EQ/DRC/分频器挂载点。
  • 更换算法库:EQ 算法全部走 EQ_STUCT_API 抽象(get_eq_context() 返回),替换 audio_eq_lib.a 即可换算法而不动封装层。
  • 新增效果类型:在 effects_adj.h 枚举中分配新 ID,并在效果框架中按 EFFECT_OBJ 约定实现 run/init/release 即可接入链路(如 EFF_MIC_VOICE_CHANGER、EFF_MUSIC_VBASS、EFF_MUSIC_SURRROUND_EFF 等已有先例)。

Related Links

  • audio_eq.h(EQ API 结构定义)
  • audio_eq_api.c(EQ 封装层实现)
  • effects_adj.h(效果 ID 体系)
  • hw_eq.h(硬件 EQ 定义)
  • pcm_eq_api.h(PCM 域 EQ API)
  • audio_eq_lib.a(EQ 预编译算法库)
  • AD16N 在线 EQ 调试助手工程
  • eqbin2dir.bat(EQ 配置转换脚本)

兄弟页面指引:音频解码与播放链路、DAC/ADC 通路、AEC/降噪算法本体请参见音频子系统下对应目录页。

Prev
音频编码与录音
Next
DAC/ADC 音频接口与采样