音频效果处理(EQ/频谱/变调/环绕/超低音)
本页介绍 AC63 系列蓝牙 SoC SDK 中的音频效果处理能力,重点覆盖以 audio_eq 为核心的 EQ 均衡(含高低音/超低音增强)、DRC 联动、频谱分析与在线调试等机制的实现原理、数据流、配置方式与使用示例。
Purpose and Scope
本页面向希望在 fw-AC63_BT_SDK 中接入、裁剪或调试音频效果的开发者,内容涵盖:
- EQ 核心模块
audio_eq的数据结构、工作模式(EQ_MODE)、系数来源(EQ_TYPE)与 API; - EQ/DRC 功能开关位(
config_audio_eq_en/config_audio_drc_en)与编译期裁剪; - 高低音(
high_bass,即超低音/高音增强)的接口设计; - EQ 节点如何挂载到音频流(
audio_stream_entry)实现实时处理; - 频谱(
spectrum_eq)等关联模块的入口位置; - 实际工程中的调用示例(
audio_eq_drc_demo.c)。
不在本页范围内:解码/编码、DAC 驱动、蓝牙协议栈、UI 界面等属于其他目录的能力;变调(pitch)与环绕(surround)效果若由上层 DSP 算法库或 effects_adj 音效调节模块提供,其实现细节请参考对应模块文档。本页采集范围内未读取到变调/环绕算法的具体实现文件,因此仅给出模块定位与接入指引,不做未经验证的细节描述。
Overview
AC63 系列 SDK 采用「硬件 EQ 引擎 + 软件参数管理」的音效架构:实时 PCM 数据流经过挂在音频流节点链上的 audio_eq 节点,节点内部根据 struct audio_eq_param 提供的段数、采样率、系数表(struct eq_seg_info)等参数,通过系数回调(audio_eq_filter_cb)获取滤波器系数,再交给硬件 EQ 引擎(hw_eq)完成逐采样点运算。系数切换时支持淡入淡出(fade),避免增益突变产生"哒哒"杂音。
该设计把参数管理(软件)与数值运算(硬件)分离:软件层只负责维护效果模式、系数表和淡入过程,重负载的滤波运算下沉到硬件,从而在低主频 MCU 上也能实时处理多段 EQ。SDK 同时提供同步/异步两种运行方式(no_wait、CONFIG_EQ_SUPPORT_ASYNC),并可通过在线调试(EQ_ONLINE_EN)与文件解析(EQ_FILE_EN)动态更新效果。
Architecture
flowchart LR
subgraph sg_Source["信号源"]
Dec["解码器 Decoder"]
Mic["MIC / Line-in"]
end
subgraph sg_Stream["音频流节点链 audio_stream"]
Node["audio_stream_entry 节点"]
EQ["audio_eq 节点<br/>(AEID_MUSIC_EQ)"]
DRC["DRC 节点<br/>(限幅/压缩/多带)"]
end
subgraph sg_Core["EQ 参数管理层(软件)"]
Param["audio_eq_param 参数"]
Seg["eq_seg_info 系数表"]
Cb["filter_cb 系数回调"]
Fade["淡入淡出 audio_eq_fade"]
end
subgraph sg_HW["硬件/输出层"]
HwEq["hw_eq 硬件EQ引擎"]
DAC["DAC 输出"]
end
subgraph sg_Cfg["效果配置来源"]
ModeTab["EQ_MODE_TAB 默认效果表"]
FileCfg["EQ_TYPE_FILE eq_cfg_hw.bin"]
Online["EQ_TYPE_ONLINE 在线调试"]
end
Dec --> Node
Mic --> Node
Node --> EQ
EQ --> DRC
DRC --> DAC
Param --> EQ
Seg --> Cb
Cb --> HwEq
Fade --> HwEq
EQ --> HwEq
ModeTab --> Param
FileCfg --> Param
Online --> Param
架构说明:
- 音频流节点链(audio_stream):
struct audio_eq内嵌struct audio_stream_entry entry(见 audio_eq.h),EQ 以节点形式挂入解码输出流,数据按帧流入流出,与 DRC 等节点级联。 - 参数管理层:应用通过
audio_eq_param声明段数(max_nsection/nsection)、采样率(sr)、通道数、总增益(global_gain)与左右声道独立系数表(seg/seg_r);cb回调在需要更新系数时返回audio_eq_filter_info(即eq_coeff_info)。 - 淡入淡出:
audio_eq_fade记录当前系数表与目标系数表,按fade_step/q_fade_step/g_fade_step/f_fade_step步进逐步逼近目标值,避免切换瞬间的增益跳变。 - 配置来源:效果既可使用默认效果表(
EQ_TYPE_MODE_TAB,对应 7 种EQ_MODE预设),也可解析eq_cfg_hw.bin文件(EQ_TYPE_FILE)或通过在线调试(EQ_TYPE_ONLINE)实时下发,在线调试结果可保存到 VM(EQ_ONLINE_FILE_SAVE)。
核心模块实现分析
EQ 工作模式与类型
EQ 的效果预设由 EQ_MODE 枚举定义,共 7 种可切换模式(EQ_MODE_MAX 为边界标记):
typedef enum {
EQ_MODE_NORMAL = 0,
EQ_MODE_ROCK,
EQ_MODE_POP,
EQ_MODE_CLASSIC,
EQ_MODE_JAZZ,
EQ_MODE_COUNTRY,
EQ_MODE_CUSTOM,//自定义
EQ_MODE_MAX,
} EQ_MODE;
Source: audio_eq.h
系数(效果)来源则由 EQ_TYPE 区分,EQ_TYPE_FILE(0x01)表示从文件解析、EQ_TYPE_ONLINE 表示在线调试下发、EQ_TYPE_MODE_TAB 表示使用内置默认效果表——三者对应不同的 audio_eq_param 装配路径:
typedef enum {
EQ_TYPE_FILE = 0x01,
EQ_TYPE_ONLINE,
EQ_TYPE_MODE_TAB,
} EQ_TYPE;
Source: audio_eq.h
核心参数结构 audio_eq_param
audio_eq_open() 的输入完全由 struct audio_eq_param 驱动。该结构采用位域紧凑编码(u8 no_wait:1、u8 max_nsection:6 等),体现 SDK 对 RAM/代码体积的极致优化:
struct audio_eq_param {
u8 no_wait : 1; //是否使能异步eq, 1:使能 0:不使能
u8 max_nsection : 6;//最大的eq段数,根据使用填写,要小于等于EQ_SECTION_MAX
u8 nsection : 6; //实际需要的eq段数,需小于等于max_nsection
u8 out_32bit : 1; //是否支持32bit eq输出,仅在 no_wait 写1时,out_32bit 才能写1
u8 channels : 2; //通道数
u8 fade; //系数更新是否使能淡入,0:不使能,1:使能淡入
u8 f_fade_step; //滤波器中心截止频率淡入步进(10~200Hz)
float fade_step; //滤波器增益淡入步进(0.01f~1.0f)
float q_fade_step; //滤波器q值淡入步进(0.01f~1.0f)
float g_fade_step; //总增益淡入步进(0.01f~1.0f)
audio_eq_filter_cb cb;//获取eq系数的回调函数
u32 eq_name; //eq名字
u32 sr; //采样率,更根据当前数据实际采样率填写
float global_gain;
struct eq_seg_info *seg;
float global_gain_r;
struct eq_seg_info *seg_r;
void *priv; //私有指针
int (*output)(void *priv, void *data, u32 len);//异步eq输出回调,节点方式使用时,output 配NULL
void (*irq_callback)(void *priv);//总段回调函数,数据流激活
};
Source: audio_eq.h
设计要点:
no_wait(异步模式):置 1 时 EQ 以异步方式运行,数据不等待硬件处理完成即回调output,需要额外的run_buf/run_out_buf(见struct audio_eq_async);置 0 时同步处理。异步模式才允许out_32bit = 1。seg/seg_r左右声道分离:global_gain/seg对应左(或主)声道,global_gain_r/seg_r对应右声道,配合EQ_HW_LR_ALONE与EQ_LR_DIVIDE_EN可做四声道下左右效果拆分。eq_name唯一标识:如AEID_MUSIC_EQ、AEID_MUSIC_RL_EQ,用于区分多个 EQ 实例(如音乐 EQ 与 RL/RR 声道 EQ 并存)。
运行时状态 struct audio_eq
struct audio_eq 是 EQ 实例的完整运行状态:既持有硬件句柄(eq_ch)、当前/最大段数(cur_nsection/max_nsection)、采样率(sr)、增益(global_gain/global_gain_r),也持有运算前后系数表(eq_seg_tab→eq_coeff_tab)、淡入结构(fade/fade_r)、音频流入口(entry)以及静音计数(mute_cnt_l/r/max)。mute_cnt_* 用于在长时间静音后清除 EQ 内部滤波器记忆(mem),防止恢复播放时产生异常瞬态。
struct audio_eq {
void *eq_ch; //硬件eq句柄
u8 updata; //系数是否需要更新
u8 start; //eq start标识
u8 max_nsection; //eq最大段数
u8 cur_nsection; //当前eq段数
u8 check_hw_running; //检测到硬件正在运行时不等待其完成1:设置检查 0:不检查
u8 async_en;
u8 out_32bit;
u8 ch_num;
u32 sr; //采样率
u32 eq_name; //eq标识
u32 mask[2];
float global_gain;
float global_gain_r;
s16 *eq_out_buf;//同步方式,32bit输出,当out为NULL时,内部申请eq_out_buf
int out_buf_size;
int eq_out_points;
int eq_out_total;
struct audio_stream_entry entry; // 音频流入口
...
u32 mute_cnt_l; //左声道eq mem清除计数
u32 mute_cnt_r; //右声道eq mem清除计数
u32 mute_cnt_max; //记录最大点数,超过该点数,清eq mem
audio_eq_filter_cb cb; //系数回调
void *output_priv; //私有指针
int (*output)(void *priv, void *data, u32 len); //输出回调
struct eq_seg_info *eq_seg_tab; //运算前系数表
struct eq_seg_info *seg; //运算前系数表,由audio_eq_param初始化时指定
struct eq_seg_info *seg_r; //运算前系数表,由audio_eq_param初始化时指定
int *eq_coeff_tab; //运算后系数表
struct list_head hentry; //
const char *event_owner; //记录data_handler所处的任务
struct audio_eq_fade *fade;
struct audio_eq_fade *fade_r;
...
};
Source: audio_eq.h
event_owner 记录 data_handler 所在任务,配合 hentry 链表头把 EQ 实例挂入系统管理链表,便于统一的事件回调与任务切换调度——这是嵌入式多任务环境中保证 EQ 系数更新与数据流处理线程安全的关键设计。
高低音 / 超低音增强(high_bass)
超低音(ultra bass)与高音增强在 SDK 中由 struct high_bass 描述,AUDIO_EQ_HIGH = 2、AUDIO_EQ_BASS = 3 两个宏分别对应高低音段索引:
struct high_bass {
int freq; //频率写0, 内部会用默认125hz 和12khz
int gain; //增益范围 -12~12
};
Source: audio_eq.h
freq 填 0 时内部使用默认值:低频段 125 Hz(超低音)、高频段 12 kHz;gain 取值范围 -12~+12 dB。该功能由 EQ_HIGH_BASS_EN(BIT(6))使能,并可选 EQ_HIGH_BASS_FADE_EN(BIT(7))让高低音增益变化也走淡入淡出路径,防止低频大增益切换时的"噗噗"声。
频谱分析与变调/环绕模块定位
- 频谱(spectrum):SDK 提供
include_lib/media/spectrum/spectrum_eq.h,位于include_lib/media/spectrum/目录,用于频谱显示相关的 EQ 数据处理(本页采集阶段未读取该文件实现,具体接口请直接查看该头文件)。 - 变调(pitch)/ 环绕(surround):上层音效调节通常经由
effects_adj.h(audio_eq_drc_demo.c已包含此头)或独立 DSP 算法库接入音频流节点链。本页源码采集范围内未找到这两个算法的实现文件,不做未经验证的描述;接入方式与 EQ 节点一致——通过audio_stream_entry挂入节点链,在audio_eq之后、DAC 之前按需插入。
Core Flow
EQ 从打开、运行到系数更新的完整时序如下:
sequenceDiagram
participant App as 应用层(eq_sw_demo / music_eq_open)
participant EQ as audio_eq 模块
participant CB as filter_cb 系数回调
participant HW as hw_eq 硬件引擎
participant ST as audio_stream 节点链
App->>EQ: audio_eq_open(eq, param)
EQ->>EQ: 解析 param(段数/采样率/通道/淡入步进)
EQ->>ST: 注册 audio_stream_entry 节点
App->>EQ: audio_eq_start()
loop 数据流运行
ST->>EQ: 数据帧到达
EQ->>EQ: 检查 updata 系数更新标志
alt 需要更新系数
EQ->>CB: 调用 cb(eq, sr, &info) 获取系数
CB-->>EQ: eq_coeff_info 系数表
EQ->>EQ: 按 fade_step 步进逼近目标增益/q/频率
end
EQ->>HW: 下发系数并处理 PCM 数据
HW-->>EQ: 处理后数据
EQ->>ST: 输出到下一节点(DRC/DAC)
end
App->>EQ: audio_eq_set_samplerate / audio_eq_set_channel
App->>EQ: audio_dec_eq_close(eq)
关键控制流说明:
- 打开阶段:
audio_eq_open()根据param计算硬件段数与内存占用;若no_wait=0且未提供eq_out_buf,内部自动申请输出缓冲(out_buf_size/eq_out_points记录大小与点数)。 - 运行阶段:EQ 作为音频流节点被逐帧调用;
updata标志置位时触发系数刷新,刷新过程受fade控制,每帧只步进一小步,多帧后平滑到达目标值——这是消除"哒哒/爆破音"的核心机制。 - 模式切换:应用层
eq_mode_sw()切换 7 种默认系数表,eq_mode_set(EQ_MODE_CUSTOM)切换自定义表并更新总增益,切换全程由淡入淡出护航。 - 关闭阶段:
audio_dec_eq_close(eq)释放硬件句柄并从流节点链摘除,同时clock_remove(EQ_CLK)归还时钟资源(见下方使用示例)。
Usage Examples
以下示例全部取自 SDK 实际工程文件,展示 EQ 的典型接入方式。
打开音乐 EQ(同步模式 + 系数淡入)
music_eq_open() 演示了最常用的 EQ 装配方式:从 music_eq_tool 工具结构拷贝系数表,填充 audio_eq_param,使能淡入,然后通过 audio_dec_eq_open() 打开:
struct audio_eq *music_eq_open(u32 sample_rate, u8 ch_num)
{
#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE
memcpy(&fl_eq_parm_tmp, &music_eq_parm, sizeof(fl_eq_parm_tmp));
struct audio_eq_param parm = {0};
parm.channels = ch_num;
parm.no_wait = 0;
parm.cb = eq_get_filter_info;
parm.sr = sample_rate;
parm.eq_name = AEID_MUSIC_EQ;
parm.max_nsection = fl_eq_parm_tmp.seg_num;
parm.nsection = fl_eq_parm_tmp.seg_num;
parm.seg = fl_eq_parm_tmp.seg;
parm.global_gain = fl_eq_parm_tmp.global_gain;
parm.fade = 1;//使能系数淡入
parm.fade_step = 0.2f;//淡入步进(0.1f~1.0f)
parm.g_fade_step = 0.4f;//总增益步进
parm.f_fade_step = 100;//中心截止频率步进Hz
struct audio_eq *eq = audio_dec_eq_open(&parm);
clock_add(EQ_CLK);
return eq;
#endif //TCFG_EQ_ENABLE
return NULL;
}
Source: audio_eq_drc_demo.c
对应关闭接口会释放 EQ 并归还时钟:
void music_eq_close(struct audio_eq *eq)
{
#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE
if (eq) {
audio_dec_eq_close(eq);
clock_remove(EQ_CLK);
}
#endif/*TCFG_EQ_ENABLE*/
}
Source: audio_eq_drc_demo.c
左右声道独立 EQ(四声道拆分)
当 TCFG_EQ_DIVIDE_ENABLE 打开时,可再开一路 RL/RR 声道 EQ,使用独立系数表 rl_eq_parm 与标识 AEID_MUSIC_RL_EQ,避免左右声道效果互相干扰:
struct audio_eq *music_eq_rl_rr_open(u32 sample_rate, u8 ch_num)
{
#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE
memcpy(&rl_eq_parm_tmp, &rl_eq_parm, sizeof(rl_eq_parm_tmp));
struct audio_eq_param parm = {0};
parm.channels = ch_num;
parm.no_wait = 0;
parm.cb = eq_get_filter_info;
parm.sr = sample_rate;
parm.eq_name = AEID_MUSIC_RL_EQ;
parm.max_nsection = rl_eq_parm_tmp.seg_num;
parm.nsection = rl_eq_parm_tmp.seg_num;
parm.seg = rl_eq_parm_tmp.seg;
parm.global_gain = rl_eq_parm_tmp.global_gain;
parm.fade = 1;//增益更新差异大,会引入哒哒音,此处使能系数淡入
parm.fade_step = 0.2f;//淡入步进(0.1f~1.0f)
parm.g_fade_step = 0.4f;//总增益步进
struct audio_eq *eq = audio_dec_eq_open(&parm);
clock_add(EQ_CLK);
return eq;
#endif //TCFG_EQ_ENABLE
return NULL;
}
Source: audio_eq_drc_demo.c
模式切换与自定义系数更新
模式切换与动态更新是 UI/按键最常见的调用路径:
//系数切换
void eq_sw_demo()
{
eq_mode_sw();//7种默认系数切换
}
//获取当前eq系数表类型
void eq_mode_get_demo()
{
u8 mode ;
mode = eq_mode_get_cur();
}
//自定义系数表动态更新
void eq_update_demo()
{
eq_mode_set_custom_info(0, 200, 2);//第0段,200Hz中心截止频率,2db
eq_mode_set_custom_info(5, 2000, 2);//第5段,2000Hz中心截止频率,2db
set_global_gain(EQ_MODE_CUSTOM, -1);//-1表示 -1dB
eq_mode_set(EQ_MODE_CUSTOM);//设置系数、总增益更新
}
Source: audio_eq_drc_demo.c
eq_update_demo() 体现了自定义 EQ 的完整流程:先逐段设置中心频率与增益(eq_mode_set_custom_info(段号, 频率Hz, 增益dB)),再设置总增益(set_global_gain),最后调用 eq_mode_set(EQ_MODE_CUSTOM) 一次性提交——系数变化会经由 fade 机制平滑过渡。
Configuration Options
EQ/DRC 的编译期行为由 config_audio_eq_en 与 config_audio_drc_en 两个整型常量的位域控制,各 bit 定义见 eq_func_define.h:
config_audio_eq_en 功能位
| 位 | 宏名 | 说明 |
|---|---|---|
| BIT(0) | EQ_EN | EQ 模式总使能 |
| BIT(1) | EQ_SUPPORT_OLD_VER_EN | AC700N 兼容旧版本(0.7.1.0 / 0.7.1.1) |
| BIT(2) | EQ_LITE_VER_EN | 精简版 EQ 驱动:不支持异步、不支持默认效果切换,仅文件解析 |
| BIT(3) | EQ_ONLINE_EN | 在线调试模块使能 |
| BIT(4) | EQ_FILE_EN | 支持文件解析 EQ;关闭则只能使用默认效果表 |
| BIT(5) | EQ_FILE_SWITCH_EN | 支持 eq_cfg_hw.bin 文件切换更新效果 |
| BIT(6) | EQ_HIGH_BASS_EN | EQ 内部集成高低音(超低音/高音)接口使能 |
| BIT(7) | EQ_HIGH_BASS_FADE_EN | 高低音淡入淡出,配合 config_audio_eq_fade_step |
| BIT(8) | EQ_FILTER_COEFF_FADE_EN | 默认系数表切换/在线调试更新使用淡入淡出,避免杂音 |
| BIT(9) | EQ_FILTER_COEFF_LIMITER_ZERO_EN | 滤波器系数限幅归零 |
| BIT(10) | EQ_HW_UPDATE_COEFF_ONLY_EN | 有空闲段时只更新系数、不切换 |
| BIT(11) | EQ_HW_LR_ALONE | 左右声道分开处理(与 BIT(10) 同时使能/关闭) |
| BIT(12) | EQ_SUPPORT_32BIT_SYNC_EN | 支持同步方式 32bit EQ |
| BIT(13) | EQ_SUPPORT_MULIT_CHANNEL_EN | 多声道(3~8)支持(AC699N/AC700N) |
| BIT(14) | EQ_HW_CROSSOVER_TYPE0_EN | 硬件分频器,序列进序列出(需 BIT(13)) |
| BIT(15) | EQ_HW_CROSSOVER_TYPE1_EN | 分频器块出方式,仅单声道,增加内存 |
| BIT(16) | EQ_LR_DIVIDE_EN | EQ 左右声道效果拆分(四声道场景) |
| BIT(17) | EQ_ONLINE_FILE_SAVE | EQ 在线调试结果保存到 VM |
| BIT(18) | EQ_DRC_PROCESS_SPLIT | EQ/DRC 节点处理支持拆分 |
| BIT(20) | EQ_MDRC_V2_EN | MDRC V2 使能 |
对应快捷宏(如 config_audio_eq_online_en、config_filter_coeff_fade_en、config_high_bass_en、hw_eq_support_multi_channels 等)在 eq_func_define.h 中定义,业务代码应使用这些宏而非直接读位。
config_audio_drc_en 功能位
| 位 | 宏名 | 说明 |
|---|---|---|
| BIT(0) | DRC_EN | DRC 总使能 |
| BIT(1) | DRC_NBAND_MERGING_ASM_EN | 多带处理后多带合并使用汇编加速 |
| BIT(2) | DRC_NBAND_DIS | 关闭 DRC 多带 |
| BIT(3) | DRC_LIMITER_DIS | 关闭 DRC 限幅器 |
| BIT(4) | DRC_COMPRESSOF_DIS | 关闭 DRC 压缩器 |
| BIT(5) | WDRC_TYPE_EN | WDRC 使能 |
由 DRC_LIMITER_DIS 等反推的使能宏(config_drc_limiter_en、config_drc_nband_en、config_wdrc_en 等)同样定义于 eq_func_define.h。
运行期参数(struct audio_eq_param)
| 字段 | 类型 | 默认/范围 | 说明 |
|---|---|---|---|
no_wait | u8:1 | 0 | 1=异步 EQ,0=同步 |
max_nsection | u8:6 | ≤ EQ_SECTION_MAX | 最大 EQ 段数 |
nsection | u8:6 | ≤ max_nsection | 实际 EQ 段数 |
out_32bit | u8:1 | 0 | 32bit 输出,仅异步模式下可为 1 |
channels | u8:2 | 1~2(多声道平台可到 8) | 通道数 |
fade | u8 | 0 | 系数更新淡入使能 |
f_fade_step | u8 | — | 中心截止频率淡入步进(10~200Hz) |
fade_step | float | — | 滤波器增益淡入步进(0.01f~1.0f) |
q_fade_step | float | — | Q 值淡入步进 |
g_fade_step | float | — | 总增益淡入步进 |
cb | 回调 | 必填 | 获取 EQ 系数回调 |
eq_name | u32 | AEID_MUSIC_EQ 等 | EQ 实例标识 |
sr | u32 | 实际采样率 | 采样率 |
global_gain / global_gain_r | float | 0 | 左右声道总增益(dB) |
seg / seg_r | struct eq_seg_info* | — | 左右声道系数表 |
output | 回调 | NULL(节点方式) | 异步输出回调 |
API Reference
以下接口全部来自 audio_eq.h 的公开声明(头文件共 311 行,后续还有数据处理/关闭等接口,本页仅列出已读取并核实的部分)。
void audio_eq_init(void)
EQ 模块初始化,在系统启动阶段调用一次,建立 EQ 链表(hentry)与内部资源。
void audio_eq_init_new(int eq_section_num)
按指定段数初始化 EQ 模块,eq_section_num 为全局可用段数(受 EQ_SECTION_NUM / EQ_PRIV_SECTION_NUM 约束)。在需要动态分配段数的场景使用。
int audio_eq_open(struct audio_eq *eq, struct audio_eq_param *param)
打开一个 EQ 实例。
参数:
eq:调用方提供的struct audio_eq实例(可静态分配,也可通过audio_dec_eq_open内部申请)。param:配置参数,见struct audio_eq_param表。
返回: 成功返回 EQ 句柄(int),失败返回错误码。工程中常通过包装函数 audio_dec_eq_open(&parm) 打开。
说明: 打开时会按 max_nsection 计算硬件段与内存;channels 与 sr 必须在数据流入前设置正确,否则滤波系数错误。
void audio_eq_set_output_handle(struct audio_eq *eq, int (*output)(void *priv, void *data, u32 len), void *output_priv)
设置异步模式下的输出回调:output 收到处理后数据,output_priv 为私有上下文。节点方式(挂入 audio_stream)使用时无需设置。
void audio_eq_set_output_buf(struct audio_eq *eq, s16 *buf, u32 len)
同步模式设置输出缓冲:buf 为用户提供的缓冲区,len 为字节长度;不设置时 EQ 内部自动申请(见 eq_out_buf/out_buf_size)。
void audio_eq_set_samplerate(struct audio_eq *eq, int sr)
设置 EQ 采样率。采样率变化必须调用此接口(如解码器切歌、蓝牙 SBC/AAC 切换采样率),内部会据此重算滤波器系数。
void audio_eq_set_channel(struct audio_eq *eq, u8 channel)
设置 EQ 输入输出通道数。
int audio_eq_set_check_running(struct audio_eq *eq, u8 check_hw_running)
设置是否检查硬件运行状态:check_hw_running=1 时检测到硬件正在运行则不等其完成直接返回(仅异步 EQ 有效),用于避免调用线程被阻塞。
int audio_eq_set_info(struct audio_eq *eq, u8 channels, u8 out_32bit)
设置 EQ 信息:channels 通道数,out_32bit 使能 32bit 输出(1=32bit,0=16bit)。
int audio_eq_set_info_new(struct audio_eq *eq, u8 channels, u8 in_mode, u8 out_mode, u8 run_mode, u8 data_in_mode, u8 data_out_mode)
扩展版设置接口,支持更精细的数据格式控制:
channels:通道数;in_mode:输入格式,2=float,1=32bit,0=16bit;out_mode:输出格式,2=float,1=32bit,0=16bit;run_mode:运行模式,0=normal,1=mono,2=stereo;data_in_mode/data_out_mode:数据存放方式,0=块模式,1=序列模式。
返回: int,成功为 0。
int audio_eq_start(struct audio_eq *eq)
启动 EQ 处理。启动后数据流经该节点即开始滤波;系数更新(updata)在运行中生效。
Failure Modes, Edge Cases & Concurrency
- 系数突变导致的杂音:增益/Q 值/频率一次性大幅变化会产生"哒哒"或爆破音。源码级对策是
fade淡入淡出机制(fade_step/q_fade_step/g_fade_step/f_fade_step逐帧步进)以及EQ_FILTER_COEFF_FADE_EN(BIT(8))将模式切换与在线调试更新都纳入淡入路径。audio_eq_drc_demo.c中 RL/RR 声道 EQ 的注释明确说明"增益更新差异大,会引入哒哒音,此处使能系数淡入"。 - 静音后的滤波器记忆残留:长时间静音后恢复播放,IIR 滤波器内部状态(mem)可能残留旧数据产生瞬态。
struct audio_eq的mute_cnt_l/r与mute_cnt_max记录静音点数,超过阈值即清空 EQ mem。 - 异步模式下的等待阻塞:异步 EQ 若硬件忙,默认可能等待其完成,阻塞调用线程;
audio_eq_set_check_running()提供"检测到运行中即返回"的非阻塞选项,配合irq_callback在数据流激活时回调,适合低延迟场景。 - 采样率/通道不匹配:
sr与channels必须在audio_eq_open时与实际数据一致,后续变化必须调用audio_eq_set_samplerate/audio_eq_set_channel,否则滤波器系数按错误参数计算。 - 多任务并发:
event_owner记录数据处理器所在任务,EQ 系数更新(应用任务)与数据处理(音频任务)分属不同上下文;系数表采用"运算前表(eq_seg_tab/seg)→ 运算后表(eq_coeff_tab)"双表设计,更新先写运算前表、硬件按需取用,降低并发竞争窗口。 - 左右声道/四声道拆分:
EQ_HW_LR_ALONE(BIT(11))与EQ_LR_DIVIDE_EN(BIT(16))分别控制硬件左右独立处理与效果拆分;EQ_HW_UPDATE_COEFF_ONLY_EN(BIT(10))要求与 BIT(11) 同时使能/关闭,配置不一致会导致异常行为。 - 精简版限制:
EQ_LITE_VER_EN(BIT(2))下不支持异步与默认效果切换接口,仅支持文件解析——若业务代码误用eq_mode_sw()等接口将失效。
Performance & Operational Considerations
- 硬件引擎承担运算:滤波数值运算由
hw_eq(如asm/hw_eq.h)完成,软件只做参数管理与系数生成,CPU 占用低;多带 DRC 合并可开启DRC_NBAND_MERGING_ASM_EN(BIT(1))用汇编加速。 - 时钟管理:工程示例在打开 EQ 时
clock_add(EQ_CLK)、关闭时clock_remove(EQ_CLK),表明 EQ 运行会占用系统时钟资源,关闭时必须归还,否则影响低功耗。 - 内存权衡:
out_32bit输出、分频器块出方式(BIT(15))、多声道(BIT(13))都会显著增加内存占用,需按产品 RAM 预算裁剪。 - 在线调试:
EQ_ONLINE_EN+EQ_ONLINE_FILE_SAVE支持运行时调参并保存到 VM,量产联调时按需开启,正式发布可关闭以省资源。
Extension Points
- 自定义效果模式:
EQ_MODE_CUSTOM配合eq_mode_set_custom_info(段号, 频率Hz, 增益dB)与set_global_gain()可动态构造任意均衡曲线,无需重新编译。 - 文件效果表:
EQ_FILE_EN+EQ_FILE_SWITCH_EN支持通过eq_cfg_hw.bin文件热更新效果,适合产线或用户自定义。 - 多 EQ 实例并存:
eq_name(AEID_MUSIC_EQ/AEID_MUSIC_RL_EQ等)标识不同实例,可在音乐、通话、录音等场景分别挂载不同 EQ。 - 节点链扩展:EQ 以
audio_stream_entry节点形式存在,可在其前后插入自定义 DSP 节点(变调、环绕、声场等),复用同一套流式数据通路。 - 高低音独立调节:
high_bass结构(默认 125 Hz / 12 kHz,增益 ±12 dB)是超低音增强的标准入口,可替换为自定义频段实现。
Related Links
- audio_eq.h(EQ 核心 API 与数据结构)
- eq_func_define.h(EQ/DRC 功能开关位定义)
- audio_eq_drc_demo.c(EQ/DRC 使用示例)
- spectrum_eq.h(频谱分析模块入口)
- audio_eq_drc_apply.h(EQ/DRC 应用层接口)
- eq_config.h(EQ 配置与默认效果表)
- 音频流节点机制请参阅本目录其他页面(如音频流与解码章节);变调/环绕 DSP 算法若独立提供,请参考对应算法模块文档。