MP3编码中huffman table选取完全注解

/**

 * Choose the Huffman table that will encode ix[begin..end] with            

 * the fewest bits.                                                         

 * Note: This code contains knowledge about the sizes and characteristics   

 * of the Huffman tables as defined in the IS (Table B.7), and will not work

 * with any arbitrary tables.

 *

 * 选取合适的 huffman table.

 *

 * ix[samp_per_frame2]   量化后的信号

 * begin             address_begin

 * end               address_end

 */

int new_choose_table( int                 ix[samp_per_frame2],

                    unsigned int           begin,

                    unsigned int           end )

{

    int i, max;   //

    int choice[2]; //

    int sum[2];    /*

                * sum[0] 记录table[index]ix[begin, end]编码所需要的位元数

                * sum[1] 记录table[index+1]ix[begin, end]编码所需要的位元数

                *

                * index是通过 "[0, 14]号表进行循环" 计算得来的.

                */

   

    /* region中查找出最大的值, 该值是用来和15做比较的, 之后选表的时候需要用到该值得 */

    max = ix_max( ix, begin, end );

    /* 如果查出最大的值是0, 那么这个区段估计就是zero区段, 而不是big_value或者count1 */

    if( !max ) return 0;

   

    /*

     *

     */

    choice[0] = 0;

    choice[1] = 0;

   

    /*

     * linbits are used when values larger than 15 has to be encoded

     *

     * 由于标准中所提供的32个表中,并非所有的表都能用,而且有大量的码表只是linbits不同。

     * 因此如何存储这些码表,并能够很方便地进行查询、编码,是编码过程中很关键的问题之一。

     * 但提出的多级索引方法可以很好地的解决这一问题。过程如图2所示。对可能的表有不同的

     * 处理方式

     *

     * 正常表 如表15,即每一级索引都是对应于表15的各项信息。

    * 无效表 如表14,其最终的指向是码表零,即相当于无效表。

    * 雷同表 如表1617实际上只是在第II级索引的linbits不同,其最后的Huffman数据是相

     *        同的。通过这样的多级码表地址索引可以很好的解决程序的模块化实现。

     *

     * 参考 << MP3编码法之研究与实现 >> Page26

     *

     * huffman表共有34, 其中2个表给count1使用, 另外32个表给big_value使用. big_value区间

     * 分成3个子区间region0, region1, region2. 各个region拥有各自的huffmantable.

     * huffman0-14的最大值不超过15(也就是说只能针对最大值不超过15的子区间编码), 15-31的最

     * 小值皆为15, 如果要针对超过15的频线编码, 就需要使用linbits的方法.

     *

     * 何谓linbits方法?

     * ESCAPE = 量化后的值 - 15

     * 可编码之最大值 = 15 + pow(2, linbits);

     *

     * ----------------------------------------------------------------------

     * [0,  14]号表供max<15region使用

     * [15, 31]号表供max>=15region使用

     * [32, 33]号表供count1使用

     */

    if( max < 15 )

    {

    /* try tables with no linbits. 不使用linbits方法, 此时使用huffmantable 0-14

     * 如果max小于15, 则表在[0,14]范围上选表. 0-14号表是为这样的频谱设计的.

     * 这时候不需要使用 linbits 机制.

     */

        /*

         *

         */

        for ( i=14; i--; ) // [0, 14]号表进行循环

        {

        /* 为什么是 ht[i].xlen > max

         * 而不是 ht[i].ylen > max ?

         * 

         */

            if ( ht[i].xlen > max )

        {

              choice[ 0 ] = i;

                break;

        }

        }

       

        /* 计算ix[begin, end]编码所需要的位元数. */

       sum[ 0 ] = count_bit( ix, begin, end, choice[0] );

      

       /*

        * [0,14]号表并不是全使用的, 只有2,5,7,10,13号表可能被使用.

        * 其他表有什么作用还不清楚.

        *

        * 这个观点是错误的, 起初我认为只有2,5,7,10,13号表是可被使用的, 现在发现

        * 不是这样的, 似乎是所有的表都是可用的. 而一些论文上也确实是说 2,5,7,10,13号表

        * 被使用, 有一部分不被使用。

        * shine的代码实现上来看似乎所有表都可使用. 这里需要深究.

        */

       switch ( choice[0] )

       {

           /*

            * 注意这里的逻辑, 觉得好奇怪.

            * 之前是有通过 "[0, 14]号表进行循环" 来查找到合适的huffman table

            * 但是这里会根据查找到的table[index]而来再用table[index+1]计算

            * table[index+1]ix[begin, end]编码所需要的位元数. 而且对于不同的

            * table[index], 其逻辑是不一样的, 不知道规范是如何对此定义的.

            * 日后定要回来温习这里的疑惑!

            *

            * ????????????????????????

            *

            * 看它的逻辑, 好象是table[index] table[index+1] 都可以用来对ix[begin, end]

            * 进行编码的, 但是要找更合适的, 那就是看在使用哪个table的时候所需要的位元数更小.

            *

            */

            case 2:

               // table[2], table[3]是同一个阶层的.

               // 所谓同一个阶层的意思就是, 一个给定的ix[begin, end]如果可以使用

               // table[2]编码的话, 那使用table[3]也是可以的, 至于是选table[2]

               // 还是选table[3], 那就要看二者哪个所需要的位元数更低了.

               //

               // 往下看的话会发现table[5]table[6]是一个阶层的

               // table[7], table[8]table[9]是一个阶层的

               // table[10], table[11]table[12]是一个阶层的

               // table[13]table[15]是一个阶层的

            sum[ 1 ] = count_bit( ix, begin, end, 3 );

            if ( sum[1] <= sum[0] )

                choice[ 0 ] = 3;

            break;

            case 5:

            sum[ 1 ] = count_bit( ix, begin, end, 6 );

            if ( sum[1] <= sum[0] )

                choice[ 0 ] = 6;

            break;

            case 7:

               /* 对比采用table[7], table[8], table[9]哪个码表才能占用位元数更小 */

            sum[ 1 ] = count_bit( ix, begin, end, 8 );

            if ( sum[1] <= sum[0] )

            {

                  choice[ 0 ] = 8;

                  sum[ 0 ] = sum[ 1 ];

            }

            sum[ 1 ] = count_bit( ix, begin, end, 9 );

            if ( sum[1] <= sum[0] )

                choice[ 0 ] = 9;

            break;

            case 10:

            sum[ 1 ] = count_bit( ix, begin, end, 11 );

            if ( sum[1] <= sum[0] )

            {

                  choice[ 0 ] = 11;

                  sum[ 0 ] = sum[ 1 ];

            }

            sum[ 1 ] = count_bit( ix, begin, end, 12 );

            if ( sum[1] <= sum[0] )

                choice[ 0 ] = 12;

            break;

            case 13:

            sum[ 1 ] = count_bit( ix, begin, end, 15 );

            if ( sum[1] <= sum[0] )

                choice[ 0 ] = 15;

            break;

       }

    }

    else

    {

    /* try tables with linbits

     * max>=15就需要从[15,31]号表范围内选了, [32, 33]是提供为count1使用的.

     * 这时候就需要使用 linbits 机制了.

     *

     * 何谓linbits方法?

     * ESCAPE = 量化后的值 - 15

     * 可编码之最大值 = 15 + pow(2, linbits);

     */

       max -= 15;

      

    /* [15,31]号表又可分为[15, 23], [24, 31]两个部分

     *

     * 先从[15,23]号表中选出合适的table[index_1]

     * 再从[24,31]号表中选出合适的table[index_2]

     *

     * 然后比较采用table[index_1]压缩ix[begin, end]还是

     * 采用table[index_2]压缩ix[begin, end]能使用更少的位元数.

     */

       for( i=15; i<24; i++ )

       {

        if( ht[i].linmax >= max )

        {

              choice[ 0 ] = i;

              break;

        }

       }

       for(i=24; i<32; i++)

       {

        if( ht[i].linmax >= max )

        {

              choice[ 1 ] = i;

              break;

        }

       }

      

       sum[0] = count_bit( ix, begin, end, choice[0] );

       sum[1] = count_bit( ix, begin, end, choice[1] );

      

       if ( sum[1] < sum[0] )   choice[0] = choice[1];

    }

   

    return choice[0];

}

 

其中

1.

sum[ 0 ] = count_bit( ix, begin, end, choice[0] );

这个函数是计算使用choice[0]这个表的时候, 压缩ix[begin,---end]所需要的位元数, 暂不考虑其实现

 

2

.huffmantable需要要规范中去查找到。

 

3.

 

/*

注意观察就知道了,哈哈!!!!

 

查看 标准<< 11172_3_ANNEXAB >> Table 3-B.7. Huffman codes for Layer III

 

*table

static HUFFBITS     t1HB[]    = {1, 1,  1,  0};

                            {1, 001,01, 000}

*********************************************

*hlen

static unsigned char t1l[]   = {1, 3, 2, 3};

 

*********************************************

Huffman code table 1

 x  y hlen hcod

 0  0  1   1

 0  1  3   001

 1  0  2   01

 1  1  3   000

 

 

 

*/

 

 

 

 

 

// -----------------------------------------------------------------------------------

#define NOREF -1

struct huffcodetab ht[HTN] =

{

/* xlen   ylen linbits  linmax   *table  *hlen  */

   

    // ------------ [0, 14]使用 ------------

    {0, 0,     0,      0,     NULL,  NULL},

    {2, 2,     0,      0,     t1HB, t1l},

    {3, 3,     0,      0,     t2HB, t2l},

    {3, 3,     0,      0,     t3HB, t3l},

    {0, 0,     0,      0,     NULL,  NULL},// Apparently not used

    {4, 4,     0,      0,     t5HB, t5l},

    {4, 4,     0,      0,     t6HB, t6l},

    {6, 6,     0,      0,     t7HB, t7l},

    {6, 6,     0,      0,     t8HB, t8l},

    {6, 6,     0,      0,     t9HB, t9l},

    {8, 8,     0,      0,     t10HB, t10l},

    {8, 8,     0,      0,     t11HB, t11l},

    {8, 8,     0,      0,     t12HB, t12l},

    {16,    16,    0,      0,     t13HB, t13l},

    {0, 0,     0,      0,     NULL,  NULL},// Apparently not used

   

    // ------------ [15, 31]使用 ------------

    {16,    16,    0,      0,     t15HB, t15l},

    {16,    16,    1,      1,     t16HB, t16l},

    {16,    16,    2,      3,     t16HB, t16l},

    {16,    16,    3,      7,     t16HB, t16l},

    {16,    16,    4,      15,    t16HB, t16l},

    {16,    16,    6,      63,    t16HB, t16l},

    {16,    16,    8,     255,   t16HB, t16l},

    {16,    16,    10,    1023,  t16HB, t16l},

    {16,    16,    13,    8191,  t16HB, t16l},

    {16,    16,    4,      15,    t24HB, t24l},

    {16,    16,    5,      31,    t24HB, t24l},

    {16,    16,    6,      63,    t24HB, t24l},

    {16,    16,    7,     127,   t24HB, t24l},

    {16,    16,    8,     255,   t24HB, t24l},

    {16,    16,    9,     511,   t24HB, t24l},

    {16,    16,    11,    2047,  t24HB, t24l},

    {16,    16,    13,    8191,  t24HB, t24l},

   

    // ------------ [32, 33]count1使用 ------------

    {1,     16,    0,      0,     t32HB, t32l},

    {1,     16,    0,      0,     t33HB, t33l},

};

 

 

请注意查看shine的实现

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值