973 lines
32 KiB
C
973 lines
32 KiB
C
|
||
/*******************************************************************
|
||
ANC 多滤波器场景
|
||
*******************************************************************/
|
||
#include "audio_anc.h"
|
||
#include "audio_anc_mult_scene.h"
|
||
|
||
|
||
#if ANC_MULT_ORDER_ENABLE
|
||
|
||
#if 0
|
||
#define anc_mult_log printf
|
||
#else
|
||
#define anc_mult_log(...)
|
||
#endif/*log_en*/
|
||
|
||
//ANC重组数据流程测试
|
||
#define ANC_MULT_DATA_TEST 0 //1 测试读取 ;2 测试重组
|
||
|
||
typedef struct {
|
||
u8 yorder;
|
||
anc_mult_gain_t *gains; //gains, 复用flash位置
|
||
anc_fr_t *fr; //滤波器,复用flash位置
|
||
} anc_mult_param_t;
|
||
|
||
typedef struct {
|
||
struct list_head entry;
|
||
u16 scene_id; //场景号
|
||
anc_mult_param_t lff;
|
||
anc_mult_param_t lfb;
|
||
anc_mult_param_t ltrans;
|
||
anc_mult_param_t lcmp;
|
||
anc_mult_param_t rff;
|
||
anc_mult_param_t rfb;
|
||
anc_mult_param_t rtrans;
|
||
anc_mult_param_t rcmp;
|
||
} anc_mult_bulk_t;
|
||
|
||
typedef struct {
|
||
struct list_head head;
|
||
audio_anc_t *param;
|
||
u16 cur_scene;
|
||
double *lff_coeff;
|
||
double *lfb_coeff;
|
||
double *lcmp_coeff;
|
||
double *ltrans_coeff;
|
||
double *rff_coeff;
|
||
double *rfb_coeff;
|
||
double *rcmp_coeff;
|
||
double *rtrans_coeff;
|
||
} anc_mult_hdl_t;
|
||
|
||
//场景数据子结构;
|
||
typedef struct {
|
||
u16 scene_id;
|
||
u16 cnt;
|
||
u8 dat[0]; //小心访问非对齐异常
|
||
} anc_mult_scene_file_t;
|
||
|
||
/*
|
||
包含关系
|
||
anc_coeff_t
|
||
->anc_mult_scene_file_t
|
||
->struct anc_param_head_t
|
||
->data;
|
||
*/
|
||
anc_mult_hdl_t *mult_hdl = NULL;
|
||
|
||
static anc_coeff_t *anc_mult_cfg_test(int *db_len);
|
||
static anc_coeff_t *anc_mult_cfg_part_test(int *db_len);
|
||
|
||
|
||
//多滤波器数据填充
|
||
static int anc_mult_scene_param_read(struct list_head *list, u8 *dat)
|
||
{
|
||
int i = 0;
|
||
int file_offset = 0;
|
||
u8 *temp_dat;
|
||
anc_mult_scene_file_t *file = (anc_mult_scene_file_t *)dat;
|
||
anc_mult_scene_file_t file_align;
|
||
memcpy((u8 *)&file_align, (u8 *)file, sizeof(anc_mult_scene_file_t));
|
||
struct anc_param_head_t id_head[file_align.cnt];
|
||
|
||
anc_mult_bulk_t *bulk = zalloc(sizeof(anc_mult_bulk_t));
|
||
|
||
bulk->scene_id = file_align.scene_id;
|
||
|
||
/* put_buf(db_coeff->dat, db_coeff->cnt * 6); */
|
||
anc_mult_log("anc_mult_scene_id %d\n", file_align.scene_id);
|
||
temp_dat = file->dat + (file_align.cnt * 6);
|
||
for (i = 0; i < file_align.cnt; i++) {
|
||
memcpy(&id_head[i], file->dat + (i * 6), 6); //结构体为8字节,这里只有6字节
|
||
anc_mult_log("id:0X%x, offset:%d,len:%d\n", id_head[i].id, id_head[i].offset, id_head[i].len);
|
||
switch (id_head[i].id) {
|
||
case ANC_L_FF_FGQ:
|
||
anc_mult_log("ANC_L_FF_FGQ\n");
|
||
bulk->lff.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->lff.yorder = id_head[i].len / 13;
|
||
break;
|
||
case ANC_L_FB_FGQ:
|
||
anc_mult_log("ANC_L_FB_FGQ\n");
|
||
bulk->lfb.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->lfb.yorder = id_head[i].len / 13;
|
||
break;
|
||
case ANC_L_CMP_FGQ:
|
||
anc_mult_log("ANC_L_CMP_FGQ\n");
|
||
bulk->lcmp.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->lcmp.yorder = id_head[i].len / 13;
|
||
break;
|
||
case ANC_L_TRANS_FGQ:
|
||
anc_mult_log("ANC_L_TRANS_FGQ\n");
|
||
bulk->ltrans.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->ltrans.yorder = id_head[i].len / 13;
|
||
break;
|
||
|
||
case ANC_L_FF_PARM:
|
||
anc_mult_log("ANC_L_FF_PARM\n");
|
||
bulk->lff.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_L_FB_PARM:
|
||
anc_mult_log("ANC_L_FB_PARM\n");
|
||
bulk->lfb.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_L_CMP_PARM:
|
||
anc_mult_log("ANC_L_CMP_PARM\n");
|
||
bulk->lcmp.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_L_TRANS_PARM:
|
||
anc_mult_log("ANC_L_TRANS_PARM\n");
|
||
bulk->ltrans.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
|
||
case ANC_R_FF_FGQ:
|
||
anc_mult_log("ANC_R_FF_FGQ\n");
|
||
bulk->rff.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->rff.yorder = id_head[i].len / 13;
|
||
break;
|
||
case ANC_R_FB_FGQ:
|
||
anc_mult_log("ANC_R_FB_FGQ\n");
|
||
bulk->rfb.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->rfb.yorder = id_head[i].len / 13;
|
||
break;
|
||
case ANC_R_CMP_FGQ:
|
||
anc_mult_log("ANC_R_CMP_FGQ\n");
|
||
bulk->rcmp.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->rcmp.yorder = id_head[i].len / 13;
|
||
break;
|
||
case ANC_R_TRANS_FGQ:
|
||
anc_mult_log("ANC_R_TRANS_FGQ\n");
|
||
bulk->rtrans.fr = (anc_fr_t *)(temp_dat + id_head[i].offset);
|
||
bulk->rtrans.yorder = id_head[i].len / 13;
|
||
break;
|
||
|
||
case ANC_R_FF_PARM:
|
||
anc_mult_log("ANC_R_FF_PARM\n");
|
||
bulk->rff.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_R_FB_PARM:
|
||
anc_mult_log("ANC_R_FB_PARM\n");
|
||
bulk->rfb.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_R_CMP_PARM:
|
||
anc_mult_log("ANC_R_CMP_PARM\n");
|
||
bulk->rcmp.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_R_TRANS_PARM:
|
||
anc_mult_log("ANC_R_TRANS_PARM\n");
|
||
bulk->rtrans.gains = (anc_mult_gain_t *)(temp_dat + id_head[i].offset);
|
||
break;
|
||
case ANC_L_ADAP_GOLD_CURVE:
|
||
case ANC_R_ADAP_GOLD_CURVE:
|
||
if (mult_hdl->param->adaptive) {
|
||
anc_mult_log("ANC_L/R_ADAP_GOLD_CURVE\n");
|
||
mult_hdl->param->adaptive->ref_ff_curve = temp_dat + id_head[i].offset;
|
||
mult_hdl->param->adaptive->ref_ff_curve_len = id_head[i].len;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
/* put_buf((u8 *)(temp_dat + id_head[i].offset), id_head[i].len); */
|
||
}
|
||
|
||
//加入链表
|
||
list_add_tail(&bulk->entry, list);
|
||
//下一个场景的数据偏移量
|
||
file_offset = ((u32)temp_dat - (u32)dat) + id_head[file_align.cnt - 1].offset + id_head[file_align.cnt - 1].len;
|
||
anc_mult_log("next scene offset %d\n", file_offset);
|
||
return file_offset;
|
||
}
|
||
|
||
static int anc_mult_scene_list_del(struct list_head *list)
|
||
{
|
||
anc_mult_bulk_t *bulk;
|
||
anc_mult_bulk_t *temp;
|
||
list_for_each_entry_safe(bulk, temp, list, entry) {
|
||
list_del(&bulk->entry);
|
||
free(bulk);
|
||
}
|
||
}
|
||
|
||
|
||
//多滤波器文件读取
|
||
int anc_mult_coeff_file_fill(anc_coeff_t *db_coeff)
|
||
{
|
||
int offset = 0;
|
||
u8 *temp_dat;
|
||
#if ANC_MULT_DATA_TEST == 1
|
||
int len;
|
||
db_coeff = anc_mult_cfg_test(&len);
|
||
#endif/*ANC_MULT_DATA_TEST*/
|
||
if (mult_hdl && db_coeff) {
|
||
if ((db_coeff->version & 0xF0) == 0xA0) {
|
||
anc_mult_log("%s scene_cnt %d\n", __func__, db_coeff->cnt);
|
||
anc_mult_scene_list_del(&mult_hdl->head); //先卸载所有链表
|
||
audio_anc_mult_scene_max_set(db_coeff->cnt);
|
||
temp_dat = db_coeff->dat;
|
||
for (int i = 0; i < db_coeff->cnt; i++) {
|
||
//temp_dat表示当前场景数据指针,以下函数会返回 下一个场景相对当前temp_dat的偏移量
|
||
temp_dat += anc_mult_scene_param_read(&mult_hdl->head, temp_dat);
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
//多滤波器初始化API
|
||
void anc_mult_init(audio_anc_t *param)
|
||
{
|
||
mult_hdl = zalloc(sizeof(anc_mult_hdl_t));
|
||
mult_hdl->param = param;
|
||
|
||
//链表初始化
|
||
INIT_LIST_HEAD(&mult_hdl->head);
|
||
}
|
||
|
||
extern void audio_anc_biquad2ab_double(anc_fr_t *iir, double *out_coeff, u8 order, int alogm);
|
||
static int anc_mult_cfg_analsis(anc_mult_param_t *p, double **coeff, float *gain, int alogm)
|
||
{
|
||
if (*coeff) {
|
||
free(*coeff);
|
||
*coeff = NULL;
|
||
}
|
||
if (!p->yorder) {
|
||
//没有滤波器, 退出
|
||
return -1;
|
||
}
|
||
*coeff = (double *)malloc(p->yorder * 40);
|
||
/* g_printf("coeff %x\n", (u32)*coeff); */
|
||
audio_anc_biquad2ab_double(p->fr, *coeff, p->yorder, alogm);
|
||
float temp;
|
||
memcpy((u8 *)&temp, (u8 *)&p->gains->iir_gain, 4);
|
||
if (temp < 0) {
|
||
*gain = 0 - temp;
|
||
return 1; //返回符号位
|
||
} else {
|
||
*gain = temp;
|
||
return 0; //返回符号位
|
||
}
|
||
}
|
||
|
||
//场景ID校验
|
||
int audio_anc_mult_scene_id_check(u16 scene_id)
|
||
{
|
||
if (!mult_hdl) {
|
||
return 1;
|
||
}
|
||
anc_mult_bulk_t *bulk;
|
||
list_for_each_entry(bulk, &mult_hdl->head, entry) {
|
||
if (bulk->scene_id == scene_id) {
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
//目标场景, 转成IIR滤波器,并设置到lib coeff/gain变量
|
||
int anc_mult_scene_set(u16 scene_id)
|
||
{
|
||
int ret = 1;
|
||
if (!mult_hdl) {
|
||
return 1;
|
||
}
|
||
anc_mult_log("anc_mult_scene_set cur scene_id %d\n", scene_id);
|
||
u8 gain_sign = 0;
|
||
audio_anc_t *param = mult_hdl->param;
|
||
mult_hdl->cur_scene = scene_id;
|
||
anc_mult_bulk_t *bulk;
|
||
anc_mult_bulk_t *cmp_bulk;
|
||
anc_mult_bulk_t *trans_bulk;
|
||
list_for_each_entry(bulk, &mult_hdl->head, entry) {
|
||
if (bulk->scene_id == scene_id) {
|
||
if (anc_mult_cfg_analsis(&bulk->lff, &mult_hdl->lff_coeff, ¶m->gains.l_ffgain, param->gains.alogm) > 0) {
|
||
gain_sign |= ANCL_FF_SIGN;
|
||
}
|
||
param->lff_coeff = mult_hdl->lff_coeff;
|
||
param->lff_yorder = bulk->lff.yorder;
|
||
/* g_printf("param->lff_yorder %d\n", param->lff_yorder); */
|
||
/* put_buf((u8 *)mult_hdl->lff_coeff, bulk->lff.yorder * 40); */
|
||
/* g_printf("gain %d/100, gain_sign %x\n", (int)(param->gains.l_ffgain * 100.0f), gain_sign); */
|
||
|
||
if (anc_mult_cfg_analsis(&bulk->lfb, &mult_hdl->lfb_coeff, ¶m->gains.l_fbgain, param->gains.alogm) > 0) {
|
||
gain_sign |= ANCL_FB_SIGN;
|
||
}
|
||
param->lfb_coeff = mult_hdl->lfb_coeff;
|
||
param->lfb_yorder = bulk->lfb.yorder;
|
||
|
||
if (anc_mult_cfg_analsis(&bulk->rff, &mult_hdl->rff_coeff, ¶m->gains.r_ffgain, param->gains.alogm) > 0) {
|
||
gain_sign |= ANCR_FF_SIGN;
|
||
}
|
||
param->rff_coeff = mult_hdl->rff_coeff;
|
||
param->rff_yorder = bulk->rff.yorder;
|
||
|
||
if (anc_mult_cfg_analsis(&bulk->rfb, &mult_hdl->rfb_coeff, ¶m->gains.r_fbgain, param->gains.alogm) > 0) {
|
||
gain_sign |= ANCR_FB_SIGN;
|
||
}
|
||
param->rfb_coeff = mult_hdl->rfb_coeff;
|
||
param->rfb_yorder = bulk->rfb.yorder;
|
||
|
||
#if !ANC_MULT_ORDER_CMP_ONLY_USE_ID1 //CMP支持多场景
|
||
cmp_bulk = bulk;
|
||
#endif/*ANC_MULT_ORDER_CMP_ONLY_USE_ID1*/
|
||
#if !ANC_MULT_ORDER_TRANS_ONLY_USE_ID1 //通透支持多场景
|
||
trans_bulk = bulk;
|
||
#endif/*ANC_MULT_ORDER_CMP_ONLY_USE_ID1*/
|
||
ret = 0;
|
||
}
|
||
if (bulk->scene_id == 1) {
|
||
#if ANC_MULT_ORDER_CMP_ONLY_USE_ID1 //CMP固定使用场景1的参数
|
||
cmp_bulk = bulk;
|
||
#endif/*ANC_MULT_ORDER_CMP_ONLY_USE_ID1*/
|
||
#if ANC_MULT_ORDER_TRANS_ONLY_USE_ID1 //通透固定使用场景1的参数
|
||
trans_bulk = bulk;
|
||
#endif/*ANC_MULT_ORDER_CMP_ONLY_USE_ID1*/
|
||
}
|
||
}
|
||
|
||
if (anc_mult_cfg_analsis(&cmp_bulk->lcmp, &mult_hdl->lcmp_coeff, ¶m->gains.l_cmpgain, param->gains.alogm) > 0) {
|
||
gain_sign |= ANCL_CMP_SIGN;
|
||
}
|
||
param->lcmp_coeff = mult_hdl->lcmp_coeff;
|
||
param->lcmp_yorder = cmp_bulk->lcmp.yorder;
|
||
|
||
if (anc_mult_cfg_analsis(&cmp_bulk->rcmp, &mult_hdl->rcmp_coeff, ¶m->gains.r_cmpgain, param->gains.alogm) > 0) {
|
||
gain_sign |= ANCR_CMP_SIGN;
|
||
}
|
||
param->rcmp_coeff = mult_hdl->rcmp_coeff;
|
||
param->rcmp_yorder = cmp_bulk->rcmp.yorder;
|
||
|
||
if (anc_mult_cfg_analsis(&trans_bulk->ltrans, &mult_hdl->ltrans_coeff, ¶m->gains.l_transgain, param->gains.trans_alogm) > 0) {
|
||
gain_sign |= ANCL_TRANS_SIGN;
|
||
}
|
||
param->ltrans_coeff = mult_hdl->ltrans_coeff;
|
||
param->ltrans_yorder = trans_bulk->ltrans.yorder;
|
||
|
||
if (anc_mult_cfg_analsis(&trans_bulk->rtrans, &mult_hdl->rtrans_coeff, ¶m->gains.r_transgain, param->gains.trans_alogm) > 0) {
|
||
gain_sign |= ANCR_TRANS_SIGN;
|
||
}
|
||
param->rtrans_coeff = mult_hdl->rtrans_coeff;
|
||
param->rtrans_yorder = trans_bulk->rtrans.yorder;
|
||
|
||
param->gains.gain_sign = gain_sign;
|
||
audio_anc_max_yorder_verify(param);
|
||
#if ANC_EAR_ADAPTIVE_EN
|
||
//ANC自适应开发者模式,映射左右参数
|
||
audio_anc_param_map(1, 1);
|
||
#endif/*ANC_EAR_ADAPTIVE_EN*/
|
||
return ret;
|
||
}
|
||
|
||
//释放IIR滤波器空间
|
||
void audio_anc_mult_scene_coeff_free(void)
|
||
{
|
||
/*
|
||
空间暂不释放:
|
||
频繁切场景时或与自适应交叉使用时,set 和 free的动作可能不是一一对应的,
|
||
导致最后一个信号量响应时,滤波器已经被提前释放了。
|
||
*/
|
||
return;
|
||
if (!mult_hdl) {
|
||
return;
|
||
}
|
||
if (mult_hdl->lff_coeff) {
|
||
free(mult_hdl->lff_coeff);
|
||
mult_hdl->param->lff_coeff = NULL;
|
||
mult_hdl->lff_coeff = NULL;
|
||
}
|
||
if (mult_hdl->lfb_coeff) {
|
||
free(mult_hdl->lfb_coeff);
|
||
mult_hdl->param->lfb_coeff = NULL;
|
||
mult_hdl->lfb_coeff = NULL;
|
||
}
|
||
if (mult_hdl->ltrans_coeff) {
|
||
free(mult_hdl->ltrans_coeff);
|
||
mult_hdl->param->ltrans_coeff = NULL;
|
||
mult_hdl->ltrans_coeff = NULL;
|
||
}
|
||
if (mult_hdl->lcmp_coeff) {
|
||
free(mult_hdl->lcmp_coeff);
|
||
mult_hdl->param->lcmp_coeff = NULL;
|
||
mult_hdl->lcmp_coeff = NULL;
|
||
}
|
||
if (mult_hdl->rff_coeff) {
|
||
free(mult_hdl->rff_coeff);
|
||
mult_hdl->param->rff_coeff = NULL;
|
||
mult_hdl->rff_coeff = NULL;
|
||
}
|
||
if (mult_hdl->rfb_coeff) {
|
||
free(mult_hdl->rfb_coeff);
|
||
mult_hdl->param->rfb_coeff = NULL;
|
||
mult_hdl->rfb_coeff = NULL;
|
||
}
|
||
if (mult_hdl->rtrans_coeff) {
|
||
free(mult_hdl->rtrans_coeff);
|
||
mult_hdl->param->rtrans_coeff = NULL;
|
||
mult_hdl->rtrans_coeff = NULL;
|
||
}
|
||
if (mult_hdl->rcmp_coeff) {
|
||
free(mult_hdl->rcmp_coeff);
|
||
mult_hdl->param->rcmp_coeff = NULL;
|
||
mult_hdl->rcmp_coeff = NULL;
|
||
}
|
||
}
|
||
|
||
/*ANC滤波器格式校验*/
|
||
static int anc_mult_coeff_check(anc_coeff_t *db_coeff, u16 len)
|
||
{
|
||
u32 coeff_len = 0;
|
||
int i;
|
||
|
||
if ((db_coeff->version & 0xF0) != 0xA0) {
|
||
return 1;
|
||
}
|
||
if (db_coeff->cnt > 5) { //理论上最大ID个数
|
||
return 1;
|
||
}
|
||
|
||
anc_mult_scene_file_t *file = (anc_mult_scene_file_t *)db_coeff->dat;
|
||
struct anc_param_head_t coeff_head[file->cnt];
|
||
|
||
for (i = 0; i < file->cnt; i++) {
|
||
memcpy(&coeff_head[i], file->dat + (i * 6), 6); //结构体为8字节,这里只有6字节
|
||
if (coeff_len != coeff_head[i].offset) {
|
||
return 1;
|
||
}
|
||
coeff_len += coeff_head[i].len;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
const static u8 anc_mult_part_id[8][2] = {
|
||
{ANC_L_FF_PARM, ANC_L_FF_FGQ},
|
||
{ANC_L_FB_PARM, ANC_L_FB_FGQ},
|
||
{ANC_L_CMP_PARM, ANC_L_CMP_FGQ},
|
||
{ANC_L_TRANS_PARM, ANC_L_TRANS_FGQ},
|
||
|
||
{ANC_R_FF_PARM, ANC_R_FF_FGQ},
|
||
{ANC_R_FB_PARM, ANC_R_FB_FGQ},
|
||
{ANC_R_CMP_PARM, ANC_R_CMP_FGQ},
|
||
{ANC_R_TRANS_PARM, ANC_R_TRANS_FGQ}
|
||
};
|
||
|
||
//部分数据文件-头部信息重组
|
||
static void anc_mult_part_head_recombination(u16 *cnt, struct anc_param_head_t *id_head, anc_mult_param_t *p, anc_mult_param_t *new_p, u8 type)
|
||
{
|
||
u8 order = (new_p->fr) ? new_p->yorder : p->yorder;
|
||
|
||
if ((p->gains != NULL) || (new_p->gains != NULL)) {
|
||
id_head[*cnt].id = anc_mult_part_id[type][0];
|
||
id_head[*cnt].len = sizeof(anc_mult_gain_t);
|
||
if (*cnt) {
|
||
id_head[*cnt].offset = id_head[(*cnt) - 1].len + id_head[(*cnt) - 1].offset;
|
||
}
|
||
(*cnt)++;
|
||
}
|
||
if (order) {
|
||
id_head[*cnt].id = anc_mult_part_id[type][1];
|
||
id_head[*cnt].len = order * sizeof(anc_fr_t);
|
||
if (*cnt) {
|
||
id_head[*cnt].offset = id_head[(*cnt) - 1].len + id_head[(*cnt) - 1].offset;
|
||
}
|
||
(*cnt)++;
|
||
}
|
||
}
|
||
|
||
//部分数据文件-数据信息重组
|
||
static void anc_mult_part_data_recombination(anc_mult_param_t *new_p, anc_mult_param_t *p, anc_mult_param_t *t_p, u8 type)
|
||
{
|
||
if (t_p->gains != NULL) {
|
||
memcpy((u8 *)new_p->gains, (u8 *)t_p->gains, sizeof(anc_mult_gain_t));
|
||
} else if (p->gains != NULL) {
|
||
memcpy((u8 *)new_p->gains, (u8 *)p->gains, sizeof(anc_mult_gain_t));
|
||
}
|
||
if (t_p->fr != NULL) {
|
||
memcpy((u8 *)new_p->fr, (u8 *)t_p->fr, t_p->yorder * sizeof(anc_fr_t));
|
||
} else if (p->fr != NULL) {
|
||
memcpy((u8 *)new_p->fr, (u8 *)p->fr, p->yorder * sizeof(anc_fr_t));
|
||
}
|
||
}
|
||
|
||
//部分数据文件-写,不支持新增场景
|
||
static int anc_mult_part_coeff_write(anc_coeff_t *target_coeff, u16 len)
|
||
{
|
||
u16 head_cnt, i, new_id_flag;
|
||
u16 scene_cnt = 0;
|
||
int ret = 0;
|
||
int new_len = sizeof(anc_coeff_t);
|
||
anc_coeff_t *old_coeff = (anc_coeff_t *)anc_db_get(ANC_DB_COEFF, &mult_hdl->param->coeff_size);
|
||
u8 *temp_dat;
|
||
|
||
anc_mult_bulk_t *new_bulk;
|
||
anc_mult_bulk_t *target_bulk;
|
||
anc_mult_bulk_t *old_bulk;
|
||
anc_mult_bulk_t *t_bulk;
|
||
|
||
if ((old_coeff->version & 0xF0) != 0xA0) {
|
||
return -1;
|
||
}
|
||
|
||
anc_mult_scene_file_t *file[old_coeff->cnt];
|
||
|
||
//1、解析目标数据信息
|
||
struct list_head target_list;
|
||
INIT_LIST_HEAD(&target_list);
|
||
|
||
if ((target_coeff->version & 0xF0) != 0xA0) {
|
||
return -1;
|
||
}
|
||
temp_dat = target_coeff->dat;
|
||
for (i = 0; i < target_coeff->cnt; i++) {
|
||
//temp_dat表示当前场景数据指针,以下函数会返回 下一个场景相对当前temp_dat的偏移量
|
||
temp_dat += anc_mult_scene_param_read(&target_list, temp_dat);
|
||
}
|
||
|
||
//检查是否属于新场景(目前不支持新加场景重组)
|
||
list_for_each_entry(target_bulk, &target_list, entry) {
|
||
new_id_flag = 1;
|
||
list_for_each_entry(old_bulk, &mult_hdl->head, entry) {
|
||
if (target_bulk->scene_id == old_bulk->scene_id) {
|
||
new_id_flag = 0;
|
||
break;
|
||
}
|
||
}
|
||
if (new_id_flag) {
|
||
ret = -2;
|
||
goto __free2;
|
||
}
|
||
}
|
||
|
||
//2、重组新数据头信息
|
||
list_for_each_entry(old_bulk, &mult_hdl->head, entry) {
|
||
t_bulk = old_bulk;
|
||
list_for_each_entry(target_bulk, &target_list, entry) {
|
||
if (target_bulk->scene_id == old_bulk->scene_id) {
|
||
t_bulk = target_bulk;
|
||
break;
|
||
}
|
||
}
|
||
file[scene_cnt] = zalloc(sizeof(struct anc_param_head_t) * 16 + sizeof(anc_mult_scene_file_t));
|
||
struct anc_param_head_t *id_head = (struct anc_param_head_t *)file[scene_cnt]->dat;
|
||
head_cnt = 0;
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->lff, &t_bulk->lff, 0);
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->lfb, &t_bulk->lfb, 1);
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->lcmp, &t_bulk->lcmp, 2);
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->ltrans, &t_bulk->ltrans, 3);
|
||
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->rff, &t_bulk->rff, 4);
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->rfb, &t_bulk->rfb, 5);
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->rcmp, &t_bulk->rcmp, 6);
|
||
anc_mult_part_head_recombination(&head_cnt, id_head, &old_bulk->rtrans, &t_bulk->rtrans, 7);
|
||
file[scene_cnt]->scene_id = old_bulk->scene_id;
|
||
file[scene_cnt]->cnt = head_cnt;
|
||
scene_cnt++;
|
||
//file+id_head+data(len+offset)
|
||
new_len += sizeof(anc_mult_scene_file_t) + (sizeof(struct anc_param_head_t) * head_cnt) + \
|
||
id_head[head_cnt - 1].len + id_head[head_cnt - 1].offset;
|
||
/* printf("last len%d, cnt%d, offset%d, len%d\n", new_len, head_cnt, id_head[head_cnt - 1].len, id_head[head_cnt - 1].offset); */
|
||
}
|
||
//重组后数据长度
|
||
anc_mult_log("PART FILE new_file_len %d\n", new_len);
|
||
|
||
//3、申请新数据空间
|
||
anc_coeff_t *new_coeff = (anc_coeff_t *)zalloc(new_len);
|
||
struct list_head new_list;
|
||
INIT_LIST_HEAD(&new_list);
|
||
|
||
int new_offset = 0;
|
||
if (!new_coeff) {
|
||
ret = -1;
|
||
goto __free1;
|
||
}
|
||
memcpy((u8 *)new_coeff, (u8 *)old_coeff, sizeof(anc_coeff_t));
|
||
temp_dat = new_coeff->dat;
|
||
//4、拷贝数据头至新数据空间
|
||
for (i = 0; i < new_coeff->cnt; i++) {
|
||
memcpy(temp_dat, (u8 *)file[i], sizeof(anc_mult_scene_file_t));
|
||
memcpy(temp_dat + sizeof(anc_mult_scene_file_t), file[i]->dat, \
|
||
sizeof(struct anc_param_head_t) * file[i]->cnt);
|
||
|
||
/* put_buf((u8*)new_coeff, new_len); */
|
||
new_offset = anc_mult_scene_param_read(&new_list, temp_dat);
|
||
temp_dat += new_offset;
|
||
}
|
||
//5、重组新数据
|
||
list_for_each_entry(old_bulk, &mult_hdl->head, entry) {
|
||
t_bulk = old_bulk;
|
||
list_for_each_entry(target_bulk, &target_list, entry) {
|
||
if (target_bulk->scene_id == old_bulk->scene_id) {
|
||
t_bulk = target_bulk;
|
||
break;
|
||
}
|
||
}
|
||
list_for_each_entry(new_bulk, &new_list, entry) {
|
||
if (new_bulk->scene_id == old_bulk->scene_id) {
|
||
anc_mult_part_data_recombination(&new_bulk->lff, &old_bulk->lff, &t_bulk->lff, 0);
|
||
anc_mult_part_data_recombination(&new_bulk->lfb, &old_bulk->lfb, &t_bulk->lfb, 1);
|
||
anc_mult_part_data_recombination(&new_bulk->lcmp, &old_bulk->lcmp, &t_bulk->lcmp, 2);
|
||
anc_mult_part_data_recombination(&new_bulk->ltrans, &old_bulk->ltrans, &t_bulk->ltrans, 3);
|
||
|
||
anc_mult_part_data_recombination(&new_bulk->rff, &old_bulk->rff, &t_bulk->rff, 4);
|
||
anc_mult_part_data_recombination(&new_bulk->rfb, &old_bulk->rfb, &t_bulk->rfb, 5);
|
||
anc_mult_part_data_recombination(&new_bulk->rcmp, &old_bulk->rcmp, &t_bulk->rcmp, 6);
|
||
anc_mult_part_data_recombination(&new_bulk->rtrans, &old_bulk->rtrans, &t_bulk->rtrans, 7);
|
||
}
|
||
}
|
||
}
|
||
//重组后数据内容
|
||
/* put_buf((u8*)new_coeff, new_len); */
|
||
|
||
//6、写入flash
|
||
mult_hdl->param->write_coeff_size = new_len; //更新滤波器长度
|
||
ret = anc_db_put(mult_hdl->param, NULL, new_coeff);
|
||
|
||
//7、释放新数据链表、ram
|
||
anc_mult_scene_list_del(&new_list);
|
||
free(new_coeff);
|
||
|
||
__free1:
|
||
//8、释放重组临时ram
|
||
for (i = 0; i < old_coeff->cnt; i++) {
|
||
free(file[i]);
|
||
}
|
||
__free2:
|
||
//9、释放目标数据解析链表
|
||
anc_mult_scene_list_del(&target_list);
|
||
return ret;
|
||
}
|
||
|
||
//单独增益ID设置-兼容之前的命令
|
||
void audio_anc_mult_gains_id_set(u8 gain_id, int data)
|
||
{
|
||
if (!mult_hdl) {
|
||
return;
|
||
}
|
||
anc_mult_bulk_t *bulk;
|
||
u8 *temp_dat;
|
||
float fgain = *((float *)&data);
|
||
int i;
|
||
|
||
struct list_head list;
|
||
INIT_LIST_HEAD(&list);
|
||
|
||
anc_coeff_t *db_coeff = (anc_coeff_t *)anc_db_get(ANC_DB_COEFF, &mult_hdl->param->coeff_size);
|
||
|
||
if ((db_coeff->version & 0xF0) != 0xA0) {
|
||
return;
|
||
}
|
||
anc_coeff_t *coeff = malloc(mult_hdl->param->coeff_size);
|
||
memcpy((u8 *)coeff, (u8 *)db_coeff, mult_hdl->param->coeff_size);
|
||
|
||
temp_dat = coeff->dat;
|
||
for (i = 0; i < coeff->cnt; i++) {
|
||
temp_dat += anc_mult_scene_param_read(&list, temp_dat);
|
||
}
|
||
list_for_each_entry(bulk, &list, entry) {
|
||
if (bulk->scene_id == audio_anc_mult_scene_get()) {
|
||
break;
|
||
}
|
||
}
|
||
switch (gain_id) {
|
||
case ANC_FFGAIN_SET:
|
||
if (bulk->lff.gains) {
|
||
bulk->lff.gains->iir_gain = (bulk->lff.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_FBGAIN_SET:
|
||
if (bulk->lfb.gains) {
|
||
bulk->lfb.gains->iir_gain = (bulk->lfb.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_TRANS_GAIN_SET:
|
||
if (bulk->ltrans.gains) {
|
||
bulk->ltrans.gains->iir_gain = (bulk->ltrans.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_CMP_GAIN_SET:
|
||
if (bulk->lcmp.gains) {
|
||
bulk->lcmp.gains->iir_gain = (bulk->lcmp.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_RFF_GAIN_SET:
|
||
if (bulk->rff.gains) {
|
||
bulk->rff.gains->iir_gain = (bulk->rff.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_RFB_GAIN_SET:
|
||
if (bulk->rfb.gains) {
|
||
bulk->rfb.gains->iir_gain = (bulk->rfb.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_RTRANS_GAIN_SET:
|
||
if (bulk->rtrans.gains) {
|
||
bulk->rtrans.gains->iir_gain = (bulk->rtrans.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_RCMP_GAIN_SET:
|
||
if (bulk->rcmp.gains) {
|
||
bulk->rcmp.gains->iir_gain = (bulk->rcmp.gains->iir_gain > 0) ? fgain : 0 - fgain;
|
||
}
|
||
break;
|
||
case ANC_GAIN_SIGN_SET:
|
||
anc_mult_param_t *p;
|
||
for (i = 0; i < 8; i++) {
|
||
p = &bulk->lff + i;
|
||
if (!p->gains) {
|
||
continue;
|
||
}
|
||
if (((data & BIT(i)) && (p->gains->iir_gain > 0)) || \
|
||
((!(data & BIT(i))) && (p->gains->iir_gain < 0))) {
|
||
p->gains->iir_gain = 0 - p->gains->iir_gain;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
mult_hdl->param->write_coeff_size = mult_hdl->param->coeff_size;
|
||
if (anc_db_put(mult_hdl->param, NULL, (anc_coeff_t *)coeff)) {
|
||
anc_mult_log("anc_coeff_write err!");
|
||
}
|
||
audio_anc_mult_coeff_file_read();
|
||
|
||
free(coeff);
|
||
}
|
||
|
||
//获取并解析flash anc_coeff.bin,实时更新参数效果
|
||
int audio_anc_mult_coeff_file_read(void)
|
||
{
|
||
if (!mult_hdl) {
|
||
return 1;
|
||
}
|
||
audio_anc_t *param = mult_hdl->param;
|
||
//读flash
|
||
anc_coeff_t *db_coeff = (anc_coeff_t *)anc_db_get(ANC_DB_COEFF, ¶m->coeff_size);
|
||
anc_mult_log("anc_db coeff_size %d\n", param->coeff_size);
|
||
//更新参数链表
|
||
int ret = anc_mult_coeff_file_fill(db_coeff);
|
||
|
||
//更新效果
|
||
if (param->mode != ANC_OFF) {
|
||
/* g_printf("read cur scene_id %d\n",mult_hdl->cur_scene); */
|
||
anc_mult_scene_set(mult_hdl->cur_scene);
|
||
audio_anc_reset(param, 0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//anc_coeff.bin在线更新,支持全部数据文件写、部分数据文件写
|
||
int audio_anc_mult_coeff_write(ANC_coeff_fill_t type, int *coeff, u16 len)
|
||
{
|
||
int ret = 0;
|
||
u8 single_type = 0;
|
||
#if ANC_MULT_DATA_TEST == 2 //流程测试,确认重组数据正常
|
||
int test_len;
|
||
if (type == ANC_MULT_COEFF_FILL_PART) {
|
||
coeff = (int *)anc_mult_cfg_part_test((int)&test_len);
|
||
} else {
|
||
coeff = (int *)anc_mult_cfg_test((int)&test_len);
|
||
}
|
||
len = test_len;
|
||
mult_hdl->param->write_coeff_size = len;
|
||
#endif/*ANC_MULT_DATA_TEST*/
|
||
|
||
anc_coeff_t *db_coeff = (anc_coeff_t *)coeff;
|
||
|
||
anc_coeff_t *tmp_coeff = NULL;
|
||
if (!mult_hdl) {
|
||
return -1;
|
||
}
|
||
anc_mult_log("anc_coeff_write:0x%x, len:%d", (u32)coeff, len);
|
||
ret = anc_mult_coeff_check(db_coeff, len);
|
||
if (ret) {
|
||
r_printf("err %d\n", ret);
|
||
return ret;
|
||
}
|
||
if (type == ANC_MULT_COEFF_FILL_PART) {
|
||
ret = anc_mult_part_coeff_write(db_coeff, len);
|
||
} else if (type == ANC_MULT_COEFF_FILL_ALL) {
|
||
ret = anc_db_put(mult_hdl->param, NULL, (anc_coeff_t *)coeff);
|
||
}
|
||
if (ret) {
|
||
anc_mult_log("anc_coeff_write err:%d", ret);
|
||
return -1;
|
||
}
|
||
ret = audio_anc_mult_coeff_file_read();
|
||
return ret;
|
||
}
|
||
|
||
|
||
#if ANC_MULT_DATA_TEST
|
||
|
||
static anc_coeff_t *anc_mult_cfg_test(int *db_len)
|
||
{
|
||
int i, j;
|
||
int offset = 0;
|
||
int len = 4 + 2 * (4 + 6 + 6) + 4 + 4 + 26 + 39;
|
||
anc_coeff_t *db = (anc_coeff_t *)zalloc(len);
|
||
anc_mult_log("test_db_len %d\n", len);
|
||
db->version = ANC_VERSION_BR28_MULT;
|
||
db->cnt = 2;
|
||
u8 *scene_temp = db->dat;
|
||
u8 *temp_dat;
|
||
struct anc_param_head_t *id_head;
|
||
anc_fr_t fr;
|
||
anc_mult_gain_t *gain;
|
||
|
||
for (j = 0; j < db->cnt; j++) {
|
||
anc_mult_scene_file_t *file = (anc_mult_scene_file_t *)scene_temp;
|
||
|
||
switch (j) {
|
||
case 0:
|
||
file->cnt = 2;
|
||
file->scene_id = 1;
|
||
temp_dat = file->dat + (file->cnt * 6);
|
||
id_head = (struct anc_param_head_t *)file->dat;
|
||
id_head[0].id = ANC_L_FF_PARM;
|
||
id_head[0].offset = 0;
|
||
id_head[0].len = 4;
|
||
gain = (anc_mult_gain_t *)temp_dat;
|
||
gain->iir_gain = 2.0f;
|
||
|
||
id_head[1].id = ANC_L_FF_FGQ;
|
||
id_head[1].offset = 4;
|
||
id_head[1].len = 26;
|
||
fr.type = ANC_IIR_BAND_PASS;
|
||
fr.a[0] = 500.0f;
|
||
fr.a[1] = 10.0f;
|
||
fr.a[2] = 3.0f;
|
||
memcpy(temp_dat + id_head[1].offset, (u8 *)&fr, 13);
|
||
memcpy(temp_dat + id_head[1].offset + 13, (u8 *)&fr, 13);
|
||
offset = ((u32)temp_dat - (u32)scene_temp) + id_head[1].offset + id_head[1].len;
|
||
break;
|
||
|
||
case 1:
|
||
file->cnt = 2;
|
||
file->scene_id = 2;
|
||
temp_dat = file->dat + (file->cnt * 6);
|
||
id_head = (struct anc_param_head_t *)file->dat;
|
||
id_head[0].id = ANC_L_FF_PARM;
|
||
id_head[0].offset = 0;
|
||
id_head[0].len = 4;
|
||
gain = (anc_mult_gain_t *)temp_dat;
|
||
gain->iir_gain = -3.0f;
|
||
|
||
id_head[1].id = ANC_L_FF_FGQ;
|
||
id_head[1].offset = 4;
|
||
id_head[1].len = 39;
|
||
fr.type = ANC_IIR_BAND_PASS;
|
||
fr.a[0] = 5000.0f;
|
||
fr.a[1] = 10.0f;
|
||
fr.a[2] = 3.0f;
|
||
memcpy(temp_dat + id_head[1].offset, (u8 *)&fr, 13);
|
||
memcpy(temp_dat + id_head[1].offset + 13, (u8 *)&fr, 13);
|
||
memcpy(temp_dat + id_head[1].offset + 26, (u8 *)&fr, 13);
|
||
offset = ((u32)temp_dat - (u32)scene_temp) + id_head[1].offset + id_head[1].len;
|
||
break;
|
||
}
|
||
scene_temp += offset;
|
||
}
|
||
*db_len = len;
|
||
put_buf((u8 *)db, *db_len);
|
||
return db;
|
||
}
|
||
|
||
|
||
anc_coeff_t *anc_mult_cfg_part_test(int *db_len)
|
||
{
|
||
int i, j;
|
||
int offset = 0;
|
||
/* int len = 4 + 2 * (4 + 6 ) + 4 + 4 + 26 + 39; */
|
||
int len = 4 + 2 * (4 + 6) + 6 + 4 + 4 + 39;
|
||
anc_coeff_t *db = (anc_coeff_t *)zalloc(len);
|
||
anc_mult_log("test_db_len %d\n", len);
|
||
db->version = ANC_VERSION_BR28_MULT;
|
||
db->cnt = 2;
|
||
u8 *scene_temp = db->dat;
|
||
u8 *temp_dat;
|
||
struct anc_param_head_t *id_head;
|
||
anc_fr_t fr;
|
||
anc_mult_gain_t *gain;
|
||
|
||
for (j = 0; j < db->cnt; j++) {
|
||
anc_mult_scene_file_t *file = (anc_mult_scene_file_t *)scene_temp;
|
||
|
||
switch (j) {
|
||
case 0:
|
||
file->cnt = 1;
|
||
file->scene_id = 1;
|
||
temp_dat = file->dat + (file->cnt * 6);
|
||
id_head = (struct anc_param_head_t *)file->dat;
|
||
id_head[0].id = ANC_L_FF_PARM;
|
||
id_head[0].offset = 0;
|
||
id_head[0].len = 4;
|
||
gain = (anc_mult_gain_t *)temp_dat;
|
||
gain->iir_gain = 1.0f;
|
||
|
||
/* id_head[1].id = ANC_L_FF_FGQ; */
|
||
/* id_head[1].offset = 4; */
|
||
/* id_head[1].len = 26; */
|
||
/* fr.type = ANC_IIR_BAND_PASS; */
|
||
/* fr.a[0] = 500.0f; */
|
||
/* fr.a[1] = 10.0f; */
|
||
/* fr.a[2] = 3.0f; */
|
||
/* memcpy(temp_dat + id_head[1].offset, (u8 *)&fr, 13); */
|
||
/* memcpy(temp_dat + id_head[1].offset + 13, (u8 *)&fr, 13); */
|
||
offset = ((u32)temp_dat - (u32)scene_temp) + id_head[0].offset + id_head[0].len;
|
||
break;
|
||
|
||
case 1:
|
||
file->cnt = 2;
|
||
file->scene_id = 2;
|
||
temp_dat = file->dat + (file->cnt * 6);
|
||
id_head = (struct anc_param_head_t *)file->dat;
|
||
id_head[0].id = ANC_L_FF_PARM;
|
||
id_head[0].offset = 0;
|
||
id_head[0].len = 4;
|
||
gain = (anc_mult_gain_t *)temp_dat;
|
||
gain->iir_gain = 1.0f;
|
||
|
||
id_head[1].id = ANC_L_FF_FGQ;
|
||
id_head[1].offset = 4;
|
||
/* id_head[1].len = 39; */
|
||
id_head[1].len = 26;
|
||
fr.type = ANC_IIR_BAND_PASS;
|
||
fr.a[0] = 1.0f;
|
||
fr.a[1] = 1.0f;
|
||
fr.a[2] = 1.0f;
|
||
memcpy(temp_dat + id_head[1].offset, (u8 *)&fr, 13);
|
||
memcpy(temp_dat + id_head[1].offset + 13, (u8 *)&fr, 13);
|
||
/* memcpy(temp_dat + id_head[1].offset + 26, (u8 *)&fr, 13); */
|
||
offset = ((u32)temp_dat - (u32)scene_temp) + id_head[0].offset + id_head[0].len;
|
||
break;
|
||
}
|
||
scene_temp += offset;
|
||
}
|
||
*db_len = len;
|
||
put_buf((u8 *)db, *db_len);
|
||
return db;
|
||
}
|
||
|
||
#endif/*ANC_MULT_DATA_TEST*/
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
#endif/*ANC_MULT_ORDER_ENABLE*/
|