目录:
1.mp3 文件简介
2.ID3 tag
id3 v2
3.音频帧
要注意的地方
4.参考
5.一个临时解析方法
一、MP3文件简介
MP3(mpeg-1 Ⅲ 或者 mpeg-2 Ⅲ)是一种将音频以数字形式存储在设备上的文件格式。
很简单的文件结构示意:
[ID3 v2] frame_1 frame_2... frame_N [ID3 v1]
二、ID3 tag
id3 v1 和 v2 可任选其一,似乎现在大多数都是 v2 版本了,毕竟可扩展性更高。
id3 v2 即是标签信息,里面包含有作者、版权、歌词、封面等等信息,如前面示意所示,它总是放在所有数据帧的最前面。
这样的 MP3 文件都是以ID3 + 版本开头的,ID3 占 3 个字节,版本 2 字节,比如,下图中左边 16 进制数据 49 44 33 表示 ID3 v2, 03 00 就是版本信息,表示 id3 v2.3.0 版本:
后面1个字节是 flags ,这个在这份文档[1]中解释十分详细。
紧接着是 4 个字节以表示整个 ID3 标签块的大小,但不包括标签头,也就是不包括前面这10字节(ID3 占 3 字节 + 版本 2 字节 + 1个 flags 字节 + 大小 4 个字节)。
接下来实际上就是各种音乐相关信息帧(详细解释请看后面截图部分),组成主要以下面字段(4 个字符,即4字节) + 大小(4 字节) + 标记(2字节):
4.20 AENC [[#sec4.20|Audio encryption]] 4.15 APIC [#sec4.15 Attached picture] 4.11 COMM [#sec4.11 Comments] 4.25 COMR [#sec4.25 Commercial frame] 4.26 ENCR [#sec4.26 Encryption method registration] 4.13 EQUA [#sec4.13 Equalization] 4.6 ETCO [#sec4.6 Event timing codes] 4.16 GEOB [#sec4.16 General encapsulated object] 4.27 GRID [#sec4.27 Group identification registration] 4.4 IPLS [#sec4.4 Involved people list] 4.21 LINK [#sec4.21 Linked information] 4.5 MCDI [#sec4.5 Music CD identifier] 4.7 MLLT [#sec4.7 MPEG location lookup table] 4.24 OWNE [#sec4.24 Ownership frame] 4.28 PRIV [#sec4.28 Private frame] 4.17 PCNT [#sec4.17 Play counter] 4.18 POPM [#sec4.18 Popularimeter] 4.22 POSS [#sec4.22 Position synchronisation frame] 4.19 RBUF [#sec4.19 Recommended buffer size] 4.12 RVAD [#sec4.12 Relative volume adjustment] 4.14 RVRB [#sec4.14 Reverb] 4.10 SYLT [#sec4.10 Synchronized lyric/text] 4.8 SYTC [#sec4.8 Synchronized tempo codes] 4.2.1 TALB [#TALB Album/Movie/Show title] 4.2.1 TBPM [#TBPM BPM (beats per minute)] 4.2.1 TCOM [#TCOM Composer] 4.2.1 TCON [#TCON Content type] 4.2.1 TCOP [#TCOP Copyright message] 4.2.1 TDAT [#TDAT Date] 4.2.1 TDLY [#TDLY Playlist delay] 4.2.1 TENC [#TENC Encoded by] 4.2.1 TEXT [#TEXT Lyricist/Text writer] 4.2.1 TFLT [#TFLT File type] 4.2.1 TIME [#TIME Time] 4.2.1 TIT1 [#TIT1 Content group description] 4.2.1 TIT2 [#TIT2 Title/songname/content description] 4.2.1 TIT3 [#TIT3 Subtitle/Description refinement] 4.2.1 TKEY [#TKEY Initial key] 4.2.1 TLAN [#TLAN Language(s)] 4.2.1 TLEN [#TLEN Length] 4.2.1 TMED [#TMED Media type] 4.2.1 TOAL [#TOAL Original album/movie/show title] 4.2.1 TOFN [#TOFN Original filename] 4.2.1 TOLY [#TOLY Original lyricist(s)/text writer(s)] 4.2.1 TOPE [#TOPE Original artist(s)/performer(s)] 4.2.1 TORY [#TORY Original release year] 4.2.1 TOWN [#TOWN File owner/licensee] 4.2.1 TPE1 [#TPE1 Lead performer(s)/Soloist(s)] 4.2.1 TPE2 [#TPE2 Band/orchestra/accompaniment] 4.2.1 TPE3 [#TPE3 Conductor/performer refinement] 4.2.1 TPE4 [#TPE4 Interpreted, remixed, or otherwise modified by] 4.2.1 TPOS [#TPOS Part of a set] 4.2.1 TPUB [#TPUB Publisher] 4.2.1 TRCK [#TRCK Track number/Position in set] 4.2.1 TRDA [#TRDA Recording dates] 4.2.1 TRSN [#TRSN Internet radio station name] 4.2.1 TRSO [#TRSO Internet radio station owner] 4.2.1 TSIZ [#TSIZ Size] 4.2.1 TSRC [#TSRC ISRC (international standard recording code)] 4.2.1 TSSE [#TSEE Software/Hardware and settings used for encoding] 4.2.1 TYER [#TYER Year] 4.2.2 TXXX [#TXXX User defined text information frame] 4.1 UFID [#sec4.1 Unique file identifier] 4.23 USER [#sec4.23 Terms of use] 4.9 USLT [#sec4.9 Unsychronized lyric/text transcription] 4.3.1 WCOM [#WCOM Commercial information] 4.3.1 WCOP [#WCOP Copyright/Legal information] 4.3.1 WOAF [#WOAF Official audio file webpage] 4.3.1 WOAR [#WOAR Official artist/performer webpage] 4.3.1 WOAS [#WOAS Official audio source webpage] 4.3.1 WORS [#WORS Official internet radio station homepage] 4.3.1 WPAY [#WPAY Payment] 4.3.1 WPUB [#WPUB Publishers official webpage] 4.3.2 WXXX [#WXXX User defined URL link frame]
注意,这里的大小只是字段信息的大小,并且可能有很多信息帧。
下面是用截图加解释的方式来证明这部分的组成成分。
我们看下这个 mp3 文件,如下图:
前面所说的头部分之后出现 TSSE 4 个字符,上面给出的表中也出现了 TSSE,它指的是使用的软/硬件编码方式,大小是 13 (00 00 00 0D)字节,实际上就是图中的 Lavf56.4.101(这说明使用的 ffmpeg 进行编码),正好 13 字节。
接下来定位到下一个字段:
APIC 也是上面中有的字段,它是指图片(并且注意到PNG,png 文件一定是以 137 80 78 71 13 10 26 10(89 50 4E 47 0D 0A 1A 0A)这 8 个字节开头,以及后面的 IHDR,它是 PNG 图片格式的组成成分头的部分),它的内容大小共有 530532(00 08 18 64)字节(不包括该帧的大小所占的 4 字节以及标记占的 2 字节),从 . 开始定位到该内容块的最一个字节的位置:
可以看到下一个字段 TALB 也是出现在表中...等等,可以验证没有任何问题。
三、音频帧
frame 则是包含有音频数据以及与音频数据有关的信息的块,音频信息当然就是比如比特率、采样率、通道、CRC 校验等等。
每一帧都是按 AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM 组成,这个在文档[2]中也有详细解释,我主要想说要注意 2 点:
1.如何在文件中找到音频帧头,这个因为帧头第一个字节一定是 255(FF),但也有可能其他地方也出现 FF,所以不能光用第一个字节判断,但也不能用 4 个字节来判断,有可能一些部分是 FF FB E0 00 ,有的却是 FF FB E2 44,但如果是文件是 MPEG-1 III,那么用前 2 个字节基本上不会错。
2.按计算公式得到的字节大小不一定就等于音频数据大小。
四、参考
[1]: Informal Standard Document: id3v2.3 M. Nilsson 3rd February 1999 http://id3.org/id3v2.3.0
[2]: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html
五、一个临时解析方法
void ReadMpegAudio(char * filename, PBYTE audio) { std::ifstream file(filename, std::ios::binary); unsigned char id3_tag[] = { 255, 251 }; for (unsigned char c = file.get(); !file.eof(); c = file.get()) { int k = 0; if (c == id3_tag[0]) { c = file.get(); if (c == id3_tag[1]) { for (int j = 0; j < 2; j++) c = file.get(); for (;; c = file.get()) { unsigned char gc = c; if (c == id3_tag[0]) { c = file.get(); if (c == id3_tag[1]) break; else audio[k++] = gc; } else audio[k++] = gc; } // std::cout << k << ' '; } else continue; } else continue; } }