読者です 読者をやめる 読者になる 読者になる

The jonki

呼ばれて飛び出てじょじょじょじょーんき

【Unity】UnityでMIDIメッセージを受け取る

魔が差してKP3+を買ってしまいました。まぁエフェクターです。


よくVJとかでMIDI機器を多用してたりしますが、自分もそういうのがやりたくなったのでUnityでKP3+を使ってみます。MIDIを出力できる機器があればKP3+じゃなくでもよいです、もちろん。

必要要件

Unity 4 Pro(DLLを使います)

KORG USB-MIDI Driverのインストール

まずドライバのインストール

Unityで使えるMIDIプラグイン

Unity 入門(黄色本)でお馴染みの高橋 啓治郎さんが開発したMIDIプラグインを利用します。まずはサンプルアプリケーションを使わせてもらいます。

テスト

KP3+をPCについないでサンプルアプリケーションを起動してみると、MIDI ReceiverオブジェクトのInspectorにKP3+のログが!色々触るとデータを受信していることがわかります。なんと簡単なのでしょう。
Inspectorに出力されているメッセージは、MidiMessage構造体の中身を見るとどのように表示されているかわかります。

    public MidiMessage (ulong data)
    {
        source = (uint)(data & 0xffffffffUL); // 送信元ソース、複数の機器やポートがあればそれぞれでちがうはず
        status = (byte)((data >> 32) & 0xff); // MIDIステータス
        data1 = (byte)((data >> 40) & 0xff);  // MIDIメッセージID
        data2 = (byte)((data >> 48) & 0xff);  // data1のIDのデータ
    }

    public override string ToString ()
    {
        return string.Format ("s({0:X2}) d({1:X2},{2:X2}) from {3:X8}", status, data1, data2, source);
    }

MIDIのステータス一覧は下記参照

たとえば普段は下記のようにKP3+では表示されていました。これはタイミングクロック(F8)が送られている状態で、何もしていない状態と思って問題ないでしょう。

Incoming MIDI messages:
s(F8) d(00,00) from 022548E8
s(F8) d(00,00) from 022548E8
s(F8) d(00,00) from 022548E8
…

次にKP3+のパッドのX軸をなぞるとこんな感じになります。ステータスB0はコントロール・チェンジ、 d(0C, value)の0CはKP3+ではタッチ・パッドX方向を意味し、valueはXの値(0〜127)になります。

Incoming MIDI messages:
s(B0) d(0C,24) from 022548E8
s(B0) d(0C,37) from 022548E8
s(F8) d(00,00) from 022548E8
…

ちなみにKP3+の工場出荷時のMIDIメッセージの記載は下記参照。他にもタッチやスライダーなどありますね。啓治郎さんのプラグインは16進表示になっているので混乱しないように注意。

Touch pad X-axis Control change (#12) // 0C
Touch pad Y-axis Control change (#13) // 0D
Touch pad on/off Control change (#92) // 5C
LEVEL slider Control change (#93) // 5D

利用例

あとはどうとでも利用できます。たとえばサンプルを利用して、MidiMessageDistributorのSendMessage先であるParticleTriggerを参考に下記のようなSendMessage受信イベントを作ってみました。スライダーを動かしたときにオブジェクトを作成し、XとYのパッド操作でForceをオブジェクトに対して与えています。0x40を引いているのは0〜127を-64〜63にして、プラスマイナスを作りたかったからです。

    void OnNoteOn (MidiMessage midi) {
		if(midi.data1 == 0x5D) { // slider
			var clone = Instantiate(SphereObj, transform.position, transform.rotation) as GameObject;
			clone.transform.parent = gameObject.transform;
			Destroy(clone.gameObject, 3f);
		} else if(midi.data1 == 0x0C) { // x
			var data = midi.data2 - 0x40;
			foreach(Transform child in transform) {
				child.transform.rigidbody.AddForce(Vector3.right * data);
			}
		} else if(midi.data1 == 0x0D) { // y
			var data = midi.data2 - 0x40;
			foreach(Transform child in transform) {
				child.transform.rigidbody.AddForce(Vector3.up * data);
			}
		}
	}

最後に

コントローラとして使うのであればOSCのアプリとかを使えばよいので、今後はKP3+らしくエフェクトをかけたものをうまく混ぜあわせてUnityに食わせたいですね。
ちなみにもっと手軽にVJやりてぇ!と思う方はfuZeで利用されたというvj-kitを使うのもありだと思います。これで使われてるMIDI bridgeも啓治郎さん作。