zoukankan      html  css  js  c++  java
  • AAC 无损解码模块算法分析

    标题指引

    1. 无损解码概述

    2.解码过程

      2.1 解码scalefactor

    2.2 解码量化谱线数据

    2.2.1 对小于16的量化谱线系数的解码方法

    2.2.2 对等于16的量化谱线系数的解码方法

      2.3 解码脉冲数据

      2.4 recoder处理

    3 C参考代码

    1. 无损解码概述

    在AAC编码器内部,无损编码用于进一步减少scalefactor和量化谱线系数的冗余。

    在AAC解码器内部,从individual_channel_stream层提取码流进行解码无损解码。码流信息包括以下解码量化谱线数据部分(global_gain,section_data(),section_scalefactor(),spectra_data())和解码脉冲数据部分(pulse_data_present, pulse_data())。

    2.解码过程

      2.1 解码scalefactor

      Scalefactor压缩数据来自码流中scale_factor_data()。

    AAC首次提出对差分scalefactor数据使用huffman编码。并且有1个huffman表。

    码流格式如下

     

    scale_factor_data()

    {

          for (g = 0; g < num_window_groups; g++) {

                for (sfb = 0; sfb < max_sfb; sfb++) {

                      if (sfb_cb[g][sfb] != ZERO_HCB) {

                            if (is_intensity(g,sfb))

                                  hcod_sf[dpcm_is_position[g][sfb]];

                            else

                                  hcod_sf[dpcm_sf[g][sfb]];

                      }

                }

          }

    }

      

    注1:sfb_cb[g][sfb] != ZERO_HCB表示窗组g的sfb子带的谱线码本不是0。若sfb_cb[g][sfb] == ZERO_HCB表示在窗组g的sfb子带内的谱线数据全部为0。谱线数据全部为0也就没有什么Scalefactor,所以码流中存在Scalefactor的前提条件是sfb_cb[g][sfb] != ZERO_HCB。

    注2:is_intensity(g,sfb)表示在窗组g的sfb子带内是否使用强度立体声编码。因为在使用了强度立体声编码的通道内传送的是dpcm_is_position数据不是差分scalefactor数据。

    在获取了差分scalefactor数据dpcm_sf[g][sfb]以后,按照如下公式解码。

    Scalefactor[g][sfb]=dpcm_sf[g][sfb]+ Scalefactor [g][sfb-1];

    1≤Sfb≤max_scalefactor

    Scalefactor [g][0]=global_gain

    2.2 解码量化谱线数据

    量化谱线数据来自码流中spectral_data()。AAC的huffman编码算法对量化谱线有两步分组处理.如上所述,第一步分组是分出scalefactor band中的谱线个数是4的倍数.目的是进行4个谱线一起编码.第二步分割是标准中把1个或几个scalefactor band合并成一个section.同一个section内的所有scalefactor band的谱线使用同一个huffman码表.所以,如果要进行huffman解码,section的宽度信息和码本号作为side information附加在section data中传输.解码端要先解出这些信息才能进行huffman解码.而section的长度小于scalefactor band的个数而大于scalefactor windows band的个数. 为了最大限度的匹配量化谱线的统计特性,Huffman为了使量化谱线的统计特性最大化的匹配huffman码本,section的数量允许和scalefactor band的数量一样大. Section个数的最大值是max_sfb.但注意section的边界要与scalefactor band的边界重合. 用huffman编码的4个一组的量化系数和2个一组的4个一组的量化系数的传送顺序是从低频系数到高频系数. 对于每个frame有多个windows的情况,要注意有分组和交织情况,系数的集合需要解交织,系数存储在数组x_quant[g][win][sfb][bin]。

    AAC的huffman解码一共有15个码本,除了一个码本专用于scalefactor解码.11个码本用于谱线系数的解码.1个码本表示传输的系数全位零,是0码本,不需解码.2个码本是intensity码本,也是0码本.在为谱线系数解码的11个码本中,每个码本有自己可以编码的最大量化谱线系数的绝对值,用LAV表示.如表2, 用于谱线系数的解码的11个码本中最后一个码本可以解码出谱线系数的最大值是16.但当解码出谱线系数的值大于0小于16的时候.解码出的值就是实际的谱线系数的绝对值,当解码锄地谱线系数是16时,表示退出huffman解码,使用其他方式解码(稍后说明).所以在该码本中解码出的值16被定义成ESC_FLAG.表2中的unsigned_cb[i]标志位表示该码本是有符号码本还是无符号码本,unsigned_cb[i]=0时表示该码本是有符号码本, unsigned_cb[i]=1时表示该码本是无符号码本.解码有符号数时,先按照无符号解码再从输入的解码比特流中提取符号位,若解码出的谱线系数非零,则其符号位紧跟在被该谱线系数的码字的后面。

    量化谱线 Huffman码本参数

    Codebook Number, i

    unsigned_cb[i]

    Dimension of Codebook

    LAV for codebook

    Codebook listed in

    0

    -

    -

    0

    -

    1

    0

    4

    1

     

    2

    0

    4

    1

     

    3

    1

    4

    2

     

    4

    1

    4

    2

     

    5

    0

    2

    4

     

    6

    0

    2

    4

     

    7

    1

    2

    7

     

    8

    1

    2

    7

     

    9

    1

    2

    12

     

    10

    1

    2

    12

     

    11

    1

    2

    (16) ESC

     

    12

    -

    -

    (reserved)

    -

    13

    -

    -

    (reserved)

    -

    14

    -

    -

    intensity out-of-phase

    -

    15

    -

    -

    intensity in-phase

    -

    Codebook Number,i:码本的索引,即码流中sect_cb值。

    unsigned_cb[i]:表示码本i是有符号码本还是无符号码本。

    Dimension of Codebook:码本的维数。

    2.2.1 对小于16的量化谱线系数的解码方法

    首先解码huffman表中的index值。再完成从index到谱线数据的映射。流程图如下

    之所以采取分组的整体huffman编码的方法是为了进一步压缩帧内的相关性节省码字.但由index映射到谱线数据一步实在多此一举(当然也有好处就是节省码本空间),实际上完全可以直接选用(w,x,y,z)制表,查表。

     2.2.2 对等于16的量化谱线系数的解码方法

     若sect_cb等于11且解码出的谱线系数有y,z值有一个等于ESC_FLAG(ESC_FLAG等于16)的情况要进行跳出huffman表的处理,使用其他方式编码。跳出huffman表

    表示码流中有一个escape_sequence值表示跳出huffman表的谱线的值。这个escape_flag是变长的。由3部分组成escape_prefix,escape_separator和escape_word组成。

    escape_prefix是N个1,escape_separator是1个0。escape_word是一个N+4位的值。

    escape_sequence=2^(N+4)+ escape_word;

    注意,escape_sequence也是有符号的,在解码escape_sequence之前,有几个符号位就有几个escape_sequence。(实际上有几个escape_sequence前面一定有相应多的符号位)。

    解码流程图如下

     2.3 解码脉冲数据

      若码流中的标志位pulse_data_present为1则表示编码器使用了脉冲退出处理。表示在编码器端有一个或多个量化谱线用更小的幅值的系数替代number_pulse表示有多少个量化系数被替代,在重建谱线数据时要在相应的谱线中加上或减去pulse_amp值。注意:在8短窗序列中是不能使用脉冲数据编码的。

       算法流程图

    2.4 recoder处理

    由于在其他的解码器中都是使用不分组的谱线数据,所以对已经分组的量化谱线数据要重新排序。伪代码如下

    quant_to_spec() {

       k = 0;

       for (g = 0; g < num_window_groups; g++) {

         j = 0;

         for (sfb = 0; sfb < num_swb; sfb ++) {

            width = swb_offset[sfb+1] - swb_offset[sfb];

            for (win = 0; win < window_group_length[g]; win++) {

               for (bin = 0; bin < width; bin++) {

                 spec[win+k][bin+j] = x_quant[g][win][sfb][bin] ;

               }

            }

            j += width;

         }

         k += window_group_length[g];

       }

    }

    3 C参考代码

    13818 -7 ISO官方参考代码中解码一个huffman码字的函数的流程图与注释:

    int decode_huff_cw(Huffman *h)函数的流程图与注释

  • 相关阅读:
    HDU4507 吉哥系列故事――恨7不成妻(数位dp)
    UCF Local Programming Contest 2017 G题(dp)
    ICPC Latin American Regional Contests 2019 I题
    UCF Local Programming Contest 2017 H题(区间dp)
    HDU2089 不要62
    AcWing1084 数字游戏II(数位dp)
    UCF Local Programming Contest 2017 F题(最短路)
    Google Code Jam 2019 Round 1A Pylons(爆搜+贪心)
    AcWing1083 Windy数(数位dp)
    Vue
  • 原文地址:https://www.cnblogs.com/qxeric/p/2641896.html
Copyright © 2011-2022 走看看