# 访问 MIDI 系统资源

> 原文： [https://docs.oracle.com/javase/tutorial/sound/accessing-MIDI.html](https://docs.oracle.com/javase/tutorial/sound/accessing-MIDI.html)

Java Sound API 为 MIDI 系统配置提供了灵活的模型，就像配置采样音频系统一样。 Java Sound API 的实现本身可以提供不同种类的 MIDI 设备，其他的可以由服务提供商提供并由用户安装。您可以编写程序，以便对计算机上安装的特定 MIDI 设备做出一些假设。相反，程序可以利用 MIDI 系统的默认值，或者它可以允许用户从碰巧可用的任何设备中进行选择。

此部分显示您的程序如何了解已安装的 MIDI 资源，以及如何访问所需的资源。在您访问并打开设备后，您可以将它们相互连接，如后面[发送和接收 MIDI 信息](MIDI-messages.html)中所述。

## MidiSystem 类

[`MidiSystem`](https://docs.oracle.com/javase/8/docs/api/javax/sound/midi/MidiSystem.html) 类在 Java Sound API 的 MIDI 包中的作用直接类似于 [`AudioSystem`](https://docs.oracle.com/javase/8/docs/api/javax/sound/sampled/AudioSystem.html) 在采样音频包中的作用。 `MidiSystem`充当访问已安装的 MIDI 资源的交换所。

您可以查询`MidiSystem`以了解安装了哪些类型的设备，然后您可以遍历可用设备并获取对所需设备的访问权限。例如，应用程序可能首先询问`MidiSystem`哪些合成器可用，然后显示它们的列表，用户可以从中选择一个。一个更简单的应用程序可能只使用系统的默认合成器。

`MidiSystem`类还提供了在 MIDI 文件和`Sequences`之间进行转换的方法。它可以报告 MIDI 文件的文件格式，并可以写入不同类型的文件。

应用程序可以从`MidiSystem`获取以下资源：

*   排序器
*   合成
*   发射器（例如与 MIDI 输入端口相关的发射器）
*   接收器（例如与 MIDI 输出端口相关的接收器）
*   来自标准 MIDI 文件的数据
*   来自 soundbank 文件的数据

本页重点介绍这四种资源类型。其他内容将在本教程后面讨论。

## 获取默认设备

使用 Java Sound API 的典型 MIDI 应用程序首先获取所需的设备，它可以包含一个或多个音序器，合成器，输入端口或输出端口。

有默认合成器设备，默认音序器设备，默认发送设备和默认接收设备。如果系统上有任何可用设备，后两个设备通常分别代表 MIDI 输入和输出端口。 （很容易对此处的方向性感到困惑。想想端口与软件相关的传输或接收，而不是与连接到物理端口的任何外部物理设备有关.MIDI 输入端口 _ 传输 _ 从外部设备到 Java Sound API `Receiver`的数据，同样 MIDI 输出端口 _ 从软件对象接收 _ 数据并将数据中继到外部设备。）

一个简单的应用程序可能只使用默认值而不是浏览所有已安装的设备。 `MidiSystem`类包括以下用于检索默认资源的方法：

```
static Sequencer getSequencer()
static Synthesizer getSynthesizer()
static Receiver getReceiver()
static Transmitter getTransmitter()

```

这两种方法中的前两种获得系统的默认排序和综合资源，它们代表物理设备或完全用软件实现。 `getReceiver`方法获取`Receiver`对象，该对象接收发送给它的 MIDI 消息并将它们中继到默认接收设备。类似地，getTransmitter 方法获得一个 Transmitter 对象，该对象可以代表默认发送设备向某个接收器发送 MIDI 消息。

## 了解安装了哪些设备

更彻底的方法是从系统上安装的整套设备中选择所需的设备，而不是使用默认设备。应用程序可以以编程方式选择所需的设备，或者它可以显示可用设备的列表，并让用户选择要使用的设备。 `MidiSystem`类提供了用于学习安装哪些设备的方法，以及用于获得给定类型的设备的相应方法。

以下是了解已安装设备的方法：

```
 tatic MidiDevice.Info[] getMidiDeviceInfo()

```

如您所见，它返回一组信息对象。这些返回的`MidiDevice.Info`对象中的每一个都标识一种类型的定序器，合成器，端口或其他已安装的设备。 （通常系统最多只有一个给定类型的实例。例如，某个供应商的给定合成器模型只安装一次。）`MidiDevice.Info`包含以下字符串来描述设备：

*   名称
*   版本号
*   供应商（创建设备的公司）
*   设备的描述

您可以在用户界面中显示这些字符串，以便用户从设备列表中进行选择。

但是，要以编程方式使用字符串来选择设备（而不是向用户显示字符串），您需要事先知道它们可能是什么。提供每个设备的公司应在其文档中包含此信息。需要或更喜欢特定设备的应用程序可以使用此信息来定位该设备。该方法具有将程序限制为其事先知道的设备实现的缺点。

另一种更通用的方法是继续并迭代`MidiDevice.Info`对象，获得每个相应的设备，并以编程方式确定它是否适合使用（或者至少适合包括在用户可以选择的列表中）。下一节将介绍如何执行此操作。

## 获取所需设备

找到适当设备的 info 对象后，应用程序将调用以下`MidiSystem`方法获取相应的设备本身：

```
static MidiDevice getMidiDevice(MidiDevice.Info info)

```

如果您已经找到描述所需设备的信息对象，则可以使用此方法。但是，如果您无法解释`getMidiDeviceInfo`返回的信息对象以确定您需要哪个设备，并且您不想向用户显示有关所有设备的信息，则可以执行以下操作：迭代`getMidiDeviceInfo`返回的所有`MidiDevice.Info`对象，使用上述方法获取相应的设备，并测试每个设备以查看它是否合适。换句话说，您可以在将每个设备包含在显示给用户的列表中之前查询每个设备的类及其功能，或者在不涉及用户的情况下以编程方式决定设备。例如，如果你的程序需要一个合成器，你可以获得每个已安装的设备，看看哪些是实现`Synthesizer`接口的类的实例，然后将它们显示在一个列表中，用户可以从中选择一个，如下所示：

```
// Obtain information about all the installed synthesizers.
Vector synthInfos;
MidiDevice device;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
for (int i = 0; i < infos.length; i++) {
    try {
        device = MidiSystem.getMidiDevice(infos[i]);
    } catch (MidiUnavailableException e) {
          // Handle or throw exception...
    }
    if (device instanceof Synthesizer) {
        synthInfos.add(infos[i]);
    }
}
// Now, display strings from synthInfos list in GUI.    

```

作为另一个例子，您可以以编程方式选择设备，而不涉及用户。假设你想要获得可以同时播放最多音符的合成器。如上所述，迭代所有 MidiDevice.Info 对象，但在确定设备是合成器之后，通过调用`Synthesizer`的`getMaxPolyphony`方法来查询其功能。您保留具有最大复音数的合成器，如下一节所述。即使您没有要求用户选择合成器，您仍然可以显示所选`MidiDevice.Info`对象的字符串，仅用于用户的信息。

## 打开设备

上一节介绍了如何安装已安装的设备。但是，可能安装了设备但不可用。例如，另一个应用程序可能会独占使用它。要为程序实际预留设备，需要使用`MidiDevice`方法`open`：

```
if (!(device.isOpen())) {
    try {
      device.open();
  } catch (MidiUnavailableException e) {
          // Handle or throw exception...
  }
}

```

一旦你访问了一个设备并通过打开它来保留它，你可能想要将它连接到一个或多个其他设备以让 MIDI 数据在它们之间流动。稍后在[发送和接收 MIDI 消息](MIDI-messages.html)中描述该过程。

完成设备后，通过调用`MidiDevice`的`close`方法释放它以供其他程序使用。