有一个朋友喜欢听MP3,为了获取MP3,写了一个程序,专门从一家音乐网站上搜索下载mp3,一下子下载了有上千首。这时朋友又犯愁了,这些MP3的歌曲名字都是使用1,2,3,4,。。等数字命名,挑选起来十分不方便。虽然MP3播放器能够读出MP3文件信息的歌曲名,但歌曲文件本身的名字却不利于自己管理。于是就想写一个小程序实现MP3自动更名。查了一些资料,研究了一下MP3的文件结构。

研究MP3的结构,就不能不研究ID3标签。ID3标签是MP3音乐档案中的歌曲附加讯息,它能够在MP3中附加曲子的演出者、作者以及其它类别资讯,方便众多乐曲的管理。缺少ID3标签并不会影响 MP3的播放,但若没有的话,管理音乐文件也会相当的麻烦。如果你在网上download MP3,里面多半已经写有预设的ID3讯息。ID3,一般是位于一个mp3文件的开头或末尾的若干字节内,附加了关于该mp3的歌手,标题,专辑名称,年代,风格等信息,该信息就被称为ID3信息,ID3信息分为两个版本,v1和v2版。

其中:v1版的ID3在mp3文件的末尾128字节,以TAG三个字符开头,后面跟上歌曲信息。

v2版一般位于mp3的开头,可以存储歌词,该专辑的图片等大容量的信息。

但ID3并不是MP3标签的ISO国际标准,ID3的各种版本目前只是一个近乎事实上的标准,并没有人强迫播放器或者编码程序必须支持它。

ID3V1大概有两个版本,由于ID3V1.0没有包括曲目序号的定义,所以Michael Mutschler在1997年进行了改进,引入了版本1.1。通过占用备注字段的最后两个字节,用一个00字节作标记,另一个字节改为序号,可以让ID3支持曲目编号了。一个字节的空间让ID3 V1.1支持最高到255的曲目序号,考虑到一张唱片超过256个曲目的可能性极小,这个改进还是相当合理的。但ID3V1只有128个字节可以使用,如果要在MP3中储存更多的信息,比如歌词,专辑图片等,显然是无法达到的,于是产生了ID3V2。ID3V2到现在一共有4个版本,但流行的播放软件一般只支持第3版,既ID3v2.3。由于ID3V1记录在MP3文件的末尾,ID3V2就只好记录在MP3文件的首部了。也正是由于这个原因,对ID3V2的操作比ID3V1要慢。而且ID3V2结构比ID3V1的结构要复杂得多,但比前者全面且可以伸缩和扩展。

但我们只需要读出MP3的TITLE,所以只要解析IDV1就够了,这里不对IDV2做过多说明,其实我也没有深入研究IDV2。

ID3V1的内容和每个标签占用的字节说明如下:

char Header[3];    /*标签头必须是"TAG"否则认为没有标签*/
char Title[30];    /*标题*/
char Artist[30];   /*作者*/
char Album[30];    /*专集*/
char Year[4];    /*出品年代*/
char Comment[30];   /*备注*/
char Genre;    /*类型*/

可以定义一个如下的结构来存储MP3信息:

typedef struct _MP3INFO //MP3信息的结构
{
 char Identify[3]; //TAG三个字母
 //这里可以用来鉴别是不是文件信息内容
 char Title[31];   //歌曲名,30个字节
 char Artist[31];  //歌手名,30个字节
 char Album[31];   //所属唱片,30个字节
 char Year[5];   //年,4个字节
 char Comment[29]; //注释,28个字节
 unsigned char reserved;  //保留位,1个字节
 unsigned char reserved2; //保留位,1个字节
 unsigned char reserved3; //保留位,1个字节
} MP3INFO;
代码可以简单如下:

#include "stdlib.h"
#include "stdio.h"
#include "windows.h"
#define MAX 128

typedef struct _MP3INFO //MP3信息的结构
{
 char Identify[3]; //TAG三个字母
 //这里可以用来鉴别是不是文件信息内容
 char Title[31];   //歌曲名,30个字节
 char Artist[31];  //歌手名,30个字节
 char Album[31];   //所属唱片,30个字节
 char Year[5];   //年,4个字节
 char Comment[29]; //注释,28个字节
 unsigned char reserved;  //保留位,1个字节
 unsigned char reserved2; //保留位,1个字节
 unsigned char reserved3; //保留位,1个字节
} MP3INFO;

int main(int argc, char* argv[])
{
 FILE * fp;
 unsigned char mp3tag[128] = {0};
    MP3INFO mp3info;
 char oldname[MAX],newname[MAX],cmd[MAX];

fp = fopen("G://mp3//Debug//5.mp3","rb");
 if (NULL==fp)
 {
  printf("open read file error!!");
  return 1;
 }
 fseek(fp,-128,SEEK_END);
 fread(&mp3tag,1,128,fp);
    if(!((mp3tag[0] == 'T'|| mp3tag[0] == 't')
  &&(mp3tag[1] == 'A'|| mp3tag[1] == 'a')
  &&(mp3tag[2] == 'G'|| mp3tag[0] == 'g')))
 {
     printf("mp3 file is error!!");
  fclose(fp) ;
  return 1;
 }

memcpy((void *)mp3info.Identify,mp3tag,3); //获得tag
 memcpy((void *)mp3info.Title,mp3tag+3,30); //获得歌名
 memcpy((void *)mp3info.Artist,mp3tag+33,30); //获得作者
 memcpy((void *)mp3info.Album,mp3tag+63,30); //获得唱片名
 memcpy((void *)mp3info.Year,mp3tag+93,4); //获得年
 memcpy((void *)mp3info.Comment,mp3tag+97,28); //获得注释
 memcpy((void *)&mp3info.reserved,mp3tag+125,1); //获得保留
 memcpy((void *)&mp3info.reserved2,mp3tag+126,1);
 memcpy((void *)&mp3info.reserved3,mp3tag+127,1);
 fclose(fp);
 if (strlen(mp3info.Title) == 0)
 {
  printf("title is null/n");
  return 1;
 }
    strcpy(oldname,"5.mp3");
 sprintf(newname,"%s.mp3",mp3info.Title);
 sprintf(cmd,"rename G://mp3//Debug//%s %s",oldname,newname);
 printf("%s/n", cmd);
 system(cmd);

return 0;
}

http://blog.csdn.net/yanjiaye520/article/details/6054579

MP3文件的结构与编程的更多相关文章

  1. 【转】MP3文件原理及结构解析

    1.引言文件压缩技术的日新月异使得MP3成为时下最烫手的音乐格式,优质的音乐随着0与1的排列迅速散布 到世界各地,撼动人心.何谓MP3?MP3的全称是MPEG Audio Layer 3,它是一种高效 ...

  2. C# 获取 mp3文件信息

    C# 获取 mp3文件信息[包括:文件大小.歌曲长度.歌手.专辑] 第一种方式:[代码已验证] // http://bbs.csdn.net/topics/390392612   string fil ...

  3. 浅谈如何使用代码为MP3文件写入ID3Tags

    作者:郑童宇 GitHub:https://github.com/CrazyZty 1.前言 做了三年左右的Android开发,一直没写过博客,最近正好打算换工作,算是闲一些,就将以前开发所遇到的一些 ...

  4. PE文件常用结构体

    Dos头结构: typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_c ...

  5. C# 获取 mp3文件信息【包括:文件大小、歌曲长度、歌手、专辑】

    C# 获取 mp3文件信息[包括:文件大小.歌曲长度.歌手.专辑] 第一种方式:[代码已验证] // http://bbs.csdn.net/topics/390392612   string fil ...

  6. C#读取MP3文件的专辑图片和ID3V2Tag信息(带代码)

    第二次更新,后面的代码有问题,有些专辑图片读取不到.发现是PNG图片的问题.在读取的过程中调试发现,图片帧前10个字节包含了图片的格式,在有些歌曲写着JPEG的格式,数据却是PNG的.先说下思路. j ...

  7. vc中播放mp3文件的方法小结

    一般播放MP3常见的有两种方法,一种是自己解码,另外一种用系统的库,比如MCI,当然如果可以用控件直接用个控件会更方便. 1.      使用mci #include <windows.h> ...

  8. MP3文件信息修改

    MP3文件信息 参考链接:https://www.jianshu.com/p/e368517ec7b9 总结: ID3V1在MP3文件后面;ID3V2在MP3文件前面;现在有些文件是V1的,有些文件是 ...

  9. MP3文件信息批量更改器

    以前(估计是2003年)编写一个MP3文件信息批量更改器MP3TagChanger,现放上来参考.(VB6编码) 使用方法很简单,会Winamp或者千千静听的就懂使用. http://pan.baid ...

随机推荐

  1. urlrewrite 匹配规则之优先选择

    urlrewrite rule可以使用java的正则表达式匹配规则,但是这里存在一个问题点,假如有一个通配的规则和一个精确匹配的规则,urlrewrite 会选择那个去匹配呢? 如下两种规则: < ...

  2. surfaceView画图

    1.视图 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:too ...

  3. ACM 做题过程中的一些小技巧。

    ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...

  4. linux下利用sed重命名文件

    3 for file in `ls ./*.*`  4 do  5 mv $file `echo $file|sed 's/IM_21R_ID331/1M21R_ID331/g'`  6 done  ...

  5. 分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小

    原文:分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小 /** * Reallocates an array with a new size, and copies the co ...

  6. Java网络编程:利用Java mail包发送电子邮件

    下面代码是利用Java mail包封装了一个发送邮件的类 import java.io.File; import java.util.ArrayList; import java.util.Date; ...

  7. Away3D带你360°漫游全景影像

    1代码展示 package { import away3d.containers.View3D; import away3d.controllers.HoverController; import a ...

  8. 关于js基础easy忘记的那些事儿

    1.Number() 通过这个函数转化后的值仅仅有两个:数值和NaN,通过parseInt也能转化为数值.可是像"134df"转化后的值为134,而Number("134 ...

  9. iPhone应用程序开发基础之一: IBOutlet与IBAction

    在图形界面编程时,解决的第一问题就是如何将静态界面与代码关联起来,或者说是代码如何与界面上的对象 通信, 代码如何操作界面上的对象.在iPhone平台上,引入了IBOutlet与IBAction.通过 ...

  10. Cookie 路径在本机测试及服务器部署,在浏览器处理方式上的不同

    Table of Contents 1 问题场景 2 解决过程 2.1 cookie是否设置成功 2.2 cookie是否上传到服务器 3 总结 1 问题场景 最近在学用Python进行web开发,写 ...