近来本着踏实努力一点一滴的原则,研究了下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的歌曲信息,一般声明如下:
struct MP3INFO //MP3的信息结构,固定的,存放在歌曲最后128个字节中 { char identify[3]; // TAG char Title[30]; // 歌曲名,30个字节 char Artist[30]; // 歌手名,30个字节 char Album[30]; // 所属唱片,30个字节 char Year[4]; // 年份,4个字符 char Comment[30]; // 注释,28个字节,有些说是30个,但都没啥关系,只是保留位的大小要改改 char reserved[1]; //保留,暂无用 };
知道了这些就很容易了,不敢用什么办法,只要读取到最后的128个字节,所有的相关信息就可以得到了,用VC6.0控制台程序测试如下(主代码):
#include "stdafx.h" struct MP3INFO //MP3的信息结构,固定的,存放在歌曲最后128个字节中 { char identify[3]; // TAG char Title[30]; // 歌曲名,30个字节 char Artist[30]; // 歌手名,30个字节 char Album[30]; // 所属唱片,30个字节 char Year[4]; // 年份,4个字符 char Comment[30]; // 注释,28个字节,有些说是30个,但都没啥关系,只是保留位的大小要改改 char reserved[1]; //保留,暂无用 }; int main(int argc, char* argv[]) { printf("读取一个MP3的信息,每个MP3的最后128个字节存储的,它有固定的结构,下面试读取之!\n"); MP3INFO mp3; FILE *pf = fopen("H:/1.mp3","r"); printf("打开文件:%d\n",pf); fseek(pf,-128,SEEK_END); fread(&mp3,sizeof(mp3),1,pf); printf("TAG标志:%s\n",mp3.identify); printf("曲名:%s\n",mp3.Title); printf("歌手:%s\n",mp3.Artist); printf("唱片:%s\n",mp3.Album); printf("年份:%s\n",mp3.Year); printf("注释:%s\n",mp3.Comment); fclose(pf); return 0; }
效果如下:
读取的任务完成了。对于修改,知道了这些再做完善也很容易:(如下)
memset(&mp3,0,sizeof(mp3)); printf("修改信息:\n"); mp3.Identify[0]='T'; mp3.Identify[1]='A'; mp3.Identify[2]='G'; mp3.Flag='0'; mp3.Track='5'; mp3.Style='3'; lstrcpy(mp3.Title,(LPCTSTR)"修改的名字"); lstrcpy(mp3.Artist,(LPCTSTR)"修改的作者"); lstrcpy(mp3.Album,(LPCTSTR)"修改的唱片"); lstrcpy(mp3.Year,(LPCTSTR)"1989"); lstrcpy(mp3.Comment,(LPCTSTR)"修改的注释"); fseek(pf,-128,SEEK_END); fwrite(&mp3,sizeof(mp3),1,pf);
修改完成后,在UltraEdit中查看(16进制),信息格式完全正确。但是,用Windows自带的属性查看发现,其上面的内容不全是我们修改的,这是为什么呢?
经多方查找 http://en.wikipedia.org/wiki/ID3,http://baike.baidu.com/view/66078.html
/* * ID3v1是固定的128个字节,这个你不用担心。其实ID3v1是这样安排的:如果MP3的注释是大于28个字节的,那么就要借用126-127两个字节。 * 所以ID3v1的注释部分可能是28个字节也可能是30个字节。那么,怎么区分到底是28个字节还是30个字节呢?很简单,126处就是管这个的, * 我们只要看看126处是不是0x00,如果是0x00那么注释就有28个字节。如果不等于0x00,那么就是说注释是30个字节。同时别忘了, * 由于第127字节存储了Track信息,那么如果注释是30个字节的时候,这首歌的ID3v1里的那个127处的信息自然就不是Track信息了。 * Track自然就是没有地方存了,所以127处变的没有Track意义了,它只是Comment的一部分了。 */ struct ID3v1 //MP3的信息结构,固定的,存放在歌曲最后128个字节中 { char Identify[3]; // ID3v1为TAG char Title[30]; // 歌曲名,30个字节 char Artist[30]; // 歌手名,30个字节 char Album[30]; // 所属唱片,30个字节 char Year[4]; // 年份,4个字符 char Comment[28]; // 注释,28个字节,有时是30个, char Flag; // 标志,为0说明有音轨(下一位),不一定有 char Track; // 音轨,#,歌曲号,不一定有 char Style; // 风格流派,需要查询,不一定有 };
所以对读写取程序做些修改:
void ReadID3v1(char* pfile) { printf("读取一个MP3的信息,每个MP3的最后128个字节存储的,它有固定的结构,下面试读取之!\n"); ID3v1 mp3; FILE *pf = fopen(pfile,"r+"); printf("打开文件:%d\n",pf); fseek(pf,-128,SEEK_END); fread(&mp3,sizeof(mp3),1,pf); if (mp3.Identify[0]!='T' || mp3.Identify[1]!='A' || mp3.Identify[2]!='G' ) { printf("此歌曲不支持ID3v2标准!\n"); fclose(pf); return; } printf("TAG标志:%.3s\n",mp3.Identify); printf("曲名:%.30s\n",mp3.Title); printf("歌手:%.30s\n",mp3.Artist); printf("唱片:%.30s\n",mp3.Album); printf("年份:%.4s\n",mp3.Year); printf("注释:%.30s\n",mp3.Comment); if (mp3.Flag==0) { printf("歌曲序号:%d,流派标志:%d\n",mp3.Track,mp3.Style); } getchar(); //下面试着修改信息 memset(&mp3,0,sizeof(mp3)); printf("修改信息:\n"); mp3.Identify[0]='T'; mp3.Identify[1]='A'; mp3.Identify[2]='G'; mp3.Flag='0'; mp3.Track='5'; mp3.Style='3'; lstrcpy(mp3.Title,(LPCTSTR)"修改的名字"); lstrcpy(mp3.Artist,(LPCTSTR)"修改的作者"); lstrcpy(mp3.Album,(LPCTSTR)"修改的唱片"); lstrcpy(mp3.Year,(LPCTSTR)"1989"); lstrcpy(mp3.Comment,(LPCTSTR)"修改的注释"); fseek(pf,-128,SEEK_END); fwrite(&mp3,sizeof(mp3),1,pf); printf("over,%s\n",mp3.Title); fclose(pf); }
http://blog.csdn.net/bbdxf/article/details/7438006

MySQL适合初学者学习数据库技能。1.安装MySQL服务器和客户端工具。2.理解基本SQL查询,如SELECT。3.掌握数据操作:创建表、插入、更新、删除数据。4.学习高级技巧:子查询和窗口函数。5.调试和优化:检查语法、使用索引、避免SELECT*,并使用LIMIT。

MySQL通过表结构和SQL查询高效管理结构化数据,并通过外键实现表间关系。1.创建表时定义数据格式和类型。2.使用外键建立表间关系。3.通过索引和查询优化提高性能。4.定期备份和监控数据库确保数据安全和性能优化。

MySQL是一个开源的关系型数据库管理系统,广泛应用于Web开发。它的关键特性包括:1.支持多种存储引擎,如InnoDB和MyISAM,适用于不同场景;2.提供主从复制功能,利于负载均衡和数据备份;3.通过查询优化和索引使用提高查询效率。

SQL用于与MySQL数据库交互,实现数据的增、删、改、查及数据库设计。1)SQL通过SELECT、INSERT、UPDATE、DELETE语句进行数据操作;2)使用CREATE、ALTER、DROP语句进行数据库设计和管理;3)复杂查询和数据分析通过SQL实现,提升业务决策效率。

MySQL的基本操作包括创建数据库、表格,及使用SQL进行数据的CRUD操作。1.创建数据库:CREATEDATABASEmy_first_db;2.创建表格:CREATETABLEbooks(idINTAUTO_INCREMENTPRIMARYKEY,titleVARCHAR(100)NOTNULL,authorVARCHAR(100)NOTNULL,published_yearINT);3.插入数据:INSERTINTObooks(title,author,published_year)VA

MySQL在Web应用中的主要作用是存储和管理数据。1.MySQL高效处理用户信息、产品目录和交易记录等数据。2.通过SQL查询,开发者能从数据库提取信息生成动态内容。3.MySQL基于客户端-服务器模型工作,确保查询速度可接受。

构建MySQL数据库的步骤包括:1.创建数据库和表,2.插入数据,3.进行查询。首先,使用CREATEDATABASE和CREATETABLE语句创建数据库和表,然后用INSERTINTO语句插入数据,最后用SELECT语句查询数据。

MySQL适合初学者,因为它易用且功能强大。1.MySQL是关系型数据库,使用SQL进行CRUD操作。2.安装简单,需配置root用户密码。3.使用INSERT、UPDATE、DELETE、SELECT进行数据操作。4.复杂查询可使用ORDERBY、WHERE和JOIN。5.调试需检查语法,使用EXPLAIN分析查询。6.优化建议包括使用索引、选择合适数据类型和良好编程习惯。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6
视觉化网页开发工具

WebStorm Mac版
好用的JavaScript开发工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

记事本++7.3.1
好用且免费的代码编辑器