zoukankan      html  css  js  c++  java
  • [原创]桓泽学音频编解码(4):MP3 和 AAC 中反量化原理,优化设计与参考代码中实现

    标准11172-3(MP3)的量化原理

    11172-3即mpeg-1 audio(以下称11172-3)中层1层2和层3的量化算法是不同的,层1层2使用的是均匀量化,层3使用的是非均匀量化。

    层1和层2的反量化公式如下。

    层1和层2的rescaler公式如下。

    S´´ 输入反量化数据

    层3的反量化公式

    (1)    long block:

    (2)    short block:

    标准13818-7(AAC)的量化原理

    13818-7即AAC标准中所采用的非均匀量化公式

     

     

    其中int为取整操作.mdct_line是mdct输出频率谱线,scalefactor是各子带的缩放因子,common_scalefac是全局缩放因子,MAGIC_NUMBER是调整偏差,其值为60。

     

    非线性反量化公式如下所示:

     

     

    非线性量化的主要优点是内置有一个取决于系数幅度的噪声整形。对于给定的频谱样值,在一定的范围内增加scalefactor或减小全局缩放因子嘟可以放大量化器输出值的幅度,同时迅速降

    低量化失真的程度。

     

    反量化模块优化设计

    对与反量化模块的实现有以下几种方式

    1. 直接计算法

    2. 查表法

    3. 泰勒展开式法

    4. 线性差值法

    5. 综合法

    直接计算的话使用的是超越函数计算,运算量很大,不适合应用。查表法是算法最简单,计算量最小,但它属于一种用空间换时间的方法,即制作一张对于所有范围的输入数据,都能直接得到输出结果的表。但是若输入数据的范围为较大,如果全部制成表格,则需存储表格的空间也很大,浪费空间。泰勒展开式法是一种用普通计算代替超越函数计算的方法,但随着精度的提高泰勒展开的级数也增加较大。运算量也是相当的大。不适合实现。所以一般都用线性差值加查表法的综合结构实现反量化解码。

     

    在11172-3和13818-7中,反量化的主要部分是

     

    计算xiquant的值是反量化的主要工作,常规的方法是采用查表法,即制作一张对于所有范围的输入数据,都能直接得到输出结果的表。但是由于x的范围为08191,如果全部制成表格,则需8192字存储空间,在存储空间紧张的系统中这样做非常不经济。因此,为了降低存储空间,同时也保证运算的正确性。制作长度为256的查找表,每项以4字节表示,其它数值可以通过线性插值运算得到:

    1)对于x= 1--256之间的值,可以直接查表得到。

     

    2)对于x在257-2048之间的值,使用公式:

    3)对于x在2049-8192之间的值,使用公式:

     

    式中int()表示取整,rem()表示取余,f()对系数表进行查找操作。使用这种方法在节省了存储空间的同时,计算也只是简单的乘加运算。在定点处理器中式3-6或式3-7的运算只要一次乘法,3次加法和3次移位操作。虽然这种简化运算与实际值有误差,但是在实际解码时量化后的频谱系数超过256的往往所占比例并不是很大,经过统计发现, x的取值小于256的占了99%,这说明使用这种插值和查找表方法是能够得到满意的解码音质。

     

    反量化模块在不同参考软件中的实现方法

    13818-7 参考代码上的iquant实现

    MAX_IQ_TBL = 128

    在128以下的值用查表法

    在128以上的值用直接计算法

    以下来自esc_iquant函数

        if (q < MAX_IQ_TBL) {

          return((Float)iq_exp_tbl[q]);

        }

        else {

          return(pow(q, 4./3.));

    }

    Faad参考代码上iquant实现

    以下iquant不含负数变正书处理

    #ifdef FIXED_POINT

    /* For FIXED_POINT the iq_table is prescaled by 3 bits (iq_table[]/8) */

    #ifndef BIG_IQ_TABLE

     Faad的处理提供两种方法,使用宏定义区别开来

    方法1

    全部查表法,

          // IQ_TABLE_SIZE = 8192

    if (q < IQ_TABLE_SIZE)

        {

            return sgn * tab[q];

    }

    注faad的表是静态表,在全局数据段中

    方法2

    部分查表加线性差值法

    #define COEF_BITS 28

    #define COEF_PRECISION (1 << COEF_BITS)

    #define REAL_BITS 14 // MAXIMUM OF 14 FOR FIXED POINT SBR

    #define REAL_PRECISION (1 << REAL_BITS)

    #define REAL_CONST(A) \

    (((A) >= 0) ? ((real_t)((A)*(REAL_PRECISION)+0.5)) : ((real_t)((A)*(REAL_PRECISION)-0.5)))

    static const real_t errcorr[] =

    {

            REAL_CONST(0)     , REAL_CONST(1.0/8.0),

    REAL_CONST(2.0/8.0) , REAL_CONST(3.0/8.0),

            REAL_CONST(4.0/8.0) , REAL_CONST(5.0/8.0),

    REAL_CONST(6.0/8.0) , REAL_CONST(7.0/8.0),

            REAL_CONST(0)

        };

        real_t x1, x2;

    // IQ_TABLE_SIZE = 1026

        if (q < IQ_TABLE_SIZE)

        {

            return sgn * tab[q];

        }

       if (q >= 8192)

        {

            *error = 17;

            return 0;

        }

        /* 线性差值部分 */

        x1 = tab[q>>3];

        x2 = tab[(q>>3) + 1];

        return sgn * 16 * (MUL_R(errcorr[q&7],(x2-x1)) + x1);

    faad使用的公式和前面提出的不大一样

    只要q>1026就用公式

    Libmp3dec的iquant实现

    Libmp3dec使用函数l3_unscale完成反量化和rescale 两个功能

    l3_unscale反量化使用全部查表法实现反量化

    e = table_4_3_exp[value];

    但与faad的全查表不同的是,libmp3dec的表是动态表,在堆栈中,初始化时申请的。Faad的表在全局数据段中。是静态的。

    MPEG1 参考代码的iquant实现

    态的MPEG1参考代码的iquant在III_dequantize_sample函数中实现,完全使用exp指数运算。

  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/gaozehua/p/2482087.html
Copyright © 2011-2022 走看看