矩形波、サイン波のオシレータができたので今度は三角波のオシレータを作ります。典型的な三角波は0から始まり最初の1/4の時点で最大音量になります。この間直線です。サイン波のような丸みはありません。そしてこのあと3/4の時点で最小音量になるようにこちらも直線的に音量が小さくなります。この間ちょうど1/2の地点で音量が0になります。最後に最小音量から0に戻ります。
三角波のグラフ
言葉で説明するよりグラフを見ましょう。

グラフは3周半過ぎたあたりまで表示されています。
音量を決めるロジック
矩形波のときと同様1周期のどこにあるかをxという変数で取得しています。xの値は0以上1未満の小数です。
| x | 音量 | 式 |
|---|---|---|
| 0から0.25まで | 0から1まで増加 | x * 4 |
| 0.25から0.75まで | 1から-1まで減少 | (0.5 – x) * 4. |
| 0.75から1まで | -1から0まで増加 | (x – 1) * 4 |
Javaでこれを表現します。
double point = x < 0.25 ? x * 4.0 : x < 0.75 ? (0.5 - x) * 4.0 : (x - 1.0) * 4.0;
後の処理は矩形波と全く同じです。
三角波のオシレーターのコード
矩形波のオシレーターをコピーして少し変えて作りました。
package mocha.sound;
public class TriangleOscillator implements Oscillatable {
double t;
double delta_t;
public TriangleOscillator(double sample_rate) {
t = 1.0 / sample_rate;
delta_t = 0;
}
@Override
public double read(double freq, double volume) {
double x = delta_t - Math.floor(delta_t);
double point = x < 0.25 ? x * 4.0 : x < 0.75 ? (0.5 - x) * 4.0 : (x - 1.0) * 4.0;
delta_t += freq * t;
return point * volume;
}
}
処理する側はオシレーターのクラス名を変更するだけです。全体のソースは矩形波のものを見てください。
SampleWav ss = new SampleWav(new TriangleOscillator(SAMPLE_RATE), 440, 3);
AudioSystem.write(
new AudioInputStream(ss, ss.getFormat(), ss.length()),
AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/tri_440.wav"));
実行結果
実行した結果は以下の通りです。サイズ節約のためwavファイルはmp3に変換してあります。
矩形波よりは柔らかい音になっているのがわかるでしょうか?参考までに矩形波を下にはりました。
またサイン波よりは硬い音になっています。以下はサイン波です。