音頻編解碼之G7221編碼器

如有不當之處歡迎批評指正

前述

  由於工作需要接觸了一段時間的音頻編解碼算法—G.722.1, 在此作以記錄。

簡介

  • G.722.1是一種基於變換域編碼的算法
  • 採樣率: 16000hz
  • 比特率: 24kbit/s 32kbit/s
  • 變換域: MLT(Modulated Lapped Transform)
  • 幀長: 20ms
  • 變換窗長: 40ms
  • 有效編碼帶寬: 50~7000hz

編碼器

圖1 G.722.1編碼器方框圖

1 G.722.1編碼器方框圖

  上圖展示了G.722.1的編碼過程, 主要包含三個模塊:

  • MLT的幅度包絡進行計算、量化和編碼
  • 確定編碼方法,並對MLT的係數進行歸一化、量化和編碼

  下面詳細分析這幾個模塊所做的事情。

1. 計算、量化和編碼MLT的幅度包絡

1-1. MLT重疊調製變換

  MLT是一個嚴格抽樣,完美重建的線形變換過程(引用自G.722.1官方文檔中文版)此處不介紹具體公式。前一幀320個採樣點與當前幀320個採樣點拼接爲640個採樣點作爲MLT變化的輸入,MLT變換輸出320個係數。
mlt(m),0m<320mlt(m), 0\leq{m}<320

1-2. 計算、量化MLT的幅度包絡

  將MLT輸出的320個係數平均分爲16 個區域,每個區域包含20個係數,對應500hz帶寬,但編碼器只對前14個區域也就是0~7000hz進行編碼。
  首先根據以下公式計算每個區域的幅度包絡:
rms(r)=120j=019mlt(20r+j)mlt(20r+j),0r<14rms(r) = \sqrt{\frac{1}{20}\sum_{j=0}^{19}mlt(20r+j)mlt(20r+j)}, 0\leq{r}<14
  利用以下量化集合對上述14個區域的幅度包絡進行量化,生成量化索引rms_index(r)0r<14rms\_index(r),0\leq{r}<14
2(i+22),8i31,iZ2^{(\frac{i+2}{2})}, -8\leq{i}\leq{31}, i\in\mathbb Z
  進一步對第一個區域的量化索引rms_index(0)rms\_index(0)進行限制使得
1rms_index(0)311\leq{rms\_index(0)}\leq31
  具體在量化過程中,ii的取值應該使得幅度包絡rms(r)rms(r)處於2(i0.5+22)2^{(\frac{i-0.5+2}{2})}2(i+0.5+22)2^{(\frac{i+0.5+2}{2})}之間。用下面的例子說明該操作:如果rms(r)=310rms(r)=310,則應該將其量化爲2(15+22)2^{(\frac{15+2}{2})},也即rms_index(r)=15rms\_index(r)=15,因爲2(150.5+22)rms(r)=3102(15+0.5+22)2^{(\frac{15-0.5+2}{2})}\leq{rms(r)=310}\leq{2^{(\frac{15+0.5+2}{2})}}

1-3. 編碼MLT的幅度包絡

  使用5bit來編碼幅度包絡的量化索引rms_index(r)rms\_index(r)。直接將第零個區域的量化索引rms_index(0)rms\_index(0)進行傳輸,而其餘區域傳輸的則是與前一個區域量化索引的差值的霍夫曼編碼。
diff_rms_index(r)=rms_index(r)rms_index(r1),1r<14diff\_rms\_index(r)=rms\_index(r)-rms\_index(r-1), 1\leq{r}<{14}
且限定其取值範圍
12diff_rms_index(r)11-12\leq{diff\_rms\_index(r)}\leq11
  也就是說,除了第零個區域外,其餘區域傳輸的都是diff_rms_index(r)diff\_rms\_index(r)的霍夫曼編碼(通過查找兩個霍夫曼表實現,一個霍夫曼表表示編碼該差值需要多少bit,另一個霍夫曼表表示把該差值具體編碼成什麼)。

2. 確定編碼方法、量化和編碼MLT的係數

  第一部分主要是量化和編碼每個區域的幅度包絡,該部分主要用於確定一些量化和編碼MLT係數相關的參數,並用這些參數對MLT係數進行量化。這部分相比第一部分增加了難度,筆者剛開始接觸的時候看了好幾遍纔算看懂。筆者在這儘量用簡潔的語言描述清楚該部分所做的事情。

2-1. 產生16組不同的編碼(分類)方法

  該部分根據編碼完MLT的幅度包絡所剩下的比特數以及rms_index(r)rms\_index(r)產生16種不同的編碼方法(或者說產生16種不同的參數,這些參數用於對MLT係數進行量化和編碼)並從中選取最合適的一種編碼方法(或者說選取最合適的一種參數)。下面簡單介紹一下這16種不同的編碼方法。
  編碼器會給14個區域中的每個區域都分配一個類別,共有0~78種可選類別。每種類別決定了該區域的量化和編碼參數,並決定了量化該區域的MLT係數預計所需的比特數,如圖2所示。

1 G.722.1每一類別預計所需的比特數

表1 G.722.1 每一類別預計所需的比特數
  由於每個區域有8種類別可選,因此從算術上來說應該有 8148^{14} 種不同的編碼方法,但這其中有許多編碼方法是不合理的,G.722.1編碼器最終只生成16種不同的編碼方法,並且這16種編碼方法之間是有聯繫的,那就是每種編碼方法和與其相鄰的編碼方法之間只有一個區域分配的類別不同,並且該區域的類別值只相差1。這塊可能有點繞,既有16種編碼方法,又有14個區域,還有8種區域類別,這幾個數字之間到底是什麼關係哪,下面舉個例子來說明一下,見表1

2 G.722.1編碼方法示例
編碼方法1 編碼方法2 編碼方法3 *** 編碼方法16
區域0 2 2 2 * *
區域1 1 1 1 * *
區域2 2 2 2 * *
區域3 1 0 0 * *
區域4 2 2 2 * *
區域5 4 4 4 * *
區域6 3 3 2 * *
區域7 4 4 4 * *
區域8 3 3 3 * *
區域9 6 6 6 * *
區域10 5 5 5 * *
區域11 7 7 7 * *
區域12 6 6 6 * *
區域13 7 7 7 * *

  表中展示了編碼器產生的16種編碼方法之間的關係,可以看到第2種編碼方法與第1種編碼方法只在區域3的類別分配上不同,第1種編碼方法給區域3分配的是類別1,第2種編碼方法給區域3分配的是類別0,兩者區域3的類別值只差1。第3種編碼方法與第2種編碼方法也是類似的關係, 依次類推,其餘第n種編碼方法與第n-1種編碼方法也是類似的關係。通過表1,相信讀者現在已經能捋清楚16種編碼方法、14個區域和8種區域類別之間的關係了。還有需要注意的一點是,最終產生的16種編碼方法是按照所用比特數從大到小依次排列的,也就是第0種編碼方法所用比特數最多,第15種編碼方法所用比特數最少。
  寫到這,其實並沒有具體提到這16種編碼方法到底是如何根據前面所說的剩餘比特數和rms_index(r)rms\_index(r)產生的。筆者也不打算在這詳說,因爲這部分比較繁瑣,筆者不一定能說清楚,最重要的是筆者也沒太理解其中公式的具體含義。。。。。。感興趣的可以根據G.722.1官方文檔以及源碼作進一步瞭解。

2-2. 歸一化、量化和編碼MLT係數

  該部分對類別分配爲0~6的區域的MLT係數進行所謂的標量量化矢量霍夫曼編碼(SQVH),而對類別分配爲7的區域的MLT係數不進行編碼,認爲該區域沒有有效的音頻信息
  首先,編碼器對每個區域的MLT係數的絕對值進行歸一化和量化,產生量化索引k(j)k(j):
k(j)=min{xmlt(20r+j)+deadzone_roundingkmax}k(j)=min\{\lfloor|x*mlt(20r+j)|+deadzone\_rounding\rfloor,kmax\}
  其中
0j<200\leq{j}<20x=1/(stepsize(rms(r)))x=1/(stepsize*(rms(r)的量化值))
  上式中所用的參數見表3

3 G.722.1 SQVH程序所用參數表1

表3 G.722.1 SQVH程序所用參數表1
  上面展示瞭如何對MLT係數的絕對值進行歸一化和量化,但爲何通過這種方式來做、表3中參數的具體值是如何得到的以及deadzone_round的作用是什麼,筆者現在還沒搞太懂。介紹完MLT係數的歸一化,下面就介紹如何對這些歸一化之後的係數進行量化和編碼。
  先看錶4,定義了幾個參數 vdvpru

4 G.722.1 SQVH程序所用參數表2

表4 G.722.1 SQVH程序所用參數表2
  要理解表4中的幾個參數的具體含義就要和表3一起對照着看。可以觀察到表4中每一行均滿足以下關係:
vdvpr=20\bm{vd}*\bm{vpr}=20u=(kmax+1)vd\bm{u}=(kmax+1)^{\bm{vd}}
  先看第一個公式中的20是什麼意思哪,回想一下,這個20正是每個區域中所包含的MLT係數的個數。因此,vd\bm{vd}vpr\bm{vpr}所代表的含義也就比較明顯了:將每個區域的20MLT係數,每vd\bm{vd}個組成一個矢量,總共有vpr\bm{vpr}個矢量。類別爲0的區域矢量數最多,總共有10個矢量。類別爲5、6的區域矢量數最少,總共有4個矢量。
  再看第二個公式,kmaxkmax是在表3中定義的,是指不同類別的區域的MLT係數歸一化之後能取到的最大值。比如,類別爲0的區域,其MLT係數歸一化之後能取到的最大值是13,最小值是0,總共有14種可能的取值;類別爲6的區域,其MLT係數歸一化之後能取到的最大值是1,最小值是0,總共有2種可能的取值;kmax+1kmax+1就是指該類別的區域的MLT係數歸一化之後所有可能的取值數目。因此第二個公式代表的意思就是該類別的區域的每個矢量(每個矢量共包含vd\bm{vd}個標量)所有可能取值數目。
  上面講了如何對不同類別的區域的MLT係數的絕對值進行歸一化,並如何組合成矢量,下面就開始介紹如何對這些組合成的矢量進行編碼。
  將每個區域的各個矢量按照下面的公式量化爲標量:
vector_index(v)=l=0vd1k(vvd+l)(kmax+1)vd(l+1)vector\_index(v)=\sum_{l=0}^{\bm{vd}-1}{k(v*\bm{vd}+l)(kmax+1)^{\bm{vd}-(l+1)}}
  其中
  0vvpr10\leq{v}\leq{\bm{vpr}-1}表示區域rr中的第vv個矢量
  再將vector_index(v)vector\_index(v)通過查表的方式進行霍夫曼編碼(此處同樣有兩張表,一張表表示編碼該值需要多少比特,另一張表表示將該值具體編碼成什麼)。上述所描述的從MLT係數的歸一化到最終的霍夫曼編碼的整個過程稱爲標量量化矢量霍夫曼編碼(SQVH) 。
  至此,G.722.1編碼器的主要部分已講的差不多了。還有一些細節需要了解。

3. 細節

3-1. 符號比特

  剛纔講的是對MLT係數的絕對值進行歸一化、量化和編碼,並沒提到符號位,實際上在具體傳輸比特的過程中,符號比特直接位於表示vector_index(v)vector\_index(v)的比特的後面。vector_index(v)vector\_index(v)裏面對應包含了多少非零值。後面就有多少個符號比特,其中正數的符號比特爲1

3-2. 確定最終編碼方法

  之前提到總共有16種編碼方法,且第0種編碼方法使用的比特數最多,第15種編碼方法使用的比特數最少,最終傳輸的過程中只選用其中最合適的一種。比如第0種編碼方法使用了500個比特,1種編碼方法使用了470個比特,但每一幀最多隻能用480個比特,所以最終選擇第1種編碼方法,多出來的10個比特全部置爲1;還有比如第0~15種編碼方法所用比特數都大於480,那麼最終選取第15種編碼方法,傳輸過程中只傳輸前480個比特,剩餘的比特不傳輸

3-3. 比特流模塊

  最終編碼後的比特流包含三個部分:
圖2 G.722.1 編碼器主要比特流字段及其傳輸順序

2 G.722.1 編碼器主要比特流字段及其傳輸順序

  第一部分和第三部分比較清楚,第二部分就是指具體使用的哪種編碼方法,因爲總共有16種編碼方法,所以用4個比特表示。

4. 總結

  G.722.1的編碼器部分終於講的差不多了,其中有很多細節筆者也沒太搞懂,若是讀者瞭解其中緣由,希望能指教一二。還有就是G.722.1在實際代碼實現過程中可能不完全和文檔中的一樣,感興趣的可以閱讀源碼瞭解細節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章