【python脚本系列】利用mido库解析midi文件

【python脚本系列】利用mido库解析midi文件

 

      Hallo大家好~~我是Lampard猿奋

      昨天写了关于Midi数字化乐器接口的文章,介绍了midi是一组代表音乐参数(如音高,动态,节奏等等 )的标准化代码,是音乐与计算机之间交互的语言。那么这个语言究竟是怎么组成,是什么数据结构呢,下面就借助python的mido库和大家一起打开这个黑盒

(一)几个重要概念

(1)Channel通道

      channel是指定的0~15的一个值,因为MIDI文件给我们提供了默认的16个通道,每一个通道可以对应一种乐器,相当于midi支持一首歌曲里同时使用16种乐器进行演奏

      当然每一个通道对应的乐器并不是固定的,我们可以代码Message('program_change', channel, program, time=0)改变其对应关系,也就是说虽然同时支持16种乐器,但16种乐器不需要是固定的,上述接口中program代表着乐器Id,更多乐器Id相关可以跳转至此:【Midi音色表】

(2)Track音轨

      音轨,音轨与通道并不是一一对应,而是可以多对多的关系。音轨是逻辑上的划分,比如可以将钢琴的左手演奏放在track 1,右手演奏放在track 2。但是输出时候,都是对应输出到钢琴的通道。你也可以只设置一个track 1,并且在里面记录着不同通道的消息。另外,还经常将track 0用来存储midi的作者、版权、音轨名、乐器名等元信息

(3)Event事件

      事件也叫做消息(在mido库中使用message表示)。包括三种事件meta event元消息,midi event主消息, sysex event系统消息

      元消息上文有提及是作者,版权,音乐名等信息的存在track0中,系统消息是存储midi系统不同版本的信息,主要需要留意的就是midi消息

       midi有多种信息类型,我们可以参考mido文档去查阅:【mido库文档】,而我们主要需要关注两个信息note_on和note_off

(4)note_on

      note_on消息,可以理解为音符的开始(按下),其格式为Message('note_on', note, velocity, time, channel)

      其中note是0~127的一个数字,代表音符的高低,通过实践证明60代表的音高是C4

      velocity代表音强,也是0~127的一个数字,默认为64,若要体现音符强度的变化可以修改它

      time是时间变量,是十分复杂的一个参数,在note_on信息这里可以理解为该音符写在前一个音符结束多久之后,单位是微秒(ms)

      channel同上一个函数一样,代表通道的编号,即将这个音符写到哪个通道之上,这可能起到更改乐器的效果

(5)note_off

      note_off消息,可以理解为音符的结束(抬起),一般紧跟在note_on消息之后,其格式与上面的相同Message('note_off', note, velocity, time, channel)
      note参数与note_on消息保持一致,否则有可能不能成功写入
      velocity同note_on保持一致就好
      time在此处表示的意义是音符的持续时间,也是以微秒(ms)为单位
      channel也是表示通道号,与note_on保持相同即可

(二)使用Mido库

      看了那么多字感觉头都大了,好像也不太理解说的是什么。那下面还是直观一些用Mido库给我们提供的案例来分析一下Midi文件的结构吧【mido库示例】

 (1) 创建一个MIdi文件

from mido import Message, MidiFile, MidiTrack

mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)

track.append(Message('program_change', program=12, time=0))
track.append(Message('note_on', note=64, velocity=64, time=32))
track.append(Message('note_off', note=64, velocity=127, time=32))

mid.save('new_song.mid')

      这段示例代码虽然短,可是已经将编写MIDI文件的基本思路完全表达出来了:

    1. 首先创建一个MidiFile对象
    2.创建一个(或多个)MidiTrack对象,并将其append到MidiFile中
    3.向一个(或多个)MidiTrack对象内添加Message对象(包括program_change(变更通道对应乐器)、note_on(按下)、note_off(抬起)等)
    4.保存MidiFile对象

      我把这段代码命名为makeMidi.py,执行一遍就能获取到我们生成的new_song.midi文件

 

 (2) 解析这个MIdi文件

      然后就是读取这个midi,mido库同样给出了示例,逻辑很简单就是打印出这个midi文件每一个音轨track的信息    

       最后我们看一下我们打出的日志,我把解析的脚本命名为readMidi.py,执行后可以看到我们刚才输入的信息,在音轨0的32ms后执行一次的点击动作,对应的音色是64

      如果我们不想打印出全部信息,指向关注不同track之间的note_on和note_off的信息,我们可以msg.type == “note_on/note_off”这样来判别

(三)结语

      当我们能够解析出midi的信息之后就可以和音效制作乐谱的同学沟通啦。距离实现音游玩法也跟进了一步,待玩法进度推进后我再继续更新~~

      感谢阅读,点赞,关注!!!

  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lampard杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值