您的位置:首页 > 其它

Mp3解码算法流程

2012-03-08 14:48 120 查看

第1章 声明

本文档版权归属于

西安交通大学人工智能与机器人研究所

作者:李国辉 ghli@aiar.xjtu.edu.cn

第2章 Mp3解码算法流程

MP3的全称为MPEG1 Layer-3音频文件, MPEG音频文件是MPEG1标准中的声音部分,也叫MPEG音频层,它根据压缩质量和编码复杂程度划分为三层,即Layer1、Layer2、Layer3,且分别对应MP1、MP2、MP3这三种声音文件,并根据不同的用途,使用不同层次的编码。MPEG音频编码的层次越高,编码器越复杂,压缩率也越高,MP1和MP2的压缩率分别为4:1和6:1-8:1,而MP3的压缩率则高达10:1-12:1。一分钟CD音质的音乐,未经压缩需要10MB的存储空间,而经过MP3压缩编码后只有1MB左右。不过MP3对音频信号采用的是有损压缩方式,为了降低声音失真度,MP3采取了“心理声学模型”,即编码时先对音频文件进行频谱分析,然后再根据心理声学模型把谱线分成若干个阈值分区,并计算每个阈值分区的阈值,接着通过量化和熵编码对每个谱线进行编码,最后形成具有较高压缩比的MP3文件,并使压缩后的文件在回放时能够达到比较接近原音源的声音效果。

2.1. Mp3文件格式

MP3文件以一帧为一个编码单元,各帧编码数据是独立的。为了清晰而准确地描述mp3文件格式,下面采用位流语法描述,这种语法格式与c语言近似,易于理解,且描述清晰。其中粗体表示码流中的数据项,bslbf代表位串,即“Bit string, left bit first ”,uimsbf代表无符号整数,即”unsinged integer, mostsignificant bit first”,数字表示该数据项所占的比特数。

2.1.1. Audio Sequence

audio sequence()

{

while (true)

{

frame()

}

}

2.1.2. Audio Frame

frame()

{

header()

error_check()

audio_data()

ancillary_data()

}

2.1.3. Header

header()

{

syncword 12 bslbf

ID 1 bslbf

layer 2 bslbf

protection_bit 1 bslbf

bitrate_index 4 bslbf

sampling_frequency 2 bslbf

padding_bit 1 bslbf

private_bit 1 bslbf

mode 2 bslbf

mode_extension 2 bslbf

copyright 1 bslbf

original/home 1 bslbf

emphasis 2 bslbf

}

2.1.4. Error Check

error_check()

{

if (protection_bit==0)

crc_check 16 rpchof

}

2.1.5. Audio data , Layer III

audio_data()

{

main_data_begin 9 uimsbf

if(mode==single_channel)private_bits 5 bslbf

else private_bits 3 bslbf

for(ch=0;ch<nch;ch++)

for(scfsi_band=0;scfsi_band<4;scfsi_band++)

scfsi[ch][scfsi_band] 1 bslbf

for(gr=0;gr<2;gr++)

for(ch=0;ch<nch;ch++){

part2_3_length[gr][ch] 12 uimsbf

big_values[gr][ch] 9 uimsbf

global_gain[gr][ch] 8 uimsbf

scalefac_compress[gr][ch] 4 bslbf

window_switching_flag[gr][ch] 1 bslbf

if(window_switching_flag[gr][ch]){

block_type[gr][ch] 2 bslbf

mixed_block_flag[gr][ch] 1 uimsbf

for(region=0;region<2;region++)

table_select[gr][ch][region] 5 bslbf

for(window=0;window<3;window++)

subblock_gain[gr][ch][window] 3 uimsbf

}

else{

for(region=0;region<3;region++)

table_select[gr][ch][region] 5 bslbf

region0_count[gr][ch] 4 bslbf

region1_count[gr][ch] 3 bslbf

}

preflag[gr][ch] 1 bslbf

scalefac_scale[gr][ch] 1 bslbf

count1table_select[gr][ch] 1 bslbf

}

main_data

}

2.1.6. Main_data

main_data()

{

for(gr=0;gr<2;gr++)

for(ch=0;ch<nch;ch++){

if((window_switching_flag[gr][ch]==1)&&(block_type[gr][ch]==2)){

if(mixed_block_flag[gr][ch]){

for(sfb=0;sfb<8;sfb++)

scalefac_l[gr][ch][sfb] 0..4 uimsbf

for(sfb=3;sfb<12;sfb++)

for(window=0;window<3;window++)

scalefac_s[gr][ch][sfb][window] 0..4 uimsbf

}

else{

for(sfb=0;sfb<12;sfb++)

for(window=0;window<3;window++)

scalefac_s[gr][ch][sfb][window] 0..4 uimsbf

}

}

else{

if((scfsi[ch][0]==0||(gr==0))

for(sfb=0;sfb<6;sfb++)

scalefac_l[gr][ch][sfb] 0..4 uimsbf

if((scfsi[ch][1]==0||(gr==0))

for(sfb=6;sfb<11;sfb++)

scalefac_l[gr][ch][sfb] 0..4 uimsbf

if((scfsi[ch][2]==0||(gr==0))

for(sfb=11;sfb<16;sfb++)

scalefac_l[gr][ch][sfb] 0..3 uimsbf

if((scfsi[ch][3]==0||(gr==0))

for(sfb=16;sfb<21;sfb++)

scalefac_l[gr][ch][sfb] 0..3 uimsbf

}

Huffmancodebits()

}

for(b=0;b<no_of_ancillary_bits;b++)

ancillary_bit 1 bslbf

}

2.1.7. Huffmancodebits

Huffmancodebits(){

for(l=0;l<big_values*2;l+=2){

hcod[|x|][|y|] 0..19 bslbf

if(|x|==15&&linbits>0) linbitsx 1..13 uimsbf

if(x!=0)signx 1 bslbf

if(|y|==15&&linbits>0) linbitsy 1..13 uimsbf

if(y!=0) signy 1 bslbf

is[l]=x

is[l+1]=y

}

for(;l<big_values*2+count1*4;l+=4){

hcod[|v|][|w|][|x|][|y|] 1..6 bslbf

if(v!=0) signv 1 bslbf

if(w!=0) signw 1 bslbf

if(x!=0) signx 1 bslbf

if(y!=0) signy 1 bslbf

is[l]=v

is[l+1]=w

is[l+2]=x

is[l+3]=y

}

for(;l<576;l++)

is[l]=0

}

2.1.8. Ancillary data

ancillary_data(){

if((layer==1||layer==2))

for(b=0;b<no_of_ancillary_bits;b++)

ancillary_bit 1 bslbf

}

2.2. 数据项的含义

2.2.1. Header

Ø Syncword

同步头,表示一帧数据的开始,共12位,全1即0XFFF。

表格 2‑1 Layer

Layer

'11'

Layer I

'10'

Layer II

'01'

Layer III

'00'

reserved

表格 2‑2 Bitrate_index

bitrate specified (kBit/s)

bitrate_index

Layer I

Layer II

Layer III

'0000'

free

free

free

'0001'

32

32

32

'0010'

64

48

40

'0011'

96

56

48

'0100'

128

64

56

'0101'

160

80

64

'0110'

192

96

80

'0111'

224

112

96

'1000'

256

128

112

'1001'

288

160

128

'1010'

320

192

160

'1011'

352

224

192

'1100'

384

256

224

'1101'

416

320

256

'1110'

448

384

320

'1111'

forbidden

forbidden

forbidden

Ø ID

算法标识位,“1”表示MPEG音频,“0”保留。

Ø Layer

用来说明是哪一层编码,如表格 2‑1 Layer所示。

Ø Protection_bit

用来表明冗余信息是否被加到音频流中,以进行错误检测和错误隐蔽。“1”表示未增加,“0”表示增加。

Ø Bitrate_index

用来指示该帧的bitrate,如表格 2‑2 Bitrate_index所示。

Ø Sampling_frequency

用来指示采样频率,如表格 2‑3 Sampling_frequency所示。

表格 2‑3 Sampling_frequency

sampling_frequency

frequency specified (kHz)

'00'

44.1

'01'

48

'10'

32

'11'

reserved

Ø Padding_bit

如果该位为1,那么帧中包含一个额外槽,用于把平均位率调节到采样频率,否则该位必须为0。在采样频率为44.1kHz时,填补是必要的,在自由格式中也可能需要填补。

Ø Private_bit

留做私用,没有定义。

Ø Mode

定义通道模式,如表格 2‑4 Mode所示。

表格 2‑4 Mode

mode

mode specified

'00'

stereo

'01'

joint_stereo (intensity_stereo and/or ms_stereo)

'10'

dual_channel

'11'

single_channel

Ø Mode_extension

用来标识采用了哪一种joint_stereo,具体对应的频带范围隐含在算法中,如表格 2‑5 Mode_extension所示。

表格 2‑5 Mode_extension

mode_extension

'00'

subbands 4-31 in intensity_stereo, bound==4

'01'

subbands 8-31 in intensity_stereo, bound==8

'10'

subbands 12-31 in intensity_stereo, bound==12

'11'

subbands 16-31 in intensity_stereo, bound==16

Ø Copyright

表明版权用,“1”表示有版权,“0”表示没有版权。

Original/copy :表明原版还是复制,“1”表示原版,“0”表示复制。

Emphasis :表明加重音类型,如表格 2‑6 Emphasis所示。

表格 2‑6 Emphasis

emphasis

emphasis specified

'00'

none

'01'

50/15 microseconds

'10'

reserved

'11'

CCITT J.17

2.2.2. Error Check

CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k 位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC 码)r 位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。在MP3协议中采用了CRC-16生成CRC码,其生成多项式如下:

2.2.3. Side information

Sideinformation 指的是在audio_data中main_data之前的一部分信息。这部分提供了解码中一些辅助的信息,用来帮助整个解码过程。为了帮助理解这一部分数据项的含义,会在下面大致阐述mp3解码所用的基本概念。

Ø Main_data_begin

表示一帧数据main data的开始位置。它表示main data相对于该帧同步头的负偏移。这里涉及到一个bit reservoir的技术,它改变了每帧的可用比特数为常数的限制,而是围绕一个长时间的平均值(目标比特率)变化。因为MP3的编码方式是采用Huffman编码,所以编码后每一帧的数据长度是不一样的,可能有的大于目标比特率为每一帧分配的空间,有的可能小于这个空间,所以为了增加空间利用率,当前帧未使用完的空间可以保存起来留给后面需要的帧使用,因此每一帧的main data开始位置可能在它的header和sideinformation之前,而main_data_begin就是用来指示这个开始位置的,这种技术就叫做bit
reservoir。

Ø Private_bits

留做私用。

Ø Scfsi、scalefac_compress

参考2.3.4 缩放因子(scalefactor)

Ø Part_2_3_length

表示main data中scalefactor和huffman数据所占用的比特数。

Ø Global_gain

全局量化步长。

Ø Window_switching_flag、block_type和mixed_block_flag

参考2.3.5 节的长短块切换

Ø Table_select、big_values、count1_table_select、region0_count和region1_count

参考2.3.2 Huffman码表的选择

Ø Subblock_gain

短窗块量化时所用的增益偏移量。

Ø Preflag和scalefac_scale

在反量化过程中对压缩数据还原时用到的变量。

2.3. Mp3解码算法所用的基本概念

2.3.1. 子带和缩放因子频带

压缩之后的mp3数据是以一桢为单位的,每一桢分为两节(granule),这两节在编解码时相对独立,从每一节中可以解码出576个pcm数据,两节可解出1152个pcm数据。从二进制101……码流中得到我们所需要的信息的第一步就是huffman解码,huffuman编码信息存放在每一节中的Huffmancodebits( )中,通过huffman解码可以得到576个值,这576个值在不同节类型(参考2.3.5 节的长短块切换)下有不同的含义,下面分情况描述:

u 该节为长块

这576个值代表576条频率线上的值,它们是时域中576个pcm值经过时频变换的结果。这576条频率线从低到高分为32个子带,每个子带包含18条频率线。解出来的这576个值是整数,需要进行反量化变成浮点数,反量化的过程并不是一条频率线为单位进行的,而是若干条频率线为单位进行的,这若干条频率线组成了频带(band),叫做缩放因子频带(scalefactorband),顾名思义,在一个缩放因子频带内的频率线在反量化时共用缩放因子。在44.1khz的采样率下,缩放因子频带的划分如所示:

表格 2‑7 长块的缩放因子频带划分

scalefactor band

width of band

index of start

index of end

0

4

0

3

1

4

4

7

2

4

8

11

3

4

12

15

4

4

16

19

5

4

20

23

6

6

24

29

7

6

30

35

8

8

36

43

9

8

44

51

10

10

52

61

11

12

62

73

12

16

74

89

13

20

90

109

14

24

110

133

15

28

134

161

16

34

162

195

17

42

196

237

18

50

238

287

19

54

288

341

20

76

342

417

其中,频率线418至575不需要归属于某一个scalefactor band, 因为属于这一个频带的频率线在进行反量化时,系统提供默认的反量化因子。

u 该节为短块

这576个值代表192条频率线上的值,这192条频率线从低到高分为32个子带,每个子带包含6条频率线。每一条频率线上有三个值,分别属于三个窗(window0、window1和window2)。这192条频率线被划分为若干缩放因子频带,在44.1khz情况下,划分方式如下:

表格 2‑8 短块的缩放因子频带划分

scalefactor band

width of band

index of start

index of end

0

4

0

3

1

4

4

7

2

4

8

11

3

4

12

15

4

6

16

21

5

8

22

29

6

10

30

39

7

12

40

51

8

14

52

65

9

18

66

83

10

22

84

105

11

30

106

135

其中,频率线136至192不需要归属于某一个scalefactor band, 因为属于这一个频带的频率线在进行反量化时,系统提供默认的反量化因子。按先后顺序解出来的这576个值先是按缩放因子频带从低到高排列,在每一个缩放因子频带内,按window0,window1,window2排列,在每一个window中,频率线从低到高排列。

u 该节是混合块

在这种情况下,按先后顺序解出来的576个值分为两部分,第一部分(前36个值)是长块部分,故它们代表36条频率线,这36条频率线(参考表格 2‑7 长块的缩放因子频带划分)划分为8个缩放因子频带;第二部分(后540个值)是短块部分,它们代表180个频率线,每个频率线上有三个值,分别属于window0、window1和window2,这180个频率线(参考表格 2‑8 短块的缩放因子频带划分)划分为9个缩放因子频带(scalefactorband3àscalefactor band11)。

综合上述三种情况,这576值排列方式如下所示:

图 2‑1不同情况下huffman解码得到的576个值的含义

2.3.2. Huffman码表的选择

从Huffmancodebits( )中解码得到576个值的过程不是一个简单的查表过程,这涉及到换表的过程。在解码时,当从一个缩放因子频带过渡到另一个缩放因子频带时,huffman码表可能需要改变。Huffman解码得到的576个值分为三个部分,如下所示:

图 2‑2 bigvalues和count1的含义

在大值区(xxx),得到的值较大,一共有bigvalues*2个值,每两个值一起编码;在小值区(---),值只能为-1,0,+1,一共有count1*4个值,每四个值一起编码;在零值区(000)值为零,不需要编码。

在不同区域编码时,用到的huffman表是不一样的。

u 在大值区编码时,为了进一步提高编码效率,大值区又分为三个区域:region0、region1和region2,在不同区域用不同的huffman表编码。region的划分是以缩放因子频带为单位划分的。在side information中,region0_count[gr][ch]和region1_count[gr][ch]提供了划分信息。region0_count+1表示在region0区的缩放因子频带的个数,region1_count+1表示在region1区的缩放因子频带的个数。需要说明的是,如果是短块或者混合块中的短块部分,一个缩放因子频带被计数三次,例如,对于短块来说,region0_count为8意味着region1从scalefactor
band 3开始。Region2区的长度在side information中并没有给出,但是根据big_values[gr][ch]、region0_count和region1_count可以计算出来。在得到大值区region的划分之后,就可以根据table_select[gr][ch][region]来选择在每个区域所用的huffman码表,一共有32个huffman码表可供选择,在mp3官方协议错误!未找到引用源。AnnexB Table 3-B.7中给出了这32个表。

u 在小值区,所用huffman表的选择信息由count1table_select[gr][ch]提供。需要说明的是,小值区的长度是count1*4,虽然在side information中并没有count1,但解码程序知道在耗尽part2_3_length[gr][ch]长度的码流之后就可以判断已经达到了小值区的末尾。

2.3.3. huffman码表的特点

大值区的huffuman表一个入口项可得到两个值,小值区的huffman表一个入口项可得到四个值。大值区的huffman表有一个参数为linbits(见2.1.7)。当linbit为0时,该huffman表只能用来编码小于等于15的数。当linbit不为0时,该huffman表可用来编码值大于15的数,当用这样的huffman码表编码时,在hcod[|x|][|y|]之后的码流中有linbit位,这长度为linbit的位串表示无符号整数,它与x(或者y)相加后表示x(或者y)真正的编码值。

2.3.4. 缩放因子(scalefactor)

如前所述,一个缩放因子频带内的频率线在反量化时共用缩放因子,在码流中,缩放因子被编码于main_data中(见2.1.6)。要解码得到缩放因子,首先需要知道该缩放因子所占的比特数,在side information中scale_compress[gr][ch]提供了这样的信息,首先需要查找如下表格:

表格 2‑9 scale_compress

scale_compress

slen1

slen2

0

0

0

1

0

1

2

0

2

3

0

3

4

3

0

5

1

1

6

1

2

7

1

3

8

2

1

9

2

2

10

2

3

11

3

1

12

3

2

13

3

3

14

4

2

15

4

3

下面针对不同的节(块)类型说明slen1和slen2的含义。

u 该节为长块

slen1表示缩放因子频带0到10所用缩放因子的长度;slen2表示缩放因子频带11到20所用缩放因子的长度。

u 该节为短块

slen1表示缩放因子频带0到5所用缩放因子的长度;slen2表示缩放因子频带6到11所用缩放因子的长度。

u 该节为混合块

在这种情况下,长块部分(sfb0到sfb7)和短块部分(sfb3到sfb5)所用的缩放因子的长度相同,为slen1;短块部分(sfb6到sfb11)所用的缩放因子长度相同,为slen2。

为了进一步地减少mp3码流的大小,节1(granule1)有时会共用节0(granule 0)的缩放因子信息,是否共用由字段scfsi[scfsi_band]来决定,如下所示:

表格 2‑10 scfsi

scfsi[scfsi_band]

0

scalefactors are transmitted for each granule

1

scalefactors transmitted for granule 0 are also valid for granule 1

表格 2‑11 scfsi_band

scfsi_band

scalefactor bands (see Annex B,Table3-B.8)

0

0,1,2,3,4,5

1

6,7,8,9,10

2

11…15

3

16…20

只有granule1的长块才可以共用前一节的缩放因子信息,对于短块来说,scfsi为0。知道缩放因子的共用就不难理解在2.1.6(Main_data)中位流的组织形式。

2.3.5. 节的长短块切换

节的类型由block_type来定义,如果window_switching_flag未置位,那么block_type的值为0。如果window_switching_flag置位,那么block_type由字段block_type[gr][ch]给出,如下所示:

表格 2‑12 block_type

block_type[gr]

0

reserved

1

start block

2

3 short windows

3

end block

当block_type为0、1、3时,该节属于长块。当block_type为2时,如果mixed_block_flag[gr][ch]为0,则该节为短块;mixed_block_flag[gr][ch]为1,则该节为混合块。长块和短块在解码时算法有较大区别。

2.4. mp3解码具体流程

MP3解码的流程如下所示,解码的主要过程包括Preprocessing、Huffman decoding、Requantization、Reordering、Stereo decoding、Alias reduction、IMDCT、Frequency inversion、Synthesis filter bank,最后输出原始的PCM数据。

图 2‑3 解码流程图

2.4.1. 预处理(Preprocessing)

这个步骤主要是完成Header和Side information的解码,得到后面解码所需要的一些信息,并保存起来。

2.4.2. Huffman decoding

在2.3.1(子带和缩放因子频带)和2.3.2(Huffman码表的选择)中已经详细介绍了,在这里就不再重叙。

2.4.3. 反量化(Requantization)

经过Huffman解码之后的值必须经过反量化的处理,反量化过程根据使用的windows使用不同的反量化运算公式,其反量化的公式如下:

u 短块:

公式 2‑1

u 长块:

公式 2‑2

u 混合块:

对于短块部分,按公式 2‑1反量化;对于长块部分,按公式 2‑2反量化。参考(图 2‑1不同情况下huffman解码得到的576个值的含义)。

isi表示是第i个完成Huffman decoding的值,先将该值开4/3次方,这步一般通过查表完成。global_gain及preflag的值可以从side information中得到,当side information中的scalefac_scale=0时,scalefac_multiplier=0.5,scalefac_scale=1时则scalefac_multiplier=1,scalefac_l及scalefac_s为从scale_factor 所解出来的量化因子的值,preflag则是MP3标准中规定中所设定的常数值,而210则是系统中需要用来衡量的一个标准值。

2.4.4. 重排序(Reordering)

MP3编码器为了使Huffman编码更加有效率,对短块和混合块中的短块部分进行了Reordering,因此解码器要按照这个Reordering的方法Reverse Reordering。需注意,该步骤只作用于短块和混合块中的短块部分。

2.4.5. 立体声解码(Stereo decoding)

在这里,假设两个声道独立编解码,不对立体声进行解释。有关立体声处理的详细信息,请参考mp3官方协议。

2.4.6. 混叠消除(Alias reduction)

为了避免相邻的两个子频带之间的混迭,在编码和解码中都需要进行alias reduction去混迭的处理,这个运算可以看成是对任意两个相邻子频带连续做8次的butterfly的运算,该运算只对长块和混合块中的长块部分使用。具体算法如下:

for(sb=1;sb<32;sb++)

for(i=0;i<8;i++){

xar[18*sb-1-i]=xr[18*sb-1-i]Cs[i]-xr[18*sb+i]Ca[i]

xar[18*sb+i]=xr[18*sb+i]Cs[i]+xr[18*sb-1-is]Ca[i]

}

更形象一点,用图表示如下:

图 2‑4 混叠消除示意图

2.4.7. IMDCT变换

对于长块及混合块中的长块部分,IMDCT transform作用在一个子带的18个频率线上,产生36个输出;对于短块以及混合块中的短块部分,IMDCT transform作用在一个子带的6个频率线上,产生12个输出,连续作用三次,则也产生36个输出,IMDCT transform的公式如下所示,长块时n为36,短块时n为12。

做完IMDCTtransform之后,还要对输出的36个值做加窗运算,窗口函数是根据side information中的block_type决定的,窗口函数与block_type之间的关系如下:

u block_type=0 (normal window)

u block_type=1 (start block)

u block_type=3 (stop block)

u block_type=2 (short block)

对于长块,属于前三种情况其中一种;对于短块,属于最后一种情况;对于混合块,长块部分属于第一种情况, 短块部分属于最后一种情况。

最后一个步骤是对32个子频带中所计算出来的进行overlapping,它是将当前子带计算出来的36个值的低18个值与前一个块相应子带计算出来的36个值的高18个值进行重叠相加,当前子带的后18个值被保存起来,用在下一个块中。公式如下:

在进行IMDCT变换之后,不再有长块、短块的概念,只需知道得到的576个值从低到高分为32个子带,每个子带18个值。

2.4.8. 子带合成滤波(Synthesis filter bank)

这部分是MP3解码的最后一个部分了,它负责从IMDCT的输出值中把PCM值还原出来,它可以分成五个步骤,首先是Matrixing运算,它从32个子带的每个子带中取出一个值组成32个值送入一个矩阵中进行运算,然后把输出的64个结果放入一个1024的先入先出(FIFO)的缓存中,接着从1024值中取出一半,组成一个512矢量,并对这512矢量进行加窗运算,加窗系数Di由mp3官方协议AnnexB Table3-B.3提供。最后将加窗结果进行叠加生成32个时域pcm输出,具体流程如下图所示,其中

图 2‑5 子带合成滤波器流程图

第3章 libmad解码程序源代码分析

libmad是专门面向嵌入式应用的mp3解码程序,它用定点运算模拟浮点运算,因此不需要处理器有浮点运算功能。libmad对mp3解码中关键部分采用了优化的算法,这些优化算法能够大幅度地减少计算量,而且大多应用于mp3解码的VLSI实现中。由于以上的特点,libmad非常适用于嵌入式应用。libmad的版权归属于Underbit Technologies, Inc.

libmad包含的源文件主要有:bit.c、stream.c、decoder.c、frame.c、layer3.c、synth.c、huffman.c。下面按照解码的顺序对源代码分模块说明。

3.1. 码流读取

解码程序的输入就是二进制码流,因此码流读取是很重要、很基础的功能模块。码流的读取是以比特为单位的,而cpu读写内存是以字节为单位的,故在两者之间需由相关函数架起桥梁。这个函数就是mad_bit_read( ),定义于bit.c:

137 unsigned long mad_bit_read(structmad_bitptr *bitptr, unsigned int len)

138 {

139 register unsigned long value;

140

141 if (bitptr->left == CHAR_BIT)

142 bitptr->cache = *bitptr->byte;

143

144 if (len < bitptr->left) {

145 value = (bitptr->cache & ((1 << bitptr->left) - 1))>>

146 (bitptr->left - len);

147 bitptr->left -= len;

148

149 return value;

150 }

151

152 /* remaining bits in current byte */

153

154 value = bitptr->cache & ((1 << bitptr->left) - 1);

155 len -= bitptr->left;

156

157 bitptr->byte++;

158 bitptr->left = CHAR_BIT;

159

160 /* more bytes */

161

162 while (len >= CHAR_BIT) {

163 value = (value << CHAR_BIT) | *bitptr->byte++;

164 len -= CHAR_BIT;

165 }

166

167 if (len > 0) {

168 bitptr->cache = *bitptr->byte;

169

170 value = (value << len) | (bitptr->cache >> (CHAR_BIT -len));

171 bitptr->left -= len;

172 }

173

174 return value;

175}

以上涉及到一个数据结构structmad_bitptr:

struct mad_bitptr {

unsigned char const *byte;

unsigned short cache;

unsigned short left;

};

结构体mad_bitptr指向码流中的要一个要读取的比特,该比特所在的字节由byte确定,该比特在字节中的位置由left确定,如果left为8,则该比特为(*byte) 的最高为(MSB)。另外,成员cache为字节数据缓冲,也就是(*byte)。

我们看函数mad_bit_read()的第144行,((1<<bitptr->left)-1)表示一个蒙板,一个8位的数与它相与可表示低left位的值,将这个值右移((bitptr->left – len)位,即为要读取的若干比特位的值。函数的第170行也是同样的原理,只是要读取的比特位较长,涉及到多个,读者可自行揣摩。

另外,在bit.c中,还有若干码流处理函数:mad_bit_bitsleft()、mad_bit_nextbyte()、mad_bit_length()、mad_bit_skip()。

3.2. 桢的同步

每一桢的开头有同步字,即syncword,为12个比特位(0xFFF),用以标明一桢的开始,但通过在码流中查找同步字来定位桢是很费事的,因此mp3解码采用了另一种快速的定位手段。在mp3码流中,相邻两个同步字之间的距离(也就是一桢的长度)是slot的整数倍,其中slot就是一个字节。一桢的长度要么是N个字节,要么是N+1字节。其中N这样计算:

上式计算出来的N如果不是整数,应该被截短(truncated)。当桢头中的Padding_bit为1时,桢长为N+1;当Padding_bit为0时,桢长为N。

桢的同步通过函数mad_header_decode()完成,定义于frame.c:

[mad_frame_decode()àmad_header_decode()]

300 int mad_header_decode(struct mad_header*header, struct mad_stream *stream)

301 {

302 register unsigned char const *ptr, *end;

303 unsigned int pad_slot, N;

304

305 ptr = stream->next_frame;

306 end = stream->bufend;

307

……

364 /* begin processing */

365 stream->this_frame = ptr;

366 stream->next_frame = ptr + 1; /* possibly bogus sync word */

367

368 mad_bit_init(&stream->ptr,stream->this_frame);

369

370 if (decode_header(header, stream) == -1)

371 goto fail;

……

377 /* calculate free bit rate */

378 if (header->bitrate == 0) {

379 if ((stream->freerate == 0 ||!stream->sync ||

380 (header->layer == MAD_LAYER_III &&stream->freerate > 640000)) &&

381 free_bitrate(stream,header) == -1)

382 goto fail;

383

384 header->bitrate = stream->freerate;

385 header->flags |= MAD_FLAG_FREEFORMAT;

386 }

387

388 /* calculate beginning of next frame */

389 pad_slot = (header->flags &MAD_FLAG_PADDING) ? 1 : 0;

390

391 if (header->layer == MAD_LAYER_I)

392 N = ((12 * header->bitrate /header->samplerate) + pad_slot) * 4;

393 else {

394 unsigned int slots_per_frame;

395

396 slots_per_frame = (header->layer ==MAD_LAYER_III &&

397 (header->flags &MAD_FLAG_LSF_EXT)) ? 72 : 144;

398

399 N = (slots_per_frame * header->bitrate /header->samplerate) + pad_slot;

400 }

……

410 stream->next_frame = stream->this_frame+ N;

……

426 return 0;

……

}

第305行从stream结构体中获取下一个需要解码的桢的首地址,然后在365行传递给stream->this_frame,于是从前一桢过渡到它的下一桢。在得到桢长N之后,更新stream->next_frame(410行),为下一桢的解码做好准备。

另外,结构体stream定义如下:

struct mad_stream {

unsigned char const *buffer; /*input bitstream buffer */

unsigned char const *bufend; /*end of buffer */

unsigned long skiplen; /*bytes to skip before next frame */

intsync; /* streamsync found */

unsigned long freerate; /*free bitrate (fixed) */

unsigned char const *this_frame; /*start of current frame */

unsigned char const *next_frame; /*start of next frame */

struct mad_bitptr ptr; /*current processing bit pointer */

struct mad_bitptr anc_ptr; /*ancillary bits pointer */

unsigned int anc_bitlen; /*number of ancillary bits */

unsigned char (*main_data)[MAD_BUFFER_MDLEN];

/*Layer III main_data() */

unsigned int md_len; /*bytes in main_data */

intoptions; /* decodingoptions (see below) */

enum mad_error error; /*error code (see above) */

};

关于stream结构体中一些成员的含义在 3.5节(main_data的读取 )中解释。

3.3. 桢头解码

桢头解码有函数decode_header()完成,定义于frame.c:

[mad_header_decode()àdecode_header()]

static

int decode_header(struct mad_header*header, struct mad_stream *stream)

{

unsigned int index;

header->flags = 0;

header->private_bits = 0;

/*header() */

/*syncword */

mad_bit_skip(&stream->ptr, 11);

/*MPEG 2.5 indicator (really part of syncword) */

if(mad_bit_read(&stream->ptr, 1) == 0)

header->flags |= MAD_FLAG_MPEG_2_5_EXT;

/*ID */

if(mad_bit_read(&stream->ptr, 1) == 0)

header->flags |= MAD_FLAG_LSF_EXT;

else if (header->flags & MAD_FLAG_MPEG_2_5_EXT) {

stream->error = MAD_ERROR_LOSTSYNC;

return -1;

}

……

}

桢头解码所得到的信息(ID、Layer、Bitrate、Samping_frequency……)存放于结构体mad_header中,定义如下:

struct mad_header {

enum mad_layer layer; /*audio layer (1, 2, or 3) */

enum mad_mode mode; /*channel mode (see above) */

intmode_extension; /*additional mode info */

enum mad_emphasis emphasis; /*de-emphasis to use (see above) */

unsigned long bitrate; /*stream bitrate (bps) */

unsigned int samplerate; /*sampling frequency (Hz) */

unsigned short crc_check; /*frame CRC accumulator */

unsigned short crc_target; /*final target CRC checksum */

intflags; /* flags(see below) */

intprivate_bits; /* privatebits (see below) */

mad_timer_t duration; /*audio playing time of frame */

};

所要解码的mp3文件包含多少桢,decode_header()就被执行多少次。

3.4. sideinfo解码

sideinfo的解码由函数III_sideinfo()完成,定义于layer3.c,知道sideinfo的结构,阅读该函数不会有什么困难,我们把它留给读者。sideinfo解码所得到的信息(main_data_begin、scfsi、part2_3_length、big_values……)存放于结构体sideinfo中,定义如下:

struct sideinfo {

unsigned int main_data_begin;

unsigned int private_bits;

unsigned char scfsi[2];

struct granule {

struct channel {

/* from side info */

unsigned short part2_3_length;

unsigned short big_values;

unsigned short global_gain;

unsigned short scalefac_compress;

unsigned char flags;

unsigned char block_type;

unsigned char table_select[3];

unsigned char subblock_gain[3];

unsigned char region0_count;

unsigned char region1_count;

/* from main_data */

unsigned char scalefac[39]; /*scalefac_l and/or scalefac_s */

}ch[2];

}gr[2];

};

其中,数据成员scalefac[39]表示缩放因子频带的缩放因子,对于长块,一共有22个缩放因子频带(0-20的缩放因子从码流中获取,21的缩放因子为0)。对于短块,在码流的sideinfo部分得不到;对于短块,一共有13个缩放因子频带(0-11的缩放因子从码流中获取,12的缩放因子为0),其中每个频带有3个窗,分别用不同的缩放因子,因此,scalefac[ ]数组的大小为39(13*3)。缩放因子不存放于sideinfo中,而是存放于main_data中,后面在对main_data解码时,会把缩放因子填入数组scalefac[39]。

3.5. main_data的读取

main_data包含缩放因子和huffman编码数据。mp3编码时,并没有将main_data全部存放于当前桢里,而是main_data的开头有一部分存放于前一桢里,并且位于当前桢的同步字之前,sideinfo中main_data_begin表示这一部分的字节个数,如下图所示:

图 3‑1 main_data的组成

main_data的读取由函数mad_layer_III()完成,定义于layer3.c:

[mad_frame_decode()àmad_layer_III()]

2516 int mad_layer_III(struct mad_stream*stream, struct mad_frame *frame)

2517 {

……

/*decode frame side information */

2573 error = III_sideinfo(&stream->ptr,nch, header->flags & MAD_FLAG_LSF_EXT, &si, &data_bitlen, &priv_bitlen);

……

/*find main_data of next frame */

{

struct mad_bitptr peek;

unsigned long header;

mad_bit_init(&peek, stream->next_frame);

header = mad_bit_read(&peek, 32);

if ((header & 0xffe60000L)/* syncword | layer */ == 0xffe20000L){

if (!(header & 0x00010000L)) /* protection_bit */

mad_bit_skip(&peek,16); /* crc_check */

2596 next_md_begin =

mad_bit_read(&peek,(header & 0x00080000L)/* ID */ ? 9 : 8);

}

mad_bit_finish(&peek);

}

/*find main_data of this frame */

2605 frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr);

……

2610 md_len = si.main_data_begin + frame_space -next_md_begin;

2612 frame_used = 0;

2614 if (si.main_data_begin == 0) {

2615 ptr = stream->ptr;

2616 stream->md_len = 0;

2617

2618 frame_used = md_len;

2619 }

else {

2628 mad_bit_init(&ptr,

*stream->main_data + stream->md_len -si.main_data_begin);

2631 if (md_len > si.main_data_begin) {

2632 assert(stream->md_len+ md_len -

2633 si.main_data_begin <=MAD_BUFFER_MDLEN);

2635 memcpy(*stream->main_data+ stream->md_len,

mad_bit_nextbyte(&stream->ptr),

frame_used = md_len -si.main_data_begin);

2638 stream->md_len+= frame_used;

}

}

2643 frame_free = frame_space - frame_used;

/*decode main_data */

if(result == 0) {

2648 error = III_decode(&ptr, frame,&si, nch);

}

……

/*preload main_data buffer with up to 511 bytes for next frame(s) */

2670 if (frame_free >= next_md_begin) {

2671 memcpy(*stream->main_data,

2672 stream->next_frame - next_md_begin,next_md_begin);

2673 stream->md_len = next_md_begin;

}

……

2697 return result;

}

在进入mad_layer_III()函数之前,桢头信息也被解码出来,从桢头中知道是layerIII,因此调用mad_layer_III(),而不是mad_layer_I()或mad_layer_II()。因此,在mad_layer_III中,需要sideinfo解码(2573行)。

要读取属于当前桢的main_data,需要知道next_md_begin(2596)和frame_space(2605),两者之差即为属于当前桢的main_data部分,也就是frame_used,而frame_free等于next_md_begin。特别地,当为mp3文件的第一桢时,即满足2614行的条件,ptr指向第一桢的main_data,然后调用III_decode()(2648行),须注意,并没有把第一桢的main_data存放于(*stream->main_data)[ ]中;当为mp3文件的后续桢时(不是第一桢),则需把main_data存放于(*stream->main_data)[
],然后使ptr指向这个数组的起始位置(2628行),再调用III_decode()。

mad_stream结构体中的成员md_len表示已经读取的当前桢的main_data的字节个数,当前一桢被解码时获取了next_md_begin(2673行),然后对该成员赋这个初值,然后在当前桢被解码时获取了frame_used,把它加到成员md_len中(2638),此时属于当前桢的main_data全部得到。

3.6. 缩放因子解码

读取缩放因子是通过函数III_scalefactors()完成的,定义于layer3.c:

[mad_layer_III() àIII_decode()àIII_scalefactors()]

713 static

714 unsigned int III_scalefactors(structmad_bitptr *ptr, struct channel *channel,

715 struct channel const *gr0ch, unsigned intscfsi)

716 {

717 struct mad_bitptr start;

718 unsigned int slen1, slen2, sfbi;

719

720 start = *ptr;

721

722 slen1 = sflen_table[channel->scalefac_compress].slen1;

723 slen2 = sflen_table[channel->scalefac_compress].slen2;

724

725 if (channel->block_type == 2) {

726 unsigned int nsfb;

727

728 sfbi = 0;

729

730 nsfb = (channel->flags &mixed_block_flag) ? 8 + 3 * 3 : 6 * 3;

731 while (nsfb--)

732 channel->scalefac[sfbi++] =mad_bit_read(ptr, slen1);

733

734 nsfb = 6 * 3;

735 while(nsfb--)

736 channel->scalefac[sfbi++] =mad_bit_read(ptr, slen2);

737

738 nsfb = 1 * 3;

739 while (nsfb--)

740 channel->scalefac[sfbi++] = 0;

741 }

742 else { /* channel->block_type != 2 */

743 if (scfsi & 0x8) {

744 for (sfbi = 0; sfbi < 6; ++sfbi)

745 channel->scalefac[sfbi]= gr0ch->scalefac[sfbi];

746 }

747 else {

748 for (sfbi = 0; sfbi < 6; ++sfbi)

749 channel->scalefac[sfbi]= mad_bit_read(ptr, slen1);

750 }

……

779 channel->scalefac[21] = 0;

780 }

781

782 return mad_bit_length(&start, ptr);

783 }

参数channel指向当前要读取缩放因子的块,gr0ch指向一桢中第一节对应的块。如前所述,如果当前块为一桢中第二节对应的块,则它可能共用gr0ch中的缩放因子,如第743行所示;如果当前块为第一节所对应的块,则scfsi必然为0,因此从码流中读取缩放因子,如第748行所示。

3.7. huffman解码

huffman解码是比较复杂的一部分,它涉及到sideinfo中的big_values、region0_count、region1_count、table_select、part2_3_length、count1table_select。mp3在进行huffman编码时,对576个采样点分为若干区域,对不同的区域采用不同的huffman码表,为了行文方便,对采用同一huffman码表的区域称为码表区域,需要注意,码表区域的划分与缩放因子的划分并不完全一致。下图给出了某一块的码表区域划分,图中缩放因子频带的划分对应采样率为44.1khz的长块。

图 3‑2 码表区域的划分

对huffman数据的解码由函数III_huffdecode()完成,定义于layer3.c:

[mad_layer_III() àIII_decode()àIII_huffdecode()]

static

enum mad_error III_huffdecode(structmad_bitptr *ptr, mad_fixed_t xr[576],

struct channel *channel,

unsigned char const *sfbwidth,

unsigned int part2_length)

{

946 bits_left = (signed)channel->part2_3_length - (signed) part2_length;

if(bits_left < 0)

return MAD_ERROR_BADPART3LEN;

/* align bit reads to byte boundaries */

956 cachesz = mad_bit_bitsleft(&peek);

957 cachesz += ((32 - 1 - 24)+ (24 - cachesz)) & ~7;

959 bitcache = mad_bit_read(&peek, cachesz);

960 bits_left -= cachesz;

962 xrptr = &xr[0];

/*big_values */

{

972 sfbound = xrptr + *sfbwidth++;

973 rcount =channel->region0_count + 1;

975 entry =&mad_huff_pair_table[channel->table_select[region = 0]];

987 big_values = channel->big_values;

989 while (big_values-- && cachesz + bits_left > 0) {

994 if (xrptr == sfbound) {

995 sfbound+= *sfbwidth++;

/*change table if region boundary */

999 if(--rcount == 0) {

1000 if (region == 0)

1001 rcount = channel->region1_count + 1;

1002 else

1003 rcount = 0; /* all remaining */

1005 entry = &mad_huff_pair_table[channel->table_select[++region]];

}

}

1034 pair =&table[MASK(bitcache, cachesz, clumpsz)];

/* x (0..1) */

1119 value= pair->value.x;

1131 xrptr[0]= MASK1BIT(bitcache, cachesz--) ?

-requantized : requantized;

/*y (0..1) */

1137 value= pair->value.y;

1149 xrptr[1]= MASK1BIT(bitcache, cachesz--) ?

-requantized : requantized;

1154 xrptr += 2;

}

}

/*count1 */

{

1166 table = mad_huff_quad_table[channel->flags & count1table_select];

1170 while (cachesz + bits_left > 0 && xrptr <= &xr[572]) {

/* v (0..1) */

1206 xrptr[0] = quad->value.v ?

(MASK1BIT(bitcache,cachesz--) ? -requantized : requantized) : 0;

/* w (0..1) */

1211 xrptr[1] = quad->value.w ?

(MASK1BIT(bitcache,cachesz--) ? -requantized : requantized) : 0;

1214 xrptr += 2;

/* x (0..1) */

1229 xrptr[0] = quad->value.x ?

(MASK1BIT(bitcache,cachesz--) ? -requantized : requantized) : 0;

/* y (0..1) */

1234 xrptr[1] = quad->value.y ?

(MASK1BIT(bitcache,cachesz--) ? -requantized : requantized) : 0;

1237 xrptr += 2;

}

}

/*rzero */

1263 while (xrptr < &xr[576]) {

1264 xrptr[0] = 0;

1265 xrptr[1] = 0;

1267 xrptr += 2;

}

1270 return MAD_ERROR_NONE;

}

在上述代码中,xrptr指向下一个要从huffman码流中得到的值,xrptr以2为单位递增(1154行、1214行、1237行),递增之后,要判断是否到达了缩放因子频带的边界(994行),从而进一步判断是否需要换表(999行)。当xrptr到达大值区的边界时(989行),就转向小值区,需要换表(1166)。小值区的长度在sideinfo中并没有直接给出,但当耗尽了main_data时(比特数为part2_3_length),就意味着小值区的结束,程序中第946行和1170行可以反映这一点。当小值区结束之后,就进入零值区,直接给采样点赋零值即可。

有一点需要说明,在大值区,由region0_count、region1_count、big_values共同决定大值区码表区域的划分,但有些情况下,三者表达的信息并不一致。当发生窗类型切换时(window_switching_flag为1),region1_count=36,这个值过大,并不表示具体的含义,只是意味着把大值区划分了两个区域(由region0_count和bigvalues决定划分方式),只用两种码表。当然,这种情况下,仍然会有小值区和零值区。

3.8. 反量化(requantization)

反量化由两个函数完成:III_requantize()、III_exponents(),定义于layer3.c:

[III_huffdecode()àIII_exponents()]

static

void III_exponents(struct channel const*channel,

unsigned char const *sfbwidth, signed int exponents[39])

{

signed int gain;

unsigned int scalefac_multiplier, sfbi;

gain = (signed int) channel->global_gain - 210;

scalefac_multiplier = (channel->flags & scalefac_scale) ? 2 : 1;

if(channel->block_type == 2) {

/* this is probably wrong for 8000 Hz short/mixed blocks */

gain0 = gain - 8 * (signed int) channel->subblock_gain[0];

gain1 = gain - 8 * (signed int) channel->subblock_gain[1];

gain2 = gain - 8 * (signed int) channel->subblock_gain[2];

while (l < 576) {

exponents[sfbi + 0] = gain0 -

(signedint) (channel->scalefac[sfbi + 0] << scalefac_multiplier);

exponents[sfbi + 1] = gain1 -

(signedint) (channel->scalefac[sfbi + 1] << scalefac_multiplier);

exponents[sfbi + 2] = gain2 -

(signedint) (channel->scalefac[sfbi + 2] << scalefac_multiplier);

l += 3 * sfbwidth[sfbi];

sfbi += 3;

}

}

else { /* channel->block_type!= 2 */

for (sfbi = 0; sfbi < 22; ++sfbi) {

exponents[sfbi]= gain -

(signed int) ((channel->scalefac[sfbi] +pretab[sfbi]) <<

scalefac_multiplier);

}

……

}

}

顾名思义,III_exponents()返回一个指数,从代码中可以看出,该指数恰好是公式 2‑1、公式 2‑2中2的指数部分乘以4,可以看到在III_requantize()中,该返回值会除以4。

[III_huffdecode()àIII_requantize()]

static

mad_fixed_t III_requantize(unsigned intvalue, signed int exp)

{

mad_fixed_t requantized;

signed int frac;

struct fixedfloat const *power;

frac = exp % 4; /* assumessign(frac) == sign(exp) */

exp/= 4;

892 power = &rq_table[value];

893 requantized = power->mantissa;

894 exp += power->exponent;

……

916 requantized <<= exp;

return frac ? mad_f_mul(requantized, root_table[3 + frac]) :requantized;

}

第892行根据huffman解码得到的value(|isi|)查表得到|isi|4/3。具体公式为:

第894行计算得到以2为底的指数部分,然后在916行通过移位指令得到最终的反量化值。

3.9. 重排序(reordering)

重排序应用于短块以及混合块的短块部分。首先将所有采样点按window0、window1、window2分类,然后按如下示意图重新排序:

图 3‑3

重排序由函数III_reorder()完成,定义于layer3.c:

[III_decode()àIII_reorder()]

static

void III_reorder(mad_fixed_t xr[576],struct channel const *channel,

unsigned char const sfbwidth[39])

{

mad_fixed_t tmp[32][3][6];

unsigned int sb, l, f, w, sbw[3], sw[3];

/*this is probably wrong for 8000 Hz mixed blocks */

sb= 0;

for(w = 0; w < 3; ++w) {

sbw[w] = sb;

sw[w] = 0;

}

f =*sfbwidth++;

w =0;

for(l = 18 * sb; l < 576; ++l) {

if (f-- == 0) {

f = *sfbwidth++ - 1;

1309 w = (w + 1) % 3;

}

1312 tmp[sbw[w]][w][sw[w]++] = xr[l];

1314 if (sw[w] == 6) {

1315 sw[w] = 0;

1316 ++sbw[w];

1317 }

}

memcpy(&xr[18 * sb], &tmp[sb], (576 - 18 * sb) *sizeof(mad_fixed_t));

}

第1312行完成重排序功能,对每一个窗口(w),有窗口内的计算器sw[w](从0到5变化)和子带计数器sbw[w](从0到31),如第1314~第1316行所示。w的变化如第1309行所示。

3.10. IMDCT变换

在libmad中,IMDCT采用Szu-Wei Lee’s提出的快速算法。IMDCT由函数III_imdct_l()和III_imdct_s()完成,分别对应长块和短块,定义于layer3.c。读者可对照算法原理自行研究。在完成IMDCT之后,需要进行overlapping。overlapping将imdct输出的36个值zi分为两部分,前半部分与上一个块相应子带的后半部分相加,后半部分保存起来用于下一个块的overlapping。这部分由函数III_overlap()完成,定义于layer3.c:

[III_decode()àIII_overlap()]

static

voidIII_overlap(mad_fixed_t const output[36], mad_fixed_t overlap[18],

mad_fixed_t sample[18][32], unsigned int sb)

{

unsigned int i;

2264 for (i = 0; i < 18; ++i) {

2265 sample[i][sb] = output[i + 0] + overlap[i];

2266 overlap[i] = output[i + 18];

}

}

第2265行sample数组的数据组织形式sample[i][sb],i表示18个时域输出,sb表示32个子带,这样是为了方便后续的子带合成滤波。

另外,该函数在III_decode被调用时所赋的实参如下:

2453 /*long blocks */

2454 for (sb = 0; sb < 2; ++sb, l += 18) {

2455 III_imdct_l(&xr[ch][l], output,block_type);

2456 III_overlap(output,(*frame->overlap)[ch][sb], sample, sb);

2457 }

从第2456行可以看出,imdct输出的值是与上一个块的相应子带((*frameàoverlap)[ch][sb])叠加

其中,各变量的定义如下:

2379 mad_fixed_txr[2][576];

2422 mad_fixed_toutput[36];

2420 mad_fixed_t(*sample)[32] = &frame->sbsample[ch][18 * gr];

上面涉及到frame结构体的定义:

structmad_frame {

struct mad_header header; /* MPEG audio header */

int options; /*decoding options (from stream) */

mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */

mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */

};

3.11. 子带合成滤波(synthesis filter bank)

子带合成滤波是mp3解码中非常耗费时间的关键流程,其中涉及到从32个值变换到64个值的矩阵运算,对于该矩阵运算,libmad采用KonstantinosKonstantinides提出的方法,该方法将矩阵运算进行一系列变化,最后归于32点dct变换,而dct变换有类似于FFT的快速算法(FCT),从该矩阵运算到32点的dct变换如下图所示:

图 3‑4 从dct到矩阵运算

上图中,V(1*64)表示矩阵的输出,A、B都是长度为1*16的矢量,(A,B)表示32点dct的输出。

在得到矩阵的输出之后,需将这64个值送入到长度为1024的FIFO中,然后从FIFO中取出512进行加窗运算,如下图所示:

图 3‑5 FIFO和抽取的矢量

为清晰起见,送入的64个值按先后顺序被冠以标号(0、1、2、……、16、17、……),仔细观察上图,可知,每当给fifo送入64个值,取出来的512个矢量某个标号的32个值要变化一次,观察标号3,它从B(16)、-B(16)变化到-A(-16)、-A(16),再变化到B(16)、-B(16)。另外,每送入64个值,最先进入的标号消失,新的标号产生,且两者标号之差恰好等于16。上述的这种规律可用于编程之中,从而避免FIFO在送入64个值时产生的数据搬送。

得到了512个矢量之后,如下图所示可得32个pcm值输出。

图 3‑6
向量相加输出pcm

其中C(16)等于A(-16),也就是对A(16)的反转,他们都是长度为16的矢量。libmad中的函数dct32()输出的就是C(16)(hi)和B(16)(lo),这一点需要特别注意。libmad中用于子带滤波的是synth_full(),定义于synth.c:

[mad_synth_frame()àsynth_full()]

static

void synth_full(struct mad_synth *synth,struct mad_frame const *frame,

unsignedint nch, unsigned int ns)

{

……

569 for (ch = 0; ch < nch; ++ch) {

570 sbsample = &frame->sbsample[ch];

571 filter =&synth->filter[ch];

572 phase = synth->phase;

573 pcm1 =synth->pcm.samples[ch];

575 for (s = 0; s < ns; ++s) {

576 dct32((*sbsample)[s], phase >> 1,

577 (*filter)[0][phase & 1],(*filter)[1][phase & 1]);

579 pe = phase & ~1;

580 po = ((phase - 1) & 0xf) | 1;

/* calculate 32 samples */

584 fe = &(*filter)[0][ phase & 1][0];

585 fx = &(*filter)[0][~phase & 1][0];

586 fo = &(*filter)[1][~phase & 1][0];

……

613 pcm2 = pcm1 + 30;

615 for (sb = 1; sb < 16; ++sb) {

616 ++fe;

617 ++Dptr;

619 /*D[32 - sb][i] == -D[sb][31 - i] */

ptr= *Dptr + po;

ML0(hi,lo, (*fo)[0], ptr[ 0]);

MLA(hi,lo, (*fo)[1], ptr[14]);

MLA(hi,lo, (*fo)[2], ptr[12]);

MLA(hi,lo, (*fo)[3], ptr[10]);

MLA(hi,lo, (*fo)[4], ptr[ 8]);

MLA(hi,lo, (*fo)[5], ptr[ 6]);

MLA(hi,lo, (*fo)[6], ptr[ 4]);

MLA(hi,lo, (*fo)[7], ptr[ 2]);

MLN(hi,lo);

ptr= *Dptr + pe;

MLA(hi,lo, (*fe)[7], ptr[ 2]);

MLA(hi,lo, (*fe)[6], ptr[ 4]);

MLA(hi,lo, (*fe)[5], ptr[ 6]);

MLA(hi,lo, (*fe)[4], ptr[ 8]);

MLA(hi,lo, (*fe)[3], ptr[10]);

MLA(hi,lo, (*fe)[2], ptr[12]);

MLA(hi,lo, (*fe)[1], ptr[14]);

MLA(hi,lo, (*fe)[0], ptr[ 0]);

642 *pcm1++= SHIFT(MLZ(hi, lo));

ptr= *Dptr - pe;

ML0(hi,lo, (*fe)[0], ptr[31 - 16]);

MLA(hi,lo, (*fe)[1], ptr[31 - 14]);

MLA(hi,lo, (*fe)[2], ptr[31 - 12]);

MLA(hi,lo, (*fe)[3], ptr[31 - 10]);

MLA(hi,lo, (*fe)[4], ptr[31 - 8]);

MLA(hi,lo, (*fe)[5], ptr[31 - 6]);

MLA(hi,lo, (*fe)[6], ptr[31 - 4]);

MLA(hi,lo, (*fe)[7], ptr[31 - 2]);

ptr= *Dptr - po;

MLA(hi,lo, (*fo)[7], ptr[31 - 2]);

MLA(hi,lo, (*fo)[6], ptr[31 - 4]);

MLA(hi,lo, (*fo)[5], ptr[31 - 6]);

MLA(hi,lo, (*fo)[4], ptr[31 - 8]);

MLA(hi,lo, (*fo)[3], ptr[31 - 10]);

MLA(hi,lo, (*fo)[2], ptr[31 - 12]);

MLA(hi,lo, (*fo)[1], ptr[31 - 14]);

MLA(hi,lo, (*fo)[0], ptr[31 - 16]);

664 *pcm2--= SHIFT(MLZ(hi, lo));

++fo;

}

……

684 phase = (phase + 1) % 16;

}

}

}

在分析源代码之前,不妨先看一下数组(*filter)的组织形式,参考图 3‑7 (*filter)数组的组织形式,指针fe(584行)、fo(586行)分别指向图中不同行、不同列的数组的第一行,这两个数组或者是(*filter)[0][0]和(*filter)[1][1],或者是(*filter)[0][1]和(*filter)[1][0]。phase加1(684行)意味1024FIFO中被送入64个值,注意在循环(615行)中,每一次循环产生两个pcm值(613、642、664行),这两个循环所用的fe、fo是一样的,因为在图
3‑6(向量相加输出pcm)计算32个pcm值有对称性,因此实际上数据存储时,只需存B(16)、C(16),而不需要存储B(-16)和C(-16)。另外根据对称性计算时,有取负操作,这是通过变化加窗系数来做做到的(619行)。

synth_full()涉及到两个数据结构:

struct mad_synth {

mad_fixed_t filter[2][2][2][16][8]; /*polyphase filterbank outputs */

/*[ch][eo][peo][s][v] */

unsigned int phase; /*current processing phase */

struct mad_pcm pcm; /*PCM output */

};

struct mad_pcm {

unsigned int samplerate; /*sampling frequency (Hz) */

unsigned short channels; /*number of channels */

unsigned short length; /*number of samples per channel */

mad_fixed_t samples[2][1152]; /*PCM output samples [ch][sample] */

};

图 3‑7 (*filter)数组的组织形式

附录A libmad的交叉编译过程

我们所使用的用于mp3解码的处理器是leon2,它的指令体系为sparcv8标准。下面阐述针对该指令体系的交叉编译过程。

1.解压缩从网上下载的压缩包:tar –xzvf libmad-0.15.1b.tar.gz。

2.进入目录libmad-0.15.1b,建立build目录:mkdir build

3.进入目录build,执行:../configure --enable-fpm=sparc --host=sparc-elf CFLAGS=”-Wall -g -O -fforce-mem -fforce-addr -fthread-jumps -fcse-follow-jumps -fcse-skip-blocks -fexpensive-optimizations -fregmove -fschedule-insn2 -mflat”

4.执行:make make install ,这时生成的库被安装到/usr/local/lib/libmad.a ;头文件mad.h 被安装到/usr/local/include/

5.进入顶层文件(包含main函数的文件)所在的目录,执行:sparc-elf-gcc -O -mflat -mv8 -I /usr/local/include mp3_top.c /usr/local/lib/libmad.a-nostartfiles -Ttext=0x40000000 -omp3.out

6.反汇编:sparc-elf-objdump -D -h mp3.out>mp3.lst
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: