Audio Codec : MPEG2 AAC -- TNS
1 Temporal Noise Shaping (TNS)原理
TNS是在1996年提出的一种能够自适应于输入信号特性来降低前回声效应的新技术。它利用应用于信号频谱的处理来实现时域噪声形状的控制,能够对量化噪声的细微时域结构(甚至在一个滤波器组窗口内)进行控制。它的提出基于如下的考虑:
时域一频域对偶性的考虑:TNS技术利用时域和频域之间的对偶性,以一种新的形式发展了己有的预测编码技术。众所周知,对于具有“非平坦(non-flatness)',频谱的信号既可以直接对频谱值进行编码(变换编码),也可以对时域信号进行预测编码。对于具有“非平坦”时域结构的信号(即瞬态信号)自然也就有两种对应的方法。对于瞬态信号可以直接对时域值进行编码,也可以对频谱系数进行预测编码。总而言之,在时域上的预测提高了编码器的频域分辨率,而在频域上的预测提高了编码器的时域分辨率。
使用预测编码进行噪声整形:如果对时域信号进行前向预测编码,则可以调节解码器最终的量化误差的功率谱密度(PSD)以适应输入信号的功率谱。与此相对应,在频域上对频谱数据进行预测编码,则在解码器输出端可以调节量化误差的时域形状以适应输入信号的时域形状。这样,可以有效地把量化误差置于实际信号之下,并且可以由此避免瞬态信号或冲击信号的掩蔽效应问题。因此,这种对频谱数据的预测方法也被称为TNS方法。
由于TNS处理既可以用于整个频谱也可以用于部分频谱,所以可在任何与频率有关的地
方使用时域噪声控制,它也可以用几个预测滤波器作用在不同的频率(系数)范围。
TNS的解码过程如下:首先经过查表得到相应的反射系数。然后把这些反射系数转换成线性预测编码(LPC)系数a[] o最后就是对相应的频带进行全极点有限冲击响应滤波.
公式
y[n]=x[n]-a[1]*y[n一1]-…-a[order]*y[n-order]
其中x[n]为频谱上的当前值,Y回为滤波后值,而Y[n-1]是前一滤波后值,依次类推。如图1所示为此滤波器的框图,其中Z为延时器,控制器根据阶数(order)的大小控制其中延时器的输出是否为零的个数。
图1 TNS滤波器框图
TNS解码的运算量计算方法为:order*L次实数乘法,order*L次加(减)法,其中L是应用INS滤波的频率系数的长度,一般为640:使用乘加指令能够得到最大的解码速度。AAC LC框架的TNS阶数受限(Order最大为12),与主框架(Order最大20)相比,计算量明显下降,这便于LC框架在系统资源受限的系统中的应用。
2 MPEG2 AAC TNS算法应用
2.1 码流格式
当individual_channel_stream码流中的tns_data_present等于1时表示编码器使用了TNS处理,码流中存在tns_data码流。
TNS码流格式如下
tns_data() |
|
{ |
|
for (w = 0; w < num_windows; w++) { |
|
n_filt[w]; |
1..2 |
if (n_filt[w]) |
|
coef_res[w]; |
1 |
for (filt = 0; filt < n_filt[w]; filt++) { |
|
length[w][filt]; |
{4;6} |
order[w][filt]; |
{3;5} |
if (order[w][filt]) { |
|
direction[w][filt]; |
1 |
coef_compress[w][filt]; |
1 |
for (i = 0; i < order[w][filt]; i++) |
|
coef[w][filt][i]; |
2..4 |
} |
|
} |
|
} |
|
} |
|
语意是
n_filt[w] |
每个窗中使用的filter的个数 |
coef_res[w] |
0:传输的滤波器系数是3bit 1:传输的滤波器系数是4bit |
length[w][filt] |
一个filter使用的region的长度 |
order[w][filt] |
一个filter的阶数 |
direction[w][filt] |
0:filter的方向是向上的 1:filter的方向是向下的 |
coef_compress[w][filt] |
0:Filter系数的最高位忽略 1:Filter系数的最高位不忽略 |
coef[w][filt][i] |
Filter系数 |
注意:每个码流标志的有效位数是根据窗形确定的。
|
短窗 |
长窗,开始窗,结束窗 |
n_filt[w] |
1位 |
2位 |
length[w][filt] |
4位 |
6位 |
order[w][filt] |
3位 |
5位 |
2.2 解码过程
Step1:解码滤波器传输系数,包括化为有符号数和反量化。
Step2:全极点滤波器应用到目标频率上。
Direction用于决定滤波器的方向,‘1’表示向下,‘0’表示向上。
TNS_MAX_ORDER:定义最大的可能的滤波器阶数。
TNS_MAX_BAND:定义用于TNS的scalefactor band的最大个数。
伪码
/* TNS decoding for one channel and frame */
tns_decode_frame()
{
for (w = 0; w < num_windows; w++) {
bottom = num_swb;
for (f = 0; f < n_filt[w]; f++) {
top = bottom;
bottom = max(top - length[w][f], 0);
tns_order = min(order[w][f], TNS_MAX_ORDER);
if (!tns_order) continue;
tns_decode_coef(tns_order, coef_res[w]+3, coef_compress[w][f],
coef[w][f], lpc[]);
start = swb_offset[min(bottom,TNS_MAX_BANDS,max_sfb)];
end = swb_offset[min(top,TNS_MAX_BANDS,max_sfb)];
if ((size = end - start) <= 0) continue;
if (direction[w][f]) {
inc = -1; start = end - 1;
} else {
inc = 1;
}
tns_ar_filter(&spec[w][start], size, inc, lpc[], tns_order);
}
}
}
tns_decode_coef(order, coef_res_bits, coef_compress, coef[], a[])
{
/* 初始化内部表格 */
sgn_mask[] = { 0x2, 0x4, 0x8 };
neg_mask[] = { ~0x3, ~0x7, ~0xf };
/* size used for transmission */
coef_res2 = coef_res_bits - coef_compress;
s_mask = sgn_mask[coef_res2 - 2]; /* mask for sign bit */
n_mask = neg_mask[coef_res2 - 2]; /* mask for padding neg. values */
/* 转换为有符号整数 */
for (i = 0; i < order; i++)
tmp[i] = (coef[i] & s_mask) ? (coef[i] | n_mask) : coef[i];
/* 反量化 */
iqfac = ((1 << (coef_res_bits-1)) - 0.5) / (p/2.0);
iqfac_m = ((1 << (coef_res_bits-1)) + 0.5) / (p/2.0);
for (i = 0; i < order; i++) {
tmp2[i] = sin(tmp[i] / ((tmp[i] >= 0) ? iqfac : iqfac_m));
}
/* 转化到LPC系数 */
a[0] = 1;
for (m = 1; m <= order; m++) {
for (i = 1; i < m; i++) { /* loop only while i<m */
b[i] = a[i] + tmp2[m-1] * a[m-i];
}
for (i = 1; i < m; i++) { /* loop only while i<m */
a[i] = b[i];
}
a[m] = tmp2[m-1]; /* changed */
}
}
tns_ar_filter(spectrum[], size, inc, lpc[], order)
{
y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order)
-每次要初始化滤波器状态信息为0
-输出数据覆盖输入数据
- An input vector of "size" samples is processed and the index increment
to the next data sample is given by "inc"
}
3 参考代码
ISO参考代码中,用void tns_decode_subblock(Float *spec, int nbands, short *sfb_top, int islong,TNSinfo *tns_info)函数实现TNS操作。并定义数据结构如下
TNS 算法数据结构
typedef struct
{
int n_filt; |
tns滤波器个数 |
int coef_res; |
滤波器系数 |
TNSfilt filt[TNS_MAX_FILT]; |
|
} TNSinfo;
tns_decode_subblock流程图如下