Webrtc 迴音消除 二
目前成果: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
}
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。 |