KT25-0812_82A-UART/cpu/br25/audio_mic/effect_cfg.c
2025-08-12 18:09:23 +08:00

573 lines
18 KiB
C

#include "effect_cfg.h"
#include "effect_tool.h"
#include "mic_effect.h"
#include "system/includes.h"
#include "media/includes.h"
#include "app_config.h"
#include "app_online_cfg.h"
/* #include "application/audio_eq.h" */
/* #include "reverb/reverb_api.h" */
/* #include "effects_config.h" */
/* #include "effects_default_config.h" */
#define LOG_TAG "[APP-EFFECTS]"
#define LOG_ERROR_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#include "debug.h"
#if (TCFG_MIC_EFFECT_ENABLE)
static const u8 effect_tool_sdk_name[16] = "AC696X";
static const u8 effect_tool_ver[4] = {0, 4, 3, 0};
static const u8 effect_tool_password[16] = "000";
typedef struct {
spinlock_t lock;
u16 effect_file_cfg : 1;
u16 revert : 15;
#if TCFG_EQ_ENABLE
int EQ_Coeff_table[(EFFECT_EQ_SECTION_MAX + 3) * 5];
#endif
u16 cur_mode_id;
struct __effect_mode_cfg *mode_cfg;
struct __effect_mode *mode;
struct __tool_callback cb;
} EFFECT_CFG;
/*-----------------------------------------------------------*/
static EFFECT_CFG *p_effects_cfg = NULL;
#define __this p_effects_cfg
extern u16 crc_get_16bit(const void *src, u32 len);
extern int eq_seg_design(struct eq_seg_info *seg, int sample_rate, int *coeff);
extern void mic_eq_drc_update();
/* static const struct eq_seg_info eq_tab_normal[EQ_SECTION_MAX_DEFAULT] = { */
static const struct eq_seg_info eq_tab_normal[] = {
{0, EQ_IIR_TYPE_BAND_PASS, 31, 0 << 20, (int)(0.7f * (1 << 24))},
/* {1, EQ_IIR_TYPE_BAND_PASS, 62, 0 << 20, (int)(0.7f * (1 << 24))},
{2, EQ_IIR_TYPE_BAND_PASS, 125, 0 << 20, (int)(0.7f * (1 << 24))},
{3, EQ_IIR_TYPE_BAND_PASS, 250, 0 << 20, (int)(0.7f * (1 << 24))},
{4, EQ_IIR_TYPE_BAND_PASS, 500, 0 << 20, (int)(0.7f * (1 << 24))},
{5, EQ_IIR_TYPE_BAND_PASS, 1000, 0 << 20, (int)(0.7f * (1 << 24))},
{6, EQ_IIR_TYPE_BAND_PASS, 2000, 0 << 20, (int)(0.7f * (1 << 24))},
{7, EQ_IIR_TYPE_BAND_PASS, 4000, 0 << 20, (int)(0.7f * (1 << 24))},
{8, EQ_IIR_TYPE_BAND_PASS, 8000, 0 << 20, (int)(0.7f * (1 << 24))},
{9, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{10, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{11, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{12, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{13, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{14, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{15, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{16, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{17, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{18, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},
{19, EQ_IIR_TYPE_BAND_PASS, 16000, 0 << 20, (int)(0.7f * (1 << 24))},*/
};
static void eq_coeff_set(int sr, u8 ch)
{
int i;
if (!sr) {
sr = 44100;
log_error("sr is zero");
}
struct __effect_mode *cur_mode = &__this->mode[__this->cur_mode_id];
for (i = 0; i < cur_mode->seg_num; i++) {
if (cur_mode->eq_design_mask & BIT(i)) {
cur_mode->eq_design_mask &= ~BIT(i);
#if TCFG_EQ_ENABLE
eq_seg_design(&cur_mode->parm.eq.val.seg[i], sr, &__this->EQ_Coeff_table[5 * i]);
#if 0
int *tar_tab = __this->EQ_Coeff_table;
/* int *tar_tab = EQ_Coeff_table; */
log_d("i %d, cf0:%d, cf1:%d, cf2:%d, cf3:%d, cf4:%d ", i, tar_tab[5 * i]
, tar_tab[5 * i + 1]
, tar_tab[5 * i + 2]
, tar_tab[5 * i + 3]
, tar_tab[5 * i + 4]
);
#endif
#endif
}
}
}
#if MIC_EFFECT_EQ_EN
int *get_outval_addr(u8 mode)
{
return &__this->EQ_Coeff_table[EFFECT_EQ_SECTION_MAX * 5 + mode * 5];
}
int mic_eq_get_filter_info(struct audio_eq *eq, int sr, struct audio_eq_filter_info *info)
{
log_info("mic_eq_get_filter_info \n");
int *coeff = NULL;
ASSERT(__this);
struct __effect_mode *cur_mode = &__this->mode[__this->cur_mode_id];
if ((sr != __this->mode_cfg->sample_rate) || (cur_mode->parm.eq.update)) {
spin_lock(&__this->lock);
if (sr != __this->mode_cfg->sample_rate) {
cur_mode->eq_design_mask = (u32) - 1;
}
eq_coeff_set(sr, 0);//算前五段eq
__this->mode_cfg->sample_rate = sr;
cur_mode->parm.eq.update = 0;
spin_unlock(&__this->lock);
}
/* for (int i = 0; i < mic_effect_eq_section_num(); i++) { */
/* int *tar_tab = __this->EQ_Coeff_table; */
/* log_d("i %d, cf0:%d, cf1:%d, cf2:%d, cf3:%d, cf4:%d ", i, tar_tab[5 * i] */
/* , tar_tab[5 * i + 1] */
/* , tar_tab[5 * i + 2] */
/* , tar_tab[5 * i + 3] */
/* , tar_tab[5 * i + 4] */
/* ); */
/* } */
coeff = __this->EQ_Coeff_table;
info->L_coeff = info->R_coeff = (void *)coeff;
info->L_gain = info->R_gain = cur_mode->global_gain;
info->nsection = mic_effect_eq_section_num();
return 0;
}
#endif
////根据命令设置参数
static int effect_cfg_update_parm(void *priv, u16 mode_index, u16 cmd_index, u8 *data, u32 len, u8 online)
{
__this = (EFFECT_CFG *)priv;
struct __effect_mode *cur_mode = &__this->mode[mode_index];
log_i("mode = %d,cmd = %x\n", mode_index, cmd_index);
switch (cmd_index) {
case EFFECTS_CMD_REVERB:
memcpy(&cur_mode->parm.reverb.val, data, len);
cur_mode->parm.reverb.flag = 1;
cur_mode->parm.reverb.update = 1;
mic_effect_reverb_parm_fill(&cur_mode->parm.reverb.val, 1, online);
break;
case EFFECTS_CMD_PITCH2:
memcpy(&cur_mode->parm.pitch.val, data, len);
cur_mode->parm.pitch.flag = 1;
cur_mode->parm.pitch.update = 1;
mic_effect_pitch_parm_fill(&cur_mode->parm.pitch.val, 1, online);
break;
case EFFECTS_CMD_ECHO:
memcpy(&cur_mode->parm.ehco.val, data, len);
cur_mode->parm.ehco.flag = 1;
cur_mode->parm.ehco.update = 1;
mic_effect_echo_parm_fill(&cur_mode->parm.ehco.val, 1, online);
break;
case EFFECTS_CMD_NOISE:
memcpy(&cur_mode->parm.noise.val, data, len);
cur_mode->parm.noise.flag = 1;
cur_mode->parm.noise.update = 1;
mic_effect_noisegate_parm_fill(&cur_mode->parm.noise.val, 1, online);
break;
case EFFECTS_CMD_SHOUT_WHEAT:
memcpy(&cur_mode->parm.shout_wheat.val, data, len);
cur_mode->parm.shout_wheat.flag = 1;
cur_mode->parm.shout_wheat.update = 1;
mic_effect_shout_wheat_parm_fill(&cur_mode->parm.shout_wheat.val, 1, online);
break;
case EFFECTS_CMD_LOW_SOUND:
memcpy(&cur_mode->parm.low_sound.val, data, len);
cur_mode->parm.low_sound.flag = 1;
cur_mode->parm.low_sound.update = 1;
mic_effect_low_sound_parm_fill(&cur_mode->parm.low_sound.val, 1, online);
break;
case EFFECTS_CMD_HIGH_SOUND:
memcpy(&cur_mode->parm.high_sound.val, data, len);
cur_mode->parm.high_sound.flag = 1;
cur_mode->parm.high_sound.update = 1;
mic_effect_high_sound_parm_fill(&cur_mode->parm.high_sound.val, 1, online);
break;
case EFFECTS_EQ_ONLINE_CMD_PARAMETER_SEG:
#if TCFG_EQ_ENABLE
if (online) {
struct eq_seg_info seg;
memcpy(&seg, data, sizeof(struct eq_seg_info));
if (seg.index == (u16) - 1) {
memcpy(&cur_mode->global_gain, &seg.iir_type, sizeof(float));
}
put_buf(&cur_mode->global_gain, 4);
log_i("cur_mode->global_gain %f\n", cur_mode->global_gain);
if (seg.index >= EFFECT_EQ_SECTION_MAX) {
if (seg.index != (u16) - 1) {
log_e("eq seg inex err!!\n");
} else {
cur_mode->parm.eq.update = 1;
mic_eq_drc_update();
}
break;
}
memcpy(&cur_mode->parm.eq.val.seg[seg.index], &seg, sizeof(struct eq_seg_info));
cur_mode->eq_design_mask |= BIT(seg.index);
cur_mode->parm.eq.update = 1;
mic_eq_drc_update();
log_info("idx:%d, iir:%d, frq:%d, gain:%d, q:%d \n", seg.index, seg.iir_type, seg.freq, 10 * seg.gain / (1 << 20), 10 * seg.q / (1 << 24));
} else {
memcpy(&cur_mode->parm.eq.val, data, sizeof(EFFECTS_EQ_PARM_SET));
cur_mode->parm.eq.flag = 1;
cur_mode->global_gain = cur_mode->parm.eq.val.global_gain;
cur_mode->seg_num = cur_mode->parm.eq.val.seg_num;
cur_mode->eq_design_mask = (u32) - 1;
eq_coeff_set(__this->mode_cfg->sample_rate, 0);
cur_mode->parm.eq.update = 1;
}
#endif
break;
case EFFECTS_CMD_MIC_ANALOG_GAIN:
memcpy(&cur_mode->parm.mic_gain.val, data, len);
cur_mode->parm.mic_gain.flag = 1;
cur_mode->parm.mic_gain.update = 1;
mic_effect_mic_gain_parm_fill(&cur_mode->parm.mic_gain.val, 1, online);
break;
default:
return -1;
break;
}
return 0;
}
////更新模式参数
static void effect_cfg_fill_mode_parm(u16 mode, u8 online)
{
if (__this == NULL) {
return ;
}
if (mode >= __this->mode_cfg->mode_max) {
log_e("effect mode overlimit, %d, mode max = %d\n", mode, __this->mode_cfg->mode_max);
return ;
}
log_i("mic_effect_change_mode %d\n", mode);
__this->cur_mode_id = mode;
struct __effect_mode *cur_mode = &__this->mode[__this->cur_mode_id];
///根据模式参数配置来更新参数
//<更新reverb参数
if (cur_mode->parm.reverb.flag) {
mic_effect_reverb_parm_fill(&cur_mode->parm.reverb.val, 1, online);
} else {
mic_effect_reverb_parm_fill(NULL, 1, online);
}
//<更新pitch参数
if (cur_mode->parm.pitch.flag) {
mic_effect_pitch_parm_fill(&cur_mode->parm.pitch.val, 1, online);
} else {
mic_effect_pitch_parm_fill(NULL, 1, online);
}
//<更新echo参数
if (cur_mode->parm.ehco.flag) {
mic_effect_echo_parm_fill(&cur_mode->parm.ehco.val, 1, online);
} else {
mic_effect_echo_parm_fill(NULL, 1, online);
}
//<更新噪声门限参数
if (cur_mode->parm.noise.flag) {
mic_effect_noisegate_parm_fill(&cur_mode->parm.noise.val, 1, online);
} else {
mic_effect_noisegate_parm_fill(NULL, 1, online);
}
//<更新喊麦参数
if (cur_mode->parm.shout_wheat.flag) {
mic_effect_shout_wheat_parm_fill(&cur_mode->parm.shout_wheat.val, 1, online);
} else {
mic_effect_shout_wheat_parm_fill(NULL, 1, online);
}
//<更新低音参数
if (cur_mode->parm.low_sound.flag) {
mic_effect_low_sound_parm_fill(&cur_mode->parm.low_sound.val, 1, online);
} else {
mic_effect_low_sound_parm_fill(NULL, 1, online);
}
//<更新高音参数
if (cur_mode->parm.high_sound.flag) {
mic_effect_high_sound_parm_fill(&cur_mode->parm.high_sound.val, 1, online);
} else {
mic_effect_high_sound_parm_fill(NULL, 1, online);
}
//<更新eq参数
if (cur_mode->parm.eq.flag) {
} else {
}
//<更新mic模拟增益参数
if (cur_mode->parm.mic_gain.flag) {
mic_effect_mic_gain_parm_fill(&cur_mode->parm.mic_gain.val, 1, online);
} else {
mic_effect_mic_gain_parm_fill(NULL, 1, online);
}
}
#ifdef CONFIG_AC608N
u16 crc_get_16bit(const void *src, u32 len)
{
/* log_info(__func__); */
u8 *p = (u8 *)src;
u16 ret;
OS_SR_ALLOC();
// vm_mutex_enter();
OS_ENTER_CRITICAL();
JL_CRC->REG = 0 ;
while (len--) {
JL_CRC->FIFO = *p++;
}
__asm__ volatile("csync");
ret = JL_CRC->REG;
OS_EXIT_CRITICAL();
// vm_mutex_exit();
/* printf("CRC16 %02x\r\n", ret); */
return ret;
}
#endif
static s32 effect_cfg_get_file_info(void)
{
unsigned short mode_seq;
unsigned short mode_len;
u16 cur_mode_id = 0;
u8 mode_cnt = 0;
unsigned short magic;
int ret = 0;
int read_size;
FILE *file = NULL;
u8 *file_data = NULL;
u8 *head_buf = NULL;
if (__this == NULL) {
return -EINVAL;
}
file = fopen(__this->mode_cfg->file_path, "r");
if (file == NULL) {
log_error("effects file open err\n");
return -ENOENT;
}
log_info("effects file open ok \n");
// effects ver
u8 fmt = 0;
if (1 != fread(file, &fmt, 1)) {
ret = -EIO;
goto err_exit;
}
u8 ver[4] = {0};
if (4 != fread(file, ver, 4)) {
ret = -EIO;
goto err_exit;
}
if (memcmp(ver, effect_tool_ver, sizeof(effect_tool_ver))) {
log_info("effects ver err \n");
log_info_hexdump(ver, 4);
fseek(file, 0, SEEK_SET);
}
__next_mode:
if (sizeof(unsigned short) != fread(file, &mode_seq, sizeof(unsigned short))) {
ret = 0;
goto err_exit;
}
if (sizeof(unsigned short) != fread(file, &mode_len, sizeof(unsigned short))) {
ret = 0;
goto err_exit;
}
int mode_start = fpos(file);
cur_mode_id = MODE_SEQ_TO_INDEX(mode_seq);
if (cur_mode_id >= __this->mode_cfg->mode_max) {
if (cur_mode_id != 0xdfff) {
log_info("effect mode index err!!!\n");
ret = -EINVAL;
} else {
ret = 0;
}
goto err_exit;
}
log_info("effect mode index = %d\n", cur_mode_id);
while (1) {
//read crc
if (sizeof(unsigned short) != fread(file, &magic, sizeof(unsigned short))) {
ret = 0;
break;
}
int pos = fpos(file);
//read id len
EFFECTS_FILE_HEAD *effect_file_h;
int head_size = sizeof(EFFECTS_FILE_HEAD);
head_buf = malloc(head_size);
if (sizeof(EFFECTS_FILE_HEAD) != fread(file, head_buf, sizeof(EFFECTS_FILE_HEAD))) {
ret = -EIO;
break;
}
effect_file_h = (EFFECTS_FILE_HEAD *)head_buf;
if ((effect_file_h->id >= EFFECTS_CMD_REVERB) && (effect_file_h->id < EFFECTS_CMD_MAX)) {
//reread id len and read data
fseek(file, pos, SEEK_SET);
int data_size = effect_file_h->len + sizeof(EFFECTS_FILE_HEAD);
file_data = malloc(data_size);
if (file_data == NULL) {
ret = -ENOMEM;
break;
}
if (data_size != fread(file, file_data, data_size)) {
ret = -EIO;
break;
}
//compare crc
if (magic == crc_get_16bit(file_data, data_size)) {
u8 *parm = file_data + head_size;
int parm_size = data_size - head_size;
spin_lock(&__this->lock);
log_info("effect_file_h->id %x, %d\n", effect_file_h->id, cur_mode_id);
effect_cfg_update_parm(__this, cur_mode_id, effect_file_h->id, parm, parm_size, 0);
spin_unlock(&__this->lock);
} else {
log_error("effects_cfg_info crc err\n");
ret = -ENOEXEC;
}
free(head_buf);
head_buf = NULL;
free(file_data);
file_data = NULL;
}
int mode_end = fpos(file);
if ((mode_end - mode_start) == mode_len) {
goto __next_mode;
}
}
err_exit:
if (head_buf) {
free(head_buf);
head_buf = NULL;
}
if (file_data) {
free(file_data);
file_data = NULL;
}
fclose(file);
if (ret == 0) {
log_info("effects cfg_info ok \n");
}
return ret;
}
static void effect_tool_change_mode(u16 mode)
{
log_i("effect_tool_change_mode = %d\n", mode);
effect_cfg_fill_mode_parm(mode, 1);
}
static void effect_eq_default_init()
{
#if TCFG_EQ_ENABLE
for (int i = 0; i < __this->mode_cfg->mode_max; i++) {
struct __effect_mode *cur_mode = &__this->mode[i];
cur_mode->seg_num = EFFECT_EQ_SECTION_MAX;
cur_mode->global_gain = 0;
for (int j = 0; j < cur_mode->seg_num; j++) {
memcpy(&cur_mode->parm.eq.val.seg[j],
&eq_tab_normal[0],
sizeof(struct eq_seg_info));
}
cur_mode->eq_design_mask = (u32) - 1;
}
#endif
}
bool effect_cfg_open(struct __effect_mode_cfg *parm)
{
if (__this) {
return true;
}
if (parm == NULL) {
return false;
}
if (parm->attr == NULL) {
return false;
}
if (parm->mode_max == 0) {
return false;
}
__this = zalloc(sizeof(EFFECT_CFG));
__this->mode = (struct __effect_mode *)zalloc(parm->mode_max * sizeof(struct __effect_mode));
__this->mode_cfg = parm;
effect_eq_default_init();
spin_lock_init(&__this->lock);
__this->effect_file_cfg = 1;
if (effect_cfg_get_file_info()) { //获取EFFECTS文件失败
__this->effect_file_cfg = 0;
effect_eq_default_init();
}
__this->cb.priv = __this;
__this->cb.cmd_func = effect_cfg_update_parm;
__this->cb.change_mode = effect_tool_change_mode;
#if TCFG_MIC_EFFECT_ONLINE_ENABLE
effect_tool_open((struct __effect_mode_cfg *)parm, &__this->cb);
#endif
return true;
}
void effect_cfg_close(void)
{
if (!__this) {
return ;
}
effect_tool_close();
void *ptr = __this;
__this = NULL;
free(ptr);
}
int effect_cfg_init(void)
{
effect_cfg_open(&effect_tool_parm);
return 0;
}
__initcall(effect_cfg_init);
void effect_cfg_change_mode(u16 mode)
{
if (__this == NULL) {
return ;
}
if (__this->effect_file_cfg == 0) {
log_e("no effects_cfg file, change mode fail!\n");
return ;
}
effect_cfg_fill_mode_parm(mode, 0);
}
u16 effect_cfg_get_cur_mode(void)
{
return (__this ? __this->cur_mode_id : 0);
}
#endif//TCFG_MIC_EFFECT_ENABLE