Files
2025-12-03 11:12:34 +08:00

545 lines
16 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".mic_dut_process.data.bss")
#pragma data_seg(".mic_dut_process.data")
#pragma const_seg(".mic_dut_process.text.const")
#pragma code_seg(".mic_dut_process.text")
#endif
#include "mic_dut_process.h"
#include "app_config.h"
#include "asm/audio_adc.h"
#include "audio_config.h"
#include "asm/dac.h"
#include "audio_dvol.h"
#include "effects/eq_config.h"
#include "circular_buf.h"
#if ((defined TCFG_AUDIO_MIC_DUT_ENABLE) && TCFG_AUDIO_MIC_DUT_ENABLE)
#include "online_debug/aud_mic_dut.h"
/*移植代码时需要重新实现或者修改的函数或者变量
* AUDIO_ADC_CH
* int audio_mic_dut_info_get(mic_dut_info_t *info);
* int audio_mic_dut_dac_start(u32 sr, u16 vol);
* int audio_mic_dut_dac_stop(void);
* int audio_mic_dut_dac_write(s16 *data, int len);
* int audio_mic_en(u8 ,u16, u16, u16. u16, u16, void *);
* int audio_mic_dut_gain_set(u16 gain);
*/
/*mic数据输出开头丢掉的数据包数*/
#define MIC_DUT_IN_DUMP_PACKET 10
/*MIC上行eq*/
#define MIC_DUT_EQ_ENABLE 0
#define AUDIO_ADC_BUF_NUM 3 //mic_adc采样buf个数
#define AUDIO_ADC_IRQ_POINTS 320 //mic_adc采样长度(单位:点数)
#ifdef CONFIG_CPU_BR28
#define AUDIO_ADC_CH 4 //双mic通话
#else
#define AUDIO_ADC_CH 2 //双mic通话
#endif
#define AUDIO_ADC_BUFS_SIZE (AUDIO_ADC_BUF_NUM * AUDIO_ADC_IRQ_POINTS * AUDIO_ADC_CH)
struct audio_mic_hdl {
struct audio_adc_output_hdl adc_output;
struct adc_mic_ch mic_ch;
s16 adc_buf[AUDIO_ADC_BUFS_SIZE]; //align 2Bytes
s16 output_buf[AUDIO_ADC_BUFS_SIZE]; //数据输出缓存
cbuffer_t output_cbuf;
u16 dump_packet;
struct dec_eq_drc *mic_dut_eq;
};
static struct audio_mic_hdl *audio_mic = NULL;
extern struct audio_adc_hdl adc_hdl;
extern struct audio_dac_hdl dac_hdl;
void *mic_dut_eq_open(u32 sample_rate, u8 ch_num)
{
/* #ifdef TCFG_EQ_ENABLE */
#if 0
struct dec_eq_drc *eff = zalloc(sizeof(struct dec_eq_drc));
struct audio_eq_param eq_param = {0};
eq_param.channels = ch_num;
eq_param.online_en = 1;
eq_param.mode_en = 0;
eq_param.remain_en = 0;
eq_param.no_wait = 0;
eq_param.out_32bit = 0;
eq_param.max_nsection = EQ_SECTION_MAX;
eq_param.cb = eq_get_filter_info;
eq_param.eq_name = song_eq_mode;
eq_param.sr = sample_rate;
eff->eq = audio_dec_eq_open(&eq_param);
return eff;
#else
return NULL;
#endif//TCFG_EQ_ENABLE
}
void mic_dut_eq_run(struct dec_eq_drc *eq_drc, void *data, u32 len)
{
/* #ifdef TCFG_EQ_ENABLE */
#if 0
struct dec_eq_drc *eff_hdl = (struct dec_eq_drc *)eq_drc;
if (eff_hdl->eq) {
audio_eq_run(eff_hdl->eq, data, len);
}
#endif/*TCFG_EQ_ENABLE*/
}
void mic_dut_eq_close(struct dec_eq_drc *eq_drc)
{
/* #ifdef TCFG_EQ_ENABLE */
#if 0
struct dec_eq_drc *eff_hdl = (struct dec_eq_drc *)eq_drc;
/* struct audio_eq_drc *eff_hdl = (struct audio_eq_drc *)eq_drc; */
if (eff_hdl->eq) {
audio_dec_eq_close(eff_hdl->eq);
eff_hdl->eq = NULL;
}
free(eff_hdl);
#endif /*TCFG_EQ_ENABLE*/
}
/*获取麦克风测试硬件数据*/
int audio_mic_dut_info_get(mic_dut_info_t *info)
{
mic_dut_info_t mic_info = {
.version = 0x01,
#if (AUDIO_ADC_CH > 2)
.amic_enable_bit = BIT(0) | BIT(1) | BIT(2) | BIT(3),
#elif (AUDIO_ADC_CH > 1)
.amic_enable_bit = BIT(0) | BIT(1),
#else /*AUDIO_ADC_CH == 1*/
.amic_enable_bit = BIT(0),
#endif /*AUDIO_ADC_CH*/
.dmic_enable_bit = 0x00,
.channel = 1,
.bit_wide = 16,
.sr_enable_bit = MIC_ADC_SR_8000 | MIC_ADC_SR_16000 | MIC_ADC_SR_32000,
.sr_default = 16000,
.mic_gain = 19,
.mic_gain_default = 10,
.dac_gain = app_audio_volume_max_query(AppVol_BT_MUSIC),
.dac_gain_default = 2,
};
memcpy(info, &mic_info, sizeof(mic_dut_info_t));
return 0;
}
static dvol_handle *dvol_hdl;
/*打开dac*/
int audio_mic_dut_dac_start(u32 sr, u16 vol)
{
printf("dac sr: %d, vol: %d\n", sr, vol);
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
dvol_hdl = audio_digital_vol_open(vol, app_audio_volume_max_query(AppVol_BT_MUSIC), MUSIC_DVOL_FS, 31);
dvol_hdl->vol_table_default = 1;
audio_digital_vol_set(dvol_hdl, vol);
#endif /*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
printf("cur_vol:%d,max_sys_vol:%d\n", vol, app_audio_volume_max_query(AppVol_BT_MUSIC));
audio_dac_set_sample_rate(&dac_hdl, sr);
audio_dac_start(&dac_hdl);
audio_dac_channel_start(NULL);
return 0;
}
/*关闭dac*/
int audio_mic_dut_dac_stop(void)
{
audio_dac_stop(&dac_hdl);
audio_dac_close(&dac_hdl);
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_close(dvol_hdl);
#endif /*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
return 0;
}
/*写数到dac*/
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
s16 mic_dut_mono_to_dual[AUDIO_ADC_IRQ_POINTS * 2 + 4];
#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/
int audio_mic_dut_dac_write(s16 *data, int len)
{
s16 *dac_data = data;
u16 data_len = len;
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_run(dvol_hdl, dac_data, len);
#endif /*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
for (u16 i = 0; i < (len >> 1); i++) {
mic_dut_mono_to_dual[2 * i] = dac_data[i];
mic_dut_mono_to_dual[2 * i + 1] = dac_data[i];
}
dac_data = mic_dut_mono_to_dual;
data_len = len + data_len;
#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/
return audio_dac_write(&dac_hdl, dac_data, data_len);
}
/*
*********************************************************************
* AUDIO ADC MIC OPEN
* Description: 打开mic通道
* Arguments : mic_ch mic通道 LADC_CH_MIC_R/LADC_CH_MIC_L/AUDIO_ADC_MIC_0/AUDIO_ADC_MIC_1/AUDIO_ADC_MIC_2/AUDIO_ADC_MIC_3
* sr mic采样率 8000/16000/32000/44100/48000
* gain0 mic0增益
* gain1 mic0增益
* gain2 mic0增益
* gain3 mic0增益
* Return : None.
* Note(s) : (1)打开一个mic通道示例:
* audio_mic_en(LADC_CH_MIC_L,16000,10,0,0,0);
* 或者
* audio_mic_en(LADC_CH_MIC_R,16000,10,0,0,0);
* (2)打开两个mic通道示例:
* audio_mic_en(LADC_CH_MIC_R|LADC_CH_MIC_L,16000,10,10,0,0);
*********************************************************************
*/
int audio_mic_en(u8 mic_ch, u16 sr,
u16 gain0, u16 gain1, u16 gain2, u16 gain3,
void (*data_handler)(void *priv, s16 *data, int len))
{
printf("mic ch : %d\n\n", mic_ch);
if (mic_ch) {
if (audio_mic) {
printf("audio_mic re-malloc error\n");
return -1;
}
audio_mic = zalloc(sizeof(struct audio_mic_hdl));
if (audio_mic == NULL) {
printf("audio mic zalloc failed\n");
return -1;
}
#if MIC_DUT_EQ_ENABLE
audio_mic->mic_dut_eq = mic_dut_eq_open(sr, 1);
#endif /*MIC_DUT_EQ_ENABLE*/
cbuf_init(&audio_mic->output_cbuf, audio_mic->output_buf, sizeof(audio_mic->output_buf));
cbuf_clear(&audio_mic->output_cbuf);
/*打开mic电压*/
audio_mic_pwr_ctl(MIC_PWR_ON);
struct mic_open_param mic_param = {0};
if (mic_ch & AUDIO_ADC_MIC_0) {
mic_param.mic_mode = AUDIO_MIC_CAP_MODE;
mic_param.mic_ain_sel = AUDIO_MIC0_CH0;
mic_param.mic_bias_sel = AUDIO_MIC_BIAS_CH0;
mic_param.mic_bias_rsel = 4;
mic_param.mic_dcc = 8;
audio_adc_mic_open(&audio_mic->mic_ch, AUDIO_ADC_MIC_0, &adc_hdl, &mic_param);
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_0, gain0);
audio_adc_mic_gain_boost(AUDIO_ADC_MIC_0, 1);
}
if (mic_ch & AUDIO_ADC_MIC_1) {
mic_param.mic_mode = AUDIO_MIC_CAP_MODE;
mic_param.mic_ain_sel = AUDIO_MIC1_CH0;
mic_param.mic_bias_sel = AUDIO_MIC_BIAS_CH1;
mic_param.mic_bias_rsel = 4;
mic_param.mic_dcc = 8;
audio_adc_mic_open(&audio_mic->mic_ch, AUDIO_ADC_MIC_1, &adc_hdl, &mic_param);
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_1, gain1);
audio_adc_mic_gain_boost(AUDIO_ADC_MIC_1, 1);
}
if (mic_ch & AUDIO_ADC_MIC_2) {
mic_param.mic_mode = AUDIO_MIC_CAP_MODE;
mic_param.mic_ain_sel = AUDIO_MIC2_CH0;
mic_param.mic_bias_sel = AUDIO_MIC_BIAS_CH2;
mic_param.mic_bias_rsel = 4;
mic_param.mic_dcc = 8;
audio_adc_mic_open(&audio_mic->mic_ch, AUDIO_ADC_MIC_2, &adc_hdl, &mic_param);
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_2, gain2);
audio_adc_mic_gain_boost(AUDIO_ADC_MIC_2, 1);
}
if (mic_ch & AUDIO_ADC_MIC_3) {
mic_param.mic_mode = AUDIO_MIC_CAP_MODE;
mic_param.mic_ain_sel = AUDIO_MIC3_CH0;
mic_param.mic_bias_sel = AUDIO_MIC_BIAS_CH3;
mic_param.mic_bias_rsel = 4;
mic_param.mic_dcc = 8;
audio_adc_mic_open(&audio_mic->mic_ch, AUDIO_ADC_MIC_3, &adc_hdl, &mic_param);
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_3, gain3);
audio_adc_mic_gain_boost(AUDIO_ADC_MIC_3, 1);
}
audio_adc_mic_set_sample_rate(&audio_mic->mic_ch, sr);
audio_adc_mic_set_buffs(&audio_mic->mic_ch, audio_mic->adc_buf, AUDIO_ADC_IRQ_POINTS * 2, AUDIO_ADC_BUF_NUM);
audio_mic->adc_output.handler = data_handler;
audio_adc_add_output_handler(&adc_hdl, &audio_mic->adc_output);
audio_adc_mic_start(&audio_mic->mic_ch);
/*清掉mic开头几包数据*/
audio_mic->dump_packet = MIC_DUT_IN_DUMP_PACKET;
} else {
if (audio_mic) {
audio_adc_mic_close(&audio_mic->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &audio_mic->adc_output);
audio_mic_pwr_ctl(MIC_PWR_OFF);
#if MIC_DUT_EQ_ENABLE
mic_dut_eq_close(audio_mic->mic_dut_eq);
#endif /*MIC_DUT_EQ_ENABLE*/
free(audio_mic);
audio_mic = NULL;
}
}
return 0;
}
/*设置mic增益*/
int audio_mic_dut_gain_set(u16 gain)
{
if (audio_mic) {
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_0, gain);
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_1, gain);
#if (AUDIO_ADC_CH > 2)
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_2, gain);
audio_adc_mic_set_gain(&audio_mic->mic_ch, AUDIO_ADC_MIC_3, gain);
#endif /*AUDIO_ADC_CH*/
}
return 0;
}
/*
*********************************************************************
* Comfort Noise Generator
* Description: 舒适噪声生成
* Arguments : state 伪随机数生成状态
* gain 舒适噪声的增益
* data 待添加舒适噪声的数据
* npoint 待添加舒适噪声的数据长度
* Return : None.
* Note(s) : 增益计算公式:gain cal(python):
* >>>import math
* >>>gain=math.pow(10,gain_db/20.)*2**20;
* >>>print(gain)
*********************************************************************
*/
//int wn_gain = 1865; /*Normal*/
//int wn_gain = 1<<19;
//
static unsigned int next = 457;
void set_srand(unsigned int seek)
{
next = seek;
}
static int my_rand()
{
next = next * 1103515245 + 12345;
return next >> 16;
}
#define COMFORT_NOISE_SEED 457
static unsigned int seed = COMFORT_NOISE_SEED;
void set_comfort_noise_seed(unsigned int sd)
{
seed = sd;
set_srand(sd);
}
static void comfort_noise_run(unsigned int *state, int gain, short *data, int npoint)
{
for (int i = 0; i < npoint; i++) {
#if 0
*state = (*state * 1103515245 + 12345) & 0x7fffffff;
int tmp32 = (*state >> 15) - (1 << 15);
tmp32 = (long long)tmp32 * gain >> 20;
tmp32 += data[i];
if (tmp32 > 32767) {
tmp32 = 32767;
}
if (tmp32 < -32768) {
tmp32 = -32768;
}
data[i] = tmp32;
#else
short tmp16 = (short)my_rand();
int tmp32 = ((long long)tmp16 * gain) >> 20;
if (tmp32 > 32767) {
tmp32 = 32767;
}
if (tmp32 < -32768) {
tmp32 = -32768;
}
data[i] = (short)tmp32;
#endif
}
}
/*
*********************************************************************
* AUDIO MIC OUTPUT
* Description: mic采样数据回调
* Arguments : pric 私有参数
* data mic数据
* len 数据长度
* Return : 0 成功 其他 失败
* Note(s) : 单声道数据格式
* L0 L1 L2 L3 L4 ...
* 双声道数据格式()
* L0 R0 L1 R1 L2 R2...
*********************************************************************
*/
void audio_mic_dut_eq_run(s16 *data, int len)
{
#if MIC_DUT_EQ_ENABLE
u8 scan_start = mic_dut_online_get_scan_state();
if (scan_start && audio_mic) {
mic_dut_eq_run(audio_mic->mic_dut_eq, data, len);
}
#endif /*MIC_DUT_EQ_ENABLE*/
}
static void audio_mic_dut_output_handle(void *priv, s16 *data, int len)
{
if (audio_mic) {
s16 *mic_data = data;
int wlen;
u8 mic_idx = mic_dut_online_get_mic_idx();
u8 mic_start = mic_dut_online_get_mic_state();
u8 scan_start = mic_dut_online_get_scan_state();
/* printf("mic_data:%x,%d\n",data,len); */
for (u16 i = 0; i < (len >> 1); i++) {
mic_data[i] = data[i * AUDIO_ADC_CH + mic_idx];
}
/*清掉开头10包数据*/
if (audio_mic->dump_packet) {
audio_mic->dump_packet --;
}
if ((mic_start || scan_start) && !audio_mic->dump_packet) {
#if MIC_DUT_EQ_ENABLE
/* if(scan_start) { */
/* mic_dut_eq_run(audio_mic->mic_dut_eq, mic_data, len); */
/* } */
#endif /*MIC_DUT_EQ_ENABLE*/
wlen = cbuf_write(&audio_mic->output_cbuf, mic_data, len);
if (wlen != len) {
printf("dut out buf full !!!\n");
}
}
/*dac播放白噪*/
if (scan_start && !audio_mic->dump_packet) {
s16 tmpbuf[AUDIO_ADC_IRQ_POINTS];
comfort_noise_run(&seed, 1048576, tmpbuf, len / 2);
wlen = audio_mic_dut_dac_write(tmpbuf, len);
if (wlen != len) {
printf("dut scan dac write fail !!!\n");
}
}
mic_dut_online_sem_post();
}
}
int audio_mic_dut_sample_rate_set(u32 sr)
{
return 0;
}
int audio_mic_dut_amic_select(u8 idx)
{
return 0;
}
int audio_mic_dut_dmic_select(u8 idx)
{
return 0;
}
/*打开mic*/
int audio_mic_dut_start(void)
{
u8 amic_enable_bit = mic_dut_online_amic_enable_bit();
u16 gain = mic_dut_online_get_mic_gain();
u32 sr = mic_dut_online_get_sample_rate();
/*打开所有MIC*/
audio_mic_en(amic_enable_bit,
sr,
gain,
gain,
gain,
gain,
audio_mic_dut_output_handle);
return 0;
}
/*关闭mic*/
int audio_mic_dut_stop(void)
{
/*关闭所有MIC*/
audio_mic_en(0, 0,
0, 0, 0, 0,
NULL);
return 0;
}
/*获取mic数据*/
int audio_mic_dut_data_get(s16 *data, int len)
{
/*获取对应的MIC数据,并返回获取到的数据大小*/
int rlen = 0;
if (audio_mic) {
rlen = cbuf_read(&audio_mic->output_cbuf, data, len);
}
return rlen;
}
/*获取mic缓存数据长度*/
int audio_mic_dut_get_data_len(void)
{
return cbuf_get_data_len(&audio_mic->output_cbuf);
}
/*设置dac输出音量*/
int audio_mic_dut_dac_gain_set(u16 gain)
{
return 0;
}
/*开始mic频响扫描*/
int audio_mic_dut_scan_start(void)
{
u32 sr = mic_dut_online_get_sample_rate();
u16 vol = mic_dut_online_get_dac_gain();
/*重置随机白噪声种子*/
set_comfort_noise_seed(COMFORT_NOISE_SEED);
// 打开DAC
audio_mic_dut_dac_start(sr, vol);
// 打开mic
audio_mic_dut_start();
return 0;
}
/*关闭mic频响扫描*/
int audio_mic_dut_scan_stop(void)
{
//关闭mic
audio_mic_dut_stop();
// DAC 关闭
audio_mic_dut_dac_stop();
return 0;
}
#endif /*((defined TCFG_AUDIO_MIC_DUT_ENABLE) && TCFG_AUDIO_MIC_DUT_ENABLE)*/