MIDI シーケンスのグラフィカル表現を組み立てようとしています。シーケンスの実際の位置を反映して、シーケンスの再生時に垂直線がパネル上を水平に移動するようにしたいと思います。getTickPosition()
垂直線の位置を提供する ようなものを使用する必要があることはわかっています。
しかし、垂直線が自分自身を再描画することを認識できるように、これらのイベントを発生させるにはどうすればよいでしょうか? ティックが何らかの形でトリガーする特別なリスナーを作成しますか?
Timer
NN ミリ秒ごとに目盛りの位置をチェックして更新するSwing を確立します。
では、MidiSystem には組み込みのタイマーはありませんか?
確かにあります。しかし重要なのは、すべての GUI 更新が EDT で行われる必要があるということです。それらを Swing から呼び出すことによりTimer
、それらはそうです。また、MIDI タイマーは MIDI API/システムを使用するためのものであり、邪魔されずに何をするかを任せ、 Swing からチェックしたときに関連情報を報告しますTimer
。
また、UI コンポーネントの性質JProgressBar
上、この GUI の右上にある を参照してください。
Java Sound WIKIで見られるソースを、このアプローチの SSCCE に適合させました。
import javax.sound.midi.*;
import javax.swing.*;
import java.awt.event.*;
import java.net.URL;
class PlayMidi {
public static void main(String[] args) throws Exception {
URL url = new URL("http://pscode.org/media/EverLove.mid");
Sequence sequence = MidiSystem.getSequence(url);
final Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
sequencer.setSequence(sequence);
Runnable r = new Runnable() {
public void run() {
final JProgressBar progress = new JProgressBar(0,(int)sequencer.getMicrosecondLength());
ActionListener updateListener = new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
progress.setValue((int)sequencer.getMicrosecondPosition());
}
};
Timer timer = new Timer(40,updateListener);
sequencer.start();
timer.start();
JOptionPane.showMessageDialog(null, progress);
sequencer.close();
timer.stop();
}
};
SwingUtilities.invokeLater(r);
}
}
次のチュートリアルをよく見ていきます。
http://docs.oracle.com/javase/tutorial/sound/MIDI-seq-adv.html
役立つ可能性のあるものがいくつかあります。他のデバイスや特別なイベントリスナーと同期するためのツールです。以下(スレーブについて)は特に有望に見えます:
Sequencerには、Sequencer.SyncModeという内部クラスがあります。SyncModeオブジェクトは、MIDIシーケンサーの時間の概念をマスターまたはスレーブデバイスと同期させる方法の1つを表します。シーケンサーがマスターに同期されている場合、シーケンサーはマスターからの特定のMIDIメッセージに応じて現在の時刻を修正します。シーケンサーにスレーブがある場合、シーケンサーは同様にMIDIメッセージを送信してスレーブのタイミングを制御します。
再描画にトリガーを送信することが唯一の仕事である「MidiSlaveDevice」を作成する場合、目的のシナリオに対する解決策を得ることができます。念のために言っておきますが、私はまだこれを自分で行っていないので、うまくいくかどうかは完全にはわかりません。