webRTC中音頻相關的netEQ(五):DSP處理


上篇(webRTC中音頻相關的netEQ(四):控制命令決策)講了MCU模塊是怎么根據網絡延時、抖動緩沖延時和反饋報告等來決定給DSP模塊發什么控制命令的。DSP模塊根據收到的命令進行相關處理,處理簡要流程圖如下。

 

從上圖看出如果有語音包從packet buffer里取出來先要做解碼得到PCM數據,沒有就不用做解碼了。編解碼也是數字信號處理算法的一種,是個相當大的topic,不是本文所關注的,本文關注的是對解碼后的PCM數據做數字信號處理,如加減速。如果命令是非Normal命令,就要根據命令做DSP處理,是Normal命令就不用做了。最后取出一幀數據用於播放。

 

MCU發給DSP的主要的控制命令有正常播放(normal)、加速播放(accelerate)、減速播放(preemptive expand)、丟包補償(PLC,代碼中叫expand)、融合(merge)等。正常播放就是不需要做額外的DSP處理。加減速也就是改變語音時長,即在不改變語音的音調並保證良好音質的情況下使語音在時間軸上壓縮或者拉伸,或者叫變速不變調。語音時長調整算法可分為時域調整和頻域調整,時域調整以重疊區波形相似性(WSOLA)算法為代表,通常用在語音通信中。頻域調整通常音樂數據中。丟包補償就是基於先前的語音數據生成當前丟掉的語音數據。融合處理發生在上一播放的幀與當前解碼的幀不是連續的情況下,需要來銜接和平滑一下。這些都是非常專業的算法,本文不會涉及,本文是講工程上的一些實現,主要是buffer的處理。

 

在講這些處理之前先看netEQ里相關的幾塊buffer,分別是decodedBuffer(用於放解碼后的語音數據)、algorithmBuffer(用於放DSP算法處理后的語音數據)、speechBuffer(用於放將要播放的語音數據,這個在前面的文章(webRTC中音頻相關的netEQ(二):數據結構)中講過)和speechHistoryBuffer(用於放丟包補償的歷史語音數據,即靠這些數據來產生補償的語音數據)。

  

先看加速處理。它主要用於加速播放,是抖動延遲過大時在不丟包的情況下盡量減少抖動延遲的關鍵措施。它的處理流程如下:

1,看decodedBuffer里是否有30Ms的語音數據(語音數據量要大於等於30Ms才能做加速處理),如果沒有就需要向speechBuffer里未播放的語音數據借,使滿足大於等於30Ms的條件。下圖示意了借的步驟:

先算出decodedBuffer里缺的樣本數(記為nsamples, 等於30Ms的樣本數減去buffer里已有的樣本數),即需要向speechBuffer借的樣本數。然后在decodedBuffer里將已有的樣本數右移nsamples,同時從speechBuffer里end處開始取出nsamples個樣本,將其放在decodedBuffer里開始處空出來的地方。

 

2,做加速算法處理,輸入是decodedBuffer里的30Ms語音數據,輸出放在algorithmBuffer里。如果壓縮后的樣本數小於向speechBuffer借的樣本個數nsamples(假設小msamples),不僅要把這些壓縮后的樣本拷進speechBuffer里(從end位置處向前放),同時還要把從cur到pos處的樣本數向后移msamples,cur指針也向后移msamples個數。下圖給出了示意:

如果壓縮后的樣本數大於向speechBuffer借的樣本個數(假設大qsamples),先要把從cur到pos處的樣本數向前移qsamples(cur和pos指針都要向前移qsamples個數),然后把這些壓縮后的樣本拷進speechBuffer里(從pos位置處向后放)。下圖給出了示意:

 

3,從speechBuffer里取出一幀語音數據播放,同時把cur指針向后移一幀的位置。

 

減速處理的流程跟加速是類似的, 這里就不詳細講了。下面開始講丟包補償,它的處理流程如下:

1,基於speechHistoryBuffer利用丟包補償算法生成補償的語音數據(記樣本數為nsamples)放在algorithmBuffer里,同時還要更新speechHistoryBuffer里的數據為下次做丟包補償做准備。示意圖如下:

先把speechHistoryBuffer里的數據左移nsamples,然后把algorithmBuffer里的nsamples個樣本放在speechHistoryBuffer的尾部。

2,把algorithmBuffer里生成的數據放到speechBuffer里。示意圖如下:

先將speechBuffer里的數據左移nsamples,然后把algorithmBuffer里的nsamples個樣本放在speechBuffer的尾部,同時cur指針也要左移nsamples。

3,從speechBuffer里取出一幀語音數據播放,同時把cur指針向后移一幀的位置。

 

至於merge中buffer的處理,相對簡單,這里就不講了。至此我覺得netEQ的主要核心點都講完了,共5篇,算一個系列吧。理解了這些核心點后要想對netEQ有更深的認識就得去實際的調試了,把一些細節搞得更清楚。netEQ里面的細節特別多,要想全部搞清楚是要花不少時間的。要是全部搞清楚了對語音接收側處理的認識會有一個質的提升。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM