一、 帧
帧头长4字节,是的,是4个字节,共32位。 帧头后面可能有两个字节的CRC 校验,这两个字节的是否存在决定于FRAMEHEADER 信息的第16bit, 为0 则帧头后面无校验,为1 则有校验,校验值长度为2 个字节,(后面是可变长度的附加信息,对于标准的MP3文件来说,其长度是32字节,本段括号内的文字内容有待商榷,暂时没见到这样的文件),紧接其后的 是压缩的声音数据,当解码器读到此处时就进行解码了。
typedef FrameHeader {
unsigned int sync: 11; //同步信息
unsigned int version: 2; //版本
unsigned int layer: 2; //层
unsigned int error protection: 1; // CRC校验
unsigned int bitrate_index: 4; //位率
unsigned int sampling_frequency: 2; //采样频率
unsigned int padding: 1; //帧长调节
unsigned int private: 1; //保留字
unsigned int mode: 2; //声道模式
unsigned int mode extension: 2; //扩充模式
unsigned int copyright: 1; // 版权
unsigned int original: 1; //原版标志
unsigned int emphasis: 2; //强调模式
}HEADER, *LPHEADER;
1.1 帧头4字节使用说明见表1。
表1 MP3帧头字节使用说明
名称 | 位长 | 说 明 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
同步信息 | 11 | 第1、2字节 | 所有位均为1,第1字节恒为FF。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
版本 | 2 | 00-MPEG 2.5 01-未定义 10-MPEG 2 11-MPEG 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
层 | 2 | 00-未定义 01-Layer 3 10-Layer 2 11-Layer 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CRC校验 | 1 | 0-校验 1-不校验 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
位率 | 4 | 第3字节 | 取样率,单位是kbps,例如采用MPEG-1 Layer 3,64kbps是,值为0101。
V1 - MPEG 1 V2 - MPEG 2 and MPEG 2.5 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
采样频率 | 2 | 采样频率,对于MPEG-1: 00-44.1kHz 01-48kHz 10-32kHz 11-未定义 对于MPEG-2: 00-22.05kHz 01-24kHz 10-16kHz 11-未定义 对于MPEG-2.5: 00-11.025kHz 01-12kHz 10-8kHz 11-未定义 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
帧长调节 | 1 | 用来调整文件头长度,0-无需调整,1-调整,具体调整计算方法见下文。padding | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
保留字 | 1 | 没有使用。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
声道模式 | 2 | 第4字节 | 表示声道, 00-立体声Stereo 01-Joint Stereo 10-双声道 11-单声道 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
扩充模式 | 2 | 当声道模式为01是才使用。
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
版权 | 1 | 文件是否合法,0-不合法 1-合法 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
原版标志 | 1 | 是否原版, 0-非原版 1-原版 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
强调方式 | 2 | 用于声音经降噪压缩后再补偿的分类,很少用到,今后也可能不会用。 00-未定义 01-50/15ms 10-保留 11-CCITT J.17 |
规律说明:根据上表的分析,所有的Mp3文件的数据帧开始的两个字节必需是“FF FA”或者 “FF FB”。
1.2 MP3帧长的计算
MP3帧长取决于位率和频率,计算公式为:
Size=((采样个数 * (1 / 采样率))* 帧的比特率)/8 + 帧的填充大小
对于Mp3格式,Size=((1152 * (1 / 采样率))* 帧的比特率)/8 + 帧的填充大小
=144*帧的比特率/采样率+帧的填充大小
a,帧的填充大小就是第23位的帧长调节,不是0就是1。
b,采样个数:MPEG的不同规范(MPEG-1/2/3),以及同一规范中不同的 Layer(Layer I/II/III),每一帧
所对应的采样数,都是固定的,其具体的值参见下表:表 4 MPEG帧的采样数索引表(单位:个/帧)
MPEG 1 | MPEG 2 (LSF) | MPEG 2.5 (LSF) | |
Layer I | 384 | 384 | 384 |
Layer II | 1152 | 1152 | 1152 |
Layer III | 1152 | 576 | 576 |
3.举例说明
本例是王菲的怀念(大小4,680,730 字节)
前面的四个字节为“FF FB B0 64”对应的二进制串为“11111111 11111011 10110000
01100100”,参照前面的分析,第16位为“1”,则无校验数据;第17至20位为“1011”,则比特率=192kbps;第21至22位为
“00”,则采样频率=44.1kHz;第23位为“0”,则帧长调整是0;所以帧长Size=144*192/44.1+0=626,前面除法需向下求
整(但有时又是四舍五入)。所以在地址0x272处又开始了新的帧,我这里是“FF
FB B0 44”。
二 VBR 标志帧
前面分析了帧的结构,Mp3文件分为CBR和VBR两种,这里着重分析一下VBR文件,VBR文件的第一个帧不是有效的数据帧,是它的标志帧。这种标志帧有Xing帧和VBRi帧。
2.1 Xing 帧
VBR 是XING 公司推出的算法,所以在MP3 的FRAME
里会有“XING"这个关键字(现在很多流行的小软件也可以进行VBR 压缩,它们是否遵守这个约定,那就不得而知了),它存放在MP3
文件中的第一个有效FRAME 里,它标识了这个MP3 文件是VBR 的。同时第一个FRAME 里存放了MP3 文件的FRAME
的总个数,这就很容易获得了播放总时间,同时还有100 个字节存放了播放总时间的100 个时间分段的FRAME 的INDEX,假设4 分钟的MP3
歌曲,240S, 分成100
段,每两个相邻INDEX 的时间差就是2.4S, 所以通过这个INDEX,只要前后处理少数的FRAME,就能快速找出我们需要快进的FRAME
头。
2.1.1 解析帧
表2 VBR Xing文件第一帧结构
字节 | 说 明 |
1-4 | 标准声音帧头(Mp3时,为“FF FA xx xx”或者“FF FB xx xx”) |
5-40 | 存放VBR文件标识“Xing”(58 69 6E 67),此标识具体位置视采用的MPEG标准和声道模式而定。标识的前后字节没有使用。 |
37-40 | MPEG-1和非单声道(常见) 注意:Mp3的就是这种情况,第5至36的数据存储的是前面提到过的32字节的边信息,无效边信息时是32字节的“00” |
22-25 | MPEG-1和单声道 |
22-25 | MPEG-2和非单声道 |
14-17 | MPEG-2和单声道 |
41-44 | 标志,说明是否存储了帧数、文件长度、目录表和VBR规模信息,如果存储了,则01 02 04 08。注意:如果四种信息都存储了则这4个字节为“00 00 00 0F”,即F的二进制是“1111”,相应地,如果存储了帧数、文件长度、目录表,则这4个字节为“00 00 00 0E” |
45-48 | 帧数(包括第一帧) |
49-52 | 文件长度 |
53-152 | 目录表,用来按时间进行字节定位。 |
153-156 | VBR规模,用于位率变动音频质量指示,最差 0,最好 100,大端[可 |
2.1.2 举例说明
曲子是:刘德华 - 虹桥机场的咖啡厅.mp3(5,898,130字节,时长3分14秒)
a,第37至40地址为“58 69 6E 67”,就是“Xing”标志了;
b,第41至44地址为“00 00 00 0F”,这里是Flag了,表示该帧存储了帧数、文件长度、目录表和VBR规模信息。
c,第45至48地址为“00 00 1D 11”,这里是文件的总帧数(包括第一帧),是big-endia的,(1*16^3+13*16^2+1*16+1)帧。
d,第49至52地址为“00 59 FD
DE”,这里是文件的总大小,也是Big-Endian的,
(5*16^5+9*16^4+15*16^3+13*16^2+13*16+14)=5,897,694(字节),
但是右键文件的属性发现却是5,898,130字节,这多出来的字节暂时还没弄明白(郁闷中)。
e,第53至152地址,就是一百个字节的目录表了(称作TOC表),如图蓝色地部分。
TOC (Table of Contents)
Contains of 100 indexes (one Byte length) for easier lookup in file. Approximately
solves problem with moving inside file.
Each Byte has a value according this formula:
(TOC[i] / 256) * fileLenInBytes
So if song lasts eg. 240 sec. and you want to jump to 60. sec. (and file is 5 000
000 Bytes length) you can use:
TOC[(60/240)*100] = TOC[25]
and corresponding Byte in file is then approximately at:
(TOC[25]/256) * 5000000
If you want to trim VBR file you should also reconstruct Frames, Bytes and TOC
properly.
TCO 索引的计算方式如下 文件长度 100 比如文件持续 240 秒,我需要跳到 60 秒,文件长度为 5000000 字节 计算如下TOC[(60/240)*100] =TOC[25]/256) * 5000000 如果要自己重建的话,基本是把这个步骤反过来做就可以了。要求准确的话,就需要根据时间点找到正确帧的位置然后再计算, 定位帧的做法都是从第一帧开始搜索。
f,第153至156字节地址为“00 00 00 64”,,音频质量指示质量指示器,为 0(最好)-100(最差)的 Big-Endian 值,没想到这个文件的音质是最差的100。
g,接下来是Lame版本的相关信息
2.2 VBRI帧(该种文件没有找到,此部分内容是完全摘抄的,供参考)
据了解,目前此头信息,只有用 Fraunhofer 的编码器生成的 MPEG音频文件,才会用到此
头。其和Xing 头不一样,其放在第一个MPEG头的后面,大小正好是 32字节。其位置,
长度和示例,都是以字节为单位。下表是 VBRi 头的具体格式及含义,单位为字节:
位置 (字节) | 长度 (字节) | 含义 | 示例 |
0 | 4 | 4个 ASCII字符的 VBR 头ID: “VBRI”无NULL结尾 | “VBRI” |
4 | 2 | 版本 ID,大端,类型:DWORD | 1 |
6 | 2 | 延迟,类型:float | 7344 |
8 | 2 | 音频质量指示 | 75 |
10 | 4 | 文件总大小,大端,类型:DWORD | 45000 |
14 | 4 | 总的帧数,大端,类型:DWORD | 7344 |
18 | 2 | TOC 表的表项数目,大端,类型:WORD | 100 |
20 | 2 | TOC 表项的缩放因子,大端,类型:DWORD | 1 |
22 | 2 | 单个 TOC 表项的大小,单位字节,最大为 4,大端, 类型:DWORD | 2 |
24 | 2 | 帧数/表项,大端,类型:WORD | 845 |
26 | 用于检索的 TOC 表,整型值,可以通过每个表项大小乘于表项个数得到此 TOC 表的总大小,大端 |
三 Info 帧
info帧,结构和Xing帧是相同的,从一些网上的资料显示:这种类型的帧有点怪,在CBR文件中的第一个数据帧可以是Info帧,在VBR文件中的第
一个数据帧也有可能是Info帧,但是我个人更倾向于认为第一个数据帧为Info帧的文件是CBR文件,比如Kugoo软件制作的铃声的第一帧都是
Info帧,而且是CBR文件。在下一篇博文(四)怎样区分是否是固定位率文件和这个有关。