MP3的全稱是MPEG Audio Layer3,它是一種高效的計算機音頻編碼方案,它以較大的壓縮比將音頻文件轉換成較小的擴展名為.MP3的文件,基本保持原文件的音質。MP3是ISO/MPEG標准的一部分,ISO/MPEG標准描述了使用高性能感知編碼方案的音頻壓縮,此標准一直在不斷更新以滿足“質高量小”的追求,現已形成MPEGLayer1、Layer2、Layer3三個音頻編碼解碼方案。MPEGLayer3壓縮率可達1:10至1:12,1M的MP3文件可播放1分鍾,而1分鍾CD音質的WAV文件(44100Hz,16bit,雙聲道,60秒)要占用10M空間,這樣算來,一張650M的MP3光盤播放時間應在10小時以上,而同樣容量的一張CD盤播放時間在70分鍾左右。MP3的優勢是CD難以比擬的。
MPEG Audio 標准
MPEG(MovingPictureExpertsGroup)是ISO下的一個動態圖 像專家組,它制定的MPEG標准廣泛應用於各種多媒體中。 MPEG標准包括視頻和音頻標准,其中音頻標准已制定出MPEG-1、MPEG-2、MPEG-2AAC和MPEG-4。
MPEG-1和MPEG-2標准使用同一個音頻編碼解碼族—Layer1、2、3。MPEG-2一個新特點是采用低采樣率擴展降低數據流量,另一特點是多通道擴展,將主聲道增加為5個。MPEG-2AAC(MPEG-2AdvancedAudioCoding)標准是FraunhoferIIS 同AT&T公司於1997年推出的,旨在顯著減少數據流量,MPEG22AAC采用的修正的離散余弦變換(MDCT,ModifiedDiscreteCo2sineTransform)算法,采樣率可在8KHz到96KHz之間,聲道數可在1-48之間。
MPEG Audio Layer1、2、3三個層使用相同的濾波器組、位流結構和頭信息,采樣頻率為32KHz、4411KHz或48KHz。Layer1是為數字壓縮磁帶DCC(DigitalCompactCassette)設計的,數據流量為384kbps,Layer2在復雜性和性能間作了權衡,數據流量下降到256kbps-192kbps。Layer3一開始就為低數據流量而設計,數據流量在128kbps-112kbps,Layer3增加了MDCT變換,使其頻率分辨能力是Layer2的18倍,Layer3還使用了與MPEGVid2eo類似的平均信息量編碼(EntropyCoding),減少了冗余信息。MP3絕大部分使用的是MPEG21標准。
音頻壓縮
MP3格式始於80年代中期,德國Erlangen的Fraunhofer研究 所致力於高質量、低數據率的聲音編碼。
MP3音頻壓縮包含編碼和解碼兩個部分。編碼是將WAV文件中的數據轉換成高壓縮率的位流形式,解碼是接受位流並將其重建到WAV文件中。
MP3采用了感知音頻編碼(PerceptualAudioCoding)這一失真算法。人耳感受聲音的頻率范圍是20Hz-220kHz,MP3截掉了大量的冗余信號和無關的信號,編碼器通過混合濾波器組將原始聲音變換到頻率域,利用心理聲學模型,估算剛好能被察覺到的噪聲水平,再經過量化,轉換成Huffman編碼,形成MP3位流。解碼器要簡單得多,它的任務是從編碼后的譜線成分中,經過反 量化和逆變換,提取出聲音信號。
在壓縮音頻數據時,先將原始聲音數據分成固定的分塊,然后作順向MDCT變換,MDCT本身並不進行數據壓縮,只是將一組時域數據轉換成頻域數據,以得知時域變化情況,順向MDCT將每塊的值轉換為512個MDCT系數。量化使數據得到壓縮,在對量化后的變換樣值進行比特分配時要考慮使整個量化塊最小,這就成為有損壓縮了。解壓時,經反向MDCT將512個系數還原成原始聲音數據,前后的原始聲音數據是不一致的,因為在壓縮過程中,去掉了冗余和不相關數據。
MP3文件結構
MP3 文件大體分為三部分:TAG_V2(ID3V2),Frame, TAG_V1(ID3V1)
ID3V2 | 包含了作者,作曲,專輯等信息,長度不固定,擴展了ID3V1的信息量 |
Frame
|
一系列的幀,個數有文件大小和幀長決定 每個FRAM的長度可能不固定,也可能固定,由位率bitrate決定 每個FRAME由分為幀頭和數據實體兩部分 幀頭記錄了mp3的位率,采樣率,版本等信息,每個幀之間相互獨立 |
ID3V1 | 包含了作者,作曲,專輯等信息,長度為128BYTE |
1. 幀頭格式
下面是一個頭內容圖示,使用字符 A 到 M 表示不同的區域。在表格中你可以看到每一區域
的詳細內容。
AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
關於讀取幀頭我使用了下面的方法
定義一個結構體
typedef struct frameHeader
{
unsigned int sync1:8; //同步信息 1
unsigned int error_protection:1; //CRC 校驗
unsigned int layer:2; //層
unsigned int version:2; //版本
unsigned int sync2:3; //同步信息 2
unsigned int extension:1; //版權
unsigned int padding:1; //填充空白字
unsigned int sample_rate_index:2; //采樣率索引
unsigned int bit_rate_index:4; //位率索引
unsigned int emphasis:2; //強調方式
unsigned int original:1; //原始媒體
unsigned int copyright:1; //版權標志
unsigned int mode_extension:2; //擴展模式,僅用於聯合立體聲
unsigned int channel_mode:2; //聲道模式
}FHEADER, *pFHEADER;請注意我的同步信息分成了兩個部分,而且其他的位的順序也和上表列出的有所差別,這個
主要是因為 c 語言在存取數據時總是從低位開始,而這個幀頭是需要從高位來讀取的。
讀取方式如下
FHEADER header;
fread( &header, sizeof( FHEADER ), 1, streams );//這里假設文件已打開,讀取位置已經指向幀
頭所在的位置
這樣一次就可以讀入幀頭的所有信息了。
2、如何計算幀長度
我們首先區分兩個術語:幀大小和幀長度。幀大小即每幀采樣數表示一幀中采樣的個數,這是恆定值。其值入下表所示
幀長度是壓縮時每一幀的長度,包括幀頭。它將填充的空位也計算在內。LayerI 的一個空位長 4 字節,LayerII 和 LayerIII 的空位是 1 字節。當讀取 MPEG 文件時必須計算該值以便找到相鄰的幀。
注意:因為有填充和比特率變換,幀長度可能變化。
從頭中讀取比特率,采樣頻率和填充,
LyaerI 使用公式:
幀長度(字節) = (( 每幀采樣數 / 8 * 比特率 ) / 采樣頻率 ) + 填充 * 4
LyerII 和 LyaerIII 使用公式:
幀長度(字節)= (( 每幀采樣數 / 8 * 比特率 ) / 采樣頻率 ) + 填充
例:
LayerIII 比特率 128000,采樣頻率 44100,填充 0
=〉幀大小 417 字節
3、每幀的持續時間
之前看了一些文章都說 mp3 的一幀的持續時間是 26ms,結果在實際程序的編寫中發現無法正確按時間定位到幀,然后又查了一些文章才知道,所謂 26ms 一幀只是針對 MPEG1 Layer III 而且采樣率為 44.1KHz 來說是對的,但 mp3 文件並不都是如此,其實這個時間也是可以通過計算來獲得,下面給出計算公式
每幀持續時間(毫秒) = 每幀采樣數 / 采樣頻率 * 1000
這樣通過計算可知 MPEG1 Layer III 采樣率為 44.1KHz 的一幀持續時間為 26.12...不是整數,不過我們權且認為它就是 26 毫秒吧。
如果是 MPEG2 Layer III 采樣率為 16KHz 的話那一幀要持續 36 毫秒,這個相差還是蠻大的,所以還是應該通過計算來獲的,當然可以按 MPEG 版本,層數和采樣率來建一個表,這樣直接查表就可以知道時間了。
5、幀數據
在幀頭后邊是 Side Info(姑且稱之為通道信息)。對標准的立體聲 MP3 文件來說其長度為 32字節。通道信息后面是 Scale factor(增益因子)信息。當解碼器在讀到上述信息后,就可以進行解碼了。當 MP3 文件被打開后,播放器首先試圖對幀進行同步,然后分別讀取通道信息及增益因子等數據,再進行霍夫曼解碼,至此我們已經獲得解壓后的數據。但這些數據仍然不能進行播放,它們還處於頻域,要想聽到歌曲還要將它由頻域通過特定的手段轉換到時域。接下來的處理分別為立體化處理;抗鋸齒處理;IMDCT 變換;IDCT 變換及窗口化滑動處理。
我們知道,對於 mp3 來說現在有兩種編碼方式,一種是 CBR,也就是固定位率,固定位率的幀的大小在整個文件中都是是固定的(公式如上所述),只要知道文件總長度,和從第一幀幀頭讀出的信息,就都可以通過計算得出這個 mp3 文件的信息,比如總的幀數,總的播放時間等等,要定位到某一幀或某個時間點也很方便,這種編碼方式不需要文件頭,第一幀開始就是音頻數據。另一種是 VBR,就是可變位率,VBR 是 XING 公司推出的算法,所以在 MP3 的 FRAME 里會有“Xing"這個關鍵字(也有用"Info"來標識的,現在很多流行的小軟件也可以進行 VBR 壓縮,它們是否遵守這個約定,那就不得而知了),它存放在 MP3文件中的第一個有效幀的數據區里,它標識了這個 MP3 文件是 VBR 的。同時第一個幀里存放了 MP3 文件的幀的總個數,這就很容易獲得了播放總時間,同時還有 100 個字節存放了播放總時間的 100 個時間分段的幀索引,假設 4 分鍾的 MP3 歌曲,240S,分成 100 段,每兩個相鄰 INDEX 的時間差就是 2.4S,所以通過這個 INDEX,只要前后處理少數的FRAME,就能快速找出我們需要快進的幀頭。其實這第一幀就相當於文件頭了。不過現在有些編碼器在編碼 CBR 文件時也像 VBR 那樣將信息記入第一幀,比如著名的 lame,它使用"Info"來做 CBR 的標記。
6、VBR 頭
這里列出 VBR 的第一幀存儲文件信息的頭的格式。有兩種格式,一種是常見的 XING Header
(頭部包含字符‘Xing’)
,另一種是 VBRI Header (頭部包含字符‘VBRI’)鑒於 VBRI Header
不 常 見 , 下 面 只 說 XING Header , 關 於 VBRI Header 請 看
http://www.codeproject.com/audio/MPEGAudioInfo.asp。
XING Header 的起始位置,相對於第一幀幀頭的位置,單位是字節
36-39 "Xing"
21-24 "Xing"
21-24 "Xing"
13-16 "Xing"
文件為 MPEG1 並且不是單聲道(大多數 VBR 的 mp3 文件都是如此)
文件為 MPEG1 並且是單聲道
文件為 MPEG2 並且不是單聲道
文件為 MPEG2 並且是單聲道
XING Header 格式
這樣算來,XING Header 包括幀頭一共最多只需要 156 個字節就夠了。當然也可以在 XING
Header 后面存儲編碼器的信息,比如 lame 在其后就是存儲其版本,這需要給第一幀留足夠
的空間才行。
至於 mp3 的信息用從 XING Header 讀出的信息就可以計算
比如
總持續時間 = 總幀數 * 每幀采樣數 / 采樣率 (結果為秒)
平均位率 = 文件長度 / 總持續時間 * 8
MPEG 音頻標簽
MPEG 音頻標簽分為兩種,一種是 ID3v1,存在文件尾部,長度 128 字節,另一種是 ID3v2,
是對 ID3v1 的擴展,存在文件頭部,長度不定。
1、ID3v1
ID3v1 標簽用來描述 MPEG 音頻文件。包含藝術家,標題,唱片集,發布年代和流派。另
外還有額外的注釋空間。位於音頻文件的最后固定為 128 字節。可以讀取該文件的最后這
128 字節獲得標簽。
結構如下
AAABBBBB BBBBBBBB BBBBBBBB BBBBBBBB
BCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCD
DDDDDDDD DDDDDDDD DDDDDDDD DDDDDEEE
EFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFG
該規格要求所有的空間必須以空字符(ASCII 0)填充。但是並不是所有的應用程序遵循該規
則,比如 winamp 就用空格(ASCII 32)代替之。
在 ID3v1.1 結構中有些改變。注釋部分的最后一個字節用來定義唱片集中的軌道號。如果不
知道該信息時可以用空字符(ASCII 0)代替。
流派使用原碼表示,為下列數字之一:
Winamp 擴充了這個表
其他任何的數值都認為是“unknown”
2、ID3V2
ID3V2 到現在一共有 4 個版本,但流行的播放軟件一般只支持第 3 版,既 ID3v2.3。由於
ID3V1 記錄在 MP3 文件的末尾,ID3V2 就只好記錄在 MP3 文件的首部了(如果有一天發
布 ID3V3,真不知道該記錄在哪里)。也正是由於這個原因,對 ID3V2 的操作比 ID3V1 要
慢。而且 ID3V2 結構比 ID3V1 的結構要復雜得多,但比前者全面且可以伸縮和擴展。
下面就介紹一下 ID3V2.3。
每個 ID3V2.3 的標簽都一個標簽頭和若干個標簽幀或一個擴展標簽頭組成。關於曲目的信息如標題、作者等都存放在不同的標簽幀中,擴展標簽頭和標簽幀並不是必要的,但每個標
簽至少要有一個標簽幀。標簽頭和標簽幀一起順序存放在 MP3 文件的首部。
(一)、標簽頭
在文件的首部順序記錄 10 個字節的 ID3V2.3 的頭部。數據結構如下:
char Header[3]; /*必須為"ID3"否則認為標簽不存在*/
char Ver; /*版本號 ID3V2.3 就記錄 3*/
char Revision; /*副版本號此版本記錄為 0*/
char Flag; /*存放標志的字節,這個版本只定義了三位,稍后詳細解說*/
char Size[4]; /*標簽大小,包括標簽頭的 10 個字節和所有的標簽幀的大小*/
注:對這里我有疑惑,因為在實際尋找首幀的過程中,我發現有的 mp3 文件的標簽大小是不
包含標簽頭的,但有的又是包含的,可能是某些 mp3 編碼器寫標簽的 BUG,所以為了兼容
只好認為其是包含的,如果按大小找不到,再向后搜索,直到找到首幀為止。
(1).標志字節
標志字節一般為 0,定義如下:
abc00000
a -- 表示是否使用 Unsynchronisation(這個單詞不知道是什么意思,字典里也沒有找到,一般
不設置)
b -- 表示是否有擴展頭部,一般沒有(至少 Winamp 沒有記錄),所以一般也不設置
c -- 表示是否為測試標簽(99.99%的標簽都不是測試用的啦,所以一般也不設置)
(2).標簽大小
一共四個字節,但每個字節只用 7 位,最高位不使用恆為 0。所以格式如下
0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
計算大小時要將 0 去掉,得到一個 28 位的二進制數,就是標簽大小(不懂為什么要這樣做),
計算公式如
下:
int total_size;
total_size = (Size[0]&0x7F)*0x200000
+(Size[1]&0x7F)*0x4000
+(Size[2]&0x7F)*0x80
+(Size[3]&0x7F)
(二)、標簽幀
每個標簽幀都有一個 10 個字節的幀頭和至少一個字節的不固定長度的內容組成。它們也是
順序存放在文件
中,和標簽頭和其他的標簽幀也沒有特殊的字符分隔。得到一個完整的幀的內容只有從幀頭
中的到內容大
小后才能讀出,讀取時要注意大小,不要將其他幀的內容或幀頭讀入。
幀頭的定義如下:
char FrameID[4]; /*用四個字符標識一個幀,說明其內容,稍后有常用的標識對照表*/char Size[4]; /*幀內容的大小,不包括幀頭,不得小於 1*/
char Flags[2]; /*存放標志,只定義了 6 位,稍后詳細解說*/
(1).幀標識
用四個字符標識一個幀,說明一個幀的內容含義,常用的對照如下:
TIT2=標題 表示內容為這首歌的標題,下同
TPE1=作者
TALB=專集
TRCK=音軌 格式:N/M 其中 N 為專集中的第 N 首,M 為專集中共 M 首,N 和 M 為
ASCII 碼表示的數字
TYER=年代 是用 ASCII 碼表示的數字
TCON=類型 直接用字符串表示
COMM=備注 格式:"eng\0 備注內容",其中 eng 表示備注所使用的自然語言
(2).大小
這個可沒有標簽頭的算法那么麻煩,每個字節的 8 位全用,格式如下
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
算法如下:
int FSize;
FSize = Size[0]*0x1000000
+Size[1]*0x10000
+Size[2]*0x100
+Size[3];
(3).標志
只定義了 6 位,另外的 10 位為 0,但大部分的情況下 16 位都為 0 就可以了。格式如下:
abc00000 ijk00000
a -- 標簽保護標志,設置時認為此幀作廢
b -- 文件保護標志,設置時認為此幀作廢
c -- 只讀標志,設置時認為此幀不能修改(但我沒有找到一個軟件理會這個標志)
i -- 壓縮標志,設置時一個字節存放兩個 BCD 碼表示數字
j -- 加密標志(沒有見過哪個 MP3 文件的標簽用了加密)
k -- 組標志,設置時說明此幀和其他的某幀是一組
值得一提的是 winamp 在保存和讀取幀內容的時候會在內容前面加個'\0',並把這個字節計
算在幀內容的
大小中。
附:幀標識的含義
(4). Declared ID3v2 frames
The following frames are declared in this draft.AENC Audio encryption
APIC Attached picture
COMM Comments
COMR Commercial frame
ENCR Encryption method registration
EQUA Equalization
ETCO Event timing codes
GEOB General encapsulated object
GRID Group identification registration
IPLS Involved people list
LINK Linked information
MCDI Music CD identifier
MLLT MPEG location lookup table
OWNE Ownership frame
PRIV Private frame
PCNT Play counter
POPM Popularimeter
POSS Position synchronisation frame
RBUF Recommended buffer size
RVAD Relative volume adjustment
RVRB Reverb
SYLT Synchronized lyric/text
SYTC Synchronized tempo codes
TALB Album/Movie/Show title
TBPM BPM (beats per minute)
TCOM Composer
TCON Content type
TCOP Copyright message
TDAT Date
TDLY Playlist delay
TENC Encoded by
TEXT Lyricist/Text writer
TFLT File type
TIME Time
TIT1 Content group description
TIT2 Title/songname/content description
TIT3 Subtitle/Description refinement
TKEY Initial key
TLAN Language(s)
TLEN Length
TMED Media type
TOAL Original album/movie/show title
TOFN Original filename
TOLY Original lyricist(s)/text writer(s)TOPE Original artist(s)/performer(s)
TORY Original release year
TOWN File owner/licensee
TPE1 Lead performer(s)/Soloist(s)
TPE2 Band/orchestra/accompaniment
TPE3 Conductor/performer refinement
TPE4 Interpreted, remixed, or otherwise modified by
TPOS Part of a set
TPUB Publisher
TRCK Track number/Position in set
TRDA Recording dates
TRSN Internet radio station name
TRSO Internet radio station owner
TSIZ Size
TSRC ISRC (international standard recording code)
TSSE Software/Hardware and settings used for encoding
TYER Year
TXXX User defined text information frame
UFID Unique file identifier
USER Terms of use
USLT Unsychronized lyric/text transcription
WCOM Commercial information
WCOP Copyright/Legal information
WOAF Official audio file webpage
WOAR Official artist/performer webpage
WOAS Official audio source webpage
WORS Official internet radio station homepage
WPAY Payment
WPUB Publishers official webpage
WXXX User defined URL link frame
MP3 文件實例剖析
在 VC++中打開一個名為 test.mp3 文件,其內容如下:
000000 FF FB 52 8C 00 00 01 49 09 C5 05 24 60 00 2A C1
000010 19 40 A6 00 00 05 96 41 34 18 20 80 08 26 48 29
000020 83 04 00 01 61 41 40 50 10 04 00 C1 21 41 50 64
......
0000D0 FE FF FB 52 8C 11 80 01 EE 90 65 6E 08 20 02 30
0000E0 32 0C CD C0 04 00 46 16 41 89 B8 01 00 08 36 48
0000F033 B7 00 00 01 02 FF FF FF F4 E1 2F FF FF FF FF
......
0001A0 DF FF FF FB 52 8C 12 00 01 FE 90 58 6E 09 A0 02
0001B0 33 B0 CA 85 E1 50 01 45 F6 19 61 BC 26 80 28 7C
0001C0 05 AC B4 20 28 94 FF FF FF FF FF FF FF FF FF FF......
001390 7F FF FF FF FD 4E 00 54 41 47 54 45 53 54 00 00
0013A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
......
0013F000 00 00 00 04 19 14 03 00 00 00 00 00 00 00 00
001400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
001410 00 00 00 00 00 00 4E
該文件長度 1416H(5.142K),幀頭為:FF FB 52 8C,轉換成二進制為:
11111111 11111011
01010010 10001100
對照表 1 可知,test.mp3 幀頭信息見表 5。
表 5 test.mp3 文件幀頭信息
第 1397H 開始的三個字節是 54 41 47,存放的是字符“TAG”,表示此文件有 ID3 V1.0 信息。
139AH 開始的 30 個字節存放歌名,前 4 個非 00 字節是 54 45 53 54,表示“TEST”;
13F4H 開始的 4 個字節是 04 19 14 03,存放年份“04/25/2003”;
最后 1 個字節是 4E,表示音樂類別,代號為 78,即“Rock&Roll”;
其它字節均為 00,未存儲信息。
原文鏈接: https://wenku.baidu.com/view/d4877350ad02de80d4d840cb.html
原文鏈接: https://wenku.baidu.com/view/a071bf4e852458fb770b56a0.html