当前位置:首页 > 文章列表 > 文章 > java教程 > Java MidiSystem 怎样枚举可用的 MIDI 设备

Java MidiSystem 怎样枚举可用的 MIDI 设备

来源:17golang原创 2026-10-30 16:34:37 0浏览 收藏

我第一次写 Java MIDI 设备选择时,容易把“设备信息”与“设备实例”混为一谈。实际的枚举入口很简单:先调用 MidiSystem.getMidiDeviceInfo() 得到 MidiDevice.Info[],把每个信息对象展示给用户;确定目标后,再把它交给 MidiSystem.getMidiDevice(info)。这样既能先统计候选数量,也能在真正需要时再判断设备能力。

官方资料:https://docs.oracle.com/en/java/javase/25/docs/api/java.desktop/javax/sound/midi/MidiSystem.html

枚举 MIDI 设备不是直接遍历 MidiDevice 实例,而是先遍历 MidiDevice.Info 目录。返回数组长度为 0 时,表示当前 Java MIDI 系统没有可见设备;拿到信息对象后,才用 getMidiDevice 定位具体设备。

先把候选数量和设备信息分开

这篇文章采用三个可观察基线:候选设备数量、四项元数据是否完整、设备能提供的接收器与发送器上限。它们是 API 字段,不是我在某台机器上测出的固定结果,因此不会把“有几个设备”写成所有环境都一样的结论。

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;

public class MidiDeviceCatalog {
    public static void main(String[] args) {
        // 先取得信息目录,不在枚举阶段打开任何设备。
        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
        if (infos.length == 0) {
            // 空数组是环境结果,不能简单当作 API 调用失败。
            System.out.println("没有发现可用的 MIDI 设备");
            return;
        }

        // 每个 Info 代表一个可供 MidiSystem 定位的设备条目。
        for (int index = 0; index < infos.length; index++) {
            MidiDevice.Info info = infos[index];
            System.out.printf("[%d] %s%n", index, info.getName());
        }
    }
}
Java MidiSystem 枚举入口与 MidiDevice.Info 设备元数据的静态关系说明图
图1:静态说明图,查看 Java MIDI 枚举入口与设备元数据之间的关系。

这里的关键判断是 infos.length。如果它为零,应先检查操作系统是否安装了 MIDI 设备、驱动是否可用以及当前 Java 运行环境能否看到对应设备,而不是继续对空数组取下标。

读取 Info 的四项元数据

MidiDevice.Info 的职责是描述设备。名称适合做列表主标题,厂商便于区分同名设备,版本和描述用于辅助选择。把这些字段一并展示,往往比只打印一个名称更容易定位“选错设备”的问题。

for (MidiDevice.Info info : infos) {
    // 这些字段来自设备信息对象,不代表设备已经打开。
    String name = info.getName();
    String vendor = info.getVendor();
    String version = info.getVersion();
    String description = info.getDescription();

    // 组合成可记录的目录行,便于后续让用户选择。
    System.out.printf("%s | %s | %s | %s%n",
            name, vendor, version, description);
}

如果应用要保存用户选择,建议保存稳定的业务标识或让用户在启动时重新确认,而不要只依赖数组下标。设备插拔、驱动变化都可能让枚举顺序发生变化。

从 Info 定位 MidiDevice,再看能力

选择某条目录记录后,再调用 MidiSystem.getMidiDevice(info)。此时得到的是 MidiDevice 实例,可以读取设备信息和能力上限。正如第二张图所示,信息对象承担定位职责,设备实例承担能力查询职责,两者不是同一个层次。

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiUnavailableException;

static void printCapabilities(MidiDevice.Info info) {
    try {
        // 用用户选中的 Info 定位设备实例;资源不足时会抛出异常。
        MidiDevice device = MidiSystem.getMidiDevice(info);

        // -1 通常表示没有固定上限,不能当成“支持 -1 个”。
        System.out.printf("%s: receivers=%d, transmitters=%d%n",
                device.getDeviceInfo().getName(),
                device.getMaxReceivers(),
                device.getMaxTransmitters());
    } catch (MidiUnavailableException ex) {
        // 设备条目存在不等于此刻一定能取得设备资源。
        System.err.println("设备当前不可用:" + ex.getMessage());
    }
}
MidiDevice.Info 定位 MidiDevice 并连接能力查询与异常边界的静态关系说明图
图2:静态说明图,查看设备信息对象、设备实例与能力边界的关系。

这里不要把 getMaxReceivers() 或 getMaxTransmitters() 当成当前已占用数量;它们描述设备支持的最大连接能力,具体语义要以 MidiDevice 的接口约定为准。拿到实例后,如果后续调用会打开设备或取得接收器、发送器,还要设计对应的关闭责任。

三个边界决定枚举是否可用

我会把结果分成三种状态记录:第一,信息数组为空,说明当前环境没有可见候选;第二,信息对象存在但 getMidiDevice 抛出 MidiUnavailableException,说明设备资源在此刻不可取得;第三,设备存在但接收器或发送器能力不符合业务要求,此时应回到候选清单换设备,而不是把异常吞掉。

现象判断处理建议
infos.length == 0没有可见设备检查设备、驱动和运行环境
定位时抛出 MidiUnavailableException设备暂时不可取得记录原因并允许重试或换设备
能力上限不满足候选与业务不匹配按接收器/发送器要求重新筛选

因此,最小可靠流程就是“先枚举信息、再显示元数据、最后定位实例”。如果只是做设备选择页面,停在 MidiDevice.Info 层就够了;只有需要连接 MIDI 数据流时,才继续管理 MidiDevice 的打开和关闭。

相关问题

为什么不直接保存 MidiDevice 对象?

设备实例与资源状态有关,插拔或占用变化后可能失效。保存信息用于重新定位更适合启动时的设备选择。

为什么枚举结果为空却没有异常?

getMidiDeviceInfo() 返回空数组是“没有安装或没有被当前环境识别的设备”,与调用本身抛出资源异常是两种情况。

什么时候才需要打开设备?

仅展示设备目录时不需要打开;要取得接收器、发送器或进行实际 MIDI 通信时,再按生命周期打开并关闭相关资源。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
GitLab Secrets Manager 正式可用后密钥怎样继承项目权限GitLab Secrets Manager 正式可用后密钥怎样继承项目权限
上一篇
GitLab Secrets Manager 正式可用后密钥怎样继承项目权限
Python quopri 的 header 参数为什么改变下划线含义
下一篇
Python quopri 的 header 参数为什么改变下划线含义
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    797次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    786次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    874次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    841次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    675次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码