如何通过客户端将原始MIDI字节写入Linux Midi?

如何通过客户端将原始MIDI字节写入Linux Midi?

命令行实用程序 midi 可用于将 MIDI 十六进制字节发送到 中标识的任何 alsa rawmidi 端口amidi -l。我有一个音乐软件(Organteq),它可以监视 Midi Through 中的任何消息。我想通过写入 Midi Through 来写入该软件。

不幸的是,该端口没有显示在 midi 上,因此我无法写入它。该端口确实显示在 aplaymidi 和 pmidi 上,两者都不支持原始字节,仅发送 midi 文件:

aplaymidi -l
 Port    Client name                      Port name
 14:0    Midi Through                     Midi Through Port-0
 20:0    CLASSIC ORGAN CMK3               CLASSIC ORGAN CMK3 CLASSIC ORGA.

在 aconnect 上也可见:

aconnect -l
client 0: 'System' [type=kernel]
    0 'Timer           '
        Connecting To: 144:0
    1 'Announce        '
        Connecting To: 144:0, 128:0
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
        Connecting To: 128:1
client 20: 'CLASSIC ORGAN CMK3' [type=kernel,card=1]
    0 'CLASSIC ORGAN CMK3 CLASSIC ORGA'
        Connecting To: 128:2
client 128: 'Organteq' [type=user,pid=2372]
    0 'announcements   '
        Connected From: 0:1
    1 'Midi Through Port-0'
        Connected From: 14:0
    2 'CLASSIC ORGAN CMK3 CLASSIC ORGA'
        Connected From: 20:0
client 144: 'PipeWire-System' [type=user,pid=1100]
    0 'input           '
        Connected From: 0:1, 0:0
client 145: 'PipeWire-RT-Event' [type=user,pid=1100]
    0 'input           '

那么,我该如何写入 1) 到客户端 14,或者甚至更好,2) 直接写入客户端 128?

答案1

根据我的询问,没有命令行实用程序。然而,使用 ALSA C 接口这是可能的。必须使用 打开 Linux ALSA 序列器snd_seq_open(),并使用 命名打开的句柄,然后使用该名称snd_seq_set_client_name创建一个端口(以允许其他 ALSA 客户端从该端口读取数据)。snd_seq_create_simple_port()SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ

此时,当程序运行时,使用 pmidi -l 或 aconnect -l 应该可以看到您的端口。

然后要写入您选择的 ALSA 端口,只需snd_seq_event_t为您的 MIDI 事件创建一个结构并填写相关信息(无论是通过手动分配字段还是使用如下宏函数),最后使用snd_seq_event_output().

snd_seq_event_t ev;
int err;
snd_seq_ev_clear(&ev); snd_seq_ev_set_direct(&ev); //direct passing mode (i.e. no queue)

snd_seq_ev_set_dest(&ev, 128, 1); //id and port number of destination. could also subscribe to this port and then use snd_seq_ev_set_subs to send to subscribers
snd_seq_ev_set_noteon(&ev, 0, 45, 127);  //channel, key number, velocity
if ((err = snd_seq_event_output(seq_handle, &ev)) < 0) {
    printf("send to sequencer failed \n"); return -1; }
snd_seq_drain_output(seq_handle); //call when nothing further to send

答案2

加载 snd-virmidi 模块 ( modprobe snd-virmidi)。这将创建一个带有多个原始 MIDI 设备的虚拟声卡,您也可以从 Organteq 访问这些设备。

相关内容