339 lines
13 KiB
C
339 lines
13 KiB
C
#ifndef _HW_EQ_H_
|
||
#define _HW_EQ_H_
|
||
|
||
#include "generic/typedef.h"
|
||
#include "generic/list.h"
|
||
#include "os/os_api.h"
|
||
|
||
#define EQ_SECTION_MAX 20
|
||
|
||
/**
|
||
* @brief EQ运行模式
|
||
*/
|
||
enum {
|
||
NORMAL = 0, /*!< 正常模式 */
|
||
MONO, /*!< 单声道模式 */
|
||
STEREO, /*!< 立体声模式 */
|
||
};
|
||
|
||
/**
|
||
* @brief 输出数据类型
|
||
*/
|
||
enum {
|
||
DATO_SHORT = 0, /*!< short短整型 */
|
||
DATO_INT, /*!< int整型 */
|
||
DATO_FLOAT, /*!< float浮点型 */
|
||
};
|
||
|
||
/**
|
||
* @brief 输入数据类型
|
||
*/
|
||
enum {
|
||
DATI_SHORT = 0, /*!< short短整型 */
|
||
DATI_INT, /*!< int整型 */
|
||
DATI_FLOAT, /*!< float浮点型 */
|
||
};
|
||
|
||
/**
|
||
* @brief 输入数据存放模式
|
||
*/
|
||
enum {
|
||
BLOCK_DAT_IN = 0, /*!< 块模式,例如输入数据是2通道,先存放完第1通道的所有数据,再存放第2通道的所有数据 */
|
||
SEQUENCE_DAT_IN, /*!< 序列模式,例如输入数据是2通道,先存放第1通道的第一个数据,再存放第2个通道的第一个数据,以此类推 */
|
||
};
|
||
|
||
/**
|
||
* @brief 输出数据存放模式
|
||
*/
|
||
enum {
|
||
BLOCK_DAT_OUT = 0, /*!< 块模式,例如输出数据是2通道,先存放完第1通道的所有数据,再存放第2通道的所有数据 */
|
||
SEQUENCE_DAT_OUT, /*!< 序列模式,例如输入数据是2通道,先存放第1通道的第一个数据,再存放第2个通道的第一个数据,以此类推 */
|
||
};
|
||
|
||
|
||
/**
|
||
* @brief eq IIR type滤波器类型
|
||
*/
|
||
typedef enum {
|
||
EQ_IIR_TYPE_HIGH_PASS = 0x00, /*!< 高通滤波器 */
|
||
EQ_IIR_TYPE_LOW_PASS, /*!< 低通滤波器 */
|
||
EQ_IIR_TYPE_BAND_PASS, /*!< 带通滤波器 */
|
||
EQ_IIR_TYPE_HIGH_SHELF, /*!< 高架滤波器 */
|
||
EQ_IIR_TYPE_LOW_SHELF, /*!< 低架滤波器 */
|
||
} EQ_IIR_TYPE;
|
||
|
||
/**
|
||
* @brief eq段信息
|
||
*/
|
||
struct eq_seg_info {
|
||
u16 index; /*!< eq段序号 */
|
||
u16 iir_type; /*!< 滤波器类型EQ_IIR_TYPE */
|
||
int freq; /*!< 中心截止频率 */
|
||
float gain; /*!< 增益(-12 ~12 db) */
|
||
float q; /*!< q值(0.3~30) */
|
||
};
|
||
|
||
/**
|
||
* @brief eq系数信息
|
||
*/
|
||
struct eq_coeff_info {
|
||
u16 nsection : 6; /*!< eq段数 */
|
||
u16 no_coeff : 1; /*!< 不是滤波系数 */
|
||
#ifdef CONFIG_EQ_NO_USE_COEFF_TABLE
|
||
u32 sr; /*!< 采样率 */
|
||
#endif
|
||
float *L_coeff; /*!< 左声道滤波器系数地址 */
|
||
float *R_coeff; /*!< 右声道滤波器系数地址 */
|
||
float L_gain; /*!< 左声道总增益(-20~20db) */
|
||
float R_gain; /*!< 右声道总增益(-20~20db)*/
|
||
float *N_coeff[8]; /*!< 滤波器系数 */
|
||
float N_gain[8]; /*!< 滤波器增益 */
|
||
};
|
||
|
||
/// \cond DO_NOT_DOCUMENT
|
||
struct hw_eq_ch;
|
||
/// \endcond
|
||
|
||
/**
|
||
* @brief 硬件eq
|
||
*/
|
||
struct hw_eq {
|
||
struct list_head head; /*!< 链表头 */
|
||
OS_MUTEX mutex; /*!< 互斥锁 */
|
||
struct hw_eq_ch *cur_ch; /*!< 当前需要处理的eq通道 */
|
||
};
|
||
|
||
/// \cond DO_NOT_DOCUMENT
|
||
enum {
|
||
HW_EQ_CMD_CLEAR_MEM = 0xffffff00,
|
||
HW_EQ_CMD_CLEAR_MEM_L,
|
||
HW_EQ_CMD_CLEAR_MEM_R,
|
||
};
|
||
/// \endcond
|
||
|
||
/**
|
||
* @brief 硬件eq句柄
|
||
*/
|
||
struct hw_eq_handler {
|
||
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驱动内输入处理回调 */
|
||
};
|
||
|
||
// *INDENT-OFF*
|
||
/**
|
||
* @brief 硬件eq通道信息
|
||
*/
|
||
struct hw_eq_ch {
|
||
unsigned int updata_coeff_only : 1; /*!< 只更新参数,不更新中间数据 */
|
||
unsigned int no_wait : 1; /*!< 是否是异步eq处理 0:同步的eq 1:异步的eq */
|
||
unsigned int channels : 4; /*!< 输入通道数 */
|
||
unsigned int SHI : 4; /*!< eq运算输出数据左移位数控制,记录*/
|
||
unsigned int countL : 4; /*!< eq运算输出数据左移位数控制临时记录 */
|
||
unsigned int stage : 9; /*!< eq运算开始位置标识 */
|
||
unsigned int nsection : 6; /*!< eq段数 */
|
||
unsigned int no_coeff : 1; /*!< 非滤波系数 */
|
||
unsigned int reserve : 2;
|
||
|
||
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: 2; /*!< 0按照输入的数据排布方式 ,输出数据 1:单入多出, 2:立体声入多出 */
|
||
unsigned short in_mode : 2; /*!< 输入数据的位宽 0:short 1:int 2:float */
|
||
unsigned short out_32bit : 2; /*!< 输出数据的位宽 0:short 1:int 2:float */
|
||
unsigned short out_channels: 4; /*!< 输出通道数 */
|
||
unsigned short data_in_mode: 1; /*!< 输入数据存放模式 */
|
||
unsigned short data_out_mode: 1; /*!< 输出数据存放模式*/
|
||
#ifdef CONFIG_EQ_NO_USE_COEFF_TABLE
|
||
u32 sr; /*!< 采样率 */
|
||
#endif
|
||
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; //临时输出buf地址, 目的为了规避DMA读的慢导致越界问题
|
||
int tmp_outbuf_size; //临时输出buf地址大小
|
||
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中断执行的回调函数 */
|
||
};
|
||
|
||
//系数计算子函数
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 低通滤波器
|
||
@param fc:中心截止频率
|
||
@param fs:采样率
|
||
@param quality_factor:q值
|
||
@param coeff:计算后,系数输出地址
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void design_lp(int fc, int fs, float quality_factor, float *coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 高通滤波器
|
||
@param fc:中心截止频率
|
||
@param fs:采样率
|
||
@param quality_factor:q值
|
||
@param coeff:计算后,系数输出地址
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void design_hp(int fc, int fs, float quality_factor, float *coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 带通滤波器
|
||
@param fc:中心截止频率
|
||
@param fs:采样率
|
||
@param gain:增益
|
||
@param quality_factor:q值
|
||
@param coeff:计算后,系数输出地址
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void design_pe(int fc, int fs, float gain, float quality_factor, float *coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 低频搁架式滤波器
|
||
@param fc:中心截止频率
|
||
@param fs:采样率
|
||
@param gain:增益
|
||
@param quality_factor:q值
|
||
@param coeff:计算后,系数输出地址
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void design_ls(int fc, int fs, float gain, float quality_factor, float *coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 高频搁架式滤波器
|
||
@param fc:中心截止频率
|
||
@param fs:采样率
|
||
@param gain:增益
|
||
@param quality_factor:q值
|
||
@param coeff:计算后,系数输出地址
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void design_hs(int fc, int fs, float gain, float quality_factor, float *coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 滤波器系数检查
|
||
@param coeff:滤波器系数
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int eq_stable_check(float *coeff);
|
||
|
||
float eq_db2mag(float x);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 获取直通的滤波器系数
|
||
@param coeff:滤波器系数
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void eq_get_AllpassCoeff(void *Coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 滤波器计算管理函数
|
||
@param seg:提供给滤波器的基本信息
|
||
@param sample_rate:采样率
|
||
@param coeff:计算后,系数输出地址
|
||
@return true:成功 false:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int eq_seg_design(struct eq_seg_info *seg, int sample_rate, float *coeff);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief EQ初始化
|
||
@param eq:句柄
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_init(struct hw_eq *eq, u32 eq_section_num);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 打开一个通道
|
||
@param ch:通道句柄
|
||
@param eq:句柄
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_ch_open(struct hw_eq_ch *ch, struct hw_eq *eq);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置回调接口
|
||
@param ch:通道句柄
|
||
@param handler:回调的句柄
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_ch_set_handler(struct hw_eq_ch *ch, struct hw_eq_handler *handler);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置通道基础信息
|
||
@param ch:通道句柄
|
||
@param channels:通道数
|
||
@param out_32bit:是否输出32bit位宽数据 1:是 0:16bit位宽
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_ch_set_info(struct hw_eq_ch *ch, u8 channels, u8 out_32bit);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置硬件转换系数
|
||
@param ch:通道句柄
|
||
@param info:系数、增益等信息
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_ch_set_coeff(struct hw_eq_ch *ch, struct eq_coeff_info *info);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 启动一次转换
|
||
@param ch:eq句柄
|
||
@param input:输入数据地址
|
||
@param output:输出数据地址
|
||
@param len:输入数据长度
|
||
@return 输出数据的长度
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_ch_start(struct hw_eq_ch *ch, void *input, void *output, int len);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 关闭一个通道
|
||
@param ch:eq句柄
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_ch_close(struct hw_eq_ch *ch);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 挤出eq中的数据
|
||
@param eq:eq句柄
|
||
@return 0:成功 -1:失败
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_flush_out(struct hw_eq *eq);
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 获取eq是否正在运行状态
|
||
@param eq:eq句柄
|
||
@return true or false
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int audio_hw_eq_is_running(struct hw_eq *eq);
|
||
|
||
#endif
|
||
|