【STM32】无源蜂鸣器播放音乐《千与千寻》,HAL库-CSDN博客一文中看到有读者留言和私信我问怎么制作这个音乐的数组,这里简单谈一下制作方法

笔者是使用python语言来将下载好的midi音乐文件进行读取并转化为单片机进行播放的格式

用到的库是mido库,官网如下

Mido - MIDI Objects for Python — Mido 1.3.4.dev12+g3385b0d documentation

这个官方库的文档对midi做了一些介绍和关于如何使用这个库,需要一点点的python语言基础,有不懂的内容多翻翻文档,基本都有答案了。

核心原理是读取midi文件,获取音阶频率,持续时间这两个参数

将midi文件和py文件放在同一目录下

代码如下

import mido


midiSpiritedAway = mido.MidiFile("spiritedAway.mid")

#解析并打印 MIDI 文件中的所有消息
for i, track in enumerate(midiSpiritedAway.tracks):
   # print(f"Track {i}:")
   for msg in track:
      #   如果是 note_on 并且 velocity 为 0,则将其视为 note_off
      if msg.type == 'note_on' and msg.velocity == 0:
         msg = mido.Message('note_off', note=msg.note, velocity=0, time=msg.time)
         #   只打印 note 和 time,以十六进制表示
      if (msg.type == 'note_on' or msg.type == 'note_off' ) :
         status_byte = '90' if msg.type == 'note_on' else '80'  # note_on 对应 0x90, note_off 对应 0x80
         note_hex = format(msg.note, '02X')  # 音符编号转换为两位十六进制
         time_hex = format(msg.time, '04X')  # 时间戳转换为四位十六进制
         print(f"0x{status_byte},0x{note_hex},0x{time_hex},")
      elif (msg.type == "control_change"):
         print("\n\n*******************\n\n")
      elif ("Track" in str(msg)):
         print("\n\n-------------------\n\n")
      else:
         pass

打印输出的就是需要的数组了,有时候会有多个,高音和低音,自行选取。笔者后续对别的音源也进行测试,发现有些播放起来有点问题,但也没有继续深究。

由于大多midi文件可能含有多个track(就比如这里的《千与千寻》,笔者选取的其实是第一个track),对于仅有一个单片机的系统来说有点难以处理,解析出来的数据也很混乱,这是其中的不足之处。换句话说,这个办法对midi文件比较挑剔,后续有机会的话,笔者还会深入研究,争取做出一个上位机,可以更方便地解析每个track和message

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐