MPEG音频编码实验(输出音频的采样率和目标码率;选择某个数据帧,输出)
MPEG-1 Audio LayerII编码器原理
MPEG-I 心理声学模型
◼ 通过子带分析滤波器组使信号具有高的时间分辨率,确保在短暂冲击信号情况下,编码 的声音信号具有足够高的质量
◼ 又可以使信号通过FFT运算具有高的频率分 辨率,因为掩蔽阈值是从功率谱密度推出来 的。
◼ 在低频子带中,为了保护音调和共振峰的结 构,就要求用较小的量化阶、较多的量化级 数,即分配较多的位数来表示样本值。而话 音中的摩擦音和类似噪声的声音,通常出现 在高频子带中,对它分配较少的位数
MPEG-1音频编码器框架图
◼ 多相滤波器组(Polyphase Filter Bank):将 PCM样本变换到32个子带的频域信号 如果输入的采样频率为48kHz,那么子带的频率 宽度为48/(2*32)=0.75Hz
◼ 心理声学模型(Psychoacoustic Model):计算 信号中不可听觉感知的部分
计算噪声遮蔽效应
心理声学模型I
◼ 1、将样本变换到频域
32个等分的子带信号并不能精确地反映人耳的听觉特性。 引入FFT补偿频率分辨率不足的问题。 采用Hann加权和DFT
Hann加权减少频域中的边界效应
此变换不同于多相滤波器组,因为模型需要更精细 的频率分辨率,而且计算掩蔽阈值也需要每个频率 的幅值
模型1:采用512 (Layer I) 或1024 (Layers II and III)样本窗口
Layer I:每帧384个样本点,512个样本点足够覆盖
Layer II 和Layer III:每帧1152个样本点,每帧两次 计算,模型1选择两个信号掩蔽比(SMR)中较小的 一个
◼ 2、确定声压级别
◼ 3、考虑安静时阈值 也即绝对阈值。在标准中有根据输入PCM信号的采 样率编制的“频率、临界频带率和绝对阈值”表。 此表为多位科学家经多次心理声学实验所得。
◼ 4、将音频信号分解成“乐音(tones)” 和“非乐音/噪声” 部分:因为两种信号的掩蔽能力不同
◼ 5、音调和非音调掩蔽成分的消除 利用标准中给出的绝对阈值消除被掩蔽成分; 考虑在每个临界频带内,小于0.5Bark的距离 中只保留最高功率的成分
◼ 6、单个掩蔽阈值的计算 音调成分和非音调成分单个掩蔽阈值根据标 准中给出的算法求得
◼7、全局掩蔽阈值的计算
◼ 8、每个子带的掩蔽阈值
选择出本子带中最小的阈值作为子带阈值
对高频不正确——高频区的临界频带很宽, 可能跨越多个子带,从而导致模型1将临界带 宽内所有的非音调部分集中为一个代表频率, 当一个子带在很宽的频带内却远离代表频率 时,无法得到准确的非音调掩蔽值。但计算 量低。
◼ 9、计算每个子带信号掩蔽比(signal-to-mask ratio, SMR)
SMR = 信号能量 / 掩蔽阈值 , 并将SMR传递给编码单元
◼ 比特分配器(Bit Allocator):根据心理声学模 型的计算结果,为每个子带信号分配比特数
◼ 装帧(Frame Creation):产生MPEG-I兼容的 比特流
实验要求
理解程序设计的整体框架;
将PCM码流分成两条线进行处理,一条经多项滤波器组划分为32个子带,每个子带有12个样点,对每个子带计算一次比例因子,用来确定量化器。另一条线对PCM信号进行FFT,由心理声学模型计算以频率为自变量的掩噪比。使量化噪声小于掩蔽域值。由心理声学模型确定比例因子选择信息和动态比特分配,决定一个子带分配多少比特。最后通过帧包装将量化自带的样本和其他数据(采样率,比特率,比例因子信息,动态比特分配信息)组装成比特流。
理解感知音频编码的设计思想:两条线、时频分析的矛盾
两条线:
第一条线:心理声学模型:以临界频带为分析单位,分析的横坐标是频率。谱线间隔越小越好。
第二条线:信号的短时相关性,时域越短越好,这样能抓住瞬时变化率。
时频分析的矛盾:频域的频谱分辨率和时域的变化率是一对矛盾,时域信号取得越短,频域谱线间隔越大。
理解心理声学模型实现的过程:临界频带的概念;掩蔽值计算的思路
临界频带是指当某个纯音被以它为中心频率,且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽为临界频带的宽度。
掩蔽值计算:
单个掩蔽域值:乐音和非乐音掩蔽域值
全局掩蔽域值:某一频率点的掩蔽阈值等于该点的绝对掩蔽阈值与的那个掩蔽域值相加
每个子带的掩蔽域值:选出这个子带内最小的阈值作为该子带阈值
理解码率分配的实现思路
使整帧和整个子带的总噪声掩蔽比最小:MNR(掩噪比)=SNR(信噪比)-SMR(信掩比)
对最低的MNR的子带分配比特,使获益最大的子带量化级数级别增加一级,重新计算分配了更多比特的MNR
输出音频的采样率和目标码率
◼ 输出音频的采样率和目标码率
◼ 选择某个数据帧,输出
该帧所分配的比特数
该帧的比例因子
该帧的比特分配结果
在m2aenc.c的main函数中
定义相关变量,及输出文件
int main (int argc, char **argv)
{
/*****add by csy*****/
int cha;//声道
int sbd;//子带
int gro;//组
FILE *outinfo = fopen("output.txt", "wb");
/*****add end*****/
。。。。。。。
选取第二帧
#else
/*****add by csy*****/
if(frameNum==2)
{
fprintf(outinfo,"采样率:%.1fkhz\n",s_freq[header.version][header.sampling_frequency]);
fprintf(outinfo,"目标码率:%dMbps\n",bitrate[header.version][header.bitrate_index]);
fprintf(outinfo,"第2帧所用比特数:%d\n",adb);
}
/******add end******/
transmission_pattern (scalar, scfsi, &frame);
main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
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);
/*****add by csy*****/
if(frameNum==2)
{
fprintf(outinfo,"比例因子\n");
for ( cha = 0; cha < nch; cha++ )//声道
{
fprintf(outinfo,"声道%d\n",cha);
fprintf(outinfo,"子带\t组1\t组2\t组3\t\n");
for ( sbd = 0; sbd < frame.sblimit; sbd++ )//子带
{
fprintf(outinfo,"%4d\t",sbd);
for( gro = 0; gro < 3; gro++ )//组
{
fprintf(outinfo,"%3d\t",scalar[cha][gro][sbd]);
}
fprintf(outinfo,"\n");
}
}
fprintf(outinfo,"帧比特分配:\n");
for ( cha = 0; cha < nch; cha++ )//声道
{
fprintf(outinfo,"声道%d\n",cha);
for ( sbd = 0; sbd < frame.sblimit; sbd++ )//子带
{
fprintf(outinfo,"子带%2d:\t",sbd);
fprintf(outinfo,"%2d\n",bit_alloc[cha][sbd]);
}
}
if(outinfo)
fclose(outinfo);
}
/******add end*****/
结果
输出文件
输出音频的采样率和目标码率
输出第二帧所分配的比特数
输出第二帧的比例因子
输出第二帧的比特分配结果