当前位置:Gxlcms > mysql > [MP3学习]MP3标签信息之ID3v1,IDv2

[MP3学习]MP3标签信息之ID3v1,IDv2

时间:2021-07-01 10:21:17 帮助过:55人阅读

近来本着踏实努力一点一滴的原则,研究了下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的歌曲信息,一般声明如下:

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

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

  1. #include "stdafx.h"
  2. struct MP3INFO
  3. //MP3的信息结构,固定的,存放在歌曲最后128个字节中
  4. {
  5. char identify[3]; // TAG
  6. char Title[30]; // 歌曲名,30个字节
  7. char Artist[30]; // 歌手名,30个字节
  8. char Album[30]; // 所属唱片,30个字节
  9. char Year[4]; // 年份,4个字符
  10. char Comment[30]; // 注释,28个字节,有些说是30个,但都没啥关系,只是保留位的大小要改改
  11. char reserved[1];
  12. //保留,暂无用
  13. };
  14. int main(int argc, char* argv[])
  15. {
  16. printf("读取一个MP3的信息,每个MP3的最后128个字节存储的,它有固定的结构,下面试读取之!\n");
  17. MP3INFO mp3;
  18. FILE *pf = fopen("H:/1.mp3","r");
  19. printf("打开文件:%d\n",pf);
  20. fseek(pf,-128,SEEK_END);
  21. fread(&mp3,sizeof(mp3),1,pf);
  22. printf("TAG标志:%s\n",mp3.identify);
  23. printf("曲名:%s\n",mp3.Title);
  24. printf("歌手:%s\n",mp3.Artist);
  25. printf("唱片:%s\n",mp3.Album);
  26. printf("年份:%s\n",mp3.Year);
  27. printf("注释:%s\n",mp3.Comment);
  28. fclose(pf);
  29. return 0;
  30. }

效果如下:



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

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

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

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

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

所以对读写取程序做些修改:
  1. void ReadID3v1(char* pfile)
  2. {
  3. printf("读取一个MP3的信息,每个MP3的最后128个字节存储的,它有固定的结构,下面试读取之!\n");
  4. ID3v1 mp3;
  5. FILE *pf = fopen(pfile,"r+");
  6. printf("打开文件:%d\n",pf);
  7. fseek(pf,-128,SEEK_END);
  8. fread(&mp3,sizeof(mp3),1,pf);
  9. if (mp3.Identify[0]!='T' || mp3.Identify[1]!='A' || mp3.Identify[2]!='G' )
  10. {
  11. printf("此歌曲不支持ID3v2标准!\n");
  12. fclose(pf);
  13. return;
  14. }
  15. printf("TAG标志:%.3s\n",mp3.Identify);
  16. printf("曲名:%.30s\n",mp3.Title);
  17. printf("歌手:%.30s\n",mp3.Artist);
  18. printf("唱片:%.30s\n",mp3.Album);
  19. printf("年份:%.4s\n",mp3.Year);
  20. printf("注释:%.30s\n",mp3.Comment);
  21. if (mp3.Flag==0)
  22. {
  23. printf("歌曲序号:%d,流派标志:%d\n",mp3.Track,mp3.Style);
  24. }
  25. getchar();
  26. //下面试着修改信息
  27. memset(&mp3,0,sizeof(mp3));
  28. printf("修改信息:\n");
  29. mp3.Identify[0]='T';
  30. mp3.Identify[1]='A';
  31. mp3.Identify[2]='G';
  32. mp3.Flag='0';
  33. mp3.Track='5';
  34. mp3.Style='3';
  35. lstrcpy(mp3.Title,(LPCTSTR)"修改的名字");
  36. lstrcpy(mp3.Artist,(LPCTSTR)"修改的作者");
  37. lstrcpy(mp3.Album,(LPCTSTR)"修改的唱片");
  38. lstrcpy(mp3.Year,(LPCTSTR)"1989");
  39. lstrcpy(mp3.Comment,(LPCTSTR)"修改的注释");
  40. fseek(pf,-128,SEEK_END);
  41. fwrite(&mp3,sizeof(mp3),1,pf);
  42. printf("over,%s\n",mp3.Title);
  43. fclose(pf);
  44. }

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

人气教程排行