数据压缩实验六 MPEG音频压缩编码
一、实验原理
1. MPEG-1声音的主要性能
输入为PCM信号,采样率为32,44.1或48kHz,输出为 32kbps到384kbps。
2. MPEG音频编码主要流程
三个独立的压缩层次
Layer1:编码器最简单,384kbps(4:1, 用于小型数字盒带DCC,Compact Cassette)
Layer2:编码器复杂程度中等,256kbps~192kbps(6: 1~8:1, 用于DAB、CD-I和VCD)
Layer3:编码器最为复杂,64kbps,用于ISDN,网络 音频。
MPEG音频编码为同时获得较高的时域精准度与频域精准度,对信息分两条线即时域和频域分别处理,在综合获得最终结果。通过子带分析滤波器组使信号具有高的时间 分辨率,确保在短暂冲击信号情况下,编码 的声音信号具有足够高的质量; 使信号通过FFT运算具有高的频率分辨率,因为掩蔽阈值是从功率谱密度推出来的。流程图如下:
声音压缩算法属于感知编码,可以确立心理声学特性的模型来取消更 多的冗余数据。
3.心理声学模型 :
1.听觉系统中存在一个听觉阈值电平,低于这个电平的声 音信号就听不到 。听觉阈值的大小随声音频率的改变而改变,一个人是否听到声音取决于声音的频率,以及声音 的幅度是否高于这种频率下的听觉阈值 。
2.听觉掩蔽特性。即听觉阈值电平是自适应的,会随听到的不同频率声音而发生变化 。
4.频域掩蔽域随声压级变化曲线:
5.32个子带滤波器组:
通过子带分析滤波器组使信号具有高的时间分辨率,确保在短暂冲击信号情况下,编码的声音信号具有足够高的质量。将PCM样本变换到32个子带的频域信号:如果输入的采样频率为48kHz ,那么子带的频率宽度为48/ (2*32 )=0.75Hz
该多相滤波器组为如下图:
6.比例因子的取值和编码:
对各个子带每12个样点进行一次比例因子计算。先定出12个 样点中绝对值的最大值。查比例因子表中比这个最大值大的 最小值作为比例因子。用6比特表示。
第2层的一帧对应36个子带样值,是第1层的三倍,原 则上要传三个比例因子。为了降低比例因子的传输码率, 采用了利用人耳时域掩蔽特性的编码策略:
每帧中每个子带的三个比例因子被一起考虑,划分成 特定的几种模式。根据这些模式,1个、2个或3个比例因 子和比例因子选择信息(每子带2比特)一起被传送。如 果一个比例因子和下一个只有很小的差别,就只传送大 的一个,这种情况对于稳态信号经常出现。
使用这一算法后,和第1层相比,第2层传输的比例因 子平均减少了2个,即传输码率由22.5Kb/s降低到了 7.5Kb/s。
7.比特分配及编码:
在调整到固定的码率之前先确定可用于样值编码的有效比特数。这个数值取决于比例因子、比例因子选择信息、比特分配信息 以及辅助数据所需比特数 。
比特分配的过程 :
1、对每个子带计算掩蔽-噪声比MNR,MNR = SNR –SMR (dB)
2、对最低MNR的子带分配比特,使获益最大的子带的量化级别增加一级
3、重新计算分配了更多比特子带的MNR
循环,直到没有比特可用。使整帧和每个子带的总噪声—掩蔽比最小。第1层一帧用4比特给每个子带的比特分配信 息编码;而第2层只在低频段用4比特,高频 段则用2比特。
8.子带样值的量化和编码:
(1)输入以12个样本为一组,每组样本经过时间-频率变换 之后进行一次比特分配并记录一个比例因子(scale factor)
(2)比特分配信息告诉解码器每个样本由几位表示,比例因子用6比特表示,解码器使用这个6比特的比例因子乘逆量化器的每个输出样本值,以恢复被量化的子带 值。比例因子的作用是充分利用量化器的量化范围, 通过比特分配和比例因子相配合,可以表示动态范围超过120dB的样本。
(3)第2层中,量化级别的数目随子带的不同而不同,但量化等级仍然覆盖了3~65535的范围,同时子带不被分配给比特的概率增加了,没有分配给比特的子带就不被量化。低频段的量化等级有15级,中频段7级,高频段只有3级。
二、关键代码分析
实验流程一再原理部分中说明,下面直接分析关键代码。
#ifdef NEWENCODE
sf_transmission_pattern (scalar, scfsi, &frame);
main_bit_allocation_new (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
//main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
if (error_protection)
CRC_calc (&frame, bit_alloc, scfsi, &crc);
write_header (&frame, &bs);
//encode_info (&frame, &bs);
if (error_protection)
putbits (&bs, crc, 16);
write_bit_alloc (bit_alloc, &frame, &bs);
//encode_bit_alloc (bit_alloc, &frame, &bs);
write_scalefactors(bit_alloc, scfsi, scalar, &frame, &bs);
//encode_scale (bit_alloc, scfsi, scalar, &frame, &bs);
subband_quantization_new (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
*subband, &frame);
//subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
// *subband, &frame);
write_samples_new(*subband, bit_alloc, &frame, &bs);
//sample_encoding (*subband, bit_alloc, &frame, &bs);
#else
/*add by Alfred*/
if(frameNum==200)
{
int k,t,i;
fprintf(result,"采样率=%.1f khz\n",s_freq[header.version][header.sampling_frequency]);
fprintf(result,"目标码率=%d kbps\n", bitrate[header.version][header.bitrate_index]);
fprintf(result,"第%d帧\n",frameNum);
fprintf(result,"可用比特数=%d\n",adb);
fprintf(result,"比例因子:\n");
for(k=0;k<nch;k++)
{
fprintf(result,"声道[%d]\n",k);
for(i=0;i<frame.sblimit;i++)
{
fprintf(result,"子带[%d]:",i);
for(t=0;t<3;t++)
{
fprintf(result,"%d\t",scalar[k][t][i]);
}
fprintf(result,"\n");
}
}
}
/*end by Alfred*/
transmission_pattern (scalar, scfsi, &frame);
main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
/*add by Alfred*/
if(frameNum==200)
{
int k,i;
fprintf(result,"比特分配:\n");
for(k=0;k<nch;k++)
{
fprintf(result,"声道[%d]\n",k);
for(i=0;i<frame.sblimit;i++)
{
fprintf(result,"子带[%d]:%d\n",i,bit_alloc[k][i]);
}
}
}
/*end by Alfred*/
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
三、实验结果
输出一个“.txt”文件。
下一篇: 概率机器人总结——粒子滤波先实践再推导