MPEG音频编码实验
MPEG音频编码原理
感知音频编码的设计思想
-
两条线
通过子带编码可以降低可以减小量化范围,降低比特率;通过心理声学模型可以利用人耳的掩蔽效应去除冗余的数据。
子带分解模块需要向心理声学模型传输子带样值从而确定比例因子;心理声学模型通过对1024点的计算结合用于数据的码率从而确定每个子带的量化比特数。
通过这两条线实现声音的压缩算法。
-
时-频域分析的矛盾
为了使编码的时间信号具有足够高的质量,需要具有足够高的时间分辨率,这就要求每次的采样样本尽可能少;但为了在频域上的心理声学模型模型计算有足够高的分辨率,需要一次的样本长度尽可能长。为了解决这个矛盾,最终采用每个样本12点采样提高时间分辨率,通过子带拼接来提高心理声学分析的频率分辨率。对于时域上的移位频率分析上很难区分,通过从高时间分辨率的子带块提取比例因子在一定程度上弥补了这个缺点。
心理声学模型
临界频带
-
临界频带是指当某个纯音被以它为中心频率、且具有一定带 宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等 于这一频带内的噪声功率,这个带宽为临界频带宽度。 如下图所示:
频域掩蔽域随声压级变化曲线 -
人类听觉系统大致等效于一个信号通过一组并联的不同中 频率的带通滤波器,如下图所示:
掩蔽值和码率分配计算
信号掩蔽比:SMR = 信号能量 / 掩蔽阈值
算法:使整帧和每个子带的总噪声—掩蔽比最小;循环,直到没有比特可用:
◼ 噪声-掩蔽比:NMR = SMR– SNR (dB)
◼ 对最高NMR的子带分配比特,使获益最大的子带的量化级别增加一级
◼ 重新计算分配了更多比特子带的NMR
MPEG音频编码的实现
程序设计的整体框架
结构体frame_info
和 frame_header
定义了音频帧的结构,结构体bit_stream_struc
定义了上一层次音频流的结构:从中可以得到声道数、子带数、比特分配和采样率等成员信息。根据这些可以迅速找到所需的信息:
/*****************************************m2aenc.c*************************************/
```
frame_info frame;// 音频帧信息
frame_header header; //帧头信息
char original_file_name[MAX_NAME_SIZE];//源文件
char encoded_file_name[MAX_NAME_SIZE];//编码文件
short **win_buf;
static short buffer[2][1152];// 3 组/帧 x 12个样本/子带 x 32个子带/帧 = 1152个样本/帧
static unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT];// 比特分配表[声道][子带]
static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT];// 比例因子[声道][组][子带]
static double smr[2][SBLIMIT], lgmin[2][SBLIMIT], max_sc[2][SBLIMIT];
// FLOAT snr32[32];
short sam[2][1344]; /* was [1056]; */
int model, nch, error_protection;
static unsigned int crc;
int sb, ch, adb; //当前子带、声道,该帧预分配比特数
unsigned long frameBits, sentBits = 0;c
unsigned long num_samples;
int lg_frame;
int i;
```
//音频流逐帧处理
while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
```
adb = available_bits (&header, &glopts); // 计算比特预算
```
输出音频的采样率和目标码率
/*****************************************m2aenc.c*************************************/
```
#if TRACE
printf( "---------------------------------------------------------------------\n");
printf( "输入文件:%s\t", original_file_name);
printf( "输出文件:%s\n\n", encoded_file_name);
printf( "输出音频的采样率和目标码率:\n");
printf( "采样率:%f kHz\n", s_freq[header.version][header.sampling_frequency]);
printf( "目标码率:%d kbps\n", bitrate[header.version][header.bitrate_index]);
#endif
//音频流逐帧处理
while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
```
输出某个帧所分配的比特数 、比例因子 、比特分配结果
/*****************************************m2aenc.c*************************************/
```
//音频流逐帧处理
while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
```
#else
scale_factor_calc (*sb_sample, scalar, nch, frame.sblimit);
pick_scale (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 (*sb_sample, *j_sample, frame.sblimit);
scale_factor_calc (j_sample, &j_scale, 1, frame.sblimit);
}
#endif
#if TRACE
if (frameNum == 2)
{
printf("\n选择的音频帧:%d\n", frameNum);
printf("该帧所分配的比特数 :%d bits\n", adb);
printf("\n该帧的比例因子:\n");
for (ch = 0; ch < nch; ch++)
{
printf("\n%d声道:\n", ch+1);
for (sb = 0; sb < frame.sblimit; sb++)
{
printf( "子带[%d]:\t", sb + 1);
for (sbb = 0; sbb < 3; sbb++)
printf( "%d\t", scalar[ch][sbb][sb]);
printf( "\n");
}
}
printf( "\n该帧的比特分配结果:\n");
for (ch = 0; ch < nch; ch++)
{
printf("\n%d声道:\n", ch+1);
for (sb = 0; sb < frame.sblimit; sb++)
printf( "子带[%d]:\t%d\n", sb + 1, bit_alloc[ch][sb]);
}
}
#endif
```
}
```
实验结果
均采用默认参数
---------------------------------------------------------------------
输入文件:.\my_test\music.wav 输出文件:.\my_test\music_2.wav
输出音频的采样率和目标码率:
采样率:44.100000 kHz
目标码率:192 kbps
选择的音频帧:2
该帧所分配的比特数 :5016 bits
该帧的比例因子:
1声道:
子带[1]: 9 11 10
子带[2]: 14 14 14
子带[3]: 19 17 19
子带[4]: 25 23 24
子带[5]: 29 28 28
子带[6]: 23 25 23
子带[7]: 22 22 24
子带[8]: 22 22 21
子带[9]: 29 27 27
子带[10]: 30 30 32
子带[11]: 30 29 28
子带[12]: 27 28 28
子带[13]: 25 24 28
子带[14]: 26 27 23
子带[15]: 23 23 21
子带[16]: 26 23 25
子带[17]: 28 31 30
子带[18]: 30 33 31
子带[19]: 30 30 29
子带[20]: 28 29 29
子带[21]: 29 31 28
子带[22]: 32 30 30
子带[23]: 40 39 41
子带[24]: 54 50 50
子带[25]: 53 52 55
子带[26]: 55 53 54
子带[27]: 51 53 55
子带[28]: 53 53 52
子带[29]: 53 53 54
子带[30]: 53 52 52
该帧的比特分配结果:
1声道:
子带[1]: 8
子带[2]: 8
子带[3]: 6
子带[4]: 8
子带[5]: 7
子带[6]: 8
子带[7]: 8
子带[8]: 6
子带[9]: 5
子带[10]: 6
子带[11]: 6
子带[12]: 7
子带[13]: 6
子带[14]: 6
子带[15]: 6
子带[16]: 5
子带[17]: 5
子带[18]: 5
子带[19]: 4
子带[20]: 6
子带[21]: 3
子带[22]: 3
子带[23]: 0
子带[24]: 0
子带[25]: 0
子带[26]: 0
子带[27]: 0
子带[28]: 0
子带[29]: 0
子带[30]: 0
---------------------------------------------------------------------
输入文件:.\my_test\noise.wav 输出文件:.\my_test\noise_2.wav
输出音频的采样率和目标码率:
采样率:44.100000 kHz
目标码率:192 kbps
选择的音频帧:2
该帧所分配的比特数 :5016 bits
该帧的比例因子:
1声道:
子带[1]: 23 24 26
子带[2]: 23 24 23
子带[3]: 25 25 25
子带[4]: 24 26 24
子带[5]: 25 25 27
子带[6]: 23 25 23
子带[7]: 25 25 23
子带[8]: 25 24 25
子带[9]: 25 23 25
子带[10]: 22 24 23
子带[11]: 25 25 24
子带[12]: 23 24 24
子带[13]: 22 26 24
子带[14]: 23 24 25
子带[15]: 23 25 24
子带[16]: 23 22 23
子带[17]: 24 25 22
子带[18]: 24 23 24
子带[19]: 25 24 23
子带[20]: 23 24 24
子带[21]: 25 25 24
子带[22]: 25 24 24
子带[23]: 24 25 26
子带[24]: 24 25 24
子带[25]: 23 23 23
子带[26]: 24 24 22
子带[27]: 25 25 24
子带[28]: 25 24 24
子带[29]: 24 25 25
子带[30]: 22 24 25
该帧的比特分配结果:
1声道:
子带[1]: 6
子带[2]: 7
子带[3]: 6
子带[4]: 7
子带[5]: 7
子带[6]: 6
子带[7]: 6
子带[8]: 7
子带[9]: 6
子带[10]: 6
子带[11]: 6
子带[12]: 6
子带[13]: 6
子带[14]: 6
子带[15]: 6
子带[16]: 5
子带[17]: 6
子带[18]: 6
子带[19]: 5
子带[20]: 4
子带[21]: 4
子带[22]: 4
子带[23]: 4
子带[24]: 2
子带[25]: 1
子带[26]: 1
子带[27]: 1
子带[28]: 1
子带[29]: 1
子带[30]: 0
---------------------------------------------------------------------
输入文件:.\my_test\music+noise.wav 输出文件:.\my_test\music+noise_2.wav
输出音频的采样率和目标码率:
采样率:44.100000 kHz
目标码率:192 kbps
选择的音频帧:2
该帧所分配的比特数 :5016 bits
该帧的比例因子:
1声道:
子带[1]: 9 11 10
子带[2]: 14 14 14
子带[3]: 18 17 19
子带[4]: 21 22 22
子带[5]: 24 24 24
子带[6]: 22 22 22
子带[7]: 20 22 26
子带[8]: 20 21 19
子带[9]: 23 22 24
子带[10]: 24 24 25
子带[11]: 24 22 22
子带[12]: 23 25 23
子带[13]: 22 23 23
子带[14]: 22 22 23
子带[15]: 23 23 20
子带[16]: 22 22 25
子带[17]: 22 26 24
子带[18]: 25 27 24
子带[19]: 24 23 23
子带[20]: 23 26 23
子带[21]: 23 23 23
子带[22]: 26 25 25
子带[23]: 23 24 25
子带[24]: 25 26 24
子带[25]: 24 25 24
子带[26]: 25 25 25
子带[27]: 23 25 22
子带[28]: 23 24 23
子带[29]: 25 24 26
子带[30]: 26 25 24
该帧的比特分配结果:
1声道:
子带[1]: 8
子带[2]: 7
子带[3]: 6
子带[4]: 7
子带[5]: 7
子带[6]: 7
子带[7]: 7
子带[8]: 6
子带[9]: 6
子带[10]: 6
子带[11]: 6
子带[12]: 6
子带[13]: 6
子带[14]: 6
子带[15]: 6
子带[16]: 5
子带[17]: 6
子带[18]: 5
子带[19]: 5
子带[20]: 4
子带[21]: 4
子带[22]: 5
子带[23]: 4
子带[24]: 1
子带[25]: 1
子带[26]: 1
子带[27]: 1
子带[28]: 1
子带[29]: 0
子带[30]: 0
可以看到对于噪声来说尽管各个子带的缩放因子几乎相同,但根据心理声学模型,在不失真的条件下仍能够压缩到不错的程度。
上一篇: 随机信号的参数建模法( AR 模型)
推荐阅读
-
第一部分day4-三次登录实验、字符编码
-
AVI MPEG WMV RM to MP3 Converter(音频视频转换为MP3)如何提取视频文件中的音频
-
音频压缩编码 opus 附完整C++代码示例
-
“软件工程(C编码实践篇)”实验报告【实验五:用callback增强链表模块来实现命令行菜单小程序V2.8】
-
“软件工程(C编码实践篇)”实验报告【实验三:内部模块化的命令行菜单小程序V2.0】
-
数据压缩实验六 MPEG音频压缩编码
-
MPEG音频编码实验
-
android 音频采集、FLTP重采样与AAC编码推流
-
【学习图像处理】之实验四——图像编码之LZW编码
-
MPEG音频编码实验(输出音频的采样率和目标码率;选择某个数据帧,输出)