关于mp3文件结构解析的问题

最近在用qt5编写播放器时遇到个问题,在Windows端需要解析音频文件音谱来绘制曲线图,但发现Windows端的库要么太老、要么太弱鸡、要么得自己编译,无奈花了一天时间在下载、编译taglib、学习ffmpeg路上,到最后都是以动态库调用时出现未知函数告终(mingw_gcc),原来qt本身就有对这些的封装,可采用qmediaplaer代替他们,只不过需要安装解码器才行,但qmediaplaer并不支持ffmpeg、taglib的音频文件直接操作功能,这不得已自己重写一版。。。

参考文章
MP3文件结构解析(超详细)
要一个解析MP3的代码要C语言的 要自己写的不要网上的
Inside the MP3 Codec - Page 11
lets-build-mp3-decoder
Reading MP3 files [closed]

C语言结构体为

ID3V2

//起始位置:0x0-0x9
struct ID3V2Header{
	char Header[3];    /*必须为“ID3”否则认为标签不存在*/
	char Ver[1];         /*版本号ID3V2.3 就记录3*/
	char Revision[1];     /*副版本号此版本记录为0*/
	char Flag[1];        /*标志字节,只使用高三位,其它位为0 */
	char Size[4];      /*标签大小*/
};
//起始位置:0x10-0x19
struct ID3V2INFO{
	char ID[4]; /*标识帧,说明其内容,例如作者/标题等*/
	char Size[4]; /*帧内容的大小,不包括帧头,不得小于1*/
	char Flags[2]; /*标志帧,只定义了6 位*/
};


ID3V1

//起始位置:-128
struct ID3V1HEAD{
	char tag[3];//tag占用3字节
	char musicname[30];//音乐标签占30字节
	char artist[30];//歌曲作者占30字节
	char album[30];//发行专辑占30字节
	char year[4];//发行年份占4字节
	char generic[30];//一些音乐的介绍以及其他杂七杂八内容占30字节
	char type[1];//类型,占1字节
};

part1:ID3v1版本可以通过音乐文件末尾倒数第128字节开始进行数据截取,这也是最简单的

//用于解析mp3文件,采用id3v1取倒数128固定位置数据
MP3INFO MediaTools::toMp3Info(QString path) {
  int part = 128;
  QString tag, musicname, artist, album, year, generic, musictype;
  QFile f(path);
  f.open(QFile::ReadOnly);//以只读方式打开文件
  f.seek(f.size() - part);//从倒数128开始读取数据
  part = part - 3;
  tag = QString::fromLocal8Bit(f.readLine(4));//前3字节为tag标签,这里为什么用4,因为这是qt
  f.seek(f.size() - part);
  part = part - 30;//这里减去30,是为了给下面往后移动30字节读取内容
  musicname = QString::fromLocal8Bit(f.readLine(31));
  f.seek(f.size() - part);
  part = part - 30;
  artist = QString::fromLocal8Bit(f.readLine(31));
  f.seek(f.size() - part);
  part = part - 30;
  album = QString::fromLocal8Bit(f.readLine(31));
  f.seek(f.size() - part);
  part = part - 4;
  year = QString::fromLocal8Bit(f.readLine(5));
  f.seek(f.size() - part);
  part = part - 30;
  generic = QString::fromLocal8Bit(f.readLine());
  f.seek(f.size() - 1);
  musictype = QString::fromLocal8Bit(f.readLine(1));
  f.close();
  //返回mp3info对象,可以用结构体代替
  return MP3INFO(tag, musicname, artist, album, year, generic, musictype);
}

part2:ID3v2.3版本在国内只有原理讲解文章与一些开源第三方库可供参考
我这里实现了一版非常烂的demo,望各位懂这方面的大佬帮忙指点指点

void MediaTools::seekFiles(int &len, QFile &f) {
  QByteArray by;//创建一个字节数组对象
  f.seek(len);//设置文件读取起始位置
  //这个为音乐文件里0x21起始头部的帧信息头部,占4字节
  qDebug() << "seekFiles  0 ::" << QString::fromLocal8Bit(f.readLine(5));
  f.seek(len + 4);
  //这个为音乐文件里帧内容大小
  by = f.read(4);
  qDebug() << "seekFiles  1 ::" << by;
  f.seek(len + 4 + 4);
  qDebug() << "seekFiles  2 ::" << QString::fromLocal8Bit(f.readLine(3));
  int FSize;
  //帧内容大小计算公式
  FSize = by[0] * 0x100000000 + by[1] * 0x10000 + by[2] * 0x100 + by[3];
  qDebug() << "seekFiles  fsize ::" << FSize;
  f.seek(len + 11);
  qDebug() << "seekFiles  data ::" << QString::fromLocal8Bit(f.readLine());
  len = len + 10 + FSize;
  qDebug() << "next positi ::: " << len << "\n";
}

//第一次调用位置
void MediaTools::Mp3ID3V2_3(QString path) {
  QFile f(path);
  f.open(QFile::ReadOnly);
  QByteArray by;
  //读取0x0-0x9位置的数据
  qDebug() << "0 ::" << QString::fromLocal8Bit(f.readLine(4));//tag标识
  f.seek(3);
  qDebug() << "1 ::" << QString::fromLocal8Bit(f.readLine(2));
  f.seek(4);
  qDebug() << "2 ::" << QString::fromLocal8Bit(f.readLine(2));
  f.seek(5);
  qDebug() << "3 ::" << QString::fromLocal8Bit(f.readLine(2));
  f.seek(6);
  //帧数据内容大小,这里的大小为所有帧的内容大小,也就是说,在这个地址往后偏移1位就是音频数据了
  by = f.read(4);
  qDebug() << "4 ::" << by;
  int len = 10;
  int total_size;

  total_size = (by[0] & 0x7F) * 0x200000 + (by[1] & 0x7F) * 0x400 +
               (by[2] & 0x7F) * 0x80 + (by[3] & 0x7F);
  qDebug() << total_size;
  //通过不断的调用来获取音频文件里TIT2、TPE1、TALB等内容信息
  seekFiles(len, f);
  seekFiles(len, f);
  seekFiles(len, f);
  seekFiles(len, f);
  seekFiles(len, f);
  seekFiles(len, f);
  seekFiles(len, f);
  seekFiles(len, f);

  f.close();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
敬告:该系列的课程在抓紧录制更新中,敬请大家关注。敬告: 该系列的课程涉及:FFmpeg,WebRTC,SRS,Nginx,Darwin,Live555,等。包括:音视频、流媒体、直播、Android、视频监控28181、等。  我将带领大家一起来学习:Qt麦克风数据探测、FFmpeg解码音频数据、音频波形图、音频播放器。具体内容包括:1.Qt采集麦克风并探测数据,生成动态矩形图。2.FFMpeg解码音频数据,生成PCM数据,并绘制波形图。3.音频播放器实战。 音视频与流媒体是一门很复杂的技术,涉及的概念、原理、理论非常多,很多初学者不学 基础理论,而是直接做项目,往往会看到c/c++的代码时一头雾水,不知道代码到底是什么意思,这是为什么呢? 因为没有学习音视频和流媒体的基础理论,就比如学习英语,不学习基本单词,而是天天听英语新闻,总也听不懂。所以呢,一定要认真学习基础理论,然后再学习播放器、转码器、非编、流媒体直播、视频监控、等等。 梅老师从事音视频与流媒体行业18年;曾在永新视博、中科大洋、百度、美国Harris广播事业部等公司就职,经验丰富;曾亲手主导广电直播全套项目,精通h.264/h.265/aac,曾亲自参与百度app上的网页播放器等实战产品。目前全身心自主创业,主要聚焦音视频+流媒体行业,精通音视频加密、流媒体在线转码快编等热门产品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值