【问题标题】:Using AudioWorkletProcessor for low-latency audio scheduling?使用 AudioWorkletProcessor 进行低延迟音频调度?
【发布时间】:2020-10-11 18:33:39
【问题描述】:
我有一个使用以下设置的交互式音乐排序应用程序:
- 用户在 UI 中进行更改以操作音频节点图。
- 一个简单的 WebWorker 负责保持时间。它会定期向主线程发送一条“tick”消息。
- 主线程中的侦听器接收消息并执行歌曲中的下一步(使用 AudioBufferSourceNode.start 播放样本、调整音量参数等)。
在 WebWorker 中使用计时器比仅使用 setInterval 更可靠,但在主线程处理消息之前仍可能存在延迟,从而导致音频故障。
似乎理想的解决方案是在 WebWorker 中执行第 3 步,但 AudioContext is not supported in workers。这样一来,AudioWorklet 就成为了唯一的低延迟网络音频 API。但它是图中的一个节点,而我正在寻找一种方法来管理整个事情。除了重写整个系统以在 AudioWorkletProcessor 中运行(大量工作)之外,有没有办法使用处理器进行精确调度,但保留现有的图形结构?
【问题讨论】:
标签:
javascript
html5-audio
web-audio-api
audiocontext
audio-worklet
【解决方案1】:
AudioContext 有自己的时钟,使用它。
node1.start( ctx.currentTime + 1 ); // in one second
node2.start( ctx.currentTime + 2 ); // in two seconds
node3.start( ctx.currentTime + 3 ); // in three seconds
- 如果您想对前一个缓冲区源的结尾做出反应,请使用其
onended 事件监听器:
node.onended = (evt) => startANewNode();
- 如果您想要一个并行计时器,请使用一个 setTimeout 循环来纠正可能的漂移:
const duration = 1000;
let expected = ctx.currentTime + duration;
function loop() {
const drift = expected - ctx.currentTime;
startANewNode();
setTimeout( loop, duration - drift );
}
setTimeout( loop, duration );
当然,您甚至可以将所有这些点结合在一起,完全基于 AudioContext 的时钟创建您自己的计时器。