[原创]桓泽学音频编解码(11):AC3 exponent(指数部分)模块解码算法分析
前面的博客索引
[原创]桓泽学音频编解码(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 无损解码模块算法分析
1 编码概述
在AC-3标准中,每个频率系数由浮点数表示,并将它归一化为0到1之间的小数,然后分解为指数和尾数两部分.设频率系数为a, 0<a<1,则可使a=m*2^(-exp), 其中m为尾数,0<m<1, exp为指数(注意不是-exp)。可以理解为将a用二进制小数表示,小数点与小数点后第一个1之间的0的个数便为指数指数被限制在0与24之间,即0≤exp≤24。若exp>24,则尾数m可以小于0.5,exp仍然限制为24. exp需要5bit来表示他的值。AC3标准规定了exponent在码流中的传送方法和exponent的表示方法。
在所有独立声道、所有被耦合声道、所有耦合声道以及低频效果声道都存在编码指数exponent。所以以上所用声道的exponent都会出现在码流中。
1.1 Exponent的表示方法:
首先为了进一步压缩exponent,对于每个频率指数的传输使用差分编码进一步压缩。一个全频带或一个低频效果通道的一个指数(注意没有耦合声道),总是发送一个4比特的绝对值,其范围为0~15。该值之处的第一个变换系数的前导零的个数。相继频率逐次增高的指数使用差分值传送。他们加到以前的指数之上形成下一个绝对值。差分exponent值限定在
2,1,0,-1,-2这五个值内。而每个通道起始的exponent的编码方法是,独立声道和低音效果声道的第一个exponent用4位表示其值,而不是exponent幅值的5位。即其表示范围从0~24降为0~15。耦合声道的起始指数cplabsexp只是一个起始计算值并不表示第一个耦合通道数据值,而对他的编码是其表示0~24的偶数值,即被耦合通道起始数据最低位(LSB)一定为0。因而解码器必须将4bit值取出把它左移1位计算。
其次为了把差分exponent变为无符号数。对每个差分exponent值加2。转换exponent的有效范围在4,3,2,1,0。用3位表示。
1.2 Exponent的传送方法:
首先为了进一步压缩指数信息。音频块对频率指数进行分组,同一个组内的指数相同。即组内的exponent按照一个差分值传送,用3位表示。分组策略有3种(D15,D25,D45)。(注:低音效果声道只能使用D15策略)D15是每个exponent分成一个组。D25是2个exponent分成一个组。D45是4个exponent分成一个组。
第二,在实际传送分组的exponent数据时。标准规定3个组一起传送。用7位表示。编码方式是
7bit数据=(25 * 第一组3位) + (5 *第二组3位) +第三组3位。
因为每组3位的最大值为4。所以7bit数据的范围是0~124。
一个特定的声道凡在音频块种划分成数据组的差分指数的数目,取决于指数策略及该声道频率带宽的信息。在各数据组种只输送的个数取决于指数策略。
第三,音频块1到音频块5可以重复使用在同一个frame内前一个音频块的exponent。
(ac3的frame数据是512×6(block数)×总通道数)
2 解码算法过程
在解码过程中,首先要根据指数策略将编码指数包分解为实际的指数值。因为这些指数值实际上体现了音频样本的频谱包络。一方面当然要以此恢复编码样本的的实际频率值,另一方面也要利用这些编码后的样本包络值加上比特分配信息以计算出比特分配指针,从而恢复出实际的尾数。
使用到的码流信息
/* 第一部分: exponent 方案信息 */ |
|
意义 |
cplexpstr |
2 |
耦合通道exponent分组策略 |
chexpstr[ch] |
2 |
独立通道exponent分组策略 |
lfeexpstr |
1 |
低音增强通道exponent分组策略 |
chbwcod[ch] |
6 |
|
/* 第二部分: exponent 码流值 */ |
|
|
cplabsexp |
4 |
耦合通道起始exponent绝对值 |
cplexps[grp] |
7 |
耦合通道差分exponent分组码流 |
exps[ch][0] |
4 |
独立通道起始exponent绝对值 |
exps[ch][grp] |
7 |
独立通道差分exponent分组码流 |
gainrng[ch] |
2 |
用于反变换算法 |
lfeexps[0] |
4 |
低音增强通道起始exponent绝对值 |
lfeexps[grp] |
7 |
低音增强通道差分exponent分组码流 |
输入:exponent 编码方案信息,exponent码流
输出:每个通道的频率谱线的exponent值
Exponent解码算法流程图
Step1:从码流中解析分组策略,解析每个通道起始exponent绝对值,解析差分exponent值
分组策略信息的表示方法是
Chexpstr[ch] cplexpstr |
Exponent 策略 |
‘00’ |
重用前一个块的exponent |
‘01’ |
D15 |
‘10’ |
D25 |
‘11’ |
D45 |
lfeexpstr |
Exponent 策略 |
‘0’ |
重用前一个块的exponent |
‘1’ |
D15 |
Step2:确定每个通道有频率指数的起始频率和截止频率,确定每个通道内有多少组7位的bit数据。
确定起始频率和截止频率的算法是
独立通道中
截至频率:endmant[ch] = ((chbwcod[ch] + 12) * 3) + 37; (未被耦合声道)
截至频率:cplstrtmant;(被耦合声道)
起始频率:strtmant[ch] = 0
低音效果通道
起始频率:lfestrtmant = 0
截至频率:lfeendmant = 7
耦合声道
起始频率:cplstrtmant = (cplbegf * 12) + 37
截至频率:cplendmant = ((cplendf + 3) * 12) + 37
其中cplbegf,cplendf,cplstrtmant见耦合码流。
计算每个通道内有多少组7位的bit数据的算法是
独立通道中和被耦合声道
nchgrps[ch] = truncate {(endmant[ch] – 1) / 3} ; /* for D15 mode */
= truncate {(endmant[ch] – 1 + 3) / 6} ; /* for D25 mode */
= truncate {(endmant[ch] - 1 + 9) / 12} ; /* for D45 mode */
低音效果通道
nlfegrps = 2
耦合声道
ncplgrps = (cplendmant – cplstrtmant) / 3 ; /* for D15 mode */
= (cplendmant – cplstrtmant) / 6 ; /* for D25 mode */
= (cplendmant – cplstrtmant) / 12 ; /* for D45 mode */
Step3:,进行差分解码
1.从每个7比特数据中解码3组数据,
组1内exp = truncate (gexp / 25)
组2内exp = truncate {(gexp % 25} / 5)
组3内exp = (gexp % 25) % 5
gexp 表示 lfeexps cplexps exps
2.差分exp=组内exp-2
3.exp[n]=exp[n-1]+差分exp[n];
4.
对于D15模式,直接输出exp[n]
对于D25模式,相邻的2个exp值相同,复制输出
对于D45模式,相邻的4个exp值相同,复制输出
对于耦合通道
Clpexp[n]+cplstrmant=exp[n].
3 C参考代码
3.1 获取exponent策略的流程图
3.2 计算截至频率和通道内exponent组个数的流程图
3.3 获取exponent数据的流程图