|
2, MP3文件格式
+ V$ |. ?8 c( w. H1 E8 s8 ^# o5 D0 _: k
用一个二进制查看器(比如Ultra-Edit)打开一个MP3文件,就能看到一大堆看似杂乱无序的数据。但只要用心了解就会知道,其实,这一切都是有章可循的。2 T6 D9 [: p( P* o
8 y) y, u% Q: m% u1 I
MP3文件是由帧(frame)构成,帧是MP3文件的最小组成单位。每帧都包含帧头,并可以计算帧的长度。根据帧的性质不同,文件主要分为三个部分,ID3v2标签帧,数据帧和ID3v1标签帧。并非每个MP3文件都有ID3v2,但是数据帧和ID3v1帧是必须的。ID3v2在文件头,以字符串“ID3”为标志,包含了演唱者,作曲,专辑等信息,长度不固定,扩展了ID3V1的信息量。ID3v1在文件结尾,以字符串“TAG”为标记,其长度是固定的128个字节,包含了演唱者、歌名、专辑、年份等信息。
& O! f" b5 {) b- `3 _ 5 L, r7 ] e% Y# h a! e
I, ID3V2
" U. P' {7 d* d# b. `% H8 [7 O# T' {/ K/ p9 N
ID3V2到现在一共有四个版本,但流行的播放软件一般只支持第三版,既ID3V2.3。每个ID3V2.3 的标签都一个标签头和若干个标签帧或一个扩展标签头组成。关于曲目的信息如标题、作者等都存放在不同的标签帧中,扩展标签头和标签帧并不是必要的,但每个标签至少要有一个标签帧。标签头和标签帧一起顺序存放在MP3 文件的首部。; a) |) n: Q3 N! R, Y$ _
0 o w/ F0 J0 V3 g标签头 # i2 u* s- Z2 p' P- ~% ^; H
8 O! X1 i( l+ L Z* R& M长度为10个字节,位于文件首部,其数据结构如下:
, r3 d4 P, J7 n8 F( R/ M9 |, P2 ^& h
char Header[3]; /* 字符串 "ID3" */$ `, |, U9 q& p: S2 F
7 S2 f J; h9 \char Ver; /* 版本号ID3V2.3 就记录3 */
) e- D) `" W ^- q: Y% i* ^
2 M5 o$ ]: S% z5 Cchar Revision; /* 副版本号此版本记录为0 */
* f5 A) [. v* O
* z5 _4 Q0 g9 {/ nchar Flag; /* 存放标志的字节,这个版本只定义了三位,很少用到,可以忽略 */
& _0 }. _1 } t5 K( h! W# Y* V
M& Z4 {3 V- a7 H$ k/ x! uchar Size[4]; /* 标签大小,除了标签头的10 个字节的标签帧的大小 */ 9 H6 N- N, h; z: k3 D: w: y6 r
. w* b) }& a( O0 O0 | |
标签大小为四个字节,但每个字节只用低7位,最高位不使用,�为0,其格式如下:
3 f( {, @4 J; P& {6 u6 g0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
0 Y2 |) |7 s: E" J
) i$ _, M. X @4 S' d& e) Y: i- T计算公式如下: $ B& X& Q% S/ D9 ~1 D0 Q
6 W# i1 A' K9 d" p
ID3V2_frame_size = (int)(Size[0] & 0x7F) << 21- s" Y& U1 k3 P* X U
| (int)(Size[1] & 0x7F) << 14
]- t) D/ Z% T1 V5 ?8 \/ Z9 p, l; o! M | (int)(Size[2] & 0x7F) << 75 }7 g: Y9 ^7 i5 V6 `* s
| (int)(Size[3] & 0x7F) + 10; 6 V# C, K& l5 L+ s, I6 N
/ w0 O! g4 {3 B; n6 j
) V/ {) f4 m7 X标签帧
; g# U; E, Q& d/ N' a8 S* f+ ^5 v1 f, C
每个标签帧都有一个10字节的帧头和至少一个字节的不固定长度的内容组成。它们是顺序存放在文件中,由各自特定的标签头来标记帧的开始。其帧的结构如下: 2 @; w; x5 P3 b M; r1 m
3 @8 e' y4 y3 @, S
char FrameID[4]; /*用四个字符标识一个帧,说明其内容 */
8 [% d# C0 K( I. G: l) Q3 I {' B7 r4 L8 X% S
char Size[4]; /* 帧内容的大小,不包括帧头,不得小于1 */ + ?: r4 |$ X( ]/ Z* f) ^ C, R" I
9 @; X1 j1 @6 i) Y
char Flags[2]; /* 存放标志,只定义了6 位,此处不再说明 */ , M' X8 Z- P- @" _% c0 I
' `. N, |% @+ o: v6 K* ~7 J/ G常用帧标识: 3 M4 g5 m4 f% a) T- z# S0 ~
% ]. ?5 ?! g* d3 MTIT2:标题
7 d8 e; j0 Y: q6 q1 @( {: Z) i; ITPE1:作者; O3 b$ ?2 U& }% k0 z3 N9 ^6 ]0 X5 b
TALB:专辑
1 W0 I9 L+ r2 h9 I u/ rTRCK: 音轨,格式:N/M,N表示专辑中第几首,M为专辑中歌曲总数0 c; i5 d: d8 y1 o7 U/ f
TYER:年份
3 ^9 x' f$ Q& `* ]7 BTCON:类型3 t D! _3 z3 r1 ]! a- v- W0 v
COMM:备注,格式:“eng\0备注内容”,其中eng表示所使用的语言
0 u- z. d+ w' @! {$ w" b: j帧大小为四个字节所表示的整数大小。
; j3 F8 W( m1 n" p& ?& r
) j3 n: J* P7 y0 h7 }" `" n1 i
& s8 T$ x& h# \II, ID3V1
9 R$ }( H5 c; ?4 @ z& l, x# e l
其数据结构如下: % o# C- l/ M; J; q# L3 g z8 I# b
, Y- _- ]! X: R& z$ p$ k
char Header[3]; /* 标签头必须是"TAG"否则认为没有标签 */7 Z6 _4 [1 f4 f4 p! w( E$ A) h
char Title[30]; /* 标题 */
7 F, r8 `7 T, [6 G& X' Y, C8 I0 C7 kchar Artist[30]; /* 作者 */
! A: U" g A. s6 m. \char Album[30]; /* 专集 */ y( n. i% d% @
char Year[4]; /* 出品年代 */
( f9 @' S" ?. m' ?! wchar Comment[28]; /* 备注 */
1 X1 T Q }1 R4 |8 ` K6 `( b2 _: Wchar reserve; /* 保留 */, ?: {' h& B* t5 ]" g5 Q
char track;; /* 音轨 */
# B& ]0 f! A1 Qchar Genre; /* 类型 */
. Q2 c( J0 Y& X) V3 u1 y7 o* c* e6 E4 U1 {% b! I. d4 R+ S6 |
其实,关于最后31个字节还存在另外一个版本,就是30个字节的Comment和一个字节的Genre.
; p5 ], t( X# z" O" o! y2 @' a, G
7 c9 V! Y: w* g! _) B% t* I8 O有了上述的这些信息,我们就可以自己写代码,从MP3文件中抓取信息以及修改文件名了。但是,如果真的想写一个播放软件,还是需要读它的数据帧,并进行解码。 |
|