電波ビーチ

☆(ゝω・)v

pythonでMIDI信号を受信する

あらすじ

MBPにMidiコントローラーを2つつなげてマッピングしていたら、チャンネルやノートがかぶってしまい、どちらからも操作可能になってしまう事態が発生しました。こういうやつの取扱はProcessingと相場が決まっています。で、The MidiBusなるライブラリを使ってみたのですが…スライダーの値は取れるのですがパッドとフェーダーが反応しない!!という問題が・・・

異なる信号を割り振るとかをやりたかったわけではなく、とりあえずいじっている機器とその信号だけ表示できればよかったのでこの問題については一切調べてません。既にブラウザでMidiできる時代ですし、Midiのことはまったく知りませんが、自分でもなんとかできるんじゃね?と思い、ちょっと調べてみることにしました。

rtmidi2

ちなみに当然フルスクラッチは自分には不可能なことがわかりきっているのでふつうにライブラリを使います。ググるとrtmidi2とかいうモジュールを使えばいいそうです。唯一の日本語情報がQiitaにありました。

qiita.com

ということで気軽にかまえていたのですが、適当にコピペしただけでは動きませんでした・・・。どうやらわたしの場合、複数の機器をつなげていたせいでしょう。

とりあえずソースを眺めてみたのですが、

github.com

なんか見たことない形式でした。たぶんこれが悪名高いCythonとうやつなのでしょう、意味不明でした。READMEも「わかっているひと」向けっぽいです。少なくともわたしにはなにがなにやら、でした。


rtmidi2.pyxなるファイルが中核っぽいので嫌々みてみながら試行錯誤して、なんとなくほしい情報は取れるようになったので置いておきます。ちなみにこの水平線のあいだに10時間くらいかかりました。あと自分でもなんでこれでいいのかさっぱりわからん代物なのでたぶんマネないほうがいいと思います。。がんばったから痕跡でも残しておきたいという思いです。

import rtmidi2, time

midi_in = rtmidi2.MidiInMulti().open_ports("*")
print(midi_in.ports)
print(rtmidi2.get_in_ports())

deviceID, Val, vel = 0, [], 0

def callback_with_source(src, msg, time):
    global deviceID, Val, vel
    deviceID, Val, vel = src, msg, time

midi_in.set_callback(callback_with_source, src_as_string=False)

i = 0
print("start")
while True:
    time.sleep(0.05)
    if len(Val) is not 0:
        i+=1
        print(deviceID, Val, vel, flush=True)
        time.sleep(0.01)
    deviceID, Val, vel = 0, [], 0
    if i>100:    #とりあえず20回分だけテスト
        break
print("end")

ちなみにprint()のflushオプションなんて初めて知りました。ある意味収穫はあったといえましょう(と、必死に自己肯定)