使用python制作MIDI音乐数组
本文介绍了使用Python解析MIDI音乐文件生成单片机播放数据的方法。通过mido库读取MIDI文件中的音阶频率和持续时间参数,将音符信息转换为十六进制格式(note_on为0x90,note_off为0x80)。需要注意的是,该方法存在较多限制:多个音轨处理困难、解析数据混乱、对MIDI文件质量要求较高,且仅能处理单一音轨。作者建议后续开发专用上位机来优化解析过程,提升多音轨处理能力。该方法为
【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
更多推荐



所有评论(0)