一、MPEG-1 Audio LayerII编码器原理
1、多相滤波器组:将PCM样本变换到32个子带的频域信号
如果输入的采样频率为48kHz,那么子带的频率宽度为48/(2*32)=0.75Hz
缺点:
(1)等带宽的滤波器组与人类听觉系统的临界频带不对应
在低频区域,单个子带会覆盖多个临界频带。在这种情况下,量化比特数不能兼每个临界频带
(2)滤波器组与其逆过程不是无失真的
但滤波器组引入的误差差很小,且听不到
(3)子带间频率有混叠
滤波后的相邻子带有频率混叠现象,一个子带中的信号可以影响相邻子带的输出
2、心理声学模型:计算信号中不可听觉感知的部分
计算噪声遮蔽效应
(1)心理声学模型1:计算复杂度低,但对假设用户听不到的部分压缩太严重
(2)心理声学模型2 :提供了适合Layer III编码的更多特征
实际实现的模型复杂度取决所需要的压缩因子
3、比特分配器:根据心理声学模型的计算结果,为每个子带信号分配比特数
4、装帧:产生MPEG-I兼容的比特流
二、感知音频编码的设计思想
感知编码是利用人耳听觉的心理声学特性,将凡是人耳感觉不到的成分不编码不传送的一种编码技术。
1、绝对听觉门限
声源振动的能量通过声波传入人耳,使耳膜发生振动,人们就产生了声音的感觉。但是人耳能听到的振动频率约在20Hz到20KHz之间,低于20Hz或高于20KHz的振动,不能引起人类听觉器官的感觉。心理声学模型中一个基本的概念就是听觉系统中存在一个听觉阈值电平,低于这个电平的声音信号就听不到,因此就可以把这部分信号去掉。听觉阈值的大小随声音频率的改变而改变,各个人的听觉阈值也不同。一个人是否能听到声音取决于声音的频率,以及声音的幅度是否高于这种频率下的听觉阈值。
2、听觉掩蔽效应
一种频率的声音阻碍听觉系统感受另一种频率的声音的现象称为掩蔽效应。掩蔽可分成频域掩蔽和时域掩蔽。
(1)频域掩蔽
频域掩蔽是指掩蔽声与被掩蔽声同时作用时发生掩蔽效应,是一种较强的掩蔽效应。通常,频域中的一个强音会掩蔽与之同时发声的附近的弱音,弱音离强音越近,一般越容易被掩蔽。一般来说,低频的音容易掩蔽高频的音;在距离强音较远处,绝对听觉门限比该强音所引起的掩蔽阈值高,这时噪声的掩蔽阈值应取绝对听觉门限。
(2)时域掩蔽
在时间上相邻的声音之间产生的掩蔽现象称为时域掩蔽,即掩蔽效应发生在掩蔽声与被掩蔽声不同时出现。若掩蔽声音出现之前的一段时间内发生掩蔽效应,则称为导前掩蔽;否则称为滞后掩蔽。产生时域掩蔽的主要原因是人的大脑处理信息需要花费一定的时间,异时掩蔽也随着时间的推移很快会衰减,是一种弱掩蔽效应。
3、感知编/解码器
利用人耳的心理声学特性,可以设计相应的模块去除一些冗余信息,提高数据的压缩效率。
三、心理声学模型的实现过程
1、临界频带
由于声音频率与掩蔽曲线不是线性关系,为从感知上来统一度量声音频率,引入了 “临界频带”的概念。当某个纯音被以它为中心频率、且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽为临界频带宽度。通常认为,在20Hz到16kHz范围内有24个临界频带。
2、掩蔽值的计算
四、码率分配的实现思路
1、在调整到固定的码率之前
先确定可用于样值编码的有效比特数,这个数值取决于比例因子、比例因子选择信息、比特分配信息以及辅助数据所需比特数
2、比特分配的过程
(1)对每个子带计算掩蔽-噪声比MNR,是信噪比SNR–信掩比SMR,即:MNR = SNR–SMR
(2)NMR=SMR-SNR
3、算法:使整帧和每个子带的总噪声—掩蔽比最小
(1)计算噪声-掩蔽比( NMR): NMR = SMR – SNR (dB)
其中SNR 由MPEG-I标准给定 (为量化水平的函数) NMR:表示波形误差与感知测量之间的误差
(2)循环,直到没有比特可用
◼ NMR = SMR– SNR (dB)
◼ 对最高NMR的子带分配比特,使获益最大的子带的量化级别增加一级
◼ 重新计算分配了更多比特子带的NMR
五、程序设计
main函数主要作用:
1、过滤数据滑动窗口以获取 32 个子波段,即每个通道的样本
2、如果采用联合立体声模式,则将左右通道组合在一起
3、计算一帧的比例因子和比例因素选择信息
4、使用选定的心理声学模型计算心理声学掩蔽水平
5、使用第4步的掩蔽电平对低掩蔽比的子带执行迭转位分配
6、如果错误保护标志处于活动状态,则添加CRC纠错
7、将比特分配,比例因子和比例因子信息打包到比特流中
8、量化子带并将其打包到比特流中
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]; //存放2声道共32个子带的比特分配表
static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT]; //存放2声道、3组各子带的比例因子
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;
sb_sample = (SBS *) mem_alloc (sizeof (SBS), "sb_sample");
j_sample = (JSBS *) mem_alloc (sizeof (JSBS), "j_sample");
win_que = (IN *) mem_alloc (sizeof (IN), "Win_que");
subband = (SUB *) mem_alloc (sizeof (SUB), "subband");
win_buf = (short **) mem_alloc (sizeof (short *) * 2, "win_buf");
/* clear buffers */
memset ((char *) buffer, 0, sizeof (buffer));
memset ((char *) bit_alloc, 0, sizeof (bit_alloc));
memset ((char *) scalar, 0, sizeof (scalar));
memset ((char *) j_scale, 0, sizeof (j_scale));
memset ((char *) scfsi, 0, sizeof (scfsi));
memset ((char *) smr, 0, sizeof (smr));
memset ((char *) lgmin, 0, sizeof (lgmin));
memset ((char *) max_sc, 0, sizeof (max_sc));
//memset ((char *) snr32, 0, sizeof (snr32));
memset ((char *) sam, 0, sizeof (sam));
global_init (); //全局初始化
header.extension = 0;
frame.header = &header;
frame.tab_num =