目录
原理理解模块
一、理解感知音频编码的设计思想
1.两条线
①主干:子带分解
以1152个样本为单位,输入到滤波器组中进行32个子带的分解,即以32个样本为一个时间窗口,做36次自带分解,形成36个样本,形成以12个样本为单位的3个块(以12个样本为观察组,之间的差别不大),以此进行比例因子的提取和选择,通过频域分析线路的辅助,进行后续的量化等工作。
②辅助:频域分析
通过1024点的FFT输出FFT结果,和比例因子共同输入到心理声学模型中,输出SMR并生成听阈曲线,再结合码率限制进行动态比特分配,使整帧和每个子带的总噪声-掩蔽比最小,最终结合主干线路进行装帧。
2.时-频分析的矛盾
32个子带样本在时域上的分析较为清晰,不能精确地反映人耳的听觉特性,且如果频域进行32点FFT,分辨率不高;而FFT也仍然存在问题,其只能说明哪些频率成分存在,不能说明这些频率成分在什么时间出现。
二、理解心理声学模型的实现过程
1.临界频带的概念
临界频带是指当某个纯音被以它为中心频率、且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽为临界频带宽度。
2.掩蔽值计算的思路
音频信号可以分解为乐音和噪声,两者共有四种掩蔽组合,即“乐音-乐音”、“乐音-噪声”、“噪声-乐音”、“噪声-噪声”。另有安静时的阈值为绝对阈值。
某一频率点i的总掩蔽阈值可通过该点的绝对掩蔽阈值与单独掩蔽阈值相加获得。
第一项为绝对阈值、第二项为乐音掩蔽、第三项为噪音掩蔽。
三、理解码率分配的实现思路
对每个子带计算掩蔽-噪声比MNR,即信噪比SNR-信掩比SMR,即MNR=SNR-SMR
如:现有20bit的预算,每分配一个bit,信噪比提升6dB,噪掩比降低6dB。在初始未分配bit的情况下SMR、SNR、MNR数值为:
SMR | 20 | 18 | 11 | -1 | -3 | -5 | -2 |
SNR | 0 | 0 | 0 | - | - | - | - |
MNR | 20 | 18 | 11 | - | - | - | - |
由于信掩比后四个值为负,所以不分配bit。由于MNR中20dB最大,所以优先分配1bit,此时MNR降低了6dB:
SMR | 20 | 18 | 11 | -1 | -3 | -5 | -2 |
SNR | 6 | 0 | 0 | - | - | - | - |
MNR | 14 | 18 | 11 | - | - | - | - |
此时MNR中18dB最大,再分配1bit,此时为:
SMR | 20 | 18 | 11 | -1 | -3 | -5 | -2 |
SNR | 6 | 6 | 0 | - | - | - | - |
MNR | 14 | 12 | 11 | - | - | - | - |
按该种规律,每次都在MNR中筛选出最大的一项进行比特分配,进行循环直到没有比特可用。
实验操作模块
一、理解程序设计的整体框架
音频输入:
// 读取音频长度
unsigned long get_audio (FILE * musicin, short buffer[2][1152], unsigned long num_samples, int nch, frame_header *header)
// 将音频存入buffer
unsigned long read_samples (FILE * musicin, short sample_buffer[2304], unsigned long num_samples, unsigned long frame_size)
// 计算可用比特数,即比特预算
int available_bits (frame_header *header, options * glopts);
多项滤波器组:
// 对buffer中存储的音频数据进行子带分解和滤波
void WindowFilterSubband( short *pBuffer, int ch, double s[SBLIMIT] );
计算比例因子:
// 二分法查找比例因子
void scale_factor_calc (double[][3][SCALE_BLOCK][SBLIMIT],
unsigned int[][3][SBLIMIT], int, int);
// 每个子带对应的三组样本(每组12个样本)分别选择三个不同的比例因子
void pick_scale (unsigned int[2][3][SBLIMIT], frame_info *,
double[2][SBLIMIT]);
// 比例因子选择信息
void transmission_pattern (unsigned int[2][3][SBLIMIT],
unsigned int[2][SBLIMIT], frame_info *);
心理声学模型:
不同model对应不同的心理声学模型,根据所选模型计算SMR
动态比特分配:
// 计算MNR,循环进行动态比特分配
void main_bit_allocation_new (double SMR[2][SBLIMIT],
unsigned int scfsi[2][SBLIMIT],
unsigned int bit_alloc[2][SBLIMIT], int *adb,
frame_info * frame, options * glopts);
量化装帧:
// 比特分配
void encode_bit_alloc (unsigned int[2][SBLIMIT], frame_info *,
Bit_stream_struc *);
// 比例因子
void encode_scale (unsigned int[2][SBLIMIT],
unsigned int[2][SBLIMIT],
unsigned int[2][3][SBLIMIT], frame_info *,
Bit_stream_struc *);
// 子带量化
void subband_quantization (unsigned int[2][3][SBLIMIT],
double[2][3][SCALE_BLOCK][SBLIMIT],
unsigned int[3][SBLIMIT],
double[3][SCALE_BLOCK][SBLIMIT],
unsigned int[2][SBLIMIT],
unsigned int[2][3][SCALE_BLOCK][SBLIMIT],
frame_info *);
// 量化后编码
void sample_encoding (unsigned int[2][3][SCALE_BLOCK][SBLIMIT],
unsigned int[2][SBLIMIT], frame_info *,
Bit_stream_struc *);
二、选择三个不同特性的音频文件,输出音频的采样率和目标码率
- 噪声(持续噪声、突发噪声):以吹风机开小风档作为持续噪声con_noise.wav,以突然的拍手声作为突发噪声abr_noise.wav;
- 音乐:截取十秒纯音乐作为乐音输入music.wav;
- 音乐+噪声:将音乐和持续噪声和突发噪声合并作为测试音频test.wav。
三、对某个数据帧进行输出
- 该帧所分配的比特数
- 该帧的比例因子
- 该帧的比特分配结果
四、代码修改和结果输出
1.代码修改
在源文件m2aenc.c的开头加入define语句:
#define FRAME_TRACE 1
在主函数部分加入以下内容:
......
#ifdef NEWENCODE
scalefactor_calc_new(*sb_sample, scalar, nch, frame.sblimit);
find_sf_max(scalar, &frame, max_sc);
if (frame.actual_mode == MPG_MD_JOINT_STEREO) {
/* this way we calculate more mono than we need */
/* but it is cheap */
combine_LR_new(*sb_sample, *j_sample, frame.sblimit);
scalefactor_calc_new(j_sample, &j_scale, 1, frame.sblimit);
}
#else
scale_factor_calc(*sb_sample, scalar, nch, frame.sblimit);
pick_scale(scalar, &frame, max_sc);
/*-----------------------------------------------------------------------*/
/*-------------------------------添加代码---------------------------------*/
#if FRAME_TRACE
if (frameNum == 2) {
printf("声道数:%d\n", nch);
printf("当前是第 %d 帧\n", frameNum);
printf("该帧比特预算:%d bits\n", adb);
printf("\n");
/* 比例因子 */
printf("-----------比例因子-----------\n");
for (ch = 0; ch < nch; ch++) // 每个声道单独输出
{
printf("-------声道%2d-------\n", ch + 1);
for (sb = 0; sb < frame.sblimit; sb++) // 每个子带
{
printf("子带[%2d]:\t", sb + 1);
for (gr = 0; gr < 3; gr++) {
printf("%2d\t", scalar[ch][gr][sb]);
}
printf("\n");
}
}
printf("\n");
/* 比特分配表 */
printf("-----------比特分配表-----------\n"); //输出比特分配结果
for (ch = 0; ch < nch; ch++) {
printf("-------声道%2d-------\n", ch + 1); //按声道分配
for (sb = 0; sb < frame.sblimit; sb++) {
printf("子带[%2d]:\t%2d\n", sb + 1, bit_alloc[ch][sb]);
}
printf("\n");
}
}
#endif // FRAME_TRACE
/*-------------------------------代码结束---------------------------------*/
/*-----------------------------------------------------------------------*/
if (frame.actual_mode == MPG_MD_JOINT_STEREO) {
/* this way we calculate more mono than we canshu */
/* but it is cheap */
combine_LR(*sb_sample, *j_sample, frame.sblimit);
scale_factor_calc(j_sample, &j_scale, 1, frame.sblimit);
}
#endif
......
在print_config函数最后添加以下部分:
#if FRAME_TRACE
printf("-------------调试信息-------------\n");
printf("输入文件:%s\n", inPath);
printf("输出文件:%s\n", outPath);
printf("采样频率:%.1f kHz\n", s_freq[header->version][header->sampling_frequency]);
printf("目标码率:%d kbps\n", bitrate[header->version][header->bitrate_index]);
#endif // FRAME_TRACE
2.结果显示
音乐:music.wav
-------------调试信息-------------
输入文件:D:\大三\大三下\数据压缩\week13\music.wav
输出文件:D:\大三\大三下\数据压缩\week13\music.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:2
当前是第 2 帧
该帧比特预算:5016 bits
-----------比例因子-----------
-------声道 1-------
子带[ 1]: 63 63 63
子带[ 2]: 63 63 63
子带[ 3]: 63 63 63
子带[ 4]: 63 63 63
子带[ 5]: 63 63 63
子带[ 6]: 63 63 63
子带[ 7]: 63 63 63
子带[ 8]: 63 63 63
子带[ 9]: 63 63 63
子带[10]: 63 63 63
子带[11]: 63 63 63
子带[12]: 63 63 63
子带[13]: 63 63 63
子带[14]: 63 63 63
子带[15]: 63 63 63
子带[16]: 63 63 63
子带[17]: 63 63 63
子带[18]: 63 63 63
子带[19]: 63 63 63
子带[20]: 63 63 63
子带[21]: 63 63 63
子带[22]: 63 63 63
子带[23]: 63 63 63
子带[24]: 63 63 63
子带[25]: 63 63 63
子带[26]: 63 63 63
子带[27]: 63 63 63
子带[28]: 63 63 63
子带[29]: 63 63 63
子带[30]: 63 63 63
-------声道 2-------
子带[ 1]: 63 63 63
子带[ 2]: 63 63 63
子带[ 3]: 63 63 63
子带[ 4]: 63 63 63
子带[ 5]: 63 63 63
子带[ 6]: 63 63 63
子带[ 7]: 63 63 63
子带[ 8]: 63 63 63
子带[ 9]: 63 63 63
子带[10]: 63 63 63
子带[11]: 63 63 63
子带[12]: 63 63 63
子带[13]: 63 63 63
子带[14]: 63 63 63
子带[15]: 63 63 63
子带[16]: 63 63 63
子带[17]: 63 63 63
子带[18]: 63 63 63
子带[19]: 63 63 63
子带[20]: 63 63 63
子带[21]: 63 63 63
子带[22]: 63 63 63
子带[23]: 63 63 63
子带[24]: 63 63 63
子带[25]: 63 63 63
子带[26]: 63 63 63
子带[27]: 63 63 63
子带[28]: 63 63 63
子带[29]: 63 63 63
子带[30]: 63 63 63
-----------比特分配表-----------
-------声道 1-------
子带[ 1]: 3
子带[ 2]: 3
子带[ 3]: 3
子带[ 4]: 5
子带[ 5]: 6
子带[ 6]: 6
子带[ 7]: 5
子带[ 8]: 5
子带[ 9]: 4
子带[10]: 4
子带[11]: 4
子带[12]: 4
子带[13]: 4
子带[14]: 4
子带[15]: 3
子带[16]: 2
子带[17]: 1
子带[18]: 1
子带[19]: 0
子带[20]: 0
子带[21]: 0
子带[22]: 0
子带[23]: 0
子带[24]: 0
子带[25]: 0
子带[26]: 0
子带[27]: 0
子带[28]: 0
子带[29]: 0
子带[30]: 0
-------声道 2-------
子带[ 1]: 3
子带[ 2]: 3
子带[ 3]: 3
子带[ 4]: 5
子带[ 5]: 6
子带[ 6]: 6
子带[ 7]: 5
子带[ 8]: 5
子带[ 9]: 4
子带[10]: 4
子带[11]: 4
子带[12]: 4
子带[13]: 4
子带[14]: 3
子带[15]: 3
子带[16]: 2
子带[17]: 1
子带[18]: 1
子带[19]: 0
子带[20]: 0
子带[21]: 0
子带[22]: 0
子带[23]: 0
子带[24]: 0
子带[25]: 0
子带[26]: 0
子带[27]: 0
子带[28]: 0
子带[29]: 0
子带[30]: 0
持续噪声:con_noise.wav
-------------调试信息-------------
输入文件:D:\大三\大三下\数据压缩\week13\con_noise.wav
输出文件:D:\大三\大三下\数据压缩\week13\con_noise.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:2
当前是第 9 帧
该帧比特预算:5016 bits
-----------比例因子-----------
-------声道 1-------
子带[ 1]: 10 10 12
子带[ 2]: 8 10 9
子带[ 3]: 9 11 10
子带[ 4]: 8 12 11
子带[ 5]: 11 9 9
子带[ 6]: 9 9 10
子带[ 7]: 11 9 9
子带[ 8]: 10 9 9
子带[ 9]: 9 10 10
子带[10]: 10 9 8
子带[11]: 11 9 9
子带[12]: 8 11 10
子带[13]: 9 10 8
子带[14]: 10 9 9
子带[15]: 11 9 10
子带[16]: 8 9 10
子带[17]: 10 9 9
子带[18]: 12 10 9
子带[19]: 10 9 11
子带[20]: 9 10 8
子带[21]: 10 9 12
子带[22]: 9 11 9
子带[23]: 10 8 8
子带[24]: 11 9 11
子带[25]: 9 10 9
子带[26]: 9 9 10
子带[27]: 9 12 8
子带[28]: 11 10 10
子带[29]: 10 10 11
子带[30]: 8 10 8
-------声道 2-------
子带[ 1]: 5 5 5
子带[ 2]: 8 13 9
子带[ 3]: 12 14 12
子带[ 4]: 13 13 9
子带[ 5]: 14 13 13
子带[ 6]: 13 13 12
子带[ 7]: 13 14 16
子带[ 8]: 16 16 16
子带[ 9]: 16 16 16
子带[10]: 12 14 15
子带[11]: 15 15 16
子带[12]: 16 16 14
子带[13]: 14 17 14
子带[14]: 15 16 14
子带[15]: 14 15 16
子带[16]: 17 16 14
子带[17]: 17 18 14
子带[18]: 16 15 15
子带[19]: 16 16 14
子带[20]: 16 19 16
子带[21]: 14 16 15
子带[22]: 13 15 15
子带[23]: 14 18 15
子带[24]: 16 16 18
子带[25]: 16 16 16
子带[26]: 13 14 14
子带[27]: 15 13 15
子带[28]: 11 13 14
子带[29]: 10 11 10
子带[30]: 11 14 12
-----------比特分配表-----------
-------声道 1-------
子带[ 1]: 4
子带[ 2]: 4
子带[ 3]: 4
子带[ 4]: 4
子带[ 5]: 5
子带[ 6]: 5
子带[ 7]: 5
子带[ 8]: 4
子带[ 9]: 4
子带[10]: 4
子带[11]: 4
子带[12]: 5
子带[13]: 3
子带[14]: 4
子带[15]: 4
子带[16]: 3
子带[17]: 4
子带[18]: 4
子带[19]: 4
子带[20]: 3
子带[21]: 3
子带[22]: 4
子带[23]: 2
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 2
子带[28]: 2
子带[29]: 2
子带[30]: 1
-------声道 2-------
子带[ 1]: 5
子带[ 2]: 4
子带[ 3]: 4
子带[ 4]: 4
子带[ 5]: 5
子带[ 6]: 5
子带[ 7]: 5
子带[ 8]: 4
子带[ 9]: 4
子带[10]: 4
子带[11]: 4
子带[12]: 5
子带[13]: 3
子带[14]: 4
子带[15]: 4
子带[16]: 3
子带[17]: 4
子带[18]: 4
子带[19]: 4
子带[20]: 3
子带[21]: 3
子带[22]: 4
子带[23]: 2
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 2
子带[28]: 2
子带[29]: 2
子带[30]: 1
突发噪声:abr_noise.wav
-------------调试信息-------------
输入文件:D:\大三\大三下\数据压缩\week13\abr_noise.wav
输出文件:D:\大三\大三下\数据压缩\week13\abr_noise.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:2
当前是第 9 帧
该帧比特预算:5016 bits
-----------比例因子-----------
-------声道 1-------
子带[ 1]: 10 9 9
子带[ 2]: 11 10 10
子带[ 3]: 11 9 9
子带[ 4]: 10 9 9
子带[ 5]: 11 9 9
子带[ 6]: 10 11 11
子带[ 7]: 10 11 8
子带[ 8]: 11 10 8
子带[ 9]: 9 9 9
子带[10]: 10 8 10
子带[11]: 8 6 10
子带[12]: 8 8 9
子带[13]: 9 6 9
子带[14]: 8 10 10
子带[15]: 9 9 11
子带[16]: 9 10 10
子带[17]: 8 10 10
子带[18]: 10 8 8
子带[19]: 13 11 10
子带[20]: 11 9 11
子带[21]: 9 11 8
子带[22]: 8 11 8
子带[23]: 11 9 9
子带[24]: 10 9 11
子带[25]: 9 9 10
子带[26]: 10 10 9
子带[27]: 11 8 10
子带[28]: 9 9 9
子带[29]: 10 9 9
子带[30]: 10 11 11
-------声道 2-------
子带[ 1]: 6 7 7
子带[ 2]: 11 12 12
子带[ 3]: 12 12 11
子带[ 4]: 9 11 11
子带[ 5]: 11 9 8
子带[ 6]: 10 11 12
子带[ 7]: 9 9 9
子带[ 8]: 9 9 10
子带[ 9]: 10 8 9
子带[10]: 12 10 12
子带[11]: 10 8 12
子带[12]: 12 10 10
子带[13]: 10 10 10
子带[14]: 10 9 12
子带[15]: 10 11 10
子带[16]: 10 10 10
子带[17]: 13 10 9
子带[18]: 11 11 11
子带[19]: 11 11 10
子带[20]: 11 12 10
子带[21]: 10 13 11
子带[22]: 9 10 9
子带[23]: 8 9 11
子带[24]: 10 12 9
子带[25]: 12 11 11
子带[26]: 10 12 10
子带[27]: 10 12 11
子带[28]: 13 10 12
子带[29]: 9 11 11
子带[30]: 12 10 9
-----------比特分配表-----------
-------声道 1-------
子带[ 1]: 6
子带[ 2]: 3
子带[ 3]: 3
子带[ 4]: 5
子带[ 5]: 4
子带[ 6]: 4
子带[ 7]: 4
子带[ 8]: 3
子带[ 9]: 5
子带[10]: 4
子带[11]: 3
子带[12]: 4
子带[13]: 3
子带[14]: 3
子带[15]: 4
子带[16]: 1
子带[17]: 3
子带[18]: 3
子带[19]: 2
子带[20]: 2
子带[21]: 1
子带[22]: 2
子带[23]: 2
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 1
子带[28]: 2
子带[29]: 1
子带[30]: 0
-------声道 2-------
子带[ 1]: 6
子带[ 2]: 4
子带[ 3]: 3
子带[ 4]: 5
子带[ 5]: 5
子带[ 6]: 4
子带[ 7]: 4
子带[ 8]: 3
子带[ 9]: 5
子带[10]: 4
子带[11]: 3
子带[12]: 4
子带[13]: 3
子带[14]: 3
子带[15]: 4
子带[16]: 1
子带[17]: 3
子带[18]: 3
子带[19]: 2
子带[20]: 2
子带[21]: 1
子带[22]: 2
子带[23]: 2
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 1
子带[28]: 2
子带[29]: 1
子带[30]: 0
音乐+噪声:test.wav
-------------调试信息-------------
输入文件:D:\大三\大三下\数据压缩\week13\test.wav
输出文件:D:\大三\大三下\数据压缩\week13\test.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:2
当前是第 9 帧
该帧比特预算:5016 bits
-----------比例因子-----------
-------声道 1-------
子带[ 1]: 10 9 9
子带[ 2]: 11 9 9
子带[ 3]: 10 9 10
子带[ 4]: 12 8 8
子带[ 5]: 10 9 9
子带[ 6]: 9 9 11
子带[ 7]: 11 9 8
子带[ 8]: 10 10 10
子带[ 9]: 10 10 9
子带[10]: 9 9 10
子带[11]: 10 9 9
子带[12]: 10 9 9
子带[13]: 8 11 10
子带[14]: 9 10 11
子带[15]: 10 8 10
子带[16]: 10 8 11
子带[17]: 9 10 10
子带[18]: 9 10 8
子带[19]: 8 10 8
子带[20]: 12 7 10
子带[21]: 9 9 9
子带[22]: 10 10 9
子带[23]: 11 11 9
子带[24]: 9 9 9
子带[25]: 12 10 9
子带[26]: 10 10 11
子带[27]: 10 10 9
子带[28]: 9 10 10
子带[29]: 10 11 8
子带[30]: 8 10 10
-------声道 2-------
子带[ 1]: 6 5 6
子带[ 2]: 12 10 9
子带[ 3]: 13 11 10
子带[ 4]: 12 13 13
子带[ 5]: 13 13 16
子带[ 6]: 15 15 14
子带[ 7]: 16 14 13
子带[ 8]: 16 17 15
子带[ 9]: 17 17 16
子带[10]: 17 18 17
子带[11]: 16 19 17
子带[12]: 17 17 17
子带[13]: 18 19 18
子带[14]: 17 19 18
子带[15]: 18 17 18
子带[16]: 17 19 17
子带[17]: 18 15 18
子带[18]: 19 19 16
子带[19]: 18 19 17
子带[20]: 17 17 18
子带[21]: 17 18 17
子带[22]: 17 17 17
子带[23]: 19 17 17
子带[24]: 16 18 17
子带[25]: 17 17 17
子带[26]: 15 15 15
子带[27]: 14 13 14
子带[28]: 14 15 14
子带[29]: 13 13 12
子带[30]: 11 12 12
-----------比特分配表-----------
-------声道 1-------
子带[ 1]: 4
子带[ 2]: 4
子带[ 3]: 3
子带[ 4]: 4
子带[ 5]: 4
子带[ 6]: 4
子带[ 7]: 3
子带[ 8]: 4
子带[ 9]: 4
子带[10]: 3
子带[11]: 4
子带[12]: 4
子带[13]: 3
子带[14]: 3
子带[15]: 3
子带[16]: 3
子带[17]: 3
子带[18]: 4
子带[19]: 2
子带[20]: 1
子带[21]: 1
子带[22]: 2
子带[23]: 2
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 2
子带[28]: 2
子带[29]: 2
子带[30]: 1
-------声道 2-------
子带[ 1]: 7
子带[ 2]: 4
子带[ 3]: 3
子带[ 4]: 4
子带[ 5]: 4
子带[ 6]: 4
子带[ 7]: 4
子带[ 8]: 4
子带[ 9]: 4
子带[10]: 3
子带[11]: 4
子带[12]: 4
子带[13]: 3
子带[14]: 3
子带[15]: 3
子带[16]: 3
子带[17]: 3
子带[18]: 4
子带[19]: 2
子带[20]: 1
子带[21]: 1
子带[22]: 2
子带[23]: 2
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 2
子带[28]: 2
子带[29]: 2
子带[30]: 1