RSS Twitter Facebook
g200kg > Web Audio API 解説 > 05.ノードのライフタイム

Web Audio API 解説

2019/01/19

05.ノードのライフタイム



ノードのライフタイム

さて、「オシレーターの使い方」の例でこんなサンプルを使いましたが・・・


function Start() {
    const audioctx = new AudioContext();
    const t0 = audioctx.currentTime;
    for(let i = 0; i < 10; ++i) {
        const osc = new OscillatorNode(audioctx);
        osc.connect(audioctx.destination);
        osc.start(t0 + i * 0.5 + 0.5);
        osc.stop(t0 + i * 0.5 + 0.6);
    }
}

よく見るとループ内で作られた osc はループを抜けるとどこからも参照されなくなってしまいます。まだこれから音を出さないといけないのですが、これで破棄されてしまわないのでしょうか?

WebAudio API では各ノードのオブジェクトがいつ破棄されるかについて、次のように JavaScript のルールに加えて幾つかの条件が決まっていて、この内のどれか 1 つでも残っていると破棄されません。この例だと 2 番目の条件で音を出し終わるまでオシレーターは維持されているわけです。

  1. 通常の Javascript のオブジェクトとしての参照がある
  2. Oscillator / AudioBufferSource 等の動作時刻を設定できるノードで、今後動作する時刻が設定されている、または動作中
  3. 他のノードから接続されている
  4. ノード内部の処理でまだ処理すべきデータが残っている (これは例えばリバーブの残響部分などです)
  5. MediaStreamAudioSourceNode で、入力となっているストリームが再生中になっている
  6. MediaElementAudioSourceNode で、対応する HTMLMediaElements が再生可能な状態になっている

更にこういう例もあります。前と同じようにあらかじめスケジュールが設定された 10 個の音を出しますが、オシレーターとゲインの組になっていて音量を 1 音ごとに変化させようとしています。

各 osc と gain の組はマスターボリュームのゲインノードに接続します。 mastervol はグローバルに参照が保持されていますが、Setup() のループ内で作られる osc と gain は、作り終わった後どこからも参照されなくなります (せっかくなので各オシレーターの音程と音量を乱数で適当に設定しています)。



<!DOCTYPE html>
<html>
<body>
<h1>Node Lifetime</h1>
<button onclick="Start()">Start</button><br/>
<script>

let audioctx, mastervol;

function Start() {
    if(!audioctx){
        audioctx = new AudioContext();
        mastervol = new GainNode(audioctx);
        mastervol.connect(audioctx.destination);
    }

    var t0 = audioctx.currentTime;
    for(var i = 0; i < 10; ++i) {
        const osc = new OscillatorNode(audioctx);
        const gain = new GainNode(audioctx);

        osc.frequency.value = 100 + Math.random() * 1000;
        gain.gain.value = 0.2 + Math.random() * 0.8;
        osc.connect(gain).connect(mastervol);
        osc.start(t0 + i * 0.5 + 0.5);
        osc.stop(t0 + i * 0.5 + 0.6);
    }
}

</script>
</body>
</html>
テストページ:ノードのライフタイム

この場合 osc はスケジュールが設定されているので維持され、gain は osc から接続されているために維持されています。osc は音を出し終わると自動的に破棄されますが、するとその osc に繋がっている gain も他のノードからの接続を失って連鎖的に破棄される事になります。

全部音を出し終わると mastervol への接続もなくなりますが、mastervol はグローバルな参照を持っているために消えずに残ります。




g200kg