Pygame 读取 MIDI 输入
Posted
技术标签:
【中文标题】Pygame 读取 MIDI 输入【英文标题】:Pygame read MIDI input 【发布时间】:2020-11-13 09:26:18 【问题描述】:我参考了Pygame MIDI documentation 和this code 来尝试让MIDI 输入工作。 MIDI 接口 (Avid Eleven Rack) 在我的音频软件 (Pro Tools) 中接收来自我的 MIDI 控制器的 MIDI 数据。但是,使用 Pygame,我似乎根本无法阅读任何信息。
源代码
import pygame
from pygame.locals import *
from pygame import midi
class MidiInput():
def __init__(self):
# variables
self.elevenRackInID = 2
# init methods
pygame.init()
pygame.midi.init()
self.midiInput = pygame.midi.Input(self.elevenRackInID, 100)
def run(self):
# print(pygame.midi.Input(3, 100))
# for i in range(10):
# print(pygame.midi.get_device_info(i), i)
self.read = self.midiInput.read(100)
# self.convert = pygame.midi.midis2events(self.read, self.elevenRackInID)
print(self.read)
test = MidiInput()
while True:
test.run()
唯一打印到控制台的是空方括号:
[]
附加信息
我刚刚再次检查:输入的 ID 是正确的,它实际上是一个输入。
“self.midiInput.poll()”返回 False。所以根据 Pygame 文档,没有数据进来。
您可以在下面看到数据、投票和设备信息:
data: [] || poll: False || device info: (b'MMSystem', b'Eleven Rack', 1, 0, 1)
根据 Pygame 列出我所有的 MIDI 设备(带索引):
(b'MMSystem', b'Microsoft MIDI Mapper', 0, 1, 0) 0
(b'MMSystem', b'External', 1, 0, 0) 1
(b'MMSystem', b'Eleven Rack', 1, 0, 1) 2
(b'MMSystem', b'Maschine Mikro MK2 In', 1, 0, 0) 3
(b'MMSystem', b'Microsoft GS Wavetable Synth', 0, 1, 0) 4
(b'MMSystem', b'External', 0, 1, 0) 5
(b'MMSystem', b'Eleven Rack', 0, 1, 0) 6
(b'MMSystem', b'Maschine Mikro MK2 Out', 0, 1, 0) 7
非常感谢任何帮助或建议!
【问题讨论】:
【参考方案1】:我在另一个论坛上得到了答案。事实证明,有一个示例文件显示了如何使代码工作。 因此,如果其他人偶然发现了这个问题,这里是示例代码的有用部分:
import sys
import os
import pygame as pg
import pygame.midi
def print_device_info():
pygame.midi.init()
_print_device_info()
pygame.midi.quit()
def _print_device_info():
for i in range(pygame.midi.get_count()):
r = pygame.midi.get_device_info(i)
(interf, name, input, output, opened) = r
in_out = ""
if input:
in_out = "(input)"
if output:
in_out = "(output)"
print(
"%2i: interface :%s:, name :%s:, opened :%s: %s"
% (i, interf, name, opened, in_out)
)
def input_main(device_id=None):
pg.init()
pg.fastevent.init()
event_get = pg.fastevent.get
event_post = pg.fastevent.post
pygame.midi.init()
_print_device_info()
if device_id is None:
input_id = pygame.midi.get_default_input_id()
else:
input_id = device_id
print("using input_id :%s:" % input_id)
i = pygame.midi.Input(input_id)
pg.display.set_mode((1, 1))
going = True
while going:
events = event_get()
for e in events:
if e.type in [pg.QUIT]:
going = False
if e.type in [pg.KEYDOWN]:
going = False
if e.type in [pygame.midi.MIDIIN]:
print(e)
if i.poll():
midi_events = i.read(10)
# convert them into pygame events.
midi_evs = pygame.midi.midis2events(midi_events, i.device_id)
for m_e in midi_evs:
event_post(m_e)
del i
pygame.midi.quit()
您可以在此目录中自己找到该文件:
C:\Users\myUser\AppData\Roaming\Python\Python37\site-packages\pygame\examples\midi.py
用您的 Win 用户名替换 'myUser'
。此外,'Python37'
可能因您安装的 Python 版本而异。
【讨论】:
【参考方案2】:我不相信 Leonhard W 下面发布的代码是可用的:pygame.midi poll() 方法和 pygame.midi read() 方法都没有阻塞。结果是 CPU 消耗达到顶峰 (~50%)。
当然,在实践中,读取 MIDI 事件的代码将在单独的线程中运行,尽管这对 CPU 消耗没有帮助。
针对其他地方的另一个非常有用的评论,我查看了 Mido 库 (https://mido.readthedocs.io/en/latest/index.html#)。这提供了阻塞读取方法,只需几行代码,我就可以从 MIDI 控制器键盘查找消息并将它们传递给 MIDI 合成器。
import mido
names = mido.get_input_names()
print(names)
out_port = mido.open_output()
with mido.open_input(names[0]) as inport:
for msg in inport:
out_port.send(msg)
唯一的缺点是我在敲击琴键和听到音符之间会有明显的延迟(可能是 1/4 秒)。哦,好吧,向上和向上。
【讨论】:
以上是关于Pygame 读取 MIDI 输入的主要内容,如果未能解决你的问题,请参考以下文章