用Mido简单玩MIDI音乐——简介

2/21/2022 乐理MIDIPythonMido

这篇文章主要讨论如何通过 Mido 简单播放音乐以及一些基础的乐理知识

# MIDI

MIDI是一种音乐的数字乐器接口协议,通过音符的播放模拟演奏音乐。经过很多年的发展,MIDI已经有了一定的作曲承载能力。现在,通过MIDI也可以模拟很多有清晰曲谱的古典音乐,在Kaggle上也有了不少MIDI数据集。

# MIDO

Mido是python的一个MIDI包,提供统一的MIDI控制接口,最主要的方式是向MIDI文件中的不同音轨添加音符,或者打开接口后发送控制信息实时播放。Mido的API比较直观,使用也比较方便,足够覆盖大多数的使用情景。

# Mido的安装

首先放官网:

  • 源代码:https://github.com/mido/mido
  • 文档:https://mido.readthedocs.io/en/latest/index.html

Mido 需要 Python 2.7+ / 3.6+,安装很简单:

$ pip install mido

Mido本身并不直接控制MIDI的解析、播放,而是需要其他库控制,这些库被称为mido的后端,目前支持rtmidi、pygame等。默认情况下,使用rtmidi作为后端。安装也很简单:

$ pip install python-rtmidi

安装完成后我们就可以开始愉快的玩耍了。

# Midi的基础概念

要认识mido,就需要首先了解MIDI的一些标准。在查阅了一些MIDI标准的文件后,简单总结下 MIDI 1.1 的一些特性,以便理解mido的设计:

  • MIDI是由一串字节组成,采用了变长记录的设计,用以平衡长短音符的占用;变长数据通过32bit记录数据块长度;每单位数据由大端法表示,即最高有效位在前。
  • MIDI中数据组织的基本单位是块(chunk),分为header和track块;
    • header块主要记录整个文件的元信息,包括长度、track块数量、格式(与音轨有关)、切分(division);
      • 关于division的含义有两种表示,根据最高位区分:
        1. 表示一个音符的切分量,例如division为96表示四分音符用96 ticks,八分音符的时长即为48 ticks;
        2. 负数表示一秒的帧数,再表示每帧的tick数;
    • track块用于记录一个音轨中的所有事件,MIDI通过事件(event)控制音符的变化,如演奏某个音符或停止等;
      • 每个event都带有一个自开始的offset时间和事件;
        • 事件分为:MIDI事件,系统外事件(sysex)和元事件;
  • MIDI使用序号对照音符,共128个音符,覆盖C-1到G9,已经超过了常见钢琴的88个音。
  • MIDI有16个channel,可以理解为不同乐器的载体,通过调整channel的音色可以进行简单的配器。其中,channel 10用于记录打击乐。

# MIDI标准的信息表

  • MIDI音符对应表:
    音符对照表

  • MIDI音色表:

PC# Family PC# Family
1-8 Piano 65-72 Reed
9-16 Chromatic Percussion 73-80 Pipe
17-24 Organ 81-88 Synth Lead
25-32 Guitar 89-96 Synth Pad
33-40 Bass 97-104 Synth
41-48 Strings 105-112 Ethnic
49-56 Ensemble 113-120 Percussive
57-64 Brass 121-128 Sound Effects

# Mido基本概念

Mido通过名为Message的对象控制midi后端,基本的原理是向后端的port或者文件发送MIDI事件,以控制实时的或是文件上的输出。在MIDI支持的事件集中,Mido仅有选择性的支持其中的一部分最常用的。

此处简单记录Message的效果,更多详细信息可以参考:

Message名 参数/属性 备注
note_off channel note velocity 释放某个音符
note_on channel note velocity 按下某个音符
polytouch channel note value 在按下音符后改变按下的压力
control_change channel control value 改变控制器
program_change channel program 改变音色
aftertouch channel value 将某条音轨上的所有音符的按压力度改变
pitchwheel channel pitch 改变某条音轨的变调
sysex data 用于MIDI系统外的信息传递
quarter_frame frame_type frame_value
songpos pos 记录歌曲开始的MIDI节拍的位置
song_select song 选择播放的序列或歌曲
tune_request 用于调整和弦
clock 用于同步音频的节拍
start 控制音符播放,clock会附带
continue 控制音符继续播放
stop 结束播放
active_sensing 可用于连接检测
reset 重置所有状态

# Next Step

有了以上的信息,我们就可以开始尝试各种通过程序控制的作曲方法了。