時延是語音通訊中的一個重要指標,當端到端(end2end)的時延(即one-way-delay,單向時延)低於150Ms時人感受不到,當端到端的時延超過150Ms且小於450Ms時人能感覺到但能忍受不影響通話交流,當端到端的時延大於1000Ms時嚴重影響通話交流,用戶體驗不好。同時時延也是語音方案過認證的必選項,超過了規定值這個方案是過不了認證的。今天咱們就講講時延是怎麼產生的以及怎麼樣在通訊終端上減少時延。html
1,時延產生web
下圖是語音從採集到播放的傳輸過程。算法
從上圖看出,傳輸過程包括三部分,一是從發送端採集到語音數據處理後發送到網絡設備,二是網絡設備之間傳送,三是從網絡設備發送給接收端並播放出來。每一個過程都會產生時延,整體能夠分爲三類。一是通訊終端上引入的時延,這時本文要講的重點,後面具體講。二是通訊終端和網絡設備之間的時延,包括採集終端到網絡設備的延時和網絡設備到播放設備的延時。三是網絡設備之間的時延。二和三屬於網絡設備引入的延時,本文不討論。網絡
如今咱們具體看通訊終端上引入的時延,它在發送端(或者叫上行/TX)和接收端(或者叫下行/RX)都有。在發送端主要包括聲音的採集引入的延時、前處理算法引入的延時和編碼算法引入的時延。聲音採集時一般5Ms或者10Ms從採集DMA中取一次語音數據,可是編碼時多數codec要求的一幀是20Ms(好比AMR-WB),這二者之間不匹配,就要求採集到的數據放在buffer裏緩一段時間,等到幀長時再取出來去編碼,這就引入了時延。以一幀20Ms爲例,就會引入20Ms的延時。前處理算法主要有AEC、ANS、AGC,這些算法都會引入延時,這跟濾波器的階數有關,階數越多,延時越大。編碼算法同前處理算法同樣也引入了延時。在接收端主要包括端網絡延時、解碼算法延時、後處理算法延時和播放延時。端網絡延時主要出如今解碼以前的jitter buffer內,若是有抗丟包處理(例如FEC)延時還會增長(有FEC增長延時的緣由是要等接收到的包到指定個數才能作FEC解碼還原出原始包,用FEC抗丟包的原理我在前面的文章(語音通訊中提升音質的方法)中寫過)。解碼和後處理算法和發送端的編碼前處理相似有延時。播放前爲了保持播放的流暢性會在語音數據進播放DMA前加一級buffer,這也引入了延時。架構
2,時延測量post
時延是過認證的必選項。對於語音通訊解決方案來講,先得讓時延低於認證指定的值,而後再看有沒有減少的可能。如能夠將時延作到更小,則是該方案的亮點。要測量時延就得在實驗室搭建一個理想的端到端的語音通訊系統(理想是指網絡幾乎不引入時延),同時兩端均採用該語音方案,這樣就能夠用儀器測出端到端的延時了。測時延時,儀器上顯示的時延是一個平均值,等通話時長達到必定值後就會穩定下來。拿它跟認證指定的值比較,若是大於指定值,認證是過不了的,先要減少時延讓它低於指定值。若是低於指定值,則說明該方案有一個好的起點,能夠繼續減少讓其成爲亮點。測試
用儀器測出來的單向時延大致上應該是終端上各個模塊引入的時延之和。要減少時延首先得搞清楚是哪一個模塊引入的時延較大。有些模塊引入的時延是已知固定的,且不能減小,好比信號處理算法模塊。有些模塊引入的時延是未知的,咱們就須要去測量這個模塊引入的時延具體是多少。作這些前須要對該語音通訊方案的軟件架構熟悉,知道方案中有幾個(除了信號處理算法模塊外)引入時延的點。這種時延一般是對buffer的存取引入的時間差,該怎麼測出時延值呢?我通常用以下的方法:當把語音數據放進buffer時記下當時的時間t1,保存在這段數據開始的地方(雖然破壞了語音數據,不過不要緊,咱們只是用來測延時,是一種手段,不關心語音質量),當從buffer中取出這段語音數據時,再記錄下時間t2,將t2減去保存在數據中的t1就獲得本次存取引入的延時。統計很是屢次(我一般用一萬次)再算平均值,就能夠獲得這個點引入的時延了。下面舉例說明。有一塊能夠存5幀(每幀20Ms)的buffer,某一幀語音數據放在第三幀處。放時的時間是158120毫秒,將這個值放在放這段數據開始的地方。將這段數據從buffer裏取出來時的時間是158180秒,能夠算出本次延時是60Ms(158180-158120=60),統計10000次,算出延時總和,再除以10000,獲得延時平均值是58Ms。因此這個點引入的時延是58Ms。編碼
3,時延的減少方法url
知道了各個點引入的時延大小,下面就要看怎麼減少時延了。這裏的減少是指能減少的,有些是不能減少的,好比codec引入的時延。我用過的方法主要有如下兩種。spa
1)用減少緩衝深度來減少時延
這種方法說白了就是讓語音數據在buffer裏呆的時間短些,好比之前在buffer裏有了3幀(假設每幀20Ms)語音數據纔會從buffer中取出給下一模塊,這樣平均就會引入60Ms的時延。若是將3幀改成2 幀,則平均引入的時延就降爲40Ms,這樣就減小了20Ms的時延。不過用這種方法是有條件的,要確保語音質量不降低。改了後要用儀器測,若是長時測試下語音質量不降低就說明這個改後的值是能夠接受的。通過試驗後找到一個能夠接受的緩衝深度的最小的值,就把這個值用在方案中。
2)用加速信號處理算法來減小時延
音頻信號處理中有個算法叫加速,它是對PCM信號進行處理,在不丟失語音信息的前提下把時長減少,它的原理是WSOLA。好比原PCM數據時長是5秒,通過加速處理後變成了4秒,人聽上去信息沒丟失,可是語速變快了。若是在buffer中待播放的PCM數據較長,確定延時較大,能夠經過這種加速算法把要播放的數據處理一下,變成短時長的PCM數據,這樣就能夠減少延時了。我第一次作voice engine的時候,除了減少buffer緩衝深度沒有其餘好的方法來減少延時。後來作了語音加速播放的功能(具體見我前面的文章:音頻處理之語音加速播放),以爲能夠用這個算法來減少延時。但是當時事情很是多,再加上要作到延時減少了但同時也要讓聽者感受不到在加速播放還有不少細節工做要作,也就沒作成。隨着webRTC風靡音視頻開發圈,我也開始關注。瞭解到其中的netEQ就有用加速算法來減少延時的功能,看來英雄所見略同啊。哈哈。同時我也感受到要多作東西,見多才能識廣呀,說不定結合之前作過的東西就能獲得解決問題的好的思路呢。固然加速減小延時功能只是netEQ的一部分。netEQ主要是解決網絡抖動延時丟包等問題來提升語音質量的,能夠說說目前公開的處理此類問題的最佳方案了。從下篇開始,我將花幾篇文章來詳細的講講netEQ。netEQ是webRTC中音頻相關的兩大核心技術之一(另外一個是先後處理,有AEC/ANS/AGC等),很值得研究。