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子版本号 2 03H 00H 表示是 ID3v2.3
ID3v2标志 1 abc00000B a 非同步编码 b 扩展标签头 c 测试指示为,都是 1 有效,一般都是 0
ID3v2大小 4 只有后 7 位有效,size = byteA:7 * 0x200000 + byteB:7 * 0x4000 + byteC:7 * 0x80 + byteD:7
扩展标签头 扩展标签头大小 4 size = byte0 * 0x200000 + byte1 * 0x4000 + byte2 * 0x80 + byte3
扩展标志 2 xx
补空大小 4 你可以在所有的标签帧后面添加补空数据,也可以预留空间存放额外的帧,使得整个标签大小比标签头中的大小要更大,这里记录的就是增加的大小,一般不用
标签帧 帧标识 4 固定的 4 个字符,用来标识这一帧里面存放的内容是什么,标识见下面的对照表:标签帧的标识以及其意义对照表
帧大小 4 size = 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) 内容
0 11 帧同步标识,表示数据帧一帧的开始
11 2 MPEG 音频版本号,参照表:MPEG 音频版本表
13 2 Layer 版本,参照表:Layer 索引表
15 1 保护位,0 - 16bit CRC 0 - 无 CRC
16 4 比特率索引,参照表:比特率索引表(单位-Kbps)
20 2 采样率索引,参照表:采样率索引表
22 1 如果设置的话数据被补空为一个 slot,LayerI slot 是 4 字节,其余为 1 字节
23 1 私有位
24 2 channel 模式,参照表:channel 模式表
26 2 模式扩展
28 1 Copyright 位
29 1 Original 位
30 2 强调,不关注

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

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) 内容
0 4 固定的 ‘Xing’ or ‘Info’
4 4 不关注
8 4 帧数量,大端存储
8 or 12 4 字节数,大端存储
8, 12 or 16 100 100 个时间点索引,例如一段音频长 3 分钟,分成 100 份,记录每一段的起始位置
8, 12, 16, 108, 112, 116 4 不关注

3. MP3 文件的内容排列

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

MPEG 音频版本表

index content
00 MPEG 2.5
01 reserved
10 MPEG 2
11 MPEG 1

Layer 索引表

index content
00 reserved
01 LayerIII
10 LayerII
11 LayerI

比特率索引表(单位 Kbps)

index - - - - - -
Bitrate Index MPEG 1 MPEG 2,2.5
LayerI LayerII LayerIII LayerI LayerII & LayerIII
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 (Hz) MPEG-2 (Hz) MPEG-2.5 (Hz)
00 44100 22050 11025
01 48000 24000 12000
10 32000 16000 8000
11 reserved reserved reserved

每帧数据的采样数

- MPEG 1 MPEG 2 (LSF) MPEG 2.5 (LSF)
Layer I 384 384 384
Layer II 1152 1152 1152
Layer III 1152 576 576

channel 模式表

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

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

index content
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]
发布了130 篇原创文章 · 获赞 266 · 访问量 28万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览