回采的数据是在中断函数au0_dma_isr_data_output里面给的,而给算法的时候是在主程序karaok_sdadc_process,这样子就会出现中断给的数据和当前的mic帧不匹配,或者说每次的差值不一定,算法就会有问题,解决办法是讲回采数据放入队列,给个缓冲区来循环取放值,这样子缓存去的数据先进先出,就可以实现存取长时间的数据,在这长时间的情况下,一定能轮到另外一边主程序karaok_sdadc_process运行,以拿到数据
错误模型如下,没加循环缓存
cpp
#include "include.h"
#include "func.h"
#include "karaok_list.h"
#if SYS_KARAOK_EN
#define AUDIO_DEBUG
/*****************************************************************************
* Module :
*****************************************************************************/
extern u8 mdac_spr_hold; //开启将MDAC的采样率固定为跟LR一样
void bt_aec_process(u8 *ptr, u32 samples, int ch_mode);
void bt_sco_tx_process(u8 *ptr, u32 samples, int ch_mode);
static karaok_list_cfg_t karaok_list_cfg AT(.func_list.cfg.karaok);
static module_link_list_str_t karaok_link_list_tbl[] = {
/* 模块类型, 使能, 初始化, 输入接口, 设置输出*/
{KARAOK_INPUT_TYPE, 1, karaok_audio_init, karaok_audio_input, karaok_audio_output_callback_set},
// {MIC_MSC_HIFI4_EFFECT_TYPE, 1, mic_hifi4_effect_audio_init, mic_hifi4_effect_audio_buf_input, mic_hifi4_effect_audio_output_callback_set},
// {SRC1_OUT_TYPE, 1, src1_out_init, src1_out_audio_input, NULL},
{SRC2_OUT_TYPE, 1, src2_out_init, src2_out_audio_input, NULL},
};
#define MICBUF_LENGTH 4096
WEAK uint32_t micbuf_length_weak = MICBUF_LENGTH;
u8 ude_micbuf[MICBUF_LENGTH] AT(.ude.aubuf);//这个变量也要跟buf一样大小
short mic_buff[MIC_SAMPLES_LEN] AT(.mic_algo.buf);
short aec_mic_buff[AEC_MIC_48K_EACH_SAMPLES_LEN] AT(.mic_algo.buf);
short aec222_mic_buff[AEC_MIC_48K_EACH_SAMPLES_LEN] AT(.usb_222dev.buf);
#ifdef TEST_MODE
short interleaved_channel_buff[MIC_SAMPLES_16K_STEP] AT(.mic_algo.buf);
#endif
#if DAC_DMA_OUTPUT_EN || FUNC_REC_EN
#define DAC_DMA_OUTPUT_SAMPLES MIC_EACH_BUFF_LEN //byte not short
u8 au0_dma_buff[DAC_DMA_OUTPUT_SAMPLES*4] AT(.au0out_buf); //DMA OUT的中断缓存,至少为 au0_dma_start_do 的 samples*2*(1<<is_24bits)*2 Byte
void au0_dma_start_do(u32 type, u8 *au0_dma_addr, u16 samples, u8 is_24bits);
AT(.text.au0dma) WEAK
void au0_dma_start(u32 type)
{
au0_dma_start_do(type, au0_dma_buff, DAC_DMA_OUTPUT_SAMPLES, 0);
}
#if DAC_DMA_OUTPUT_EN
#ifdef AUDIO_DEBUG
AT(.com_text.au0dma1)
const char au0_dma_output_str[] = "au0_size_1s_sampling_rate:%d, size:%d\n";
#endif
AT(.com_text.au0dma)
void au0_dma_isr_data_output(void *ptr/*16bit stereo*/, u32 size/*Byte*/)//采样率只可以设置成48k或者44.1k
{
// for (u32 i = MIC_SAMPLES_AEC_STEP, j = 0; i < MIC_SAMPLES_LEN; i+=3, j+=2){
// mic_buff[i] = (*((short *)ptr+j) + *((short *)ptr+j+1))/2;
// }
// for (u32 i = MIC_SAMPLES_AEC_STEP, j = 0; i < MIC_SAMPLES_16K_STEP; i++, j+=2){
// mic_buff[i] = (*((short *)ptr+j) + *((short *)ptr+j+1))/2;
// }
for (u32 i = 0, j = 0; i < AEC_MIC_48K_EACH_SAMPLES_LEN; i++, j+=2){
aec_mic_buff[i] = (*((short *)ptr+j) + *((short *)ptr+j+1))/2;
}
#ifdef AUDIO_DEBUG
static u32 ticks = 0;
static u32 sampling_rate = 0;
sampling_rate += size/4;//双通道,16位,byte,48k
if (tick_check_expire(ticks, 1000)) {
ticks = tick_get();
my_printf(au0_dma_output_str, sampling_rate, size);//采样率只可以设置成48k或者44.1k
sampling_rate = 0;
}
#endif
}
#endif // DAC_DMA_OUTPUT_EN
#endif // DAC_DMA_OUTPUT_EN || FUNC_REC_EN
AT(.com_text.func_list.karaok)
void my_algo_process(short *ptr)
{
for(int i = 0; i < MIC_48K_EACH_SAMPLES_LEN; i++)
{
ptr[i] = 10 * ptr[i + MIC_SAMPLES_MIC_STEP];//algo
}
for(int i = 0, j = 0; i < MIC_48K_EACH_SAMPLES_LEN; i+=3, j++)
{
ptr[j + MIC_SAMPLES_16K_STEP] = ptr[i];//16k
}
for(int i = 0, j = 0; i < MIC_48K_EACH_SAMPLES_LEN; i+=6, j++)
{
ptr[j + MIC_SAMPLES_8K_STEP] = ptr[i];//8k
}
}
#ifdef TEST_MODE
AT(.com_text.func_list.karaok)
void interleaved_channel(short *scr, short *dst)
{
for(int i = 0, j = 0; i < MIC_48K_EACH_SAMPLES_LEN; i++, j+=3)
{
dst[j] = scr[i + MIC_SAMPLES_ALGO_STEP];//algo
dst[j + 1] = scr[i + MIC_SAMPLES_MIC_STEP];//mic
dst[j + 2] = scr[i + MIC_SAMPLES_AEC_STEP];//aec
}
}
#endif
AT(.com_text.func_list.karaok)
void karaok_audio_init(u8 sample_rate, u16 samples, u8 channel)
{
memset(&karaok_list_cfg, 0, sizeof(karaok_list_cfg_t));
karaok_list_cfg.sample_rate = sample_rate;
my_printf("%s: MDACVOLCON %x\n", __func__, MDACVOLCON);
my_printf("%s: sample_rate %d\n", __func__, sample_rate);
// bsp_change_md_volume(4, 1);//调节mdac输出音量
my_printf("%s: MDACVOLCON %x\n", __func__, MDACVOLCON);
my_printf("%s: bt_sco_is_msbd %d\n", __func__, bt_sco_is_msbc());//判断蓝牙录音的采样率:1(16k),0(8k)
// mdac_spr_set(SPR_16000);
mdac_spr_hold = 0;
}
AT(.com_text.func_list.karaok)
void karaok_audio_input(u8 *ptr, u32 samples, int ch_mode, u32 is_24bits, void *param)
{
if (karaok_list_cfg.callback) {
karaok_list_cfg.callback((u8 *)mic_buff, samples, MIC_CHANNEL, is_24bits, param);
}
}
AT(.text.src)
void karaok_audio_output_callback_set(audio_callback_t callback)
{
karaok_list_cfg.callback = callback;
}
AT(.text.bsp.bsp.unicast)
void karaok_module_init(u8 sample_rate)
{
// my_printf("%s\n", __func__);
my_printf("%s: sample_rate %d\n", __func__, sample_rate);
module_link_list_init(karaok_link_list_tbl,
sizeof(karaok_link_list_tbl)/sizeof(module_link_list_str_t), sample_rate, 10, 2);
}
AT(.text.bsp.bsp.unicast)
void karaok_module_exit(void)
{
// my_printf("%s\n", __func__);
src1_fade_out();
}
//AT(.com_text.karaok.proc1)
//const char k_sdadc_str[] = "get_karaok_sco_sta():%d, sample_cnt:%d\n";
AT(.com_text.karaok.proc)
void karaok_sdadc_process(u8 *ptr, u32 samples, int ch_mode)
{
u8 channel = (ch_mode&BIT(0)) + 1;
u8 in_24bits = (ch_mode&BIT(1)) ? 1 : 0;
memcpy(mic_buff + MIC_SAMPLES_MIC_STEP, ptr, MIC_48K_EACH_SAMPLES_LEN * sizeof(short));
memcpy(mic_buff + MIC_SAMPLES_AEC_STEP, aec_mic_buff, MIC_48K_EACH_SAMPLES_LEN * sizeof(short));
#ifdef AUDIO_DEBUG
static u32 p_algo_ticks = 0;
static u32 n_algo_ticks = 0;
static u32 lastTimestamp = 0;
static u32 timeInterval = 0;
p_algo_ticks = tick_get();
if (lastTimestamp != 0) {
timeInterval = p_algo_ticks - lastTimestamp;
}
lastTimestamp = p_algo_ticks;
#endif //AUDIO_DEBUG
hifi4_effect_mic_process_new(XTP_EFFECT_ID_SPEAKER, (u8 *)mic_buff, MIC_SAMPLES_LEN, MIC_CHANNEL, 0);
// my_algo_process(mic_buff);
#ifdef AUDIO_DEBUG
n_algo_ticks = tick_get();
#endif//AUDIO_DEBUG
if (dev_is_online(DEV_USBPC)) {
#ifdef TEST_MODE
interleaved_channel(mic_buff, interleaved_channel_buff);
usbmic_sdadc_process((u8 *)interleaved_channel_buff, samples, MIC_TEST_CHANNEL);
#else
usbmic_sdadc_process((u8 *)mic_buff, samples, MIC_CHANNEL);
#endif//TEST_MODE
}
audio_process_param_t audio_process_param;
audio_process_param.link_id = INPUT_MIC_ID;
if (get_karaok_sco_sta()) {
if (bt_sco_is_msbc()) {
bt_sco_tx_process((u8 *)(mic_buff + MIC_SAMPLES_16K_STEP), MIC_16K_EACH_SAMPLES_LEN, 0);
}else{
bt_sco_tx_process((u8 *)(mic_buff + MIC_SAMPLES_8K_STEP), MIC_8K_EACH_SAMPLES_LEN, 0);
}
}
// mdac_spr_set(SPR_16000);
karaok_audio_input((u8 *)mic_buff, samples, channel, in_24bits, &audio_process_param);
#ifdef AUDIO_DEBUG
static u32 ticks = 0;
static u32 sampling_rate = 0;
sampling_rate += samples;
if (tick_check_expire(ticks, 1000)) {
ticks = tick_get();
printf("%s: samples = %d, sampling_rate = %d, channel = %d, usb_connect = %d, bt_phone = %d, bt_is_16k = %d, algo_time = %d timeInterval = %d\n",
__func__, samples, sampling_rate, channel, dev_is_online(DEV_USBPC), get_karaok_sco_sta(), bt_sco_is_msbc(), n_algo_ticks - p_algo_ticks, timeInterval);
sampling_rate = 0;
}
#endif//AUDIO_DEBUG
}
#endif //SYS_KARAOK_EN
正确模型如下,加循环缓存
cpp
#include "include.h"
#include "func.h"
#include "karaok_list.h"
#if SYS_KARAOK_EN
// #define AUDIO_DEBUG
/*****************************************************************************
* Module :
*****************************************************************************/
extern u8 mdac_spr_hold; //开启将MDAC的采样率固定为跟LR一样
void bt_aec_process(u8 *ptr, u32 samples, int ch_mode);
void bt_sco_tx_process(u8 *ptr, u32 samples, int ch_mode);
static karaok_list_cfg_t karaok_list_cfg AT(.func_list.cfg.karaok);
static module_link_list_str_t karaok_link_list_tbl[] = {
/* 模块类型, 使能, 初始化, 输入接口, 设置输出*/
{KARAOK_INPUT_TYPE, 1, karaok_audio_init, karaok_audio_input, karaok_audio_output_callback_set},
// {MIC_MSC_HIFI4_EFFECT_TYPE, 1, mic_hifi4_effect_audio_init, mic_hifi4_effect_audio_buf_input, mic_hifi4_effect_audio_output_callback_set},
// {SRC1_OUT_TYPE, 1, src1_out_init, src1_out_audio_input, NULL},
{SRC2_OUT_TYPE, 1, src2_out_init, src2_out_audio_input, NULL},
};
#define MICBUF_LENGTH 4096
WEAK uint32_t micbuf_length_weak = MICBUF_LENGTH;
u8 ude_micbuf[MICBUF_LENGTH] AT(.ude.aubuf);//这个变量也要跟buf一样大小
short mic_buff[MIC_SAMPLES_LEN] AT(.mic_algo.buf);
short aec_mic_stm_buff[AEC_MIC_48K_EACH_SAMPLES_LEN * 3] AT(.aec_mic.buf);
au_stm_t aw_stm AT(.aec_mic.buf);
#ifdef TEST_MODE
short interleaved_channel_buff[MIC_SAMPLES_16K_STEP] AT(.mic_algo.buf);
#endif
#if DAC_DMA_OUTPUT_EN || FUNC_REC_EN
#define DAC_DMA_OUTPUT_SAMPLES MIC_EACH_BUFF_LEN //byte not short
u8 au0_dma_buff[DAC_DMA_OUTPUT_SAMPLES*4] AT(.au0out_buf); //DMA OUT的中断缓存,至少为 au0_dma_start_do 的 samples*2*(1<<is_24bits)*2 Byte
void au0_dma_start_do(u32 type, u8 *au0_dma_addr, u16 samples, u8 is_24bits);
AT(.text.au0dma) WEAK
void au0_dma_start(u32 type)
{
memset(aec_mic_stm_buff, 0, sizeof(aec_mic_stm_buff));
memset(&aw_stm, 0, sizeof(au_stm_t));
aw_stm.buf = (u8 *)aec_mic_stm_buff;
aw_stm.size = sizeof(aec_mic_stm_buff);
aw_stm.len = 0;
aw_stm.wptr = (u8 *)aec_mic_stm_buff;
aw_stm.rptr = (u8 *)aec_mic_stm_buff;//初始化循环buf
au0_dma_start_do(type, au0_dma_buff, DAC_DMA_OUTPUT_SAMPLES, 0);
}
#if DAC_DMA_OUTPUT_EN
#ifdef AUDIO_DEBUG
AT(.com_text.au0dma1)
const char au0_dma_output_str[] = "au0_size_1s_sampling_rate:%d, size:%d\n";
#endif
AT(.com_text.au0dma)
void au0_dma_isr_data_output(void *ptr/*16bit stereo*/, u32 size/*Byte*/)//采样率只可以设置成48k或者44.1k
{
short aec_mic_buff[AEC_MIC_48K_EACH_SAMPLES_LEN];
for (u32 i = 0, j = 0; i < AEC_MIC_48K_EACH_SAMPLES_LEN; i++, j+=2){
aec_mic_buff[i] = (*((short *)ptr+j) + *((short *)ptr+j+1))/2;
}
puts_stm_buf(&aw_stm, (u8 *)aec_mic_buff, sizeof(aec_mic_buff));//数据放入循环buf
#ifdef AUDIO_DEBUG
static u32 ticks = 0;
static u32 sampling_rate = 0;
sampling_rate += size/4;//双通道,16位,byte,48k
if (tick_check_expire(ticks, 1000)) {
ticks = tick_get();
my_printf(au0_dma_output_str, sampling_rate, size);//采样率只可以设置成48k或者44.1k
sampling_rate = 0;
}
#endif
}
#endif // DAC_DMA_OUTPUT_EN
#endif // DAC_DMA_OUTPUT_EN || FUNC_REC_EN
AT(.com_text.func_list.karaok)
void my_algo_process(short *ptr)
{
for(int i = 0; i < MIC_48K_EACH_SAMPLES_LEN; i++)
{
ptr[i] = 10 * ptr[i + MIC_SAMPLES_MIC_STEP];//algo
}
for(int i = 0, j = 0; i < MIC_48K_EACH_SAMPLES_LEN; i+=3, j++)
{
ptr[j + MIC_SAMPLES_16K_STEP] = ptr[i];//16k
}
for(int i = 0, j = 0; i < MIC_48K_EACH_SAMPLES_LEN; i+=6, j++)
{
ptr[j + MIC_SAMPLES_8K_STEP] = ptr[i];//8k
}
}
#ifdef TEST_MODE
AT(.com_text.func_list.karaok)
void interleaved_channel(short *scr, short *dst)
{
for(int i = 0, j = 0; i < MIC_48K_EACH_SAMPLES_LEN; i++, j+=3)
{
dst[j] = scr[i + MIC_SAMPLES_ALGO_STEP];//algo
dst[j + 1] = scr[i + MIC_SAMPLES_MIC_STEP];//mic
dst[j + 2] = scr[i + MIC_SAMPLES_AEC_STEP];//aec
}
}
#endif
AT(.com_text.func_list.karaok)
void karaok_audio_init(u8 sample_rate, u16 samples, u8 channel)
{
memset(&karaok_list_cfg, 0, sizeof(karaok_list_cfg_t));
karaok_list_cfg.sample_rate = sample_rate;
my_printf("%s: MDACVOLCON %x\n", __func__, MDACVOLCON);
my_printf("%s: sample_rate %d\n", __func__, sample_rate);
// bsp_change_md_volume(4, 1);//调节mdac输出音量
my_printf("%s: MDACVOLCON %x\n", __func__, MDACVOLCON);
my_printf("%s: bt_sco_is_msbd %d\n", __func__, bt_sco_is_msbc());//判断蓝牙录音的采样率:1(16k),0(8k)
// mdac_spr_set(SPR_16000);
mdac_spr_hold = 0;
}
AT(.com_text.func_list.karaok)
void karaok_audio_input(u8 *ptr, u32 samples, int ch_mode, u32 is_24bits, void *param)
{
if (karaok_list_cfg.callback) {
karaok_list_cfg.callback((u8 *)mic_buff, samples, MIC_CHANNEL, is_24bits, param);
}
}
AT(.text.src)
void karaok_audio_output_callback_set(audio_callback_t callback)
{
karaok_list_cfg.callback = callback;
}
AT(.text.bsp.bsp.unicast)
void karaok_module_init(u8 sample_rate)
{
// my_printf("%s\n", __func__);
my_printf("%s: sample_rate %d\n", __func__, sample_rate);
module_link_list_init(karaok_link_list_tbl,
sizeof(karaok_link_list_tbl)/sizeof(module_link_list_str_t), sample_rate, 10, 2);
}
AT(.text.bsp.bsp.unicast)
void karaok_module_exit(void)
{
// my_printf("%s\n", __func__);
src1_fade_out();
}
//AT(.com_text.karaok.proc1)
//const char k_sdadc_str[] = "get_karaok_sco_sta():%d, sample_cnt:%d\n";
AT(.com_text.karaok.proc)
void karaok_sdadc_process(u8 *ptr, u32 samples, int ch_mode)
{
u8 channel = (ch_mode&BIT(0)) + 1;
u8 in_24bits = (ch_mode&BIT(1)) ? 1 : 0;
memcpy(mic_buff + MIC_SAMPLES_MIC_STEP, ptr, MIC_48K_EACH_SAMPLES_LEN * sizeof(short));
gets_stm_buf(&aw_stm, (u8 *)(mic_buff + MIC_SAMPLES_AEC_STEP), AEC_MIC_48K_EACH_SAMPLES_LEN * sizeof(short));//从循环buf拿数据
#ifdef AUDIO_DEBUG
static u32 p_algo_ticks = 0;
static u32 n_algo_ticks = 0;
static u32 lastTimestamp = 0;
static u32 timeInterval = 0;
p_algo_ticks = tick_get();
if (lastTimestamp != 0) {
timeInterval = p_algo_ticks - lastTimestamp;
}
lastTimestamp = p_algo_ticks;
#endif //AUDIO_DEBUG
// hifi4_effect_mic_process_new(XTP_EFFECT_ID_SPEAKER, (u8 *)mic_buff, MIC_SAMPLES_LEN, MIC_CHANNEL, 0);
my_algo_process(mic_buff);
#ifdef AUDIO_DEBUG
n_algo_ticks = tick_get();
#endif//AUDIO_DEBUG
if (dev_is_online(DEV_USBPC)) {
#ifdef TEST_MODE
interleaved_channel(mic_buff, interleaved_channel_buff);
usbmic_sdadc_process((u8 *)interleaved_channel_buff, samples, MIC_TEST_CHANNEL);
#else
usbmic_sdadc_process((u8 *)mic_buff, samples, MIC_CHANNEL);
#endif//TEST_MODE
}
audio_process_param_t audio_process_param;
audio_process_param.link_id = INPUT_MIC_ID;
if (get_karaok_sco_sta()) {
if (bt_sco_is_msbc()) {
bt_sco_tx_process((u8 *)(mic_buff + MIC_SAMPLES_16K_STEP), MIC_16K_EACH_SAMPLES_LEN, 0);
}else{
bt_sco_tx_process((u8 *)(mic_buff + MIC_SAMPLES_8K_STEP), MIC_8K_EACH_SAMPLES_LEN, 0);
}
}
// mdac_spr_set(SPR_16000);
karaok_audio_input((u8 *)mic_buff, samples, channel, in_24bits, &audio_process_param);
#ifdef AUDIO_DEBUG
static u32 ticks = 0;
static u32 sampling_rate = 0;
sampling_rate += samples;
if (tick_check_expire(ticks, 1000)) {
ticks = tick_get();
printf("%s: samples = %d, sampling_rate = %d, channel = %d, usb_connect = %d, bt_phone = %d, bt_is_16k = %d, algo_time = %d timeInterval = %d\n",
__func__, samples, sampling_rate, channel, dev_is_online(DEV_USBPC), get_karaok_sco_sta(), bt_sco_is_msbc(), n_algo_ticks - p_algo_ticks, timeInterval);
sampling_rate = 0;
}
#endif//AUDIO_DEBUG
}
#endif //SYS_KARAOK_EN