实验原理
音频编码的核心:心理声学模型。
子带编码:将原始信号分解为若干个子频带,对其分别进行编码处理后再合成为全频带信号。
人的感知特性:掩蔽(强音会屏蔽旁音的听域)。掩蔽可以分为四种情况:乐音对噪声的掩蔽,乐音对乐音的掩蔽,噪声对乐音的掩蔽,噪声对噪声的掩蔽。
频域掩蔽域随声压级变化曲线
音频输入源频率多样,每一个频率的声音都会有一个屏蔽曲线,上图仅仅是1kHZ的乐音如何屏蔽。问题在于如何分割频带,如何合成各个新的屏蔽曲线。于是引入临界频带,人耳频带被称为临界频带。由于人耳不能区分同一频带内同时发生的不同声音,并且掩蔽效应在临界频带内不会大起大伏,比较稳定。通常认为从20Hz到16kHz有25个临界频带,单位为bark,1 Bark = 一个临界频带的宽度 。心理声学模型进行数据分析的基本处理单位就是临界频带。掩蔽音和被掩蔽音的组合方式分四种:乐音对噪声的掩蔽,乐音对乐音的掩蔽,噪声对乐音的掩蔽,噪声对噪声的掩蔽。掩蔽效应有以下特点:乐音掩盖其他音的能力较弱,噪音掩盖其他音的能力较强;掩蔽时,对本身频率略高的频率掩蔽效果比对本身频率略低的掩蔽效果更好。一段声音由主频率与次要频率组成,最后的掩蔽曲线由所有频率的掩蔽曲线整合。
音乐与语音信号由一系列复杂的频谱分量构成 ,相应的这些多个掩蔽分量也会相互影响并最终获得一个整体的掩蔽阈值。对于多个掩蔽分量的综合掩蔽效果,目前有多种模型给出了描述方案 。Lutfi对多个掩蔽音同时存在时的综合掩蔽效果进行了研究:每个掩蔽音的掩蔽效果先独立变换然后再线性相加。
问题:综合掩蔽效果与各掩蔽信号的声音级以及掩蔽信号的个数都有关系。如何整合掩蔽音?
1. 当两个信号重叠并落在一个临界频带中时,二者的掩蔽分量可以线性相加。
2. 对于复杂音频信号可将其频谱分割成一系列离散段,每段就是一个掩蔽信号。各掩蔽音互不重叠,即以一个临界带为单位。各掩蔽音的声压级则通过将对应的临界频带上的短时功率谱密度线性相加得到。
对声音进行快速傅里叶变换FFT,频域的谱线越细越好。由于短时相关性,前后的相关的样本不能过多,才能抓住前后样本之间的瞬时关系。要提高时域的分解力,必须牺牲频域分解力,这就是时域和频域的矛盾所在。最后量化都是用一个量化表(查表)。最后输出帧包含信息:1、比特分配信息。2.比例因子信息。3.子带量化以后的量化样本。时域的高可变性,对应频域的高相关性,因此对频域信号可以预测。若信号比较平缓,比例因子查表,比例因子大小差不多,找到比最大值大的最小值,用2bit表示比例因子公用信息:00代表三个信号公用一个比例因子,01代表前两个信号用一个比例因子,10代表后两个信号公用一个比例因子,11代表三个信号用不同的比例因子。用32个带通滤波器,把音频分为32个子带。其中,每一个带通滤波器都由低通滤波器的调制得到。
输入声音信号经过一个多相滤波器组,变换到多个子带。同时经过“心理声学模型”计算以频率为自变量的噪声掩蔽阈值。量化和编码部分用信掩比SMR决定分配给子带信号的量化位数,使量化噪声<掩蔽域值。最后通过数据帧包装将量化的子带样本和其它数据按照规定的帧格式组装成比特数据流。
1.多相滤波器组(Polyphase Filter Bank):将PCM样本变换到32个子带的频域信号,如果输入的采样频率为48kHz,那么子带的频率宽度为48/(2*32)=0.75Hz
一个人是否听到声音取决于声音的频率,以及声音的幅度是否高于这种频率下的听觉阈值。听觉掩蔽特性即听觉阈值电平是自适应的,会随听到的不同频率声音而发生变化。
先确定可用于样值编码的有效比特数,这个数值取决于比例因子、比例因子选择信息、比特分配信息以及辅助数据所需比特数。
*比特分配的过程
对每个子带计算掩蔽-噪声比MNR,即:MNR = SNR –SMR 其中SNR是信噪比 ,SMR是信掩比;对最低MNR的子带分配比特,使获益最大的子带的量化级别增加一级;重新计算分配了更多比特子带的MNR,循环,直到没有比特可用。
代码分析
m2aenc.c
int main (int argc, char **argv)
{...//add 7.1
FILE *output;
char temp[50] = "frame_infomation.txt";
output = fopen(temp, "w");
if (output == NULL)
{
printf("Creating output txt file failed.\n");
exit(1);
}
//end
......
#else
//add 7.1
if(frameNum==50)
{
fprintf(output,"sampling rate=%.1f khz\n",s_freq[header.version][header.sampling_frequency]);
fprintf(output,"bits rate=%d kbps\n", bitrate[header.version][header.bitrate_index]);
fprintf(output,"the %d frame\n",frameNum);
fprintf(output,"available bits num=%d\n",adb);
fprintf(output,"scale factors:\n");
for(k=0;k<nch;k++)
{
fprintf(output,"channel[%d]\n",k);
for(i=0;i<frame.sblimit;i++)
{
fprintf(output,"subband[%d]:",i);
for(t=0;t<3;t++)
{
fprintf(output,"%d\t",scalar[k][t][i]);
}
fprintf(output,"\n");
}
}
}
//add end
transmission_pattern (scalar, scfsi, &frame);
main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
//add 7.1
if(frameNum==50)
{
int k,i;
fprintf(output,"bits allocation:\n");
for(k=0;k<nch;k++)
{
fprintf(output,"channel[%d]\n",k);
for(i=0;i<frame.sblimit;i++)
fprintf(output,"subband[%d]:%d\n",i,bit_alloc[k][i]);
}
}
//add end
if (error_protection)
CRC_calc (&frame, bit_alloc, scfsi, &crc);
encode_info (&frame, &bs);
if (error_protection)
encode_CRC (crc, &bs);
encode_bit_alloc (bit_alloc, &frame, &bs);
encode_scale (bit_alloc, scfsi, scalar, &frame, &bs);
subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
*subband, &frame);
sample_encoding (*subband, bit_alloc, &frame, &bs);
#endif
实验结果