1 package camidion.chordhelper.midieditor;
3 import java.awt.Component;
4 import java.awt.event.MouseAdapter;
5 import java.awt.event.MouseEvent;
7 import javax.swing.Box;
8 import javax.swing.BoxLayout;
9 import javax.swing.JLabel;
10 import javax.swing.JPanel;
11 import javax.swing.JSpinner;
12 import javax.swing.SpinnerNumberModel;
14 import camidion.chordhelper.ButtonIcon;
15 import camidion.chordhelper.music.MIDISpec;
18 * テンポ選択(QPM: Quarter Per Minute)
20 public class TempoSelecter extends JPanel {
21 static final int DEFAULT_QPM = 120;
22 protected SpinnerNumberModel tempoSpinnerModel =
23 new SpinnerNumberModel(DEFAULT_QPM, 1, 999, 1);
24 private JLabel tempoLabel = new JLabel(
25 "=", new ButtonIcon(ButtonIcon.QUARTER_NOTE_ICON), JLabel.CENTER
27 setVerticalAlignment(JLabel.CENTER);
29 private JLabel tempoValueLabel = new JLabel(""+DEFAULT_QPM);
30 private JSpinner tempoSpinner = new JSpinner(tempoSpinnerModel);
31 public TempoSelecter() {
32 String tooltip = "Tempo in quatrers per minute - テンポ(1分あたりの四分音符の数)";
33 tempoSpinner.setToolTipText(tooltip);
34 tempoValueLabel.setToolTipText(tooltip);
35 setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
37 add(Box.createHorizontalStrut(5));
41 tempoLabel.addMouseListener(new MouseAdapter() {
43 public void mousePressed(MouseEvent e) {
44 Component obj = e.getComponent();
45 if(obj == tempoLabel && isEditable()) {
47 // Adjust tempo by interval time between two clicks (tapping)
49 long currentMicrosecond = System.nanoTime()/1000;
50 // midi_ch_selecter.noteOn( 9, 37, 100 );
51 long interval_us = currentMicrosecond - prevBeatMicrosecondPosition;
52 prevBeatMicrosecondPosition = currentMicrosecond;
53 if( interval_us < 2000000L /* Shorter than 2 sec only */ ) {
54 int tempo_in_bpm = (int)(240000000L / interval_us) >> 2; // n/4拍子の場合のみを想定
55 int old_tempo_in_bpm = getTempoInQpm();
56 setTempo( ( tempo_in_bpm + old_tempo_in_bpm * 2 ) / 3 );
62 private long prevBeatMicrosecondPosition = 0;
63 private boolean editable;
68 public boolean isEditable() { return editable; }
71 * @param editable 編集可能ならtrue
73 public void setEditable( boolean editable ) {
74 this.editable = editable;
75 tempoSpinner.setVisible( editable );
76 tempoValueLabel.setVisible( !editable );
78 // Copy spinner's value to label
79 tempoValueLabel.setText(
80 ""+tempoSpinnerModel.getNumber().intValue()
83 tempoLabel.setToolTipText(
85 "Tap rhythmically here to adjust tempo - ここをクリックしてリズムをとるとテンポを合わせられます"
91 * @return テンポ [BPM](QPM)
93 public int getTempoInQpm() {
94 return tempoSpinnerModel.getNumber().intValue();
97 * テンポをMIDIメタメッセージのバイト列として返します。
98 * @return MIDIメタメッセージのバイト列
100 public byte[] getTempoByteArray() {
101 return MIDISpec.qpmTempoToByteArray(getTempoInQpm());
105 * @param qpm BPM(QPM)の値
107 public void setTempo(int qpm) {
108 tempoSpinnerModel.setValue(new Integer(qpm));
109 tempoValueLabel.setText(""+qpm);
112 * MIDIメタメッセージのバイト列からテンポを設定します。
113 * @param msgdata MIDIメタメッセージのバイト列(null を指定した場合はデフォルトに戻る)
115 public void setTempo(byte msgdata[]) {
116 if( msgdata==null ) clear(); else setTempo(MIDISpec.byteArrayToQpmTempo(msgdata));
118 public void clear() { setTempo(DEFAULT_QPM); }