g723源码详细分析-2 lpc转化lsp

3 lpc系数转成lsf系数 AtoLsp

首先解释一下为什么需要lsf(lsp)系数
A(z)在形式上不是以因式分解给出的,如果直接设一个lpc码本表,
对lpc系数进行矢量量化,则某个lpc系数的误差对信号整个频域的影响,
为了消除这种误差影响,我们自然地想到了利用A(z)方程的因式分解形式,
也就是说对A(z)=0的根建立码本表,对其进行矢量量化,这样每个量化后根
的误差,只对某个频域的产生影响.

lsf系数即是通过对A(z)进行变形,然后求根,它是变形后的A(z)的根.
而且它的特点是,所有的根一定在单位圆上,这就对计算机处理提供了便利
(A(z)=0的根显然不会都在单位圆上,这将导致极复杂的求根过程以及量化计算量)

现在介绍A(z)的变形

我们定义
P(z) = A(z) + Z^-(P + 1)A(z^-1)
Q(z) = A(z) - Z^-(P + 1)A(z^-1)  p是阶数,在lpc10阶里 p=10

而线谱对的真正含义是以下这两个形式的根即, P1(z)=0 以及Q1(z)=0的根

P1(z) = P(z)/(1 + z^(-1))
Q1(z) = Q(z)/(1 - z^(-1))

除(1 + z^(-1)) 是为了将 1 -1这样的根去除,降次

P(z) Q(z)对称多项式,特点是根一点在单位圆上,并且分别是在单位元上交错出现的
相应的证明请参考
F.K.Soong and B.H.Juang 的"Linear Spectrum Pair(LSP) and Speech Data Compression"
IEEE IC on ASSP,1984,pp.1.10.1-1.10.4
http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1172448 这个为网址,文档似乎是要付费的...
http://en.wikipedia.org/wiki/Line_spectral_pairs
维基百科上的解释,似乎跟P(z)是对称多项式的性质有关,导致了它的根出现在单位圆上


AtoLsp
lpc系数转成lsp系数

首先做了带宽扩展
 /*
  * Perform a bandwidth expansion on the LPC coefficients.  This
  * scales the poles of the LPC synthesis filter by a factor of
  * 0.994.
  */ //lsc 理解 相当于对冲激响应序列依次乘以 0.994   0.994^n在傅里叶变换的幅值是一个碗状,在0-2派之间,
    //与冲激响应进行卷积时,会让冲激响应的带宽扩展
    for ( i = 0 ; i < LpcOrder ; i ++ )
        LspVect[i] = mult_r( Lpc[i], BandExpTable[i] ) ;//lsc 相乘后得到的值是原值

P(z) 与 Q(z)的根是共轭对称的 很容易证出如果 z是p(z)=0的根,那个 z^-1也是p(z)的根,
在单位圆上,即说明p(z)的根是共轭对称出现

在进行长除法之前,先把 p(z) q(z)的定义详细说明一下,以及搜索时用到的一个变形也在下面给出:

    P(z) = A(z) + Z^-(P + 1)A(z^-1)   A(z) = 1 - a1*z^-1 - a2*z^-2 - ... - a10*z^-10   z^-n表示 z的-n次方
    Q(z) = A(z) - Z^-(P + 1)A(z^-1)
    P1(z) = P(z)/(1 + z^(-1))
    Q1(z) = Q(z)/(1 - z^(-1))  ---- 根其实一样,做除法降次,去掉了 z=1 z=-1这样的根,因为这两个根本身不包含特征信息

    P1(z)分母 = z^-11 + (-a1 - a10)z^-10 + (-a2 - a9)z^-9 + ...  (-a1 - a10)z^-1 + 1
    Q1(z)分母 = -z^-11 + (a1 - a10)z^-10 + (a2 - a9) z^-9 + ...  (a1 - a10) z^-1 + 1

    A(z) = 1/2 {P(z)(1 + z^{-1}) + Q(z)(1-z^{-1})}  --- 从这里看出了itu对P1(z) Q1(z)的定义(网上流行有各种版本定义,让笔者纠结了很久...)

    P1(z) = b0(z^-10 + 1) + b1(z^-9 + z^-1) + ... + b5 * z^-5
          = z^-5(b(z^-5 + z^5) + b1(z^-4 + z^-4) + ... + b5) --- z= e^jw代入
          = z^-5 * (b0 * 2cos(5w) + b1 * 2cos(4w) + ... + b5)  b5是需要除2的,因为其它系数有个乘2因子

接下来,itu开始执行长除法,得到p1(z) q1(z)的系数
代码片段与注释

 /*
  * Set p_0 = q_0 = 1.  The LPC coefficients are already scaled by
  *  1/4.  P(z) and Q(z) are scaled by an additional scaling factor of
  *  1/16, for an overall factor of 1/64 = 0x02000000L.
  */

    Lpq[0] = Lpq[1] = (Word32) 0x02000000L ;//lsc 0x80000000的1/64 1/4的lpc缩放源自语音信号本身缩小了1/2,而1/16的缩放见下面的代码段 这里认为是最高次 z^-11的系数

 /*
  * This loop computes the coefficients of P(z) and Q(z).  The long
  * division (to remove the real zeros) is done recursively.
  */ //lsc这个循环实际在执行多项式除法,求出pz qz的每阶的系数,求出前6个,后5是不需要求的,因为一样(可以通过多项式除法的定义,以及P(z)系数的对称性,推导出来)
    for ( i = 0 ; i < LpcOrder/2 ; i ++ ) {
//lsc -11这个阶就不用求了,根据多项式除法定义,这个值一定是1
        /* P(z) */
        Acc0 = L_negate( Lpq[2*i+0] ) ;   //lsc 根据多项式长除法,向低阶次"借"了 高阶次的系数(完成了长除法后的),应扣减
        Acc1 = L_deposit_h( LspVect[i] ) ;
        Acc1 = L_shr( Acc1, (Word16) 4 ) ;
        Acc0 = L_sub( Acc0, Acc1 ) ;//lsc 系数的规律 如 -10这个阶,它应该是 -(a10 + a1),所以对应该阶次的系数还应再减去相应的值
        Acc1 = L_deposit_h( LspVect[LpcOrder-1-i] ) ;
        Acc1 = L_shr( Acc1, (Word16) 4 ) ;
        Acc0 = L_sub( Acc0, Acc1 ) ;//lsc 这里完成了长除法 以-10这个阶为例 - a1 - a10 - 1(对照长除法结果, z^-11 + 1 - 1, 导到了-1的产生,而z^-10系数为-a1 - a10导致了这个结果)
        Lpq[2*i+2] = Acc0 ;

        /* Q(z) */ //lsc 这段同上,也是完成多项式长除法,就不详细分析了
        Acc0 = Lpq[2*i+1] ;
        Acc1 = L_deposit_h( LspVect[i] ) ;
        Acc1 = L_shr( Acc1, (Word16) 4 ) ;

        Acc0 = L_sub( Acc0, Acc1 ) ;
        Acc1 = L_deposit_h( LspVect[LpcOrder-1-i] ) ;
        Acc1 = L_shr( Acc1, (Word16) 4 ) ;
        Acc0 = L_add( Acc0, Acc1 ) ;//lsc - a1 + a10 + 1(对照长除法结果  - z^-11 + (1 - 1)z^-10,产生-1项留给z^-10,而z^-10的系数应为a1 - a10,导致了 -a1 + a10 -1,取反,(1-z^-1)最终结果是 -a1 + a10 + 1)
        Lpq[2*i+3] = Acc0 ;

最后一项没有乘2因子,所以要缩小一半

 /*
  * Divide p_5 and q_5 by 2 for proper weighting during polynomial
  * evaluation.
  */
    Lpq[LpcOrder+0] = L_shr( Lpq[LpcOrder+0], (Word16) 1 ) ;
    Lpq[LpcOrder+1] = L_shr( Lpq[LpcOrder+1], (Word16) 1 ) ;//lsc 其它项都有乘2因子,唯最后一项是没有的

接下来对所有系数归一化,这里就不列举代码片段了,

然后是查cos表,在单位圆上暴力搜索过零值,求根
利用了这个等式求根
P1(z) = z^-5 * (b0 * 2cos(5w) + b1 * 2cos(4w) + ... + b5)

对cos表里的每个角度,计算当前值,与PrevVal值进行比较,如果异号,说明过零了

代码片段
CurrVal = L_mac( CurrVal, Spq[LpcOrder-2*j+k],
                                    CosineTable[i*j%CosineTableSize] ) ;// j次方,对应复数就是角度被乘积,需要乘j

会根据PrevVal  CurrVal 的比例,线性地计算小数点后7位,代码片段如下
            Acc0 = L_abs( CurrVal ) ;
            Acc1 = L_abs( PrevVal ) ;
            Acc0 = L_add( Acc0, Acc1 ) ;

            /* Normalize the sum */
            Exp = norm_l( Acc0 ) ;
            Acc0 = L_shl( Acc0, Exp ) ;
            Acc1 = L_shl( Acc1, Exp ) ;

            Acc1 = L_shr( Acc1, (Word16) 8 ) ;

            LspVect[LspCnt] = div_l( Acc1, extract_h( Acc0 ) ) ;//此举的意义是保留小数点后7位,即得到的应该是 n.?? 0 < n < 256 n即当前下标i

最终得到的lsp是由9位整数部分,7位小数部分组成的,代码片段如下:
            Exp = shl( (Word16) (i-1), (Word16) 7 ) ;
            LspVect[LspCnt] = add( LspVect[LspCnt], Exp ) ;//得 9 + 7 即的浮点数 lsp频率

如果没有搜索到10根,则沿用之前帧的lsp系数.

致此,完成了lpc到lsp的转换



Lsp_Qnt

lsp量化,分将10个lsp系数分成 3 + 3 + 4 分别在码本里按欧式距离最小的规则进行矢量量化,待续


                                                                                        林绍川
                                                                                        2011.05.06 于杭州






转载于:https://www.cnblogs.com/lsccsl/archive/2011/10/08/g723_c_codec_lpc_lsp_lsf.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值