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) 數據幀大?。?/span>
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
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1688758