MPEG编码原理解释
两条主线
第一条线:通过子带分析滤波器组使信号具有高的时间分辨率,确保在短暂冲击信号情况下,编码的声音信号具有足够高的质量。
第二条线:使信号通过FFT运算具有高的频率分辨率,计算信号中不可听觉感知的部分,即计算信号的掩蔽阈值,信掩比SMR,第二条线是重点。
矛盾点
频域分解力分得很细,但到了子带却映射到很粗的范围上,即按临界频带去分析,在临界频带内分析,每个临界频带得到掩蔽阈值,最后又要返回到32个子带中去,一个子带又可能跨越好几个临界频域。
临界频带
临界频带表征了人类最主要的听觉特性,在纯音对窄带噪声掩蔽量的规律中,掩蔽量刚开始时随着噪声带宽的加宽而增大,但带宽超过某一定值后,掩蔽量就不再增加,这一带宽就称为临界频带。
掩蔽值的计算
音调成分和非音调成分单个掩蔽阈值根据标准中给出的算法求得,每个子带再选出本子带中最小的阈值作为子带阈值,再计算每个子带信掩比SMR,将SMR传给编码单元进行码率分配。
码率分配
为了使整帧和每个子带的总噪声—掩蔽比(NMR)最小,其中NMR = SMR – SNR,循环此过程:计算NMR,为NMR较大的子带分配更多比特,使获益最大的子带的量化级别增加一级。直到没有多余的bit可分配
程序修改
我们仿照上一个实验,在m2aenc.h文件中添加一个trace。
在主函数中进行变量的追踪查看
#if TRACE
if (frameNum == 64) {
fprintf(p_trace, "采样率:%.1f kHz\n", s_freq[header.version][header.sampling_frequency]);
fprintf(p_trace, "目标码率:%d kbps\n", bitrate[header.version][header.bitrate_index]);
// 所分配的比特数
fprintf(p_trace, "该帧分配的比特数为:%d\n", adb);
fprintf(p_trace, "-------------------------------------------------------------\n");
// 比例因子
fprintf(p_trace, "比例因子\n");
fprintf(p_trace, "-------------------------------------------------------------\n");
for (ch = 0; ch < 2; ch++) {
fprintf(p_trace, "声道%d:\n", ch + 1);
for (sb = 0; sb < 32; sb++) {
fprintf(p_trace, "子带%d: %d %d %d\n", sb + 1, scalar[ch][0][sb], scalar[ch][1][sb], scalar[ch][2][sb]);
}
fprintf(p_trace, "-------------------------------------------------------------\n");
}
// 比特分配
fprintf(p_trace, "比特分配\n");
fprintf(p_trace, "-------------------------------------------------------------\n");
for (ch = 0; ch < 2; ch++) {
fprintf(p_trace, "声道%d:\n", ch + 1);
for (sb = 0; sb < 32; sb++) {
fprintf(p_trace, "子带%2d: %d\n", sb + 1, bit_alloc[ch][sb]);
}
fprintf(p_trace, "-------------------------------------------------------------\n");
}
fflush(p_trace);
}
#endif
乐音
噪音
我们由matlab产生噪音,噪音和乐音的混合
clear
clc
%% 读取音频信号
[audio,fs] = audioread("D:\D3xia_experiment\shujuyasuo\START.wav");
audio = audio(:,1);%取单声道
%% 生成白噪声
noise = randn(1,length(audio));
%% 输出白噪声
audiowrite('noise.wav',noise,fs);
%% 输出混合音频
mix = awgn(audio,40);
audiowrite('mix.wav',mix,fs);