网络音频常见问题解答

Boris Smus

过去几个月里,WebKit Web Audio API 已成为极具吸引力的 Web 游戏和音频应用平台。随着开发者对它越来越熟悉,我听到类似的问题反复出现。此快速更新旨在解答一些常见问题,让您在使用 Web Audio API 时获得更加愉悦的体验。

问:帮忙,我没法发出声音!

答:如果您是 Web Audio API 新用户,可以看看入门教程或 Eric 根据用户互动播放音频的食谱。

问:我应该有多少个音频上下文?

答:通常,您应为每个网页添加一个 AudioContext,并且单个音频上下文可以支持多个连接到该上下文的节点。虽然您可以在一个页面上添加多个 AudioContext,但这可能导致性能下降。

问:我有一个 AudioBufferSourceNode,我刚刚使用 noteOn() 播放过,我想再播放一遍,但 noteOn() 什么都不会用!我需要帮助!

答:源节点播放完毕后,便无法再播放更多内容。如需再次回放底层缓冲区,您应创建一个新的 AudioBufferSourceNode 并调用 noteOn()

虽然重新创建源节点可能会让人觉得效率低下,但源节点已针对此模式进行了大量优化。此外,如果您保留了 AudioBuffer 的句柄,则无需向相应资产另外提出请求即可再次播放相同的声音。如果您发现自己需要重复这种模式,请使用 playSound(buffer)简单的辅助函数封装播放。

问:播放声音时,为什么每次都需要创建新的来源节点?

答:此架构的理念是将音频资产与播放状态分离开来。按唱片机类比,缓冲区就类似于唱片和播放头的来源。由于许多应用涉及同时播放同一缓冲区的多个版本,因此该模式至关重要。

问:如何处理来自 audiovideo 标记的声音?

答:MediaElementAudioSourceNode 仍在开发中!如果可用,其工作原理大致如下(向通过音频标记播放的样本添加滤镜效果):

<audio src="sounds/sample.wav" controls>
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
mediaSourceNode.connect(filter);
filter.connect(context.destination);

此功能在此 crbug 中进行跟踪。请注意,在此设置中,无需调用 mediaSourceNode.noteOn(),音频标记用于控制播放。

问:什么时候才能收到麦克风的声音?

答:此过程中的音频输入部分将使用 getUserMedia 作为 WebRTC 的一部分实现,并可在 Web Audio API 中作为特殊源节点使用。它可与 createMediaElementSource 结合使用。

问:如何查看 AudioSourceNode 何时结束?

答:目前您必须使用 JavaScript 计时器,因为 Web Audio API 不支持此功能。Web Audio API 使用入门教程中的以下代码段就是实际操作中的代码段:

// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
    console.log('playback finished');
}, buffer.duration * 1000);

有一个待解决的 bug,可以使 Web Audio API 实现更准确的回调。

问:加载声音会导致整个界面线程锁定,我的界面变得无响应。救命啊!**

答:使用 decodeAudioData API 进行异步加载,以免阻塞主线程。请参阅此示例

问:可以使用 Web Audio API 来处理比实时更快的声音吗?

答:是的,我们正在制定解决方案。请继续关注我们的行动!

问:我开发了一个很棒的 Web Audio API 应用,但是每当它运行的标签页在后台运行时,听起来都会很奇怪!

答:这可能是因为您使用的是 setTimeouts;如果网页在后台运行,其行为方式会有所不同。将来,Web Audio API 将能够使用网络音频的内部计时器(context.currentTime 属性)在特定时间进行回调。如需了解详情,请参阅此功能请求

一般而言,最好在应用转入后台时停止播放。您可以使用 Page Visibility API 检测网页何时转到后台。

问:如何使用 Web Audio API 更改声音的音高?

答:更改源节点上的 playbackRate

问:可以在不改变速度的情况下改变音调吗?

答:Web Audio API 在音频上下文中可以有一个 PitchNode,但这很难实现。这是因为音频社区中没有简单直接的音高转换算法。已知技术会产生伪影,尤其是在音调偏移较大的情况下。可以通过两种方法解决此问题:

  • 时域算法,会导致重复片段回显伪影。
  • 产生混响声音伪像的频域技术。

虽然没有用于执行这些方法的原生节点,但您可以使用 JavaScriptAudioNode 来完成。您可以参考此代码段

问:如何以我选择的采样率创建 AudioContext?

答:我们目前还不支持这项功能,但我们正在努力解决此问题。请参阅此功能请求

如果您还有其他问题,请随时在 StackOverflow 上使用 web-audio 标记进行提问。