文章目录
一、实验要求
1.理解程序设计的整体框架
2.理解感知音频编码的设计思想
· 两条线
· 时、频分析的矛盾!
3.理解心理声学模型的实现过程
· 临界频带的概念
· 掩蔽值计算的思路
4.理解码率分配的实现思路
5.输出音频的采样率和目标码率
6.选择三个不同特性的音频文件
· 噪声(持续噪声、突发噪声)
· 音乐
· 混合
7.某个数据帧,输出
· 该帧所分配的比特数
· 该帧的比例因子
· 该帧的比特分配结果
二、实验内容
1.整体框架
1.MPEG的编码原理
- 输入PCM码流,采样率为32,44.1或48kHz
- 输出为32kbps到384kbps
2.多相滤波器组
· 将PCM样本变换到32个子带的频域信号。
2.设计思想
* 基于人的生理和心理感知特性(心理声学模型),分析信号,对不被感知的部分不编码。
* 声音压缩算法可以确立这种特性的模型来取消更多的冗余数据。
1.两条线
- 上支线:子带分解考虑时域。子带分析滤波器组使信号具有高的时间分辨率,确保在短暂冲击信号情况下,编码的声音信号具有足够高的质量。
- 下支线:FFT和心理声学模型考虑频域。信号通过FFT运算具有高的频率分辨率,因为掩蔽阈值是从功率谱密度推出来的。
- 上支线为下支线的心理声学模型提供比例因子;下支线为上支线的量化器提供比特分配。
2.时频矛盾
由于傅里叶变换的缺陷,变换结果只表示了信号中存在哪些频率,并不能表示某个频率出现的时间,如果时域上不同时刻出现尖峰,在频域上看两者是一样的。
3.心理声学模型
1.模型原理
- 人耳的听觉系统中存在一个听觉阈值电平,低于这个电平的声音信号就听不到。
- 听觉阈值的大小随声音频率的改变而改变。
- 一个人是否听到声音取决于声音的频率,以及声音的幅度是否高于这种频率下的听觉阈值
- 人耳具有听觉掩蔽特性,人耳感知的听觉阈值电平是自适应的,会随听到的不同频率声音而发生变化
2.临界频带
- 定义:当某个纯音被以他为中心频率且具有一定带宽的连续噪声掩蔽时,若该纯音刚好被听到时的功率等于频带内的噪声功率,这个带宽就是临界频带宽度。
PS:人耳听觉系统
- 如图,人耳听觉系统大致等效于一个信号通过一组并联的不同中心频率的带通滤波器。在0Hz到20kHz频率范围内由25个重叠的带通滤波器组成的滤波器组。听者在噪声中听某一纯音时,只启用中心频率与信号频率相同的那个听觉滤波器,而噪声信号只有通带范围内的部分信号能通过,其余频率成分被抑制。
3.听觉阈值
-
两个声音响度级相同,但强度不一定相同,还与频率有关(图中密密麻麻的线,属于等响度曲线,同一条线上的响度级相同。观察同一条曲线上的两点,其强度不一定相同)
-
声压级越高,等响度曲线趋于平坦
4.掩蔽效应
如图所示,高强度的纯音会掩蔽到该纯音频率附近的声音,也就是说会使该频率附近的听阈阈值提高,因此考虑到掩蔽效应,可以更多的减少需要编码的部分。
5.乐声与噪声
- 如图所示,左图听阈Threshold高于右图,所以噪声掩蔽比乐声强;
在心理声学模型中,根据⾳频频谱的局部功率最⼤值确定乐⾳成分局部峰值为乐⾳,然后将本临界频带内的剩余频谱合在⼀起,组成⼀个代表噪声频率(⽆调成份)
6.音调和非音调掩蔽成分的消除
利用标准中给出的绝对阈值消除被掩蔽成分,考虑在每个临界频带内,小于0.5bark的距离中只保留最高功率的成分
7.单个掩蔽阈值的计算
音调成分和非音调成分单个掩蔽阈值根据标准中的算法求得
8.全局掩蔽阈值的计算
- 还要考虑其他临界频带的影响,因为一个掩蔽信号会对其他频带上的信号产生掩蔽效应
9.每个子带的掩蔽阈值
选择出本⼦带中最⼩的阈值作为⼦带阈值对⾼频不正确——⾼频区的临界频带很宽,可能跨越多个⼦带,从⽽导致模型1将临界带宽内所有的⾮⾳调部分集中为⼀个代表频率,当⼀个⼦带在很宽的频带内却远离代表频率时,⽆法得到准确的⾮⾳调掩蔽值。但计算量低。
10.选择出本⼦带中最⼩的阈值作为⼦带阈值
计算每个⼦带信号掩蔽⽐(signal-to-maskratio, SMR)
● SMR = 信号能量 / 掩蔽阈值
并将SMR传递给编码单元
4.码率分配
A.LayerⅠ编码
1.在调整到固定的码率之前
- 先确定可⽤于样值编码的有效⽐特数
- (这个数值取决于⽐例因⼦、⽐例因⼦选择信息、⽐特分配信息以及辅助数据所需⽐特数)
⽐特分配的过程
对每个⼦带计算掩蔽-噪声⽐MNR,是信噪⽐SNR–信掩⽐SMR
- MNR = SNR–SMR
- NMR=SMR-SNR
2.算法:使整帧和每个⼦带的总噪声—掩蔽⽐最⼩
- 计算噪声-掩蔽⽐(noise-to-mask ratio, NMR):NMR = SMR – SNR (dB)
其中 SNR 由MPEG-I标准给定 (为量化⽔平的函数) / NMR:表示波形误差与感知测量之间的误差
循环,直到没有可用比特为止
3.装帧
B.LayerⅡ编码
1.概述:与Layer I类似,但对Layer I有增强
- 装帧、缩放因⼦表示、量化
缩放因⼦(⽐例因⼦)⼀般从低频⼦带到⾼频⼦带出现连续下降
- 帧:3 组/帧 x 12个样本/⼦带 x 32个⼦带/帧 = 1152个样本/帧
2.量化
根据采样和码率量化,不同⼦带可以从不同的量化器集合中选择
- 某些(⾼频)⼦带的⽐特数可能为0
对量化级别在3、5、9级时,采⽤“颗粒” 优化
- 颗粒= 3 个样本,根据颗粒选择量化⽔平
3.装帧
三、实验内容
1.输出音频的采样率和目标码率
- 采样率:44.1khz
- 目标码率:bitrate=192.000kbps
2.关键代码分析
- ①输出音频的采样率和目标码率
#if FRAME_TRACE
FILE* output;
output = fopen("output.txt", "a");
fprintf(output, "========== 基本信息 ==========\n");
fprintf(output, "输入文件:%s\n", inPath);
fprintf(output, "输出文件:%s\n", outPath);
fprintf(output, "采样频率:%.1f kHz\n", s_freq[header->version][header->sampling_frequency]);
fprintf(output, "目标码率:%d kbps\n", bitrate[header->version][header->bitrate_index]);//输出文件码率
fclose(output);
#endif // FRAME_TRACE
- ②输出某个数据帧所分配的比特数、比例因子和比特分配结果
#if FRAME_TRACE
FILE* output;
output = fopen("output.txt", "a");
if (frameNum == 2) {
fprintf(output, "声道数:%d\n", nch);
fprintf(output, "目前观测第 %d 帧\n", frameNum);
fprintf(output, "本帧比特预算:%d bits\n", adb);
fprintf(output, "\n");
fprintf(output, "========== 比例因子 ==========\n");
for (ch = 0; ch < nch; ch++) // 每个声道单独输出
{
fprintf(output, "------ 声道%2d ------\n", ch + 1);
for (sb