说明:可以使用UltraEdit来查看MP3文件的字节数据。
部分参考源于网络,仅交流和学习。
1.MP3数据格式:
MP3是由数据帧组成,一般分成三部分:ID3V2部分,Frame数据帧部分,ID3V1部分,三部分依次在头部,中部,尾部。
1.1 ID3V2部分,在文件开始位置,包含作者信息等,这部分长度不固定,是ID3V1的扩展。
1.2 Frame数据帧部分,包含帧头和帧数据,帧头中一般包含mp3的位率、采样率等信息。
1.3 ID3V1部分,是mp3文件的末尾128个字节,包含基本的作者专辑等信息。
1.1.1 每个ID3V2由一个标签头和若干个标签帧组成。
a. 标签头:typedef struct _MP3INFO //MP3信息的结构
{
char Header[3]; //ID3的标签
char Ver; //版本号,具体是ID3V2.X
char Revision; //副版本号
char Flag; //存放字节标识
char Size[4]; //标签的大小,由此计算的所有后面标签帧的大小,若要获取首帧数据,则还需要便宜它+10个字节的偏移
}MP3Head;
计算标签的大小:int size = (Size[0]&0x7F)*0x200000+ (Size[1]&0x7F)*0x400 +(Size[2]&0x7F)*0x80 +(Size[3]&0x7F)
b. 标签帧:每个标签帧由一个10字节帧头和至少一个字节不固定长度内容组成。因为没有用到,所以没有具体分析。
1.2.1 每个音频数据帧由一个帧头(4字节),需要根据帧头的第16位确定紧跟帧头后是否有无校验位,然后就是帧数据。
a. 帧头的格式:
typedef structMP3FrameHeader {
unsigned int sync: 11; //同步信息
unsigned int version: 2; //版本
unsigned int layer: 2; //层
unsigned int protection: 1; // CRC校验
unsigned int bitrate_index: 4; //位率
unsigned int sampling_frequency: 2; //采样频率
unsigned int padding: 1; //帧长调节
unsigned int privateword: 1; //保留字
unsigned int mode: 2; //声道模式
unsigned int extension: 2; //扩充模式
unsigned int copyright: 1; // 版权
unsigned int original: 1; //原版标志
unsigned intemphasis: 2; //强调模式
}MP3FRAMEHEADER,*LPMP3HEADER;
这个帧结构中,按位来确定相关的信息,我这边以获取第一帧位率为例,比如我要知道bitrate_index的值,只需要找到对应的4个位上的值。
首先,以字节方式读取音频文件,判断前面三个字节是否为“0x49,0x44,0x33”即为“ID3”的标识,说明改文件中存在ID3_V2部分,则开始读取sizeof(MP3Head)字节到指定的结构体中,比如MP3Head m_head,然后根据m_head中的Size[4]数组,由公式计算出后面整个标签的大小size,然后定位seek指针从文件开始位置偏移size+10,然后读取第一帧数据的帧头,根据帧头中的版本号、层数、位率值来对照获得具体的比特率。
具体过程:
二进制打开音频文件-----判断标签头----------读取标签头,获取标签帧大小-------按偏移量取得第一帧数据的起始位置--------获得版本号、层数、位率值----------索引获得比特率。
b. 关于数据帧:数据帧的长度由位率来决定,其中关于分类,帧位率相等的CBR编码方式,每个帧的长度大小都相等。帧位率不同的就是VBR编码方式,VBR头中会出现字符“Xing”
或者另一种“VBRI”.
1.3.1 ID3V1部分可以用来获取基本的MP3音频信息,位于音频文件的最后128字节。
typedefstruct tagID3V1
{
charHeader[3]; /*标签头必须是"TAG"否则认为没有标签*/
charTitle[30]; /*标题*/
charArtist[30]; /*作者*/
charAlbum[30]; /*专集*/
charYear[4]; /*出品年代*/
charComment[28]; /*备注*/
charreserve; /*保留*/
chartrack; /*音轨*/
charGenre; /*类型*/
}ID3V1, *pID3V1;
2.WAV数据格式:
相对于MP3的数据格式,WAV的格式相对简单。由数据头和数据帧组成。需要获取音频的信息时,可以通过读取wav帧头的形式来获得。