You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java发送MIDI音符至虚拟端口无响应问题排查

问题描述

我想用Java向虚拟MIDI端口发送中央C(音符编号60)的MIDI音符,编写了如下代码:

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'的虚拟端口;在Windows上使用loopMidi工具创建虚拟端口。运行程序时,控制台输出可用设备列表:

Gervill
Real Time Sequencer
MyVirtualPort
MyVirtualPort

运行情况:

  • 传入参数“Gervill”时,可正常从扬声器听到1秒的中央C音符;
  • 选择第二个“MyVirtualPort”时,抛出“MIDI IN不可用”异常;
  • 选择第一个“MyVirtualPort”时,程序正常运行且看似发送了消息,但虚拟端口无任何活动反馈;
  • Windows平台下也出现同样情况:程序运行正常但虚拟设备无响应,切换至默认设备则可正常发声。

作为MIDI新手,想知道遗漏了什么关键步骤?


解决思路与关键步骤

核心问题:虚拟MIDI端口的成对特性

虚拟MIDI端口会成对创建:一个是输出端口(MIDI OUT,用于发送消息),一个是输入端口(MIDI IN,用于接收消息)。你看到的两个"MyVirtualPort"就是这一对设备。

异常与无反馈的原因

  1. 选择第二个端口报错:第二个"MyVirtualPort"是输入端口,仅支持接收MIDI消息,无法调用getReceiver()获取发送消息的接收器,因此抛出"MIDI IN不可用"异常。
  2. 选择第一个端口无反馈:第一个是输出端口,代码确实发送了MIDI消息,但输出端口需要连接到监听该端口的输入设备/程序才能看到反馈——你只是发送了消息,但没有任何程序在接收这个端口的输入,所以看不到活动。

关键修正步骤

  • 区分设备类型:遍历MIDI设备时,增加类型判断,明确哪个是输出端口:
    修改遍历代码如下:

    for (MidiDevice.Info info : midiDeviceInfo) {
        MidiDevice device = MidiSystem.getMidiDevice(info);
        System.out.printf("%s - 可发送消息(输出端口):%b,可接收消息(输入端口):%b%n", 
            info.getName(), device.isReceiver(), device.isTransmitter());
    }
    

    选择可发送消息(输出端口)为true的那个"MyVirtualPort"。

  • 配对监听程序:

    • MacOS:打开MIDI Studio,将"MyVirtualPort"的输出端口拖拽到另一个设备的输入端口上(比如自己的输入端口,或者DAW软件的MIDI输入);
    • Windows:使用loopMidi创建端口后,打开支持MIDI输入的程序(比如MIDI监视器、FL Studio等),将该虚拟端口设置为程序的MIDI输入源,这样就能接收到你发送的MIDI消息。
  • 补充资源关闭:程序结束前添加资源释放代码,避免资源泄漏:

    receiver.close();
    midiDevice.close();
    

内容的提问来源于stack exchange,提问作者Jos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 18:03:23