Files
99_7018_lmx/cpu/br28/mic_dut_process.c

539 lines
15 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
#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)*/