前回記事の続き(注: かなりマニアックです)。今回はトラック1の1小節目冒頭に所定のSysExメッセージを挿入してみる。
下準備
midoパッケージのインポートと、Studio One から書き出したサンプルのSMFファイルをmid
変数に読み込むところまでやっておく。
from mido import MidiFile, Message # 各トラック毎の全メッセージを表示する def dump_track(track_obj): for msg in track_obj: print(msg) # 全トラックの全メッセージをトラック毎に表示する def dump_smf(midi_obj): for i, track in enumerate(midi_obj.tracks): print(f"Track {i}: {track.name}") dump_track(track) # Studio One から書き出したSMFを mid に読み込む mid = MidiFile('smf_studio1.mid')
対象トラックの抽出
SysExメッセージはトラック1に挿入したいと思うので、SMFオブジェクト(上例ではmid
変数に格納)を構成するトラック・リストより、トラック1を抜き出して操作することにする*1。
mid.tracks
の中身を見れば、構成トラックは以下の通りに7件あるが、このうち最初の要素はメタイベント用のトラックなので、トラック1は2番目の要素("Oboe"というトラック名が付いている)ということになる。
したがって、トラック1を以下のように抜き出して変数代入する(リストのインデックスはゼロベースなので、2ではなくて1)。
# トラック1を抜き出して、変数"track1"に代入する track1 = mid.tracks[1]
このトラックの中身は以下のようになっている(11行目以降は省略)。このメッセージ・リストの2番目の要素の直後(メタメッセージの直後)にSysExメッセージを挿入する。
メッセージ・オブジェクトの生成
メッセージ・データの作成は非常に簡単で、たとえばGM2音源使用オンのためのSysExメッセージは、以下の1行で済む*2。データ値は10進数のタプルで与える。ここは協会テンプレSMFを上記と同じくmidoパッケージを使って覗いてみた結果をそのままコピーすればよい。他セットアップ用のデータも同様である(次回以降詳述)。
# SysExメッセージの作成 msg = Message('sysex', data=(126, 127, 9, 3))
本メッセージをprint
すれば、以下のように中身を表示確認できる。
なお、midoパッケージにおける各種MIDIメッセージの仕様については、公式ドキュメントを参照されたい。
メッセージの挿入
トラック・オブジェクトはリストのサブクラスで、要はメッセージのリスト構造になっているので、リスト操作のメソッドが適用可能である。したがって、上記メッセージの挿入は、そのものずばりinsert
メソッドで入れてしまえばできあがりである。
# 上記SysExメッセージを2番目の要素の後ろに挿入する track1.insert(2, msg)
挿入後のトラック1の中身は、以下のようになった(冒頭5行)。
*1:元のSMFオブジェクトmidを直接修正してもよいが、ここでは分かりやすくするために該当のトラック・オブジェクトを切り出して編集操作する。[ここからはマニアックな話] Pythonではリストなどのミュータブルなオブジェクトを変数に代入しても、それはオリジナルに対する参照になるため、実は変数track1の中身を操作すると元のmid.tracks[1]にも反映される。「Pythonのリストで参照渡しでないコピーを作成する話」などを参考。
*2:ここではデルタタイムはデフォルトのゼロのままでよい。