Summary

JSliderTimerを使用してMIDIファイルの現在再生位置の表示と更新を実行します。

Source Code Examples

ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL url = cl.getResource("example/Mozart_toruko_k.mid");
try {
  sequencer = MidiSystem.getSequencer();
  if (url != null) {
    sequencer.open();
    sequencer.setSequence(MidiSystem.getSequence(url));
    slider.setMaximum((int) sequencer.getTickLength());
  }
} catch (IOException | MidiUnavailableException | InvalidMidiDataException ex) {
  Logger.getGlobal().severe(ex::getMessage);
}

Timer timer = new Timer(50, e -> {
  if (!isMovingSlider && sequencer.isRunning()) {
    slider.setValue((int) sequencer.getTickPosition());
  }
});
timer.start();

slider.addHierarchyListener(e -> {
  boolean b = (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0;
  if (b && !e.getComponent().isDisplayable()) {
    if (sequencer != null) {
      sequencer.close();
    }
    timer.stop();
  }
});

slider.addChangeListener(e -> {
  if (slider.getValueIsAdjusting()) {
    isMovingSlider = true;
  } else if (isMovingSlider) {
    sequencer.setTickPosition(slider.getValue());
    isMovingSlider = false;
  }
});

JButton playButton = new JButton("Play");
playButton.setEnabled(url != null);
playButton.addActionListener(e -> {
  if (!sequencer.isRunning()) {
    sequencer.start();
  }
});
View in GitHub: Java, Kotlin

Description

  • JSlider:
    • JSlider#setMaximum( (int) sequencer#getTickLength() )MIDIトラックの長さをJSliderに設定
    • JSliderChangeListenerを追加し、つまみのドラッグでJSlider#setValue( (int) sequencer#getTickPosition() )を実行して再生位置を変更可能に設定
  • Timer:
    • Timer50msごとにJSlider#setValue( (int) sequencer#getTickPosition() )を実行し、再生位置を更新
  • JButton:
    • 再生ボタンクリックでSequencer#start()を実行し、MIDIファイルの演奏を開始
  • HierarchyListener:
    • JSliderHierarchyListenerを設定し、親JFrameが破棄されてJSliderが表示不可になると、再生の停止、MIDIデバイスの解放、内部スレッドの終了、Synthesizerの切断を行うためSequencer#close()を実行する

Reference

Comment