MP3
动态图像专家组-1 或 动态图像专家组-2 音频层III(MPEG-1 or MPEG-2 Audio Layer III),常简称为 MP3,是当今流行的一种数字音频编码和有损压缩格式,它被设计来大幅降低音频数据量,通过舍弃 PCM 音频资料中对人类听觉不重要的部分,达成压缩成较小文件的目的。而对于大多数用户的听觉感受来说,MP3 的音质与最初的不压缩音频相比没有明显的下降。它是在 1991 年,由位于德国埃尔朗根的研究组织弗劳恩霍夫协会的一组工程师发明和标准化的
它根据压缩质量和编码复杂程度划分为三层,即Layer-1、Layer2、Layer3, 且分别对应MP1、MP2、MP3 这三种声音文件,并根据不同的用途,使用不同层次的编码
MP1 和MP2 的压缩率分别为 4:1 和 6:1-8:1,而 MP3 的压缩率则高达10:1-12:1
比特率
比特率对于 MP3 文件来说是可变的。总的原则是比特率越高则声音文件中包含的原始声音信息越多,这样回放时声音质量也越高。在MP3 编码的早期,整个文件使用一个固定的比特率,称为固定码率(CBR)
MPEG-1 Layer 3 允许使用的比特率是 32、40、48、56、64、80、96、112、128、160、192、224、256 和 320 kbit/s,允许的采样频率是 32、44.1 和 48千赫兹,44.1kHz 是最为经常使用的速度(与 CD 的采样速率相同)。MPEG-2 和 MPEG-2.5(非正式的) 包括其他一些比特率:6、12、24、32、40、48、56、64、80、96、112、128、144、160kbit/s
可变码率(VBR)也是可能的。MP3 文件的中的音频切分成有自己不同比特率的帧,这样在文件编码的时候就可以动态地改变比特率。尽管在最初的实现中并没有这项功能。VBR技术现在音频/视频编码领域已经得到了广泛的应用,这项技术使得在声音变化大的部分使用较大的比特率而在声音变化小的部分使用较小的比特率成为可能。这个方法类似于声音控制的磁带录音机不记录静止部分节省磁带消耗。一些编码器在很大程度上依赖于这项技术
设计限制
MP3 格式存有设计限制,即使使用更好的编码器仍旧不能克服这些限制。一些新的压缩格式如 Opus 等不再有这些限制。
- 比特率最大是 320 kbit/s,时间分辨率相对于变化迅速的信号来说太低
- 对于超过 15.5/15.8 kHz的频率没有因数频带,即超过此频率的声音无法编码在 MP3 内,从频谱来看,15 kHz以上的声音全部消失了,而人耳的听觉上限一般在20 kHz
- 采样频率最高为 48kHz,对于超过 48kHz 采样频率的音频无法编码在 MP3 内
- 联合立体声(Joint stereo)是基于帧与帧完成的
- 没有定义编码器/解码器的整体时延,这就意味着 gapless playback 缺少一个正式的规定
格式分析
MP3 Structure
名称 | 说明 |
---|---|
TAG_V2(ID3v2) | 包含了作者、作曲、专辑等信息,长度不固定,扩展了 ID3v1 的信息量 |
音频数据 | 1. 音频数据由系列的数据帧构成 2. 每个帧的长度可能固定,也可能不固定,由位率(码率)决定 3. 每个帧都包括:帧头、数据实体两部分 4. 帧头记录着 MP3 的位率、采样率、版本等信息 5. 如果启用 CRC 验证,则帧头后面跟随两字节 CRC 校验 之后可能跟随 32 字节的附加信息,也可能没有附加信息 |
TAG_V1(ID3v1) | 包含了作者、作曲、专辑等信息,长度为 128byte |
其他信息 | 部分 MP3 可能一些额外的信息 |
MP3 文件的结构图(不支持 MPEG 2.5 版,因此 MP3 同步字为 12 位而不是 11 位)(图来自 MP3 Wiki)
ID3v2
ID3v2 一共有四个版本,ID3v2.1/2.2/2.3/2.4,目前流行的播放软件一般只支持第三版即 ID3v2.3
ID3v2.3 由一个标签头和若干个标签帧或者一个扩展标签头组成,至少要有一个标签帧,每一个标签帧记录一种信息,例如作曲、标题等
本章节描述的是 ID3v2.3
ID3v2 header
名称 | 类型 | 示例值 | 说明 |
---|---|---|---|
ID3v2/file identifier | char[3] | “ID3” | ID3v2 为 “ID3” |
ID3v2 version | uint16_t | 0x03 0x00 | 前一个字节表示主版本号,后一个字节表示修订版本号 |
ID3v2 flags | uint8_t | abc00000 | 目前只使用最高的 3 位,其他位为 0 a: 是否使用 unsynchronisation b: 是否有 extended header c: 是否为测试标签 |
ID3v2 size | uint32_t | 4 * 0xxxxxxx | 4字节,每个字节只能用低 7 位,最高位为 0 0x00 0x00 0x02 0x01 = 257 |
ID3v2 extended header
名称 | 类型 | 说明 |
---|---|---|
Extended header size | uint32_t | ID3v2 扩展头大小,不包括该字段本身 |
Extended Flags | uint16_t | 此字段虽然占用两个字节,但是除了首个字节的最高位,其余各位都不使用,且必须为 0。如果首字节的最高位被置 1,那么 ID3v2 扩展头将会多一个字段 ”Total frame CRC“。CRC32 是一种循环冗余校验技术,为了发现标签数据在传输或存储过程中可能出现的错误,使用 CRC32 算法先对标签数据进行一个次运算,这次运算得出的结果是 32 个二进制位。如果标签数据在传输或存储过程中保持原样不变,在这 32 个二进制位的参与下对数据再次进行运算结果一定会是 32 个二进制 0。若 32 位结果中任何一位不是 0,则说明数据在传输或存储的某个环节中已经出现了差错。这里所说的 CRC32 数据指的就是传输或存储之前对数据运算所得的32 个二进制位,显然它必须占用 4 个字节的存储空间,此时的 ID3v2 扩展头大小也就变成了 14 个字节。因此前面所提 “Extended header size” 字段在这种情况存储的值也就变成了 14-4=10。需要注意的是,对标签数据的 CRC32 运算应该在 unsynchronisation 方案应用于标签数据之前进行 |
Size of padding | uint32_t | ID3v2占据了文件的头部,ID3v2后面才是音频帧数据。如果 ID3v2 需要扩大以容纳更多的标签数据,那么音频帧数据也需在文件中向后搬移。为了避免这种情况频繁发生,ID3v2 在其结构尾部预留了一定的存储空间,如果 ID3v2 的扩大没有超出这些预留空间,那就不需要向后移动音频帧的位置了。这些预留的存储空间被称为 pading,由于在 ID3v2 需要扩大之前 padding 空间并未存储有意义的数据,所以 padding 空间中的每个字节都存储着 0x00。padding 空间不参与 CRC 校验运算 |
Total frame CRC | uint32_t | 只有 Extended Flags 首字节最高位为 1 才会存在该字段。此字段占用 4 个字节。CRC 校验仅限于标签数据本身,ID3v2 头和 ID3v2 扩展头都不参与其中,padding 数据也不参与 CRC 校验 |
ID3v2 frame header
名称 | 类型 | 说明 |
---|---|---|
Frame ID | char[4] | 帧标识 |
Size | uint32_t | 帧内容大小,不包括帧头,不小于 1 |
Flags | uint16_t | 见 Frame header flags |
Declared ID3v2 frames
Frame ID(ID3v2.3) | Frame ID(ID3v2.4) | 英文描述 | 中文描述 |
---|---|---|---|
AENC | ARNC | Audio encryption | 音频是否加密 |
- | ASPI | Audio seek point index | 音频搜索点索引 |
APIC | APIC | Attached picture | 封面图片 |
COMM | COMM | Comments | 格式:”eng/0 备注内容”,其中 eng 表示备注所使用的自然语言 |
COMR | COMR | Commercial frame | 广告 |
ENCR | ENCR | Encryption method registration | 加密方法,同 AENC 一同使用 |
EQUA | EQU2 | Equalization | 均衡器,允许用户在文件中预先定义均衡曲线 |
ETCO | ETCO | Event timing codes | 事件时间编码 |
GEOB | GEOB | General encapsulated object | 通用封装对象 |
GRID | GRID | Group identification registration | 能够对其他不相关的帧进行分组 |
IPLS | TIPL | Involved people list | 参与人员名单 |
LINK | LINK | Linked information | 外部 ID3v2 标签链接 |
MCDI | MCDI | Music CD identifier | CD 音乐标识 |
MLLT | MLLT | MPEG location lookup table | 时间位置对照表 |
OWNE | OWNE | Ownership frame | 所有权 |
PRIV | PRIV | Private frame | 用于存储软件生产商自定义的信息 |
PCNT | PCNT | Play counter | 文件播放次数计数器 |
POPM | POPM | Popularimeter | 普通仪表 |
POSS | POSS | Position synchronisation frame | 第一帧时间偏移量 |
RBUF | RBUF | Recommended buffer size | 推荐缓冲区大小 |
RVAD | RVA2 | Relative volume adjustment | 音量调节器 |
RVRB | RVRB | Reverb | 混响调整 |
- | SEEK | Seek frame | 搜索用 |
- | SIGN | Signature frame | 签名用 |
SYLT | SYLT | Synchronized lyric/text | 同步歌词或文本 |
SYTC | SYTC | Synchronized tempo codes | 同步节拍编码 |
TALB | TALB | Album/Movie/Show title | 专集 |
TBPM | TBPM | Beats per minute (BPM) | 拍子 |
TCOM | TCOM | Composer | 作曲家 |
TCON | TCON | Content type | 音乐类型,直接用字符串表示 |
TCOP | TCOP | Copyright message | 版权 |
TDAT | TDRC | TDAT Date | 灌录日期 |
- | TDEN | Encoding time | 编码时间 |
TDLY | TDLY | Playlist delay | 播放延时 |
- | TDRC | Recording time | 音频纪录时间 |
- | TDRL | Release time | 音频发行时间 |
- | TDTG | Tagging time | 音频被标记时间 |
TENC | TENC | Encoded by | 编码者 |
TEXT | TEXT | Lyricist/Text writer | 填词人 |
TFLT | TFLT | File type | 文件类型 |
TIME | TDRC | Time | 灌录的时间 |
TIT1 | TIT1 | Content group description | 内容组别 |
TIT2 | TIT2 | Title/songname/content description | 标题 |
TIT3 | TIT3 | Subtitle/Description refinement | 歌名副标题 |
TKEY | TKEY | Initial key | 音调 |
TLAN | TLAN | Language(s) | 语言 |
TLEN | TLEN | Length | 音频长度 |
- | TMCL | Musician credits list | 音乐家与乐器对照 |
TMED | TMED | Media type | 媒体类型 |
- | TMOO | Mood | 情境 |
TOAL | TOAL | Original album/movie/show title | 原唱片集 |
TOFN | TOFN | Original filename | 原文件名 |
TOLY | TOLY | Original lyricist(s)/text writer(s) | 原歌词 |
TOPE | TOPE | Original artist(s)/performer(s) | 原艺术家/演唱者 |
TORY | TDOR | Original release year | 原发行年份 |
TOWN | TOWN | File owner/licensee | 文件所有者 |
TPE1 | TPE1 | Lead performer(s)/Soloist(s) | 作者 |
TPE2 | TPE2 | Band/orchestra/accompaniment | 乐队/管弦乐队/伴奏 |
TPE3 | TPE3 | Conductor/performer refinement | 指挥家 |
TPE4 | TPE4 | Interpreted, remixed, or otherwise modified by | 翻唱/混音/改编 |
TPOS | TPOS | Part of a set | 片段来源 |
- | TPRO | Produced notice | Produced notice |
TPUB | TPUB | Publisher | 出版商 |
TRCK | TRCK | Track number/Position in set | 音轨,格式: N/M,其中 N 为专集中的第 N 首, M 为专集中共 M 首,N 和 M 为 ASCII 码表示的数字 |
TRDA | TDRC | Recording dates | 灌录时期 |
TRSN | TRSN | Internet radio station name | 网络电台名称 |
TRSO | TRSO | Internet radio station owner | 网络电台所有者 |
TSIZ | 弃用 | Size | 音频长度 |
- | TSOA | Album sort order | 依专辑排序 |
- | TSOP | Performer sort order | 依演出者排序 |
- | TSOT | Title sort order | 依标题排序 |
TSRC | TSRC | ISRC (international standard recording code) | 国际灌录编码标准 |
TSSE | TSSE | Software/Hardware and settings used for encoding | 编码使用的 软件/硬件 设置 |
- | TSST | Set subtitle | 设置字幕 |
TYER | TDRC | Year | 年代,是用 ASCII 码表示的数字 |
TXXX | TXXX | User defined text information frame | 年度 |
UFID | UFID | Unique file identifier | 唯一的文件标识符 |
USER | USER | Terms of use | 使用条款 |
USLT | USLT | Unsychronized lyric/text transcription | 歌词 |
WCOM | WCOM | Commercial information | 广告信息 |
WCOP | WCOP | Copyright/Legal information | 版权信息 |
WOAF | WOAF | Official audio file webpage | 官方音频文件网页 |
WOAR | WOAR | Official artist/performer webpage | 官方艺术家网页 |
WOAS | WOAS | Official audio source webpage | 官方音频原始资料网页 |
WORS | WORS | Official internet radio station homepage | 官方互联网无线配置首页 |
WPAY | WPAY | Payment | 付款 |
WPUB | WPUB | Publishers official webpage | 出版商官方网页 |
WXXX | WXXX | User defined URL link frame | 用户自定义 URL 链接 |
Frame header flags
Flags 字段定义:%abc00000 %ijk00000
字段 | 说明 |
---|---|
a | 标签保护标志。设置时认为此帧作废 |
b | 文件保护标记。设置时认为此帧作废 |
c | 只读标志。设置时认为此帧不能修改 |
d | 压缩标志。设置时一个字节存放两个 BCD 码表示数字 |
e | 加密标志 |
f | 组标志。设置时说明此帧和其他的某帧是一组 |
MP3 Frame
MP3 Frame = MP3 Header + MP3 Data
Frame Header
名称 | 位长 | 说明 |
---|---|---|
同步信息 | 11 | 所有位均为 1 |
版本 | 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 | 取样率,单位是 kbps,例如:采用 MPEG-1 Layer 3,64kbps,值为 0101 具体参照比特率对照表 |
采样率 | 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-调整,具体调整计算方法见下文 |
保留字 | 1 | |
声道模式 | 2 | 00-立体声 Stereo 01-Joint Stereo 10-双声道 11-单声道 |
扩充模式 | 2 | 当声道模式为 01 时才使用 Value 强度立体声 MS立体声 00 off off 01 on off 10 off on 11 on on |
版权 | 1 | 文件是否合法 0-不合法 1-合法 |
原版标志 | 1 | 是否原版 0-非原版 1-原版 |
强调方式 | 2 | 用于声音经降噪压缩后再补偿的分类,很少用到,今后也可能不会用 00-未定义 01-50/15ms 10-保留 11-CCITT J.17 |
Bitrate index
单位 kbps
bits | V1,L1 | V1,L2 | V1,L3 | V2,L1 | V2,L2 | V2,L3 |
---|---|---|---|---|---|---|
0000 | free | free | free | free | free | free |
0001 | 32 | 32 | 32 | 32(32) | 32(8) | 8(8) |
0010 | 64 | 48 | 40 | 64(48) | 48(16) | 16(16) |
0011 | 96 | 54 | 48 | 96(56) | 56(24) | 24(24) |
0100 | 128 | 64 | 56 | 128(64) | 64(32) | 32 (32) |
0101 | 160 | 80 | 64 | 160(80) | 80(40) | 64 (40) |
0110 | 192 | 96 | 80 | 192(96) | 96(48) | 80 (48) |
0111 | 224 | 112 | 96 | 224(112) | 112(56) | 56 (56) |
1000 | 256 | 128 | 112 | 256(128) | 128(64) | 64 (64) |
1001 | 288 | 160 | 128 | 288(144) | 160(80) | 128 (80) |
1010 | 320 | 192 | 160 | 320(160) | 192(96) | 160 (96) |
1011 | 352 | 224 | 192 | 352(176) | 224(112) | 112 (112 |
1100 | 384 | 256 | 224 | 384(192) | 256(128) | 128 (128) |
1101 | 416 | 320 | 256 | 416(224) | 320(144) | 256 (144) |
1110 | 448 | 384 | 320 | 448(256) | 384(160) | 320 (160) |
1111 | bad | bad | bad | bad | bad | bad |
名词说明:
V1 - MPEG 1,V2 - MPEG 2 and MPEG 2.5
L1 - Layer 1,L2 - Layer 2,L3 - Layer 3
“free” 表示位率可变,”bad” 表示不允许值
Frame Length
帧大小即每帧的采样数,表示一帧数据中采样的个数,该值是恒定的,如下表所示:
MPEG1 | MPEG2(LSF) | MPEG2.5(LSF) | |
---|---|---|---|
Layer1 | 384 | 384 | 384 |
Layer2 | 1152 | 1152 | 1152 |
Layer3 | 1152 | 576 | 576 |
帧长度是压缩时每一帧的长度,包括帧头的 4 个字节。它将填充的空位也计算在内。Layer 1 的一个空位长 4 字节,Layer 2 和 Layer 3 的空位是 1 字节。当读取 MPEG 文件时必须计算该值以便找到相邻的帧。注意:因为有填充和比特率变换,帧长度可能变化
计算公式如下:
- Layer 1:Len(字节) = ((每帧采样数 / 8 * 比特率) / 采样频率) + 填充 * 4
- Layer2/3:Len(字节) = ((每帧采样数 / 8 * 比特率) / 采样频率) + 填充
例:MPEG1 Layer3 比特率 128000,采样率 44100,填充 0,帧长度为:
((1152 / 8 * 128Kbps) / 44.1kHz + 0 = 417 字节
Frame Duration
每帧持续时间(毫秒) = 每帧采样数 / 采样频率 * 1000
例:1152 / 441000 * 1000 = 26ms
Side Info
Side Info 位于有效帧的数据区里对应大小如下:
MPEG 1 | MPEG 2/2.5 (LSF) | |
---|---|---|
Stereo, Joint Stereo, Dual Channel | 32 | 17 |
Mono | 17 | 9 |
Encoding
对于 MP3 来说现在有两种编码方式,一种是 CBR,一种是 VBR
CBR,固定位率。固定位率的帧的大小在整个文件中都是是固定的(公式如上所述),只要知道文件总长度,和从第一帧帧头读出的信息,就都可以通过计算得出这个 MP3 文件的信息,比如总的帧数,总的播放时间等等,要定位到某一帧或某个时间点也很方便,这种编码方式不需要文件头,第一帧开始就是音频数据
VBR,可变位率。VBR 是 XING 公司推出的算法,所以在 MP3 的 FRAME 里会有 “Xing” 这个关键字(也有用”Info”来标识的,现在很多流行的小软件也可以进行 VBR 压缩,它们是否遵守这个约定,那就不得而知了),它存放在 MP3 文件中的第一个有效帧的数据区里,它标识了这个 MP3 文件是 VBR 的。同时第一个帧里存放了 MP3 文件的帧的总个数,这就很容易获得了播放总时间,同时还有 100 个字节存放了播放总时间的100 个时间分段的帧索引,假设 4 分钟的 MP3 歌曲,240s,分成 100 段,每两个相邻 INDEX 的时间差就是 2.4S,所以通过这个INDEX,只要前后处理少数的 FRAME,就能快速找出我们需要快进的帧头。其实这第一帧就相当于文件头了
不过现在有些编码器在编码 CBR 文件时也像 VBR 那样将信息记入第一帧,比如著名的 lame,它使用 “Info” 来做 CBR 的标记
VBR Header
VBR 文件头位于 MP3 文件中第一个有效帧的数据区,详细结构如下:
位置 | 长度 | 说明 | 示例 |
---|---|---|---|
0 | 4 | VBR 头标记,4 个字节的 ASCII 字符,内容为 “Xing” 或者 “Info” | “Xing” |
4 | 4 | 指示 VBR 头具体内容的标记,多种内容使用逻辑或组合: 0x0001-总帧数存储区域存在,不包括第一帧 0x0002-文件长度存储区域存在,不包括标签 0x0004-TOC 存储区域存在 0x0008-质量指示存储区域存在 |
0x0007(表示:总帧数、文件长度 和 TOC 存储区域存在) |
8 | 4 | 帧数为大端双字(可选) | 7344 |
8 or 12 | 4 | 文件字节数为大端双字(可选) | 45000 |
8, 12 or 16 | 100 | 搜索作为整数字节的 100 个 TOC 条目(可选) | |
8, 12, 16, 108, 112 or 116 | 4 | 质量指标为大端双字 从 0 - 最佳质量到,100 - 最差质量(可选) |
0 |
VBRI Header
目前此头信息,只有用 Fraunhofer 的编码器生成的 MPEG 音频文件,才会用到此头
位置 | 长度 | 说明 | 示例 |
---|---|---|---|
0 | 4 | VBRI 头 ID 用 4 字节 ASCII 字符表示,总是 “VBRI”,而不是以 NULL 结尾 | “VBRI” |
4 | 2 | 版本 ID, Big-Endian WORD | 1 |
6 | 2 | 延迟,Big-Endian float | 7344 |
8 | 2 | 质量指标 | 75 |
10 | 4 | 文件总字节数,Big-Endian DWORD | 45000 |
14 | 4 | 文件总帧数,Big-Endian DWORD | 7344 |
18 | 2 | TOC 表的表项数目,Big-Endian WORD | 100 |
20 | 2 | TOC 表项的缩放因子,Big-Endian DWORD | 1 |
22 | 2 | 单个 TOC 表项的大小,单位字节,最大为 4,Big-Endian WORD | 2 |
24 | 2 | 帧数/表项,Big-Endian WORD | 845 |
26 | 用于检索的 TOC 表,整数值,可以通过每个表项大小乘以表项个数的到此 TOC 表的总大小,Big-Endian integral |
Duration calc
对于能获取到总帧数的文件就可以计算出 MP3 的总时长
MP3 总时长(s) = (每帧采样数 * 总帧数) / 采样率
例如:(1152 * 8888) / 48000 = 213.312 s
Seek
VBR 编码的 seek 操作主要是利用 Xing 头中的 TOC 表(如果这个表存在),TOC 表(Table Of Contents)是一个长度为 100 的 byte 数组,数组中每个元素都代表在音频时长内的一个特定的时间点对应的文件的相对位置。 简单的说,TOC 表的组成,就是把整个文件平均分成 256 段,每一段代表一个文件位置,再把总的音频时长平均分为 100 段,每一段代表一个时间点,然后对这 100 个时间点,每一个都找出 256 个文件位置中其对应的那个位置,这个位置是这 256 个位置中的相对位置,取值在 0~255,放在 TOC 表中
假设文件持续 200 秒,现在需要跳到 50 秒,文件长度为 1000000 byte,那么先用以下公式计算出 50 秒对应 TOC 表的哪个元素:
1 | TOC[(50 / 200) * 100] = TOC[25] |
然后在根据以下公式算出文件位置:
1 | (TOC[25] / 256) * 1000000 |
FFMPEG 转换音频
1 | # VBR |
Reference
- https://id3.org/id3v2.3.0
- https://id3.org/id3v2.4.0-structure
- https://zh.wikipedia.org/wiki/ID3
- https://zh.wikipedia.org/wiki/MP3
- https://juejin.cn/post/6844904000786006023
- https://blog.csdn.net/u010650845/article/details/53520426
- https://juejin.cn/post/6948651938229518366#heading-5
- http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
- 本文标题:MP3
- 本文作者:Thomas Woo
- 发布时间:2021-09-09 20:30
- 最后更新:2022-12-12 15:29
- 本文链接:http://smileorigin.site/media/MP3/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 许可协议。转载请注明出处!