概述
ID3V1
mp3解码的课题断断续续做了一年多了,这是我学习c语言之后想自己写的第一个课题,如果时光倒退,冒出这个想法的第一时间,我会给自己一个嘴巴子,搞搞贪吃蛇、五子棋什么的不好,非要搞mp3解码,为了这个,这一年我都忘记自己看了多少论文了。
各种论坛上有巨量的关于这个课题的文章,其中大量的都是头部信息的,盖上个文件解码的标题,白白浪费了宝宝很多时间。凭借着一股傻乎劲,宝宝从一无所知,逐渐也揭开了mp3的面纱,但是有些细节还是没摸透。并且,宝宝成功的卡在了哈夫曼码区。
宝宝心里苦呀,凭我的智商又不能完全搞得了整个MP3的解码,不搞完它,心理又始终惦记着,不从这个坑里走出来,宝宝人大概就废了,于是宝宝含着眼泪继续再一次卷土重来,这一次一定要把这个课题给结了。
文件结构
MP3文件的结构是这个样子的:
头部 | 音频数据 | 尾部 |
---|---|---|
ID3V2 | DATA | ID3V1 |
可以不存在 | 必须的 | 可以不存在 |
这是mp3文件宏观的样子,最主要的是音频数据,但宝宝现在还动不了它,所以关于它的各种例如心理学模型,哈夫曼编解码,傅里叶变换之类的,统统先不搞,下一个阶段再收拾它。
宝宝现在就盯准头部和尾部,就是传说的ID3V1和V2。
传统的mp3要么是 头部+音频数据 要么是 音频数据+尾部
但是自从ID3V2.4之后,就变成可以这个样子:头部 + 音频数据 + 尾部
ID3
这货大约是一种在mp3文件中附加例如歌手等信息的一种标准,它不是mp3的必要部分,mp3解码也用不上它,实际上mp3文件可以仅仅只有 音频数据
ID3v1可以在音频数据后面附加128字节的信息,为了在文件中附加更多的信息,于是有了ID3V2,它的升级版,为了不破坏ID3V1的读写,它放到了头部,并且采用了变长的方式。以下是它的版本
ID3V1 | 流行度 |
---|---|
逐渐少见了 |
ID3V2 | 流行度 |
---|---|
2.1 | 几乎没 |
2.2 | 几乎没 |
2.3 | 主流 |
2.4 | 很少 |
从其他大佬的文章中可以看到ID3V2有四个版本,但是从我保存的mp3文件中,并没有找到2.1和2.2的,暂时也没有找到跟这两个版本相关的资料。
官方传送门
ID3V2.3
ID3V2.4
ID3V1
ID3V1的结构非常简单,只有128字节
offset | len | value | 说明 |
---|---|---|---|
0x0 | 3 | TAG | 段标识 |
0x3 | 30 | 歌名 | |
0x21 | 30 | 作者 | |
0x3f | 30 | 专辑名 | |
0x5d | 4 | 年份 | |
0x61 | 28 | 附注 | |
0x7d | 1 | 保留位(说明音轨有无) | |
0x7e | 1 | 音轨号 | |
0x7f | 1 | mp3类型 |
另:有资料说保留位和音轨号的两个byte属于附注,咱也不懂,咱也不敢问。
ps:看到有资料说,id3v1 有两个版本,一个是v1,一个是v1.1,1.1版本就是从附注中划出了音轨部分的两个字节
数据结构:
typedef struct id3v1
{
char Tag[3];
char Title[30];
char Artist[30];
char Album[30];
char Year[4];
char Comment[28];
unsigned char Reserved;
unsigned char TrackNum;
unsigned char GenreIndex;
}ID3V1;
ID3V1略烦人的地方就是GenreIndex,它定义了140多种音乐类型,据说原来有差不多100种,然后Winamp扩充到125种,算上其他的,总共有140多种,要想知道这个值里的对应啥类型,还得建个表
#define GENRE_INDEX_MAX
148
char *Genre[GENRE_INDEX_MAX]=
{
"Blues","ClassicRock","Country","Dance","Disco","Funk","Grunge","Hip-Hop",
"Jazz","Metal","NewAge","Oldies","Other","Pop","R&B","Rap",
"Reggae","Rock","Techno","Industrial","Alternative","Ska","Deathl","Pranks",
"Soundtrack","Euro-Techno","Ambient","Trip-Hop","Vocal","Jazz+Funk","Fusion","Trance",
"Classical","Instrumental","Acid","House","Game","SoundClip","Gospel","Noise",
"AlternRock","Bass","Soul","Punk","Space","Meditative","InstrumentalPop","InstrumentalRock",
"Ethnic","Gothic","Darkwave","Techno-Industrial","Electronic","Pop-Folk","Eurodance","Dream",
"SouthernRock","Comedy","Cult","Gangsta","Top40","ChristianRap","Pop/Funk","Jungle",
"NativeAmerican","Cabaret","NewWave","Psychadelic","Rave","Showtunes","Trailer","Lo-Fi",
"Tribal","AcidPunk","AcidJazz","Polka","Retro","Musical","Rock&Roll","HardRock",
//Winamp扩充
"Folk","Folk-Rock","NationalFolk","Swing","FastFusion","Bebob","Latin","Revival",
"Celtic","Bluegrass","Avantgarde","GothicRock","ProgessiveRock","PsychedelicRock","SymphonicRock","SlowRock",
"BigBand","Chorus","EasyListening","Acoustic","Humour","Speech","Chanson","Opera",
"ChamberMusic","Sonata","Symphony","BootyBass","Primus","PornGroove","Satire","SlowJam",
"Club","Tango","Samba","Folklore","Ballad","PowerBallad","RhythmicSoul","Freestyle",
"Duet","PunkRock","DrumSolo","Acapella","Euro-House","DanceHall",
//其他扩充
"Goa","Drum&Bass","Club-House","Hardcore","Terror","Indie","BritPop","Negerpunk",
"PolskPunk","Beat","ChristianGangstaRap","Heavyl","Blackl","Crossover","ContemporaryChristian","ChristianRock",
"Merengue","Salsa","Trashl","Anime","JPop","Synthpop"
};
完整的测试
#include <stdio.h>
#define GENRE_INDEX_MAX
148
typedef struct id3v1
{
char Tag[3];
char Title[30];
char Artist[30];
char Album[30];
char Year[4];
char Comment[28];
unsigned char Reserved;
unsigned char TrackNum;
unsigned char GenreIndex;
}ID3V1;
char *Genre[GENRE_INDEX_MAX]=
{
"Blues","ClassicRock","Country","Dance","Disco","Funk","Grunge","Hip-Hop",
"Jazz","Metal","NewAge","Oldies","Other","Pop","R&B","Rap",
"Reggae","Rock","Techno","Industrial","Alternative","Ska","Deathl","Pranks",
"Soundtrack","Euro-Techno","Ambient","Trip-Hop","Vocal","Jazz+Funk","Fusion","Trance",
"Classical","Instrumental","Acid","House","Game","SoundClip","Gospel","Noise",
"AlternRock","Bass","Soul","Punk","Space","Meditative","InstrumentalPop","InstrumentalRock",
"Ethnic","Gothic","Darkwave","Techno-Industrial","Electronic","Pop-Folk","Eurodance","Dream",
"SouthernRock","Comedy","Cult","Gangsta","Top40","ChristianRap","Pop/Funk","Jungle",
"NativeAmerican","Cabaret","NewWave","Psychadelic","Rave","Showtunes","Trailer","Lo-Fi",
"Tribal","AcidPunk","AcidJazz","Polka","Retro","Musical","Rock&Roll","HardRock",
//Winamp扩充
"Folk","Folk-Rock","NationalFolk","Swing","FastFusion","Bebob","Latin","Revival",
"Celtic","Bluegrass","Avantgarde","GothicRock","ProgessiveRock","PsychedelicRock","SymphonicRock","SlowRock",
"BigBand","Chorus","EasyListening","Acoustic","Humour","Speech","Chanson","Opera",
"ChamberMusic","Sonata","Symphony","BootyBass","Primus","PornGroove","Satire","SlowJam",
"Club","Tango","Samba","Folklore","Ballad","PowerBallad","RhythmicSoul","Freestyle",
"Duet","PunkRock","DrumSolo","Acapella","Euro-House","DanceHall",
//其他扩充
"Goa","Drum&Bass","Club-House","Hardcore","Terror","Indie","BritPop","Negerpunk",
"PolskPunk","Beat","ChristianGangstaRap","Heavyl","Blackl","Crossover","ContemporaryChristian","ChristianRock",
"Merengue","Salsa","Trashl","Anime","JPop","Synthpop"
};
int main()
{
ID3V1 id3;
FILE *fp;
fp = fopen("ID3V1.mp3","rb");
if(fp == NULL)return -1;
fseek(fp,-128,SEEK_END);
fread((void*)&id3,1,128,fp);
printf("----------------ID3V1Info----------------n");
if(strcmp(id3.Tag,"TAG") != 0)
{
printf("not exist ID3V1");
return -1;
}
else
{
printf("Tag:tt%.3sn",id3.Tag);
printf("Title:tt%.30sn",id3.Title);
printf("Artist:tt%.30sn",id3.Artist);
printf("Album:tt%.30sn",id3.Album);
printf("Year:tt%.4sn",id3.Year);
printf("Comment:t%.28sn",id3.Comment);
printf("Reserved:t%xn",id3.Reserved);
printf("TrackNum:t%xn",id3.TrackNum);
printf("Genre:tt%sn",id3.GenreIndex < GENRE_INDEX_MAX ? Genre[id3.GenreIndex]:"null");
}
printf("----------------------------------------nn");
fclose(fp);
return 0;
}
关于ID3更多的信息
最后
以上就是贪玩流沙为你收集整理的MP3文件头部信息解码- ID3V1的全部内容,希望文章能够帮你解决MP3文件头部信息解码- ID3V1所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复