访问 MIDI 系统资源

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

本节说明程序如何了解已安装了哪些 MIDI 资源,以及如何访问所需的 MIDI 资源。访问并打开设备后,可以将它们彼此连接,如稍后在传输和接收 MIDI 信息中讨论的。

MidiSystem 类

Java Sound API 的 MIDI 包中MidiSystem类的角色直接与 sampled-audio 包中的AudioSystem相似。 MidiSystem充当访问已安装 MIDI 资源的票据交换所。

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

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

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

  • Sequencers

  • Synthesizers

  • 运行机(例如与 MIDIImporting 端口关联的运行机)

  • 接收器(例如与 MIDI 输出端口关联的接收器)

  • 来自标准 MIDI 文件的数据

  • 声音库文件中的数据

此页面重点介绍这些资源的前四种。其他的将在本教程的后面讨论。

获取默认设备

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

存在默认的合成器设备,默认的音序器设备,默认的发送设备和默认的接收设备。如果系统上有可用的设备,则后两个设备通常分别代表 MIDIImporting 和输出端口。 (这里容易混淆方向性.考虑与软件有关的端口发送或接收,而不是与连接到物理端口的任何外部物理设备有关的端口.MIDIImporting 端口从外部设备传输数据设备到 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包含以下字符串 以描述设备:

  • Name

  • Version number

  • 供应商(创建设备的公司)

  • 设备说明

您可以在用户interface中显示这些字符串,以使用户从设备列表中进行选择。

但是,要以编程方式使用字符串 来选择设备(与向用户显示字符串 相反),您需要事先知道它们可能是什么。提供每种设备的公司应在其文档中包含此信息。需要或偏爱特定设备的应用程序可以使用此信息来定位该设备。这种方法的缺点是将程序限制在它事先知道的设备实现上。

另一种更通用的方法是 continue 对MidiDevice.Info对象进行迭代,获取每个对应的设备,并以编程方式确定它是否适合使用(或至少适合包含在用户可以选择的列表中)。下一节将介绍如何执行此操作。

获取所需的设备

找到合适的设备的信息对象后,应用程序将调用以下MidiSystem方法来获取相应的设备本身:

static MidiDevice getMidiDevice(MidiDevice.Info info)

如果已经找到描述所需设备的信息对象,则可以使用此方法。但是,如果您无法解释getMidiDeviceInfo返回的信息对象来确定所需的设备,并且不想将所有设备的信息显示给用户,则可以执行以下操作:迭代在getMidiDeviceInfo返回的所有MidiDevice.Info对象上,使用上述方法获取相应的设备,并测试每个设备是否合适。换句话说,您可以在将每个设备包括在显示给用户的列表中之前,查询每个设备的类及其功能,或者作为一种以编程方式决定设备的方式而无需用户参与。例如,如果您的程序需要合成器,则可以获取每个已安装的设备,查看实现Synthesizerinterface的类的实例,然后将其显示在列表中,用户可以从中选择一个,如下所示:

// 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 对象,但是在确定设备是合成器之后,可以通过调用SynthesizergetMaxPolyphony方法来查询其功能。您将保留具有最大复音的合成器,如下一节所述。即使您没有要求用户选择合成器,您仍然可能会显示所选MidiDevice.Info对象中的字符串,仅用于用户信息。

Opening Devices

上一节显示了如何获取已安装的设备。但是,设备可能已安装但不可用。例如,另一个应用程序可能会专有使用它。要为程序实际保留设备,您需要使用MidiDevice方法open

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

访问设备并通过打开将其保留后,您可能需要将其连接到一个或多个其他设备,以使 MIDI 数据在它们之间流动。稍后在传输和接收 MIDI 信息中描述此过程。

使用完设备后,您可以通过调用MidiDeviceclose方法将其释放以供其他程序使用。