1

への呼び出しはhttps://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/processAudioWorkletProcessor.processによると同期的であるため、実行に時間がかかりすぎる場合 (たとえば 1 秒以上) はどうなりますか? 次の呼び出しでいくつかのオーディオ サンプルがスキップされますか? または、サンプルはどこかにキューに入れられますか? これに関するドキュメントは見つかりませんでした。

4

1 に答える 1

3

通常、リアルタイムAudioContextは特定の物理オーディオ出力デバイスに限定されます。したがって、currentTimeの は、AudioContextそのオーディオ出力デバイスのハードウェア クロックによって駆動されます。

AudioContext何らかの理由で時間内にサンプルを配信できなかった場合、結果は無音になります。通常、本来あるべきではないところに突然少しの無音がある場合、クリック音として聞こえることがあります。レンダリングに時間がかかりすぎたサンプルは、それまでに準備ができていれば、次のレンダリング クォンタムに使用されます。

currentTimeただし、一部のサンプルが時間内に配信されなかった場合に備えて、ブラウザーがどのように処理を進めるかには違いがあります。Firefox は見逃したサンプルをカウントしないようですが、Chrome は時間内にレンダリングできなかったものを含め、オーディオ ハードウェアが吐き出したすべてのサンプルをカウントします。

これをテストするためAudioWorkletProcessorに、メイン スレッド内から一時停止またはブロックできる を作成しました。

class BlockableProcessor extends AudioWorkletProcessor {
    constructor () {
        super();

        this.int32Array = null;
        this.port.onmessage = ({ data }) => this.int32Array = data;
    }

    process() {
        if (this.int32Array !== null) {
            while (Atomics.load(this.int32Array, 0) === 0) {
                Atomics.store(this.int32Array, 1, currentTime);
            }

            Atomics.store(this.int32Array, 1, currentTime);
        }

        return true;
    }
}

registerProcessor('blockable-processor', BlockableProcessor);

これは、関数をブロックする必要があるかどうかを確認するために使用するBlockableProcessorを受け取ることを期待しています。また、それを使用してバックをメイン スレッドに伝えます。SharedArrayBufferprocess()currentTime

次のように使用できます。

const audioWorkletNode = new AudioWorkletNode(
    audioContext,
    'blockable-processor'
);
const sharedArrayBuffer = new SharedArrayBuffer(8);
const int32Array = new Int32Array(sharedArrayBuffer);

Atomics.store(int32Array, 0, 1);
Atomics.store(int32Array, 1, 0);

audioWorkletNode.port.postMessage(int32Array);
audioWorkletNode.connect(audioContext.destination);

SharedArrayBufferの最初の値を 0に設定することでブロックできます。

Atomics.store(int32Array, 0, 0);

同様に、再度 1 に設定することでブロックを解除できます。

Atomics.store(int32Array, 0, 1);

メインスレッドcurrentTime内から書き込みを読み取ることも可能です。AudioWorkletProcessor

Atomics.load(int32Array, 1);

このセットアップを使用すると、プロセッサがブロックされた場合に、Chrome (v95) と Firefox (v93) の両方がメインスレッドとワークレットで時間の進行を停止することがわかりました。

ブロックが解除されると、Firefox は停止したところから続行し、Chrome はすべてが期待どおりに進んでいた場合にあるべき場所から続行します。

于 2021-10-27T00:06:18.890 に答える