- PR -

JavaSound での MIDI ファイルの再生について

1
投稿者投稿内容
べう
会議室デビュー日: 2004/01/23
投稿数: 17
投稿日時: 2004-02-11 11:25
j2se 1.4.2_03 for Windows にて javax.sound.midi.Sequencer を利用して MIDI ファイルを再生させようとしています。再生自体はできるのですが、指定した MIDI ポートでの再生が上手く行きません。恐らく Java で標準に接続されているソフトシンセが対象になってしまうようです。どうしたら MIDI ポートを指定できるでしょうか?

具体的には、Receiver を次のように取得し:

MidiDevice device = null;
Receiver receiver = null;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
for (int i = 0; i < infos.length; i++) {
if (infos[i].getName().equals("HOGE DEVICE")) {
device = MidiSystem.getMidiDevice(infos[i]);
device.open();
receiver = device.getReceiver();
break;
}
}

Sequencer を次のように取得し:

Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
Sequence sequence = MidiSystem.getSequence(new File("HOGE.mid"));
sequencer.setSequence(sequence);

Sequencer のトランスミッタとレシーバを接続します:

Transmitter transmitter = sequencer.getTransmitter();
transmitter.setReceiver(receiver);

いざ、再生すると

sequencer.start();

指定した Receiver で再生してくれないのです。途中で例外は発生していませんし、色々コールの順番を変えても結果は同じになってしまいます。Sequencer#getReceiver では指定した Receiver のオブジェクトがちゃんと入っています。
何か処理が抜けているでしょうか?

※ Sequencer を使用せずに Sequence から直接 MidiMessage を取り出して Receiver に send する場合は問題なく指定のポートに出力できています。ただその場合 java.util.Timer を使用してメッセージを処理することになりますが、ミリ秒単位では綺麗な再生ができません (MIDI 仕様ではマイクロ秒単位でメッセージを処理します)。
Tiger の System.nanoTime() は使ってみようとは思っていますが、CPU ループでは多分綺麗に処理できませんよね。
べう
会議室デビュー日: 2004/01/23
投稿数: 17
投稿日時: 2004-02-11 21:43
お尻の方の Tiger の話ですが、java.util.Timer の代りに java.util.concurrent.ScheduledExecutor だと、ナノ秒単位までのタイマーになりそうです。Tiger (for Windows) は通常の処理も少し速くなっている気がしました。
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2004-02-11 22:50
べうさん、こんにちは。

equalsは正確に一致しているでしょうか?

一度一覧を表示させて、それをプログラムに反映させてもいいのですが、
決め打ちではなく、メニュー方式で選択する方法もいいかと思います。
べう
会議室デビュー日: 2004/01/23
投稿数: 17
投稿日時: 2004-02-12 10:04
> 一度一覧を表示させて、それをプログラムに反映させてもいいのですが、
> 決め打ちではなく、メニュー方式で選択する方法もいいかと思います。

はい、無論両方試しております。
Receive#send もほぼ同じ形で試しており、指定したポートにデータが出力されていますので、ターゲットとなる Receiver を取得していることは確かです。
1

スキルアップ/キャリアアップ(JOB@IT)