ラベル

2015年4月18日土曜日

Web Audio APIでオーディオをフェードイン、フェードアウトさせる方法

フェードイン、フェードアウトくらい楽勝だろと思ったら、意外な落とし穴が。



Web Audio APIに限らず、フェードイン、フェードアウトを実装したかったら、どうするか?
単純に時間が経つごとにボリュームを上げたり下げたりすればいいだけです。

そんな単純なことなんですが、Web Audio APIでそれをやろうとすると、APIの仕様をよく理解しないとできないんです。

例えば、フェードアウトを実装したいとします。
何はともあれ、何かしらの音源ノードとゲインノードを作成してコネクトするのが大前提。

そしたら、次はゲインを時間軸にそって下げてやればいいだけです。


Web Audio APIには、指定した時間までに、指定した値までゲインをなめらかに変化させてくれる便利なメソッドがあらかじめ用意されています。
なんだ楽勝じゃん。

例えばフェードアウトに使えるようなメソッドは
linearRampToValueAtTime(value, endTime)
という長ったらしい名前のメソッドがあります。
endTimeまでにゲインをvalueまで変化させてくれます。

foo.gain.linearRampToValueAtTime(value, endTime);
といった感じにゲインノードに対して使います。

さて、ここで問題があって、endTimeはAudioContext.currentTimeというプロパティから計算しなくてはいけません。
AudioContext.currentTimeは、AudioContextが作られた瞬間からの経過秒数が格納されています。
つまり現在時間を
startTime = AudioContext.currentTime;
と設定して、例えば1秒後にendTimeを設定したいなら
endTime = startTime + 1;
のように設定してやらないといけません。

さて、これで準備はできました。
foo.gain.linearRampToValueAtTime(0, endTime);
と書いて実行すると、フェードアウトが…できません。
指定時間になると突然ボリュームが0になります。

アイエエエ、ナンデ!?
ゲインノードの初期値は1ですから、1秒後までにゲインを0へなめらかに変化させてくれるはずなんですが、なめらかに変化しません!


実は、ここが落とし穴で、このlinearRampToValueAtTimeメソッドは初期値が”空”なんです!
ゲインノードの初期値とlinearRampToValueAtTimeメソッドの初期値とは別なんです。

この仕様に気づくまで数時間かかりましたw

単に初期値を設定してやればいいだけなんです。

初期値の設定方法はかなり適当で

foo.gain.linearRampToValueAtTime(1, startTime);
foo.gain.linearRampToValueAtTime(0, endTime);

のように現在時間に値を何でもいいからいれるだけ。
もうちょっとカッコよく書くなら

foo.gain.setValueAtTime(1, startTime);
foo.gain.linearRampToValueAtTime(0, endTime);

と書くといいでしょう。
どっちも同じです。

これでフェードアウトが実装できます。

はぁ、疲れたw
あんまりいないとは思いますが、私みたいにハマった人のために書き記しておきます。





Related Posts Plugin for WordPress, Blogger...