今回で最初の4小節を完成としたいと思います。最後の手入れをします。
テンポの揺らぎ
合奏と独奏を比べたとき独奏は他の演奏者と合わせる必要がないためかなり自由に曲のテンポを変えることができます。このため独奏曲は常にテンポを適度に変更するように設定するとそれらしく聞こえるようになります。
原譜にはアーティキュレーションについての指定はなにもないのでどのように解釈演奏しようが自由です。とはいえここではある程度戦略を決めるようにしましょう。8音フレーズのうち最初がレガートでテンポもゆっくり、最高音に達する3番目の音で一番早く、その後少しスタッカート気味に音を短く切るようにテンポも少しだけゆっくりにします。レガートやスタカートは音の長さとしてすでにしているのでここではテンポを指定するようにします。
| 位置 | テンポの割合 |
|---|---|
| 0 | 78% |
| 1 | 91% |
| 2 | 100% |
| 4 | 96% |
実装
上記の想定でテンポの設定をします。8音フレーズが1小節に2回あるので同じ設定を2回行なっています。
for (int i = 0; i < notes.length; i++) {
int m = i + 1;
track.add(new MidiEvent(getTempoMessage(tempo * 0.78), timeSign.getTick(m, 0)));
track.add(new MidiEvent(getTempoMessage(tempo * 0.91), timeSign.getTick(m, 0.25)));
track.add(new MidiEvent(getTempoMessage(tempo), timeSign.getTick(m, 0.5)));
track.add(new MidiEvent(getTempoMessage(tempo * 0.96), timeSign.getTick(m, 1)));
track.add(new MidiEvent(getTempoMessage(tempo * 0.78), timeSign.getTick(m, 2)));
track.add(new MidiEvent(getTempoMessage(tempo * 0.91), timeSign.getTick(m, 2.25)));
track.add(new MidiEvent(getTempoMessage(tempo), timeSign.getTick(m, 2.5)));
track.add(new MidiEvent(getTempoMessage(tempo * 0.96), timeSign.getTick(m, 3)));
}
実際の演奏
ここまでいろいろやってきたので実際のプログラムの成果を聞いてみることにします。以下は音源はGARRITAN PERSONAL ORCHESTRA 5を使っています。4小節のフレーズを4回繰り返しています。
ソース
最後にここまで作ったソースを載せておきます。
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Track;
import mocha.sound.midi.MidiTimeSign;
import static mocha.sound.midi.MidiUtil.getTempoMessage;
import static mocha.sound.midi.MidiUtil.playMidi;
import mocha.sound.midi.TrackEditor;
public class SequenceTest {
public static void main(String[] args) throws Exception {
int resolution = 480;
Sequence sequence = new Sequence(Sequence.PPQ, resolution);
Track track;
track = sequence.createTrack();
double tempo = 65;
track.add(new MidiEvent(getTempoMessage(tempo), 0));
MidiTimeSign timeSign = new MidiTimeSign(resolution, 4.0);
TrackEditor te1 = new TrackEditor(timeSign, sequence.createTrack(), 0);
te1.setProgram(0, 0, 0, 0, 42);
int[][] notes = new int[][]{
new int[]{43, 50, 59, 57, 50},
new int[]{43, 52, 60, 59, 52},
new int[]{43, 54, 60, 59, 54},
new int[]{43, 55, 59, 57, 54}
};
for (int n = 0; n < 4; n++) {
for (int i = 0; i < notes.length; i++) {
int m = n * notes.length + i;
track.add(new MidiEvent(getTempoMessage(tempo * 0.78), timeSign.getTick(m, 0)));
te1.play(m, 0.00, notes[i][0], 100, 0.3);
track.add(new MidiEvent(getTempoMessage(tempo * 0.91), timeSign.getTick(m, 0.25)));
te1.play(m, 0.25, notes[i][1], 90, 0.3);
track.add(new MidiEvent(getTempoMessage(tempo), timeSign.getTick(m, 0.5)));
te1.play(m, 0.50, notes[i][2], 90, 0.28);
te1.play(m, 0.75, notes[i][3], 80, 0.28);
track.add(new MidiEvent(getTempoMessage(tempo * 0.96), timeSign.getTick(m, 1)));
te1.play(m, 1.00, notes[i][2], 90, 0.13);
te1.play(m, 1.25, notes[i][1], 70, 0.18);
te1.play(m, 1.50, notes[i][2], 70, 0.15);
te1.play(m, 1.75, notes[i][1], 60, 0.15);
track.add(new MidiEvent(getTempoMessage(tempo * 0.78), timeSign.getTick(m, 2)));
te1.play(m, 2.00, notes[i][0], 100, 0.3);
track.add(new MidiEvent(getTempoMessage(tempo * 0.91), timeSign.getTick(m, 2.25)));
te1.play(m, 2.25, notes[i][1], 90, 0.3);
track.add(new MidiEvent(getTempoMessage(tempo), timeSign.getTick(m, 2.5)));
te1.play(m, 2.50, notes[i][2], 90, 0.28);
te1.play(m, 2.75, notes[i][3], 80, 0.28);
track.add(new MidiEvent(getTempoMessage(tempo * 0.96), timeSign.getTick(m, 3)));
te1.play(m, 3.00, notes[i][2], 90, 0.13);
te1.play(m, 3.25, notes[i][1], 70, 0.18);
te1.play(m, 3.50, notes[i][2], 70, 0.15);
te1.play(m, 3.75, notes[i][4], 60, 0.15);
}
}
Synthesizer synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
Receiver receiver = synthesizer.getReceiver();
//MidiDevice aria = MidiUtil.getMidiDevices("ARIA", true)[0];
//aria.open();
//Receiver receiver = aria.getReceiver();
playMidi(sequence, receiver);
}
}