国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
MP3文件的ID3V1信息與ID3V2信息結(jié)構(gòu)的分析
MP3文件的ID3V1信息與ID3V2信息結(jié)構(gòu)的分析

——吳俊濤2005/05/05

E-mail:bo_tao@126.com  QQ:29248671

主 頁:http://wjt276.home4u.china.com(有源代碼)

 本人是一位編程愛好者,想通過VB。NET編寫一個(gè)可以讀取MP3文件的信息的不程序,可以不知道文件結(jié)構(gòu),呀我在網(wǎng)上找了好長時(shí)間(好幾個(gè)月)都沒有找到VB的。后來看到一個(gè)VC的,還附有結(jié)構(gòu)分析,太好了,動(dòng)手了。

一:“ID3v1”信息的分析

MP3的基本歌曲信息存在了MP3文件的最后128個(gè)字節(jié)里,其結(jié)構(gòu)是:
Public   Structure   ID3v1Info

Dim   ID3v1TAG   As   String   'TAG三個(gè)字母,ID3V1的標(biāo)識

Dim   Title   As   String   '存儲(chǔ)標(biāo)題信息,30個(gè)字節(jié)

Dim   Artist   As   String   '存儲(chǔ)歌手信息,30個(gè)字節(jié)

Dim   Album   As   String   '存儲(chǔ)專輯信息,30個(gè)字節(jié)

Dim   Year   As   String   '存儲(chǔ)年代信息,4個(gè)字節(jié)

Dim   Comments   As   String   '存儲(chǔ)備注信息,28個(gè)字節(jié)(有時(shí)為30字節(jié))

Dim   Genre   As   String   '存儲(chǔ)音樂風(fēng)格信息,保留位,1個(gè)字節(jié) 

Dim   Reserved   As   String   '保留位,1個(gè)字節(jié)(有時(shí)沒有意思

Dim   Track   As   String   '音軌(曲號)保留位,1個(gè)字節(jié)(有時(shí)沒有)

End   Structure

ID3V1信息存儲(chǔ)結(jié)構(gòu)如下(如圖1):

圖   1   一個(gè)MP3文件的ID3v1信息


1-3   TAG

4-33   歌曲名(Take   Me   To   Your   Heart   )

34-63   歌手名(Michael   Learns   to   Rock)

64-93   專輯名(Take   Me   to   Your   Heart)

94-97   年(2004)

98-125   備注   (http://www.uptu.com)

126 保留位,這時(shí)為0,則說明有音軌,下一位就是音軌

127 保留位,為音軌(第幾首歌)(OC)

128   保留位   (風(fēng)格)(66)

 

而在Winamp的ID3v1歌曲信息里(如圖1),我們看到的是他都包括:
Title(歌曲名)
Artist(歌手名)
Album(專輯名)
Year(年)
Comment(備注)
Genre(歌曲風(fēng)格)注,見下面有詳細(xì)的列表
Track#(歌曲在專輯里的順序,就是我們經(jīng)常說的“第幾首”)

Title,Artist,Album,Year,Comment我們都是可以在那個(gè)128個(gè)字節(jié)里得到,Genre和Track哪里去了呢?有的朋友都重視了那128字節(jié)信息的前125個(gè)信息了,而這兩個(gè)信息是卻放在了最后的126-128字節(jié)里。其實(shí),127那處就是Track信息,而  128處就是Genre信息。他們的存儲(chǔ)方式都不是字符,我們提取他們的時(shí)候需要注意,他們都是數(shù)字。比如,就如我們看到的這首歌的126處是0x0D,那么很顯然,他就是13。也就是第13號歌曲風(fēng)格,Pop流行(   下面列表)。

這時(shí),你也該猜到了,127和128都是有意義的,自然126處也是有其意義!ID3v1信息的Comment(注釋)一共占用28個(gè)字節(jié)。這個(gè)說法并不是完全的正確。準(zhǔn)確的說應(yīng)該是正確了一部分。有的時(shí)候注釋也可以超過這個(gè)數(shù)字的。ID3v1要求注釋最多可以到30個(gè)字節(jié)。那么有的讀者會(huì)問“MP3的  ID3v1就是得有130個(gè)字節(jié)的信息了嘛?”不是,當(dāng)然不是。ID3v1是固定的128個(gè)字節(jié),這個(gè)你不用擔(dān)心。其實(shí)ID3v1是這樣安排的:如果  MP3的注釋是大于28個(gè)字節(jié)的,那么就要借用126-127兩個(gè)字節(jié)。所以ID3v1的注釋部分可能是28個(gè)字節(jié)也可能是30個(gè)字節(jié)。那么,怎么區(qū)分到底是28個(gè)字節(jié)還是30個(gè)字節(jié)呢?很簡單,126處就是管這個(gè)的,我們只要看看126處是不是0x00,如果是0x00那么注釋就有28個(gè)字節(jié)。如果不等于0x00,那么就是說注釋是30個(gè)字節(jié)。同時(shí)別忘了,由于第127字節(jié)存儲(chǔ)了Track信息,那么如果注釋是30個(gè)字節(jié)的時(shí)候,這首歌的ID3v1里的那個(gè)127處的信息自然就不是Track信息了。Track自然就是沒有地方存了,所以127處變的沒有Track意義了,它只是Comment的一部分了。在你決定制作讀取ID3v1的程序的時(shí)候,請?zhí)貏e注意一下。

我們最終知道了126處是ID3v1信息的注釋部分到底是28個(gè)字節(jié)還是30個(gè)字節(jié)的標(biāo)志位。127處是音軌信息(Track),而Reserved3則是歌曲風(fēng)格(Genre)?,F(xiàn)在我們重新再寫一次結(jié)構(gòu)

原理2:MP3文件有沒有ID3v1信息的錯(cuò)誤理解
  那就是到底什么能叫做“MP3文件沒有ID3v1信息”。檢測的方法是先提取指定的MP3文件的最后128字節(jié)信息,然后確定這128個(gè)字節(jié)的前3個(gè)字節(jié)是“TAG”。很多朋友都會(huì)同意這個(gè)方法沒有問題的??墒?,實(shí)際上問題并不是那么簡單。

Winamp或者其他的MP3播放相關(guān)的軟件都有MP3信息的寫入和讀取的功能,然而這些寫入ID3v1的軟件都會(huì)不自覺的當(dāng)你一打開這個(gè)MP3文件就會(huì)給它加上這128個(gè)字節(jié)的信息。也就是說當(dāng)我們用這種軟件打開MP3文件的時(shí)候,這些軟件就會(huì)自動(dòng)的在這個(gè)MP3文件尾端添加了一個(gè)128字節(jié)的  ID3v1結(jié)構(gòu),而且還是以“TAG”開頭?。ㄈ鐖D3)。那么很顯然,光靠檢測那“TAG”三個(gè)字節(jié)的信息,還是不能完全確定MP3到底有沒有ID3v1 信息的。我們還要確定這“TAG”后的125字節(jié)是不是正確的信息。一般情況下,這類軟件產(chǎn)生的ID3v1結(jié)構(gòu)都是由一堆00,或者一堆空格組成的,所以我們要判斷一下是不是ID3v1的信息是一堆00或者一堆空格。如果是,那么MP3文件雖然有這“TAG”三個(gè)字母,卻仍然不是一個(gè)合法的ID3v1信息。MP3文件仍然應(yīng)該認(rèn)為沒有ID3v1信息。我覺得這個(gè)東西有必要特別提醒大家注意。

二:ID3v2信息的提取
MP3文件的“ID3v1信息”。這個(gè)信息結(jié)構(gòu)提取起來非常容易,寫入到文件也不是什么難事。但是它的信息安排和可擴(kuò)展性卻非常之差(只能128個(gè)字節(jié))。就如你所知,MP3文件還有另外的一個(gè)信息結(jié)構(gòu),這個(gè)結(jié)構(gòu)具有更好的可擴(kuò)展性,而且存儲(chǔ)的容量也不受限制(也就是總長度不固定)。這個(gè)信息就是  ID3v2信息(相對ID3v1而言)。由于ID3v1信息存儲(chǔ)在了文件的最后128個(gè)字節(jié)里,那么ID3v2就不得不放棄選擇存儲(chǔ)在文件的末尾了,于是它被存儲(chǔ)在了文件的起始位置。

ID3v2信息的存儲(chǔ)和讀取遠(yuǎn)遠(yuǎn)要比ID3v1信息復(fù)雜的多。這是因?yàn)镮D3v2信息不再固定,而且由于這段信息存儲(chǔ)在了文件的首端,所以重新寫入的時(shí)候也遠(yuǎn)比ID3v1麻煩的多。

我用盡可能清楚而且簡練的話,給大家講一下ID3v2信息的讀取方法。ID3v2到現(xiàn)在一共有4個(gè)版本,不過比較流行的MP3播放軟件一般只支持第3版,即ID3v2.3。我們要讀取的就是ID3v2.3信息。ID3v2信息包括兩個(gè)部分,一個(gè)部分是標(biāo)頭信息,另一個(gè)部分是標(biāo)體信息。其中標(biāo)頭信息占固定的十個(gè)字節(jié),

 每個(gè)ID3V2的標(biāo)簽部一個(gè)標(biāo)簽頭和若干個(gè)標(biāo)簽幀或一個(gè)擴(kuò)展標(biāo)簽組成關(guān)于曲目的信息如標(biāo)題、作者等都放在在不同的標(biāo)簽幀中,擴(kuò)展標(biāo)簽頭和標(biāo)簽幀關(guān)不是必要的,但每個(gè)標(biāo)簽至少要有一個(gè)標(biāo)簽頭和標(biāo)簽幀一直順序存放在MP3文件首部。

它的結(jié)構(gòu)如下:

(一)、標(biāo)簽頭

Private   Structure   ID3v2Header

  Dim   Header()   As   Byte 'ID3v2標(biāo)識位,應(yīng)該是“ID3”三個(gè)字母為對

  Dim   Ver   As   Byte '版本號ID3V2就記錄3

  Dim   Revision   As   Byte’副版本號此版本記錄為0

  Dim   Flag   As   Byte‘存放標(biāo)志的字節(jié),這個(gè)版本只定義了三位,稍后詳細(xì)解說

  Dim   Size()   As   Byte’標(biāo)簽大小,不包括標(biāo)簽頭的10個(gè)字節(jié)(但是有的文章說包括)我是通過核實(shí)   才這樣說的,看看源代碼就知道了

End   Structure

這十個(gè)字節(jié)的信息作用:

1、Header(2),一般為“ID3”,否則沒有ID3V2信息

2、Flag   標(biāo)志字節(jié):標(biāo)志字節(jié)一般為0,字義為abc00000

a-表示是否使用Unsynchronisation

b-表示是否有擴(kuò)展頭部,一般沒有(WINAMP也沒有)所以一般不設(shè)置

 c-表示是否為測試標(biāo)簽(99.9%的標(biāo)簽都不是測試用的,所以一般不設(shè)置)

3、Sixe(3) 標(biāo)簽大?。阂还菜膫€(gè)字節(jié),但每個(gè)字節(jié)只使用7位,最高位不使用恒為0,所以格式如下:

  0xxxxxxx   0xxxxxxx   0xxxxxxx   0xxxxxxx

 計(jì)算大小時(shí)要將0去掉,得到一個(gè)28位的二進(jìn)制數(shù),就是標(biāo)簽的大,計(jì)算公式如下

  ①、VC的:ID3size   =(Size[0]&0x7F)*0x200000  +(Size[1]&0x7F)*0x400   +(Size[2]&0x7F)*0x80  +(Size[3]&0x7F);

②、VB的:ID3size   =Size(0)   *   (2   ^  21)   +   Size(1)   *   (2   ^   14)   +   Size(2)   *   (2   ^   7)   +  Size(3)   *   (2   ^   0)

VB的我已在類中聲明了一個(gè)函數(shù)ByteToLong,很方便,直調(diào)用就OK了。

通過解析這段標(biāo)頭信息我們可以知道一個(gè)MP3文件是不是有ID3v2信息,如果有我們就知道了ID3v2的數(shù)據(jù)體的總長度。

(二)、標(biāo)簽幀

  接下來我們要解析ID3v2的   標(biāo)簽幀,別擔(dān)心,雖然復(fù)雜,但也沒你想象的那么的痛苦。ID3v2的數(shù)據(jù)體又分為很多相同的數(shù)據(jù)結(jié)構(gòu)。

每個(gè)標(biāo)簽幀都有一個(gè)10個(gè)字節(jié)的幀頭和至少一個(gè)字節(jié)的不固定長度的內(nèi)容組成,它們也是順序存放在文件中,和標(biāo)簽頭和其他的標(biāo)簽幀也沒有特殊的字符分隔,得到一個(gè)完整的幀的內(nèi)容只有從幀頭中的到內(nèi)容大小 后才能讀出,讀取時(shí)要注意大小,不要將其它的幀的內(nèi)容或幀頭讀入。幀的定義如下:

Private   Structure   ID3v2Frame

  Dim   FrameID   As   String‘用4個(gè)字符標(biāo)識一個(gè)幀,說明其內(nèi)容,常用的標(biāo)識對照表見附表

  Dim   Size()   As   Byte’4個(gè)字節(jié) 幀內(nèi)容的大小,不包括幀頭,不得小于1,計(jì)算時(shí)也用上面的公式計(jì)算

  Dim   Flags()   As   Byte’2個(gè)字節(jié) 存放標(biāo)志,只定義了6位,稍后詳細(xì)解說

End   Structure 

 1、FrameID   幀標(biāo):用四個(gè)字符標(biāo)識一個(gè)幀的內(nèi)容含義,常用的對照如下:

TEXT:   歌詞作者   TENC:   編碼
WXXX:   URL鏈接(URL)   TCOP:   版權(quán)(Copyright)
TOPE:   原藝術(shù)家   TCOM:   作曲家
TDAT:   日期   TPE3:   指揮者
TPE2:   樂隊(duì)   TPE1:   藝術(shù)家相當(dāng)于ID3v1的Artist
TPE4:   翻譯(記錄員、修改員)   TYER:   年代相當(dāng)于ID3v1的Year
USLT:   歌詞   TALB:   專輯相當(dāng)于ID3v1的Album
TIT1:   內(nèi)容組描述   TIT2:   標(biāo)題相當(dāng)于ID3v1的Title
TIT3:   副標(biāo)題   TCON:   流派(風(fēng)格)相當(dāng)于ID3v1的Genre見下表
TBPM:   每分鐘節(jié)拍數(shù)   COMM:   注釋相當(dāng)于ID3v1的Comment
TDLY:   播放列表返錄   TRCK:   音軌(曲號)相當(dāng)于ID3v1的Track
TFLT:   文件類型   TIME:   時(shí)間 
TKEY:   最初關(guān)鍵字   TLAN:   語言
TLEN:   長度   TMED:   媒體類型
TOAL:   原唱片集   TOFN:   原文件名
TOLY:   原歌詞作者   TORY:   最初發(fā)行年份
TOWM:   文件所有者(許可證者)   TPOS:   作品集部分
TPUB:   發(fā)行人   TRDA:   錄制日期
TRSN:   Intenet電臺名稱   TRSO:   Intenet電臺所有者
TSIZ:   大小       TSRC:   ISRC(國際的標(biāo)準(zhǔn)記錄代碼)
TSSE:   編碼使用的軟件(硬件設(shè)置)   UFID:   唯一的文件標(biāo)識符
AENC:   音頻加密技術(shù)        

其中要說明的是這個(gè)FrameID,在ID3v1里我們是根據(jù)每一個(gè)信息所占用的固定的字節(jié)數(shù)和位置來判斷他是哪個(gè)信息的。而ID3v2為了提供更好的可擴(kuò)展性,把這些信息變得“動(dòng)態(tài)”化了,因?yàn)殚L度并不是預(yù)先設(shè)定好的,而是在size[4]里存儲(chǔ)的。這樣長度就可以不再固定了。我覺得在我們自己定義文件的時(shí)候ID3v2和ID3v1也是值得我們考慮的一個(gè)方面。如果結(jié)構(gòu)很小而且存儲(chǔ)的量也不大,我們可以采用ID3v1的信息存儲(chǔ)方式。如果存儲(chǔ)的信息不固定,而且要求有很好的可擴(kuò)展性,那么ID3v2當(dāng)然成了首選。實(shí)際上,現(xiàn)在很多格式的文件的存儲(chǔ)方式都是ID3v2的存儲(chǔ)方式非常接近的。

2、Size() 幀內(nèi)容大?。翰辉偈强倶?biāo)頭那樣的每個(gè)字節(jié)只取后7位了,它是按照正常的8位存儲(chǔ)的。得到幀內(nèi)容的大小的格式如下?。?

xxxxxxxx   xxxxxxxx   xxxxxxxx   xxxxxxxx

 計(jì)算成整形,公式如下:

     ①、VC的:   FSize   =   Size[0]*0x100000000   +   Size[1]*0x10000   +   Size[2]*0x100   +   Size[3];

②、VB的:ID3size   =Size(0)   *   (2   ^   21)   +   Size(1)   *   (2   ^  14)   +   Size(2)   *   (2   ^   7)   +   Size(3)   *   (2   ^   0)

VB的我已在類中聲明了一個(gè)函數(shù)ByteToLong,很方便,直調(diào)用就OK了。

3、Flags() 標(biāo)志:只定義了6位,另外10位為0 但大部分的情況下16位都為0就可以了,格式如下:

 a-標(biāo)簽保護(hù)標(biāo)志,設(shè)置時(shí)認(rèn)為此幀作廢

b-文件保護(hù)標(biāo)志,設(shè)置時(shí)認(rèn)為此幀作廢

c-只讀標(biāo)志,設(shè)置時(shí)認(rèn)為此幀不能修改(目前好像沒有看到過)

i-壓縮標(biāo)志,設(shè)置時(shí)一個(gè)字節(jié)存放兩個(gè)BCD碼表示數(shù)字

j-加密標(biāo)志(好像不太實(shí)用)

k-組標(biāo)志,設(shè)置時(shí)說明此幀和其它的某幀是一組。


  詳細(xì)你可能到www.ID3.org去了解一下。

4、幀內(nèi)容(數(shù)據(jù)體)


標(biāo)頭后面就是數(shù)據(jù)體了,我們提取數(shù)據(jù)體的前十個(gè)字節(jié),我們知道了這個(gè)數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)的FrameID是TIT2,查上面的表,說明這個(gè)數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)的是歌曲名信息。大小是00   00   00   17,換成十進(jìn)制就是23。也就是歌曲名是這個(gè)子標(biāo)頭后的23個(gè)字節(jié)的信息。也就是:“Take  Me   To   Your   Heart   ”。接下來的一個(gè)數(shù)據(jù)結(jié)構(gòu)的FrameID是TPE1,說明是歌手名,而大小是00   00  00   17,說明這個(gè)數(shù)據(jù)體有23個(gè)字節(jié),也就是:“Michael   Learns   to  Rock”。依次類推。這里需要大家知道的是一個(gè)漢字占用兩個(gè)字節(jié)。在寫入時(shí),要計(jì)算字節(jié)數(shù),我已編寫了一個(gè)函數(shù)ByteSize,大家可以直接使用了。

還有特別要提醒大家的是,ID3v2的注釋信息(FrameID是COMM)的數(shù)據(jù)體的前四(但經(jīng)我測試為前5個(gè)字節(jié))個(gè)字節(jié),并不是注釋內(nèi)容,而是注釋使用的自然語言,這個(gè)例子里我們看到是:”eng\0”,我們要跳過這四個(gè)字節(jié)的信息進(jìn)行解析。此外ID3v2的歌曲類型Genre(FrameID是  TCON)的存儲(chǔ)也不太一樣的。由于很多MP3播放器的寫入方式并不是非常一致,而在Genre寫入的也不一致。比如,這首歌的ID3v2的Genre是  Classic   Rock,其實(shí)有的還會(huì)寫入成:(1),或者1,還有(1)Classic  Rock,所以格式五花八門,我們要在解析的時(shí)候注意一下。還有,值得一提的是winamp在保存和讀取幀內(nèi)容的時(shí)候會(huì)在內(nèi)容前面加個(gè) '\0',并把這個(gè)字節(jié)計(jì)算在幀內(nèi)容的大小中。所以前面提到的歌手名“Michael   Learns   to  Rock”本身應(yīng)該22個(gè)字節(jié),可是卻占了23個(gè)字節(jié)。

源代碼已發(fā)布,你可以到本站點(diǎn)的主頁去下載,如有什么問題,請一定聯(lián)系我呀,不要客氣軾呀

您如有什么問題,可以發(fā)E-MAIL給我,我們一起來討論,主頁里有源代碼和實(shí)例,有興趣的朋友不訪去看看   http://wjt276.home4u.china.com

作者:吳俊濤       時(shí)間:2005/05/05
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
MP3文件的數(shù)據(jù)結(jié)構(gòu)以及為mp3內(nèi)嵌歌詞的代碼 — 編程愛好者論壇http://b...
ID3文件格式
超級整合:MP3終極選購使用技巧33條
將配置保存到EXE本身(生成EXE木馬程序)
R語言之內(nèi)存管理
Struts標(biāo)簽:<bean:size>
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服