1. 程式人生 > >Webrtc 迴音消除 二

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
,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。