Web 音频的新功能?

Web 音频 API 仍在开发中,这意味着正在添加、重命名、重新排列或删除新的方法和属性!

本文将回顾自 2015 年初我们 上次更新 以来在 Web 音频规范和 Firefox 实现方面发生的变化。这些演示均可在 Firefox Nightly 中运行,但一些最新更改可能尚未出现在 Firefox 正式版或开发者版中。

API 更改

重大变更

中的 reduction 属性DynamicsCompressorNode现在是float而不是AudioParam. 你可以使用compressor.reduction而不是compressor.reduction.value.

来读取该值。此值显示压缩器应用于信号的增益衰减量,它一直是只读的,因此将其设置为float而不是AudioParam是有意义的(因为无法安排任何更改)。

要检测运行代码的浏览器是否支持AudioParamfloat数据类型,你可以检查.value属性是否存在于reduction:

if(compressor.reduction.value !== undefined) {
  // old style
} else {
  // new style
}

中。查看 此示例,其中在鼓循环播放时访问reduction属性。请注意该值如何变化以响应曲目中的响度,以及我们在读取属性之前如何检测浏览器支持哪个 API 版本value.

新属性和方法

中的新生命周期管理方法AudioContext

由于AudioContext相当昂贵,因此添加了三种新方法suspend(), resume()close().

。这些方法允许开发者暂停处理一段时间,直到再次需要它,并使用close()释放一些资源,当AudioContext不再需要时。

本质上,当AudioContext被暂停时,不会播放任何声音,当它恢复时,它将从停止的地方继续播放。规范中的 suspend() 说明 包含所有详细信息。

此示例 演示了这些方法的使用。

精确AudioNode disconnect()方法

过去,你无法选择性地断开节点连接:如果你在给定节点上运行disconnect(),它将断开与所有其他节点的连接。

值得庆幸的是,disconnect()方法现在可以重载以增加你可以执行的断开连接类型

  • disconnect()– 从所有节点断开节点的连接(这是现有的函数)
  • disconnect(outputNumber)– 断开来自节点的outputNumber通道的所有连接
  • disconnect(anotherNode)– 断开与anotherNode
  • 的所有连接disconnect(anotherNode, outputNumber)outputNumber– 断开来自anotherNode
  • 通道的节点的所有连接disconnect(anotherNode, outputNumber, inputNumber)anotherNode– 断开来自outputNumber进入inputNumber通道的连接
  • disconnect(audioParam)– 断开从该节点到audioParam
  • 的连接disconnect(audioParam, outputNumber)outputNumber– 断开来自该节点的audioParam

通道到

的连接我强烈建议你阅读 AudioNode 规范 以了解这些断开连接的影响的全部细节。你还可以阅读 原始讨论 以了解此更改背后的动机。

中的新 length 属性我强烈建议你阅读 AudioNode 规范 以了解这些断开连接的影响的全部细节。你还可以阅读 原始讨论 以了解此更改背后的动机。OfflineAudioContext

var oac = new OfflineAudioContext(1, 1000, 44100);
console.log(oac.length);
>> 1000

此新属性反映了在初始化

时传递给构造函数的值,因此开发者无需在单独的变量中跟踪它这是一个 示例,它演示了使用该属性以及使用增益包络渲染声波。detune

属性在这是一个 示例,它演示了使用该属性以及使用增益包络渲染声波。AudioBufferSourceNode这类似于OscillatorNode

时传递给构造函数的值,因此开发者无需在单独的变量中跟踪它AudioParam的,但现在可以用于比仅使用现有的playbackRate

属性更准确地微调样本。AudioParam-typed 位置和方向属性在PannerNode这些新属性是

,这意味着你可以使用自动化来修改它们,而不是在循环中连续调用setPosition() setOrientation()方法。AudioParam

StereoPannerNodepan属性已经是PannerNode,因此所有允许你将声音空间定位的节点也允许你自动执行其空间属性。非常适合模块化合成!pan也就是说,我们仍然缺少自动执行

AudioListener中的位置和方向属性的能力,这意味着如果你想定期更新它们,你现在必须使用方法。(Bug #1283029 跟踪此问题)。

传递值以设置中的位置和方向属性的能力,这意味着如果你想定期更新它们,你现在必须使用:

var wave = audioContext.createPeriodicWave(real, imag, { disableNormalization: false });

PeriodicWave

var wave = audioContext.createPeriodicWave(real, imag);
wave.disableNormalization = false;

实例的初始参数你现在可以在创建实例时传递一个选项对象

与以前的语法进行比较将来,所有节点创建方法都将允许开发者传递对象以设置其初始参数,并且也将是可构造的,因此我们可以执行以下操作

Building an IIRFilter with Digital Filter Design

new GainNode(anAudioContext, {gain: 0.5});. 这将使 Web 音频代码比在初始化节点时实际可能更简洁。更少的代码需要维护,这始终是个好消息!新节点将来,所有节点创建方法都将允许开发者传递对象以设置其初始参数,并且也将是可构造的,因此我们可以执行以下操作IIRFilterNode

如果BiquadFilterNode不足以满足你的需求,则AudioContext将允许你构建自己的自定义滤波器。你可以在上调用createIIRFilter()

var customFilter = audioContext.createIIRFilter([ 0.1, 0.2, ...], [0.4, 0.3, ...]);

函数来创建实例,并传入两个系数数组,分别表示定义滤波器的前馈反馈, 这是一个 示例,它演示了使用该属性以及使用增益包络渲染声波。, 此类型的滤波器节点不可自动化,这意味着一旦创建,你便无法更改其参数。如果你想使用自动化,则必须继续使用现有的BiquadFilter节点,并更改其Q.

frequency你可以在上调用gain

属性,它们都是

AudioParams

,这意味着你可以使用自动化来修改它们,而不是在循环中连续调用规范包含有关 这些差异 的更多数据,你可以使用 数字滤波器设计 资源来设计和可视化滤波器,并使用预先填充的数组获取可立即使用的 Web 音频代码。

链接方法

node0.connect(node1);
node1.connect(node2);
node2.connect(node3);

一些“语法糖”来改善开发人员的体验

node0.connect(node1).connect(node2).connect(node3);

connect()AudioParam方法返回它们连接到的节点,因此你可以更快地链接多个节点。比较

链接方法

gain.setValueAtTime(0, ac.currentTime);
gain.linearRampToValueAtTime(1, ac.currentTime + attackTime);

一些“语法糖”来改善开发人员的体验

gain.setValueAtTime(0, ac.currentTime)
  .linearRampToValueAtTime(1, ac.currentTime + attackTime);

之前

之后以及自动化方法也可以链接起来,因为每个方法都会返回它被调用的对象。例如,你可以使用它来更快地定义包络未来即将推出Web 音频工作组即将完成AudioWorklet的规范编写,这是

AudioWorker以及的新名称。这些将取代

ScriptProcessorNode

,该节点也允许你编写自己的节点,但它在 UI 线程上运行,因此在性能方面不是最佳选择。AudioParam定义 AudioWorklet 的拉取请求 以及规范中的相关对象必须首先合并,一旦完成,供应商就可以开始在他们的浏览器上实现对

的支持。AudioWorkletFirefox 更改:性能和调试改进

三位勤奋的工程师(Karl Tomlinson、Daniel Minor 和 Paul Adenot)花费了至少六个月的时间来提高 Firefox 中 Web 音频的性能。从实际意义上讲,这意味着音频代码现在运行时间更短,并且比 Chrome 更快或与 Chrome 一样快。唯一的例外是使用

时,Firefox 的性能不是很好……但会改进的同样,现在不太容易引入延迟(如果主线程非常繁忙)。这对于控制台模拟器等应用程序来说非常棒:低延迟意味着更忠实的模拟,从而让玩游戏更加有趣!

更深入地讲,已经引入了用于计算 DSP 内核的汇编级优化。这些优化利用了 ARM 和 x86 上的 SIMD 指令以并行计算多个值,用于平移、调整增益等简单功能。这意味着更快的代码和更高效的代码,从而消耗更少的电量——这对于移动设备尤其重要。

此外,涉及

MediaElement

  • 节点的跨源错误现在将报告给开发者工具控制台,而不是静默失败。这将帮助开发者识别确切的问题,而不是猜测为什么他们只听到静音。
  • 还有很多其他已修复的 bug——可能太多了,无法在这里列出!但是如果你真的很好奇,请查看 错误列表

关于 Soledad Penadés