一.实验原理
1.多项滤波器组
用来分割子带,将PCM样本变换到32个子带的频域信号
2.量化编码
(1)比例因子的选取及编码
对各个子带每12个样点进行一次比例因子计算。先定出12个样点中绝对值的最大值。查比例因子表中比这个最大值大的最小值作为比例因子。用6比特表示。第2层的一帧对应36个子带样值,是第1层的三倍,原则上要传三个比例因子。为了降低比例因子的传输码率,采用了利用人耳时域掩蔽特性的编码策略。每帧中每个子带的三个比例因子被一起考虑,划分成特定的几种模式。根据这些模式,1个、2个或3个比例因子和比例因子选择信息(每子带2比特)一起被传送。如果一个比例因子和下一个只有很小的差别,就只传送大的一个,这种情况对于稳态信号经常出现。使用这一算法后,和第1层相比,第2层传输的比例因子平均减少了2个,即传输码率由22.5Kb/s降低到了7.5Kb/s。
(2)比特分配
对每个子带计算掩蔽–噪声比MNR,是信噪比SNR–信掩比SMR,即:MNR=SNR-SMR。使整个一帧和每个子带的总噪声-掩蔽比最小。这是一个循环过程,每一次循环使获益最大的子带的量化级别增加一级,当然所用比特数不能超过一帧所能提供的最大数目。第1层一帧用4比特给每个子带的比特分配信息编码;而第2层只在低频段用4比特,高频段则用2比特。
(3)子带样值的量化及编码
输入以12个样本为一组,每组样本经过时间一频率变换之后进行一次比特分配并记录一个比例因子(scale factor)。比特分配信息告诉解码器每个样本由几位表示,比例因子用6比特表示,解码器使用这个6比特的比例因子乘逆量化器的每个输出样本值,以恢复被量化的子带值。比例因子的作用是充分利用量化器的量化范围,通过比特分配和比例因子相配合,可以表示动态范围超过120dB的样本。第2层中,量化级别的数目随子带的不同而不同,但量化等级仍然覆盖了365535的范围,同时子带不被分配给比特的概率增加了,没有分配给比特的子带就不被量化。低频段的量化等级有15级,中频段7级,高频段只有3级
二.实验流程
理解过程
- 理解程序设计的整体框架
- 理解感知音频编码的设计思想
- 理解心理声学模型的实现过程
临界频带的概念
掩蔽值计算的思路
理解码率分配的实现思路
输出要求
- 输出音频的采样率和目标码率
- 选择某个数据帧,输出
该帧所分配的比特数
该帧的比例因子
该帧的比特分配结果
三.关键代码
m2aenc.c
FILE *output_txt;
char temp[100] = "info.txt";
int main (int argc, char **argv)
{
...
output_txt = fopen(temp, "w");
if (output_txt == NULL)
printf("Creating output txt file failed.\n");
...
}
int sb, gr, ch;
if (frameNum == 66)
{
fprintf(output_txt, "采样频率为 %d kHz. \n 目标码率为 %d kbps.\n",
header.sampling_frequency, bitrate[header.version][header.bitrate_index]);
fprintf(output_txt, "输出的为第 %d 帧\n", frameNum);
fprintf(output_txt, "分配的比特数为 %d\n", adb);
fprintf(output_txt, "比例因子为:\n");
for (ch = 0; ch < nch; ch++)
{
fprintf(output_txt, "channel[%2d] \n", ch + 1);
for (sb = 0; sb < frame.sblimit; sb++)
{
fprintf(output_txt, "subband[%2d]: ", sb + 1);
for (gr = 0; gr < 3; gr++)
{
fprintf(output_txt, "%2d\t", scalar[ch][gr][sb]);
}
fprintf(output_txt, "\n");
}
}
}
四.实验结果