CELT和SILK以及Opus的位分配方法
三者的位分配编码都主要是使用Range Coding(Opus是CELT和SILK拼出来的)。
那么有如下问题:
1.有什么区别。还是一样?
2.把AAC的Huffman Coding换成Range Coding怎么样
首先分析,SILK,
SILK里面的Range Coding比较简单,SILK里面有2个全部
1. SILK 全部参数使用RC。
2. SILK 全部参数都有自己的积累概率函数CDF。
SILK 里面 RC统一调用SKP_Silk_range_encoder进行编码,3个参数,第一个是数据结构指针,第二个CDF,第三个是CDF的定点长度。
SILK能全部使用RC编码的原因是,SILK是语音编码,参数的动态幅值比较固定且小,统计CDF时容易收敛。
然后分析,CELT,
相比SILK, CELT的熵编码比较复杂。
CELT的不仅仅是用了RC编码也使用了动态位编码。
并且CELT的RC和为了进行RC的算法设计比较灵活,比如RC编码uint数据。
特点如下
1.CELT使用了动态位编码是因为,在编码fine quant 参数时,这个参数的位分配和动态幅值比较大,统计CDF比较困难,所以是用了编码和解码同时计算位分配参数,根据位分配参数编码和提取fine quant 参数。
在这点上,CELT对fine quant的编码方式有点类似AC3对mantissa的编码方式,但是AC3的 mantissa编码是用掩蔽参数计算出来的,这点又不同。另外AC3的mantissa是类似量化残差的参数。而fine quant是类似ac3中exp参数或是aac的scalefactor参数。
2.CELT的RC对UINT数据进行了灵活的编码方法,比如在编码pitch的gain 的octave参数时,编码pulse参数,编码立体声角度的时候。都是用了ec_enc_uint函数编码
该函数一方面使用传统的RC处理一方面调用ec_enc_bits对固定位或指定位长数据进行编码。
3.CELT对RC进行了分类,分别实现ec_encode_bin(传统的RC),ec_enc_bit_prob(指对一个位进行编码)。ec_encode(传统的RC)。
ec_encode和ec_encode_bin的区别是
ec_encode_bin要指对CDF的定点长度。ec_encode不需要。
而ec_enc_bit_prob和ec_encode_bin/ec_encode的区别是
ec_enc_bit_prob只编码一个位用一个_prob就可以表示,不比向传统RC一样传递2个CDF参数(前一个CDF和当前的CDF参数)。
在Opus中,SILK的SKP_Silk_range_encoder函数变为了ec_enc_icdf函数。并把CELT的RC函数加入Opus里面,仅此而已。
2. 对AAC和MP3的参数编码方式进行改造是可行的。
但是有2点要注意,
1.由于可能存在的参数动态幅值不确定(如量化残差,最大8192级)不容易收敛,CDF的统计比较复杂要如何处理。判断哪些参数做RC.如何合理使用RC。
2.CDF的统计可能需要大量样本参与。