g723源码详细分析-11-多脉码激励编码
生活随笔
收集整理的這篇文章主要介紹了
g723源码详细分析-11-多脉码激励编码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節分析了g723低速率下的固定碼本搜索,
在高速率下面,對去了自適應激勵成份后的語音信號,
g723采用的是多脈沖編碼方式.本文現做一個簡要的閘述
在分析代碼之前,仍然是要做一些公式推導,否則不易讀懂代碼
過程其實與固定碼本搜索時的方式類似.
多脈沖激勵的定義:
激勵是由有限個經過最優估值的脈沖構成(每個脈沖的位置與增益都是
經過最優估值的)
那么很容易得出相應的誤差公式,假設脈沖的個數是m
???????????? ? ? ?? M
e[n]= t[n] -? Σ? g(k) * h[n-n(k)]
?????????? ? ? ?? k=1
n(k) 代表第k個脈沖的位置 g(k)代表第k個脈沖的增益
誤差均方:
?????? N????????? ? ? ?? N??????????? M
E = Σ? e[n]^2 =? Σ? (t[n] -? Σ? g(k) * h[n-n(k)])^2 ---- <式1>
? ?? n=1???????? ? ? n=1???????? k=1
對
?M
?Σ? g(k) * h[n-n(k)]
k=1
這個式子進行一些處理,將其變形為
?N
?Σ? g(l) * h[n-l]
l=1
當l=n(k) g(l)為對應位置的脈沖值g(k),
其它的l取值時g(l)為零
<式1>此時可以變形為
??? N??????????? N?????????? N
E = Σ? e[n]^2 =? Σ? (t[n] -? Σ? g[l] * h[n-l])^2
?? n=1????????? n=1???????? l=1
?? ? ? N??????????? ? ? ?? N?????? ? N?????????????????? ? ? ? N? ? ? N? ? ? N
E = Σ t[n]^2 - 2 * Σ t[n] * Σ (g[l] * h[n-l]) +? Σ???? Σ?????? Σ? g[j]*h[n-j]*g[l]*h[n-l]
? ?? n=1????????????? n=1???? ? l=1??????????????? ? ? ? n=1? j=1 ?? l=1
??? N???????????? N??????? N??????????????????? N?? N??????????????? N
? = Σ t[n]^2 -2 * Σ g[l] * Σ (t[n] * h[n-l]) +? Σ?? Σ? g[j] * g[l] * Σ (h[n-j]*h[n-l])?? --- 交換求和次序
?? n=1?????????? l=1????? n=1????????????????? l=1 j=1????????????? n=1
??? N??????????????????? M?????? ?? N???????????????????? ? ? ? ? ? ?? M??????? ? M??????? ?? N
? = Σ t[n]^2 - 2 * Σ g[k] * Σ (t[n] * h[n-n(k)]) +? Σ g[k] *? Σ? g[j] *? Σ (h[n-n(j)]*h[n-n(k)])
E分別對每個g(k)分別進行求導,g(k)最優估值必定要導數為零處,將會得到M個等式
?N????????????????????? ? ? ? ? ? M??????? ? N
?Σ (t[n] * h[n-n(k)]) =? Σ? g[j] * Σ (h[n-n(j)]*h[n-n(k)])???????????? k = 1,2, ..., M
n=1??????????????????????????? j=1?????? n=1
可以化簡為
??????????? ? ? ? ?? M
?Rth(n(k)) = Σ g[j] Rhh(n(j),n(k)) ---<式2>???????? Rth是t與h的互相關m, Rhh是h的自相關
????????? ? ? ? ? ?? j=1
?????????? ?
而<式1>可以化簡為:
?? ? ? N???????? ?? M
E = Σ t[n]^2 - Σ g[k]*Rt(n(k)) ---<式3>
????? n=1??????? k=1
? ?
由于n(k)是未知的,要求解這個方程是極其復雜的,
在難以求得最優解的情況下,采用一種簡化算法,求得次優解
即每次只求一個最優解的位置,<式2>就變成這樣:
Rth(n(1)) = g[1] Rhh(n(1),n(1)) ---<式4>
??????? Rth(n(1))
g[1] = --------------
?????? Rhh(n(1),n(1))
從<式3>可以看出,n(1)是滿足下式最大值的位置
?? Rth(n(1))^2
? --------------?? ---<式5>
? Rhh(n(1),n(1))
這樣可以很容易地求出n(1),并根據<式4>求出g[1]
然后從 t中扣除g[1]與h卷積后的成份,更新t
t[n] = t[n] - g[1] * h[n-n(1)] ---<式6>
用更新后的t繼續進行下一輪的搜索,直到找出M個脈沖位置以及它們的增益.
以上是公式推導過程,與itu的文檔中的描述相當接近了,不過itu采取的是更為化簡的估值算法.
itu認為每個脈沖的增益都是相同的,用
??? max(|Rth(i)|)
G= ------------?? ---- 等同于itu文檔中的公式25
??? Rhh(0,0)
來對增益進行估值,
在G-3.2db ~ G + 6.4db這個范圍內,將G分成4個等級值,進行搜索脈沖的位置
脈沖位置搜索的依據是<式5>,并且忽略了分母的差異,只搜索分子最大的
每搜索一次按照<式6>更新輸入的殘差信號(代碼里直接更新自相關,道理是相同的)
最后,得到估值增益,以及脈沖位置
推倒完畢(^_^),現在進入代碼:
Find_Best
這個函數描述了搜索脈沖位置與增益的過程
首先是構造沖激響應,在后面會提到,搜索會根據基音周期是否小于子幀長,再調整沖激響應
再進行一次搜索,然后與未調整沖激響應的搜索結果進行比較,取更接近的那一組脈沖位置與增益
??? /* Update Impulse response */
??? if ( Olp < (Word16) (SubFrLen-2) ) {
??????? Temp.UseTrn = (Word16) 1 ;
??????? Gen_Trn( Imr, ImpResp, Olp ) ;//lsc 相當于與olp為周期間隔脈進行卷積
??? }
??? else {
??????? Temp.UseTrn = (Word16) 0 ;
??????? for ( i = 0 ; i < SubFrLen ; i ++ )
??????????? Imr[i] = ImpResp[i] ;
??? }
計算沖激響應的自相關,以相沖激響應與目標向量的互相關,并對其進行歸一化處理,這里不貼代碼了
計算的結果存放在ImrCorr(沖激響應自相關) ErrBlk(沖激響應與目標向量的互相關)
ImrCorr是擴大2^(9 + Exp)倍的
ErrBlk是擴大2^(10 + Exp)倍的(這樣便于后繼的計算)
由于脈沖要么全位于奇位置,要么全位于偶位置,所以搜索分成奇偶兩次
在搜索循環中,首先進行增益估值
增益估值使用的是FcbkGainTable這個碼本表里的值,該碼本表是與固定碼本增益共享的
采用乘法運算,繞開費時的除法運算,即將增益碼本FcbkGainTable里的值與沖激響應的零時自相關(即Rhh(0))相乘
然后與ErrBlk數組里絕對值最大的相減(也就是max(|Rth(i)|)),取差值最小的那個增益,然后在它附近的4個增益值中
進行搜索最優增益估值
代碼如下:
??? /* Search for the best sequence */ //lsc 這里是指奇偶兩次循環
??? for ( k = 0 ; k < Sgrid ; k ++ ) {
??????? Temp.GridId = (Word16) k ;
??????? /* Find maximum amplitude */ //lsc 找了最大的那個 |d[j]|
??????? Acc1 = (Word32) 0 ;
??????? for ( i = k ; i < SubFrLen ; i += Sgrid ) {
??????????? Acc0 = L_abs( ErrBlk[i] ) ;
??????????? if ( Acc0 >= Acc1 ) {
??????????????? Acc1 = Acc0 ;
??????????????? Temp.Ploc[0] = (Word16) i ;//lsc 互相關絕對值最大的那個的下標,這也是搜索過程中被搜索出的第一個脈沖的位置
??????????? }
??????? }
??????? /* Quantize the maximum amplitude */
??????? Acc2 = Acc1 ;//lsc Acc2就是最大的 |d[j]|
??????? Acc1 = (Word32) 0x40000000L ;
??????? MaxAmpId = (Word16) (NumOfGainLev - MlqSteps) ;
??????? //lsc 這里再次利用乘法繞開除法,將 G* Rhh[0]得到的結果與 Acc2相減,差值最小的那個就是G
??????? for ( i = MaxAmpId ; i >= MlqSteps ; i -- ) {
??????????? Acc0 = L_mult( FcbkGainTable[i], ImrCorr[0] ) ;
??????????? Acc0 = L_sub( Acc0, Acc2 ) ;//lsc 同一數量級,所以可減
??????????? Acc0 = L_abs( Acc0 ) ;
??????????? if ( Acc0 < Acc1 ) {
??????????????? Acc1 = Acc0 ;
??????????????? MaxAmpId = (Word16) i ;
??????????? }
??????? }
??????? MaxAmpId -- ;//lsc 得到的值在降一級搜索,見itu文檔 MaxAmpId最小值是1
??????? //lsc 位置的搜索過程,我們看到一些簡化,即G都是一樣的,每個位置的搜索并不對增益做任何更新(照理應計算出G,并用其來更新互相關)
??????? //按G的值循環搜索
??????? for ( i = 1 ; i <=2*MlqSteps ; i ++ ) {
??????????? for ( j = k ; j < SubFrLen ; j += Sgrid ) {
??????????????? WrkBlk[j] = ErrBlk[j] ;//lsc 取出偶數位/奇數位的 互相關
??????????????? OccPos[j] = (Word16) 0 ;
??????????? }
??????????? Temp.MampId = MaxAmpId - (Word16) MlqSteps + (Word16) i ;//lsc 這樣做等最從0位置開始搜索
??????????? MaxAmp = FcbkGainTable[Temp.MampId] ;
??????????? if ( WrkBlk[Temp.Ploc[0]] >= (Word32) 0 )
??????????????? Temp.Pamp[0] = MaxAmp ;
??????????? else
??????????????? Temp.Pamp[0] = negate(MaxAmp) ;
??????????? OccPos[Temp.Ploc[0]] = (Word16) 1 ;//lsc 選中第一個位置,對均方差求導很容易得到這個結論
??????????? for ( j = 1 ; j < Np ; j ++ ) {
??????????????? Acc1 = (Word32) 0xc0000000L ;
??????????????? for ( l = k ; l < SubFrLen ; l += Sgrid ) {
??????????????????? if ( OccPos[l] != (Word16) 0 )//lsc 表示這個位置已經被選中了
??????????????????????? continue ;
??????????????????? Acc0 = WrkBlk[l] ;//lsc 這個是互相關
??????????????????? Acc0 = L_msu( Acc0, Temp.Pamp[j-1],
??????????????????????????? ImrCorr[abs_s((Word16)(l-Temp.Ploc[j-1]))] ) ;//lsc 這里是在更新互相關,因為分母都一樣,所以只要分子最大,就可以選定這個位置
??????????????????? WrkBlk[l] = Acc0 ;
??????????????????? Acc0 = L_abs( Acc0 ) ;
??????????????????? if ( Acc0 > Acc1 ) {
??????????????????????? Acc1 = Acc0 ;? ?
??????????????????????? Temp.Ploc[j] = (Word16) l ;//lsc Ploc的意思是 pluse location,即脈沖位置,
??????????????????? }
??????????????? }
??????????????? //lsc 這里其實只是記錄符號
??????????????? if ( WrkBlk[Temp.Ploc[j]] >= (Word32) 0 )
??????????????????? Temp.Pamp[j] = MaxAmp ;
??????????????? else
??????????????????? Temp.Pamp[j] = negate(MaxAmp) ;
??????????????? //lsc 選定位置
??????????????? OccPos[Temp.Ploc[j]] = (Word16) 1 ;
??????????? }
??????????? /* Compute error vector */
??????????? for ( j = 0 ; j < SubFrLen ; j ++ )
??????????????? OccPos[j] = (Word16) 0 ;
??????????? for ( j = 0 ; j < Np ; j ++ )
??????????????? OccPos[Temp.Ploc[j]] = Temp.Pamp[j] ;
??????????? //lsc 計算卷積
??????????? for ( l = SubFrLen-1 ; l >= 0 ; l -- ) {
??????????????? Acc0 = (Word32) 0 ;
??????????????? for ( j = 0 ; j <= l ; j ++ )
??????????????????? Acc0 = L_mac( Acc0, OccPos[j], Imr[l-j] ) ;
??????????????? Acc0 = L_shl( Acc0, (Word16) 2 ) ;
??????????????? OccPos[l] = extract_h( Acc0 ) ;
??????????? }
??????????? /* Evaluate error */
??????????? //lsc 計算均方差
??????????? Acc1 = (Word32) 0 ;
??????????? for ( j = 0 ; j < SubFrLen ; j ++ ) {
??????????????? Acc1 = L_mac( Acc1, Tv[j], OccPos[j] ) ;
??????????????? Acc0 = L_mult( OccPos[j], OccPos[j] ) ;
??????????????? Acc1 = L_sub( Acc1, L_shr( Acc0, (Word16) 1 ) ) ;
??????????? }
??????????? //lsc 如果大,說明均方差小 (a^2 - 2ab + b^2) 很容易得到這個結論
??????????? //則選這組位置
??????????? if ( Acc1 > (*Best).MaxErr ) {
??????????????? (*Best).MaxErr = Acc1 ;
??????????????? (*Best).GridId = Temp.GridId ;
??????????????? (*Best).MampId = Temp.MampId ;
??????????????? (*Best).UseTrn = Temp.UseTrn ;
??????????????? for ( j = 0 ; j < Np ; j ++ ) {
??????????????????? (*Best).Pamp[j] = Temp.Pamp[j] ;
??????????????????? (*Best).Ploc[j] = Temp.Ploc[j] ;
??????????????? }
??????????? }
??????? }
??? }
致此,g723編碼部分的代碼分析絕大部分已經完成了,剩余的一些代碼是更新自適應碼本,打包字節等
這將在下一個章節做一個簡述
這里做一個g723編碼模塊的簡要小結
step1:LPC分析
??? 這一步驟就是要得出一個全極點的聲道系統函數,并且依此生成聲道的沖激響應
??? 它包括lpc參數計算(萊文森德賓遞推公式) 轉lsp,并量化反量化等
?? ?
step2:
??? 語音數據處理,包括共振峰感知加權,基音周期估算(采用自相關方法)
step3:
??? 自適應激勵碼本搜索
step4:
??? 去除自適應激勵貢獻后的語音數據的激勵碼本搜索
??? 它包含兩種速率下面的不同處理,分別為高速率下多脈沖激勵碼搜索,以及低速率下的固定碼本搜索
?? ?
?? ?
?????????????????????????????????????????????????????????????? 林紹川
?????????????????????????????????????????????????????????????? 2011.10.06 于杭州
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?
在高速率下面,對去了自適應激勵成份后的語音信號,
g723采用的是多脈沖編碼方式.本文現做一個簡要的閘述
在分析代碼之前,仍然是要做一些公式推導,否則不易讀懂代碼
過程其實與固定碼本搜索時的方式類似.
多脈沖激勵的定義:
激勵是由有限個經過最優估值的脈沖構成(每個脈沖的位置與增益都是
經過最優估值的)
那么很容易得出相應的誤差公式,假設脈沖的個數是m
???????????? ? ? ?? M
e[n]= t[n] -? Σ? g(k) * h[n-n(k)]
?????????? ? ? ?? k=1
n(k) 代表第k個脈沖的位置 g(k)代表第k個脈沖的增益
誤差均方:
?????? N????????? ? ? ?? N??????????? M
E = Σ? e[n]^2 =? Σ? (t[n] -? Σ? g(k) * h[n-n(k)])^2 ---- <式1>
? ?? n=1???????? ? ? n=1???????? k=1
對
?M
?Σ? g(k) * h[n-n(k)]
k=1
這個式子進行一些處理,將其變形為
?N
?Σ? g(l) * h[n-l]
l=1
當l=n(k) g(l)為對應位置的脈沖值g(k),
其它的l取值時g(l)為零
<式1>此時可以變形為
??? N??????????? N?????????? N
E = Σ? e[n]^2 =? Σ? (t[n] -? Σ? g[l] * h[n-l])^2
?? n=1????????? n=1???????? l=1
?? ? ? N??????????? ? ? ?? N?????? ? N?????????????????? ? ? ? N? ? ? N? ? ? N
E = Σ t[n]^2 - 2 * Σ t[n] * Σ (g[l] * h[n-l]) +? Σ???? Σ?????? Σ? g[j]*h[n-j]*g[l]*h[n-l]
? ?? n=1????????????? n=1???? ? l=1??????????????? ? ? ? n=1? j=1 ?? l=1
??? N???????????? N??????? N??????????????????? N?? N??????????????? N
? = Σ t[n]^2 -2 * Σ g[l] * Σ (t[n] * h[n-l]) +? Σ?? Σ? g[j] * g[l] * Σ (h[n-j]*h[n-l])?? --- 交換求和次序
?? n=1?????????? l=1????? n=1????????????????? l=1 j=1????????????? n=1
??? N??????????????????? M?????? ?? N???????????????????? ? ? ? ? ? ?? M??????? ? M??????? ?? N
? = Σ t[n]^2 - 2 * Σ g[k] * Σ (t[n] * h[n-n(k)]) +? Σ g[k] *? Σ? g[j] *? Σ (h[n-n(j)]*h[n-n(k)])
?? n=1???????? ? ?? ? k=1????? n=1????????????????? ? ? ? ? ? ? k=1?????? j=1??????? n=1
--- 變量替換,去除g(x)等于0的項
E分別對每個g(k)分別進行求導,g(k)最優估值必定要導數為零處,將會得到M個等式
?N????????????????????? ? ? ? ? ? M??????? ? N
?Σ (t[n] * h[n-n(k)]) =? Σ? g[j] * Σ (h[n-n(j)]*h[n-n(k)])???????????? k = 1,2, ..., M
n=1??????????????????????????? j=1?????? n=1
可以化簡為
??????????? ? ? ? ?? M
?Rth(n(k)) = Σ g[j] Rhh(n(j),n(k)) ---<式2>???????? Rth是t與h的互相關m, Rhh是h的自相關
????????? ? ? ? ? ?? j=1
?????????? ?
而<式1>可以化簡為:
?? ? ? N???????? ?? M
E = Σ t[n]^2 - Σ g[k]*Rt(n(k)) ---<式3>
????? n=1??????? k=1
? ?
由于n(k)是未知的,要求解這個方程是極其復雜的,
在難以求得最優解的情況下,采用一種簡化算法,求得次優解
即每次只求一個最優解的位置,<式2>就變成這樣:
Rth(n(1)) = g[1] Rhh(n(1),n(1)) ---<式4>
??????? Rth(n(1))
g[1] = --------------
?????? Rhh(n(1),n(1))
從<式3>可以看出,n(1)是滿足下式最大值的位置
?? Rth(n(1))^2
? --------------?? ---<式5>
? Rhh(n(1),n(1))
這樣可以很容易地求出n(1),并根據<式4>求出g[1]
然后從 t中扣除g[1]與h卷積后的成份,更新t
t[n] = t[n] - g[1] * h[n-n(1)] ---<式6>
用更新后的t繼續進行下一輪的搜索,直到找出M個脈沖位置以及它們的增益.
以上是公式推導過程,與itu的文檔中的描述相當接近了,不過itu采取的是更為化簡的估值算法.
itu認為每個脈沖的增益都是相同的,用
??? max(|Rth(i)|)
G= ------------?? ---- 等同于itu文檔中的公式25
??? Rhh(0,0)
來對增益進行估值,
在G-3.2db ~ G + 6.4db這個范圍內,將G分成4個等級值,進行搜索脈沖的位置
脈沖位置搜索的依據是<式5>,并且忽略了分母的差異,只搜索分子最大的
每搜索一次按照<式6>更新輸入的殘差信號(代碼里直接更新自相關,道理是相同的)
最后,得到估值增益,以及脈沖位置
推倒完畢(^_^),現在進入代碼:
Find_Best
這個函數描述了搜索脈沖位置與增益的過程
首先是構造沖激響應,在后面會提到,搜索會根據基音周期是否小于子幀長,再調整沖激響應
再進行一次搜索,然后與未調整沖激響應的搜索結果進行比較,取更接近的那一組脈沖位置與增益
??? /* Update Impulse response */
??? if ( Olp < (Word16) (SubFrLen-2) ) {
??????? Temp.UseTrn = (Word16) 1 ;
??????? Gen_Trn( Imr, ImpResp, Olp ) ;//lsc 相當于與olp為周期間隔脈進行卷積
??? }
??? else {
??????? Temp.UseTrn = (Word16) 0 ;
??????? for ( i = 0 ; i < SubFrLen ; i ++ )
??????????? Imr[i] = ImpResp[i] ;
??? }
計算沖激響應的自相關,以相沖激響應與目標向量的互相關,并對其進行歸一化處理,這里不貼代碼了
計算的結果存放在ImrCorr(沖激響應自相關) ErrBlk(沖激響應與目標向量的互相關)
ImrCorr是擴大2^(9 + Exp)倍的
ErrBlk是擴大2^(10 + Exp)倍的(這樣便于后繼的計算)
由于脈沖要么全位于奇位置,要么全位于偶位置,所以搜索分成奇偶兩次
在搜索循環中,首先進行增益估值
增益估值使用的是FcbkGainTable這個碼本表里的值,該碼本表是與固定碼本增益共享的
采用乘法運算,繞開費時的除法運算,即將增益碼本FcbkGainTable里的值與沖激響應的零時自相關(即Rhh(0))相乘
然后與ErrBlk數組里絕對值最大的相減(也就是max(|Rth(i)|)),取差值最小的那個增益,然后在它附近的4個增益值中
進行搜索最優增益估值
代碼如下:
??? /* Search for the best sequence */ //lsc 這里是指奇偶兩次循環
??? for ( k = 0 ; k < Sgrid ; k ++ ) {
??????? Temp.GridId = (Word16) k ;
??????? /* Find maximum amplitude */ //lsc 找了最大的那個 |d[j]|
??????? Acc1 = (Word32) 0 ;
??????? for ( i = k ; i < SubFrLen ; i += Sgrid ) {
??????????? Acc0 = L_abs( ErrBlk[i] ) ;
??????????? if ( Acc0 >= Acc1 ) {
??????????????? Acc1 = Acc0 ;
??????????????? Temp.Ploc[0] = (Word16) i ;//lsc 互相關絕對值最大的那個的下標,這也是搜索過程中被搜索出的第一個脈沖的位置
??????????? }
??????? }
??????? /* Quantize the maximum amplitude */
??????? Acc2 = Acc1 ;//lsc Acc2就是最大的 |d[j]|
??????? Acc1 = (Word32) 0x40000000L ;
??????? MaxAmpId = (Word16) (NumOfGainLev - MlqSteps) ;
??????? //lsc 這里再次利用乘法繞開除法,將 G* Rhh[0]得到的結果與 Acc2相減,差值最小的那個就是G
??????? for ( i = MaxAmpId ; i >= MlqSteps ; i -- ) {
??????????? Acc0 = L_mult( FcbkGainTable[i], ImrCorr[0] ) ;
??????????? Acc0 = L_sub( Acc0, Acc2 ) ;//lsc 同一數量級,所以可減
??????????? Acc0 = L_abs( Acc0 ) ;
??????????? if ( Acc0 < Acc1 ) {
??????????????? Acc1 = Acc0 ;
??????????????? MaxAmpId = (Word16) i ;
??????????? }
??????? }
??????? MaxAmpId -- ;//lsc 得到的值在降一級搜索,見itu文檔 MaxAmpId最小值是1
??????? //lsc 位置的搜索過程,我們看到一些簡化,即G都是一樣的,每個位置的搜索并不對增益做任何更新(照理應計算出G,并用其來更新互相關)
??????? //按G的值循環搜索
??????? for ( i = 1 ; i <=2*MlqSteps ; i ++ ) {
??????????? for ( j = k ; j < SubFrLen ; j += Sgrid ) {
??????????????? WrkBlk[j] = ErrBlk[j] ;//lsc 取出偶數位/奇數位的 互相關
??????????????? OccPos[j] = (Word16) 0 ;
??????????? }
??????????? Temp.MampId = MaxAmpId - (Word16) MlqSteps + (Word16) i ;//lsc 這樣做等最從0位置開始搜索
??????????? MaxAmp = FcbkGainTable[Temp.MampId] ;
??????????? if ( WrkBlk[Temp.Ploc[0]] >= (Word32) 0 )
??????????????? Temp.Pamp[0] = MaxAmp ;
??????????? else
??????????????? Temp.Pamp[0] = negate(MaxAmp) ;
??????????? OccPos[Temp.Ploc[0]] = (Word16) 1 ;//lsc 選中第一個位置,對均方差求導很容易得到這個結論
??????????? for ( j = 1 ; j < Np ; j ++ ) {
??????????????? Acc1 = (Word32) 0xc0000000L ;
??????????????? for ( l = k ; l < SubFrLen ; l += Sgrid ) {
??????????????????? if ( OccPos[l] != (Word16) 0 )//lsc 表示這個位置已經被選中了
??????????????????????? continue ;
??????????????????? Acc0 = WrkBlk[l] ;//lsc 這個是互相關
??????????????????? Acc0 = L_msu( Acc0, Temp.Pamp[j-1],
??????????????????????????? ImrCorr[abs_s((Word16)(l-Temp.Ploc[j-1]))] ) ;//lsc 這里是在更新互相關,因為分母都一樣,所以只要分子最大,就可以選定這個位置
??????????????????? WrkBlk[l] = Acc0 ;
??????????????????? Acc0 = L_abs( Acc0 ) ;
??????????????????? if ( Acc0 > Acc1 ) {
??????????????????????? Acc1 = Acc0 ;? ?
??????????????????????? Temp.Ploc[j] = (Word16) l ;//lsc Ploc的意思是 pluse location,即脈沖位置,
??????????????????? }
??????????????? }
??????????????? //lsc 這里其實只是記錄符號
??????????????? if ( WrkBlk[Temp.Ploc[j]] >= (Word32) 0 )
??????????????????? Temp.Pamp[j] = MaxAmp ;
??????????????? else
??????????????????? Temp.Pamp[j] = negate(MaxAmp) ;
??????????????? //lsc 選定位置
??????????????? OccPos[Temp.Ploc[j]] = (Word16) 1 ;
??????????? }
??????????? /* Compute error vector */
??????????? for ( j = 0 ; j < SubFrLen ; j ++ )
??????????????? OccPos[j] = (Word16) 0 ;
??????????? for ( j = 0 ; j < Np ; j ++ )
??????????????? OccPos[Temp.Ploc[j]] = Temp.Pamp[j] ;
??????????? //lsc 計算卷積
??????????? for ( l = SubFrLen-1 ; l >= 0 ; l -- ) {
??????????????? Acc0 = (Word32) 0 ;
??????????????? for ( j = 0 ; j <= l ; j ++ )
??????????????????? Acc0 = L_mac( Acc0, OccPos[j], Imr[l-j] ) ;
??????????????? Acc0 = L_shl( Acc0, (Word16) 2 ) ;
??????????????? OccPos[l] = extract_h( Acc0 ) ;
??????????? }
??????????? /* Evaluate error */
??????????? //lsc 計算均方差
??????????? Acc1 = (Word32) 0 ;
??????????? for ( j = 0 ; j < SubFrLen ; j ++ ) {
??????????????? Acc1 = L_mac( Acc1, Tv[j], OccPos[j] ) ;
??????????????? Acc0 = L_mult( OccPos[j], OccPos[j] ) ;
??????????????? Acc1 = L_sub( Acc1, L_shr( Acc0, (Word16) 1 ) ) ;
??????????? }
??????????? //lsc 如果大,說明均方差小 (a^2 - 2ab + b^2) 很容易得到這個結論
??????????? //則選這組位置
??????????? if ( Acc1 > (*Best).MaxErr ) {
??????????????? (*Best).MaxErr = Acc1 ;
??????????????? (*Best).GridId = Temp.GridId ;
??????????????? (*Best).MampId = Temp.MampId ;
??????????????? (*Best).UseTrn = Temp.UseTrn ;
??????????????? for ( j = 0 ; j < Np ; j ++ ) {
??????????????????? (*Best).Pamp[j] = Temp.Pamp[j] ;
??????????????????? (*Best).Ploc[j] = Temp.Ploc[j] ;
??????????????? }
??????????? }
??????? }
??? }
致此,g723編碼部分的代碼分析絕大部分已經完成了,剩余的一些代碼是更新自適應碼本,打包字節等
這將在下一個章節做一個簡述
這里做一個g723編碼模塊的簡要小結
step1:LPC分析
??? 這一步驟就是要得出一個全極點的聲道系統函數,并且依此生成聲道的沖激響應
??? 它包括lpc參數計算(萊文森德賓遞推公式) 轉lsp,并量化反量化等
?? ?
step2:
??? 語音數據處理,包括共振峰感知加權,基音周期估算(采用自相關方法)
step3:
??? 自適應激勵碼本搜索
step4:
??? 去除自適應激勵貢獻后的語音數據的激勵碼本搜索
??? 它包含兩種速率下面的不同處理,分別為高速率下多脈沖激勵碼搜索,以及低速率下的固定碼本搜索
?? ?
?? ?
?????????????????????????????????????????????????????????????? 林紹川
?????????????????????????????????????????????????????????????? 2011.10.06 于杭州
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?
總結
以上是生活随笔為你收集整理的g723源码详细分析-11-多脉码激励编码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS7使用yum安装MySql并
- 下一篇: 东进数字卡会议编程