而对于VBR,由于每一帧的比特率都是变化的,所以计算起来就相对要复杂一些,下面就来详细介绍。
想要计算VBR的MP3的播放时间,总的来说,有两种方法:
这个方法,就是和CBR同样的思路,对于VBR的MP3来说,假如也像CBR的MP3一样,也有个类似的每一帧都是固定的某个值的比特率,那么计算整个VBR的播放时间,也就可以用上面CBR一样的公式去计算了。
由此,就有了平均比特率的概念,即,将所有帧的比特率的值相加,得到一个总的比特率的值,然后除于总的帧数,就得到了一个平均比特率,这样,使得理论上,此VBR相当于一个比特率为该平均比特率的CBR了。
不过,可以看出,需要计算平均比特率之前,要先得到每一帧的比特率的值,以及总的帧的数目,然后才可以计算平均比特率的值。
而为了得到每一帧的比特率的值,就要将整个VBR MP3文件都遍历一遍,以此找到所有的帧,并解析每一个帧的帧头,得到比特率索引值,然后查表得到比特率的值。
如此做的话,效率显然很低。因为此处只是为了计算整个VBR MP3的播放时间,却要遍历整个文件,还要解析每一帧的帧头,显得很是得不偿失。
所以,就有了更好的,效率更高的,下面要介绍的另一种方法,来计算VBR MP3的播放时间。
另外,需要提醒的是,对于平均比特率来说,往往和第一帧的比特率相差很大。因为常见的MP3音乐的开头部分,即第一帧或者前几帧,多数是一些无声的数据,或者本身包含信息量很少,比特率很低的数据。因此,其意味着,如果解码器对于VBR文件,误解为CBR文件,按照CBR所有帧的比特率都相同的逻辑,去解析第一帧,得到一个比特率,然后用此比特率来计算整个文件的播放时间的话,那么往往计算出的播放时间和实际的相差很大。这也就是后面引用中一个帖子里面遇到的情况,即,Media Player Classic播放VBR的MP3时的时间问题。
总帧数法,即利用总的帧的数目,来计算VBR的播放时间。
此方法的前提,是我们前面就强调过的:
MP3,即MPEG-1,Layer III,不论是CBR,还是VBR,每一帧的采样个数都是固定的1152个。即每一帧,都是固定的1152个采样。
CBR和VBR中的固定和可变,都是指的是比特率Bitrate,而不是采样率Sample Rate。对于同一MP3文件,不论CBR还是VBR,采样率都是固定的。
了解了这两个前提后,就可以看出,对于VBR来说,虽然每一帧的比特率不同,但是每一帧的时间都是固定的,因为
每一帧的时间
= 该帧的采样个数 * 该帧的采样率
= 1152 * 采样率
其中:
MPEG-1,Layer III,即MP3,不论是CBR还是VBR,都是固定的1152
对于单个的VBR文件,都是统一的,固定的,常见的是44100Hz。采样率可以通过解析第一帧的帧头得出采样率索引,然后查表得到采样率。
既然知道了每一帧的时间都是固定的,那么很容易就想到,如果知道VBR MP3有一共多少帧,那么就可以用 总的帧数 × 每一帧的时间 = 总的时间长度了。
所以,剩下的事情,就是去得到VBR MP3的总的帧数。
最简单,但是效率很低的方法就是,像上面方法1一样,遍历整个VBR文件,找出一共有多少帧,对于第一帧,解析第一帧的帧头,得到采样率。
这样有了采样率和总的帧数,就可以用上面的解释的原理来计算了,对应公式就是:
公式 4.2. VBR MP3总的时长(VBR Duration)
VBR Duration
= Total_Frame_Number * Time_Per_Frame
= Total_Frame_Number * (Sample_Number * Time_Per_Sample)
= Total_Frame_Number * (Sample_Number * (1 / Frame_Sample_Rate))
VBR MP3总的时长
= 总的帧数 * 单个帧的时长
= 总的帧数* (帧的采样个数 * 每个帧的时长)
= 总的帧数* (帧的采样个数 * (1 / 帧的采样率))
其中:
VBR中的总的帧的数目。
对于MP3(MPEG1,Layer III)来说,是固定的1152个采样。
通过解析第一帧,即可得知帧采样率索引,查表,即可得此采样率。
但是,可以看到,虽然此遍历整个文件以得到总的帧数的方法,但是还是显得效率不高。此处我们毕竟只是需要知道总的帧数而已,却还是要遍历文件。
对此问题,想象一下,要是有人在VBR的文件头部,单独提供了这个总的帧数,那么不就可以省去了我们再去遍历整个文件了吗?
而实际情况是,你所想到的事情,别人已经帮你实现了。^_^。
现实中,VBR文件中,就是已经有了对应的头Header,用于存放VBR相关的信息。
这样的头信息,也就是下面将要介绍的XING和VBRI。
VBR的帧头,记录了和VBR相关的一些信息,至少包含了我们前面介绍的,用于方便我们计算VBR的播放时长的总的帧数。
VBR MP3的帧头,主要有两种类型,XING和VBRI。
此外,VBR的头中,往往还包含了一个用于定位的TOC(table of content)目录表。即用于在快进或快退的时候,通过表中的信息,可以方便地定位到对应的位置。如果没有此TOC表,需要单独去计算出对应的位置,比较麻烦。
关于它们的具体格式和含义,下面就对其进行详细解释。
此tag由XING公司推出的算法/规范,所以叫做XING。
对于大多数的VBR文件都加了此头,但并不全是。此头位于MPEG音频头后面的某个特定位置(多数是0x24)。包含了此XING头的第一个帧,其后的数据是空的,所以即使解码器没有考虑到此头,也可以正常处理此帧。对于Layer III的文件来说,比如常见的MP3,此VBR放在边信息(side information)之后。
下表是XING头的具体格式及含义:
表 4.1. XING 头的格式及含义
位置(字节) | 长度(字节) | 含义 | 示例 | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 4 | 4个ASCII字符的VBR头 ID,要么是Xing,要么是Info,无NULL结尾(普通字符串都以NULL,即\0结尾) | 'Xing' | |||||||||||
4 | 4 |
存放一个标志,用于表示接下来存在哪些域/字段,各字段逻辑或的结果:
|
0x0007 就表示下面存在:
|
|||||||||||
8 | 4 | 总帧数(Frames),大端[可选] | 7344 | |||||||||||
8或12 | 4 | 文件总大小,单位字节,大端[可选] | 45000 | |||||||||||
8,12,16 | 100 | TOC表,大端[可选] | ||||||||||||
8或12, 16, 108, 112 ,116 | 4 | 音频质量指示,最差0,最好100,大端[可选] | 0 |
虽然知道了XING头的具体含义,可以去根据具体的值,解析出对应的含义了,但是,由于其是放在side information之后的,所以,要先定位,找到XING头,关于其位置,用如下公式计算:
其中:
即通过程序去找到连续的11个bit都是1的位置,即可同步MPEG的帧,找到对应的MPEG头的开始处。
详细信息,后面用到此公式时会具体解释。
根据头的格式,Xing头里面必须包含ID和flag这两个段。其他字段都是可选的,是否包含,要看flag的值。有时候这个Xing头,CBR里面也有,此时,前面的ID的值就是Info,而不是Xing了。
据了解,目前此头信息,只有用Fraunhofer的编码器生成的MPEG音频文件,才会用到此头。
其和Xing头不一样,其放在第一个MPEG头的后面,大小正好是32字节。其位置,长度和示例,都是以字节为单位。
下表是VBRi头的具体格式及含义,单位为字节:
表 4.2. 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表的总大小,大端 |