LoginSignup
2
1

More than 3 years have passed since last update.

大量のMIDIからGeneral MIDIデータを検出する

Last updated at Posted at 2020-11-06

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音源を判別できる)ので、それを利用します。

スクリプトについて

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時間位かかりますのでご利用は計画的に。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1