1. 程式人生 > >webRTC中音訊相關的netEQ(四):控制命令決策

webRTC中音訊相關的netEQ(四):控制命令決策

上篇(webRTC中音訊相關的netEQ(三):存取包和延時計算)講了語音包的存取以及網路延時和抖動緩衝延時的計算,MCU也收到了DSP模組發來的反饋報告。本文講MCU模組如何根據網路延時、抖動緩衝延時和反饋報告等決定發給DSP模組的控制命令, 好讓DSP模組先對取出的語音包做解碼處理(如果有的話)以及根據這些命令做訊號處理。

MCU模組給DSP模組發的控制命令主要有正常播放(normal)、加速播放(accelerate)、減速播放(preemptive expand)、丟包補償(PLC,程式碼中叫expand)、融合(merge),還有些次要的,如解碼器重新初始化(decoder re-init)、packet buffer 重置(packet buffer reset)等。這裡講主要的控制命令是怎麼決策的,次要的相對簡單就略去不講了,有興趣的可以自己去看相關程式碼。DSP模組收到這些命令後會轉化為自己的處理命令,下表列出了主要的控制命令和處理命令的對映關係。

 

MCU模組給DSP模組發什麼樣的控制命令首先取決於當前幀和前一幀的接收情況。當前幀和前一幀的接收情況主要分以下四種(對當前幀和前一幀做排列組合得到四種情況):

1,當前幀和前一幀都接收正常,資料包會進入正常的解碼流程。MCU模組會發正常播放、加速播放、減速播放三種控制命令中的一個給DSP,解碼後的資料會根據命令做相應的處理。

2,當前幀接收正常,但前一幀丟失。如果前一幀丟失,但當前幀接收正常,說明前一幀是通過丟包補償生成的。為了使前一幀由丟包補償生成的資料和當前沒有丟包的幀的資料保持語音連續,需要根據前後幀的相關性做平滑處理。這種情況下MCU模組會發正常播放、融合兩種控制命令中的一個給DSP。DSP模組先對當前幀解碼,然後解碼後的資料會根據命令做相應的處理。

3,僅當前幀發生丟包或延遲,這時就不需要解碼了。MCU模組會發丟包補償命令給DSP,DSP模組會進入丟包補償單元來生成補償資料。

4,當前幀丟失或延遲,前一幀同樣丟失或延遲。MCU模組會連續的發丟包補償命令給DSP,DSP模組也會連續的進入丟包補償單元來生成補償資料。不過越到後面生成的補償資料效果越差。

在上面的四種情況中,有些情況下MCU模組只會發一種命令給DSP模組,比如當前幀丟失,只會發丟包補償控制命令給DSP。但有些情況下MCU模組可能會發幾種命令中的一種給DSP模組,比如當前幀和前一幀都接收正常,MCU模組會發正常播放、加速播放、減速播放三種控制命令中的一個給DSP。到底發哪種命令呢,這就取決於網路延時、抖動緩衝延時以及DSP發給MCU的反饋報告等因素了。這是本文的重點,下面具體講。

在DSP發給MCU的反饋報告中有個變數playedOutTS,它表示已經播放到的PCM資料的時間戳。同時MCU中還有個變數availableTS,它表示packet buffer中能獲得的有效包的起始時間戳,顯然如果availableTS等於0表示packet buffer為空。如果playedOutTS等於availableTS,它說明語音包正常接收;如果playedOutTS小於availableTS,它說明有語音包的丟失或者延時,需要做丟包補償(PLC)。上篇文章(webRTC中音訊相關的netEQ(三):存取包和延時計算)中講了網路延時值(optBufLevel)和抖動緩衝延時值(buffLevelFilt)的計算,MCU就是要根據時間戳(playedOutTS & availableTS)的關係和延時(optBufLevel & buffLevelFilt)的關係以及上一幀的播放模式等來決定發什麼樣的控制命令給DSP。先舉個簡單的例子,如果playedOutTS = availableTS並且buffLevelFilt > optBufLevel,這說明當前包正常接收,但是抖動緩衝延時大於網路延時,即緩衝的包多了增加了時延,需要做加速播放處理,所以MCU會發加速處理命令給DSP。下面給出各個控制命令的條件,即滿足所列條件時MCU就會發相應的控制命令給DSP。

1,正常播放控制命令 / 加速播放控制命令 / 減速播放控制命令的條件

正常播放控制命令為BUFSTATS_DO_NORMAL。加速播放控制命令為BUFSTATS_DO_ACCELERATE,加速播放的原因是要播放的資料正常到達,但是抖動緩衝延時大於網路延時,增加了時延,因此要加速播放。減速播放控制命令為BUFSTATS_DO_PREEMPTIVE_EXPAND,又稱為優先擴充套件控制命令。減速播放的原因是要播放的資料正常到達,但是抖動緩衝延時小於網路延時,會引起播放時聲音的斷續,降低音質,因此要減速播放,拉長時間,使不會出現斷續。這三種控制命令都有一個必要條件,那就是playedOutTS = availableTS, 所以把這三種控制命令放在一起講。在“playedOutTS = availableTS”條件下,只有三種控制命令可供選擇,要麼正常播放,要麼加速播放,要麼減速播放。把加速播放和減速播放的條件搞清楚了,剩下的就是正常播放條件了。下圖更直觀的說明了正常播放、加速播放和減速播放的關係,去掉加速和減速的就是正常播放的了。

先看加速播放的條件。它的第二個條件是上一幀播放模式不為丟包補償(第一個條件為playedOutTS = availableTS),第三個條件是下列兩個之一:

1) 加速播放第三個條件之一

其中sample_rate為取樣率,如8000/16000。samples_per_packet為每個包的取樣點數,以16KHZ/每包20ms為例,samples_per_packet就為320。 timescaleHoldOff初始化為32,且每發生一次加速或減速播放就右移一位。此引數是為了防止連續的加速或減速播放惡化人耳的聽覺感受。

2)加速播放第三個條件之二

再看減速播放的條件。它的第一個條件與第二個條件與加速播放一樣,第三個條件如下:

說實話我沒有完全理解上面三個加減速的數學表示式的判據,尤其是係數值的選取。我知道不能簡單的認為“buffLevelFilt > optBufLevel"就加速“buffLevelFilt < optBufLevel"就減速,要真的這麼判斷的話效果肯定是不好的。如果哪位朋友理解了,麻煩給講講,先謝謝了!

除加減速播放這些條件外,剩下的就是正常播放了。可以寫成如下的虛擬碼:

If(playedOutTS == availableTS)

{

    If(上一幀播放模式不為丟包補償)

    {

        If(加速播放第三個條件是下列之一 || 加速播放第三個條件是下列之二)

            return 加速播放;

        If(減速播放第三個條件)

            return 減速播放;

    }

    return 正常播放;

}

2,丟包隱藏控制命令的條件

丟包隱藏控制命令為BUFSTATS_DO_EXPAND,又稱為擴充套件控制命令。丟包隱藏的原因是要播放的包已丟失或者還沒到(延時)。發生丟包隱藏的場景有:

1)availableTS = 0,即packet buffer為空,顯然這時需要做丟包補償。

2)playedOutTS < availableTS,即要播放的包丟失或者延時到,但是packet buffer裡有緩衝包,需要滿足下面兩個條件之一即可:

a)  上一幀播放模式不為丟包補償

b)  上一幀播放模式為丟包補償,且前面幾幀均為丟包補償,這是連續丟包的場景,這時要看連續丟包補償的次數。netEQ設定最多可以補償100ms的資料,以每包20ms為例,最多可以補償5個包,其實100ms後的補償效果也不好了。所以連續丟包補償的次數小於5的話,還會繼續丟包補償,否則就不做丟包補償了。

3,融合控制命令的條件

融合控制命令為BUFSTATS_DO_MERGE,主要用於丟包隱藏後產生的PCM資料與從packet buffer裡取出的資料的銜接過程。所以產生融合控制命令的條件是:

1)playedOutTS < availableTS (此式也表示packet buffer不為空,為空時availableTS = 0)

2)上一幀的處理模式為丟包補償

以上就是主要的控制命令的條件。可能不同版本之間可能有差異,我是根據我用的版本來講的。就像上面我說的,有些我也沒有完全理解,只是把它照本宣科的講出來。苦於沒有文件呀,網上也沒有相關的論述,目前只能先這樣了,後面如果完全理解了再補充。