以前作った拍子を管理するクラスTimeSignは「何小節目の何拍目」かを入力すると「開始から何拍目」であることを返すように作られていました。入力の「小節」はint型、入出力の「拍」はdouble値です。
このようなユースケースもありましたので転記します。小節数は0ベースになっています。
小節 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
拍子設定 | 4/4 | 3/4 | 3/8 | ||||||||
位置(拍) | 0 | 4 | 8 | 12 | 16 | 19 | 22 | 25 | 28 | 29.5 | 31 |
MIDIで使うための機能追加
MIDIイベントに使うためには「開始から何ティック目」であるかが必要なためTimeSignで戻される拍数に解像度を掛け合わせれば良いことになります。解像度を480として上のユースケースの前半部にティック情報を追加します。
小節 | 0 | 1 | 2 | 3 | 4 | 5 |
拍子設定 | 4/4 | 3/4 | ||||
位置(拍) | 0 | 4 | 8 | 12 | 16 | 19 |
位置(ティック) | 0 | 1920 | 3840 | 5760 | 7680 | 9120 |
今回はTimeSignクラスを継承しその機能を利用するMidiTimeSignクラスを作ることにします。
実装
クラスの宣言とコンストラクタです。解像度と初期の拍数設定を引数に取ります。解像度はこのクラスで保持して初期の拍数はTimeSignに渡します。
public class MidiTimeSign extends TimeSign { int resolution; public MidiTimeSign(int resolution, double initial){ super(initial); this.resolution = resolution; }
小節と拍を入力すると開始からの時間位置をティックで返すメソッドを作ります。TimeSignクラスで持っていた拍数を返すメソッドを内部で実行してそれに解像度を掛け合わせて小数点を丸めて返しています。
public long getTick(int measure, double beat){ double totalBeat = getTotalBeat(measure, beat); return Math.round(totalBeat * resolution); }
確認
確認用のコードを書いてユースケース通りになるかを確認します。
途中で3拍子に変更する設定をして0小節目から5小節目までを出力します。
MidiTimeSign ts = new MidiTimeSign(480, 4); ts.put(4, 3.0); for(int i = 0;i <= 5;i++){ System.out.println("measure=" + i + ", total beat=" + ts.getTotalBeat(i, 0) + ", tick=" + ts.getTick(i, 0)); }
以下が出力結果です。ユースケース通りになっていることが確認できました。
measure=0, total beat=0.0, tick=0 measure=1, total beat=4.0, tick=1920 measure=2, total beat=8.0, tick=3840 measure=3, total beat=12.0, tick=5760 measure=4, total beat=16.0, tick=7680 measure=5, total beat=19.0, tick=9120
ソース
今回のソースになります。
/* * mocha-java.com */ package mocha.sound.midi; import mocha.sound.TimeSign; /** * * @author minaberger */ public class MidiTimeSign extends TimeSign { int resolution; public MidiTimeSign(int resolution, double initial) { super(initial); this.resolution = resolution; } public long getTick(int measure, double beat) { double totalBeat = getTotalBeat(measure, beat); return Math.round(totalBeat * resolution); } }