AudioWorkletProcessor: process() 方法

process() 方法是 AudioWorkletProcessor 派生类的音频处理算法的实现。

虽然该方法不是 AudioWorkletProcessor 接口的一部分,但任何 AudioWorkletProcessor 的实现都必须提供 process() 方法。

该方法从音频渲染线程同步调用,针对每个通过处理器对应 AudioWorkletNode 的音频块(也称为渲染量子)调用一次。换句话说,每次有新的音频块准备供您的处理器处理时,就会调用 process() 函数来执行此操作。

注意: 当前,音频数据块始终为 128 帧长,即它们包含每个输入通道的 128 个 32 位浮点样本。但是,已经制定了修订规范以允许音频块的大小根据情况进行更改(例如,如果音频硬件或 CPU 利用率在较大的块大小下效率更高)。因此,您必须始终检查样本数组的大小,而不是假设特定的大小。

此大小甚至可能允许随时间推移发生变化,因此您不能只查看第一个块并假设样本缓冲区的大小始终相同。

语法

js
process(inputs, outputs, parameters)

参数

输入

连接到节点的输入数组,其中每个项目都是一个通道数组。每个通道都是一个包含 128 个样本的 Float32Array。例如,inputs[n][m][i] 将访问第 n 个输入、该输入的第 m 个通道以及该通道的第 i 个样本。

每个样本值都在 [-1 .. 1] 范围内。

输入的数量以及该数组的长度在节点构造时固定(请参阅 AudioWorkletNode)。如果节点的第 n 个输入没有连接活动的节点,则 inputs[n] 将是一个空数组(没有可用的输入通道)。

每个输入中通道的数量可能会因 channelCountchannelCountMode 属性而异。

输出

inputs 参数结构类似的输出数组。它旨在在 process() 方法执行期间进行填充。默认情况下,每个输出通道都填充了零,除非修改输出数组,否则处理器将输出静音。

参数

一个包含字符串键和 Float32Array 值的对象。对于使用 parameterDescriptors getter 定义的每个自定义 AudioParam,对象中的键是该 AudioParam名称,而值是一个 Float32Array。数组的值是通过考虑已安排的自动化事件计算的。

如果参数的自动化速率为 "a-rate",则数组将包含 128 个值,每个值对应当前音频块中的一帧。如果在当前块所代表的时间内没有发生自动化,则数组可能包含单个值,该值对于整个块都是常数,而不是 128 个相同的值。

如果自动化速率为 "k-rate",则数组将包含单个值,该值将用于 128 帧中的每一帧。

返回值

一个布尔值,指示是否强制 AudioWorkletNode 处于活动状态,即使 用户代理 的内部逻辑会决定关闭节点是安全的。

返回值让您的处理器可以影响 AudioWorkletProcessor 及其所属节点的生命周期策略。如果返回值与节点的状态相结合导致浏览器决定停止节点,则不会再次调用 process()

返回 true 会强制 Web 音频 API 保持节点处于活动状态,而返回 false 允许浏览器终止节点,如果节点既不生成新的音频数据也不接收它正在处理的输入数据。

3 种最常见的音频节点类型是

  1. 输出源。实现此类节点的 AudioWorkletProcessor 应在 process 方法中返回 true,只要它产生输出。该方法应在已知它不再产生输出时开始返回 false。例如,以 AudioBufferSourceNode 为例,该节点背后的处理器应在缓冲区播放时从 process 方法返回 true,并在缓冲区播放结束后开始返回 false(无法再次在同一 AudioBufferSourceNode 上调用 play)。
  2. 转换其输入的节点。实现此类节点的处理器应从 process 方法返回 false,以允许活动输入节点的存在和对节点的引用确定它是否可以被垃圾回收。具有此行为的节点的一个例子是 GainNode。一旦没有连接的输入和保留的引用,就无法再将增益应用于任何内容,因此可以安全地对其进行垃圾回收。
  3. 转换其输入的节点,但有一个所谓的尾部时间,这意味着即使在输入断开连接或处于非活动状态(产生零通道)后,它也会在一段时间内产生输出。实现此类节点的处理器应在尾部时间期间从 process 方法返回 true,从发现包含零通道的输入时开始。此类节点的一个示例是 DelayNode,它有一个等于其 delayTime 属性的尾部时间

注意: 缺少 return 语句意味着该方法返回 undefined,并且由于这是一个假值,它就像返回 false 一样。省略显式 return 语句可能会导致节点难以检测的问题。

异常

由于 process() 方法是由用户实现的,因此它可以抛出任何内容。如果抛出未捕获的错误,则节点将发出 processorerror 事件,并在其生命周期的剩余时间内输出静音。

示例

在这个例子中,我们创建了一个 AudioWorkletProcessor,它向其第一个输出输出白噪声。增益可以通过 customGain 参数控制。

js
class WhiteNoiseProcessor extends AudioWorkletProcessor {
  process(inputs, outputs, parameters) {
    // take the first output
    const output = outputs[0];
    // fill each channel with random values multiplied by gain
    output.forEach((channel) => {
      for (let i = 0; i < channel.length; i++) {
        // generate random value for each sample
        // Math.random range is [0; 1); we need [-1; 1]
        // this won't include exact 1 but is fine for now for simplicity
        channel[i] =
          (Math.random() * 2 - 1) *
          // the array can contain 1 or 128 values
          // depending on if the automation is present
          // and if the automation rate is k-rate or a-rate
          (parameters["customGain"].length > 1
            ? parameters["customGain"][i]
            : parameters["customGain"][0]);
      }
    });
    // as this is a source node which generates its own output,
    // we return true so it won't accidentally get garbage-collected
    // if we don't have any references to it in the main thread
    return true;
  }
  // define the customGain parameter used in process method
  static get parameterDescriptors() {
    return [
      {
        name: "customGain",
        defaultValue: 1,
        minValue: 0,
        maxValue: 1,
        automationRate: "a-rate",
      },
    ];
  }
}

规范

规范
Web 音频 API
# 处理

浏览器兼容性

这不是浏览器提供的,而是在客户端代码中必须编写的回调方法。

另请参阅