|
2, MP3文件格式 ! M. L f9 Z- y0 c
3 J4 F3 K3 o# s* x# A
用一个二进制查看器(比如Ultra-Edit)打开一个MP3文件,就能看到一大堆看似杂乱无序的数据。但只要用心了解就会知道,其实,这一切都是有章可循的。
* ]9 n8 l) L. ^! h& _+ ^
4 t. p" |3 A' N4 A& XMP3文件是由帧(frame)构成,帧是MP3文件的最小组成单位。每帧都包含帧头,并可以计算帧的长度。根据帧的性质不同,文件主要分为三个部分,ID3v2标签帧,数据帧和ID3v1标签帧。并非每个MP3文件都有ID3v2,但是数据帧和ID3v1帧是必须的。ID3v2在文件头,以字符串“ID3”为标志,包含了演唱者,作曲,专辑等信息,长度不固定,扩展了ID3V1的信息量。ID3v1在文件结尾,以字符串“TAG”为标记,其长度是固定的128个字节,包含了演唱者、歌名、专辑、年份等信息。
! y7 f9 X6 t% r: R. t
4 \8 j Z7 [" }' m, P9 oI, ID3V2 / `+ U/ @/ h# M* W* y1 H
8 g. f" L3 e/ wID3V2到现在一共有四个版本,但流行的播放软件一般只支持第三版,既ID3V2.3。每个ID3V2.3 的标签都一个标签头和若干个标签帧或一个扩展标签头组成。关于曲目的信息如标题、作者等都存放在不同的标签帧中,扩展标签头和标签帧并不是必要的,但每个标签至少要有一个标签帧。标签头和标签帧一起顺序存放在MP3 文件的首部。
9 r! V. i: y5 y6 f
# `* c/ Q. d2 b. G2 P8 T标签头
% z& s8 Y0 ]9 a: o0 ?. y! \4 P* w7 P/ w) P
长度为10个字节,位于文件首部,其数据结构如下: + \, F, P6 V" J2 F3 r
" c4 g, `& o0 D1 ?* X( |6 I/ k) x5 Rchar Header[3]; /* 字符串 "ID3" */
6 H# D6 p Q2 B1 u& C' V
2 T# u! R; `7 ?0 ]4 Nchar Ver; /* 版本号ID3V2.3 就记录3 */ + V- S6 }) I/ D6 w
9 E/ x) O; l- R$ t" o/ |, f' |$ Schar Revision; /* 副版本号此版本记录为0 */ ( d( V4 W! E, w0 \9 M7 W# @
6 b4 d9 I. T; c6 N8 Y; M
char Flag; /* 存放标志的字节,这个版本只定义了三位,很少用到,可以忽略 */
1 A8 f5 _- q& K* Y5 a
5 l5 C2 f, E/ J/ I. R+ w: }4 Xchar Size[4]; /* 标签大小,除了标签头的10 个字节的标签帧的大小 */
! S1 @# u2 E" y. K; s6 v! t9 o2 c6 G9 e: X: y
标签大小为四个字节,但每个字节只用低7位,最高位不使用,�为0,其格式如下:$ \8 ^8 G" ?! ^1 F' ~& F* D
0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx % C K8 w$ E, w9 B
( P5 R8 ^) a" w/ f计算公式如下: / s" z+ H4 ? t: N; W, @
! m% d1 H7 |% O2 t+ M3 g. `ID3V2_frame_size = (int)(Size[0] & 0x7F) << 21
( L1 G; ~& M% h | (int)(Size[1] & 0x7F) << 14: h. c7 y9 b* F" u2 }0 F/ {
| (int)(Size[2] & 0x7F) << 7$ O" B; K# H7 L# P+ ?- e
| (int)(Size[3] & 0x7F) + 10; % W+ T5 F3 B/ l& G9 @" p
$ m6 S) s7 x: Y! d/ V
1 p5 r) W- L- ]( x D标签帧 + \1 S% O; A: j0 q6 j" u0 d) i
# G3 [$ r( ~* G7 A每个标签帧都有一个10字节的帧头和至少一个字节的不固定长度的内容组成。它们是顺序存放在文件中,由各自特定的标签头来标记帧的开始。其帧的结构如下:
M L, l) W" u3 i: i( }1 x, w" i% g4 y& m7 n* J* ]6 o
char FrameID[4]; /*用四个字符标识一个帧,说明其内容 */ 0 ] E* y6 x1 K% Q
9 f& d+ U1 I2 Q$ h
char Size[4]; /* 帧内容的大小,不包括帧头,不得小于1 */ 8 L! }, _! {6 ]! F5 [; x6 h
6 P9 z* U# U2 J" E0 S& ^3 @! lchar Flags[2]; /* 存放标志,只定义了6 位,此处不再说明 */
. c, l& c1 e: L5 t- O6 ~0 O2 f* m) u1 {
常用帧标识: ' r0 l: B; Z: C2 _. l8 [
" |! x' W- u8 P5 {1 L9 f$ V3 lTIT2:标题0 V& g. ?- m: R z- G1 z: G
TPE1:作者# o" d- v" ]. V
TALB:专辑1 `/ w, F' K) c8 C# }
TRCK: 音轨,格式:N/M,N表示专辑中第几首,M为专辑中歌曲总数/ [& _2 y. L: B% ?
TYER:年份8 H0 L7 a0 \, B8 \' O
TCON:类型7 M3 g" a5 P) J; k
COMM:备注,格式:“eng\0备注内容”,其中eng表示所使用的语言* z: m& I, ]2 _
帧大小为四个字节所表示的整数大小。 7 z, I) v' W; L. ~; B1 Y
! C' _2 u1 ~% _$ s+ ^' c% z6 d $ B p7 j. `& V( `5 H9 K
II, ID3V1
" c; ^$ u) W( C: C. | K1 O) J" K7 c1 ~# k- ]
其数据结构如下: - A( e7 x6 n* d
5 A* {0 E! F" g# e* w7 Nchar Header[3]; /* 标签头必须是"TAG"否则认为没有标签 */4 N' f2 a6 w4 k F" @; T& M
char Title[30]; /* 标题 */# N! @5 |! `0 a
char Artist[30]; /* 作者 */# V! _/ p x. p0 n6 {+ B( N" D
char Album[30]; /* 专集 */( p6 o( h. f% p/ l+ Q5 G
char Year[4]; /* 出品年代 */9 a0 X/ ]! ?2 \5 R
char Comment[28]; /* 备注 */9 h" r A: G& \: c. y8 h) X% \
char reserve; /* 保留 */
: J8 M8 L4 o Y- @' ~* t# I* _" Rchar track;; /* 音轨 */9 D6 Y {8 v3 q- ~
char Genre; /* 类型 */ , e, j- R! J/ }7 A1 Z! ?/ Z" W4 P
& N) `* j" | l" |
其实,关于最后31个字节还存在另外一个版本,就是30个字节的Comment和一个字节的Genre.
# y3 {: V% e) U5 `! w" n. T3 X6 A G) `) u: h" M
有了上述的这些信息,我们就可以自己写代码,从MP3文件中抓取信息以及修改文件名了。但是,如果真的想写一个播放软件,还是需要读它的数据帧,并进行解码。 |
|