標籤:時延 變數 股份 子公司 8K 發展 組織 sed 位元組
語音通訊從最初的只有有線通訊變成後來的有線通訊與無線通訊(移動通訊)的競爭,當移動語音通訊價格下來後有線語音通訊明顯處於逆勢。如今移動語音通訊的競爭者是OTT(On The Top)語音,OTT語音是互連網廠商提供的服務,一般免費,如語音。目前語音通訊技術上就分成了兩大陣營:傳統通訊陣營和互連網陣營,互相競爭,推動著語音通訊技術的發展。具體到轉碼器上互連網陣營提出了涵蓋語音和音樂的音訊轉碼器OPUS(OPUS是由非盈利的Xiph.org 基金會、Skype 和Mozilla 等共同主導開發的,全頻段(8kHZ到48kHZ),支援語音和音樂(語音用SILK, 音樂用CELT),已被IETF接納成為網路上的聲音編解碼標準(RFC6716)),絕大多數OTT語音的APP都支援,有一統互連網陣營的趨勢。移動通訊標準組織3GPP為了應對互連網陣營的競爭,也提出了涵蓋語音和音樂的音訊轉碼器EVS(Enhanced Voice Service)。我曾經給我做的手機平台上成功的加上了EVS,並且通過了中國移動的實網環境下的測試。下面就講講這個codec以及用好要做的工作。
3GPP在2014年9月將EVS轉碼器標準化,由3GPP R12版本定義,主要適用於VoLTE, 但也同時適用於VoWiFi和固定網路電話VoIP。EVS轉碼器由電訊廠商、終端裝置、基礎設施和晶片供應商以及語音與音頻編碼方面的專家聯合開發,其中包括愛立信、Fraunhofer整合電路研究所、華為技術有限公司、諾基亞公司、日本電信電話公司(NTT)、日本NTT DOCOMO公司、法國電信(ORANGE)、日本松下公司、高通公司、三星電子公司、VoiceAge公司及中興通訊股份有限公司等。它是3GPP迄今為止效能和品質最好的語音頻編碼器,它是全頻段(8kHZ到48kHZ),可以在5.9kbps至128kbps的碼率範圍內工作,不僅對於語音和音樂訊號都能夠提供非常高的音頻品質,而且還具有很強的抗丟幀和抗延時抖動的能力,可以為使用者帶來全新的體驗。
是3GPP EVS相關的SPEC,從TS26.441到TS26.451。
我已將關鍵的幾個用紅框標出,其中TS26.441是總覽,TS26.442是用C語言寫的定點實現(reference code),這也是後面用好EVS工作中的重中之重。TS26.444是測試序列,最佳化reference code過程中幾乎每天都要儲存一個最佳化的版本,每天都要用測試序列跑一跑最佳化的版本,如發現不一樣了,說明最佳化的有問題,要退到上一個版本,並檢查出哪一步最佳化出問題了。TS26.445是EVS演算法的具體描述,近700頁,說實話看的頭疼,如果不是做演算法的,演算法部分看個大概就可以了,但是對特性描述相關的一定要細看。
EVS對語音訊號和音樂訊號採用不同的編碼器。語音編碼器是改進型代數位激勵線性預測(ACELP),還採用了適合不同語音類別的線性預測模式。對於音樂訊號編碼,則採用頻域(MDCT)編碼方式, 並特別關注低延遲/低位元速率情況下的頻域編碼效率,從而在語音處理器和音頻處理器之間實現無縫可靠的切換。是EVS轉碼器的框圖:
編碼時先對輸入的PCM訊號做預先處理,同時確定是語音訊號還是音頻訊號。如是語音訊號就用語音編碼器編碼得到位元流,如是音頻訊號就用感知編碼器進行編碼得到位元流。解碼時根據位元流中的資訊確定是語音訊號還是音頻訊號,如是語音訊號就用語音解碼器解碼得到PCM資料,然後做語音頻寬擴充。如是音頻訊號就用感知解碼器解碼得到PCM資料,然後做頻率頻寬擴充。最後再做後處理作為EVS解碼器的輸出。
下面說說EVS的各個關鍵特性。
1,EVS支援全頻段(8kHZ--48kHZ),碼率範圍是5.9kbps至128kbps。每幀是20Ms時間長度。是音頻頻寬的分布:
窄帶(Narrow Band, NB)範圍是300HZ-3400HZ,對應的採樣率是8kHZ,AMR-NB用的就是這種採樣率。寬頻(Wide Band, WB)範圍是50HZ-7000HZ,對應的採樣率是16kHZ,AMR-WB用的就是這種採樣率。超寬頻(Super Wide Band, SWB)範圍是20HZ-14000HZ,對應的採樣率是32kHZ。全帶(Full Band, FB)範圍是20HZ-2000HZ,對應的採樣率是48kHZ。EVS支援全頻段,所以它支援四種採樣率:8kHZ、16kHZ、32kHZ和48kHZ。
是在各種採樣率下支援的碼率:
從看出只有在WB下支援全碼率,其他採樣率下只支援部分碼率。需要注意的是EVS向前相容AMR-WB,所以它也支援AMR-WB的所有碼率。
2,EVS支援DTX/VAD/CNG/SID,這同AMR-WB一樣。在通話過程中通常有一半左右時間講話,其餘時間處於聆聽狀態。在聆聽狀態時沒必要發語音包給對方,於是就有了DTX(非連續傳輸)。要用VAD(靜音檢測)演算法去判斷是語音還是靜音,是語音包時就發語音包,是靜音時就發靜音包(SID包)。對方收到SID包後就去用CNG(舒適雜訊產生)演算法去產生舒適雜訊。EVS中有兩種CNG演算法:基於線性預測的CNG(linear prediction-domain based CNG)和基於頻域的CNG(frequency-domain based CNG)。在SID包的發送機制上EVS跟AMR-WB不同,在AMR-WB中VAD檢測到是靜音時就發送一個SID包,然後40Ms後發送第二個SID包,隨後每隔160Ms發送一個SID包,不過VAD一檢測到是語音就立刻發送語音包。EVS中SID包的發送機制可配,可以固定每隔一段時間(幾幀,範圍是3--100)發送一個SID包,也可以根據SNR自適應的發送SID包,發送周期範圍是8—50幀。EVS SID包的payload大小也與AMR-WB不同,AMR-WB的是40個位元組(50*40=2000bps),EVS是48個位元組(50*48=2400bps)。從上可以看出DTX有兩個好處,一是可以節省頻寬,增加容量,二是因為不編解碼減少了運算量,從而降低功耗增加續航時間長度。
3,EVS也支援PLC(丟包補償),這也同AMR-WB一樣。不過EVS把Jitter Buffer Module(JBM)也包含了進來,這在以前的codec中是從來沒有過的。我在使用中沒有用到JBM,由於時間比較緊,也就沒有時間去研究。後面有時間了定要好好研究一下,JB可是語音通訊的痛點之一同時也是語音品質的瓶頸之一呀。
EVS的演算法時延根據採樣率不同而不同。當採樣率為WB/SWB/FB時總時延為32ms,包括一幀20ms的時延,編碼側輸入重採樣的0.9375ms時延以及8.75ms的前向時延,解碼側時域頻寬擴充的2.3125ms時延。當採樣率為NB時總時延減小為30.9375ms,相對WB/SWB/FB減小了1.0625ms, 這1.0625ms主要是在解碼側減少的。
EVS的語音品質(MOS值)相對於AMR-NB/AMR-WB有了明顯的提升。是這幾種codec的MOS值比較:
從看出,當採樣率為NB時在各種碼率下EVS-NB的MOS值比AMR-NB的MOS值顯著提升;當採樣率為WB時在各種碼率下EVS-WB的MOS值同樣比AMR-WB的MOS值顯著提升;當採樣率為SWB並且碼率大於15kbps時EVS-SWB的MOS值接近了不編碼的PCM的MOS值。可見EVS的語音品質是相當不錯的。
用好EVS要做的工作在不同的平台上會有所不同,我是用在手機平台audio DSP上,用於語音通訊。下面就說說為了手機支援EVS我做了哪些工作。
1,學習EVS相關的SPEC。要把前面我列的SPEC都看一遍,因為不是做演算法,演算法相關的可以看的粗,但是對特性描述相關的一定要看的細,這關係到後面的使用。
2,在PC上產生encoder/decoder的應用程式。我是在Ubuntu上做的,把PCM檔案作為encoder的輸入,根據不同的配置產生相應的碼流檔案,再把碼流檔案作為decoder的輸入,解碼還原成PCM檔案。如果解碼後的PCM檔案聽下來跟原始PCM檔案無異樣,說明演算法實現是可信的(權威組織出來的演算法實現都是可信的,如果有異樣說明應用程式沒做好)。做應用程式是為了後面的最佳化,也方便理解外圍實現,如怎麼把編碼後的值變成碼流。編碼後的值放在indices(最多有1953個indices)中, 每個indices有兩個成員變數,一個是nb_bits,表示這個indices有多少位,另一個是value,表示這個indices的值。Indices有兩種儲存方式:G192(ITU-T G.192)和MIME(Multipurpose Internet Mail Extensions)。先看G192,每一幀的G192的儲存格式見:
第一個Word是同步值,分good frame(值為0x6B21)和bad frame(值為0x6B20)兩種,第二個Word是長度,後面是每個值(1用0x0081表示, 0用0x007F表示)。Indices裡的value用二進位表示,位上的值為1就存為0x0081,為0 就存為0x007F。是一個例子,採樣率為16000HZ, 碼率為8000bps,因此一幀有160位(160 = 8000/50),儲存成G192格式就是160個Word。中頭是0x6B21, 表示good frame,length是0x00A0, 後面160個Word是內容。
再來看MIME格式。要把indices的value值pack成serial值,具體怎麼pack,見pack_bit()函數。MIME的格式是第一個Word是header(低4位表示碼率index, 在用WB_IO時第5和6位要置1,EVS 時不需要),後面是位元流。還是上面採樣率為16000HZ碼率為8000bps的例子,但存成MIME格式,一幀有160位,需要20byte(20 = 160/8),如:
中頭16個位元組是reference code內建的,第17個位元組是header,0x2表示以EVS 編碼,碼率是8kbps(8kbps index為2),後面的20個位元組表示pack後的payload。
在語音通訊中,要把indices的value值pack成serial值,然後作為payload發送給對方。對方收到後先unpack再解碼得到PCM值。
3,原始reference code通常是不能直接使用的,需要最佳化。至於怎麼最佳化,請看我前面寫過的一篇文章(音訊編解碼及其最佳化方法和經驗),文章寫的是比較通用的方法。我現在要在DSP上用,DSP的頻率較低,只有三百多MHZ,不用彙編最佳化時搞不定的。我之前沒用過DSP彙編,要在短時間內最佳化的很好有很大難度。老闆權衡後決定用DSP IP廠商提供的最佳化好的庫,彙編方面它們更專業一點。
4,對reference code的應用程式改造,方便後面調實驗證時當工具使用。原始reference code儲存成檔案時是以位元組為單位的,而DSP是以Word(兩個位元組)為單位,所以要對reference code裡的pack/unpack函數改造,以適應DSP。
5,要想打電話時codec是EVS,Audio DSP 和CP上都要加相應的代碼,先寫各自的代碼自調,然後聯調。我自調時用AMR-WB的殼(因為EVS和AMR-WB的一幀都是20ms時間長度),即流程上用AMR-WB的,但codec從AMR-WB換成EVS。主要驗證encoder、pack、unpack、decoder是否ok,其中encoder和pack是上行的,unpack和decoder是下行的。它們的先後關係如:
先調上行,把encode後的儲存成G192格式,用decoder工具解碼成PCM資料用CoolEdit聽,跟自己說的話是一樣的,說明encoder是OK的。再調pack,把pack後的碼流儲存成MIME格式,同樣用decoder工具解碼成PCM資料用CoolEdit聽,跟自己說的話是一樣的,說明pack是OK的。再調下行。由於CP還沒有正確的EVS碼流發給Audio DSP,就用loopback的方式來調試,具體是把pack後的碼流作為unpack的輸入,unpack後得到的儲存成G192格式,用decoder工具解碼成PCM資料用CoolEdit聽,跟自己說的話是一樣的,說明unapck是OK的。最後調decoder,把decoder後的PCM資料用CoolEdit聽,跟自己說的話是一樣的,說明decoder是OK的。這樣自調就結束了。
6,與CP聯調。由於前面自調時各關鍵模組都是調好的,聯調起來相對比較順利,沒幾天就調好了。這樣打電話時就能享受EVS帶來的高音質了。
移動通訊最先進的音訊轉碼器EVS及用好要做的工作