logo资料库

mp3解码算法原理——具体解码算法.pdf

第1页 / 共17页
第2页 / 共17页
第3页 / 共17页
第4页 / 共17页
第5页 / 共17页
第6页 / 共17页
第7页 / 共17页
第8页 / 共17页
资料共17页,剩余部分请下载后查看
1、程序系统结构 mp3 解码流程图 其中同步及差错检查包括了头解码模块 在主控模块开始运行后,主控模块将比特流的数据缓冲区交给同步及差错检查模 块,此模块包含两个功能,即头信息解码及帧边信息解码,根据它们的信息进行 尺度因子解码及哈夫曼解码,得出的结果经过逆量化,立体声解码,混淆缩减, IMDCT,频率反转,合成多相滤波这几个模块之后,得出左右声道的 PCM 码 流 , 再由主控模块将其放入输出缓冲区输出到声音播放设备。 2、主控模块 主控模块的主要任务是操作输入输出缓冲区,调用其它各模块协同工作。 其中,输入输出缓冲区均由 DSP 控制模块提供接口。 输入缓冲区中放的数据为原始 mp3 压缩数据流,DSP 控制模块每次给出大于最大 可能帧长度的一块缓冲区,这块缓冲区与上次解帧完后的数据(必然小于一帧) 连接在一起,构成新的缓冲区。 输出缓冲区中将存放的数据为解码出来的 PCM 数据,代表了声音的振幅。它由一 块固定长度的缓冲区构成,通过调用 DSP 控制模块的接口函数,得到头指针,在 完成输出缓冲区的填充后,调用中断处理输出至 I2S 接口所连接的音频 ADC 芯片 (立体声音频 DAC 和 DirectDrive 耳机放大器)输出模拟声音。 3、同步及差错检测
同步及差错检测模块主要用于找出数据帧在比特流中的位置,并对以此位置开始 的帧头、CRC 校验码及帧边信息进行解码,这些解码的结果用于后继的尺度因子 解码模块和哈夫曼解码模块。Mpeg1 layer 3 的流的主数据格式见下图: 主数据的组织结构图 其中 granule0 和 granule1 表示在一帧里面的粒度组 1 和粒度组 2,channel0 和 channel1 表示在一个粒度组里面的两个通道,scalefactor 为尺度因子 quantized value 为量化后的哈夫曼编码值,它分为 big values 大值区和 count1 1 值区 CRC 校验:表达式为 X16+X15+X2+1 3.1 帧同步 帧同步目的在于找出帧头在比特流中的位置,ISO 1172-3 规定,MPEG1 的帧头 为 12 比特的“1111 1111 1111”,且相邻的两个帧头隔有等间距的字节数,这 个字节数可由下式算出: N= 144 * 比特率 / 采样率 如果这个式子的结果不是整数,那么就需要用到一个叫填充位的参数,表示间距 为 N +1。 3.2 头信息解码 头信息解码目的是找出这一帧的特征信息,如采样率,是否受保护,是否有填充 位等。头信息见下图:
帧头信息结构图 其长度为 4 字节,数据结构如下: typedef struct tagHeader { unsigned int sync : 11 ; / / 同步信息 unsigned int version : 2 ; / / 版本 unsigned int layer : 2 ; / / 层 unsigned int error2protection : 1 ; / / CRC 校正 unsigned int bit2rate2index : 4 ; / / 位率索引 unsigned int sample2rate2index : 2 ; / / 采样率索引 unsigned int padding : 1 ; / / 空白字 unsigned int extension : 1 ; / / 私有标志 unsigned int channel2mode : 2 ; / / 立体声模式 unsigned int mode extension : 2 ; / / 保留 unsigned int copyright : 1 ; / / 版权标志 unsigned int original : 1 ; / / 原始媒体 unsigned int emphasis : 2 ; / / 强调方式 } HEADER 3.3 帧边信息解码 帧边信息解码的主要目的在于找出解这帧的各个参数,包括主数据开始位置,尺 度因子长度等。帧边信息如下图所示:
帧边信息(side_infomation)表 3.4 main_data_begin main_data_begin(主数据开始)是一个偏移值,指出主数据是在同步字之前多少 个字节开始。需要注意的是,1.帧头不一定是一帧的开始,帧头 CRC 校验字和帧 边信息在帧数据中是滑动的。2.这个数值忽略帧头和帧边信息的存在,如果 main_data_begin = 0, 则主数据从帧边信息的下一个字节开始。 参见下图:
同步示意图 3.5 block_type block_type 指出如下三种块类型: block_type = 0 长块 block_type = 1 开始块 block_type = 3 结束块 block_type = 2 短块 在编码过程中进行 IMDCT 变换时,针对不同信号为同时得到较好的时域和频域 分辨率定义了两种不同的块长:长块的块长为 18 个样本,短块的块长为 6 个样 本。这使得长块对于平稳的声音信号可以得到更高的频率分辨率,而短块对跳变 信号可以得到更高的时域分辨率。由于在短块模式下,3 个短块代替 1 个 长 块 , 而短块的大小恰好是一个长块的 1/3,所以 IMDCT 的样本数不受块长的影响。对 于给定的一帧声音信号,IMDCT 可以全部使用长块或全部使用短块,也可以长短 块混合使用。因为低频区的频域分辨率对音质有重大影响,所以在混合块模式下 , IMDCT 对最低频的 2 个子带使用长块,而对其余的 30 个子带使用短块。这样, 既能保证低频区的频域分辨率,又不会牺牲高频区的时域分辨率。长块和短块之 间的切换有一个过程,一般用一个带特殊长转短(即,起始块 block_type = 1) 或短转长(即终止块,block_type = 3)数据窗口的长块来完成这个长短块之间 的切换。因此长块也就是包括正常窗,起始块和终止块数据窗口的数据块;短块 也包含 18 个数据,但是是由 6 个数据独立加窗后在经过连接计算得到的。 3.6 big_values, count1 每一个粒度组的频谱都是用不同的哈夫曼表来进行编码的。编码时,把整个从 0 到奈奎斯特频率的频率范围(共 576 个频率线)分成几个区域,然后再用不同的 表编码。划分过程是根据最大的量化值来完成的,它假设较高频率的值有较低的 幅度或者根本不需要编码。从高频开始,一对一对的计算量化值等于“0”的数 目,此数目记为“rzero”。然后 4 个一组地计算绝对值不超过“1”的 量 化 值(也 就是说,其中只可能有-1,0 和+1 共 3 个可能的量化级别)的数目,记为
“count1”,在此区域只应用了 4 个哈夫曼编码表。最后,剩下的偶数个值的 对数记为“big values”, 在此区域只应用了 32 个哈夫曼编码表。在此范围 里的最大绝对值限制为 8191。此后,为增强哈夫曼编码性能,进一步划分了频 谱。也就是说,对 big values 的区域(姑且称为大值区)再细化,目的是为了 得到更好的错误顽健性和更好的编码效率。在不同的区域内应用了不同的哈夫曼 编码表。具体使用哪一个表由 table_select 给出。从帧边信息表中可以看到: 当 window_switch_flag == 0 时,只将大值区在细分为 2 个区,此时 region1_count 无意义,此时的 region0_count 的值是标准默认的;但当 window_switch_flag == 1 时再将大值区细分为 3 个区。但是由于 region0_count 和 region1_count 是根据从 576 个频率线划分的, 因此有可能 超出了 big_values *2 的范围,此时以 big_values *2 为准. region0_count 和 region1_count 表示的只是一个索引值,具体频带要根据标准中的缩放因子频带 表来查得. 参见下图: 缩放因子、大值区、1 值区和零值区分布图 3.7 处理流程
4、缩放因子(scale factor)解码 缩放因子用于对哈夫曼解码数据进行逆量化的样点重构。根据帧边信息中的 scalefactor_compress 和标准中的对应表格来确定的 slen1 和 slen2 对缩放因 子进行解码,即直接从主数据块中读取缩放因子信息并存入表 scalefac_l[gr][ch][sfb]和 scalefac_s[gr][ch][sfb]中。对第 2 粒度组解码 时,若为长块,则必须考虑尺度因子选择信息。 4.1 尺度因子带(scalefactor-band) 在 mpeg layer 3 中 576 条频率线根据人耳的听觉特性被分成多个组,每个组对 应若干个尺度因子,这些组就叫做尺度因子带,每个长窗有 21 个尺度因子带而 每个短窗有 12 个尺度因子带。 4.2 scfsi scfsi(尺度因子选择信息)用于指出是否将粒度组 1 的尺度因子用于粒度组 2。 如果为 0 表示不用,则在比特流中需读取粒度组 2 的尺度因子。 4.3 处理流程
缩放因子解码流程图 5、哈夫曼解码 哈夫曼编码是一种变长编码,在 mp3 哈夫曼编码中,高频的一串零值不编码,不 超过 1 的下一个区域使用四维哈夫曼编码,其余的大值区域采用二维哈夫曼编 码,而且可选择地分为三个亚区,每个有独立选择的哈夫曼码表。通过每个亚区 单独的自适应码表,增强编码效率,而且同时降低了对传输误码的敏感度。 在程序实现上,哈夫曼表逻辑存储采用了广义表结构,物理存储上使用数组结构 。 查表时,先读入 4bit 数据,以这 4bit 数据作为索引,其指向的元素有两种类型 , 一种是值结构,另一种是链表指针式结构,在链表指针式结构中给出了还需要读 取的 bit 数,及一个偏移值。如果索引指向的是一个值结构,则这个值结构就包 含了要查找的数据。如果索引指向的是一个链表指针式结构,则还需再读取其中 指定的比特数,再把读取出的比特数同偏移值相加,递归的找下去,直到找到值 结构为止。
分享到:
收藏