楽器をデザインしたのですから音を出しましょう。楽器の試し演奏をすることにします。
音出しのロジック
今回は音の速さによる音色の違いを確かめることにします。およそ以下のような処理を行います。
- 真ん中のドの音を10回鳴らす。
- 音の間隔は1秒、音の長さは0.5秒
- 音の速さはだんだん大きい値にしていく
今回はとりあえず音を出すだけなのでそれほど込み入ったことはしません。以下処理を実装しました。
TimeLine tl = new TimeLine();
Instrumental inst = new FirstInstrument();
for(int i = 0;i < 10;i++){
tl.addReadable(i, new Panner(inst.play(60, 0.5, ((double)i + 1.0) / 10.0), new DoubleMap(0.5)));
}
WavFileWriter.create(tl, new File("wav/firstinstrument.wav"));
実行結果
実行した結果は以下の通りです。
少しずつ音色が変わっていったのがわかりましたか? 特に音の出だしのアタック音に変化が出ていたと思います。
次回はこの楽器クラスを使って曲を演奏してみます。
ソース
楽器のソースです。
package mocha.sound.soundbank;
import mocha.sound.DoubleMap;
import mocha.sound.Instrumental;
import mocha.sound.OscillatorReader;
import mocha.sound.Played;
import mocha.sound.SineOscillator;
import mocha.sound.Temperament;
import mocha.sound.TriangleOscillator;
public class FirstInstrument implements Instrumental {
@Override
public Played play(double note, double duration, double velocity) {
Played played = new Played();
DoubleMap freq1 = new DoubleMap(Temperament.getFreq(note));
DoubleMap env1 = new DoubleMap(0);
env1.putSecondValue(0.01, velocity);
env1.putSecondValue(0.15, 0.0);
played.addReadable(0, new OscillatorReader(new TriangleOscillator(), freq1, env1, 0.15));
DoubleMap freq2 = new DoubleMap(Temperament.getFreq(note));
DoubleMap env2 = new DoubleMap(0);
double top = 0.3 + velocity / 2.0;
env2.putSecondValue(0.05, top);
double real_duration;
if (duration > 3) {
env2.putSecondValue(3, 0);
real_duration = 3;
} else {
double end_volume = (1.0 - duration / 3.0) * top;
env2.putSecondValue(duration, end_volume);
env2.putSecondValue(duration + 0.1, 0);
real_duration = duration + 0.1;
}
played.addReadable(0, new OscillatorReader(new SineOscillator(), freq2, env2, real_duration));
return played;
}
}