This section shows how your program can learn what MIDI resources have been installed, and how to get access to the desired ones. After you've accessed and opened the devices, you can connect them to each other, as discussed later in Transmitting and Receiving MIDI Messages.
The role of the
MidiSystem
class in the Java Sound API's MIDI package is directly analogous to the role of
AudioSystem
in the sampled-audio package. MidiSystem
acts as a clearinghouse for accessing the installed MIDI resources.
You can query the MidiSystem
to learn what sorts of devices are installed, and then you can iterate over the available devices and obtain access to the desired ones. For example, an application program might start out by asking the MidiSystem
what synthesizers are available, and then display a list of them, from which the user can select one. A simpler application program might just use the system's default synthesizer.
The MidiSystem
class also provides methods for translating between MIDI files and Sequences
. It can report the file format of a MIDI file and can write files of different types.
An application program can obtain the following resources from the
MidiSystem
:
A typical MIDI application program that uses the Java Sound API begins by obtaining the devices it needs, which can consist of one or more sequencers, synthesizers, input ports, or output ports.
There is a default synthesizer device, a default sequencer device, a default transmitting device, and a default receiving device. The latter two devices normally represent the MIDI input and output ports, respectively, if there are any available on the system. (It's easy to get confused about the directionality here. Think of the ports' transmission or reception in relation to the software, not in relation to any external physical devices connected to the physical ports. A MIDI input port transmits data from an external device to a Java Sound API Receiver
, and likewise a MIDI output port receives data from a software object and relays the data to an external device.)
A simple application program might just use the default instead of exploring all the installed devices. The MidiSystem
class includes the following methods for retrieving default resources:
static Sequencer getSequencer() static Synthesizer getSynthesizer() static Receiver getReceiver() static Transmitter getTransmitter()
The first two of these methods obtain the system's default sequencing and synthesis resources, which either represent physical devices or are implemented wholly in software. The getReceiver
method obtains a Receiver
object that takes MIDI messages sent to it and relays them to the default receiving device. Similarly, the getTransmitter method obtains a Transmitter object that can send MIDI messages to some receiver on behalf of the default transmitting device.
Instead of using the default devices, a more thorough approach is to select the desired devices from the full set of devices that are installed on the system. An application program can select the desired devices programmatically, or it can display a list of available devices and let the user select which ones to use. The MidiSystem
class provides a method for learning which devices are installed, and a corresponding method to obtain a device of a given type.
Here is the method for learning about the installed devices:
static MidiDevice.Info[] getMidiDeviceInfo()
As you can see, it returns an array of information objects.
Each of these returned MidiDevice.Info
objects identifies
one type of sequencer, synthesizer, port, or other device that is installed.
(Usually a system has at most one instance of a given type.
For example, a given model of synthesizer from a certain vendor will
be installed only once.) The MidiDevice.Info
includes
the following strings to describe the device:
However, to use the strings programmatically to select a device (as opposed to displaying the strings to the user), you need to know in advance what they might be. The company that provides each device should include this information in its documentation. An application program that requires or prefers a particular device can use this information to locate that device. This approach has the drawback of limiting the program to device implementations that it knows about in advance.
Another, more general, approach is to go ahead and iterate over theMidiDevice.Info
objects, obtaining each corresponding device, and determining programmatically whether it's suitable to use (or at least suitable to include in a list from which the user can choose). The next section describes how to do this.
Once an appropriate device's info object is found, the application program invokes the following MidiSystem
method to obtain the corresponding device itself:
static MidiDevice getMidiDevice(MidiDevice.Info info)
You can use this method if you've already found the info object describing the device you need. However, if you can't interpret the info objects returned by getMidiDeviceInfo
to determine which device you need, and if you don't want to display information about all the devices to the user, you might be able to do the following instead: Iterate over all the MidiDevice.Info
objects returned by getMidiDeviceInfo
, get the corresponding devices using the method above, and test each device to see whether it's suitable. In other words, you can query each device for its class and its capabilities before including it in the list that you display to the user, or as a way to decide upon a device programmatically without involving the user. For example, if your program needs a synthesizer, you can obtain each of the installed devices, see which are instances of classes that implement the Synthesizer
interface, and then display them in a list from which the user can choose one, as follows:
// 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.
As another example, you might choose a device programmatically, without involving the user. Let's suppose you want to obtain the synthesizer that can play the most notes simultaneously. You iterate over all the MidiDevice.Info objects, as above, but after determining that a device is a synthesizer, you query its capabilities by invoking the getMaxPolyphony
method of Synthesizer
. You reserve the synthesizer that has the greatest polyphony, as described in the next section. Even though you're not asking the user to choose a synthesizer, you might still display strings from the chosen MidiDevice.Info
object, just for the user's information.
The previous section showed how to get an installed device. However, a device might be installed but unavailable. For example, another application program might have exclusive use of it. To actually reserve a device for your program, you need to use the MidiDevice
method open
:
if (!(device.isOpen())) { try { device.open(); } catch (MidiUnavailableException e) { // Handle or throw exception... } }
Once you've accessed a device and reserved it by opening it, you'll probably want to connect it to one or more other devices to let MIDI data flow between them. This procedure is described in later in Transmitting and Receiving MIDI Messages.
When done with a device, you release it for other programs' use by invoking the close
method of MidiDevice
.