视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
[MP3学习]MP3标签信息之ID3v1,IDv2
2020-11-09 08:33:12 责编:小采
文档

近来本着踏实努力一点一滴的原则,研究了下MP3,准备做一个了类于AIRPLAY的播放器,这是学习的第一篇,读取信息,做一个笔记。 参考资料:http://www.id3.org/ID3v1 http://en.wikipedia.org/wiki/ID3 ====================================================

近来本着踏实努力一点一滴的原则,研究了下MP3,准备做一个了类似于AIRPLAY的播放器,这是学习的第一篇,读取信息,做一个笔记。

参考资料:http://www.id3.org/ID3v1 http://en.wikipedia.org/wiki/ID3

========================================================================

MP3歌曲信息(ID3v1)结构如下:


所以需要一个结构体存储MP3的歌曲信息,一般声明如下:

struct MP3INFO	//MP3的信息结构,固定的,存放在歌曲最后128个字节中
{ 
 char identify[3]; // TAG
 char Title[30]; // 歌曲名,30个字节 
 char Artist[30]; // 歌手名,30个字节 
 char Album[30]; // 所属唱片,30个字节 
 char Year[4]; // 年份,4个字符 
 char Comment[30]; // 注释,28个字节,有些说是30个,但都没啥关系,只是保留位的大小要改改 
 char reserved[1];	//保留,暂无用
};

知道了这些就很容易了,不敢用什么办法,只要读取到最后的128个字节,所有的相关信息就可以得到了,用VC6.0控制台程序测试如下(主代码):

#include "stdafx.h"


struct MP3INFO	//MP3的信息结构,固定的,存放在歌曲最后128个字节中
{ 
 char identify[3]; // TAG
 char Title[30]; // 歌曲名,30个字节 
 char Artist[30]; // 歌手名,30个字节 
 char Album[30]; // 所属唱片,30个字节 
 char Year[4]; // 年份,4个字符 
 char Comment[30]; // 注释,28个字节,有些说是30个,但都没啥关系,只是保留位的大小要改改 
 char reserved[1];	//保留,暂无用
};


int main(int argc, char* argv[])
{
	printf("读取一个MP3的信息,每个MP3的最后128个字节存储的,它有固定的结构,下面试读取之!\n");
	MP3INFO mp3;

	FILE *pf = fopen("H:/1.mp3","r");
	printf("打开文件:%d\n",pf);

	fseek(pf,-128,SEEK_END);
	fread(&mp3,sizeof(mp3),1,pf);

	printf("TAG标志:%s\n",mp3.identify);
	printf("曲名:%s\n",mp3.Title);
	printf("歌手:%s\n",mp3.Artist);
	printf("唱片:%s\n",mp3.Album);
	printf("年份:%s\n",mp3.Year);
	printf("注释:%s\n",mp3.Comment);

	fclose(pf);

	return 0;
}

效果如下:



读取的任务完成了。对于修改,知道了这些再做完善也很容易:(如下)

memset(&mp3,0,sizeof(mp3));
	printf("修改信息:\n");
	mp3.Identify[0]='T';
	mp3.Identify[1]='A';
	mp3.Identify[2]='G';
	
	mp3.Flag='0';
	mp3.Track='5';
	mp3.Style='3';
	
	lstrcpy(mp3.Title,(LPCTSTR)"修改的名字");
	lstrcpy(mp3.Artist,(LPCTSTR)"修改的作者");
	lstrcpy(mp3.Album,(LPCTSTR)"修改的唱片");
	lstrcpy(mp3.Year,(LPCTSTR)"19");
	lstrcpy(mp3.Comment,(LPCTSTR)"修改的注释");
	
	fseek(pf,-128,SEEK_END);
	fwrite(&mp3,sizeof(mp3),1,pf);

修改完成后,在UltraEdit中查看(16进制),信息格式完全正确。但是,用Windows自带的属性查看发现,其上面的内容不全是我们修改的,这是为什么呢?

经多方查找 http://en.wikipedia.org/wiki/ID3,http://baike.baidu.com/view/66078.html

/*
 * ID3v1是固定的128个字节,这个你不用担心。其实ID3v1是这样安排的:如果MP3的注释是大于28个字节的,那么就要借用126-127两个字节。
 * 所以ID3v1的注释部分可能是28个字节也可能是30个字节。那么,怎么区分到底是28个字节还是30个字节呢?很简单,126处就是管这个的,
 * 我们只要看看126处是不是0x00,如果是0x00那么注释就有28个字节。如果不等于0x00,那么就是说注释是30个字节。同时别忘了,
 * 由于第127字节存储了Track信息,那么如果注释是30个字节的时候,这首歌的ID3v1里的那个127处的信息自然就不是Track信息了。
 * Track自然就是没有地方存了,所以127处变的没有Track意义了,它只是Comment的一部分了。
 */
struct ID3v1	//MP3的信息结构,固定的,存放在歌曲最后128个字节中
{ 
 char Identify[3]; // ID3v1为TAG
 char Title[30]; // 歌曲名,30个字节 
 char Artist[30]; // 歌手名,30个字节 
 char Album[30]; // 所属唱片,30个字节 
 char Year[4]; // 年份,4个字符 
 char Comment[28]; // 注释,28个字节,有时是30个, 
 char Flag;	// 标志,为0说明有音轨(下一位),不一定有
	char	 Track;	// 音轨,#,歌曲号,不一定有
char	 Style;	// 风格流派,需要查询,不一定有
};

所以对读写取程序做些修改:
void ReadID3v1(char* pfile)
{
	printf("读取一个MP3的信息,每个MP3的最后128个字节存储的,它有固定的结构,下面试读取之!\n");
	ID3v1 mp3;
	
	FILE *pf = fopen(pfile,"r+");
	printf("打开文件:%d\n",pf);
	
	fseek(pf,-128,SEEK_END);
	fread(&mp3,sizeof(mp3),1,pf);
	if (mp3.Identify[0]!='T' || mp3.Identify[1]!='A' || mp3.Identify[2]!='G' )
	{
	printf("此歌曲不支持ID3v2标准!\n");
	fclose(pf);
	
	return;
	}
	printf("TAG标志:%.3s\n",mp3.Identify);
	printf("曲名:%.30s\n",mp3.Title);
	printf("歌手:%.30s\n",mp3.Artist);
	printf("唱片:%.30s\n",mp3.Album);
	printf("年份:%.4s\n",mp3.Year);
	printf("注释:%.30s\n",mp3.Comment);
	if (mp3.Flag==0)
	{
	printf("歌曲序号:%d,流派标志:%d\n",mp3.Track,mp3.Style);
	}
	
	getchar();

	//下面试着修改信息
	memset(&mp3,0,sizeof(mp3));
	printf("修改信息:\n");
	mp3.Identify[0]='T';
	mp3.Identify[1]='A';
	mp3.Identify[2]='G';
	
	mp3.Flag='0';
	mp3.Track='5';
	mp3.Style='3';
	
	lstrcpy(mp3.Title,(LPCTSTR)"修改的名字");
	lstrcpy(mp3.Artist,(LPCTSTR)"修改的作者");
	lstrcpy(mp3.Album,(LPCTSTR)"修改的唱片");
	lstrcpy(mp3.Year,(LPCTSTR)"19");
	lstrcpy(mp3.Comment,(LPCTSTR)"修改的注释");
	
	fseek(pf,-128,SEEK_END);
	fwrite(&mp3,sizeof(mp3),1,pf);
	printf("over,%s\n",mp3.Title);
	
	fclose(pf);
}

http://blog.csdn.net/bbdxf/article/details/7438006

下载本文
显示全文
专题