因为根据https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process,对AudioWorkletProcessor.process的调用是同步的,所以当执行时间太长时会发生什么,例如,超过1秒?是否会在下一次呼叫中跳过某些音频样本?或者样本会在某处排队吗?我找不到关于这方面的文档。
发布于 2021-10-27 00:06:19
实时AudioContext通常对特定的物理音频输出设备是严格的。因此,AudioContext的currentTime由该音频输出设备的硬件时钟驱动。
如果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,它使用该the检查是否应该阻止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);也可以从主线程上的AudioWorkletProcessor中读取编写的currentTime。
Atomics.load(int32Array, 1);使用这个设置,我能够看到Chrome (v95)和Firefox (v93)在主线程和工作面板上都停止了时间进度,以防处理器被阻塞。
当它被解锁时,火狐继续它停止的地方,Chrome继续它应该在的地方,如果一切都按预期进行的话。
https://stackoverflow.com/questions/69624052
复制相似问题