Files
99_7018_lmx/cpu/br28/mic_dut_process.c
2025-10-29 13:10:02 +08:00

539 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "mic_dut_process.h"
#include "audio_enc.h"
#include "app_config.h"
#include "audio_adc.h"
#include "audio_config.h"
#include "asm/dac.h"
#include "audio_dvol.h"
#include "application/eq_config.h"
#include "audio_dec_eff.h"
/* #include "sound_device.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 1
#define AUDIO_ADC_BUF_NUM 3 //mic_adc采样buf个数
#define AUDIO_ADC_IRQ_POINTS 320 //mic_adc采样长度单位点数
#define AUDIO_ADC_CH 4 //双mic通话
#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)
{
#if TCFG_EQ_ENABLE
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)
{
struct dec_eq_drc *eff_hdl = (struct dec_eq_drc *)eq_drc;
#if TCFG_EQ_ENABLE
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)
{
#if TCFG_EQ_ENABLE
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 = 15,
.dac_gain_default = 2,
};
memcpy(info, &mic_info, sizeof(mic_dut_info_t));
return 0;
}
/* struct audio_dac_channel mic_dut_dac_ch; */
/*打开dac*/
int audio_mic_dut_dac_start(u32 sr, u16 vol)
{
printf("dac sr: , vol: %d\n", sr, vol);
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, vol, 0);
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_open(MUSIC_DVOL, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), MUSIC_DVOL_MAX, MUSIC_DVOL_FS, -1);
#endif /*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
#if 0
// DAC 初始化
audio_dac_new_channel(&dac_hdl, &mic_dut_dac_ch);
struct audio_dac_channel_attr attr;
attr.delay_time = 20;
attr.protect_time = 8;
attr.write_mode = WRITE_MODE_BLOCK;
audio_dac_channel_set_attr(&mic_dut_dac_ch, &attr);
sound_pcm_dev_start(&mic_dut_dac_ch, sr, app_audio_get_volume(APP_AUDIO_STATE_MUSIC));
#else
audio_dac_set_volume(&dac_hdl, vol);
audio_dac_set_sample_rate(&dac_hdl, sr);
audio_dac_start(&dac_hdl);
#endif
return 0;
}
/*关闭dac*/
int audio_mic_dut_dac_stop(void)
{
#if 0
sound_pcm_dev_stop(&mic_dut_dac_ch);
#else
audio_dac_stop(&dac_hdl);
#endif
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_close(MUSIC_DVOL);
#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(MUSIC_DVOL, 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*/
#if 0
int wlen = 0;
int offset = 0;
int cnt = 0;
do {
wlen = sound_pcm_dev_write(&mic_dut_dac_ch, dac_data + (offset >> 1), data_len - offset);
offset = offset + wlen;
cnt ++;
} while ((offset != data_len) && (cnt < 1000));
return offset;
#else
return audio_dac_write(&dac_hdl, dac_data, data_len);
#endif
}
/*
*********************************************************************
* 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);
/*打开mic0*/
if (mic_ch & BIT(0)) {
printf("adc_mic0 open, sr:%d, gain:%d\n", sr, gain0);
audio_adc_mic_open(&audio_mic->mic_ch, mic_ch, &adc_hdl);
audio_adc_mic_set_gain(&audio_mic->mic_ch, gain0);
}
/*打开mic1*/
if (mic_ch & BIT(1)) {
printf("adc_mic1 open, sr:%d, gain:%d\n", sr, gain1);
audio_adc_mic1_open(&audio_mic->mic_ch, mic_ch, &adc_hdl);
audio_adc_mic1_set_gain(&audio_mic->mic_ch, gain1);
}
#if (AUDIO_ADC_CH > 2)
/*打开mic2*/
if (mic_ch & BIT(2)) {
printf("adc_mic2 open, sr:%d, gain:%d\n", sr, gain2);
audio_adc_mic2_open(&audio_mic->mic_ch, mic_ch, &adc_hdl);
audio_adc_mic2_set_gain(&audio_mic->mic_ch, gain2);
}
/*打开mic3*/
if (mic_ch & BIT(3)) {
printf("adc_mic3 open, sr:%d, gain:%d\n", sr, gain3);
audio_adc_mic3_open(&audio_mic->mic_ch, mic_ch, &adc_hdl);
audio_adc_mic3_set_gain(&audio_mic->mic_ch, gain3);
}
#endif /*AUDIO_ADC_CH*/
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, gain);
audio_adc_mic1_set_gain(&audio_mic->mic_ch, gain);
#if (AUDIO_ADC_CH > 2)
audio_adc_mic2_set_gain(&audio_mic->mic_ch, gain);
audio_adc_mic3_set_gain(&audio_mic->mic_ch, 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)
{
u8 scan_start = mic_dut_online_get_scan_state();
#if MIC_DUT_EQ_ENABLE
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 = 0;
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)
{
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, gain, 0);
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)*/