• MP3 文件格式解析


      目录:

        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;
    	}
    }
    

      

  • 相关阅读:
    第03组 Alpha冲刺(3/4)
    第03组 Alpha冲刺(2/4)
    第03组 Alpha冲刺(1/4)
    课程总结
    第十四周学习总结&实验报告
    第十三周课程总结
    第十二周学习总结
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
  • 原文地址:https://www.cnblogs.com/darkchii/p/11883093.html
Copyright © 2020-2023  润新知