MPEG音频帧头






4.89/5 (93投票s)
一篇关于MPEG音频帧头的文章。
目录
1. 引言
本文档介绍了MPEG音频帧头的结构,包括XING和VBRI头。目的是尽可能精确快速地估算MPEG音频文件的持续时间。本文档不包含任何关于如何解码/编码实际音频数据的提示。MPEG音频文件存在不同的层。最常见的是MPEG 1 Layer III(也称为MP3),因为它拥有最先进的压缩技术。
我知道关于MPEG音频帧头的文章(甚至在CodeProject上)还有其他,但我会更深入地探讨一下。
2. MPEG音频帧
MPEG音频文件由帧组成。每个帧在其开头都包含一个头,后面跟着音频数据。该音频数据始终包含**固定数量的样本**。目前存在三种MPEG音频层,它们在音频数据如何在帧中编码方面有所不同,尽管它们都具有相同的头格式。帧本身由槽组成。在Layer I中,一个槽总是4字节长,而在所有其他层中,一个槽是1字节长。
除了层之外,还有三个版本的MPEG音频,它们在处理采样率方面有所不同(参见表2.1.2)。MPEG 1 (ISO/IEC 13818-3) 和 MPEG 2 (ISO/IEC 11172-3) 是ISO标准。MPEG 2.5是MPEG 2的非官方扩展,用于支持更低的采样率。MPEG 2/2.5也称为**LSF**,代表低采样频率。每个版本都可以处理这三层。如果您想了解更多关于MPEG音频文件的技术细节,请查看规格。您可以在www.MP3-Tech.org找到它们以及许多其他有用的MPEG信息。
文件可以以恒定比特率(**CBR**)或可变比特率(**VBR**)编码,这意味着每个帧可以具有不同的比特率。因此,这些文件的质量通常高于以恒定比特率模式编码的文件,因为它们可以在音乐需要时使用更高的比特率。
2.1. MPEG音频帧头
每个帧开头的头是32位长,格式如下。头中的位0是整个头部的最高有效位(**MSB**)。请注意,位置是零基的;位置、长度和示例都以位格式表示。
职位 | 长度 | 含义 | 示例 |
---|---|---|---|
0 | 11 | 用于查找帧头的同步位(所有位始终设置) | 1111 1111 111 |
11 | 2 | 音频版本ID(参见表3.2) 00 - MPEG Version 2.5(MPEG 2的非官方扩展) |
11 |
13 | 2 | 层索引 00 - 保留 |
01 |
15 | 1 | 保护位 0 - 由16位CRC保护,位于头部之后 |
1 |
16 | 4 | 比特率索引(参见表2.1.3) | 1001 |
20 | 2 | 采样率索引(参见表2.1.2) | 11 |
22 | 1 | 填充位 如果设置,则数据用一个槽进行填充(对于帧大小计算很重要) |
0 |
23 | 1 | 私有位(仅供参考) | 1 |
24 | 2 | 通道模式 00 - 立体声 注意:双通道文件由两个独立的单声道通道组成。每个通道使用文件比特率的一半。大多数解码器会将其输出为立体声,但情况不一定总是如此。 |
01 |
26 | 2 |
模式扩展(仅在联合立体声中使用) (参见表2.1.6) |
00 |
28 | 1 | 版权位(仅供参考) | 1 |
29 | 1 | 原版位(仅供参考) | 1 |
30 | 2 | 强调 00 - 无 强调指示用于告知解码器文件需要去强调,这意味着解码器必须在类似Dolby的噪声抑制之后“重新均衡”声音。它很少使用。 |
00 |
采样率指定每秒记录多少个样本。每个MPEG版本都可以处理不同的采样率。
采样率索引 | MPEG 1 | MPEG 2 (LSF) | MPEG 2.5 (LSF) |
---|---|---|---|
00 | 44100 赫兹 | 22050 赫兹 | 11025 赫兹 |
01 | 48000 赫兹 | 24000 赫兹 | 12000 赫兹 |
10 | 32000 赫兹 | 16000 赫兹 | 8000 赫兹 |
11 | 保留 |
比特率始终以千比特每秒显示。请注意,前缀千(缩写为小写'k')表示1000比特每秒,而不是1024!比特率索引1111已保留,不应使用。在MPEG音频标准中,描述了一种自由格式。这种自由格式意味着文件以恒定比特率编码,但该比特率不是预定义的比特率之一。只有极少数解码器可以处理这些文件。
比特率索引 | MPEG 1 | MPEG 2, 2.5 (LSF) | |||
---|---|---|---|---|---|
Layer I | Layer II | Layer III | Layer I | Layer II & III | |
0000 | 免费 | ||||
0001 | 32 | 32 | 32 | 32 | 8 |
0010 | 64 | 48 | 40 | 48 | 16 |
0011 | 96 | 56 | 48 | 56 | 24 |
0100 | 128 | 64 | 56 | 64 | 32 |
0101 | 160 | 80 | 64 | 80 | 40 |
0110 | 192 | 96 | 80 | 96 | 48 |
0111 | 224 | 112 | 96 | 112 | 56 |
1000 | 256 | 128 | 112 | 128 | 64 |
1001 | 288 | 160 | 128 | 144 | 80 |
1010 | 320 | 192 | 160 | 160 | 96 |
1011 | 352 | 224 | 192 | 176 | 112 |
1100 | 384 | 256 | 224 | 192 | 128 |
1101 | 416 | 320 | 256 | 224 | 144 |
1110 | 448 | 384 | 320 | 256 | 160 |
1111 | 保留 |
在MPEG 1 Layer II中,只有一些比特率和模式的组合是允许的。在MPEG 2/2.5中,没有这种限制。
比特率 | 允许的模式 |
---|---|
免费 | all |
32 | 单声道 |
48 | 单声道 |
56 | 单声道 |
64 | all |
80 | 单声道 |
96 | all |
112 | all |
128 | all |
160 | all |
192 | all |
224 | 立体声、强度立体声、双通道 |
256 | 立体声、强度立体声、双通道 |
320 | 立体声、强度立体声、双通道 |
384 | 立体声、强度立体声、双通道 |
为了计算帧大小,您需要每个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 |
然后您可以这样计算帧大小
Frame Size = ( (Samples Per Frame / 8 * Bitrate) / Sampling Rate) + Padding Size
由于四舍五入误差,计算帧大小的官方公式略有不同。根据ISO标准,您必须先以槽(参见2. MPEG音频格式)计算帧大小,然后将该数字截断为整数,最后乘以槽大小。您可以在我的代码中的CMPAHeader
类中找到计算帧大小的正确方法。
通过应用以下公式,您可以获得文件持续时间(秒)
Duration = File Size / Bitrate * 8
在CBR文件中,通过获取文件中的第一个帧头然后使用上述公式计算持续时间的方法才能正确工作。
模式扩展用于连接对立体声效果无用的信息,从而减少所需的比特。这些比特由联合立体声模式下的编码器动态确定,并且联合立体声可以从一个帧更改到另一个帧,甚至可以打开或关闭。对于所有其他通道模式,模式扩展字段无效。
MPEG音频文件的完整频率范围被划分为子带。共有32个子带。对于Layer I和II,头中的两位决定了应用强度立体声的频率范围(频段)。在该频率范围内,仅存储一个通道。所有其他频段包含两个独立通道的信息。对于Layer III,这两位决定了使用哪种联合立体声(强度立体声和/或M/S立体声)。
值 | Layer I & II | Layer III | |
---|---|---|---|
M/S立体声 | 强度立体声 | ||
00 | 频段4至31 | 关闭 | 关闭 |
01 | 频段8至31 | 关闭 | 开 |
10 | 频段12至31 | 开 | 关闭 |
11 | 频段16至31 | 开 | 开 |
2.2. 验证CRC
如果头部中的保护位未设置,则该帧包含一个16位CRC(循环冗余校验和)。此校验和直接跟随帧头,是一个大端序的WORD
。要验证此校验和,您必须计算该帧的校验和,并将计算出的CRC与存储的CRC进行比较。如果不相等,则可能出现了传输错误。检查CRC也有助于验证您是否真正找到了帧的开头,因为同步位在某些情况下也可能出现在帧的数据部分。
CRC是通过对帧的一部分应用CRC-16算法(生成多项式为0x8005)来计算的。以下数据被考虑用于CRC:头部的最后两个字节以及校验和之后音频数据中的若干位。计算CRC时必须跳过校验和本身。不幸的是,在Layer II中没有简单的方法来计算校验和所需的帧数。因此,我在代码中省略了它。您需要除头部之外的其他信息来计算必要的位数。但是,仅凭头部信息就可以计算Layer I和Layer III中受保护的位数。
对于Layer III,您需要考虑完整的侧信息以进行CRC计算。侧信息在Layer III文件中跟随头部或CRC。它包含有关帧通用解码的信息,但不包含实际编码的音频样本。下表显示了所有Layer III文件的侧信息大小。
MPEG 1 | MPEG 2/2.5 (LSF) | |
---|---|---|
立体声、联合立体声、双通道 | 32 | 17 |
Mono | 17 | 9 |
对于Layer I文件,您必须考虑头部中的模式扩展(参见表2.1.6)。然后,您可以通过应用以下公式计算CRC计算所需的**位数**
4 * (number of channels * bound of intensity stereo +
(32 - bound of intensity stereo));
这可以理解为两个立体声子带的数量加上单声道子带的数量,然后将结果乘以4。对于简单的单声道帧,这等于128,因为通道数为一,且强度立体声的边界为32,这意味着没有强度立体声。对于立体声帧,这是256。有关更多信息,请参见CMPAFrame
类中的CRC代码。
2.3. VBR头
一些文件以可变比特率模式(VBR)编码。要估算这些文件的持续时间,您需要了解整个文件的**平均比特率**。它通常与第一个帧的比特率相差很大,因为静音部分(尤其是在开头)会使用可用的最低比特率。为了获得此平均比特率,您必须遍历文件中的所有帧,通过汇总每个帧的比特率然后除以帧数来计算它。由于这不是一个好的做法(非常慢),因此在第一个帧的数据部分(帧头之后)存在附加的VBR头。它们包含文件的总帧数,您可以根据以下公式计算持续时间(秒)
Duration = Number of Frames * Samples Per Frame / Sampling Rate
此外,VBR头通常包含一个表,该表对于在文件中查找位置是必需的。
2.3.1 XING头
这个头通常(但不总是)添加到以可变比特率模式(VBR)编码的文件中。这个头位于第一个MPEG音频头的特定位置之后。包含XING头的整个第一个帧是有效的但空的音频帧,因此即使不考虑此头的解码器也可以解码该文件。XING头位于Layer III文件侧信息之后。因此,您可以通过在表2.2.1中的值加上4个字节(用于MPEG音频头)来计算XING头相对于帧开头的开始位置。偏移量计算不包括头部后面的16位CRC,并且对于所有层都相同,尽管只有Layer III具有侧信息。
要读取此头,您必须找到第一个MPEG音频头,然后转到帧内的特定位置。XING头本身格式如下。(请注意,位置是零基的;位置、长度和示例都以字节格式表示。)
职位 | 长度 | 含义 | 示例 |
---|---|---|---|
0 |
4 | 4个ASCII字符的VBR头ID,可以是“Xing”或“Info”,非NULL终止 | 'Xing' |
4 |
4 |
标志,指示存在哪些字段,标志通过逻辑OR组合。字段是必需的。 0x0001 - 存在帧字段 |
0x0007 (表示帧、字节和TOC有效) |
8 | 4 | 文件中的**帧**数,大端序DWORD (可选) |
7344 |
8或12 | 4 | 文件中的**字节**数,大端序DWORD (可选) |
45000 |
8、12或16 | 100 | 100个用于查找的**TOC**条目,作为整数BYTE (可选) |
|
8、12、16、108、112或116 | 4 | **质量指示器**,大端序DWORD 从0(最佳质量)到100(最差质量)(可选) |
0 |
根据此格式,XING头仅包含ID和标志。所有其他字段都是可选的,取决于设置的标志。有时此头也会添加到CBR文件中。在这种情况下,它通常具有“Info”ID而不是“Xing”。
存在此头的**LAME扩展**,由通用LAME编码器使用,但我没有考虑它,因为它对于持续时间估算不是必需的。尽管如此,这里是MP3信息标签文档的链接。
2.3.2 VBRI头
据我所知,这个头只被Fraunhofer编码器编码的MPEG音频文件使用。它与XING头不同。您可以在文件中的第一个MPEG音频头的末尾**32个字节**之后找到它。(请注意,位置是零基的;位置、长度和示例都以字节格式表示。)
职位 | 长度 | 含义 | 示例 |
---|---|---|---|
0 |
4 | 4个ASCII字符的VBR头ID,始终是“VBRI”,非NULL终止 | 'VBRI' |
4 |
2 | 版本ID,大端序WORD |
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 | 每个表条目的字节大小(最大4),大端序WORD |
2 |
24 | 2 | 每个表条目的帧数,大端序WORD |
845 |
26 | **TOC**条目,用于大端序整数查找。根据每个表条目的大小和条目数,您可以计算此字段的长度。 |
3. 附加标签
请注意,文件开头或结尾可能包含不属于MPEG音频帧的附加数据。这些数据称为标签,因为它包含文件的元数据,如标题、艺术家、音轨、年份等。您必须考虑这些标签,因为只有MPEG音频数据才计入持续时间估算。文件末尾可能有一个ID3V1标签、一个Lyrics3标签或一个Musicmatch标签。文件开头或结尾可能有一个ID3V2标签和/或一个APE标签。您可以在www.id3.org上找到有关ID3和Lyrics3标签的信息。APE最初是为APE(Monkey's Audio)格式的无损压缩音频文件开发的。但现在这个标签也用于MPEG音频文件。Musicmatch标签曾被Musicmatch编码器的旧版本使用。不幸的是,网络上关于这个标签的信息非常少,因为它是一个专有的Musicmatch格式。
4. 使用代码
我编写了一些C++类来处理MPEG音频帧头和VBR头。CMPAFile
类代表整个文件,并提供访问特定帧的方法(CMPAFrame
类)。此类实例化一个CMPAHeader
类,该类代表帧本身的MPEG音频帧头。可以通过类变量访问头中的所有字段。此外,还有一个CVBRHeader
类,它是CXINGHeader
和CVBRIHeader
的通用类。所有标签都派生自CTag
类。这些类完全独立于MFC或ATL等任何库。它们仅使用Win32 API。所有类在出错时都会抛出异常。所有异常都是CMPAException
类型。您可以使用ShowError()
方法显示异常信息。所有类都使用CMPAStream
进行文件访问。此类包含一个简单的缓冲区。
下面是一个演示如何使用这些类的代码片段。请注意,您至少必须包含头文件mpafile.h
try { // open file and look for first header CMPAFile MPAFile(_T("C:\\test.mp3")) ; cout << MPAFile.GetLengthSec() << _T(" seconds"); } catch(CMPAException& Exc) { // show error message Exc.ShowError(); }
有关更多信息,请查看演示项目**MPEG Audio Info**的源代码,这是一个简单的MFC对话框应用程序,它使用CMPAFile
类来获取MPEG音频文件的信息。它还可以对整个文件进行错误检查,以查找帧结构中的错误。
5. 链接与杂项
在这里,您可以找到我用于本文的来源
- MPEG 1 规格 (ISO/IEC 13818-3).
- MPEG 2 规格 (ISO/IEC 11172-3).
- 来自MP3-Tech.org的MPEG音频头规格.
- 来自Real Networks的XING头SDK.
- MP3信息标签.
- 来自Fraunhofer研究所的VBRI头SDK.
- 具有不同头和标签的MP3示例文件.
- ID3 & Lyrics标签.
- APE标签.
- Musimatch标签.
如果您在代码或文章中发现任何错误,或有改进建议,请发布到下面的论坛或发送电子邮件至webmaster@wincd.de。
6. 历史
- 2004-09-15
- **MPEG Audio Info 1.0版本**发布。
- **文章初版**发布。
- 2004-11-01
- **MPEG Audio Info 2.0版本**发布。
- 增加了获取任意帧(不仅仅是第一帧)信息的功能。
- 增加了MPEG音频文件的检查功能。
- 改进了对有问题的MPEG文件的处理(容错范围+/-3字节来查找下一帧)。
- 正确检测填充。
- 改进了缓冲区管理。
- 修复了其他一些小问题。
- 添加了一个自述文件。
- 文章更新。:
- 添加了关于模式扩展字段的信息。
- 修复了XING头偏移量(单声道和立体声反转)。
- 修复了VBRI中的帧和字节(它们被反转了)。
- 修复了VBRI头中质量指示器的位置。
- 纠正了一些拼写错误。
- **MPEG Audio Info 2.0版本**发布。
- 2005-11-17
- **MPEG Audio Info 2.1版本**发布。
- 清理了类架构。
- 改进了帧导航。
- 改进了文件检查。
- 修复了原版位检查。
- 修复了所有层的帧大小计算(正确截断)。
- 修复了VBR文件中跳过小帧的问题。
- 新的缓存管理。
- 添加了CRC检查。
- 添加了ID3V1/V2、APE和Lyrics3标签的检测。
- 文章更新。
- 添加了关于CRC的信息。
- 修复了采样率表。
- 一些小的增强。
- **MPEG Audio Info 2.1版本**发布。
- 2007-04-09
- **MPEG Audio Info 2.2版本**发布。
- 添加了Musicmatch-Tag检测
- 更好的异常处理
- 改进了CMPAStream的设计
- 向对话框添加了拖放功能
- 修复了内存泄漏
- 将解决方案更新到Visual Studio 2005
- 提高了查找帧的性能
- 文章更新。
- 修复了损坏的链接
- 添加了MPEG音频规范的链接
- 添加了关于Musicmatch的信息链接
- **MPEG Audio Info 2.2版本**发布。