トップ «前の日記(2005-12-19 [月]) 最新 次の日記(2005-12-21 [水])» 編集

SewiGの日記

2004|01|04|05|06|07|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|

2005-12-20 [火] [長年日記]

[Java][Programming] JavaでSMF (3)

MIDIイベントの作成は前回登場したMidiEventを自分でいくらでも作ればいいだけです。

で、再生ですがこれがけっこう面倒です。方法はいくつかあります。

1. 独自に実装する

動的なデータ変更に対応できて便利なのですが、Win32 + JavaVM環境ではSystem#currentTimeMillisの性能が恐ろしく悪いのであまりオススメできません。とはいえ、J2SE 5.0になってからSystem#nanoTimeが使えるようになってかなり精度が良くなりました。もし独自実装にするにしても、以下のようにループさせるのではなくタイマを使用したほうが、楽で見やすくて良いと思われます。音色ですが、デフォルトではJava Sound Synthesizerで演奏されます。これはSoundbankを変更することでより豪華な音色に変更できますし、指定したMIDIデバイスにも送信できます。
→ソースコード (MIDIPlayer.java, Note.java)

以下にソースコードの要所を示しておきます。

int TPQN = 480;
int BPM = 120;
int TPS = TPQN * (BPM / 60);
long interval = 1000000000L / TPS;

long offset = System.nanoTime();
long startTime = offset;
long d;

for (;;) {
	while ((d = System.nanoTime()) - offset < interval) {
		try {
			NANOSECONDS.sleep(1L);
		} catch (InterruptedException e) {
		}
	}
	offset = d;
	// ここに割り込みが入ったときの処理を書く。
	// ちなみに、Tickとナノ秒の変換は以下のようにする。誤差は無視しています。
	// long t = (long)((double)TPS / 1000000000L * (d - startTime));
}

さらに1の方法でシーケンスをQuickTimeで鳴らしたソースコードです。それにしても、JavaでQuickTimeを扱った日本語の資料が少なすぎです。Windowsなら「C:\Program Files\QuickTime\QTSystem\QTJava.zip」をCLASSPATHに追加してください。
→ソースコード (QTMIDIPlayer.java, Note.java)

2. javax.sound.midi.Sequencerを使用する

これはすごく楽ですし、パフォーマンスも悪くないです。再生させると制御が戻ってこなくなるので再生用にThreadを作るといいでしょう。よほど細かい制御を行わないかぎりjavax.sound.midi.Sequencerで事足りると思います。
→ソースコード (SequencePlayer.java)

3. JMFを使用する

ほとんど2の方法と同様に使用できます。JMFは様々なメディアに対応していてとても汎用的です。ダウンロードはhttp://java.sun.com/products/java-media/jmf/
→ソースコード (JMFPlayer.java)

本日のTrackBacks(全1件) [TrackBack URL: http://sewig.jp/diary/tb.rb/20051220]
aaa hotel discounts missouri (2010-06-03 [木] 23:01)

aaa hotel discounts missouri

aaa hotel discounts missouri


Copyright © 2004-2008 SewiG All rights reserved.