一、实验目的
理解程序设计的整体框架,理解感知音频编码的设计思想,理解心理声学模型的实现过程,理解码率分配的实现思路。
二、实验要求
输出音频的采样率和目标码率,选择三个不同特性的音频文件分析,输出某帧所分配的比特数、比例因子、比特分配结果。
三、实验原理
主要原理框图
32个子带滤波器组:
通过子带分析滤波器组使信号具有高的时间分辨率,确保在短暂冲击信号情况下,编码的声音信号具有足够高的质量。
将PCM样本变换到32个子带的频域信号:如果输入的采样频率为48kHz ,那么子带的频率宽度为48/ (2*32 )=0.75Hz
该多相滤波器组为如下图:
心理声学模型
听觉系统中存在一个听觉阈值电平,低于这个电平的声音信号就听不到。
- 听觉阈值的大小随声音频率的改变而改变
- 一个人是否听得到声音取决于声音的频率以及声音的幅度是否高于这种频率下的听觉阈值。
临界频带:临界频带是指当某个纯音被以它为中心频率、且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽为临界频带带宽。
掩蔽阈值:
- 单个掩蔽阈值的计算
音调成分和非音调成分单个掩蔽阈值根据标准中给出的算法求得。 - 全局掩蔽阈值的计算
四、实验代码
声明全局变量
#define AudioTrace 1 // 为 1 时执行打开 TraceInfo 文件以输出数据帧信息
FILE* TraceInfo; // 定义输出文件的全局变量
所添加的片段
#if AudioTrace
fopen_s(&TraceInfo,"TraceInfo.txt","wb");
if (frameNum == 2)
{
/* 比例因子 */
fprintf(TraceInfo, "========== 比例因子 ==========\n");
for (ch = 0; ch < nch; ch++) // 每个声道单独输出, ch 为当前声道,nch 为总声道数
{
fprintf(TraceInfo, "------ 声道%d ------\n", ch + 1);
for (sb = 0; sb < frame.sblimit; sb++) // sb 为每个子带,sblimit 为总子带数
{
fprintf(TraceInfo, "子带[%d]:\t", sb + 1);
for (int gr = 0; gr < 3; gr++) //gr 为三个分组
{
fprintf(TraceInfo, "%d\t", scalar[ch][gr][sb]);
}
fprintf(TraceInfo, "\n");
}
}
fprintf(TraceInfo, "\n");
/* 比特分配表 */
fprintf(TraceInfo, "========== 比特分配表 ==========\n"); //输出比特分配结果
for (ch = 0; ch < nch; ch++)
{
fprintf(TraceInfo, "------ 声道%d ------\n", ch + 1); //按声道分配
for (sb = 0; sb < frame.sblimit; sb++)
{
fprintf(TraceInfo, "子带[%d]:\t%d\n", sb + 1, bit_alloc[ch][sb]);
}
fprintf(TraceInfo, "\n");
}
}
/********** end **********/
#endif // AudioTrace
if (frame.actual_mode == MPG_MD_JOINT_STEREO) {
...