一、MPEG-1 Audio LayerII编码器原理
二、MPEG-1音频编码器框架
多相滤波器组(Polyphase Filter Bank):将PCM样本变换到32个子带的频域信号
如果输入的采样频率为48kHz,那么子带的频率宽度为48/(2*32)=0.75Hz
缺点:
等带宽的滤波器组与人类听觉系统的临界频带不对应
◼ 在低频区域,单个子带会覆盖多个临界频带。在这种情况下,量化比特数不能兼每个临界频带
滤波器组与临界频带比较:
一个子带的频率响应:
滤波器组与其逆过程不是无失真的
◼ 但滤波器组引入的误差差很小,且听不到
子带间频率有混叠
◼ 滤波后的相邻子带有频率混叠现象,一个子带中的信号可以影响相邻子带的输出
混叠:一个单频正弦信号输入可能在两个子带中产生非零信号
心理声学模型(Psychoacoustic Model):计算信号中不可听觉感知的部分
计算噪声遮蔽效应
MPEG-I 标准定义了两个模型
◼ 心理声学模型1:
计算复杂度低
但对假设用户听不到的部分压缩太严重
将音频信号分解成“乐音(tones)” 和“非乐音/噪声”部分:因为两种信号的掩蔽能力不同
模型1:根据音频频谱的局部功率最大值确定乐音成分
局部峰值为乐音,然后将本临界频带内的剩余频谱合在一起,组成一个代表噪声频率(无调成份)
要列出谱线x(k)的有调和无调,需执行下面三个步骤:
(1)标明局部最大。如果x(k)比相邻的两个谱线都大,则x(k)为局部最大值;
(2)列出有调成份,计算声压级。如果x(k)-x(k+j)>=7dB,则x(k)列为有调成份。j随谱线的位置不同。
(3)列出无调成分,计算功率。在每个临界频带内将所有余留谱线的功率加起来形成临界频带内无调成分的声压级。并列出以下参数:最接近临界频带几何平均值的谱线标记k,声压级以及无调指示。
全局掩蔽阈值的计算
还要考虑别的临界频带的影响。一个掩蔽信号会对其它频带上的信号产生掩蔽效应。这种掩蔽效应称为掩蔽扩散。
每个子带的掩蔽阈值
选择出本子带中最小的阈值作为子带阈值
对高频不正确——高频区的临界频带很宽,可能跨越多个子带,从而导致模型1将临界带宽内所有的非音调部分集中为一个代表频率,当一个子带在很宽的频带内却远离代表频率时,无法得到准确的非音调掩蔽值。但计算量低。
◼ 心理声学模型2 :
提供了适合Layer III编码的更多特征
◼ 实际实现的模型复杂度取决所需要的压缩因子
如大的压缩因子不重要,则可以完全不用心理声学模型。此时位分配算法不使用SMR( Signal Mask Ratio ),而是使用SNR
**比特分配器(Bit Allocator):**根据心理声学模型的计算结果,为每个子带信号分配比特数
**装帧(Frame Creation):**产生MPEG-I兼容的比特流
Layer I 编码:码率分配
算法:使整帧和每个子带的总噪声—掩蔽比最小
计算噪声-掩蔽比(noise-to-mask ratio, NMR): NMR = SMR – SNR (dB)
其中SNR 由MPEG-I标准给定 (为量化水平的函数) NMR:表示波形误差与感知测量之间的误差
算法:循环,直到没有比特可用:
◼ NMR = SMR– SNR (dB)
◼ 对最高NMR的子带分配比特,使获益最大的子带的
量化级别增加一级
◼ 重新计算分配了更多比特子带的NMR
Layer I 编码:装帧
Header:帧头格式
三、实验代码
main函数:
int main (int argc, char **argv)
{
typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT];
SBS *sb_sample;
typedef double JSBS[3][SCALE_BLOCK][SBLIMIT];
JSBS *j_sample;
typedef double IN[2][HAN_SIZE];
IN *win_que;
typedef unsigned int SUB[2][3][SCALE_BLOCK][SBLIMIT];
SUB *subband;
frame_info frame;
frame_header header;
char original_file_name[MAX_NAME_SIZE];
char encoded_file_name[MAX_NAME_SIZE];
short **win_buf;
static short buffer[2][1152];
static unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT];
static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT];
static double smr[2][SBLIMIT], lgmin[2][SBLIMIT], max_sc[2][SBLIMIT];
// FLOAT snr32[32];
short sam[2][1344]; /* was [1056]; */
int model, nch, error_protection;
static unsigned int crc;
int sb, ch, adb;
unsigned long frameBits, sentBits = 0;
unsigned long num_samples;
int lg_frame;
int i;
/* Used to keep the SNR values for the fast/quick psy models */
static FLOAT smrdef[2][32];
static int psycount = 0;
extern int minimum;
time_t start_time, end_time;
int total_time;
//add
int gr;
FILE *out_txt=NULL;
unsigned char *outTXT=NULL;
out_txt=fopen("output.txt","w");
//end
sb_sample = (SBS *) mem_alloc (sizeof (SBS), "sb_sample");
j_sample = (JSBS *) mem_alloc (sizeof (JSBS), "j_sample");
win_que = (IN *) mem_alloc