1, MP3簡介

MP3是今天一種常見的音樂格式,但恐怕除了工作要求之外,有興趣對此進行研究的人恐怕不多。所以,當我打算做MP3解碼方面的工作時,在找資料時也頗費了一番周折,同時也覺得很有趣。所以想在這里分享一下自己的心得,做一個總結性的介紹。這樣有興趣的同志也可以對此有一個大概了解,盡快入門。

MP3
MPEG-1 Audio Layer 3的簡稱,是當今比較流行的一種數字音頻編碼和有損壓縮格式(有Layer 3,也必然有Layer1Layer2,也就是MP1MP2,但不在本文討論范圍之內)。MP3技術的應該可以用來大幅度的降低音頻文件存儲所需要的空間。它丟掉脈沖編碼調制(PCM)音頻數據中對人類聽覺不重要得數據,從而達到了較高的壓縮比(高達121101)。簡單地說,MP3在編碼時先對音頻文件進行頻譜分析,然后用過濾器濾掉噪音電平,接著通過量化的方式將剩下的每一位打散排列,最后形成有較高壓縮比的MP3文件,并使壓縮后的文件在回放時也能夠達到比較接近原音源的效果。

MP3
的音頻質量取決于它的BitrateSampling frequency,以及編碼器質量。MP3的典型速度介于每秒128320kb之間。采樣頻率也有44.14832 kHz三種頻率,比較常見的是采用CD采樣頻率——44.1kHz。常用的編碼器是LAME,它完全遵循LGPLMP3編碼器,有著良好的速度和音質。

 

2,      MP3文件格式

用一個二進制查看器(比如Ultra-Edit)打開一個MP3文件,就能看到一大堆看似雜亂無序的數據。但只要用心了解就會知道,其實,這一切都是有規律可循的。

MP3
文件是由幀(frame)構成,幀是MP3文件的最小組成單位。每幀都包含幀頭,并可以計算幀的長度。根據幀的性質不同,文件主要分為三個部分,ID3v2標簽幀,數據幀和ID3v1標簽幀。并非每個MP3文件都有ID3v2,但是數據幀和ID3v1幀是必須的。ID3v2在文件頭,以字符串“ID3為標志,包含了演唱者,作曲,專輯等信息,長度不固定,擴展了ID3V1的信息量。ID3v1在文件結尾,以字符串“TAG”為標記,其長度是固定的128個字節,包含了演唱者、歌名、專輯、年份等信息。

I, ID3V2

ID3V2到現在一共有四個版本,但流行的播放軟件一般只支持第三版,既ID3V2.3。每個ID3V2.3 的標簽都一個標簽頭和若干個標簽幀或一個擴展標簽頭組成。關于曲目的信息如標題、作者等都存放在不同的標簽幀中,擴展標簽頭和標簽幀并不是必要的,但每個標簽至少要有一個標簽幀。標簽頭和標簽幀一起順序存放在MP3 文件的首部。

標簽頭

長度為10個字節,位于文件首部,其數據結構如下:

char Header[3]; /* 字符串 "ID3" */

char Ver;       /* 版本號ID3V2.3 就記錄3 */

char Revision; /* 副版本號此版本記錄為0 */

char Flag;     /* 存放標志的字節,這個版本只定義了三位,很少用到,可以忽略 */

char Size[4]; /* 標簽大小,除了標簽頭的10 個字節的標簽幀的大小 */

標簽大小為四個字節,但每個字節只用低7位,最高位不使用,恒為0,其格式如下:
0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx

計算公式如下:

ID3V2_frame_size = (int)(Size[0] & 0x7F) << 21
                 | (int)(Size[1] & 0x7F) << 14
                  | (int)(Size[2] & 0x7F) << 7
                  | (int)(Size[3] & 0x7F) + 10;


標簽幀

每個標簽幀都有一個10字節的幀頭和至少一個字節的不固定長度的內容組成。它們是順序存放在文件中,由各自特定的標簽頭來標記幀的開始。其幀的結構如下:

char FrameID[4];   /*用四個字符標識一個幀,說明其內容 */

char Size[4];      /* 幀內容的大小,不包括幀頭,不得小于1 */

char Flags[2];     /* 存放標志,只定義了6 位,此處不再說明 */

常用幀標識:

TIT2:標題
TPE1
:作者
TALB
:專輯
TRCK
: 音軌,格式:N/M,N表示專輯中第幾首,M為專輯中歌曲總數
TYER
:年份
TCON
:類型
COMM
:備注,格式:“eng\0備注內容”,其中eng表示所使用的語言
幀大小為四個字節所表示的整數大小。


II, ID3V1

其數據結構如下:

char Header[3];    /* 標簽頭必須是"TAG"否則認為沒有標簽 */
char Title[30];    /*
標題 */
char Artist[30];   /*
作者 */
char Album[30];    /*
專集 */
char Year[4];      /*
出品年代 */
char Comment[28]; /*
備注 */
char reserve;      /*
保留 */
char track;;       /*
音軌 */
char Genre;        /*
類型 */

其實,關于最后31個字節還存在另外一個版本,就是30個字節的Comment和一個字節的Genre.

有了上述的這些信息,我們就可以自己寫代碼,從MP3文件中抓取信息以及修改文件名了。但是,如果真的想寫一個播放軟件,還是需要讀它的數據幀,并進行解碼。


III,
數據幀

數據幀往往有多個,至于有多少,由文件大小和幀大小來決定。每個幀都有一個四字節長的幀頭,接下來可能有兩個字節的CRC校驗,其存在由幀頭中的具體信息決定。接著就是幀的實體數據,也就是MAIN_DATA了。

A,幀頭結構如下:

位置     長度     描述
BIT  BITS
————————————————————————————
31
19   12       Frame sync(0xFFF)
18/17    2        Layer, 00 – reserved, 01 – Layer III
                         10 – Layer II, 11
Layer I
16       1         protection_bit, 0
意味著受CRC保護,幀頭后面跟16位的CRC。
15-12    4        bitrate_index,
比特率
11-10    2        sampling_frequency,    00 – 44.1KHz, 01 – 48KHz
                                         10 – 32 KHz,  11 –
保留
9        1        padding_bit,1
意味著幀里包含padding位,僅當采樣頻率為44.1KHz時發生。
8        1        private_bit
7
6     2        mode,    00stereo,        01-joint stereo(intensity stereo and/or ms_stereo)
                           
11- dual_channel, 11 – single_channel
5-4      2        mode_extension,
Layer III中表示使用了哪一種joint stereo編碼方式。
                            Intensity_stereo   ms_stereo
                   00            off                off
                   01            on                 off
                   10            off                on
                   11            on                 on
3        1        copyright,1
表示受版權保護。
2        1        original
0表示該bitstream是一個copy,1表示是original.
1-0      2        emphasis
,表示會使用哪一種de-emphasis。
                   00
no emphasis,     01 – 50/15 microsec. Emphasis
                   
10 – reserved,        11 – CCITT J.17

1)      無論幀長是多少,每幀的播放時間都是26ms

2)      數據幀大?。?/span>

FrameSize = 144 * Bitrate / SamplingRate + PaddingBit
144 * Bitrate / SamplingRate不能被8整除,則加上相應的paddingBit.

B,MAIN_DATA:

MP3granule包含18 * 32subband采樣。每個數據幀含有兩個granule的數據,其內容結如下:
       - main_data_end pointer
       - side info for both granules (scfsi)
       - side info granule 1
       - side info granule 2
       - scalefactors and Huffman code data granule 1
       - scalefactors and Huffman code data granule 2

主要數據里包含了scalefactors, Huffman encoded dataancillary information。其內容不再詳敘,可以參考MP3 SPECIS0 11172-3 AUDIO PART。我們一般用的都是立體聲,scfsi的長度為32個字節。

這里要解釋的一個概念就是位流――bitstream。我們平常接觸到的數據都是整數,最小的單位就是byte后者char。雖然我們也會用一個字節里的不同位來表示不同的含義,但總的來說,我們在出來數據的時候還是把它當作一個個字節看待。但對MP3這種數據格式來說,這是行不通的。在解碼時,它的數據輸入就是一個個比特流。其中一個或幾個比特會是你的采樣數據或者信息編碼。你需要從整個MAIN_DATA里提取你所需要的以BIT為單位的參數和輸入信號,從而進行解碼。所以我們需要一個子程序,getbit(n),也就是從緩沖中提取所需要的位,并形成一個新的整數,作為我們的輸出。

C,LAME標簽幀

可是,當你真的打開一個MP3文件的時候,你會發現,很奇怪,很多時候第一個數據幀的幀頭后面的32個字節居然都為0,這是為什么呢,這么奇怪的解碼信息該如何解釋?找到MP3 INFO TAG REV SPECIFICATION的網站,我才明白,原來第一幀并不是真正的數據幀,而是LAME編碼的標志幀。

這里又要牽涉到兩個概念:CBRVBR。CBR表示比特率不變,也就是每幀的長度是一致的,它以字符串“INFO”為標記。VBRVariable BitRate的簡稱,也就是每幀的比特率和幀的長度是變化的,它以字符串“Xing”為標記。同時,它還存放了MP3文件里幀的總個數,和100個字節的播放總時間分段的幀的INDEX,還有其他一些參數,這被稱為Zone A,傳統Xing VBR標簽數據,共120個字節。

在二進制文本編輯器里我們還可看到一個字符串“LAME”,并且后面清楚地跟著版本號。這就是20個字節的Zone B初始LAME信息,表示該文件是用LAME編碼技術。接下來一直到該幀結束就是Zone CLAME標簽。

3,      相關資料

× Mp3 Info Tag rev 1 specifications - draft 0

× MP3 文件格式

× MP3 SPECIS0 11172-3 AUDIO PART

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1688758