数据压缩实验七——MEPG音频编码

来源:互联网 发布:明日之丈 知乎 编辑:程序博客网 时间:2024/05/16 15:39

实验原理

这里写图片描述
编码器说明
输入声音信号经过一个多相滤波器组,变换到多个子带。同时经过“心理声学模型”计算以频率为自变量的噪声掩蔽阈值。量化和编码部分用信掩比SMR决定分配给子带信号的量化位数,使量化噪声<掩蔽域值。最后通过数据帧包装将量化的子带样本和其它数据按照规定的帧格式组装成比特数据流。

多相滤波器组,用来分割子带

这里写图片描述

量化和编码

比例因子的取值和编码
对各个子带每12个样点进行一次比例因子计算。先定出12个样点中绝对值的最大值。查比例因子表中比这个最大值大的最小值作为比例因子。用6比特表示。
第2层的一帧对应36个子带样值,是第1层的三倍,原则上要传三个比例因子。为了降低比例因子的传输码率, 采用了利用人耳时域掩蔽特性的编码策略。
每帧中每个子带的三个比例因子被一起考虑,划分成特定的几种模式。根据这些模式,1个、2个或3个比例因子和比例因子选择信息(每子带2比特)一起被传送。如果一个比例因子和下一个只有很小的差别,就只传送大的一个,这种情况对于稳态信号经常出现。
使用这一算法后,和第1层相比,第2层传输的比例因子平均减少了2个,即传输码率由22.5Kb/s降低到了7.5Kb/s。
比特分配及编码
在调整到固定的码率之前,先确定可用于样值编码的有效比特数,这个数值取决于比例因子、比例因子选择信息、比特分配信息,以及辅助数据所需比特数。
比特分配的过程:
对每个子带计算掩蔽-噪声比MNR,是信噪比SNR – 信掩比SMR,即:MNR = SNR – SMR
这里写图片描述
使整个一帧和每个子带的总噪声-掩蔽比最小。这是一个循环过程,每一次循环使获益最大的子带的量化级别增加一级,当然所用比特数不能超过一帧所能提供的最大数目。
第1层一帧用4比特给每个子带的比特分配信息编码;而第2层只在低频段用4比特,高频段则用2比特。
子带样值的量化和编码
输入以12个样本为一组,每组样本经过时间-频率变换之后进行一次比特分配并记录一个比例因子(scale factor)。
比特分配信息告诉解码器每个样本由几位表示,比例因子用6比特表示,解码器使用这个6比特的比例因子乘逆量化器的每个输出样本值,以恢复被量化的子带值。比例因子的作用是充分利用量化器的量化范围, 通过比特分配和比例因子相配合,可以表示动态范围超过120dB的样本 。
第2层中,量化级别的数目随子带的不同而不同,但量化等级仍然覆盖了3~65535的范围,同时子带不被分配给比特的概率增加了,没有分配给比特的子带就不被量化。低频段的量化等级有15级,中频段7级,高频段只有3级。

数据帧包装

帧头 CRC 比特分配 SCFSI 比例因子 样值 辅助数据 (32) (0/16) (26-188) (0-60) (0-1080) (1152)

这里写图片描述
层I每帧含384个样本数据。每帧由32个子带分别输出的12个样本值组成。
以48kHz采样,一帧长为32×12×20.83µs =8ms。
层II每帧包含1152个样本。低、中、高频段对比特分配不同,分别用4、3、2比特。比特流中增加了一个比特因子选择信息域,解码器根据这个域的信息可知道是否需要以及如何共享比例因子。

实验流程

输出音频的采样率和目标码率
选择某个数据帧,输出该帧所分配的比特数、该帧的比例因子、该帧的比特分配结果

//add by xhyFILE *output_txt;char temp[100] = "info.txt"; //info.txt为存储数据帧信息的文件//end...int main (int argc, char **argv){    //add by xhy    output_txt = fopen(temp, "w");    if (output_txt == NULL)        printf("Creating output txt file failed.\n");    //end    ...}#ifdef NEWENCODE    ...#else    scale_factor_calc (*sb_sample, scalar, nch, frame.sblimit);    pick_scale (scalar, &frame, max_sc);    //add by xhy    int sb, gr, ch;    if (frameNum == 100)   //选择第100个数据帧    {        //输出采样率         fprintf(output_txt, "采样频率为 %d kHz. \n 目标码率为 %d kbps.\n",            header.sampling_frequency, bitrate[header.version][header.bitrate_index]);        fprintf(output_txt, "输出的为第 %d 帧\n", frameNum); //输出数据帧        fprintf(output_txt, "分配的比特数为 %d\n", adb);        fprintf(output_txt, "比例因子为:\n");  //输出比例因子        for (ch = 0; ch < nch; ch++)//声道        {            fprintf(output_txt, "channel[%2d] \n", ch + 1);             for (sb = 0; sb < frame.sblimit; sb++) //子带            {                fprintf(output_txt, "subband[%2d]:    ", sb + 1);                  for (gr = 0; gr < 3; gr++)                 {                    fprintf(output_txt, "%2d\t", scalar[ch][gr][sb]);                }                fprintf(output_txt, "\n");            }        }    }    //end     ...  }#endif...    //add by xhy    if (frameNum == 100)    {        fprintf(output_txt, "\n分配的比特数为:\n");  //输出比特分配结果        int ch, sb;        for (ch = 0; ch < nch; ch++)        {            fprintf(output_txt, "channel[%2d] \n", ch + 1); //按声道分配            for (sb = 0; sb < frame.sblimit; sb++)            {                fprintf(output_txt, "subband[%2d]:%2d\n", sb, bit_alloc[ch][sb]);            }        }    }    //end

实验结果

这里写图片描述
这里写图片描述

原创粉丝点击