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 ...
随机推荐
- 求知成瘾+逻辑成瘾+博识的无知,你中枪没?我感觉中枪了 - 外野 - Stage1st - Powered by Discuz!
求知成瘾+逻辑成瘾+博识的无知,你中枪没?我感觉中枪了 - 外野 - Stage1st - Powered by Discuz! 求知成瘾 求知欲似乎是人们的本能,尤其「好学」这个词被定义成天生的褒义 ...
- hdu 2757 Ocean Currents(优先队列+bfs)
小伙伴们真心被这道题惊呆了!刚开始是读题,题目都把小伙伴惊呆了,题目都读不懂! 在前面猴子小伙伴的帮助下,理解了一点点,又偷偷的在纸上写写画画,明白了题意! 后来,你懂的,果断拿下!在拿下的过程也经过 ...
- ONOS系统架构演进,实现高可用性解决方案
上一篇文章<ONOS高可用性和可扩展性实现初探>讲到了ONOS系统架构在高可用.可扩展方面技术概况,提到了系统在分布式集群中怎样保证数据的一致性.在数据终于一致性方面,ONOS採用了Gos ...
- .net嵌入c#代码(投票练习)
.net嵌入c#代码(投票练习) <%@ Page Language="C#" AutoEventWireup="true" CodeFile=" ...
- 极光IM使用教程-极光推送
链接地址:http://jingyan.baidu.com/article/a948d65178a6ea0a2ccd2e7e.html 极光IM使用教程,如果您的 App 需要同时集成 Push 功能 ...
- BZOJ 3039: 玉蟾宫( 悬线法 )
最大子矩阵...悬线法..时间复杂度O(nm) 悬线法就是记录一个H向上延伸的最大长度(悬线), L, R向左向右延伸的最大长度, 然后通过递推来得到. ----------------------- ...
- [转]VMware 出现下述错误: Application failure. hr=0x80040101:Failed to initialize virtual machine.
VMware 出现下述错误:Application failure. hr=0x80040101:Failed to initialize virtual machine. 解决方法:1.重新注册这三 ...
- ADO.NET 对象 结构图
- 深入理解 Spring 事务原理【转】
本文转自码农网 – 吴极心原创 连接地址:http://www.codeceo.com/article/spring-transactions.html 一.事务的基本原理 Spring事务的本质其 ...
- Java返回类型泛型的用法小结
Java返回类型泛型的用法小结 版权声明:本文为博主原创文章,未经博主允许不得转载. 关于Java泛型的基本用法就不多说了,主要是一个编译期的检查,也避免了我们代码中的强制转换,比较经典的用法有泛型D ...