[RISC-V MCU 创新应用比赛] 沁恒 CH32V103 解析mp3文件信息

[复制链接]
5510|6
 楼主| gtbestom 发表于 2021-8-30 23:29 | 显示全部楼层 |阅读模式
本帖最后由 gtbestom 于 2021-8-30 23:45 编辑

#申请原创#@21小跑堂
  在使用沁恒 CH32V103 单片机完成 mp3 播放器设计之前,首先要对 mp3 文件进行一些必要的解析
  虽然使用了 VS1003 硬解码 mp3 数据流,但仍然无法获取足够的信息
  先看从 VS1003 能获取到哪些信息

1251612cfca90b245.png


9299612cfcc98a7c6.png



  简单点的 MP3 播放器,需要显示歌名,歌手名,总时长,播放进度,还有其他的一些信息

  这上面的信息剔除一些不常用的,可以获取到一些比较常用的信息,例如 MPEG 版本,Layer 层,采样率,比特率,声道,还有解码时间

  MPEG1.0,Layer3,就是我们平时常见的 MP3 类型了,根据这两个信息,再根据采样率索引和比特率索引,可以得到采样率和比特率

69456612cfceab812c.png


55474612cfd041f6b5.png


  那歌曲总时长,在哪里找呢?

  其实 MP3 文件并没有记录歌曲总时长,但是我们可以根据文件信息,大致估算歌曲时长:

  对于固定码率 MP3 文件(CBR):


  歌曲总时长(秒) = 文件大小(字节)÷ ( 比特率(Kbps)× 1000 ÷ 8 )


3803612cfa5a73fdc.png



  例如 “佛系少女” 这首歌,按照这个方法计算,计算结果 195 秒(3分钟15秒),是正确的

  但是用文件大小计算,不总是正确的,文件大小 = 标签数据大小 + 音频数据大小,一种情况是文件标签太大,文件大小跟音频数据大小就相差太多,计算结果就会有比较大的偏差,另一种情况是可变码率 MP3 文件(VBR),计算结果也可能是错误的


98240612cfabe1051f.png



  例如 “公子向北走” 这首歌,按照这个方法计算,计算结果 265 秒(4分钟25秒),而实际时长是 4 分钟 7 秒,头部标签占了 700 多K字节,如果不剔除这些标签信息,就无法得到准确的音频数据量和播放时长,还会导致另一个问题,进度条走了大约 10 秒,也没听到 VS1003 输出音频,因为单片机向 VS1003 传输的都是头部标签信息,没有音频数据

  头部信息为什么会这么大呢?看看资源管理器的预览,可以知道有些 MP3 是内置专辑图片的,这个图片一般也在头部信息里。


29071612cfafdbbff6.png



  MP3 头部,一般有 ID3v2 标签,在 MP3 尾部,还可能会有 ID3v1 标签和 APEv2 标签,这些标签有些描述了歌曲的:歌名、歌手名、专辑名、年份、专辑图片 等信息,如果能剔除这些标签,就能获取原始的音频数据流,先用 16进制 方式打开文件分析,可以看到 MP3 前3个字节为 “ID3”,说明该 MP3 包含 ID3v2 标签


18378612cfb44ae350.png



  再看 MP3 文件末尾,可以看到 “TAG” 字符在文件末尾前 128字节处,说明包含 ID3v1 标签,如果 “TAG” 前32字节处还包含 “APETAGEX” 字符,说明也有 APEv2 标签


63312612cfb975dbb0.png



  只要计算好这些标签的总大小,就能比较准确的计算音频数据大小,事实上很多 MP3 文件都满足这一公式

  音频数据大小 = 文件大小 - ID3v2标签大小 - ID3v1标签大小 - APEv2标签大小

  再总结一下:

  文件头为“ID3”,说明有 ID3v2标签,不定长,读取第7-10字节数据,可以获得一个u32类型数据,加 10 就是 ID3v2 标签大小


  1. ID3v2Size = 10 + (((buf[6]&0x7F)<<21) | ((buf[7]&0x7F)<<14) | ((buf[8]&0x7F)<<7) | (buf[9]&0x7F));

  文件尾倒数第128字节开始,有 “TAG”,说明有 ID3v1标签,恒定 128 字节长度
  文件尾倒数第32字节开始,或者 “TAG” 前32字节位置,有 “APETAGEX”,说明有 APEv2 标签,不定长,读取后面第13字节数据,可以获得一个u32类型数据,加 32 就是 ID3v2 标签大小

  1. APEv2Size  = 32 + ( (buf[15] << 24) | (buf[14] << 16) | buf[13] << 8) | buf[12]);


  这里做了简要的计算,方便快速得到计算结果,详细的标签内容可以看相关文档,内容较多,这里就不展开

  至此就可以准确的计算  CBR 类型的 MP3 文件时长,不过我也遇到过极少情况 ID3v2 标签后不紧跟着音频数据的情况,需要查找音频同步信息头,找到第一帧音频,才能准确计算音频数据大小,音频同步头为2进制的 11111111 111xxxxx,即 11 位的 1 数据
  可变比特率 VBR 类型的 MP3 就无法这么计算了,因为比特率不是恒定的,这时候还是需要找到第一帧音频,分析 “XING”、“VBRI”、“INFO” 标签,来找到总帧数、帧数据总大小,再结合采样数、采样率来计算总时长。

  歌曲总时长(秒) = 总帧数 × 每帧采样数 ÷ 采样率;

  对于 MPEG1, Layer3 文件,即 MP3 文件而言,每帧采样数恒为 1152
  这种方法可以计算 VBR 类型 MP3 总时长,也可以计算 CBR 类型 MP3 总时长


34014612cfc0810e6a.png



  当然 ID3v1、ID3v2、APEv2 标签还包含有更多信息,可以用单片机进行解析,ID3v1 内容是 GBK 和 ASCII 编码的,可以简单的读取和显示到串口助手

  ID3v2 版本2版本3,文字多数是 Unicode UTF-16 编码的,需要 UTF-16 转 GBK 后,串口打印才不会乱码

  ID3v2 版本4,文字几乎都是 Unicode UTF-8 编码的,UTF-8 可以简单计算转换到 UTF-16,再转 GBK 打印到串口

  APEv2则规定了只用 Unicode UTF-8 编码文字

  UTF-16 转 GBK 需要较为复杂的对照表,之前一篇**我有进行了说明,有兴趣可以查看之前的帖子

77814612cf99ac5a68.png


64908612cf9b30b6eb.png


qiufengsd 发表于 2022-11-5 11:05 | 显示全部楼层
这个解析mp3的时候,需要注意哪些
timfordlare 发表于 2022-11-5 11:19 | 显示全部楼层
这个语音模块如何通过iis进行数据的传输呢?
ccook11 发表于 2022-11-5 11:37 | 显示全部楼层
可以实现远程wifi的语音播放和控制的吗?
kkzz 发表于 2022-11-5 12:07 | 显示全部楼层
wav和mp3在格式上有什么不同的吗?
小涛DZGZS 发表于 2022-11-7 01:12 | 显示全部楼层
大佬这款串口调试助手和hex编辑器叫什么,看起来好像挺不错的
豌豆爹 发表于 2022-11-7 15:58 来自手机 | 显示全部楼层
根据楼主列举的这些歌可以菜单楼主是相当年轻啊,哈哈
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

114

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部