MP3文件結構及解碼概述

MP3文件結構概述

Layer-3音頻文件,MPEG(MovingPicture Experts Group)在漢語中譯爲活動圖像專家組,特指活動影音壓縮標準,MPEG音頻文件是MPEG1標準中的聲音部分,也叫MPEG音頻層,它根據壓縮質量和編碼複雜程度劃分爲三層,即Layer-1Layer2Layer3,且分別對應MP1MP2MP3這三種聲音文件,並根據不同的用途,使用不同層次的編碼。MPEG音頻編碼的層次越高,編碼器越複雜,壓縮率也越高,MP1MP2的壓縮率分別爲4161-81,而MP3的壓縮率則高達101-121

MP3文件大體分爲三部分:TAG_V2(ID3V2),音頻數據,TAG_V1(ID3V1),其中ID3V2ID3V1的補充,並不是所有的MP3都有ID3V2補充,即是不是所有的MP3文件都有ID3V2

ID3V2

        如果MP3文件存在ID3V2,則一定在文件的頭部,ID3V2結構分爲頭部(header)和若干標籤幀,其中頭部長度爲10字節,10個字節的結構如表1

0

1

2

3

4

5

6

7

8

9

內容爲”ID3”

版本號

副版本號

存放標誌的字節

ID3V2總大小(幀頭和之後的若干標籤幀總和)

1

因爲345字節所代表的意義並不是MP3解碼的重點,故此只解說前三字節和後四字節:

  1.  從表1可看出判斷MP3文件是否存在ID3V2,只需要判斷文件前三個字節是否是”ID3”

  2. ID3V2數據大小計算公司:

total_size = (Size[0]&0x7F)*0x200000+ (Size[1]&0x7F)*0x400 + (Size[2]&0x7F)*0x80 +(Size[3]&0x7F)

其中,size[0~3],分別是表1中的6~9字節。需要注意的是,這個公司計算的長度並不包括ID3V210個字節的頭部。

ID3V2頭部之後的若干標籤幀每一幀結構分爲標籤ID4字節)、幀內容大小(4字節,不包括標籤幀幀頭)、存放標誌位(2字節)、內容。其中標籤ID的含義如下:

TEXT: 歌詞作者    TENC: 編碼        WXXX URL鏈接(URL)        TCOP: 版權(Copyright)   TOPE: 原藝術家

TCOM: 作曲家      TDAT: 日期        TPE3: 指揮者              TPE2: 樂隊               TPE1: 藝術家相當於ID3v1Artist

TPE4: 翻譯(記錄員、修改員)          TYER: 即ID3v1Year      USLT: 歌詞               TSIZ: 大小

TALB: 專輯相當於ID3v1Album         TIT1: 內容組描述          

TIT2: 標題相當於ID3v1Title       TIT3: 副標題

TCON: 流派(風格)相當於ID3v1Genre AENC: 音頻加密技術        

TBPM: 每分鐘節拍數COMM: 註釋相當於ID3v1Comment   

TDLY: 播放列表返錄                  TRCK: 音軌(曲號)相當於ID3v1Track

TFLT: 文件類型                      TIME: 時間       

TKEY: 最初關鍵字                    TLAN: 語言                

TLEN: 長度                         TMED: 媒體類型    

TOAL: 原唱片集                      TOFN: 原文件名            

TOLY: 原歌詞作者                    TORY: 最初發行年份

TOWM: 文件所有者(許可證者)          TPOS: 作品集部分          

TPUB: 發行人                        TRDA: 錄製日期

TRSN Intenet電臺名稱                 TRSO Intenet電臺所有者   UFID: 唯一的文件標識符  

TSRC ISRC(國際的標準記錄代碼)     TSSE: 編碼使用的軟件(硬件設置)

讀取MP3文件ID3V2信息的函數可如下:

//定義頭部和標籤幀

typedefstruct ID3v2Header{

   char Identify[3];         // ID3v2固定標誌:ID3

   char Ver;              //主版本號,ID3v2就是3

   char Rever;            //副版本號,一般都爲0

   char Flag;             //標誌位,一般爲0,字義爲abc00000

   char Size[4];             // 標籤大小,一共四個字節,但每個字節只使用7位,最高位不使用恆爲0,所以格式: 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx

}ID3v2Header;

 

typedefstruct ID3v2Frame//標籤幀,10個字節

{

   char FrameID[4];          // 標誌對照符,如TEXTTOPETDAT....

   char Size[4];             // 幀體的大小,按照正常的8位存儲的,FSize = Size[0]*0x100000000 + Size[1]*0x10000 + Size[2]*0x100 + Size[3];

   char Flag[2];             // 存放標誌

}ID3v2Frame;

 

//輸出信息並返回ID3V2大小

int ReadID3v2(FILE *pf)

{

   ID3v2Headermp3header;

   ID3v2Frame mp3Frame;

   int FSize      = 0;

   char str[4096] = {0};

   char str2[5]   = {0};

   int ID3size;

   inthead_size = 0;

   inti;

   if(!pf)

       return -1;

   fseek(pf,0,SEEK_SET);

   fread(&mp3header,sizeof(mp3header),1,pf);

   if (mp3header.Identify[0]!='I' || mp3header.Identify[1]!='D' || mp3header.Identify[2]!='3' ){

       printf("此歌曲不支持ID3v2標準!\n");

       //文件復位

       rewind(pf);

       return -2;

   }

   printf("ID3v2標誌:%.3s\n",mp3header.Identify);

   printf("ID3v2版本:%d\n",  mp3header.Ver);

   ID3size= (mp3header.Size[0]& 0x7F)<< 21|(mp3header.Size[1]& 0x7F)<< 14|(mp3header.Size[2] & 0x7F) << 7|(mp3header.Size[3] & 0x7F);

   printf("標籤大小:%d\n***********\n",ID3size);

   for (i=0;i<ID3size;i=i+11+FSize){

       memset(&mp3Frame,0,sizeof(mp3Frame));

       memset(&str,0,sizeof(str));

       fseek(pf,10+i,SEEK_SET);               //移動到標籤幀頭

       fread(&mp3Frame,sizeof(mp3Frame),1,pf);

       //原則上是不用-1的,但是實際發現,總有一個字節的差距,爲了計算方便-1,所以出現-1時標明此區塊無內容

       FSize  = (int)(mp3Frame.Size[0]*0x100000000 + mp3Frame.Size[1]*0x10000+ mp3Frame.Size[2]*0x100 + mp3Frame.Size[3]-1);

       if (FSize>0)   {

           fseek(pf,10+11+i,SEEK_SET);//移動到內容區           

           fread(str,FSize,1,pf);

           GetStr(mp3Frame.FrameID,str2);

           printf("%s-%s:\t%s\n",str2,mp3Frame.FrameID,str);

           head_size+=11;

       }else{

           return ID3size+10;

       }

   }

   return ID3size+10;

}

 

//通過FrameID獲取對應的中文名

void GetStr(char* oldstr,char* str)

{

   if (0==memcmp((LPCTSTR)"TIT2",oldstr,4))

   {

       memcpy(str,"標題",4);

   }elseif(0==memcmp((LPCTSTR)"TPE1",oldstr,4)){

       memcpy(str,"作者",4);

   }elseif(0==memcmp((LPCTSTR)"TALB",oldstr,4)){

       memcpy(str,"專輯",4);

   }elseif(0==memcmp((LPCTSTR)"TRCK",oldstr,4)){

       memcpy(str,"音軌",4);

   }elseif(0==memcmp((LPCTSTR)"TYER",oldstr,4)){

       memcpy(str,"年代",4);

   }elseif(0==memcmp((LPCTSTR)"COMM",oldstr,4)){

       memcpy(str,"備註",4);

   }elseif(0==memcmp((LPCTSTR)"TCON",oldstr,4)){

       memcpy(str,"類型",4);

   }else{

       memcpy(str,"未知",4);  //其他的不是很重要,所以省略了

   }

}

MP3文件數據結構及處理流程

MP3數據解碼流程借用圖1描述。

1

MP3文件的音頻數據部分,是分爲很多數據幀存放,每一幀數據播放的時間長度計算公式:

   每幀持續時間(毫秒) =每幀採樣數 /採樣頻率 * 1000

假設每幀採樣數爲1152,採樣頻率爲44.1K,則每幀數據播放的時間約爲26ms

   沒幀數據的結構包括幀頭(header)、幀邊信息(side)、主數據(main data)。

幀頭(header

        數據幀幀頭長度爲4字節,結構如圖2所示。

2

        由圖可知,同步信息(synchronizationword11位皆爲1,其他位信息如表

版本(ID

2bit

00-MPEG 2.5  01-未定義    10-MPEG 2    11-MPEG 1

層(layer

2bit

00-未定義     01-Layer 3    10-Layer 2     11-Layer 1

CRC校驗

1bit

0-校驗       1-不校驗

位率索引

4bit

bits

V1,L1

V1,L2

V1,L3

V2,L1

V2,L2

V2,L3

0000

free

free

free

free

free

free

0001

32

32

32

32(32)

32(8)

8 (8)

0010

64

48

40

64(48)

48(16)

16 (16)

0011

96

56

48

96(56)

56(24)

24 (24)

0100

128

64

56

128(64)

64(32)

32 (32)

0101

160

80

64

160(80)

80(40)

64 (40)

0110

192

96

80

192(96)

96(48)

80 (48)

0111

224

112

96

224(112)

112(56)

56 (56)

1000

256

128

112

256(128)

128(64)

64 (64)

1001

288

160

128

288(144)

160(80)

128 (80)

1010

320

192

160

320(160)

192(96)

160 (96)

1011

352

224

192

352(176)

224(112)

112 (112)

1100

384

256

224

384(192)

256(128)

128 (128)

1101

416

320

256

416(224)

320(144)

256 (144)

1110

448

384

320

448(256)

384(160)

320 (160)

1111

bad

bad

bad

bad

bad

bad

V1 - MPEG 1    V2 - MPEG 2 and MPEG 2.5

L1 - Layer 1   L2 - Layer 2    

L3 - Layer 3

"free"表示位率可變   

"bad" 表示不允許值

採樣頻率

2bit

MPEG-1 00-44.1kHz   01-48kHz   10-32kHz     11-未定義

MPEG-2 00-22.05kHz  01-24kHz   10-16kHz     11-未定義

MPEG-2.5 00-11.025kHz 01-12kHz   10-8kHz      11-未定義

是否填充

1bit

0-無需調整,1-調整

保留(reserved

1bit

 

聲道模式

2bit

00-立體聲Stereo   01-Joint Stereo   10-雙聲道       11-單聲道

保留(reserved

2bit

 

版權標誌

1bit

0-不合法  1-合法

原版標誌

1bit

0-非原版  1-原版

強調方式

2bit

00-未定義    01-50/15ms    10-保留      11-CCITT J.17

2

數據幀大小計算公式:

Size=((採樣個數 * (1 / 採樣率))*幀的比特率)/8 +幀的填充大小

對於Mp3格式:

   Size=((1152 * (1 /採樣率))*幀的比特率)/8 +幀的填充大小= 144*幀的比特率/採樣率+幀的填充大小

其中:幀的填充大小便是23bit,不是0則爲1

幀邊信息(side

幀邊信息解碼的主要目的在於找出解這幀的各個參數,包括主數據開始位置,尺度因子長度等。幀邊信息如圖3所示。

3

其中main_data_begin(主數據開始)是一個偏移值,指出主數據是在同步字之前多少個字節開始。需要注意的是,1.幀頭不一定是一幀的開始,幀頭CRC校驗字和幀邊信息在幀數據中是滑動的。2.這個數值忽略幀頭和幀邊信息的存在,如果main_data_begin = 0, 則主數據從幀邊信息的下一個字節開始,示意圖如圖4.

4

        塊類型(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個數據獨立加窗後在經過連接計算得到的。

主數據(main_data

        main_data中有兩粒度組,沒個粒度組分爲兩個聲道,取數據存儲結構如圖5

5

其中,每個通道(chN_data)的結構圖6.

6


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章