MP3文件格式全解

mp3播放参考代码(libmad库):my_minimad
wav播放参考代码(alsa声卡,alsa-lib库):wav_miniplay

WAV 格式文件头(除了文件头就是音频数据了),很简单,不用多说

struct WAVFmtHeader
{
    char  strRIFF[4];    /* 'RIFF' 资源文件标志,固定字符 */
    unsigned long  dwTotalByte;   /* 从下一个成员开始到文件结尾的总字节数 */
    char  strWAVE[4];    /* 'WAVE' 表示是 WAVE 文件,固定字符 */
    char  strFmt[4];     /* 'fmt ' 波形格式标志,固定字符 */
    unsigned long  dwPcmFmt;      /* 数据格式 16LE,32LE等等 */
    unsigned short bIsCompress;   /* 是否是压缩的 PCM 编码,大于 1 表示有压缩,等于 1 表示无压缩 */
    unsigned short wChannels;     /* 声道数量 */
    unsigned long  dwPcmSampRate; /* 采样频率 */
    unsigned long  dwByteRate;    /* byte 率, byterate = 采样频率 * 音频通道数量 * 数据位数 / 8 */
    unsigned short wFrameSize;    /* 块对齐/帧大小 framesize = 通道数 * 数据位数 / 8 */
    unsigned short wSampBitWidth;  /* 样本数据位数 */
    char  strData[4];    /* 'data' 数据标志,固定字符 */
    unsigned long  dwPcmDataSize; /* 实际音频数据的大小 */
};

1. MP3 全称

  • MP3 全称是 MPEG1 PlayerIII 音频文件
  • MPEG (Moving Picture Experts Group) 动态图像专家组,也就是为图像制作标准的组织,由 1988 年成立
  • 根据压缩的复杂度分为 PlayerI PlayerII 与 PlayerIII,复杂程度依次递增

2. MP3 文件的组成

MP3 文件的最小组成单位是帧。

2.1 ID3vX

ID3vX 是一种标签,在 MP3 文件中也以帧的形式存在,不过并不是 MP3 文件的有效音频数据帧,而是一个标签,里面包含有歌曲信息,例如:作曲人,歌曲制作时间等等

  • ID3v1

第一个版本的音频标签,长度为固定的 128 字节,位置在 MP3 文件的尾部。(事实上我看了很多的 MP3 文件,尾部并没有这个标签帧,这点存在疑惑)

ID3v1 标签帧的数据格式如下所示:

char Header[3];   /* 标签头必须是"TAG"否则认为没有标签 */
char Title[30];   /* 标题 */
char Artist[30];  /* 作者 */
char Album[30];   /* 专辑 */
char Year[4];     /*出品年代*/
char Comment[30]; /*备注*/
char Genre;       /*类型*/

其数据存放按照顺序一个个存放,如果长度不足则补 0,ID3v1 应该已经比较少用了

  • ID3v2.3

ID3v2 其实有 4 个版本,但是常用的只有 2.3 这个版本,所以这里只记录 2.3 版本的信息
ID3v2.3 有标签头和标签帧,标签头记录版本以及整个 ID3v2.3 的大小,标签帧则是记录歌曲信息

ID3v2.3 在文件的开头存放,从第一个字节开始,整个 ID3v2 的结构图如下所示

ID3v2 的结构图表

描述字节数内容
标签头ID3v2标识3固定字符 “ID3” ,表示是 ID3v2 标签
ID3v2子版本号203H 00H 表示是 ID3v2.3
ID3v2标志1abc00000B a 非同步编码 b 扩展标签头 c 测试指示为,都是 1 有效,一般都是 0
ID3v2大小4只有后 7 位有效,size = byteA:7 * 0x200000 + byteB:7 * 0x4000 + byteC:7 * 0x80 + byteD:7
扩展标签头扩展标签头大小4size = byte0 * 0x200000 + byte1 * 0x4000 + byte2 * 0x80 + byte3
扩展标志2xx
补空大小4你可以在所有的标签帧后面添加补空数据,也可以预留空间存放额外的帧,使得整个标签大小比标签头中的大小要更大,这里记录的就是增加的大小,一般不用
标签帧帧标识4固定的 4 个字符,用来标识这一帧里面存放的内容是什么,标识见下面的对照表:标签帧的标识以及其意义对照表
帧大小4size = byte0 * 0x200000 + byte1 * 0x4000 + byte2 * 0x80 + byte3
标志2不重要
帧数据size存放的数据
补空补空大小00H …
/* IDxVx 的头部结构 */
struct IDxVxHeader
{
    unsigned char aucIDx[3];     /* 保存的值比如为"ID3"表示是ID3V2 */
    unsigned char ucVersion;     /* 如果是ID3V2.3则保存3,如果是ID3V2.4则保存4 */
    unsigned char ucRevision;    /* 副版本号 */
    unsigned char ucFlag;        /* 存放标志的字节 */
    unsigned char aucIDxSize[4]; /* 整个 IDxVx 的大小,除去本结构体的 10 个字节 */
    /* 只有后面 7 位有用 */
};

2.2 CBR 与 VBR

  • CBR :帧长度固定,也就是说每一帧的播放时间是固定的,知道了一帧的长度以及文件的大小就可以计算出整个播放时长
  • VBR :帧长不固定,要获得整个播放时长需要知道文件一共有多少帧

帧长计算公式

LayerII 与 LayerII
帧长 = (每帧采样次数 * 比特率 / 8 / 采样率) + 补白
LayerI
帧长 = (每帧采样次数 * 比特率 / 8 / 采样率) + 补白 * 4

CBR 总播放时长计算公式

播放时长 = (文件大小 – ID3标签大小) * 8 / 比特率

VBR 总播放时长计算公式

播放时长 = 有效数据帧总帧数 * 每帧采样数 / 采样率
每帧数据的采样数索引表:每帧数据的采样数表
每一帧的播放时长计算公式
帧播放时长 = 采样数 / 采样频率 * 1000 毫秒

事实上 windows 上面我看到的都是按照 CBR 格式计算时长的,所以采用 CBR 格式计算即可

2.3 有效数据帧

所有的有效数据帧都有帧头,帧头为 4 个字节,它们的含义如下所示

有效数据帧帧头

偏移地址(bits)位数(bits)内容
011帧同步标识,表示数据帧一帧的开始
112MPEG 音频版本号,参照表:MPEG 音频版本表
132Layer 版本,参照表:Layer 索引表
151保护位,0 - 16bit CRC 0 - 无 CRC
164比特率索引,参照表:比特率索引表(单位-Kbps)
202采样率索引,参照表:采样率索引表
221如果设置的话数据被补空为一个 slot,LayerI slot 是 4 字节,其余为 1 字节
231私有位
242channel 模式,参照表:channel 模式表
262模式扩展
281Copyright 位
291Original 位
302强调,不关注

结构体可定义为如下所示:

struct DataFrameHeader
{
    unsigned int bzFrameSyncFlag1:8;   /* 全为 1 */
    unsigned int bzProtectBit:1;       /* CRC */
    unsigned int bzVersionInfo:4;      /* 包括 mpeg 版本,layer 版本 */
    unsigned int bzFrameSyncFlag2:3;   /* 全为 1 */
    unsigned int bzPrivateBit:1;       /* 私有 */
    unsigned int bzPaddingBit:1;      /* 是否填充,1 填充,0 不填充
    layer1 是 4 字节,其余的都是 1 字节 */
    unsigned int bzSampleIndex:2;     /* 采样率索引 */
    unsigned int bzBitRateIndex:4;    /* bit 率索引 */
    unsigned int bzExternBits:6;      /* 版权等,不关心 */ 
    unsigned int bzCahnnelMod:2;      /* 通道
    * 00 - Stereo 01 - Joint Stereo
    * 10 - Dual   11 - Single
    */
};

VBR 有效数据帧

由于市面上大多数 MP3 压缩都是用的 LAME 公司的技术,所以只讲 LAME 公司,”Info” 与 “Xing” 都是 LAME 公司的数据压缩标识
采用 VBR 编码的音频数据在有效数据帧的第一帧会有一个 VBR 头,且只有第一帧有,头部标识为 “Xing”。数据帧的第一帧包涵了整个 MP3 文件的信息,帧头是 4 个字节,接着是 32 字节的 0 填充,然后是 “Info” 或者 “Xing” 字符标识

VBR头

此 VBR 头在上面有效数据帧帧头之后偏移 32 字节的位置,数据格式如下

VBR 头

偏移(byte)长度(byte)内容
04固定的 ‘Xing’ or ‘Info’
44不关注
84帧数量,大端存储
8 or 124字节数,大端存储
8, 12 or 16100100 个时间点索引,例如一段音频长 3 分钟,分成 100 份,记录每一段的起始位置
8, 12, 16, 108, 112, 1164不关注

3. MP3 文件的内容排列

ID3v2                   如果有的话
补空                    如果有 ID3V2
VBR帧(有效数据帧第一帧)   如果是 VBR 编码的话
有效数据帧               一定有
ID3v1                   一定有(大多数地方写的),我看到的就没有

MPEG 音频版本表

indexcontent
00MPEG 2.5
01reserved
10MPEG 2
11MPEG 1

Layer 索引表

indexcontent
00reserved
01LayerIII
10LayerII
11LayerI

比特率索引表(单位 Kbps)

index------
Bitrate IndexMPEG 1MPEG 2,2.5
LayerILayerIILayerIIILayerILayerII & LayerIII
0000
0001323232328
00106448404816
00119656485624
010012864566432
010116080648040
011019296809648
01112241129611256
100025612811212864
100128816012814480
101032019216016096
1011352224192176112
1100384256224192128
1101416320256224144
1110448384320256160
1111

采样率索引表

采样率索引MPEG-1 (Hz)MPEG-2 (Hz)MPEG-2.5 (Hz)
00441002205011025
01480002400012000
1032000160008000
11reservedreservedreserved

每帧数据的采样数

-MPEG 1MPEG 2 (LSF)MPEG 2.5 (LSF)
Layer I384384384
Layer II115211521152
Layer III1152576576

channel 模式表

indexcontent
00Stereo
01Joint Stereo (Stereo)
10Dual channel (Two mono channels)
11Single channel (Mono)

标签帧的标识以及其意义对照表

indexcontent
AENC[Audio encryption]
APIC[Attached picture]
COMM[Comments]
COMR[Commercial frame]
ENCR[Encryption method registration]
EQUA[Equalization]
ETCO[Event timing codes]
GEOB[General encapsulated object]
GRID[Group identification registration]
IPLS[Involved people list]
LINK[Linked information]
MCDI[Music CD identifier]
MLLT[MPEG location lookup table]
OWNE[Ownership frame]
PRIV[Private frame]
PCNT[Play counter]
POPM[Popularimeter]
POSS[Position synchronisation frame]
RBUF[Recommended buffer size]
RVAD[Relative volume adjustment]
RVRB[Reverb]
SYLT[Synchronized lyric/text]
SYTC[Synchronized tempo codes]
TALB[Album/Movie/Show title]
TBPM[BPM (beats per minute)]
TCOM[Composer]
TCON[Content type]
TCOP[Copyright message]
TDAT[Date]
TDLY[Playlist delay]
TENC[Encoded by]
TEXT[Lyricist/Text writer]
TFLT[File type]
TIME[Time]
TIT1[Content group description]
TIT2[Title/songname/content description]
TIT3[Subtitle/Description refinement]
TKEY[Initial key]
TLAN[Language(s)]
TLEN[Length]
TMED[Media type]
TOAL[Original album/movie/show title]
TOFN[Original filename]
TOLY[Original lyricist(s)/text writer(s)]
TOPE[Original artist(s)/performer(s)]
TORY[Original release year]
TOWN[File owner/licensee]
TPE1[Lead performer(s)/Soloist(s)]
TPE2[Band/orchestra/accompaniment]
TPE3[Conductor/performer refinement]
TPE4[Interpreted, remixed, or otherwise modified by]
TPOS[Part of a set]
TPUB[Publisher]
TRCK[Track number/Position in set]
TRDA[Recording dates]
TRSN[Internet radio station name]
TRSO[Internet radio station owner]
TSIZ[Size]
TSRC[ISRC (international standard recording code)]
TSSE[Software/Hardware and settings used for
TYER[Year]
TXXX[User defined text information frame]
UFID[Unique file identifier]
USER[Terms of use]
USLT[Unsychronized lyric/text transcription]
WCOM[Commercial information]
WCOP[Copyright/Legal information]
WOAF[Official audio file webpage]
WOAR[Official artist/performer webpage]
WOAS[Official audio source webpage]
WORS[Official internet radio station homepage]
WPAY[Payment]
WPUB[Publishers official webpage]
WXXX[User defined URL link frame]
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页