9.6. EQ

概述

本工程展示了 AC790NAC791N 的EQ工具使用示例:

    1. 如何使用EQ工具在线调试;

    1. 如何使用EQ导入/导出EQ配置文件;

    1. 如何使用动态DRC调试;

9.6.1. AC790N配置

9.6.1.1. 配置说明

  • 在app_config.h中,若使用在线EQ调试,配置如下

#define TCFG_EQ_ENABLE                            1     //支持EQ功能
#define TCFG_EQ_ONLINE_ENABLE                     1     //支持在线EQ调试
#define TCFG_LIMITER_ENABLE                       1     //限幅器

9.6.1.2. 操作说明

  • example: 以故事机工程作为例子说明。

  • 打开EQ调试工具 AC790N_配置工具入口: cpu/wl80/tools/AC791N_config_tool/AC790N_配置工具入口(Config Tools Entry).jlxproj ,选择“打开EQ工具”。

  • 1.在线模式

    在线调试通过串口进行与上位机通讯,选择好固件(AC790N), 配置好串口端口(默认使用uart1, 配置在相关板级里,默认波特率1000000,USBA的DMDP作为TX,RX),点击打开串口,工具最下面有信息栏提示 串口打开成功 ,之后勾选 在线EQ , 这个时候一边播歌一边调节EQ等参数。(注意: 只支持均衡器与限幅器, 如操作了其他地方导致通讯失败, 需重新勾选 在线EQ )

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 1000000,
    .port = PORTUSB_A,
    .tx_pin = IO_PORT_USB_DPA,
    .rx_pin = IO_PORT_USB_DMA,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART1_PLATFORM_DATA_END();
  • 2.读取文件模式

    读取存放在flash里面的bin文件, 以文件中的数据调整eq参数, 该文件存放在 tools\cfg\eq_cfg_hw.bin , 由在线调试EQ工具生成, 如图, 使用该模式, 需要改动如下:

#define TCFG_EQ_ONLINE_ENABLE                     0     //支持在线EQ调试
#define TCFG_EQ_FILE_ENABLE                       1     //从bin文件读取eq配置数据

注: 请注意导出的bin不一定直接存放到 tools\cfg\ 目录, 请多留意,有必要自行挪到对应地方。

  • 3.读取TABLE模式

    读取存放在代码段中的数据, 以该TABLE的数据为准, 该TABLE存放在 apps/common/config/include/eq_tab.h , 使用该模式, 需要改动如下:

#define TCFG_EQ_ONLINE_ENABLE                     0     //支持在线EQ调试
#define TCFG_EQ_FILE_ENABLE                       0     //从bin文件读取eq配置数据
三个模式的优先级:

在线模式 > 读取文件模式 > 读取TABLE模式

9.6.2. AC791N配置

9.6.2.1. 配置说明

  • example: 进入 demo_DevKitBoard/include/demo_config.h ,开启宏 USE_AUDIO_DEMO

  • 在app_config.h中,保证配置如下

#define TCFG_EQ_ENABLE                            1     //支持EQ功能
#define TCFG_EQ_ONLINE_ENABLE                     1     //支持在线EQ调试
#define TCFG_LIMITER_ENABLE                       1     //限幅器
#define TCFG_DRC_ENABLE                           TCFG_LIMITER_ENABLE //DRC使能
#define TCFG_COMM_TYPE                            TCFG_USB_COMM

#define USB_DEVICE_CLASS_CONFIG                     (CDC_CLASS)
  • 外部库依赖 libcompressor.alib_crossover_coff.amedia_app.alibdrc.a,

  • 以DEMO_EDR工程为例,工程需要添加文件 apps/common/audio_music/audio_eff_default_parm.capps/common/audio_music/audio_config.capps/common/audio_music/effects_adj.capps/common/audio_music/eq_config_new.capps/common/config/new_cfg_tool.c

  • 由于需要用到USB功能,则需继续添加 apps/common/system/device_mount.capps/common/usb 目录下所有文件,添加搜索目录 apps/common/usbapps/common/usb/deviceapps/common/usb/hostapps/common/usb/include/hostapps/common/usb/includeinclude_lib/driver/device/usbinclude_lib/driver/device/usb/deviceinclude_lib/driver/device/usb/host

9.6.2.2. 操作说明

  • 打开EQ调试工具 AC791N_配置工具入口: cpu/wl82/tools/AC791N_config_tool/AC791N_配置工具入口(Config Tools Entry).jlxproj ,选择“打开音效配置工具(新EQ工具)”, 然后选择“ATK”后点击确定。

  • 1.在线模式
    • 1.1 在线调试通过串口进行与上位机通讯,配置好串口端口(USB串行设备),波特率后(波特率可自行选择,SDK会自动适配,默认115200,类型为异步),点击打开(暂时不支持蓝牙串口模式),进行通讯,通讯成功以后会跳转到【音效调节】界面,进行EQ、DRC各模块参数配置。

    • 1.2 选择对应的音效,然后右键点击编辑(或者双击),若当前设备在播放音乐,能直接听到修改前后的差别,根据需要进行调节。
      • 注: 增加新模式, 模式流程图如下, 模式切换可以通过修改 app_config.h#define TCFG_EQ_MODE_CHOOSE 与加载对应的bin文件进行切换, bin文件在路径 tools\AC791N_config_tool 中, 若需要下次烧录能够直接烧录到小机上,则需要将名字修改成 eq_cfg_hw.bin ,然后替换到 tools\cfg 目录下(模式1下, 为4通道独立EQ, 独立DRC控制)

    • 1.3 进入 musicEQ 界面, 可以通过调节段点,或修改对应段点数据,进行频率、增益和高/中/低带通等的设置。

    • 1.4 进入 CrossOver 界面:可以设置低中分频点,也可调节分频器阶数。

    • 分频点处问题:由于分频点是低中DRC处理器的界限,所以在该频点处两个DRC的调节叠加会比较明显。

    • 1.5 进入 LowBandDRC HighBandDRC DRC 界面:可以使用限幅器、多带限幅器、压缩器和多带压缩器,例子可以查看快照。曲线可以通过双击增加节点,右键可以编辑节点位置信息。

    • 在include_lib/media/effects_adj.h中, 如下宏控制DRC使能与否(v1.2.0以后, 该宏移去 app_config.h , 并且增加模式二, EQ/DRC可以控制左右前后声道是否共用与独立处理, 若共用则默认使用左/前声道的EQ/DRC)

#if (TCFG_EQ_MODE_CHOOSE == 0)
#define TCFG_AUDIO_MDRC_ENABLE      2       //0:不使能低中DRC 1: 多带分频器使能 2: 多带分频后,再做一次全带处理使能
#define TCFG_LAST_WHOLE_DRC_ENABLE  1       //0:不使能最后的全带DRC; 1:使能
#elif (TCFG_EQ_MODE_CHOOSE == 1)
#define TCFG_EQ_DIVIDE_ENABLE                                       1               //0:前后通道共用EQ/DRC  1:支持EQ/DRC前后声道独立处理
#define TCFG_EQ_SPILT_ENABLE                                        1               //0:左右通道共用EQ  1:支持EQ左右声道独立处理
#define TCFG_DRC_SPILT_ENABLE                                       1               //0:左右通道共用DRC 1:支持DRC左右声道独立处理
#endif

  • bypass:勾选后该DRC不起作用。

  • 启动时间:输入幅值在曲线以上时,启动DRC到声音幅值稳定所需时间。

  • 释放时间:输入幅值在曲线以下时,关闭DRC到声音幅值稳定所需时间。

  • RMS时间:detect mode在RMS模式下有效,算法一小段数据的采样范围(包含多个采样点),用于求平均值,以一个数据代表这段时间的数据。

  • 输入增益:进入该DRC前的一个数字gain增益。

  • 输出增益:退出该DRC后的一个数字gain增益。

  • detect mode:

    RMS算法:取多个采样点的平均声音幅值作为当前RMS时间的平均幅值,低频有效减少声音抖动,高频效果不明显(占用算力大)

    PEAK算法:取多个采样点,取到的采样点都加入算法运算。

    precision和precision+:precision精度比precision+差点,但是运算速度是precision+的一倍。

  • 1.6 修改完后,点击”保存配置“,生成“eq_cfg_hw.bin”配置文件,将该文件放置 cpu/wl82/tools/cfg 目录下,重新烧录的时候会将该文件烧写进设备,也可以点击 加载配置文件 加载文件里的配置。设备开机时,首先会读取加载烧录进设备的EQ文件,当打开在线EQ调试,会加载当前工具的配置,可以点击左上角 将配置写入设备 覆盖设备里旧的配置,也可以点击 从设备中读取 按钮读取设备配置。

    1. SDK代码需要在请求打开解码器时需要加上以下参数才会有EQ效果

#if TCFG_EQ_ENABLE
#if defined EQ_CORE_V1
    req.dec.attr |= AUDIO_ATTR_EQ_EN;
#if TCFG_LIMITER_ENABLE
    req.dec.attr |= AUDIO_ATTR_EQ32BIT_EN;
#endif
#if TCFG_DRC_ENABLE
    req.dec.attr |= AUDIO_ATTR_DRC_EN;
#endif
#else
    struct eq_s_attr eq_attr = {0};
    extern void set_eq_req_attr_parm(struct eq_s_attr * eq_attr);
    set_eq_req_attr_parm(&eq_attr);
    req.dec.eq_attr = &eq_attr;
    req.dec.eq_hdl = __this->eq_hdl;
#endif
#endif

9.6.2.3. 常见问题

Note

  • 在线调试发送命令一直提示超时,请检查USB/串口 IO是否被其他模块占用,检查杜邦线连接是否正常

9.6.2.4. API参考

Defines

EQ_SECTION_MAX

Enums

enum [anonymous]

EQ运行模式

Values:

enumerator NORMAL

正常模式

enumerator MONO

单声道模式

enumerator STEREO

立体声模式

enum [anonymous]

输出数据类型

Values:

enumerator DATO_SHORT

short短整型

enumerator DATO_INT

int整型

enumerator DATO_FLOAT

float浮点型

enum [anonymous]

输入数据类型

Values:

enumerator DATI_SHORT

short短整型

enumerator DATI_INT

int整型

enumerator DATI_FLOAT

float浮点型

enum [anonymous]

输入数据存放模式

Values:

enumerator BLOCK_DAT_IN

块模式,例如输入数据是2通道,先存放完第1通道的所有数据,再存放第2通道的所有数据

enumerator SEQUENCE_DAT_IN

序列模式,例如输入数据是2通道,先存放第1通道的第一个数据,再存放第2个通道的第一个数据,以此类推

enum [anonymous]

输出数据存放模式

Values:

enumerator BLOCK_DAT_OUT

块模式,例如输出数据是2通道,先存放完第1通道的所有数据,再存放第2通道的所有数据

enumerator SEQUENCE_DAT_OUT

序列模式,例如输入数据是2通道,先存放第1通道的第一个数据,再存放第2个通道的第一个数据,以此类推

enum EQ_IIR_TYPE

eq IIR type滤波器类型

Values:

enumerator EQ_IIR_TYPE_HIGH_PASS

高通滤波器

enumerator EQ_IIR_TYPE_LOW_PASS

低通滤波器

enumerator EQ_IIR_TYPE_BAND_PASS

带通滤波器

enumerator EQ_IIR_TYPE_HIGH_SHELF

高架滤波器

enumerator EQ_IIR_TYPE_LOW_SHELF

低架滤波器

Functions

void design_lp(int fc, int fs, float quality_factor, float *coeff)

低通滤波器

Parameters
  • fc:中心截止频率

  • fs:采样率

  • quality_factor:q值

  • coeff:计算后,系数输出地址

void design_hp(int fc, int fs, float quality_factor, float *coeff)

高通滤波器

Parameters
  • fc:中心截止频率

  • fs:采样率

  • quality_factor:q值

  • coeff:计算后,系数输出地址

void design_pe(int fc, int fs, float gain, float quality_factor, float *coeff)

带通滤波器

Parameters
  • fc:中心截止频率

  • fs:采样率

  • gain:增益

  • quality_factor:q值

  • coeff:计算后,系数输出地址

void design_ls(int fc, int fs, float gain, float quality_factor, float *coeff)

低频搁架式滤波器

Parameters
  • fc:中心截止频率

  • fs:采样率

  • gain:增益

  • quality_factor:q值

  • coeff:计算后,系数输出地址

void design_hs(int fc, int fs, float gain, float quality_factor, float *coeff)

高频搁架式滤波器

Parameters
  • fc:中心截止频率

  • fs:采样率

  • gain:增益

  • quality_factor:q值

  • coeff:计算后,系数输出地址

int eq_stable_check(float *coeff)

滤波器系数检查

Parameters

coeff:滤波器系数

Returns

0:成功 -1:失败

float eq_db2mag(float x)
void eq_get_AllpassCoeff(void *Coeff)

获取直通的滤波器系数

Parameters

coeff:滤波器系数

int eq_seg_design(struct eq_seg_info *seg, int sample_rate, float *coeff)

滤波器计算管理函数

Parameters
  • seg:提供给滤波器的基本信息

  • sample_rate:采样率

  • coeff:计算后,系数输出地址

Returns

true:成功 false:失败

int audio_hw_eq_init(struct hw_eq *eq, u32 eq_section_num)

EQ初始化

Parameters

eq:句柄

Returns

0:成功 -1:失败

int audio_hw_eq_ch_open(struct hw_eq_ch *ch, struct hw_eq *eq)

打开一个通道

Parameters
  • ch:通道句柄

  • eq:句柄

Returns

0:成功 -1:失败

int audio_hw_eq_ch_set_handler(struct hw_eq_ch *ch, struct hw_eq_handler *handler)

设置回调接口

Parameters
  • ch:通道句柄

  • handler:回调的句柄

Returns

0:成功 -1:失败

int audio_hw_eq_ch_set_info(struct hw_eq_ch *ch, u8 channels, u8 out_32bit)

设置通道基础信息

Parameters
  • ch:通道句柄

  • channels:通道数

  • out_32bit:是否输出32bit位宽数据 – 1:是 0:16bit位宽

Returns

0:成功 -1:失败

int audio_hw_eq_ch_set_coeff(struct hw_eq_ch *ch, struct eq_coeff_info *info)

设置硬件转换系数

Parameters
  • ch:通道句柄

  • info:系数、增益等信息

Returns

0:成功 -1:失败

int audio_hw_eq_ch_start(struct hw_eq_ch *ch, void *input, void *output, int len)

启动一次转换

Parameters
  • ch:eq句柄

  • input:输入数据地址

  • output:输出数据地址

  • len:输入数据长度

Returns

输出数据的长度

int audio_hw_eq_ch_close(struct hw_eq_ch *ch)

关闭一个通道

Parameters

ch:eq句柄

Returns

0:成功 -1:失败

int audio_hw_eq_flush_out(struct hw_eq *eq)

挤出eq中的数据

Parameters

eq:eq句柄

Returns

0:成功 -1:失败

int audio_hw_eq_is_running(struct hw_eq *eq)

获取eq是否正在运行状态

Parameters

eq:eq句柄

Returns

true or false

struct eq_seg_info
#include <eq.h>

eq段信息

Public Members

u16 index

eq段序号

u16 iir_type

滤波器类型EQ_IIR_TYPE

int freq

中心截止频率

float gain

增益(-12 ~12 db)

float q

q值(0.3~30)

struct eq_coeff_info
#include <eq.h>

eq系数信息

Public Members

u16 nsection

eq段数

u16 no_coeff

不是滤波系数

float *L_coeff

左声道滤波器系数地址

float *R_coeff

右声道滤波器系数地址

float L_gain

左声道总增益(-20~20db)

float R_gain

右声道总增益(-20~20db)

float *N_coeff[8]

滤波器系数

float N_gain[8]

滤波器增益

struct hw_eq
#include <eq.h>

硬件eq

Public Members

struct list_head head

链表头

OS_MUTEX mutex

互斥锁

struct hw_eq_ch *cur_ch

当前需要处理的eq通道

struct hw_eq_handler
#include <eq.h>

硬件eq句柄

Public Members

int (*eq_probe)(struct hw_eq_ch*)

eq驱动内前处理

int (*eq_output)(struct hw_eq_ch*, s16*, u16)

eq驱动内输出处理回调

int (*eq_post)(struct hw_eq_ch*)

eq驱动内处理后回调

int (*eq_input)(struct hw_eq_ch*, void**, void**)

eq驱动内输入处理回调

struct hw_eq_ch
#include <eq.h>

硬件eq通道信息

Public Members

unsigned int updata_coeff_only

只更新参数,不更新中间数据

unsigned int no_wait

是否是异步eq处理 0:同步的eq 1:异步的eq

unsigned int channels

输入通道数

unsigned int SHI

eq运算输出数据左移位数控制,记录

unsigned int countL

eq运算输出数据左移位数控制临时记录

unsigned int stage

eq运算开始位置标识

unsigned int nsection

eq段数

unsigned int no_coeff

非滤波系数

unsigned int reserve
volatile unsigned char updata

更新参数以及中间数据

volatile unsigned char active

已启动eq处理 1:busy 0:处理结束

volatile unsigned char need_run

多eq同时使用时,未启动成功的eq,是否需要重新唤醒处理 1:需要 0:否

unsigned short run_mode

0按照输入的数据排布方式 ,输出数据 1:单入多出, 2:立体声入多出

unsigned short in_mode

输入数据的位宽 0:short 1:int 2:float

unsigned short out_32bit

输出数据的位宽 0:short 1:int 2:float

unsigned short out_channels

输出通道数

unsigned short data_in_mode

输入数据存放模式

unsigned short data_out_mode

输出数据存放模式

float *L_coeff

输入给左声道系数地址

float *R_coeff

输入给右声道系数地址

float L_gain

输入给左声道总增益(-20~20)

float R_gain

输入给右声道总增益(-20~20)

float *N_coeff[8]
float N_gain[8]
float *eq_LRmem

eq系数地址(包含运算的中间数据)

int ram_inbuf_size

内部ram输入buf大小

int ram_outbuf_size

内部ram输出buf大小

s16 *ram_inbuf

内部ram输入buf地址

s16 *ram_outbuf

内部ram输出buf地址

s16 *out_buf

输出buf地址

s16 *tmp_outbuf
int tmp_outbuf_size
s16 *in_buf

输入buf地址

int in_len

输入数据长度

void *priv

保存eq管理层的句柄

OS_SEM sem

信号量,用于通知驱动,当前一次处理完成

struct list_head entry

当前eq通道的节点

struct hw_eq *eq

底层eq操作句柄

const struct hw_eq_handler *eq_handler

q操作的相关回调函数句柄

void *irq_priv

eq管理层传入的私有指针

void (*irq_callback)(void *priv)

需要eq中断执行的回调函数