Audio Codec : MPEG2 AAC -- 反量化模块
1 MPEG2 AAC 反量化概述
AAC 中使用的量化器是非均匀量化器,非线性量化的主要优点是内置有一个取决于系数幅度的噪声整形。对于给定的频谱样值,在一定的范围内增加scalefactor或减小全局缩放因子嘟可以放大量化器输出值的幅度,同时迅速降低量化失真的程度。
公式如下:
反量化公式
2 MPEG2 AAC反量化算法原理
输入: x_quant[g][win][sfb][bin] : 量化谱线
输出: x_invquant[g][win][sfb][bin] : 逆量化谱线
临时控制变量:
g:窗组坐标
win:窗坐标
sfb:scale factor band 坐标
bin:谱线坐标.
伪代码
for (g = 0; g < num_window_groups; g++) {
for (sfb = 0; sfb < max_sfb; sfb++) {
width = (swb_offset [sfb+1] - swb_offset [sfb]);
for (win = 0; win < window_group_len[g]; win++) {;
for (bin = 0; bin < width; bin++) {
x_invquant[g][win][sfb][bin] = sign(x_quant[g][win][sfb][bin]) *
abs(x_quant[g][win][sfb][bin]) ^(4/3);
}
}
}
}
3 优化算法
对与反量化模块的实现有以下几种方式
1. 直接计算法
2. 查表法
3. 泰勒展开式法
4. 线性差值法
5. 综合法
直接计算的话使用的是超越函数计算,运算量很大,不适合应用。查表法是算法最简单,计算量最小,但它属于一种用空间换时间的方法,即制作一张对于所有范围的输入数据,都能直接得到输出结果的表。但是若输入数据的范围为较大,如果全部制成表格,则需存储表格的空间也很大,浪费空间。泰勒展开式法是一种用普通计算代替超越函数计算的方法,但随着精度的提高泰勒展开的级数也增加较大。运算量也是相当的大。不适合实现。所以一般都用线性差值加查表法的综合结构实现反量化解码。
在11172-3和13818-7中,反量化的主要部分是
计算xiquant的值是反量化的主要工作,常规的方法是采用查表法,即制作一张对于所有范围的输入数据,都能直接得到输出结果的表。但是由于x的范围为08191,如果全部制成表格,则需8192字存储空间,在存储空间紧张的系统中这样做非常不经济。因此,为了降低存储空间,同时也保证运算的正确性。制作长度为256的查找表,每项以4字节表示,其它数值可以通过线性插值运算得到:
1)对于x= 1--256之间的值,可以直接查表得到。
2)对于x在257-2048之间的值,使用公式:
3)对于x在2049-8192之间的值,使用公式:
式中int()表示取整,rem()表示取余,f()对系数表进行查找操作。使用这种方法在节省了存储空间的同时,计算也只是简单的乘加运算。在定点处理器中式3-6或式3-7的运算只要一次乘法,3次加法和3次移位操作。虽然这种简化运算与实际值有误差,但是在实际解码时量化后的频谱系数超过256的往往所占比例并不是很大。经过统计发现, x的取值小于256的占了99%,这说明使用这种插值和查找表方法是能够得到满意的解码音质。
4 参考代码
4.1 13818-7 参考代码上的iquant实现
13818-7 ISO参考代码中的iquant的实现是集成在函数huffspec内的。
流程图如下
MAX_IQ_TBL = 128
在128以下的值用查表法
在128以上的值用直接计算法
以下来自esc_iquant函数
if (q < MAX_IQ_TBL) {
return((Float)iq_exp_tbl[q]);
}
else {
return(pow(q, 4./3.));
}
4.2 Faad参考代码上iquant实现
以下iquant不含负数变正书处理
#ifdef FIXED_POINT
/* For FIXED_POINT the iq_table is prescaled by 3 bits (iq_table[]/8) */
#ifndef BIG_IQ_TABLE
Faad的处理提供两种方法,使用宏定义区别开来
方法1
全部查表法,
// IQ_TABLE_SIZE = 8192
if (q < IQ_TABLE_SIZE)
{
return sgn * tab[q];
}
注faad的表是静态表,在全局数据段中
方法2
部分查表加线性差值法
#define COEF_BITS 28
#define COEF_PRECISION (1 << COEF_BITS)
#define REAL_BITS 14 // MAXIMUM OF 14 FOR FIXED POINT SBR
#define REAL_PRECISION (1 << REAL_BITS)
#define REAL_CONST(A) \
(((A) >= 0) ? ((real_t)((A)*(REAL_PRECISION)+0.5)) : ((real_t)((A)*(REAL_PRECISION)-0.5)))
static const real_t errcorr[] =
{
REAL_CONST(0) , REAL_CONST(1.0/8.0),
REAL_CONST(2.0/8.0) , REAL_CONST(3.0/8.0),
REAL_CONST(4.0/8.0) , REAL_CONST(5.0/8.0),
REAL_CONST(6.0/8.0) , REAL_CONST(7.0/8.0),
REAL_CONST(0)
};
real_t x1, x2;
// IQ_TABLE_SIZE = 1026
if (q < IQ_TABLE_SIZE)
{
return sgn * tab[q];
}
if (q >= 8192)
{
*error = 17;
return 0;
}
/* 线性差值部分 */
x1 = tab[q>>3];
x2 = tab[(q>>3) + 1];
return sgn * 16 * (MUL_R(errcorr[q&7],(x2-x1)) + x1);
faad使用的公式和前面提出的不大一样
只要q>1026就用公式
Float esc_iquant(int q)
{
if (q > 0) {
if (q < MAX_IQ_TBL) {
//反量化表的最大值,小于MAX_IQ_TBL的谱线的逆量化用查表法
return((Float)iq_exp_tbl[q]);
}
else {
return(pow(q, 4./3.));
}
}
else {
q = -q;
if (q < MAX_IQ_TBL) {
return((Float)(-iq_exp_tbl[q]));
}
else {
return(-pow(q, 4./3.));
}
}
}