TL;DR
- GM, GS, XGのMIDIのデータをチェックするスクリプト
- SysExを見て判別する
- jupyter labを使いつつも、関数は.pyで書きたい。
General MIDIって?
General MIDI(ジェネラル・ミディ)とは、基本的な音色マップとコントロールチェンジなどを規定したMIDIの統一規格である。略称はGM。
(wikipediaより https://ja.wikipedia.org/wiki/General_MIDI)
で、この規格をローランドが準拠して拡張したのがGS、ヤマハが拡張したのがXGです。当時はRolandのSCシリーズが一番この手の音源で売れていたので、かなり多くのGSのデータがニフティのフォーラムなどで配布されていました。懐かしい、、、
そんなMIDIファイルが2020年に欲しい
と言うことになり、redditのこちらのページ( https://www.reddit.com/r/WeAreTheMusicMakers/comments/3ajwe4/the_largest_midi_collection_on_the_internet/ )にある13万曲の中からGM, GS, XGのデータを探すスクリプトを作ってみました。
どうやって探すか?
GM, GS, XGのデータの場合、SysExでそのデバイスの設定をする情報が含まれている、ことが多いので(ちゃんとそれらのデバイス用にデータを作っていれば、ですが)midiデータの中からSysExをみて判断すればいい、と言う方針で作ってみました。
SysExとは?
System Exclusive(システム エクスクルーシブ)の略で、こちらのページ( https://www.g200kg.com/jp/docs/dic/systemexclusive.html )では以下のように説明されています。
MIDI のメッセージの種類のひとつであり、MIDIに共通な機能ではなく、その音源の機種固有のエフェクト等の機能を制御するために使用するメッセージである。
で、GM, GS, XGの何らかの機能を使っているMIDIデータであれば必ずそれに該当するSysExが含まれているはず、と言うことで各社のSysExを調べたところ、、、
MIDIデータ規格の種類 | System Exclusive |
---|---|
GM (General MIDI) | F0 7E xx 09 |
GS (ローランドのGM拡張) | F0 41 xx 42 |
XG (YamahaのGM拡張 | F0 43 xx 4C |
と言うのがSysExの先頭に含まれていればそれぞれのメーカーの企画だ、と言えそうです。上記の表は、F0がSysExの先頭を示しています。次がメーカーID、xxはデバイスID(機器固有のID)、最後がモデルIDになる(ローランドのGSの聞きならモデルID42のようなのでそれでGS音源を判別できる)ので、それを利用します。
スクリプトについて
- 実際のスクリプトはこちらのレポジトリ>https://github.com/dropcontrol/practice_mido
Pythonでmidiを扱うのにmido( https://mido.readthedocs.io/en/latest/# )と言うライブラリがあるので、それを使っています。それの習熟も兼ねてたのがレポジトリ名でバレバレですね。midoはちゃんとメンテナンスされている(大事)し、機能的にもいろいろできるので、midiのハンドリングにはもってこいだと思います。
GMMidiCheck.ipynb
と言うファイルがその実行結果になっています。書いてる時に友人に「.py で書けばCIでテストも回せていいですよ」と言われて、それもそうだな、、、と思って関数は全部midi_utill.py
に書いてあります(結局まだテストは書けてませんが、、、)。そのため.jpynbの各セルで
importlib.reload(midi_utill)
で、midi_utill.py
をリロードしています。で、この処理のポイントはMIDIファイルのSysExを比較しないとならないので、以下の関数でmidiを全部hexに変換した上で比較しています。
def getMidiHexData(midifilename):
import mido
midi = mido.MidiFile(midifilename)
MidiData = []
for i in range(len(midi.tracks)):
for msg in midi.tracks[i]:
# print(msg.hex())
MidiData.append(msg.hex())
return MidiData
他にも、ファイルのハンドリングや、ディレクトリのハンドリングなどいろいろ勉強になったのですがそれはPython自体の話なので、割愛しますので興味のある人はスクリプトを読んでみてください。
ちなみにGMMidiCheck.ipynb
の中で変数として下記の二つをよしなに指定してください。
- midiFileDir ... 判定したいMIDIファイルが入っているディレクトリ。ここに親ディレクトリを指定すれば、再帰的に全ての.midもしくは.MIDのファイルパスを取得します。
- GMMidiFileDir ... 判定してGM/GS/XGだと思われるSysEXが含まれているMIDIファイルをここに指定したディレクトリにコピーします。ディレクトリがなければ作成します。ファイル名が重複した場合は上書きされます。
一応redditのデータがGMMidiCheck.ipynb
と同じディレクトリにあることを想定しています。同じく、GM準拠のデータだと判断されたデータも同じところにディレクトリを作って書き出すことを想定しています。
結果はどうなった?
13万曲の中で(あくまでこのスクリプトで)「GM, GS, XGのデータのようだ」と引っかかったのは33000曲でした。
これだけあれば機械学習の学習元データとしては充分ですよね。しかもGMだと音色情報が公開されているので、「ドラムやパーカッション」「単音楽器」「複音楽器」などをトラックから抜き出すことも可能です(しかもそれはGM準拠なのでコントロールチェンジの情報で確実に抜き出せる、はず。きっと)。
ちなみに13万曲調べるのに大体5時間位かかりますのでご利用は計画的に。