[原创]桓泽学音频编解码(1):MPEG1 MP3 系统算法分析
[原创]桓泽学音频编解码(2):AC3/Dolby Digital 系统算法分析
[原创]桓泽学音频编解码(4):MP3 和 AAC 中反量化原理,优化设计与参考代码中实现
[原创]桓泽学音频编解码(5):MP3 和 AAC 中IMDCT算法的原理,优化设计与参考代码中实现
[原创]桓泽学音频编解码(6):MP3 无损解码模块算法分析
[原创]桓泽学音频编解码(7):MP3 和 AAC 中huffman解码原理,优化设计与参考代码中实现
[原创]桓泽学音频编解码(8):关于MP3和AAC量化器设计的研究
[原创]桓泽学音频编解码(9):MP3 多相滤波器组算法分析
[原创]桓泽学音频编解码(10):AAC 无损解码模块算法分析
[原创]桓泽学音频编解码(11):AC3 exponent(指数部分)模块解码算法分析
1 编码概述
如以前的blog所述,编码时将所有的频率谱线分成exponent和mantissa两个部分。编码器将所有mantissa量化到固定等级的精度。尾数量化到15级或少于15级时,用均匀量化。大于15级用非均匀量化,通常用2的补码表示。几个量化的尾数值组合在一起被编码成一个公共的码字。如对于3级量化器,3个量化值组合后用5bit码字表示.
2 解码过程
解码过程中码流中的尾数数据流部分被分解成长度不等的单个尾数或尾数组。在码流中,各个指数集合中的尾数以频率递增的顺序排列。不过,有些组出现与包含在组内的第一个尾数的位置上。组内后续的尾数没有来自数码流的信息。故不需要解包。
① 当比特分配指针值bap的范围是【6,15】时。使用非对称分数2的补码量化。各个尾数与其指数一起位变换系数的浮点表示。小数点在MSB的左边。故尾数字表达的范围是。
(1.0-2^(qntztab[bap]-1))to -1.0
非对称量化的尾数不进行组合。
② 当比特分配指针值bap的范围是【1,5】时,尾数用编码值表示,通过查表把编码值变换到标准的2的补码分数二进制字。自码流中取出bap指出的比特数并确认无误。这个编码值作为查表的索引查找尾数值。将得出尾数安相应的指数右移以产生变换系数值。
Transform_coefficent[k]=mantissa[k]>>exponent[k];
③ 当比特分配指针值bap是0时。AC3解码器在标准中提供的是用随即噪声抖动代替量化值。Dithflag为0时使用真的0值。用于各声道的dithflag时变化的。
④ 当比特分配指针值bap是1,2,4的情况下。进一步压缩编码尾数值。包3级字和5级字组合成一些分开的代表3各尾数的组。11级字组合成对尾数的组。安尾数处理的次序把组填满。假设在一个指数集合中尾数的数目不能填满整数各组,将在指数集之间分担这些组。块中下一个指数集集训填入未填满的那些组。假设3级或5级量化的变换系数导出的字,器总数不能被3除尽,或假设11级字不能被2除尽,对一块的最后这些组添以虚设的尾数来组成混合组。有解码器舍弃这些虚设的尾数。用bap得出的长度从码流中取出各个组。3级量化尾数(bap=1)分成3各组各5bit。5级量化尾数(bap=2)分成三个一组各7bit。11级量化尾数(bap=4)分成一对一对各7bit。
解码公式为
bap = 1:
mantissa_code[a] = truncate (group_code / 9) ;
mantissa_code[b] = truncate ((group_code % 9) / 3 ) ;
mantissa_code[c] = (group_code % 9) % 3 ;
bap = 2:
mantissa_code[a] = truncate (group_code / 25) ;
mantissa_code[b] = truncate ((group_code % 25) / 5 ) ;
mantissa_code[c] = (group_code % 25) % 5 ;
bap = 4:
mantissa_code[a] = truncate (group_code / 11) ;
mantissa_code[b] = group_code % 11 ;
where mantissa a comes before mantissa b, which comes before mantissa c
Bap |
N |
Bap |
N |
Bap |
N |
Bap |
N |
0 |
0 |
4 |
7 |
8 |
7 |
12 |
11 |
1 |
5 |
5 |
4 |
9 |
8 |
13 |
12 |
2 |
7 |
6 |
5 |
10 |
9 |
14 |
14 |
3 |
3 |
7 |
6 |
11 |
10 |
15 |
16 |
3 C参考代码
重建频率谱线数据的过程要经过2个步骤。首先是计算反量化的mantissa值,其次是用mantissa和exponent一起重建频率谱线数据。如下图
在函数static sint_16 coeff_get_mantissa(uint_16 bap, uint_16 dithflag)内实现mantissa的解码。在函数convert_to_float(uint_16 exp, sint_16 mantissa)计算完成重建谱线数据。
函数coeff_get_mantissa的流程图如下。反量化步骤采取查表方式实现。
函数convert_to_float代码如下
static inline float convert_to_float(uint_16 exp, sint_16 mantissa)
{
float x;
//the scale by 2^-15 is built into the scale factor table
x = mantissa * scale_factor[exp];
//注意15是浮点变整点标志。
return x;
}