MP3文件头部信息解码- ID3V1

ID3V1

mp3解码的课题断断续续做了一年多了,这是我学习c语言之后想自己写的第一个课题,如果时光倒退,冒出这个想法的第一时间,我会给自己一个嘴巴子,搞搞贪吃蛇、五子棋什么的不好,非要搞mp3解码,为了这个,这一年我都忘记自己看了多少论文了。

各种论坛上有巨量的关于这个课题的文章,其中大量的都是头部信息的,盖上个文件解码的标题,白白浪费了宝宝很多时间。凭借着一股傻乎劲,宝宝从一无所知,逐渐也揭开了mp3的面纱,但是有些细节还是没摸透。并且,宝宝成功的卡在了哈夫曼码区。

宝宝心里苦呀,凭我的智商又不能完全搞得了整个MP3的解码,不搞完它,心理又始终惦记着,不从这个坑里走出来,宝宝人大概就废了,于是宝宝含着眼泪继续再一次卷土重来,这一次一定要把这个课题给结了。

文件结构

MP3文件的结构是这个样子的:

头部音频数据尾部
ID3V2DATAID3V1
可以不存在必须的可以不存在

这是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字节

offsetlenvalue说明
0x03TAG段标识
0x330歌名
0x2130作者
0x3f30专辑名
0x5d4年份
0x6128附注
0x7d1保留位(说明音轨有无)
0x7e1音轨号
0x7f1mp3类型

另:有资料说保留位和音轨号的两个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:\t\t%.3s\n",id3.Tag);
			printf("Title:\t\t%.30s\n",id3.Title);
			printf("Artist:\t\t%.30s\n",id3.Artist);
			printf("Album:\t\t%.30s\n",id3.Album);
			printf("Year:\t\t%.4s\n",id3.Year);
			printf("Comment:\t%.28s\n",id3.Comment);
			printf("Reserved:\t%x\n",id3.Reserved);
			printf("TrackNum:\t%x\n",id3.TrackNum);
			printf("Genre:\t\t%s\n",id3.GenreIndex < GENRE_INDEX_MAX ? Genre[id3.GenreIndex]:"null");
	}
	
	printf("----------------------------------------\n\n");
	
	fclose(fp);
	return 0;
}

关于ID3更多的信息

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值