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”文件。