由于在开发 一起学笛子 这个网站的时候多处用到了 Web Audio API,因此,最近也阅读了不少的相关资料。奈何可能太小众了,因此,相关博文比较少,哪怕是著名的 MDN 也没有健全的中文文档,为数不多的几篇也是貌似机译的,晦涩难懂,因此,不得不借助翻译工具,阅读英文文档,啃得着实有点头疼。
本来想着针对前面的学习和使用心得写几篇笔记的,但考虑到后续还会对 Web Audio API 有更深入的使用,而且,MDN 上面的英文文档写的也比较详细,还有丰富的案例,因此,就想着还不如直接把这个系列翻译过来,一方面,通过翻译,可以倒逼自己硬啃一遍,同时也能加深理解,另一方面,留个笔记,后面再用的时候,就不用再啃一次英文文档了。
因此,接下来我会基于自己的理解,翻译这个系列的文章,试图让知识点能够稍微通俗易懂一点,不过,个人理解难免会有所偏差,因此,英语水平还不错的朋友,还是建议直接阅读原文。
为了在网络上控制音频,Web Audio API 提供了一个强大且多功能的系统,允许开发人员选择音频源、为音频添加各种效果、创建音频可视化以及应用空间效果(如平移)等。
1. 网络音频的概念和用法
Web Audio API 涉及在音频上下文(audio context)中处理音频操作,其设计允许进行模块化路由(modular routing)。基本的音频操作通过音频节点(audio nodes)来执行,这些音频节点连接在一起形成一个音频路由图(audio routing graph)。即使在单个音频上下文中,也支持多种具有不同类型声道布局的音频源。这种模块化设计十分灵活,可以创建具有动态效果的复杂音频功能。
音频节点通过它们的输入和输出连接成链或简单的网络,它们通常以一个或多个音频源开始。音频源在非常小的时间片内提供声音强度(样本)数组,通常每秒有数万个。这些音频源可以是数学计算得到的(如OscillatorNode
),也可以是来自于声音或视频文件(如AudioBufferSourceNode
和MediaElementAudioSourceNode
)的录音以及音频流(MediaStreamAudioSourceNode
)。实际上,声音文件本身只是声音强度的记录,它们来自麦克风或电子乐器,并混合成一个单一的、复杂的波形。
这些节点的输出可以链接到其他节点的输入,从而将这些声音样本流混合或修改成不同的流。一种常见的修改是将样本乘以一个值以使其更响亮或更安静(就像GainNode
一样)。一旦声音经过充分处理以达到预期效果,它就可以连接到目标的输入(BaseAudioContext.destination
),该目标将声音发送到扬声器或耳机。只有当用户应该听到音频时,最后这个连接才是必要的。
一个简单、典型的网络音频工作流程如下图所示:
- 创建音频上下文(
AudioContext
); - 在该上下文中,创建音频源,例如
<audio>
元素、振荡器、音频流等; - 创建效果节点,如混响、双二阶滤波器、声像器、压缩器等;
- 选择音频的目标,例如系统扬声器;
- 将音频源连接到效果节点,再将效果节点连接到音频目标。
时序控制具有高精度和低延迟的特点,使开发人员能够编写出准确响应事件并能够对特定样本进行定位的代码,即使在高采样率下也是如此。因此,鼓机和音序器等应用程序均可轻松实现。
Web Audio API 还允许我们控制音频的空间化。它是一个基于音频源-监听器模型的系统,允许控制移动模型,并处理由于移动音频源(或监听器)而产生相对距离后,造成的声音衰减。
2. Web Audio API 的目标受众
对于不熟悉音频或音乐术语的人来说,Web Audio API 可能看起来令人生畏,并且由于它包含了大量的功能,如果你是一名开发人员,可能会发现很难上手。
它可以用来将音频集成到你的网站或应用程序中,也可以用来创建高级的交互式乐器。所以,它对于开发人员和音乐家来说都非常合适。
对于那些熟悉编程但需要深入了解API的一些术语和结构的人,我们有一个《简单的入门教程》。
还有一篇关于《Web Audio API背后基本概念》的文章,可以帮助你了解数字音频(特别是在该 API 领域)的工作方式和相关概念。
学习编程就像玩纸牌一样——你要先学习规则,然后玩,然后再回去学习规则,然后再玩。因此,如果在前面的教程和文章之后,有些理论还不太适合,那么还有一个高级教程,它扩展了第一个教程,以帮助你练习所学的内容,并应用一些更高级的技术来构建一个步进音序器。
如果你对音乐方面更熟悉,了解乐理,想要开始制作乐器,那么你可以继续以高级教程和其他教程为指导来制作(上面链接的教程涵盖了音符的编排、定制振荡器和包络的创建,以及其他内容,如低频振荡器。)如果你不熟悉编程基础知识,你可能需要先查阅一些 JavaScript
初学者教程,然后再回到这里。
3. Web Audio API 接口
Web Audio API 有许多接口和相关事件,我们已按功能将其分为九个类别。
3.1 通用音频图定义
在Web Audio API的使用中,用于构建音频图的通用容器和定义。
AudioContext
AudioContext
接口表示由相互连接的音频模块构建的音频处理图,每个模块都由一个AudioNode
表示。音频上下文控制其包含的节点的创建以及音频处理或解码的执行。在执行其他任何操作之前,必须先创建一个AudioContext
,因为所有操作都发生在上下文中。AudioNode
AudioNode
接口表示一个音频处理模块,如音频源(例如<audio>
或<video>
元素)、音频目标或中间处理模块(例如BiquadFilterNode
滤波器或GainNode
音量控制)。AudioParam
AudioParam
接口表示与音频相关的参数,如AudioNode
的参数之一。它可以设置为固定值或变化的值,并且这种变化可以安排在某个特定时间按照特定方式发生。AudioParamMap
提供了一个类似Map
映射的接口来管理一组AudioParam
接口,这意味着它提供了forEach()
、get()
、has()
、keys()
和values()
等方法,以及一个size
属性。BaseAudioContext
BaseAudioContext
接口作为在线(AudioContext
)和离线(OfflineAudioContext
)音频处理图的基础定义,一般不会被直接使用 ,而是会通过它的两个继承接口之一来使用其功能。ended
事件
当媒体因为播放到末尾而停止时,会触发ended
事件。
3.2 定义音频源
用于定义Web Audio API中音频源的接口。
AudioScheduledSourceNode
AudioScheduledSourceNode
是几种音频源节点接口的父接口,它是一个AudioNode
。OscillatorNode
OscillatorNode
接口表示一个周期性波形,如正弦波或三角波。它是一个AudioNode
音频处理模块,用于生成给定频率的波形。AudioBuffer
AudioBuffer
接口表示一个存储在内存中的短音频资源,该资源是通过使用BaseAudioContext.decodeAudioData
方法从音频文件中创建的,或者使用BaseAudioContext.createBuffer
方法通过原始数据创建的。一旦解码成这种形式,音频就可以被放入AudioBufferSourceNode
中了。AudioBufferSourceNode
AudioBufferSourceNode
接口表示一个音频源,该音频源是由存储在AudioBuffer
中音频数据组成,位于内存中。它是一个作为音频源的AudioNode
。MediaElementAudioSourceNode
MediaElementAudioSourceNode
接口表示一个音频源,该音频源由一个 HTML<audio>
或<video>
元素组成。它是一个作为音频源的AudioNode
。MediaStreamAudioSourceNode
MediaStreamAudioSourceNode
接口表示一个音频源,该音频源由一个MediaStream
组成(例如,网络摄像头、麦克风或来自远程计算机的流)。如果流中存在多个音频轨道,则使用字典顺序(按字母顺序)中id
排在前面的轨道。它是一个作为音频源的AudioNode
。MediaStreamTrackAudioSourceNode
类型为MediaStreamTrackAudioSourceNode
的节点表示一个音频源,其数据来自MediaStreamTrack
。在使用createMediaStreamTrackSource()
方法创建节点时,您可以指定要使用哪个轨道,它提供了比MediaStreamAudioSourceNode
更多的控制。
3.3 定义音频效果滤波器
定义您想要应用于音频源的效果的接口。
BiquadFilterNode
BiquadFilterNode
接口表示一个简单的低阶滤波器。它是一个AudioNode
,可以表示不同类型的滤波器、音调控制设备或图形均衡器。BiquadFilterNode
始终具有正好一个输入和一个输出。ConvolverNode
ConvolverNode
接口是一个AudioNode
,它对给定的AudioBuffer
执行线性卷积,并经常用于实现混响效果。DelayNode
DelayNode
接口表示一个延迟线,它是一个AudioNode
音频处理模块,用于在输入数据到达和传播到输出之间产生延迟。DynamicsCompressorNode
DynamicsCompressorNode
接口提供了一种压缩效果,该效果会降低信号中最响亮部分的音量,以帮助防止在同时播放和复用多个声音时可能出现的剪切和失真。GainNode
GainNode
接口表示音量的变化。它是一个AudioNode
音频处理模块,用于在输入数据传播到输出之前,对输入数据应用给定的增益。WaveShaperNode
WaveShaperNode
接口表示一个非线性失真器。它是一个AudioNode
,使用曲线对信号应用波形整形失真。除了明显的失真效果外,它还经常用于给信号增加温暖的感觉。PeriodicWave
描述了一个周期性波形,该波形可用于塑造OscillatorNode
的输出。IIRFilterNode
实现了一个通用的无限脉冲响应(IIR
)滤波器,这种类型的滤波器也可以用于实现音调控制设备和图形均衡器。
3.4 定义音频目标
一旦你完成了音频处理,这些接口定义了音频的输出位置。
AudioDestinationNode
AudioDestinationNode
接口表示在给定上下文中音频源的最终目标——通常是你设备的扬声器。MediaStreamAudioDestinationNode
MediaStreamAudioDestinationNode
接口表示一个音频目标,该目标由一个包含单个AudioMediaStreamTrack
的 WebRTCMediaStream
组成,可以类似于从getUserMedia()
获得的MediaStream
那样使用。它是一个AudioNode
,作为音频目标工作。
3.5 数据分析和可视化
如果你想要从音频中提取时间、频率和其他数据,那么你需要使用 AnalyserNode
。
AnalyserNode
AnalyserNode
接口表示一个节点,该节点能够提供实时频率和时域分析信息,用于数据分析和可视化。
3.6 分割与合并音频通道
如果希望分割和合并音频通道,你将用到这些接口。
ChannelSplitterNode
ChannelSplitterNode
接口用于将音频源的不同通道分割成多个单声道输出。ChannelMergerNode
ChannelMergerNode
接口将不同的单声道输入合并为一个输出,每个输入都将用于填充输出的一个通道。
3.7 音频空间化
这些接口允许你为你的音频源添加音频空间化平移效果。
AudioListener
AudioListener
接口代表在音频空间化中用于音频场景的唯一听众的位置和方向。PannerNode
PannerNode
接口表示音频源信号在三维空间中的位置和行为,允许你创建复杂的平移效果。StereoPannerNode
StereoPannerNode
接口表示一个简单的立体声平移节点,可用于将音频流向左或向右平移。
3.8 JavaScript 中的音频处理
使用音频工作线程(AudioWorklet
),你可以定义用 JavaScript
或 WebAssembly
编写的自定义音频节点。音频工作线程实现了 Worklet
接口,这是 Worker
接口的一个轻量级版本。
AudioWorklet
AudioWorklet
接口可通过AudioContext
对象的audioWorklet
访问,它允许你将模块添加到音频工作线程中,以便在主线程之外执行。AudioWorkletNode
AudioWorkletNode
接口表示嵌入到音频图中的AudioNode
,它可以向对应的AudioWorkletProcessor
发送消息。AudioWorkletProcessor
AudioWorkletProcessor
接口表示在AudioWorkletGlobalScope
中运行的音频处理代码,该代码直接生成、处理或分析音频,并可以向对应的AudioWorkletNode
发送消息。AudioWorkletGlobalScope
AudioWorkletGlobalScope
接口是一个从WorkletGlobalScope
派生的对象,表示在其中运行音频处理脚本的工作线程上下文,它旨在允许在工作线程中直接使用JavaScript
而不是在主线程中生成、处理和分析音频数据。
3.9 离线/后台音频处理
可以通过以下方式在后台非常快速地处理/渲染音频图——将其渲染到 AudioBuffer
而不是设备的扬声器中。
OfflineAudioContext
OfflineAudioContext
接口是一个AudioContext
接口,它代表一个由相互连接的AudioNode
构建的音频处理图。与标准的AudioContext
不同,OfflineAudioContext
不会真正渲染音频,而是尽可能快地在一个缓冲区(AudioBuffer
)中生成音频。complete
事件
当OfflineAudioContext
的渲染结束时,会触发complete
事件。OfflineAudioCompletionEvent
OfflineAudioCompletionEvent
表示当OfflineAudioContext
的处理终止时发生的事件,complete
事件使用了此接口。
4. 指南和教程
- 高级技术:创建并编排音频
在本教程中,我们将介绍声音的创建和修改、定时和调度。我们将引入样本加载、包络、滤波器、波形表和频率调制。如果你对这些术语比较熟悉,并希望了解如何使用 Web Audio API 应用它们,那么你来对地方了。 - 使用 AudioWorklet 进行后台音频处理
本文介绍了如何创建一个音频工作线程处理器并在 Web Audio 应用程序中使用它。 - Web Audio API 的基本概念
本文解释了一些音频理论,这些理论解释了 Web Audio API 的功能是如何工作的,以帮助你在设计应用程序的音频路由时做出明智的决策。如果你还不是一名音频工程师,本文将为你提供足够的背景知识,以理解 Web Audio API 为何如此工作。 - 使用 ConstantSourceNode 控制多个参数
本文展示了如何使用ConstantSourceNode
将多个参数链接在一起,以便它们共享相同的值,并且可以通过设置ConstantSourceNode.offset
参数的值来改变这个值。 - 示例和教程:简单的合成器键盘
本文介绍了一个视频键盘的示例和代码,这个键盘也可以通过鼠标演奏,允许你在标准波形和一个自定义波形之间切换,并且你可以使用键盘下方的音量滑块来控制主音量。这个示例使用了以下 Web API 接口:AudioContext
、OscillatorNode
、PeriodicWave
和GainNode
。 - 分析 Web Audio 使用情况的工具
在编写 Web Audio API 代码时,您可能会发现需要一些工具来分析您创建的节点图或调试您的工作。本文将讨论一些可用的工具,以帮助您完成这些任务。 - 使用IIR滤波器
Web Audio API 的IIRFilterNode
接口是一个AudioNode
处理器,它实现了一个通用的无限冲激响应(IIR
)滤波器;这种滤波器可用于实现音调控制设备和图形均衡器,并且可以指定滤波器响应参数,以便根据需要进行调整。本文将探讨如何实现一个IIR
滤波器,并在一个简单的示例中使用它。 - 使用Web Audio API
开始了解 Web Audio API 的基础知识,并简要地了解一些概念,然后研究一个简单的便携式音响示例,该示例允许我们加载音频轨道、播放和暂停它,以及更改其音量和立体声平衡。 - 使用 Web Audio API 进行可视化
Web Audio API 最有趣的功能之一是从音频源中提取频率、波形和其他数据,然后可以使用这些数据来创建可视化效果。本文将解释如何实现这一点,并提供几个基本用例。 - Web Audio API 最佳实践
在编写创意代码时,并没有绝对的对错之分。只要你考虑到安全性、性能和可访问性,你就可以适应自己的风格。在本文中,我们将分享一些最佳实践——与 Web Audio API 一起工作的指导原则、技巧和窍门。 - Web 音频空间化基础
如果说 Web Audio API 提供的广泛声音处理(以及其他)选项还不够的话,它还包含了一些功能,允许你模拟当听众围绕声源移动时声音的差异,例如在 3D 游戏中围绕声源移动时的平移效果。这种效果的官方术语是空间化(spatialization),本文将介绍如何实现这种系统的基本知识。
5. 示例代码
你可以在 GitHub 上的 webaudio-example 存储库中找到大量示例代码。
评论0
暂时没有评论