Files
99_7018_lmx/cpu/br28/audio_anc_mult_scene.c

973 lines
32 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
/*******************************************************************
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, &param->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, &param->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, &param->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, &param->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, &param->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, &param->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, &param->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, &param->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, &param->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*/