MP3文件的结构与编程
有一个朋友喜欢听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文件的结构与编程的更多相关文章
- 【转】MP3文件原理及结构解析
1.引言文件压缩技术的日新月异使得MP3成为时下最烫手的音乐格式,优质的音乐随着0与1的排列迅速散布 到世界各地,撼动人心.何谓MP3?MP3的全称是MPEG Audio Layer 3,它是一种高效 ...
- C# 获取 mp3文件信息
C# 获取 mp3文件信息[包括:文件大小.歌曲长度.歌手.专辑] 第一种方式:[代码已验证] // http://bbs.csdn.net/topics/390392612 string fil ...
- 浅谈如何使用代码为MP3文件写入ID3Tags
作者:郑童宇 GitHub:https://github.com/CrazyZty 1.前言 做了三年左右的Android开发,一直没写过博客,最近正好打算换工作,算是闲一些,就将以前开发所遇到的一些 ...
- PE文件常用结构体
Dos头结构: typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_c ...
- C# 获取 mp3文件信息【包括:文件大小、歌曲长度、歌手、专辑】
C# 获取 mp3文件信息[包括:文件大小.歌曲长度.歌手.专辑] 第一种方式:[代码已验证] // http://bbs.csdn.net/topics/390392612 string fil ...
- C#读取MP3文件的专辑图片和ID3V2Tag信息(带代码)
第二次更新,后面的代码有问题,有些专辑图片读取不到.发现是PNG图片的问题.在读取的过程中调试发现,图片帧前10个字节包含了图片的格式,在有些歌曲写着JPEG的格式,数据却是PNG的.先说下思路. j ...
- vc中播放mp3文件的方法小结
一般播放MP3常见的有两种方法,一种是自己解码,另外一种用系统的库,比如MCI,当然如果可以用控件直接用个控件会更方便. 1. 使用mci #include <windows.h> ...
- MP3文件信息修改
MP3文件信息 参考链接:https://www.jianshu.com/p/e368517ec7b9 总结: ID3V1在MP3文件后面;ID3V2在MP3文件前面;现在有些文件是V1的,有些文件是 ...
- MP3文件信息批量更改器
以前(估计是2003年)编写一个MP3文件信息批量更改器MP3TagChanger,现放上来参考.(VB6编码) 使用方法很简单,会Winamp或者千千静听的就懂使用. http://pan.baid ...
随机推荐
- partial_sort_百度百科
partial_sort_百度百科 partial_sort
- ios创建画笔的样例(双笔画效果)
定义一个UIView:主要是在这个View里面加一个UIImageView,绘图都在这个UIImageView里面进行 @property(nonatomic) CGPoint prePoint; / ...
- 在Eclipse/MyEclipse中安装spket插件
Spket ide是强大的工具包为了JavaScript和XML的开发,这个强大的编辑器对JavaScript, XUL/XBLand Yahoo! Widget的开发都有全面的支持 ,比如代码完毕, ...
- uva 816 - Abbott's Revenge(有点困难bfs迷宫称号)
是典型的bfs,但是,这个问题的目的在于读取条件的困难,而不是简单地推断,需要找到一种方法来读取条件.还需要想办法去推断每一点不能满足条件,继续往下走. #include<cstdio> ...
- Ext.net.DirectMethods
http://www.ext.net.cn/forum.php?mod=viewthread&tid=1282&highlight=directmethod DirectMethod ...
- 基于visual Studio2013解决C语言竞赛题之0806平均分
题目
- 配置SAP 采购合同审批
需求: 采购合同类型是MK,采购组织是POSC,采购组PGC,标识:估计价格是空,总价有值0.00 - 9999999999.00 RMB 满足以上条件的时候需要审批该合同. 配置: spro-> ...
- C语言,题目:函数调用,内存,malloc找错
malloc int* p = (int *) malloc (sizeof(int)*128); //分配128个(可根据实际需要替换该数值)整型存储单元,并将这128个连续的整型存储单元的首地址存 ...
- Ubuntu 安装Matlab2010a
1.挂载ISO 2.到/media/iso内,在终端执行./install 3.可视化安装 4.问题 1)/usr/local/MATLAB/R2010a/bin/util/oscheck.sh:/l ...
- URAL 1180. Stone Game (博弈 + 规律)
1180. Stone Game Time limit: 1.0 second Memory limit: 64 MB Two Nikifors play a funny game. There is ...