实验要求
理解程序设计的整体框架
理解感知音频编码的设计思想
■ 两条线
■ 时、频分析的矛盾!
理解心理声学模型的实现过程
■ 临界频带的概念
■ 掩蔽值计算的思路
理解码率分配的实现思路
输出音频的采样率和目标码率
选择三个不同特性的音频文件
■ 噪声(持续噪声、突发噪声)
■ 音乐
■ 混合
某个数据帧,输出
■ 该帧所分配的比特数
■ 该帧的比例因子
■ 该帧的比特分配结果
1、理解程序设计的整体框架
2、理解感知音频编码的设计思想

输入声音信号经过一个多相滤波器组,变换到多个子带。同时经过“心理声学模型”计算以频率为自变量的噪声掩蔽阈值。量化和编码部分用信掩比SMR决定分配给子带信号的量化位数,使量化噪声<掩蔽域值。最后通过数据帧包装将量化的子带样本和其它数据按照规定的帧格式组装成比特数据流。
(1)多相滤波器组,用来分割子带
划分子带的方法有两种:线性划分和非线性划分
➢ 线性划分可能一个子带覆盖好几个临界频带

(2)量化和编码
比例因子的取值和编码
对各个子带每12个样点进行一次比例因子计算。先定出12个样点中绝对值的最大值。查比例因子表中比这个最大值大的最小值作为比例因子。用6比特表示。
◆第2层的一帧对应36个子带样值,是第1层的三倍,原则上要传三个比例因子。为了降低比例因子的传输码率,采用
了利用人耳时域掩蔽特性的编码策略。
◆每帧中每个子带的三个比例因子被一起考虑,划分成特定的几种模式。根据这些模式,1个、2个或3个比例因子和比
例因子选择信息(每子带2比特)一起被传送。如果一个比例因子和下一个只有很小的差别,就只传送大的一个,这种
情况对于稳态信号经常出现。
◆使用这一算法后,和第1层相比,第2层传输的比例因子平均减少了2个,即传输码率由22.5Kb/s降低到了7.5Kb/s。
比特分配及编码
在调整到固定的码率之前
➢ 先确定可用于样值编码的有效比特数
➢ 这个数值取决于比例因子、比例因子选择信息、比特分配信息以及辅助数据所需比特数
比特分配的过程
➢ 对每个子带计算掩蔽-噪声比MNR,信噪比SNR–信掩比SMR, 即:MNR = SNR–SMR

比特分配的过程
➢ 使整个一帧和每个子带的总噪声-掩蔽比最小。这是一个循环过程,每一次循环使获益最大的子带的量化级别增加一级,当然所用比特数不能超过一帧所能提供的最大数目
➢ 第1层一帧用4比特给每个子带的比特分配信息编码;而第2层只在低频段用4比特,高频段则用2比特
子带样值的量化和编码
◼输入以12个样本为一组,每组样本经过时间-频率变换之后进行一次比特分配并记录一个比例因子(scale factor)
◼ 比特分配信息告诉解码器每个样本由几位表示,比例因子用6比特表示,解码器使用这个6比特的比例因子乘逆量化器的每个输出样本值,以恢复被量化的子带值。比例因子的作用是充分利用量化器的量化范围,通过比特分配和比例因子相配合,可以表示动态范围超过120dB的样本 。
◼ 第2层中,量化级别的数目随子带的不同而不同,但量化等级仍然覆盖了3~65535的范围,同时子带不被分配给比特的概率增加了,没有分配给比特的子带就不被量化。低频段的量化等级有15级,中频段7级,高频段只有3级
(3)数据帧包装
◼码流结构的设计
➢ 有利于使用低复杂性和少延时的解码器,编码后的声音信号包含多个短且恒定间隔的切入点
➢ 编码数据允许在编码码流中插入整数倍的切入点,以利记录、播放和编辑短的声音序列,并能精确指定编辑点
◼为了能简单地在解码器中实现上述功能,切入点的帧必须包括码流解码所需的完整信息
◼这些特性在数字声音广播领域也很重要,因为由于经济原因须要有低复杂性的解码器,而且码流中要有许多切入点,以易于对传输误码造成的连续样值错误进行块隐藏。


◼ 层I每帧含384个样本数据。每帧由32个子带分别输出的12个样本值组成
➢ 以48kHz采样,一帧长为32×12×20.83µs =8ms。
◼ 层II每帧包含1152个样本。低、中、高频段对比特分配不同,分别用4、3、2比特。比特流中增加了一个比特因子选择信息域,解码器根据这个域的信息可知道是否需要以及如何共享比例因子。


⚫帧头(Header):每帧开始的头32个比特,包含有同步和状态比特流信息,在所有层都相同,同步码字为12bit全1码 (1111,1111,1111)。
⚫误码检测CRC:使用一种16bit奇偶校验字,可供在比特流中作检测误码用。在所有层都相同
⚫声音数据:由比特分配表、比例因子选择信息、比例因子和子带样值组成,其中子带样值是声音数据的最大部分。每层声音数据不同。
⚫辅助数据:用作辅助数据比特流。
3、理解心理声学模型的实现过程
临界频带的概念
◼ 临界频带是指当某个纯音被以它为中心频率、且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽为临界频带宽度。
掩蔽值计算的思路
人耳听觉系统
➢ 中心频率与信号频率相同的滤波器具有最大响应;中心频率偏离信号频率较多的滤波器不会产生响应。
➢ 在0Hz到20KHz频率范围内由25个重叠的带通滤波器组成的滤波器组。
➢ 听音者在噪声中听某一纯音信号时,只启用中心频率与信号频率相同的那个听觉滤波器,纯音信号通过该滤波器,而噪声信号只有通带范围内的部分信号能通过,通带以外的频率成分则被抑制,只有通过该滤波器的噪声才对掩蔽起作用。

掩蔽效果的加和
◼ 音乐与语音信号大都由一系列复杂的频谱分量构成 ,相应的这些多个掩蔽分量也会相互影响并最终获得一个整体的掩蔽阈值。对于多个掩蔽分量的综合掩蔽效果,目前有多种模型给出了描述方案 。
◼ Lutfi 对多个掩蔽音同时存在时的综合掩蔽效果进行了研究:每个掩蔽音的掩蔽效果先独立变换然后再线性相加。

◼ 问题:综合掩蔽效果与各掩蔽信号的声音级以及掩蔽信号的个数都有关系。如何整合掩蔽音?
➢ 当两个信号重叠并落在一个临界频带中时,二者的掩蔽分量可以线性相加。
➢ 对于复杂音频信号可将其频谱分割成一系列离散段,每段就是一个掩蔽信号。各掩蔽音互不重叠,即以一个临界带为单
位。各掩蔽音的声压级则通过将对应的临界频带上的短时功率谱密度线性相加得到 。
4、理解码率分配的实现思路






5、输出音频的采样率和目标码率
观察m2aenc.c中parse_args函数一下片段
/* process args */
while (++i < argc && err == 0) {
char c, *token, *arg, *nextArg;
int argUsed;
token = argv[i];
if (*token++ == '-') {
if (i + 1 < argc)
nextArg = argv[i + 1];
else
nextArg = "";
argUsed = 0;
if (!*token) {
/* The user wants to use stdin and/or stdout. */
if (inPath[0] == '\0')
strncpy (inPath, argv[i], MAX_NAME_SIZE);
else if (outPath[0] == '\0')
strncpy (outPath, argv[i], MAX_NAME_SIZE);
}
可以看出命令参数格式为:输入文件名 输出文件名


由文字可知,输出文件的采样频率为44.1 kHz,码率为192 kbps。
在print_config函数尾部,添加如下代码
FILE* fp_info;
fp_info = fopen("info_enc.txt", "a");
fprintf(fp_info, "输入文件:%s\n", inPath);
fprintf(fp_info, "输出文件:%s\n", outPath);
fprintf(fp_info, "输出音频的采样频率:%.1f kHz\n", s_freq[header->version][header->sampling_frequency]);
fprintf(fp_info, "输出音频的目标码率:%d kbps\n", bitrate[header->version][header->bitrate_index]);
fclose(fp_info);
6、某个数据帧,输出
◆该帧所分配的比特数
◆该帧的比例因子
◆该帧的比特分配结果
修改main函数中,在帧循环while(get_audio()){}结构中,添加如下代码
FILE* fp_info;
fp_info = fopen("info_enc.txt","a");
fprintf(fp_info, "*****************************************************\n");
while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
//...............
//在尾部添加
if (frameNum == 8)
{
fprintf(fp_info, "当前帧:Frame[%d]\n", frameNum);
fprintf(fp_info, "该帧分配的比特数:%d", adb);
fprintf(fp_info, "\n");
fprintf(fp_info, "*****************\n");
fprintf(fp_info, "比例因子\n");
fprintf(fp_info, "*****************\n");
for (ch = 0; ch < nch; ch++)
{
fprintf(fp_info, "****声道%2d****\n", ch + 1);
for (sb = 0; sb < frame.sblimit; sb++)
{
fprintf(fp_info, "子带[%2d]:\t", sb + 1);
for (int gr = 0; gr < 3; gr++) {
fprintf(fp_info, "%2d\t", scalar[ch][gr][sb]);
}
fprintf(fp_info, "\n");
}
}
fprintf(fp_info, "\n");
fprintf(fp_info, "*****************\n");
fprintf(fp_info, "比特分配表\n");
fprintf(fp_info, "*****************\n");
for (ch = 0; ch < nch; ch++) {
fprintf(fp_info, "****声道%2d****\n", ch + 1);
for (sb = 0; sb < frame.sblimit; sb++) {
fprintf(fp_info, "子带[%2d]:\t%2d\n", sb + 1, bit_alloc[ch][sb]);
}
fprintf(fp_info, "\n");
}
fclose(fp_info);
}
}
输出的info_enc.txt文件如下
输入文件:test.wav
输出文件:test_mpeg2.mp2
输出音频的采样频率:44.1 kHz
输出音频的目标码率:192 kbps
*****************************************************
当前帧:Frame[8]
该帧分配的比特数:16
*****************
比例因子
*****************
****声道 1****
子带[ 1]: 9 9 9
子带[ 2]: 20 20 20
子带[ 3]: 22 22 22
子带[ 4]: 28 29 29
子带[ 5]: 21 22 22
子带[ 6]: 23 23 21
子带[ 7]: 23 23 23
子带[ 8]: 23 23 23
子带[ 9]: 27 21 25
子带[10]: 23 23 23
子带[11]: 27 24 24
子带[12]: 25 25 25
子带[13]: 26 26 26
子带[14]: 27 27 27
子带[15]: 28 29 29
子带[16]: 32 28 28
子带[17]: 31 35 35
子带[18]: 31 36 31
子带[19]: 32 32 32
子带[20]: 33 33 33
子带[21]: 34 34 34
子带[22]: 32 32 32
子带[23]: 40 40 40
子带[24]: 54 54 50
子带[25]: 53 53 53
子带[26]: 54 54 54
子带[27]: 52 52 52
子带[28]: 53 53 53
子带[29]: 54 54 54
子带[30]: 53 53 53
*****************
比特分配表
*****************
****声道 1****
子带[ 1]: 10
子带[ 2]: 8
子带[ 3]: 7
子带[ 4]: 7
子带[ 5]: 9
子带[ 6]: 8
子带[ 7]: 7
子带[ 8]: 7
子带[ 9]: 7
子带[10]: 7
子带[11]: 6
子带[12]: 6
子带[13]: 6
子带[14]: 6
子带[15]: 6
子带[16]: 6
子带[17]: 6
子带[18]: 6
子带[19]: 6
子带[20]: 5
子带[21]: 4
子带[22]: 4
子带[23]: 0
子带[24]: 0
子带[25]: 0
子带[26]: 0
子带[27]: 0
子带[28]: 0
子带[29]: 0
子带[30]: 0
本文详细介绍了MPEG音频编码的实验要求和设计思想,包括多相滤波器组在子带分割中的应用,心理声学模型的临界频带和掩蔽值计算,码率分配策略以及数据帧的包装过程。实验旨在理解音频编码的整体框架和关键步骤。
1086

被折叠的 条评论
为什么被折叠?



