投稿日: Jun 05, 2019 4:42:22 AM
ポケットミク(NSX-39)の回路系の話が出てきてなんとなくやりかけだったことを思い出したり。
ついでに最近ちらちらとPyGameのmidiがトラブったみたいなポストも見かける(英語)のでちょうどいい。両方まとめてやっちゃおう。
midiは正直あんまり使わないのでpygのサポートモジュールみたいな感じで。
接続順で順番が変わってしまうデバイスの番号が煩わしいなーと思っていたのでデバイス名で接続出来るようにした。
pygmidi.py
#!/usr/bin/python3
import pygame.midi as midi
class midiObj:
def __init__(self):
midi.init()
self.midi = midi
self.devices = []
for i in range(midi.get_count()):
self.devices.append(self.decodeInfo(i, midi.get_device_info(i)))
def quit(self):
midi.quit()
def decodeInfo(self, devNo, inf):
if inf[2] == 1:
direction = "INPUT"
elif inf[3] == 1:
direction = "OUTPUT"
else:
direction = "???"
if inf[4] == 1:
opened = "OPEN"
else:
opened = "CLOSE"
return {"device":devNo, "interface":inf[0].decode(), "name":inf[1].decode(), "direction":direction, "open":opened}
def midiDevices(self):
return self.devices
def openByName(self, name, direction ):
for dev in self.devices:
if (dev["name"] == name) & (dev["direction"] == direction):
if direction == "OUTPUT":
self.midiDevice = midi.Output(dev["device"])
if direction == "INPUT":
self.midiDevice = midi.Input(dev["device"])
return self.midiDevice
def openById(self, id):
dev = self.devices[id]
if dev["direction"] == "OUTPUT":
self.midiDevice = midi.Output(dev["device"])
if dev["direction"] == "INPUT":
self.midiDevice = midi.Input(dev["device"])
return self.midiDevice
def event(self):
if self.midiDevice.poll():
data = []
for me in self.midiDevice.read(512):
d, ts = me
data.append(d)
return data
else:
return 0
名前でデバイスオープン出来るようにしたり何番目が何なの?問題をどうにかするためにディクショナリにしてデバイス情報返すとかいろいろ。
NSX-39を繋いで実験する。
#!/usr/bin/python3
import pyg
import pygmidi
import time
pyg.begin((200,200))
m = pygmidi.midiObj()
m2 = pygmidi.midiObj()
print( m.midiDevices() )
midiout = m.openByName("NSX-39 MIDI 1", "OUTPUT")
midiin = m2.openByName("NSX-39 MIDI 1", "INPUT")
while pyg._running:
pyg.process()
data = m2.event()
if data != 0:
for d in data:
channel = d[0] & 0x0f
if (d[0] & 0xf0) == 0x90:
print("note on")
print("Channel:",channel)
print("Note No:", d[1])
print("Velocity:", d[2])
if (d[0] & 0xf0) == 0x80:
print("note off")
"""
midiout.note_on(60,100,1)
time.sleep(2)
midiout.note_off(60,0,1)
"""
m2.quit()
m.quit()
pyg.quit()
楽に使えるようにと頑張ったものの midi inについてはこれくらいのコードは書かないとだめな感じになってしまった。
ポリシーとしてフレームワーク使うことで制限が出来るのはアリえないと思ってるので。
よくあるmidi関連だとsysexは扱えないよとかね。ああいう感じにはしたくなかった。
midi outに関してはもともとPyGame.midiにある命令で事足りるのでそのまま使う感じかなー。
で、PyGameのmidiの問題って何だったんだろう…。普通に動くようだがー。
一応、位置づけとしてはpygのサポート的なモノなんだけどpygと一切絡んでいないので単体でも使える。はず。多分。