AudioWorkletProcessor.process
由于根据https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process的调用是同步的,如果执行时间过长(例如超过 1 秒)会发生什么情况?在下一次通话中会跳过一些音频样本吗?或者样品会在某个地方排队吗?我找不到这方面的文档。
1 回答
实时AudioContext
性通常与某个物理音频输出设备紧密相关。因此currentTime
,anAudioContext
的 由该音频输出设备的硬件时钟驱动。
如果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
期望接收SharedArrayBuffer
它用来检查它是否应该阻止该process()
功能。它还使用它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 会继续它应该在的地方,如果一切都按预期进行的话。