1

我有一个使用以下设置的交互式音乐排序应用程序:

  1. 用户在 UI 中进行更改以操作音频节点图。
  2. 一个简单的 WebWorker 负责保持时间。它定期向主线程发送一条“tick”消息。
  3. 主线程中的侦听器接收消息并执行歌曲中的下一步(使用 AudioBufferSourceNode.start 播放样本、调整音量参数等)。

在 WebWorker 中使用计时器比仅使用 setInterval 更可靠,但在主线程处理消息之前仍可能存在延迟,从而导致音频故障。

似乎理想的解决方案是在 WebWorker 中执行第 3 步,但在 worker 中不支持 AudioContext。这样一来,AudioWorklet 就成为了唯一的低延迟网络音频 API。但它是图中的一个节点,而我正在寻找一种方法来管理整个事情。除了重写整个系统以在 AudioWorkletProcessor 中运行(大量工作)之外,有没有办法使用处理器进行精确调度,但保留现有的图形结构?

4

1 回答 1

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 的时钟创建您自己的计时器。

于 2020-06-22T03:34:43.263 回答