python mido MIDI包中使用MultiPort的问题

Posted

技术标签:

【中文标题】python mido MIDI包中使用MultiPort的问题【英文标题】:Problem with MultiPort use in python mido MIDI package 【发布时间】:2021-07-30 01:36:16 【问题描述】:

我正在开发一个在播放 MIDI 消息时自动保存它们的程序,并且在使用单个输入端口时一切都运行良好。 我想扩展为使用 2 或 3 个同时端口(该应用程序针对 VST 钢琴演奏者,有些将钢琴用作一个 MIDI 设备,将延音踏板用作另一个 USB 插槽中的第二个设备)。我能够使用两个单独的输入端口使其工作,然后使用 2 个 iter_pending() 循环。基本代码是这样的:

ports = mido.get_input_names()
port_A = mido.open_input(ports[0])
port_B = mido.open_input(ports[1])

for msg_A in port_A.iter_pending():
    ...
for msg_B in port_B.iter_pending():
    ...

这样做的问题是循环是顺序的。当我通过 2 个端口发送相同的 midi 消息进行测试时,通过 port_B 进入的事件会延迟几毫秒。

MIDO 包为此包含了一个不同类型的端口:mido.ports.MultiPort() 我的问题是我无法让它工作。

如果我尝试:

multi = mido.ports.MultiPort([port_A, port_B])
for msg in multi:
    print (msg)

按照 MIDO 文档中的建议,不打印任何味精...

我已经为multi中的端口做了各种语法组合,但似乎没有任何效果。

我在这里做错了什么?

【问题讨论】:

【参考方案1】:

你试过了吗:

open_ports = [portA, portB]

while True:
    for port in open_ports:
        do_whatever(port.poll())

或者让它异步:

portA = mido.open_input(ports[0], callback=do_whatever)
portB = mido.open_input(ports[1], callback=do_whatever)

while True:
    pass

在这两种情况下,do_whatever 都是一个函数,它接受一条消息作为参数,并对该消息执行您想要执行的任何操作。

【讨论】:

franklinscudder 的这个建议成功了。第一个建议(使用 port.poll() )效果很好。现在,通过 2 个设备发送的相同 MIDI 消息在完全相同的时间到达。不像使用 MultiPort 包装器那样语法优雅,但 MIDO 文档不是很有帮助(或者我不太擅长理解它)。我没有尝试过第二个建议(使用回调需要对我的原始代码进行重大更改)。第一个对我来说更简单。

以上是关于python mido MIDI包中使用MultiPort的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 mido 库的绝对 MIDI 刻度值

使用 Python Mido 库选择 GM MIDI Level 2 乐器

在 Python MIDI MIDO 读取/保存文件中转换时间/刻度

Mido - 如何从不同端口实时获取 midi 数据

如何将MIDO下的ticks_per_beat设置为一个新的MIDI文件?

将 midi 时间转换为小节和节拍