目录
MPEG介绍
MPEG标准主要有以下五个,MPEG-1、MPEG-2、MPEG-4、MPEG-7及MPEG-21等。该专家组建于1988年,专门负责为CD建立视频和音频标准,而成员都是视频、音频及系统领域的技术专家。及后,他们成功将声音和影像的记录脱离了传统的模拟方式,建立了ISO/IEC11172压缩编码标准,并制定出MPEG-格式,令视听传播方面进入了数字化时代。因此,大家现在泛指的MPEG-X版本,就是由ISO (InternationalOrganization for Standardization) 所制定而发布的视频、音频、数据的压缩标准。
MPEG-1音频压缩编码
MPEG-1中采用了感知音频编码,Layer II的编码器编码框图如下,上方部分是子带编码部分,这也是编码的主线;下方的部分,是MPEG音频编码的亮点。
多相滤波器
数字音频信号通过一个多相滤波器组,变换成32个等宽频带子带,使得信号具有较高的时间分辨率,确保在短暂冲击信号的情况下,编码的声音信号具有足够高的质量。高时域分辨率和高频域分辨率是不可兼得的,需要做出权衡。滤波器组的输出是临界频带经过量化的系数样值。若一个子带覆盖多个临界频带,则选择具有最小NMR的临界频带来计算分配给子带的比特数。
心理声学模型
心理声学模型决定了各个子带中允许的最大量化噪声,小于它的量化噪声都会被掩蔽。若子带内的信号功率小于掩蔽阈值,则不进行编码;否则,确定要编码的系数所需的比特数,使量化引起的噪声低于掩蔽效应;使用FFT将音频样值变换到频域。这里Layer II采用1024点FFT(Layer I中采用512点),提高了频率分辨率,可以得到更准确的频谱特性;将得到的频率组成临界频带,由于乐音和非乐音(噪声)信号的掩蔽能力不同,因此在临界频带的谱值中,将两种信号分离:可将局部峰值视为乐音,然后将本临界频带内的剩余频谱组成一个代表噪声频率(无调成份)
量化编码
- 在调整到固定码率之前
先确定可用于样值编码的有效比特数;
这个数值取决于比例因子、比例因子选择信息、比特分配信息以及辅助数据所需比特数。
- 比特分配
对每个子带计算掩噪比MNR (dB) = 信噪比SNR - 信掩比SMR,然后找出其中具有最低MNR的子带,并给该子带多分配一些比特,然后重新计算MNR,继续分配,重复该步骤,直至没有比特可以分配。这样可以使得在满足比特率和掩蔽要求的前提下,使MNR最小;
- 计算比例因子
对各个子带每36个样点(Layer I为12个样点)进行一次比例因子的计算,先确定12个连续样值中的最大值,查Layer II、Layer I比例因子表中比这它大的最小值作为量化比例因子;每12个样值计算出一个比例因子,Layer II中将每个子带分为3组,每组各有12个取样值,因此36个样值具有3个比例因子
- 子带样值量化
将子带样值除以比例因子,根据所分配的比特数查表得 A A A、 B B B,量化结果为 A X + B AX+B AX+B。
- 颗粒形成
对量化级别在3、5、9级时,采用“颗粒” 优化。
代码分析
在print_config()
函数中输出一些输入、输出文件的主要参数
#if FRAME_TRACE
fprintf(infoFp, "========== 基本信息 ==========\n");
fprintf(infoFp, "输入文件:%s\n", inPath);
fprintf(infoFp, "输出文件:%s\n", outPath);
fprintf(infoFp, "采样频率:%.1f kHz\n", s_freq[header->version][header->sampling_frequency]);
fprintf(infoFp, "输出文件码率:%d kbps\n", bitrate[header->version][header->bitrate_index]);
#endif // FRAME_TRACE
在main()
中添加输出比例因子和比特分配表
#else
scale_factor_calc(*sb_sample, scalar, nch, frame.sblimit); // 计算比例因子
pick_scale(scalar, &frame, max_sc); // pick比例因子
#if FRAME_TRACE
if (frameNum == 2) {
fprintf(infoFp, "声道数:%d\n", nch);
fprintf(infoFp, "目前观测第 %d 帧\n", frameNum);
fprintf(infoFp, "本帧比特预算:%d bits\n", adb);
fprintf(infoFp, "\n");
/* 比例因子 */
fprintf(infoFp, "========== 比例因子 ==========\n");
for (ch = 0; ch < nch; ch++) // 每个声道单独输出
{
fprintf(infoFp, "------ 声道%2d ------\n", ch + 1);
for (sb = 0; sb < frame.sblimit; sb++) // 每个子带
{
fprintf(infoFp, "子带[%2d]:\t", sb + 1);
for (int gr = 0; gr < 3; gr++) {
fprintf(infoFp, "%2d\t", scalar[ch][gr][sb]);
}
fprintf(infoFp, "\n");
}
}
fprintf(infoFp, "\n");
/* 比特分配表 */
fprintf(infoFp, "========== 比特分配表 ==========\n"); //输出比特分配结果
for (ch = 0; ch < nch; ch++) {
fprintf(infoFp, "------ 声道%2d ------\n", ch + 1); //按声道分配
for (sb = 0; sb < frame.sblimit; sb++) {
fprintf(infoFp, "子带[%2d]:\t%2d\n", sb + 1, bit_alloc[ch][sb]);
}
fprintf(infoFp, "\n");
}
}
#endif // FRAME_TRACE
实验结果
乐音:
========== 基本信息 ==========
输入文件:aaa.wav
输出文件:aaa.mp2
采样频率:44.1 kHz
输出文件码率:192 kbps
声道数:1
目前观测第 2 帧
本帧比特预算:5016 bits
========== 比例因子 ==========
------ 声道 1 ------
子带[ 1]: 40 35 35
子带[ 2]: 41 40 40
子带[ 3]: 47 46 46
子带[ 4]: 40 40 45
子带[ 5]: 46 44 47
子带[ 6]: 50 47 48
子带[ 7]: 46 49 49
子带[ 8]: 47 48 48
子带[ 9]: 49 48 48
子带[10]: 49 48 47
子带[11]: 48 47 48
子带[12]: 46 48 46
子带[13]: 49 48 48
子带[14]: 50 51 50
子带[15]: 49 49 48
子带[16]: 50 46 49
子带[17]: 51 50 48
子带[18]: 51 50 51
子带[19]: 52 49 51
子带[20]: 51 49 49
子带[21]: 49 51 50
子带[22]: 51 49 52
子带[23]: 48 49 50
子带[24]: 54 52 55
子带[25]: 54 56 54
子带[26]: 55 54 54
子带[27]: 53 53 53
子带[28]: 54 54 54
子带[29]: 54 56 54
子带[30]: 55 55 55
========== 比特分配表 ==========
------ 声道 1 ------
子带[ 1]: 5
子带[ 2]: 5
子带[ 3]: 3
子带[ 4]: 6
子带[ 5]: 5
子带[ 6]: 5
子带[ 7]: 4
子带[ 8]: 5
子带[ 9]: 7
子带[10]: 6
子带[11]: 3
子带[12]: 3
子带[13]: 5
子带[14]: 3
子带[15]: 2
子带[16]: 5
子带[17]: 5
子带[18]: 4
子带[19]: 3
子带[20]: 7
子带[21]: 4
子带[22]: 4
子带[23]: 1
子带[24]: 1
子带[25]: 0
子带[26]: 1
子带[27]: 2
子带[28]: 1
子带[29]: 1
子带[30]: 2
噪音:
========== 基本信息 ==========
输入文件:zaoyin.wav
输出文件:zaoyin.mp2
采样频率:44.1 kHz
输出文件码率:192 kbps
声道数:1
目前观测第 2 帧
本帧比特预算:5016 bits
========== 比例因子 ==========
------ 声道 1 ------
子带[ 1]: 24 23 22
子带[ 2]: 27 23 27
子带[ 3]: 24 27 24
子带[ 4]: 24 26 25
子带[ 5]: 24 25 24
子带[ 6]: 27 25 25
子带[ 7]: 25 24 24
子带[ 8]: 25 24 24
子带[ 9]: 25 22 25
子带[10]: 25 25 25
子带[11]: 27 26 27
子带[12]: 24 24 24
子带[13]: 24 23 24
子带[14]: 23 24 24
子带[15]: 26 24 25
子带[16]: 24 25 23
子带[17]: 23 25 24
子带[18]: 25 23 25
子带[19]: 24 25 25
子带[20]: 24 26 24
子带[21]: 23 25 23
子带[22]: 24 25 24
子带[23]: 23 23 24
子带[24]: 26 25 24
子带[25]: 23 25 23
子带[26]: 26 23 26
子带[27]: 25 23 25
子带[28]: 24 26 24
子带[29]: 23 25 23
子带[30]: 26 24 26
========== 比特分配表 ==========
------ 声道 1 ------
子带[ 1]: 4
子带[ 2]: 5
子带[ 3]: 5
子带[ 4]: 6
子带[ 5]: 6
子带[ 6]: 7
子带[ 7]: 7
子带[ 8]: 7
子带[ 9]: 7
子带[10]: 7
子带[11]: 6
子带[12]: 6
子带[13]: 6
子带[14]: 6
子带[15]: 6
子带[16]: 5
子带[17]: 6
子带[18]: 6
子带[19]: 5
子带[20]: 5
子带[21]: 5
子带[22]: 5
子带[23]: 3
子带[24]: 1
子带[25]: 1
子带[26]: 1
子带[27]: 1
子带[28]: 1
子带[29]: 1
子带[30]: 0
乐音叠加噪音:
========== 基本信息 ==========
输入文件:diejia.wav
输出文件:diejia.mp2
采样频率:44.1 kHz
输出文件码率:192 kbps
声道数:1
目前观测第 2 帧
本帧比特预算:5016 bits
========== 比例因子 ==========
------ 声道 1 ------
子带[ 1]: 25 24 25
子带[ 2]: 26 25 24
子带[ 3]: 23 24 23
子带[ 4]: 24 24 24
子带[ 5]: 24 25 24
子带[ 6]: 25 24 26
子带[ 7]: 26 24 26
子带[ 8]: 24 23 24
子带[ 9]: 24 24 23
子带[10]: 23 26 22
子带[11]: 26 23 24
子带[12]: 23 25 26
子带[13]: 24 23 23
子带[14]: 25 25 24
子带[15]: 24 27 25
子带[16]: 26 23 26
子带[17]: 24 26 23
子带[18]: 26 23 23
子带[19]: 25 25 24
子带[20]: 25 26 23
子带[21]: 26 24 26
子带[22]: 23 26 24
子带[23]: 26 25 24
子带[24]: 24 23 24
子带[25]: 24 25 24
子带[26]: 25 24 23
子带[27]: 27 25 27
子带[28]: 23 23 23
子带[29]: 24 24 23
子带[30]: 23 23 24
========== 比特分配表 ==========
------ 声道 1 ------
子带[ 1]: 2
子带[ 2]: 2
子带[ 3]: 2
子带[ 4]: 3
子带[ 5]: 3
子带[ 6]: 3
子带[ 7]: 3
子带[ 8]: 4
子带[ 9]: 3
子带[10]: 3
子带[11]: 2
子带[12]: 3
子带[13]: 1
子带[14]: 3
子带[15]: 1
子带[16]: 1
子带[17]: 1
子带[18]: 2
子带[19]: 2
子带[20]: 1
子带[21]: 1
子带[22]: 1
子带[23]: 1
子带[24]: 0
子带[25]: 0
子带[26]: 0
子带[27]: 0
子带[28]: 0
子带[29]: 0
子带[30]: 0