#はじめに
前回の記事の続きです。
#概要
前回のMIDIファイル再生サンプルに、使用するMIDIシンセサイザー選択機能を実装します。
以下、実際の実行画面です。
[0] Gervill
[1] LoopBe Internal MIDI
[2] Microsoft MIDI Mapper
[3] CoolSoft MIDIMapper
[4] Microsoft GS Wavetable Synth
[5] VirtualMIDISynth #1
[6] LoopBe Internal MIDI
[7] Real Time Sequencer
使用するMIDIデバイスの番号を入力 >> 4
[Microsoft GS Wavetable Synth]を開いています...
MIDIファイルのパス >> sample.mid
再生中...
適当に文字列を入力すると終了します。
>>a
停止
ちなみに、
0番目の「Gervill」というデバイスがJavaのライブラリが提供するMIDIシンセサイザーです。
デフォルトでは、こちらのデバイスが指定されます。
今回使用している「Microsoft GS Wavetable Synth」は、Windowsで標準搭載されているシンセサイザーです。
#サンプルコード
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
public class SamplePlayer {
public static void main(String[] args) {
// MIDIデータを再生するハードウェア/ソフトウェア・デバイスのインスタンス。
Sequencer sequencer = null;
Scanner scanner = new Scanner(System.in);
try {
// Sequencerインスタンスを取得する。
sequencer = MidiSystem.getSequencer(false);
// デバイスを開き、リソースを獲得する。
sequencer.open();
// 使用可能なMIDIデバイスの一覧を取得する。
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
for (int i=0; i<infos.length; i++) {
String line = String.format("[%s] %s", i, infos[i].getName());
System.out.println(line);
}
System.out.println();
int index = 0;
while (true) {
// コンソール入力から使用するMIDIデバイスのインデックスを取得する。
System.out.print("使用するMIDIデバイスの番号を入力 >> ");
String str = scanner.next();
try {
index = Integer.parseInt(str);
}
catch (NumberFormatException nfe) {
continue;
}
break;
}
// システムに目的のデバイスを表すデバイス情報を持った、MIDIデバイスを要求する。
MidiDevice device = MidiSystem.getMidiDevice(infos[index]);
System.out.println("[" + device.getDeviceInfo().getName() + "]を開いています...");
// MIDIデバイスを開く。
if (device.isOpen() == false) {
device.open();
}
// シーケンサのMIDI OUTとMIDIデバイスのMIDI INを接続する。
Receiver receiver = device.getReceiver();
sequencer.getTransmitter().setReceiver(receiver);
}
catch (MidiUnavailableException e) {
e.printStackTrace();
}
System.out.println();
// コンソール入力からMIDIファイルのパスを取得する。
System.out.print("MIDIファイルのパス >> ");
String path = scanner.next();
try {
// MIDIファイルからMIDIデータ(Sequenceオブジェクト)を取得。
File file = new File(path);
Sequence sequence = MidiSystem.getSequence(file);
// 取得したMIDIデータをシーケンサに設定する。
sequencer.setSequence(sequence);
}
catch (InvalidMidiDataException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
// シーケンサー再生
sequencer.start();
System.out.println("再生中...");
// キー入力待ち
System.out.println("適当に文字列を入力すると終了します。");
System.out.print(">>");
scanner.next();
scanner.close();
// シーケンサー停止
sequencer.stop();
System.out.println("停止");
// シーケンサーを閉じ、使用していたリソース解放する。
sequencer.close();
}
}
#解説
###使用可能なデバイス情報一覧を取得
使用可能な全MIDIデバイス情報のオブジェクト配列を取得します。
// 使用可能なMIDIデバイスの一覧を取得する。
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
###デバイスのオブジェクト取得
取得したデバイス情報のオブジェクトを使用して、getMidiDeviceを呼び出すことにより、対応するデバイスを取得できます。
取得したデバイスで、openを呼び出すことで操作可能にします。
// システムに目的のデバイスを表すデバイス情報を持った、MIDIデバイスを要求する。
MidiDevice device = MidiSystem.getMidiDevice(infos[index]);
// MIDIデバイスを開く。
if (device.isOpen() == false) {
device.open();
}
###シーケンサーとデバイスを接続
MIDIデバイスのクラスが提供するインターフェースには、以下の2つがあります。
インターフェース名 | 概要 | 一般的に使用されているもの |
---|---|---|
Transmitter | MIDIデータの送信を行う。 | シーケンサー・MIDI入力機器等 |
Receiver | MIDIデータの受信を行う。 | シンセサイザー・MIDI出力機器 |
今回は、シーケンサのMIDI送信ポート(Transmitter)に、指定したMIDIデバイスのMIDI受信ポート(Receiver)を接続します。
// シーケンサのMIDI OUTとMIDIデバイスのMIDI INを接続する。
Receiver receiver = device.getReceiver();
sequencer.getTransmitter().setReceiver(receiver);
以上で、デバイスの接続は完了です。