MidiDevice.Infoオブジェクトを取得することができれば、MidiSystemクラスのgetMidiDevice()メソッドから対象のMIDIデバイスを取得できます。

MidiSystem クラス getMidiDevice() メソッド

public static MidiDevice getMidiDevice(MidiDevice.Info info)
                throws MidiUnavailableException

このメソッドは、infoに指定されたMidiDevice.Infoが表すMIDIデバイスを返します。MIDI デバイスはjavax.sound.midi.MidiDeviceインタフェースによって抽象化されています。開発者は、MIDIデバイスの実体を意識する必要はなく、すべてのMIDIデバイスはMidiDeviceインタフェースとして操作できます。

MidiSystem クラス getMidiDevice() メソッド

public interface MidiDevice

MidiDeviceインタフェースは、すべてのMIDIデバイスが実装するインタフェースです。これは、音源だけではなくMIDIポートなども含まれます。MidiDeviceを取得できたら、open()メソッドでデバイスを開き、必要なリソースを割り当てる必要があります。デバイスが開かれていない場合、Receiverなどからデバイスを操作することはできません。

MidiDevice インタフェース open() メソッド

void open() throws MidiUnavailableException

開いたデバイスは、不要になった時点でclose()メソッドを呼び出してリソースを解放しなければなりません。

MidiDevice インタフェース close() メソッド

void close()

MidiDeviceオブジェクトが表しているMIDIデバイスにMIDIメッセージを送信するには、やはりReceiverインタフェースのオブジェクトを必要としてます。MidiDeviceからReceiverを取得するには、getReceiver()メソッドを使います。

MidiDeviceインタフェース getReceiver()メソッド

Receiver getReceiver() throws MidiUnavailableException

これで、システムにインストールされているMIDIデバイスの中から任意のデバイスを選択し、MIDIメッセージを送信できます。これまではデフォルトのMIDIデバイスにMIDIメッセージを送信していましたが、異なる音源を使ってMIDIメッセージを再生できます。

サンプル08は、コンボボックスに選択可能なMIDIデバイスを列挙し、選択されているMIDIデバイスに16進数のMIDIメッセージを直接送信できるMIDIテスト用のプログラムです。たとえば、電子ピアノへのMIDI OUTポートに対してメッセージを送信すれば、このアプリケーションから電子ピアノを演奏することが可能です。ただし、Receiver機能を持たないデバイスを選択すると例外が発生するので注意してください。

サンプル08(MIDIデバイスを列挙し、選択したものに16進数のMIDIメッセージを送信できるようにする)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.sound.midi.*;

public class Test extends JFrame implements ActionListener {
    private static final String SELECT_COMMAND = "Select";
    private static final String SEND_COMMAND = "Send";

    private JComboBox deviceList;
    private JTextField messageTextField;
    private JButton sendButton;

    private MidiDevice device;
    private Receiver receiver;

    public Test() {
        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();

        deviceList = new JComboBox(devices);
        deviceList.setActionCommand(SELECT_COMMAND);
        deviceList.addActionListener(this);
        JPanel listPanel = new JPanel();
        listPanel.setLayout(new GridLayout(2, 1));
        listPanel.add(new JLabel("デバイスの選択:"));
        listPanel.add(deviceList);

        messageTextField = new JTextField("90 3C 7F");

        sendButton = new JButton("送信");
        sendButton.setActionCommand(SEND_COMMAND);
        sendButton.addActionListener(this);

        JPanel messagePanel = new JPanel();
        messagePanel.setLayout(new BorderLayout());
        messagePanel.add(new JLabel("メッセージ:"), BorderLayout.WEST);
        messagePanel.add(messageTextField, BorderLayout.CENTER);
        messagePanel.add(sendButton, BorderLayout.EAST);

        Container contentPane = getContentPane();
        contentPane.add(listPanel, BorderLayout.NORTH);
        contentPane.add(messagePanel, BorderLayout.SOUTH);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if (command.equals(SELECT_COMMAND)) {
            selectCommand();
        }
        else if (command.equals(SEND_COMMAND)) {
            sendCommand();
        }
    }

    public void selectCommand() {
        try {
            if (device != null) device.close();

            MidiDevice.Info deviceInfo = (MidiDevice.Info)deviceList.getSelectedItem();
            device = MidiSystem.getMidiDevice(deviceInfo);
            device.open();
            receiver = device.getReceiver();
        }
        catch(Exception err)
        {
            String msg = "例外が発生しました:\n" + err.toString();
            JOptionPane.showMessageDialog(this, msg);
        }
    }

    private void sendCommand() {
        if (receiver == null) {
            JOptionPane.showMessageDialog(this, "MIDI デバイスを選択してください");
            return;
        }

        String text = messageTextField.getText();
        text = text.trim();
        String[] midi = text.split(" ");
        if (midi.length != 3) {
            JOptionPane.showMessageDialog(this, "不正なメッセージです");
            return;
        }

        try {
            int status = Integer.parseInt(midi[0], 16);
            int data1 = Integer.parseInt(midi[1], 16);
            int data2 = Integer.parseInt(midi[2], 16);

            ShortMessage message = new ShortMessage();
            message.setMessage(status, data1, data2);
            receiver.send(message, -1);
        }
        catch(Exception err)
        {
            String msg = "例外が発生しました:\n" + err.toString();
            JOptionPane.showMessageDialog(this, msg);
        }
    }

    public static void main(String[] args) throws MidiUnavailableException {
        JFrame frame = new Test();
        frame.setSize(600, 400);
        frame.setVisible(true);
    }
}

実行結果

サンプル08の実行結果