目前成果:speaker读本地数据,mic录实时数据,可以90%消除回音,AecDelay还需调优,NS和VAD正常可用。先保证AEC正常,下一步speaker实时网络数据,离Double Talk 还有很长一段路,加油!
效果图:
实时音频回音消除流程图:
关键知识点:
1、回音消除目的是实现双向对讲(double talk)
2、硬件要求,低端设备视频音频加AEC后CPU(99%),声音一卡一卡,AEC没法运算。目前只做双向语音对讲,关闭设备视频录像,解决。
3、speaker为放大电路播放的数据能量太大,AEC无法精确消除,出现真声和回声都消除的现象。调试阶段手动降低speaker放大参数,解决。
//------------------------------------------------------Demo Start------------------------------------------------------------------------------------//
while(1)
{
if (3200 == fread(far_frame_c, sizeof(char), 3200, fp_far))
{
fread(near_frame_c, sizeof(char), 3200, fp_near);
for(i = 0;i < NN*10; i++) {
far_frame_s[i] = (far_frame_c[i*2+1]<< 8) | (far_frame_c[i*2]&0xFF);//两个char型拼成一个short
far_frame[i] = far_frame_s[i];//转float型接口需要
near_frame_s[i] = (near_frame_c[i*2+1]<<8) | (near_frame_c[i*2]&0xFF);
near_frame[i] = near_frame_s[i];
}
for(i = 0 ;i < 10;i ++) {
NOTICE("AEC_BufferFarend......\n");
EWebRtcAEC_BufferFarend(handleAec, far_frame+NN*i, NN);//对参考声音(回声)的处理
NOTICE("AEC_Processs......\n");
EWebRtcAEC_Process(handleAec,near_frame+NN*i,1, aecout_frame+NN*i,NN,AecDelay,0);//回声消除
}
for(i = 0; i < NN*10; i ++) {
aecout_frame_s[i] = aecout_frame[i];
}
fwrite(aecout_frame_s, sizeof(short),NN*10, fp_outAec);
#if 0 //NS
NOTICE("NS_Processs......\n");
EWebRtcNS_Analyze(handleNS,near_frame);//NS
EWebRtcNS_Process(handleNS,aecout_frame,1,nsout_frame);
for(i = 0 ;i < NN ;i ++) {
nsout_frame_s[i] = nsout_frame[i];
}
fwrite(nsout_frame_s, sizeof(short),NN, fp_outNS);
#endif
#if 0 //Delay
NOTICE("GetDelayMetrics......\n");
//EWebRtcAEC_GetDelayMetrics(handleAecDelay,median,std,frac);
EWebRtcAEC_GetDelayMetrics(handleAec,median,std,frac);
NOTICE("median %d std %d frac %f\n",median[0],std[0],frac[0]);
#endif
#if 0//VAD is ok
NOTICE("VAD_Process......\n");
if(0 < EWebRtcVAD_Process(handleVad,SAMPLE_RATE,far_frame_s,NN) ) {
NOTICE("Voice~~~~~ sum %d\n",CirculargetSum());
CircularaddData(1);
} else {
NOTICE("silence~~~~~ sum %d\n",CirculargetSum());
CircularaddData(0);
}
if ( 230 < CirculargetSum()) {
int newValue = MAX(0,median[0]-20);
NOTICE("newValue=%d AecDealy=%d\n",newValue,AecDelay);
if(abs(newValue-AecDelay) >= 8) {
AecDelay = MAX(newValue,0);
NOTICE("AecDelay %d\n",AecDelay);
}
}
#endif
}
else
{
break;
}
}
//------------------------------------------------------Demo End------------------------------------------------------------------------------------//
基本参数:
参数名 |
数据类型 |
描述 |
SampleRate |
Int |
采样率8000 |
SamplePerframe |
int |
160*10 |
channelCount |
int |
单声道1 |
audioEncoding |
Int |
2个字节 ENCODING_PCM_16BIT |
CodecID |
Int |
AUDIO_CODEC_GSM |
8000HZ,一个Sample采样1600次,即每个sample是3200byte。一秒钟5个Sample,每个Sample是200ms,这么做是由于cpu性能。将3200byte拆分成10个320byte依次进行GSM编码,GSM要求320byte。 |