轉自:http://blog.163.com/waft_xu/blog/static/438152942008139330707/
1, MP3簡介
MP3是今天一種常見的音樂格式,但恐怕除了工作要求之外,有興趣對此進行研究的人恐怕不多。所以,當我打算做MP3解碼方面的工作時,在找資料時也頗費了一番周折,同時也覺得很有趣。所以想在這裏分享一下自己的心得,做一個總結性的介紹。這樣有興趣的同志也可以對此有一個大概瞭解,儘快入門。
MP3是MPEG-1 Audio Layer 3的簡稱,是當今比較流行的一種數字音頻編碼和有損壓縮格式(有Layer 3,也必然有Layer1和Layer2,也就是MP1和MP2,但不在本文討論範圍之內)。MP3技術的應該可以用來大幅度的降低音頻文件存儲所需要的空間。它丟掉脈衝編碼調製(PCM)音頻數據中對人類聽覺不重要得數據,從而達到了較高的壓縮比(高達12:1-10:1)。簡單地說,MP3在編碼時先對音頻文件進行頻譜分析,然後用過濾器濾掉噪音電平,接着通過量化的方式將剩下的每一位打散排列,最後形成有較高壓縮比的MP3文件,並使壓縮後的文件在回放時也能夠達到比較接近原音源的效果。
MP3的音頻質量取決於它的Bitrate和Sampling frequency,以及編碼器質量。MP3的典型速度介於每秒128到320kb之間。採樣頻率也有44.1,48和32 kHz三種頻率,比較常見的是採用CD採樣頻率——44.1kHz。常用的編碼器是LAME,它完全遵循LGPL的MP3編碼器,有着良好的速度和音質。
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, 00-stereo, 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) 數據幀大小:
FrameSize = 144 * Bitrate / SamplingRate + PaddingBit
當144 * Bitrate / SamplingRate不能被8整除,則加上相應的paddingBit.
B,MAIN_DATA:
MP3的granule包含18 * 32個subband採樣。每個數據幀含有兩個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 data和ancillary information。其內容不再詳敘,可以參考MP3 SPEC-IS0 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編碼的標誌幀。
這裏又要牽涉到兩個概念:CBR和VBR。CBR表示比特率不變,也就是每幀的長度是一致的,它以字符串“INFO”爲標記。VBR是Variable BitRate的簡稱,也就是每幀的比特率和幀的長度是變化的,它以字符串“Xing”爲標記。同時,它還存放了MP3文件裏幀的總個數,和100個字節的播放總時間分段的幀的INDEX,還有其他一些參數,這被稱爲Zone A,傳統Xing VBR標籤數據,共120個字節。
在二進制文本編輯器裏我們還可看到一個字符串“LAME”,並且後面清楚地跟着版本號。這就是20個字節的Zone B初始LAME信息,表示該文件是用LAME編碼技術。接下來一直到該幀結束就是Zone C-LAME標籤。
3, 相關資料
× Mp3 Info Tag rev 1 specifications - draft 0
× MP3 文件格式
× MP3 SPEC-IS0 11172-3 AUDIO PART