有一个朋友喜欢听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. java实现从实体到SQL语句的转换(二)

    前面写过一篇生成insert语句的博客,今天把CRUD的都完善了一下,需要的上次写的获取实体信息的类,这里就不贴出来了[点击打开查看] 下面是完整的代码: package tan.code.utils ...

  2. ASP.NET过滤器的应用

    在J2EE Web开发中有过滤器filter,该filter可以对指定的URL访问进行拦截,并执行过滤器的方法,根据实际应用情况,在过滤器中修改请求的代码.判断会话信息,也可以做权限控制,总之这个过滤 ...

  3. jfinal集成spring cxf做webservice服务

    链接地址:http://zhengshuo.iteye.com/blog/2154047 废话不说,直接上代码 新增cxf的plugin CXFPlugin package com.jfinal.pl ...

  4. android sdk国内快速更新下载

    Android SDK在线更新镜像服务器 http://www.androiddevtools.cn/ 目前正在使用的是:包含详细的配图流程 http://android-mirror.bugly.q ...

  5. C# -- 什么是方法签名?

    签名指的是返回值和参数. 比如 : public void A ( int p1,int p2){} public void B ( int q1,int q2){} 的签名相同. 而 public ...

  6. javascript每日一练(一)——javascript基础

    一.javascript的组成 ECMAScript DOM BOM 二.变量类型 常见类型有:number, string, boolean, undefined, object, function ...

  7. Charles_N:HTTP请求响应监听工具

    Charles:HTTP请求响应监听工具使用说明.doc   1.    介绍 Charles是一个HTTP代理服务器,HTTP监视器,反转代理服务器.它允许一个开发者查看所有连接互联网的HTTP通信 ...

  8. Properties文件及与之相关的System.getProperties操作(转)

    如何使用Java读写系统属性? 读: 简述properties文件的结构和基本用法结构:扩展名为properties的文件,内容为key.value的映射,例如"a=2" 示例用到 ...

  9. 解决外网与内网或内网之间的通信,NAT穿透

    在网络编码中会发现程序在局域网中是可以适用的,但是在外网与内网之间和内网与内网之间就不可行.问题就在于NAT.首先介绍下NAT. NAT的作用NAT(Network Address Translato ...

  10. 将某个MySQL库中的UTF8字符列都转成GBK格式

    DELIMITER $$ DROP PROCEDURE IF EXISTS `dba`.`Proc_ChangeCharacter2GBK`$$ CREATE DEFINER=`root`@`%` P ...