使用 Java 将 MIDI 音符发送到虚拟端口

Send MIDI note to virtual port with Java

提问人:Jos 提问时间:3/2/2023 更新时间:3/2/2023 访问量:80

问:

我想使用 Java 将 MIDI 音符发送到虚拟端口。要发送 MIDI 音符中间 C (60),我这样做:

public static void main(String[] main) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException {
    final MidiDevice.Info[] midiDeviceInfo = MidiSystem.getMidiDeviceInfo();
    for (MidiDevice.Info info : midiDeviceInfo) {
        System.out.println(info.getName());
    }

    MidiDevice.Info midiInfo = Arrays.stream(midiDeviceInfo)
            .filter(midiDefInfo -> main[0].equalsIgnoreCase(midiDefInfo.getName()))
            .findFirst().orElseThrow();

    final MidiDevice midiDevice = MidiSystem.getMidiDevice(midiInfo);
    midiDevice.open();
    Receiver receiver = midiDevice.getReceiver();
    final ShortMessage messageOn = new ShortMessage();
    final ShortMessage messageOff = new ShortMessage();
    messageOn.setMessage(ShortMessage.NOTE_ON, 1, 60, 112);
    messageOff.setMessage(ShortMessage.NOTE_OFF, 1, 60, 0);

    receiver.send(messageOn, -1);
    Thread.sleep(1000L);
    receiver.send(messageOff, -1);
}

使用MacOS的MIDI-studio,我创建了“MyVirtualPort”:

enter image description here

运行程序时,它会打印可用的设备:

Gervill
Real Time Sequencer
MyVirtualPort
MyVirtualPort

当我将“Gervill”作为参数传递时,我从扬声器中听到中间 C 1 秒钟。选择第二个“MyVirtualPort”时,会抛出 MIDI IN 不可用的异常。选择第一个“MyVirtualPort”时,程序运行良好,似乎发送了消息。但是,我在虚拟端口上没有看到任何活动。

我尝试使用 loopMidi (https://www.tobias-erichsen.de/software/loopmidi.html) 在 Windows 上运行该程序,但发生了同样的事情:程序运行良好并且似乎正确发送消息,但在虚拟设备上没有任何反应。将其设置为默认值也可以在 Windows 上成功播放中间 C。

我在这里错过了什么?我是MIDI的新手,所以这完全有可能是一件微不足道的事情。

Java MIDI JavaSound

评论

0赞 CL. 3/3/2023
Gervill测试证明您的程序可以正常工作。这似乎是 MyVirtualPort 的问题。
0赞 Jos 3/6/2023
谢谢@CL。loopMidi 在从流卡座发送时会收到一个 midi 音符,因此该音符运行良好。它不会从我的程序中接收 midi,所以这里一定有一些不同的东西。
0赞 jjazzboss 3/8/2023
您是否将软件合成器连接到虚拟端口的另一端?如果没有,则虚拟端口可能只是丢弃您的消息。您的代码看起来没问题。我在 Java 中使用类似的方法,在 Windows 上使用 loopMidi(或在 linux 上使用 virmidi),它有效。同样在第一个打印循环中,使用 MidiDevice.getMaxReceivers() 检测输出 MidiDevices。
0赞 Jos 3/9/2023
谢谢@jjazzboss。在 Windows 上,我尝试使用相同的 loopMidi 通道连接到 ableton live。也许我做错了,但 stream deck 能够使用该循环 Midi 通道将 midi 音符发送到 ableton 现场。在我的 mac 上,当将 MidiSystem.getMidiDevice(info).getMaxReceivers() 添加到打印循环时,它为前 1 个打印 -3,为最后一个打印 0。

答: 暂无答案