MP3文件格式全解
来源:互联网 发布:装饰公司的网络销售 编辑:程序博客网 时间:2024/04/26 21:24
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 的结构图表
/* 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 个字节,它们的含义如下所示
有效数据帧帧头
结构体可定义为如下所示:
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 头在上面有效数据帧帧头之后偏移 32 字节的位置,数据格式如下
VBR 头
3. MP3 文件的内容排列
ID3v2 如果有的话补空 如果有 ID3V2VBR帧(有效数据帧第一帧) 如果是 VBR 编码的话有效数据帧 一定有ID3v1 一定有(大多数地方写的),我看到的就没有
MPEG 音频版本表
Layer 索引表
比特率索引表(单位 Kbps)
采样率索引表
每帧数据的采样数
channel 模式表
标签帧的标识以及其意义对照表
- MP3文件格式全解
- MP3文件格式
- MP3文件格式
- mp3文件格式
- MP3文件格式
- MP3 文件格式
- MP3文件格式
- MP3文件格式
- mp3文件格式
- MP3文件格式
- MP3 文件格式
- MP3文件格式
- MP3文件格式
- mp3 文件格式
- MP3文件格式
- mp3文件格式
- MP3文件格式
- MP3文件格式
- android developer tiny share-20160811
- Redis和Memcache的区别进阶篇
- Android-Dalvik指令集
- css 样式设置
- OPMOCK测试框架
- MP3文件格式全解
- Android仿美团切换城市
- SDUTACM 数据结构实验之二叉树六:哈夫曼编码
- OJ2129树结构练习——判断给定森林中有多少棵树(并查集)
- 《Python编程》笔记(六)
- Android一个完整的项目转成SDK提供给第三方嵌入
- hibernate中一对一映射配置详细解析(一)
- 提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)
- JS 匿名函数01