MP3(全称 MPEG-1 Audio Layer III 或 MPEG-2 Audio Layer III,标准编号 ISO/IEC 11172-3 / 13818-3)是广泛应用的感知音频有损压缩格式之一。
下面整理播放器读取 MP3 时需要处理的几件事:跳过标签、找到音频帧、计算帧长,以及利用位库还原主数据。
1. MP3 文件整体结构
MP3 文件以音频帧为主体,开头和结尾还可能带有 ID3 标签:
+───────────────────────+──────────────────────────────+───────────────────────+
| ID3v2 标签 (文件头) | 音频数据帧序列 (Frames) | ID3v1 标签 (文件尾) |
| (变长,存歌名/封面等) | [Frame 0][Frame 1]...[Frame N]| (固定 128 字节,兼容)|
+───────────────────────+──────────────────────────────+───────────────────────+
1.1 ID3v1(尾部固定 128 字节)
- 位于文件末尾 128 字节,以 ASCII 字符
TAG开头,字段长度固定(标题 30B、艺术家 30B、专辑 30B、年份 4B、流派 1B)。ID3v1.1 借用评论字段末尾存储音轨号。
1.2 ID3v2(头部可扩展标签)
- 位于文件开头,常见版本为 ID3v2.3 / ID3v2.4。采用“Frame Header + Frame Body”的键值结构(如
TIT2为标题、TPE1为艺术家、APIC为内嵌封面图片),大小通过 Syncsafe 整数(每个字节仅使用低 7 位,防止与音频同步字冲突)表示。纯音频解码器通常直接跳过 ID3v2 头部定位首个音频帧。
2. MP3 音频帧结构与 32-bit 帧头解析
MP3 音频数据由连续的音频帧(Frame)组成。在 MPEG-1 Layer 3 下,每个音频帧解码后输出 1152 个 PCM 采样点(包含 2 个 Granule,每个 576 样本)。
+─────────────────────+─────────────────────+─────────────────────+─────────────────────+
| 帧头 (Header) | CRC 校验 (可选) | 边信息 (Side Info)| 主数据 (Main Data)|
| (4 字节) | (2 字节) | (17 或 32 字节) | (哈夫曼编码频谱数据)|
+─────────────────────+─────────────────────+─────────────────────+─────────────────────+
2.1 32-bit 帧头位域分布
31 21 20 19 18 17 16 15 12 11 10 9 8 7 6 5 4 3 2 1 0
+-----------------+-----+-----+--+------+-----+--+--+---+---+---+---+
| 同步字 (11/12b) | Ver |Layer| P|Bitrate| Freq|Pd|Pr|ChM|Ext|C|H|E|
+-----------------+-----+-----+--+------+-----+--+--+---+---+---+---+
- 同步字(Syncword, bit 31~21):连续 11 或 12 个
1(0xFFE或0xFFF),用于数据流中定位帧边界; - MPEG Version (bit 20, 19):
00=MPEG-2.5,10=MPEG-2,11=MPEG-1; - Layer (bit 18, 17):
01=Layer III (MP3),10=Layer II,11=Layer I; - Protection (bit 16):
0=包含 16-bit CRC 校验字段,1=无 CRC; - Bitrate Index (bit 15~12):码率查表索引(如 128 kbps, 192 kbps, 320 kbps 等);
- Sampling Frequency (bit 11, 10):采样率查表索引(
00=44.1kHz,01=48kHz,10=32kHz); - Padding bit (bit 9):填充位。若置 1,本帧长度增加 1 字节(用于调整采样率与码率非整数倍时的平均速率);
- Channel Mode (bit 7, 6):
00=立体声 Stereo,01=联合立体声 Joint Stereo,10=双声道 Dual Channel,11=单声道 Mono。
2.2 变长帧长度计算公式
播放器顺序读取 MP3 流时,每解析完一个 4 字节帧头,即可算出当前帧在物理文件中的字节数:
\[\text{Frame Length (Bytes)} = \left\lfloor \frac{144 \times \text{Bitrate (bps)}}{\text{Sample Rate (Hz)}} \right\rfloor + \text{Padding}\]示例:码率 128 kbps、采样率 44.1 kHz、
Padding = 0时: \(\text{Length} = \left\lfloor \frac{144 \times 128000}{44100} \right\rfloor + 0 = 417\text{ 字节}\)
3. 位库技术 (Bit Reservoir)
在恒定码率(CBR)下,各帧分配到的字节大小是固定的。但音频信号的复杂度随时间剧烈变化(平缓单音所需比特少,交响乐突发瞬态所需比特多)。
Frame N-1 (平缓信号, 消耗少) ──> 将剩余未用的比特借存至【位库 Bit Reservoir】
│
▼
Frame N (复杂瞬态, 需求大) <── 从位库借入额外比特, 突破 CBR 单帧容量限制
- 主数据负偏移(
main_data_begin): 边信息(Side Info)中包含一个 9-bit 字段main_data_begin,指示当前帧的哈夫曼主数据向前回退了多少字节。解码器在解析当前帧时,必须从滑动历史缓冲区中提取对应偏移的数据。
4. MP3 完整解码流水线
graph TD
Bitstream[MP3 比特流] --> Sync[同步字 0xFFE 定位 & 帧头解析]
Sync --> SideInfo[解析边信息 main_data_begin & 比例因子]
SideInfo --> Reservoir[位库拼接重组 Main Data]
Reservoir --> Huffman[哈夫曼熵解码 576 频域系数]
Huffman --> Dequant[非线性反量化 xr = sign * |ix|^(4/3) * 2^(gain)]
Dequant --> Stereo[立体声联合解码 MS / Intensity Stereo]
Stereo --> IMDCT[IMDCT 频域到时域变换 36/12点]
IMDCT --> Synthesis[多相综合滤波器组 Polyphase Filterbank 32子带]
Synthesis --> PCM[输出 16-bit PCM 采样点]
- 反量化(Dequantization):将哈夫曼解码出的整数系数还原为浮点频域谱线;
- IMDCT 逆变换:结合长窗(高频分辨率,平稳信号)与短窗(高时间分辨率,突发瞬态,抑制预回声)将频域变换回时域子带样点;
- 多相滤波合成:将 32 个子带信号重构合成连续的 PCM 波形。
5. 总结
帧头可以帮助定位边界和计算帧长,但找到同步字不代表当前帧一定能独立解码。Seek 后仍要处理位库所依赖的历史主数据,并检查后续帧头,避免把标签或载荷中的字节误当成同步字。