ID3v1
ID3V1标签比较简单,为定长128字节标签,并且位于文件末尾。由于其结构简单,所以其处理非常快。现在大部分的MP3文件都支持ID3V1标签。标签格式如下表所示:
char Title[30]; /*标题 歌名*/
char Artist[30]; /*作者*/
char Album[30]; /*专集*/
char Year[4]; /*出品年代*/
char Comment[30]; /*备注*/
char Genre; /*类型MP3音乐类别,共147种。*/
ID3V1的各项信息都是顺序存放,没有任何标识将其分开,比如标题信息不足30个字节,则使用'\0'补足,否则将造成信息错误。
ID3V2位于文件头部,并且大小是动态的。标签内容以数据帧的形式存在,这样可以克服ID3V1的缺点。 但是ID3V2的缺点是定义比较复杂,处理起来的效率比较低。
ID3V2标签有多个版本:id3v2.2,id3v2.3.0,最新的是id3v2.4.0。这里主要以应用最广的ID3V2.3.0为例来说明ID3V2标签。
每个ID3V2.3的标签都一个标签头和若干个标签帧或一个扩展标签头组成。关于曲目的信息如标题、作者等都存放在不同的标签帧中,扩展标签头和标签帧并不是必要的,但每个标签至少要有一个标签帧。标签头和标签帧一起顺序存放在MP3文件的首部。
一、标签头
在文件的首部顺序记录10个字节的ID3V2.3的头部。数据结构如下:
char Header[3]; /*必须为"ID3"否则认为标签不存在*/
char Ver; /*版本号ID3V2.3就记录3*/
char Revision; /*副版本号此版本记录为0*/
char Flag; /*存放标志的字节,这个版本只定义了三位,稍后详细解说*/
char Size[4]; /*标签大小,(不包括标签头的10个字节)所有的标签帧的大小*/
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表示备注所使用的自然语言
1. 大小
这个可没有标签头的算法那么麻烦,每个字节的8位全用,格式如下
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
算法如下:
int FSize;
FSize = Size[0]*0x100000000 +Size[1]*0x10000 +Size[2]*0x100 +Size[3];
2. 标志
只定义了6位,另外的10位为0,但大部分的情况下16位都为0就可以了。格式如下:
abc00000 ijk00000
a -- 标签保护标志,设置时认为此帧作废
b -- 文件保护标志,设置时认为此帧作废
c -- 只读标志,设置时认为此帧不能修改(但我没有找到一个软件理会这个标志)
i -- 压缩标志,设置时一个字节存放两个BCD码表示数字
j -- 加密标志(没有见过哪个MP3文件的标签用了加密)
k -- 组标志,设置时说明此帧和其他的某帧是一组
值得一提的是winamp在保存和读取帧内容的时候会在内容前面加个'\0',并把这个字节计算在帧内容的大小中。
4. Declared ID3v2 frames
TEXT: 歌词作者 TENC: 编码
WXXX: URL链接(URL) TCOP: 版权(Copyright)
TOPE: 原艺术家 TCOM: 作曲家
TDAT: 日期 TPE3: 指挥者
TPE2: 乐队 TPE1: 艺术家相当于ID3v1的Artist
TPE4: 翻译(记录员、修改员) TYER: 年代相当于ID3v1的Year
USLT: 歌词 TALB: 专辑相当于ID3v1的Album
TIT1: 内容组描述 TIT2: 标题相当于ID3v1的Title
TIT3: 副标题 TCON: 流派(风格)相当于ID3v1的Genre见下表
TBPM: 每分钟节拍数 COMM: 注释相当于ID3v1的Comment
TDLY: 播放列表返录 TRCK: 音轨(曲号)相当于ID3v1的Track
TFLT: 文件类型 TIME: 时间
TKEY: 最初关键字 TLAN: 语言
TLEN: 长度 TMED: 媒体类型
TOAL: 原唱片集 TOFN: 原文件名
TOLY: 原歌词作者 TORY: 最初发行年份
TOWM: 文件所有者(许可证者) TPOS: 作品集部分
TPUB: 发行人 TRDA: 录制日期
TRSN: Intenet电台名称 TRSO: Intenet电台所有者
TSIZ: 大小 TSRC: ISRC(国际的标准记录代码)
TSSE: 编码使用的软件(硬件设置) UFID: 唯一的文件标识符
AENC: 音频加密技术
其中要说明的是这个FrameID,在ID3v1里我们是根据每一个信息所占用的固定的字节数和位置来判断他是哪个信息的。而ID3v2为了提供更好 的可扩展性,把这些信息变得“动态”化了,因为长度并不是预先设定好的,而是在size[4]里存储的。这样长度就可以不再固定了。我觉得在我们自己定义 文件的时候ID3v2和ID3v1也是值得我们考虑的一个方面。如果结构很小而且存储的量也不大,我们可以采用ID3v1的信息存储方式。如果存储的信息 不固定,而且要求有很好的可扩展性,那么ID3v2当然成了首选。实际上,现在很多格式的文件的存储方式都是ID3v2的存储方式非常接近的。