前回で準備ができたのでエンベロープ・ジェネレーターEnvelope Generatorを作りたいと思います。
エンベロープ・ジェネレーターの役割
大体以下のようなことをしてほしいと思います。
- エンベロープを複製するための雛形エンベロープを保持する。
- 一定の音量を保持しその分増幅させて返す。
- 音の速さvelocityに対する感度sensitivityを保持してvelocityにより値を変化させる。
- リリース時間を保持し複製したエンベロープのリリース時間に音を消失させる。
- 音の長さdurationと音の速さvelocityからエンベロープを複製して返す。
作り出す音については音の速さに相関関係が深いものとあまりないものがあります。例えばオルガンは叩くように引いても優しく引いても音量は変わりません。一方ピアノは音量や音色が大きく変化します。このような違いもエンベロープ・ジェネレーターでコントロールするようにします。
また指定する音の長さが短いと雛形のエンベロープの一部だけが切り取られることになります。急になっている音が消えないようにリリース時間も保持してその時間で音が消えるようにします。
実装
クラスの宣言とコンストラクターです。コンストラクターには雛形エンベロープtemplateEnvelopeとリリース時間release、感度sensitivity、音量ampを指定します。
public class EnvelopeGenerator { DoubleMap templateEnvelope; double release; double sensitivity; double amp; public EnvelopeGenerator(DoubleMap templateEnvelope, double release, double sensitivity, double amp){ this.templateEnvelope = templateEnvelope; this.release = release; this.sensitivity = sensitivity; this.amp = amp; }
前回DoubleMapに実装したサブマップ取得メソッドを呼び出します。これによって指定された時間までのエンベロープを取得できます。
public DoubleMap getEnvelope(double duration, double velocity){ DoubleMap envelope = templateEnvelope.createSubMap(duration);
リリース時間分後に音が消失する設定を追加します。
envelope.putSecondValue(duration + release, 0);
感度を計算してエンベロープ全体の音量を調節します。感度が高いほど音の速さが遅い場合に音量が小さくなる仕組みです。
envelope.multiply((1 - (1 - velocity) * sensitivity) * amp); return envelope; }
リリース時間は外から取得できるようにしておきます。
public double getRelease(){ return release; }
次回はFM音源を使った楽器を作成したいと思います。