Web Audio API 1.1

W3C 首个公开工作草案,

关于此文档的更多细节
此版本
https://w3org.cn/TR/2024/WD-webaudio-1.1-20241105/
最新发布版本
https://w3org.cn/TR/webaudio-1.1/
编辑草案
https://webaudio.github.io/web-audio-api/
历史
https://w3org.cn/standards/history/webaudio-1.1/
反馈
public-audio@w3.org,邮件主题行请填写“[webaudio] … 消息主题 …” (归档)
GitHub
测试套件
https://github.com/web-platform-tests/wpt/tree/master/webaudio
编辑
(Mozilla (https://www.mozilla.org/))
(Google (https://www.google.com/))
前任编辑
Raymond Toy (至 2018 年 10 月)
Chris Wilson (至 2016 年 1 月)
Chris Rogers (至 2013 年 8 月)

摘要

本规范描述了一种用于 Web 应用中处理和合成音频的高级 Web API。其主要范式是音频路由图,其中多个 AudioNode 对象相互连接,以定义整体的音频渲染。实际处理主要在底层实现中进行(通常是优化的汇编 / C / C++ 代码),但也支持直接脚本处理和合成

引言章节涵盖了本规范背后的动机。

本 API 设计为与 Web 平台上的其他 API 和元素结合使用,特别是:XMLHttpRequest [XHR](使用 responseTyperesponse 属性)。对于游戏和交互式应用程序,预计将与 canvas 2D [2dcontext] 和 WebGL [WEBGL] 3D 图形 API 一起使用。

关于本文档

本部分描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新版本可在 W3C 技术报告索引(https://w3org.cn/TR/)中找到。

本文档由 Web 音频工作组作为首个公开工作草案发布,采用推荐标准轨道

本文档旨在成为 W3C 推荐标准。

如果您希望对本文档提出意见,请在规范仓库中提交问题或发送邮件至 public-audio@w3.org (订阅, 归档)。

本文档为首个公开工作草案

作为首个公开工作草案发布并不意味着 W3C 及其成员的背书。这是一个草案文档,可能随时被其他文档更新、替换或废弃。将其作为正在进行的工作以外的内容引用是不恰当的。

本文档由在 W3C 专利政策下运作的小组编写。W3C 维护着一份与小组交付成果相关的公开专利披露列表;该页面还包括专利披露指南。任何实际知晓某项专利包含必要权利要求 (Essential Claim) 的个人,必须根据 W3C 专利政策第 6 节披露相关信息。

本文档受 2023 年 11 月 3 日版 W3C 流程文档管辖。

引言

Web 上的音频技术在这一点之前一直相当原始,直到最近还不得不通过 Flash 和 QuickTime 等插件进行交付。HTML5 中 audio 元素的引入非常重要,它实现了基本的流式音频播放。但是,它不足以处理更复杂的音频应用。对于复杂的 Web 游戏或交互式应用程序,需要另一种解决方案。本规范的目标之一是包含现代游戏音频引擎中的功能,以及现代桌面音频制作应用程序中常见的混音、处理和滤波任务。

这些 API 在设计时考虑了各种各样的用例 [webaudio-usecases]。理想情况下,它应该能够支持任何能够合理地通过脚本控制、在浏览器中运行的优化 C++ 引擎所能实现的功能。话虽如此,现代桌面音频软件可能具有非常先进的功能,其中一些用本系统构建将很困难或不可能。Apple 的 Logic Audio 就是这样一种应用程序,它支持外部 MIDI 控制器、任意插件音频效果和合成器、高度优化的直接到磁盘音频文件读写、紧密集成的变速变调等等。尽管如此,本系统将完全有能力支持大量的、相当复杂的游戏和交互式应用程序,包括音乐类的。它还可以作为 WebGL 提供的更高级图形功能的良好补充。该 API 的设计旨在让更高级的功能可以在以后添加。

特性

本 API 支持以下主要特性:

模块化路由。

模块化路由允许在不同的 AudioNode 对象之间建立任意连接。每个节点都可以有输入和/或输出源节点没有输入,只有一个输出。目标节点有一个输入,没有输出。其他节点(如滤波器)可以放置在源节点和目标节点之间。当两个对象连接在一起时,开发人员不必担心低级别的流格式细节;系统会自动处理。例如,如果单声道音频流连接到立体声输入,它应该恰当地混合到左声道和右声道。

在最简单的情况下,单个源可以直接路由到输出。所有路由都在包含一个 AudioDestinationNodeAudioContext 内进行。

modular routing
模块化路由的一个简单示例。

为了说明这种简单的路由,这里有一个播放单个声音的简单示例。

const context = new AudioContext();

function playSound() {
    const source = context.createBufferSource();
    source.buffer = dogBarkingBuffer;
    source.connect(context.destination);
    source.start(0);
}

这是一个更复杂的示例,包含三个源和一个卷积混响发送,在最终输出阶段带有一个动态压缩器。

modular routing2
模块化路由的一个更复杂示例。
let context;let compressor;let reverb;let source1, source2, source3;let lowpassFilter;let waveShaper;let panner;let dry1, dry2, dry3;let wet1, wet2, wet3;let mainDry;let mainWet;function setupRoutingGraph () {    context = new AudioContext();    // Create the effects nodes.    lowpassFilter = context.createBiquadFilter();    waveShaper = context.createWaveShaper();    panner = context.createPanner();    compressor = context.createDynamicsCompressor();    reverb = context.createConvolver();    // Create main wet and dry.    mainDry = context.createGain();    mainWet = context.createGain();    // Connect final compressor to final destination.    compressor.connect(context.destination);    // Connect main dry and wet to compressor.    mainDry.connect(compressor);    mainWet.connect(compressor);    // Connect reverb to main wet.    reverb.connect(mainWet);    // Create a few sources.    source1 = context.createBufferSource();    source2 = context.createBufferSource();    source3 = context.createOscillator();    source1.buffer = manTalkingBuffer;    source2.buffer = footstepsBuffer;    source3.frequency.value = 440;    // Connect source1    dry1 = context.createGain();    wet1 = context.createGain();    source1.connect(lowpassFilter);    lowpassFilter.connect(dry1);    lowpassFilter.connect(wet1);    dry1.connect(mainDry);    wet1.connect(reverb);    // Connect source2    dry2 = context.createGain();    wet2 = context.createGain();    source2.connect(waveShaper);    waveShaper.connect(dry2);    waveShaper.connect(wet2);    dry2.connect(mainDry);    wet2.connect(reverb);    // Connect source3    dry3 = context.createGain();    wet3 = context.createGain();    source3.connect(panner);    panner.connect(dry3);    panner.connect(wet3);    dry3.connect(mainDry);    wet3.connect(reverb);    // Start the sources now.    source1.start(0);    source2.start(0);    source3.start(0);}

模块化路由还允许将 AudioNode 的输出路由到控制另一个 AudioNode 行为的 AudioParam 参数。在这种情况下,节点的输出可以作为调制信号,而不是输入信号。

modular routing3
模块化路由,展示了一个振荡器调制另一个振荡器的频率。
function setupRoutingGraph() {    const context = new AudioContext();    // Create the low frequency oscillator that supplies the modulation signal    const lfo = context.createOscillator();    lfo.frequency.value = 1.0;    // Create the high frequency oscillator to be modulated    const hfo = context.createOscillator();    hfo.frequency.value = 440.0;    // Create a gain node whose gain determines the amplitude of the modulation signal    const modulationGain = context.createGain();    modulationGain.gain.value = 50;    // Configure the graph and start the oscillators    lfo.connect(modulationGain);    modulationGain.connect(hfo.detune);    hfo.connect(context.destination);    hfo.start(0);    lfo.start(0);}

API 概览

定义的接口包括:

还有一些功能已从 Web Audio API 中弃用,但尚未移除,等待其替代品的实现经验。

1. 音频 API

1.1. BaseAudioContext 接口

此接口代表一组 AudioNode 对象及其连接。它允许将信号任意路由到 AudioDestinationNode。节点从上下文创建,然后连接在一起。

BaseAudioContext 不直接实例化,而是由具体接口 AudioContext(用于实时渲染)和 OfflineAudioContext(用于离线渲染)扩展。

BaseAudioContext 创建时带有一个内部槽 [[pending promises]],它是一个最初为空的有序 Promise 列表。

每个 BaseAudioContext 都有一个唯一的 媒体元素事件任务源。此外,BaseAudioContext 还有几个私有槽 [[rendering thread state]][[control thread state]],它们取自 AudioContextState,并且初始都设置为 "suspended",以及一个私有槽 [[render quantum size]],它是一个无符号整数。

enum AudioContextState {
    "suspended",
    "running",
    "closed"
};
AudioContextState 枚举描述
枚举值描述
"suspended"此上下文当前处于挂起状态(上下文时间不推进,音频硬件可能已下电/释放)。
"running"音频正在被处理。
"closed"此上下文已被释放,不能再用于处理音频。所有系统音频资源已释放。
enum AudioContextRenderSizeCategory {
    "default",
    "hardware"
};
枚举描述
"default"AudioContext 的渲染量子大小是 128 帧的默认值。
"hardware"用户代理选择一个最适合当前配置的渲染量子大小

注意:这会暴露有关主机的信息,可用于指纹识别。

callback DecodeErrorCallback = undefined (DOMException error);

callback DecodeSuccessCallback = undefined (AudioBuffer decodedData);

[Exposed=Window]
interface BaseAudioContext : EventTarget {
    readonly attribute AudioDestinationNode destination;
    readonly attribute float sampleRate;
    readonly attribute double currentTime;
    readonly attribute AudioListener listener;
    readonly attribute AudioContextState state;
    readonly attribute unsigned long renderQuantumSize;
    [SameObject, SecureContext]
    readonly attribute AudioWorklet audioWorklet;
    attribute EventHandler onstatechange;

    AnalyserNode createAnalyser ();
    BiquadFilterNode createBiquadFilter ();
    AudioBuffer createBuffer (unsigned long numberOfChannels,
                                unsigned long length,
                                float sampleRate);
    AudioBufferSourceNode createBufferSource ();
    ChannelMergerNode createChannelMerger (optional unsigned long numberOfInputs = 6);
    ChannelSplitterNode createChannelSplitter (
        optional unsigned long numberOfOutputs = 6);
    ConstantSourceNode createConstantSource ();
    ConvolverNode createConvolver ();
    DelayNode createDelay (optional double maxDelayTime = 1.0);
    DynamicsCompressorNode createDynamicsCompressor ();
    GainNode createGain ();
    IIRFilterNode createIIRFilter (sequence<double> feedforward,
                                    sequence<double> feedback);
    OscillatorNode createOscillator ();
    PannerNode createPanner ();
    PeriodicWave createPeriodicWave (sequence<float> real,
                                        sequence<float> imag,
                                        optional PeriodicWaveConstraints constraints = {});
    ScriptProcessorNode createScriptProcessor(
        optional unsigned long bufferSize = 0,
        optional unsigned long numberOfInputChannels = 2,
        optional unsigned long numberOfOutputChannels = 2);
    StereoPannerNode createStereoPanner ();
    WaveShaperNode createWaveShaper ();

    Promise<AudioBuffer> decodeAudioData (
        ArrayBuffer audioData,
        optional DecodeSuccessCallback? successCallback,
        optional DecodeErrorCallback? errorCallback);
};

1.1.1. 属性

audioWorklet, 类型 AudioWorklet, 只读

允许访问 Worklet 对象,该对象可以通过 [HTML]AudioWorklet 定义的算法导入包含 AudioWorkletProcessor 类定义的脚本。

currentTime, 类型 double, 只读

这是紧随上下文渲染图最近处理的音频块中最后一个采样帧之后的采样帧的时间(以秒为单位)。如果上下文的渲染图尚未处理音频块,则 currentTime 的值为零。

currentTime 的时间坐标系中,零值对应于图中处理的第一个块中的第一个采样帧。此系统中的已过时间对应于 BaseAudioContext 生成的音频流中的已过时间,它可能与其他系统时钟不同步。(对于 OfflineAudioContext,由于流没有被任何设备主动播放,甚至不存在对实时时间的近似。)

Web Audio API 中的所有调度时间均相对于 currentTime 的值。

BaseAudioContext 处于 "running" 状态时,此属性的值单调递增,并由渲染线程以统一的增量(对应于一个渲染量子)进行更新。因此,对于运行中的上下文,currentTime 随着系统处理音频块而稳定增加,并始终代表下一个要处理的音频块的开始时间。这也是当前状态下调度任何更改可能生效的最早时间。

在返回之前,currentTime 必须在控制线程上原子地读取。

destination, 类型 AudioDestinationNode, 只读

一个带有单个输入的 AudioDestinationNode,代表所有音频的最终目的地。通常这将代表实际的音频硬件。所有主动渲染音频的 AudioNode 都将直接或间接地连接到 destination

listener, 类型 AudioListener, 只读

一个用于 3D 空间化AudioListener

onstatechange, 类型 EventHandler

一个用于为事件设置事件处理程序的属性,该事件在 AudioContext 状态发生变化(即相应 promise 应该解析时)时分发给 BaseAudioContext。此事件处理程序的事件类型为 statechange。一个使用 Event 接口的事件将分发给该事件处理程序,它可以直接查询 AudioContext 的状态。一个新创建的 AudioContext 将始终以 suspended 状态开始,每当状态变为不同状态时,都会触发一个状态更改事件。此事件在 complete 事件触发之前触发。

sampleRate, 类型 float, 只读

BaseAudioContext 处理音频的采样率(每秒采样帧数)。假设上下文中的所有 AudioNode 都以此速率运行。基于此假设,实时处理中不支持采样率转换器或“变速”处理器。奈奎斯特频率 (Nyquist frequency) 是此采样率值的一半。

state, 类型 AudioContextState, 只读

描述 BaseAudioContext 的当前状态。获取此属性会返回 [[control thread state]] 槽的内容。

renderQuantumSize, 类型 unsigned long, 只读

获取此属性会返回 [[render quantum size]] 槽的值。

1.1.2. 方法

createAnalyser()

工厂方法,用于创建一个 AnalyserNode

无参数。
返回类型: AnalyserNode
createBiquadFilter()

工厂方法,用于创建一个代表二阶滤波器的 BiquadFilterNode,该滤波器可配置为多种常见滤波器类型之一。

无参数。
返回类型: BiquadFilterNode
createBuffer(numberOfChannels, length, sampleRate)

创建一个给定大小的 AudioBuffer。缓冲区中的音频数据将被零初始化(静音)。如果任何参数为负数、零或超出其标称范围,则必须抛出 NotSupportedError 异常。

BaseAudioContext.createBuffer() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
numberOfChannels unsigned long 确定缓冲区将具有多少个声道。实现必须至少支持 32 个声道。
length unsigned long 确定缓冲区的大小(以采样帧为单位)。这必须至少为 1。
sampleRate float 描述缓冲区中线性 PCM 音频数据的采样率(以每秒采样帧数为单位)。实现必须至少支持 8000 到 96000 范围内的采样率。
返回类型: AudioBuffer
createBufferSource()

工厂方法,用于创建一个 AudioBufferSourceNode

无参数。
返回类型: AudioBufferSourceNode
createChannelMerger(numberOfInputs)

工厂方法,用于创建一个代表声道合并器的 ChannelMergerNode如果 numberOfInputs 小于 1 或大于支持的声道数,则必须抛出 IndexSizeError 异常。

BaseAudioContext.createChannelMerger(numberOfInputs) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
numberOfInputs unsigned long 确定输入数量。必须支持最多 32 个输入。如果未指定,则使用 6
返回类型: ChannelMergerNode
createChannelSplitter(numberOfOutputs)

工厂方法,用于创建一个代表声道拆分器的 ChannelSplitterNode如果 numberOfOutputs 小于 1 或大于支持的声道数,则必须抛出 IndexSizeError 异常。

BaseAudioContext.createChannelSplitter(numberOfOutputs) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
numberOfOutputs unsigned long 输出数量。必须支持最多 32 个输出。如果未指定,则使用 6
返回类型: ChannelSplitterNode
createConstantSource()

工厂方法,用于创建一个 ConstantSourceNode

无参数。
返回类型: ConstantSourceNode
createConvolver()

工厂方法,用于创建一个 ConvolverNode

无参数。
返回类型: ConvolverNode
createDelay(maxDelayTime)

工厂方法,用于创建一个 DelayNode。初始默认延迟时间为 0 秒。

BaseAudioContext.createDelay(maxDelayTime) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
maxDelayTime double 指定允许延迟线使用的最大延迟时间(以秒为单位)。如果指定,该值必须大于零且小于三分钟,否则必须抛出 NotSupportedError 异常。如果未指定,则使用 1
返回类型: DelayNode
createDynamicsCompressor()

工厂方法,用于创建一个 DynamicsCompressorNode

无参数。
返回类型: DynamicsCompressorNode
createGain()

工厂方法,用于 GainNode

无参数。
返回类型: GainNode
createIIRFilter(feedforward, feedback)
BaseAudioContext.createIIRFilter() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
feedforward sequence<double> IIR 滤波器传递函数的前馈(分子)系数数组。此数组的最大长度为 20。如果所有值均为零,必须抛出 InvalidStateError如果数组长度为 0 或大于 20,必须抛出 NotSupportedError
feedback sequence<double> IIR 滤波器传递函数的反馈(分母)系数数组。此数组的最大长度为 20。如果数组的第一个元素为 0,必须抛出 InvalidStateError如果数组长度为 0 或大于 20,必须抛出 NotSupportedError
返回类型: IIRFilterNode
createOscillator()

工厂方法,用于创建一个 OscillatorNode

无参数。
返回类型: OscillatorNode
createPanner()

工厂方法,用于创建一个 PannerNode

无参数。
返回类型: PannerNode
createPeriodicWave(real, imag, constraints)

工厂方法,用于创建一个 PeriodicWave

调用此方法时,请执行以下步骤:
  1. 如果 realimag 长度不一致,则必须抛出 IndexSizeError

  2. o 为一个新的 PeriodicWaveOptions 类型对象。

  3. 分别将传递给此工厂方法的 realimag 参数设置为 o 上同名属性的值。

  4. o 上的 disableNormalization 属性设置为传递给该工厂方法的 constraints 属性的 disableNormalization 属性值。

  5. 构造一个新的 PeriodicWave 对象 p,将调用此工厂方法的 BaseAudioContext 作为第一个参数传入,以及 o

  6. 返回 p

BaseAudioContext.createPeriodicWave() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
real sequence<float> 余弦参数序列。有关更详细的描述,请参见其 real 构造函数参数。
imag sequence<float> 正弦参数序列。有关更详细的描述,请参见其 imag 构造函数参数。
constraints PeriodicWaveConstraints 如果不提供,波形将被归一化。否则,波形将根据 constraints 给出的值进行归一化。
返回类型: PeriodicWave
createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels)

ScriptProcessorNode工厂方法。此方法已弃用,旨在被 AudioWorkletNode 取代。创建用于通过脚本进行直接音频处理的 ScriptProcessorNode如果 bufferSizenumberOfInputChannelsnumberOfOutputChannels 超出有效范围,则必须抛出 IndexSizeError 异常。

numberOfInputChannelsnumberOfOutputChannels 同时为零是不合法的。在这种情况下,必须抛出 IndexSizeError

BaseAudioContext.createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
bufferSize unsigned long bufferSize 参数决定了缓冲区的大小(以采样帧为单位)。如果不传递该值,或者如果该值为 0,实现将根据给定环境选择最佳的缓冲区大小,该值在节点生命周期内将保持为 2 的幂。如果作者明确指定了 bufferSize,则它必须是以下值之一:256、512、1024、2048、4096、8192、16384。此值控制 audioprocess 事件的分发频率以及每次调用需要处理多少采样帧。较低的 bufferSize 值会导致更低(更好)的延迟。更高的值对于避免音频中断和故障是必要的。建议作者不要指定此缓冲区大小,而应让实现选择一个好的缓冲区大小,以平衡延迟和音频质量。如果该参数的值不是上述列出的允许的 2 的幂值之一,必须抛出 IndexSizeError
numberOfInputChannels unsigned long 此参数确定此节点的输入通道数。默认值为 2。必须支持最多 32 个通道。如果不支持通道数,则必须抛出 NotSupportedError
numberOfOutputChannels unsigned long 此参数确定此节点的输出通道数。默认值为 2。必须支持最多 32 个通道。如果不支持通道数,则必须抛出 NotSupportedError
返回类型: ScriptProcessorNode
createStereoPanner()

StereoPannerNode工厂方法

无参数。
返回类型: StereoPannerNode
createWaveShaper()

表示非线性失真的 WaveShaperNode工厂方法

无参数。
返回类型: WaveShaperNode
decodeAudioData(audioData, successCallback, errorCallback)

异步解码 ArrayBuffer 中包含的音频文件数据。ArrayBuffer 例如可以在将 responseType 设置为 "arraybuffer" 后从 XMLHttpRequestresponse 属性加载。音频文件数据可以是 audio 元素支持的任何格式。传递给 decodeAudioData() 的缓冲区其内容类型由嗅探确定,如 [mimesniff] 中所述。

虽然与此函数交互的主要方法是通过其返回的 Promise 值,但仍出于遗留原因提供了回调参数。

鼓励实现在文件损坏时警告作者。无法抛出异常,因为这会是一个破坏性更改。

注意:如果压缩的音频数据字节流已损坏,但解码仍可继续,则鼓励实现通过开发人员工具等方式警告作者。
当调用 decodeAudioData 时,必须在控制线程上执行以下步骤
  1. 如果 this相关全局对象关联文档不是 完全活跃的,则返回一个以 "InvalidStateError" DOMException 拒绝的 Promise

  2. promise 为一个新的 Promise。

  3. 如果 audioData分离,执行以下步骤

    1. promise 添加到 [[pending promises]] 中。

    2. 分离 audioData ArrayBuffer。如果此操作抛出异常,跳转至第 3 步。

    3. 将解码操作排队,以便在另一个线程上执行。

  4. 否则,执行以下错误步骤

    1. errorDataCloneError

    2. 使用 error 拒绝 promise,并将其从 [[pending promises]] 中移除。

    3. 排队一个媒体元素任务,以使用 error 调用 errorCallback

  5. 返回 promise

当排队一个要在另一个线程上执行的解码操作时,以下步骤必须在一个既不是控制线程也不是渲染线程的线程上发生,该线程称为 解码线程

注意: 多个 解码线程 可以并行运行,以服务于对 decodeAudioData 的多次调用。

  1. can decode 为一个布尔标志,初始设置为 true。

  2. 尝试使用 MIME 嗅探 § 6.2 匹配音频或视频类型模式来确定 audioData 的 MIME 类型。如果音频或视频类型模式匹配算法返回 undefined,则将 can decode 设置为 false

  3. 如果 can decodetrue,尝试将编码后的 audioData 解码为 线性 PCM。如果失败,将 can decode 设置为 false

    如果媒体字节流包含多个音频轨道,则仅将第一个轨道解码为 线性 pcm

    注意: 需要对解码过程有更多控制的作者可以使用 [WEBCODECS]

  4. 如果 can decodefalse 排队一个媒体元素任务以执行以下步骤

    1. error 为一个名称为 EncodingErrorDOMException

      1. 使用 error 拒绝 promise,并将其从 [[pending promises]] 中移除。

    2. 如果 errorCallback 未缺失,则使用 error 调用 errorCallback

  5. 否则

    1. 获取表示解码后的 线性 PCM 音频数据的结果,如果其采样率与 audioData 的采样率不同,则将其重采样为 BaseAudioContext 的采样率。

    2. 排队一个媒体元素任务以执行以下步骤

      1. buffer 为包含最终结果(在可能执行重采样后)的 AudioBuffer

      2. 使用 buffer 解析 promise

      3. 如果 successCallback 未缺失,则使用 buffer 调用 successCallback

BaseAudioContext.decodeAudioData() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
audioData ArrayBuffer 包含压缩音频数据的 ArrayBuffer。
successCallback DecodeSuccessCallback? 解码完成时调用的回调函数。此回调的唯一参数是一个 AudioBuffer,表示解码后的 PCM 音频数据。
errorCallback DecodeErrorCallback? 如果解码音频文件时出现错误,将调用的回调函数。
返回类型: Promise<AudioBuffer>

1.1.3. 回调 DecodeSuccessCallback() 参数

decodedData,类型为 AudioBuffer

包含解码后的音频数据的 AudioBuffer。

1.1.4. 回调 DecodeErrorCallback() 参数

error,类型为 DOMException

解码时发生的错误。

1.1.5. 生命周期

一旦创建,AudioContext 将持续播放声音,直到没有声音可播放,或者页面关闭。

1.1.6. 缺乏内省或序列化原语

Web Audio API 对音频源调度采取发后即忘的方法。也就是说,在 AudioContext 的生命周期内,每个音符都会创建源节点,并且永远不会显式地从图中移除。这与序列化 API 不兼容,因为没有一组可以序列化的稳定节点。

此外,拥有内省 API 将允许内容脚本能够观察垃圾回收。

1.1.7. BaseAudioContext 子类关联的系统资源

子类 AudioContextOfflineAudioContext 应被视为昂贵的对象。创建这些对象可能涉及创建高优先级线程,或使用低延迟系统音频流,这两者都会对能源消耗产生影响。在一个文档中通常没有必要创建多个 AudioContext

构建或恢复 BaseAudioContext 子类涉及获取该上下文的系统资源。对于 AudioContext,这还需要创建一个系统音频流。当上下文开始从其关联的音频图中生成输出时,这些操作返回。

此外,用户代理可以具有实现定义的 AudioContext 最大数量,超过该数量后,任何创建新 AudioContext 的尝试都将失败,并抛出 NotSupportedError

suspendclose 允许作者释放系统资源,包括线程、进程和音频流。挂起 BaseAudioContext 允许实现释放其部分资源,并允许通过调用 resume 稍后继续操作。关闭 AudioContext 允许实现释放其所有资源,之后它将无法再次使用或恢复。

Note: 例如,这可能涉及等待音频回调定期触发,或等待硬件准备好进行处理。

1.2. AudioContext 接口

此接口表示一个音频图,其 AudioDestinationNode 被路由到产生导向用户的信号的实时输出设备。在大多数用例中,每个文档仅使用单个 AudioContext

enum AudioContextLatencyCategory {
        "balanced",
        "interactive",
        "playback"
};
AudioContextLatencyCategory 枚举描述
枚举值描述
"balanced"平衡音频输出延迟和功耗。
"interactive"在不产生故障的前提下提供尽可能低的音频输出延迟。这是默认值。
"playback"优先考虑持续播放而不中断,而不是音频输出延迟。最低功耗。
enum AudioSinkType {
    "none"
};
AudioSinkType 枚举描述
枚举值描述
"none"音频图将在不通过音频输出设备播放的情况下进行处理。
[Exposed=Window]
interface AudioContext : BaseAudioContext {
    constructor (optional AudioContextOptions contextOptions = {});
    readonly attribute double baseLatency;
    readonly attribute double outputLatency;
    [SecureContext] readonly attribute (DOMString or AudioSinkInfo) sinkId;
    [SecureContext] readonly attribute AudioRenderCapacity renderCapacity;
    attribute EventHandler onsinkchange;
    attribute EventHandler onerror;
    AudioTimestamp getOutputTimestamp ();
    Promise<undefined> resume ();
    Promise<undefined> suspend ();
    Promise<undefined> close ();
    [SecureContext] Promise<undefined> setSinkId ((DOMString or AudioSinkOptions) sinkId);
    MediaElementAudioSourceNode createMediaElementSource (HTMLMediaElement mediaElement);
    MediaStreamAudioSourceNode createMediaStreamSource (MediaStream mediaStream);
    MediaStreamTrackAudioSourceNode createMediaStreamTrackSource (
        MediaStreamTrack mediaStreamTrack);
    MediaStreamAudioDestinationNode createMediaStreamDestination ();
};

如果用户代理允许上下文状态从 "suspended" 转换为 "running",则称 AudioContext 被允许启动。用户代理可以禁止此初始转换,并仅当 AudioContext相关全局对象具有 粘性激活时才允许它。

AudioContext 具有以下内部槽位

[[suspended by user]]

一个布尔标志,表示上下文是否由用户代码挂起。初始值为 false

[[sink ID]]

一个分别表示当前音频输出设备标识符或信息的 DOMStringAudioSinkInfo。初始值为 "",表示默认音频输出设备。

[[pending resume promises]]

用于存储由 resume() 创建的挂起 Promise 的有序列表。它最初为空。

1.2.1. 构造函数

AudioContext(contextOptions)

如果 当前设置对象相关全局对象关联文档不是 完全活跃的,抛出一个 "InvalidStateError" 并中止这些步骤。

创建 AudioContext 时,执行这些步骤
  1. context 为一个新的 AudioContext 对象。

  2. context 上设置一个 [[控制线程状态]]suspended

  3. context 上设置一个 [[渲染线程状态]]suspended

  4. messageChannel 为一个新的 MessageChannel

  5. controlSidePortmessageChannelport1 属性的值。

  6. renderingSidePortmessageChannelport2 属性的值。

  7. serializedRenderingSidePortStructuredSerializeWithTransfer(renderingSidePort, « renderingSidePort ») 的结果。

  8. 将此 audioWorkletport 设置为 controlSidePort

  9. 排队一个控制消息,以在 AudioContextGlobalScope 上设置 MessagePort,使用 serializedRenderingSidePort

  10. 如果提供了 contextOptions,执行以下子步骤

    1. 如果指定了 sinkId,令 sinkIdcontextOptions.sinkId 的值,并运行以下子步骤

      1. 如果 sinkId[[sink ID]] 均为 DOMString 类型,且它们彼此相等,中止这些子步骤。

      2. 如果 sinkIdAudioSinkOptions 类型,而 [[sink ID]]AudioSinkInfo 类型,且 sinkId 中的 type[[sink ID]] 中的 type 相等,中止这些子步骤。

      3. validationResultsink 标识符验证 sinkId 的返回值。

      4. 如果 validationResultDOMException 类型,抛出一个带有 validationResult 的异常并中止这些子步骤。

      5. 如果 sinkIdDOMString 类型,将 [[sink ID]] 设置为 sinkId 并中止这些子步骤。

      6. 如果 sinkIdAudioSinkOptions 类型,将 [[sink ID]] 设置为使用 sinkIdtype 值创建的 AudioSinkInfo 的新实例。

    2. 根据 contextOptions.latencyHint 设置 context 的内部延迟,如 latencyHint 中所述。

    3. 如果指定了 contextOptions.sampleRate ,将 contextsampleRate 设置为此值。否则,遵循这些子步骤

      1. 如果 sinkId 是空字符串或 AudioSinkOptions 类型,使用默认输出设备的采样率。中止这些子步骤。

      2. 如果 sinkIdDOMString,使用 sinkId 标识的输出设备的采样率。中止这些子步骤。

      如果 contextOptions.sampleRate 与输出设备的采样率不同,用户代理必须对音频输出进行重采样以匹配输出设备的采样率。

      Note: 如果需要重采样,context 的延迟可能会受到影响,可能幅度很大。

  11. 如果 context允许启动,发送一个控制消息以开始处理。

  12. 返回 context

发送一个控制消息以开始处理意味着执行以下步骤
  1. document当前设置对象相关全局对象关联文档

  2. 尝试获取系统资源,以根据 [[sink ID]] 使用以下音频输出设备进行渲染

    • 空字符串的默认音频输出设备。

    • [[sink ID]] 标识的音频输出设备。

    1. 如果资源获取失败,执行以下步骤

      1. 如果 document 不被允许使用由 "speaker-selection" 标识的功能,中止这些子步骤。

      2. 排队一个媒体元素任务,以在 AudioContext触发一个名为 error 的事件,并中止以下步骤。

  3. AudioContext 上设置 this[[渲染线程状态]]running

  4. 排队一个媒体元素任务以执行以下步骤

    1. AudioContextstate 属性设置为 "running"。

    2. AudioContext 上触发一个名为 statechange 的事件。

NOTE:AudioContext 无参数构造且资源获取失败的情况下,用户代理将尝试使用模拟音频输出设备的机制静默渲染音频图。

发送一个控制消息以在 AudioWorkletGlobalScope 上设置 MessagePort 意味着在渲染线程上执行以下步骤,并使用已传输到 AudioWorkletGlobalScopeserializedRenderingSidePort
  1. deserializedPortStructuredDeserialize(serializedRenderingSidePort, 当前 Realm) 的结果。

  2. port 设置为 deserializedPort

AudioContext.constructor(contextOptions) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
contextOptions AudioContextOptions 用户指定的控制 AudioContext 应如何构建的选项。

1.2.2. 属性

baseLatency, 类型为 double,只读

这表示 AudioContext 将音频从 AudioDestinationNode 传递到音频子系统所产生的处理延迟(以秒为单位)。它不包括 AudioDestinationNode 的输出与音频硬件之间的任何其他处理可能导致的额外延迟,特别是不包括音频图本身产生的任何延迟。

例如,如果音频上下文以 44.1 kHz 运行,且具有默认渲染量子大小,并且 AudioDestinationNode 在内部实现双缓冲,并且每个 渲染量子 都可以处理和输出音频,那么处理延迟约为 \((2\cdot128)/44100 = 5.805 \mathrm{ ms}\)。

outputLatency, 类型为 double,只读

音频输出延迟的秒数估计,即 UA 请求宿主系统播放缓冲区的时间与缓冲区中的第一个采样实际被音频输出设备处理的时间之间的时间间隔。对于产生声学信号的扬声器或耳机等设备,后者时间指声音产生的时间。

outputLatency 属性值取决于平台和连接的音频输出设备硬件。outputLatency 属性值在上下文运行或相关音频输出设备更改时可能会发生变化。当需要精确同步时,经常查询此值很有用。

renderCapacity, 类型为 AudioRenderCapacity,只读

返回与 AudioContext 关联的 AudioRenderCapacity 实例。

sinkId, 类型为 (DOMString or AudioSinkInfo),只读

返回 [[sink ID]] 内部槽位的值。此属性在更新时被缓存,并且在缓存后返回相同的对象。

onsinkchange, 类型为 EventHandler

setSinkId()事件处理程序。此事件处理程序的事件类型为 sinkchange。当更改输出设备完成时,将分发此事件。

NOTE: 这不会为 AudioContext 构建时的初始设备选择分发。statechange 事件可用于检查初始输出设备的就绪状态。

onerror, 类型为 EventHandler

AudioContext 分发的 Event事件处理程序。此处理程序的事件类型为 error,用户代理可以在以下情况下分发此事件

  • 初始化和激活所选音频设备时遇到失败。

  • AudioContextrunning 时其关联的音频输出设备断开连接。

  • 当操作系统报告音频设备故障时。

1.2.3. 方法

close()

关闭 AudioContext释放正在使用的系统资源。这不会自动释放所有 AudioContext 创建的对象,但会挂起 AudioContextcurrentTime 的进程,并停止处理音频数据。

当调用 close 时,执行这些步骤
  1. 如果 this相关全局对象关联文档不是 完全活跃的,则返回一个以 "InvalidStateError" DOMException 拒绝的 Promise

  2. promise 为一个新的 Promise。

  3. 如果 AudioContext 上的 [[控制线程状态]] 标志为 closed,使用 InvalidStateError 拒绝该 promise,中止这些步骤并返回 promise

  4. AudioContext 上的 [[控制线程状态]] 标志设置为 closed

  5. 排队一个控制消息以关闭 AudioContext

  6. 返回 promise

运行一个控制消息以关闭 AudioContext 意味着在渲染线程上运行这些步骤
  1. 尝试释放系统资源

  2. [[渲染线程状态]] 设置为 suspended

    这将停止渲染。
  3. 如果此控制消息是作为对文档卸载的反应而运行的,则中止此算法。

    在这种情况下,无需通知控制线程。
  4. 排队一个媒体元素任务以执行以下步骤

    1. 解析 promise

    2. 如果 AudioContextstate 属性尚未为 "closed"

      1. AudioContextstate 属性设置为 "closed"。

      2. 排队一个媒体元素任务AudioContext 上触发一个名为 statechange 的事件。

当一个 AudioContext 被关闭时,任何连接到 AudioContextMediaStreamHTMLMediaElement 的输出将被忽略。也就是说,它们将不再导致扬声器或其他输出设备发出任何输出。为了获得更灵活的行为,请考虑使用 HTMLMediaElement.captureStream()

Note: 当一个 AudioContext 被关闭时,实现可以选择比挂起时更积极地释放资源。

无参数。
返回类型: Promise<undefined>
createMediaElementSource(mediaElement)

根据 HTMLMediaElement 创建一个 MediaElementAudioSourceNode。作为调用此方法的结果,来自 HTMLMediaElement 的音频播放将被重新路由到 AudioContext 的处理图中。

AudioContext.createMediaElementSource() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
mediaElement HTMLMediaElement 将被重新路由的媒体元素。
返回类型: MediaElementAudioSourceNode
createMediaStreamDestination()

创建一个 MediaStreamAudioDestinationNode

无参数。
返回类型: MediaStreamAudioDestinationNode
createMediaStreamSource(mediaStream)

创建一个 MediaStreamAudioSourceNode

AudioContext.createMediaStreamSource() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
mediaStream MediaStream 将作为源的媒体流。
返回类型: MediaStreamAudioSourceNode
createMediaStreamTrackSource(mediaStreamTrack)

创建一个 MediaStreamTrackAudioSourceNode

AudioContext.createMediaStreamTrackSource() 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
mediaStreamTrack MediaStreamTrack 将作为源的 MediaStreamTrackkind 属性的值必须等于 "audio",否则必须抛出 InvalidStateError 异常。
返回类型: MediaStreamTrackAudioSourceNode
getOutputTimestamp()

返回一个新的 AudioTimestamp 实例,其中包含两个上下文相关的音频流位置值:contextTime 成员包含当前由音频输出设备渲染的采样帧的时间(即输出音频流位置),其单位和原点与上下文的 currentTime 相同;performanceTime 成员包含估计的时间,表示存储的 contextTime 值对应的采样帧由音频输出设备渲染的时刻,其单位和原点与 performance.now() 相同(如 [hr-time-3] 中所述)。

如果上下文的渲染图尚未处理音频块,则 getOutputTimestamp 调用返回一个两个成员都包含零的 AudioTimestamp 实例。

在上下文的渲染图开始处理音频块后,其 currentTime 属性值总是超过从 getOutputTimestamp 方法调用获得的 contextTime 值。

getOutputTimestamp 方法返回的值可用于获取稍后上下文时间值的性能时间估计
function outputPerformanceTime(contextTime) {
    const timestamp = context.getOutputTimestamp();
    const elapsedTime = contextTime - timestamp.contextTime;
    return timestamp.performanceTime + elapsedTime * 1000;
}

在上述示例中,估计的准确性取决于参数值与当前输出音频流位置的接近程度:给定的 contextTime 越接近 timestamp.contextTime,获得的估计准确性越高。

Note: 上下文的 currentTime 值与从 getOutputTimestamp 方法调用获得的 contextTime 值之间的差值不能视为可靠的输出延迟估计,因为 currentTime 可能会以非均匀的时间间隔递增,因此应使用 outputLatency 属性。

无参数。
返回类型: AudioTimestamp
resume()

在挂起时恢复 AudioContextcurrentTime 的进程。

当调用 resume 时,执行这些步骤
  1. 如果 this相关全局对象关联文档不是 完全活跃的,则返回一个以 "InvalidStateError" DOMException 拒绝的 Promise

  2. promise 为一个新的 Promise。

  3. 如果 AudioContext 上的 [[控制线程状态]]closed,使用 InvalidStateError 拒绝该 promise,中止这些步骤并返回 promise

  4. [[suspended by user]] 设置为 false

  5. 如果上下文未被允许启动,将 promise 添加到 [[pending promises]][[pending resume promises]] 中,并中止这些步骤,返回 promise

  6. AudioContext 上的 [[控制线程状态]] 设置为 running

  7. 排队一个控制消息以恢复 AudioContext

  8. 返回 promise

运行一个控制消息以恢复 AudioContext 意味着在渲染线程上运行这些步骤
  • 尝试获取系统资源

  • AudioContext 上的 [[渲染线程状态]] 设置为 running

  • 开始渲染音频图

  • 如果失败, 排队一个媒体元素任务以执行以下步骤

    1. 按顺序拒绝来自 [[pending resume promises]] 的所有 promise,然后清除 [[pending resume promises]]

    2. 此外,从 [[pending promises]] 中移除这些 promise。

  • 排队一个媒体元素任务以执行以下步骤

    1. 按顺序解析来自 [[pending resume promises]] 的所有 promise。

    2. 清除 [[pending resume promises]]。此外,从 [[pending promises]] 中移除这些 promise。

    3. 解析 promise

    4. 如果 AudioContextstate 属性尚未为 "running"

      1. AudioContextstate 属性设置为 "running"。

      2. 排队一个媒体元素任务AudioContext 上触发一个名为 statechange 的事件。

  • 无参数。
    返回类型: Promise<undefined>
    suspend()

    挂起 AudioContextcurrentTime 的进程,允许将已处理的任何当前上下文处理块播放到目的地,然后允许系统释放其对音频硬件的占用。这通常在应用程序知道它将在一段时间内不需要 AudioContext,并希望暂时释放系统资源AudioContext 相关联时非常有用。当帧缓冲区为空(已移交给硬件)时,promise 解析;如果上下文已处于 suspended 状态,则立即解析(无其他效果)。如果上下文已关闭,promise 将被拒绝。

    当调用 suspend 时,执行这些步骤
    1. 如果 this相关全局对象关联文档 不是 完全活动 的,则返回一个被 "InvalidStateError" DOMException 拒绝的 promise

    2. promise 为一个新的 Promise。

    3. 如果 AudioContext 上的 [[control thread state]]closed,则用 InvalidStateError 拒绝该 promise,中止这些步骤,并返回 promise

    4. promise 添加到 [[pending promises]] 中。

    5. [[suspended by user]] 设置为 true

    6. AudioContext 上的 [[control thread state]] 设置为 suspended

    7. 排队一个控制消息以挂起 AudioContext

    8. 返回 promise

    运行一个用于挂起 AudioContext控制消息,意味着在 渲染线程 上执行以下步骤
    1. 尝试 释放系统资源

    2. AudioContext 上的 [[rendering thread state]] 设置为 suspended

    3. 排队一个媒体元素任务以执行以下步骤

      1. 解析 promise

      2. 如果 AudioContextstate 属性尚不是 "suspended"

        1. AudioContextstate 属性设置为 "suspended"。

        2. 排队一个媒体元素任务,以在 AudioContext触发一个名为 statechange 的事件。

    AudioContext 被挂起时,MediaStream 的输出将被忽略;也就是说,由于媒体流的实时特性,数据将会丢失。HTMLMediaElement 的输出也将被忽略,直到系统恢复。AudioWorkletNodeScriptProcessorNode 在挂起时将停止调用其处理程序,但会在上下文恢复时恢复。就 AnalyserNode 窗口函数而言,数据被视为连续流——即 resume()/suspend() 不会导致 AnalyserNode 的数据流中出现静音。特别是,当 AudioContext 挂起时,重复调用 AnalyserNode 函数必须返回相同的数据。

    无参数。
    返回类型: Promise<undefined>
    setSinkId((DOMString or AudioSinkOptions) sinkId)

    设置输出设备的标识符。当此方法被调用时,用户代理必须运行以下步骤

    1. sinkId 为该方法的第一个参数。

    2. 如果 sinkId 等于 [[sink ID]],则返回一个 promise,立即将其解析并中止这些步骤。

    3. validationResultsinkIdsink 标识符验证 的返回值。

    4. 如果 validationResult 不为 null,则返回一个被 validationResult 拒绝的 promise。中止这些步骤。

    5. p 为一个新的 promise。

    6. 发送一个包含 psinkId控制消息 以开始处理。

    7. 返回 p

    setSinkId() 期间发送一个用于开始处理的 控制消息,意味着执行以下步骤
    1. p 为传递给此算法的 promise。

    2. sinkId 为传递给此算法的 sink 标识符。

    3. 如果 sinkId[[sink ID]] 均为 DOMString 类型,且它们彼此相等,则 排队一个媒体元素任务 以解析 p 并中止这些步骤。

    4. 如果 sinkIdAudioSinkOptions 类型,[[sink ID]]AudioSinkInfo 类型,且 sinkId 中的 type[[sink ID]] 中的 type 相等,则 排队一个媒体元素任务 以解析 p 并中止这些步骤。

    5. wasRunning 为 true。

    6. 如果 AudioContext 上的 [[rendering thread state]]"suspended",则将 wasRunning 设置为 false。

    7. 在处理完当前渲染量子(render quantum)后暂停渲染器。

    8. 尝试 释放系统资源

    9. 如果 wasRunning 为 true

      1. AudioContext 上的 [[rendering thread state]] 设置为 "suspended"

      2. 排队一个媒体元素任务以执行以下步骤

        1. 如果 AudioContextstate 属性尚不是 "suspended"

          1. AudioContextstate 属性设置为 "suspended"。

          2. 触发一个名为 statechange 的事件,并在关联的 AudioContext 上触发。

    10. 尝试 获取系统资源,以基于 [[sink ID]] 使用后续音频输出设备进行渲染

      • 空字符串的默认音频输出设备。

      • [[sink ID]] 标识的音频输出设备。

      如果失败,则用 "InvalidAccessError" 拒绝 p,中止以下步骤。

    11. 排队一个媒体元素任务以执行以下步骤

      1. 如果 sinkIdDOMString 类型,将 [[sink ID]] 设置为 sinkId。中止这些步骤。

      2. 如果 sinkIdAudioSinkOptions 类型,且 [[sink ID]]DOMString 类型,将 [[sink ID]] 设置为使用 sinkIdtype 值创建的 AudioSinkInfo 的新实例。

      3. 如果 sinkIdAudioSinkOptions 类型,且 [[sink ID]]AudioSinkInfo 类型,将 [[sink ID]]type 设置为 sinkIdtype 值。

      4. 解析 p

      5. 触发一个名为 sinkchange 的事件,并在关联的 AudioContext 上触发。

    12. 如果 wasRunning 为 true

      1. AudioContext 上的 [[rendering thread state]] 设置为 "running"

      2. 排队一个媒体元素任务以执行以下步骤

        1. 如果 AudioContextstate 属性尚不是 "running"

          1. AudioContextstate 属性设置为 "running"。

          2. 触发一个名为 statechange 的事件,并在关联的 AudioContext 上触发。

    1.2.4. 验证 sinkId

    此算法用于验证为修改 sinkId 而提供的信息

    1. document 为当前设置对象的 关联文档

    2. sinkIdArg 为传递给此算法的值。

    3. 如果 document 不被允许使用由 "speaker-selection" 标识的功能,则返回一个新的 DOMException,其名称为 "NotAllowedError"。

    4. 如果 sinkIdArgDOMString 类型,但它既不是空字符串,也不匹配任何由 enumerateDevices() 提供结果所标识的音频输出设备,则返回一个新的 DOMException,其名称为 "NotFoundError"。

    5. 返回 null

    1.2.5. AudioContextOptions

    AudioContextOptions 字典用于指定 AudioContext 的用户自定义选项。

    dictionary AudioContextOptions {
        (AudioContextLatencyCategory or double) latencyHint = "interactive";
        float sampleRate;
        (DOMString or AudioSinkOptions) sinkId;
        (AudioContextRenderSizeCategory or unsigned long) renderSizeHint = "default";
    };
    
    1.2.5.1. 字典 AudioContextOptions 成员
    latencyHint, 类型为 (AudioContextLatencyCategory 或 double),默认为 "interactive"

    标识播放类型,这会影响音频输出延迟与功耗之间的权衡。

    latencyHint 的首选值是来自 AudioContextLatencyCategory 的值。但是,也可以指定一个 double 类型的值作为延迟秒数,以更精细地控制延迟与功耗的平衡。浏览器有权自行解释该数值。实际使用的延迟由 AudioContextbaseLatency 属性给出。

    sampleRate, 类型为 float

    将创建的 AudioContextsampleRate 设置为此值。支持的值与 AudioBuffer 的采样率相同。如果不支持指定的采样率,则必须抛出 NotSupportedError 异常。

    如果未指定 sampleRate,则使用此 AudioContext 的输出设备的首选采样率。

    sinkId, 类型为 (DOMString 或 AudioSinkOptions)

    音频输出设备的标识符或相关信息。更多详情请参阅 sinkId

    renderSizeHint, 类型为 (AudioContextRenderSizeCategory 或 unsigned long),默认为 "default"

    这允许用户在传入整数时请求特定的 渲染量子大小,在不传参或传入 "default" 时使用默认的 128 帧,或者在指定 "hardware" 时请求用户代理选择一个合适的 渲染量子大小

    这只是一个提示,可能不被采纳。

    1.2.6. AudioSinkOptions

    AudioSinkOptions 字典用于为 sinkId 指定选项。

    dictionary AudioSinkOptions {
        required AudioSinkType type;
    };
    
    1.2.6.1. 字典 AudioSinkOptions 成员
    type, 类型为 AudioSinkType

    AudioSinkType 的一个值,用于指定设备的类型。

    1.2.7. AudioSinkInfo

    AudioSinkInfo 接口用于通过 sinkId 获取当前音频输出设备的信息。

    [Exposed=Window]
    interface AudioSinkInfo {
        readonly attribute AudioSinkType type;
    };
    
    1.2.7.1. 属性
    type, 类型为 AudioSinkType,只读

    表示设备类型的一个 AudioSinkType 值。

    1.2.8. AudioTimestamp

    dictionary AudioTimestamp {
        double contextTime;
        DOMHighResTimeStamp performanceTime;
    };
    
    1.2.8.1. 字典 AudioTimestamp 成员
    contextTime, 类型为 double

    表示 BaseAudioContext 的 currentTime 时间坐标系中的一个点。

    performanceTime, 类型为 DOMHighResTimeStamp

    表示 Performance 接口实现的时间坐标系中的一个点(详见 [hr-time-3])。

    1.2.9. AudioRenderCapacity

    [Exposed=Window]
    interface AudioRenderCapacity : EventTarget {
        undefined start(optional AudioRenderCapacityOptions options = {});
            undefined stop();
            attribute EventHandler onupdate;
    };
    

    此接口提供了 AudioContext 的渲染性能指标。为了计算这些指标,渲染器会针对每个 系统级音频回调 收集一个 负载值

    1.2.9.1. 属性
    onupdate, 类型为 EventHandler

    此事件处理程序的事件类型是 update。分发给此事件处理程序的事件将使用 AudioRenderCapacityEvent 接口。

    1.2.9.2. 方法
    start(options)

    开始指标收集和分析。这将根据 AudioRenderCapacityOptions 中给定的更新间隔,反复在 AudioRenderCapacity触发一个名为 update 的事件,并使用 AudioRenderCapacityEvent

    stop()

    停止指标收集和分析。它也会停止分发 update 事件。

    1.2.10. AudioRenderCapacityOptions

    AudioRenderCapacityOptions 字典可用于为 AudioRenderCapacity 提供用户选项。

    dictionary AudioRenderCapacityOptions {
            double updateInterval = 1;
    };
    
    1.2.10.1. 字典 AudioRenderCapacityOptions 成员
    updateInterval, 类型为 double,默认为 1

    用于分发 AudioRenderCapacityEvent 的更新间隔(以秒为单位)。针对每个 系统级音频回调 计算一个 负载值,并且会在指定的间隔周期内收集多个负载值。例如,如果渲染器以 48Khz 的采样率运行,且 系统级音频回调 的缓冲区大小为 192 帧,则在 1 秒的间隔内将收集 250 个负载值。

    如果给定值小于 系统级音频回调 的持续时间,则抛出 NotSupportedError

    1.2.11. AudioRenderCapacityEvent

    [Exposed=Window]
    interface AudioRenderCapacityEvent : Event {
        constructor (DOMString type, optional AudioRenderCapacityEventInit eventInitDict = {});
            readonly attribute double timestamp;
            readonly attribute double averageLoad;
            readonly attribute double peakLoad;
            readonly attribute double underrunRatio;
    };
    
    dictionary AudioRenderCapacityEventInit : EventInit {
        double timestamp = 0;
        double averageLoad = 0;
        double peakLoad = 0;
        double underrunRatio = 0;
    };
    
    1.2.11.1. 属性
    timestamp, 类型为 double,只读

    数据收集周期的开始时间,以关联的 AudioContextcurrentTime 表示。

    averageLoad, 类型为 double,只读

    在给定更新间隔内收集的负载值的平均值。精度限制为 1/100。

    peakLoad, 类型为 double,只读

    在给定更新间隔内收集的负载值中的最大值。精度同样限制为 1/100。

    underrunRatio, 类型为 double,只读

    在给定更新间隔内,缓冲区欠载(负载值大于 1.0)次数与 系统级音频回调 总次数之间的比率。

    其中 \(u\) 是缓冲区欠载次数,\(N\) 是在给定更新间隔内 系统级音频回调 的总次数,缓冲区欠载比率为

    • 如果 \(u\) = 0,则为 0.0。

    • 否则,计算 \(u/N\) 并取最接近 100 分之一的向上取整值。

    1.3. OfflineAudioContext 接口

    OfflineAudioContext 是一种特殊的 BaseAudioContext,用于(可能)比实时更快的渲染/混音。它不渲染到音频硬件,而是尽可能快地进行渲染,并将渲染结果作为 AudioBuffer 履行返回的 promise。

    [Exposed=Window]
    interface OfflineAudioContext : BaseAudioContext {
        constructor(OfflineAudioContextOptions contextOptions);
        constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate);
        Promise<AudioBuffer> startRendering();
        Promise<undefined> resume();
        Promise<undefined> suspend(double suspendTime);
        readonly attribute unsigned long length;
        attribute EventHandler oncomplete;
    };
    

    1.3.1. 构造函数

    OfflineAudioContext(contextOptions)

    如果 当前设置对象相关全局对象关联文档 不是 完全活动 的,则抛出 InvalidStateError 并中止这些步骤。

    c 为一个新的 OfflineAudioContext 对象。按如下方式初始化 c
    1. c[[control thread state]] 设置为 "suspended"

    2. c[[rendering thread state]] 设置为 "suspended"

    3. 基于 renderSizeHint 的值,确定此 OfflineAudioContext[[render quantum size]]

      1. 如果其默认值为 "default""hardware",则将 [[render quantum size]] 私有槽位设置为 128。

      2. 否则,如果传入的是一个整数,则用户代理可以决定通过将其设置为 [[render quantum size]] 私有槽位来采纳此值。

    4. 构建一个 AudioDestinationNode,其 channelCount 设置为 contextOptions.numberOfChannels

    5. messageChannel 为一个新的 MessageChannel

    6. controlSidePortmessageChannelport1 属性的值。

    7. renderingSidePortmessageChannelport2 属性的值。

    8. serializedRenderingSidePortStructuredSerializeWithTransfer(renderingSidePort, « renderingSidePort ») 的结果。

    9. 将此 audioWorkletport 设置为 controlSidePort

    10. 排队一个控制消息以在 AudioContext设置 AudioContextGlobalScope 上的 MessagePort,并传入 serializedRenderingSidePort

    OfflineAudioContext.constructor(contextOptions) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    contextOptions 构建此上下文所需的初始参数。
    OfflineAudioContext(numberOfChannels, length, sampleRate)

    OfflineAudioContext 可以使用与 AudioContext.createBuffer 相同的参数进行构建。如果任何参数为负数、零或超出其标称范围,则必须抛出 NotSupportedError 异常。

    构建 OfflineAudioContext 的过程等同于

    new OfflineAudioContext({
            numberOfChannels: numberOfChannels,
            length: length,
            sampleRate: sampleRate
    })
    

    调用以下方法。

    OfflineAudioContext.constructor(numberOfChannels, length, sampleRate) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    numberOfChannels unsigned long 确定缓冲区将具有多少个通道。支持的通道数请参阅 createBuffer()
    length unsigned long 确定以采样帧为单位的缓冲区大小。
    sampleRate float 描述缓冲区中 线性 PCM 音频数据的采样率(以每秒采样帧数为单位)。有效采样率请参阅 createBuffer()

    1.3.2. 属性

    length, 类型为 unsigned long,只读

    缓冲区的大小(以采样帧为单位)。这与构造函数中 length 参数的值相同。

    oncomplete, 类型为 EventHandler

    此事件处理程序的事件类型是 complete。分发给此事件处理程序的事件将使用 OfflineAudioCompletionEvent 接口。这是在 OfflineAudioContext 上触发的最后一个事件。

    1.3.3. 方法

    startRendering()

    基于当前的连接和预定的更改,开始渲染音频。

    虽然获取渲染音频数据的主要方法是通过其 promise 返回值,但出于遗留原因,该实例也会触发一个名为 complete 的事件。

    [[rendering started]] 为此 OfflineAudioContext 的一个内部槽位。将此槽位初始化为 false

    当调用 startRendering 时,必须在 控制线程 上执行以下步骤

    1. 如果 this相关全局对象关联文档 不是 完全活动 的,则返回一个被 "InvalidStateError" DOMException 拒绝的 promise
    2. 如果 OfflineAudioContext 上的 [[rendering started]] 槽位为 true,则返回一个被 InvalidStateError 拒绝的 promise,并中止这些步骤。
    3. OfflineAudioContext[[rendering started]] 槽位设置为 true
    4. promise 为一个新的 Promise。
    5. 创建一个新的 AudioBuffer,其通道数、长度和采样率分别等于在 contextOptions 参数中传递给此实例构造函数的 numberOfChannelslengthsampleRate 值。将此缓冲区分配给 OfflineAudioContext 中的一个内部槽位 [[rendered buffer]]
    6. 如果在前面的 AudioBuffer 构造函数调用期间抛出了异常,则用该异常拒绝 promise
    7. 否则,如果缓冲区构建成功,则 开始离线渲染
    8. promise 添加到 [[pending promises]] 中。
    9. 返回 promise
    开始离线渲染,必须在为此专门创建的 渲染线程 上执行以下步骤。
    1. 基于当前的连接和预定的更改,开始将 length 个音频采样帧渲染到 [[rendered buffer]]
    2. 对于每个 渲染量子,检查并在必要时 挂起 渲染。
    3. 如果挂起的上下文恢复,则继续渲染缓冲区。
    4. 一旦渲染完成, 排队一个媒体元素任务以执行以下步骤
      1. [[rendered buffer]] 解析由 startRendering() 创建的 promise
      2. 排队一个媒体元素任务,以在 OfflineAudioContext触发一个名为 complete 的事件,使用 OfflineAudioCompletionEvent,并将其 renderedBuffer 属性设置为 [[rendered buffer]]
    无参数。
    返回类型: Promise<AudioBuffer>
    resume()

    OfflineAudioContextcurrentTime 被挂起时,恢复其进程。

    当调用 resume 时,执行这些步骤
    1. 如果 this相关全局对象关联文档 不是 完全活动 的,则返回一个被 "InvalidStateError" DOMException 拒绝的 promise

    2. promise 为一个新的 Promise。

    3. 当以下任一条件为真时,中止这些步骤并用 InvalidStateError 拒绝 promise

    4. OfflineAudioContext 上的 [[control thread state]] 标志设置为 running

    5. 排队一个控制消息以恢复 OfflineAudioContext

    6. 返回 promise

    运行一个用于恢复 OfflineAudioContext控制消息,意味着在 渲染线程 上执行这些步骤
    1. OfflineAudioContext 上的 [[rendering thread state]] 设置为 running

    2. 开始渲染音频图

    3. 如果失败, 排队一个媒体元素任务以拒绝 promise 并中止剩余步骤。

    4. 排队一个媒体元素任务以执行以下步骤

      1. 解决(Resolve)promise

      2. 如果 OfflineAudioContextstate 属性尚不是 "running"

        1. OfflineAudioContextstate 属性设置为 "running"。

        2. 排队一个媒体元素任务,以在 OfflineAudioContext触发一个名为 statechange 的事件。

    无参数。
    返回类型: Promise<undefined>
    suspend(suspendTime)

    在指定时间安排音频上下文的时间进度挂起,并返回一个 promise。这在 OfflineAudioContext 上同步操作音频图时通常很有用。

    注意,挂起的最大精度是 渲染量子 的大小,指定的挂起时间将被四舍五入到最近的 渲染量子 边界。因此,不允许在同一个量化帧安排多次挂起。此外,为了确保精确的挂起,应在上下文未运行时进行安排。

    OfflineAudioContext.suspend() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    suspendTime double 安排在指定时间挂起渲染,该时间将被量化并向上取整至 渲染量子 大小。如果量化后的帧数
    1. 为负数,或
    2. 小于或等于当前时间,或
    3. 大于或等于总渲染持续时间,或
    4. 由另一个挂起操作安排在同一时间,
    则 promise 将被 InvalidStateError 拒绝。
    返回类型: Promise<undefined>

    1.3.4. OfflineAudioContextOptions

    这指定了在构建 OfflineAudioContext 时使用的选项。

    dictionary OfflineAudioContextOptions {
        unsigned long numberOfChannels = 1;
        required unsigned long length;
        required float sampleRate;
        (AudioContextRenderSizeCategory or unsigned long) renderSizeHint = "default";
    };
    
    1.3.4.1. 字典 OfflineAudioContextOptions 成员
    length, 类型为 unsigned long

    渲染出的 AudioBuffer 的长度(以采样帧为单位)。

    numberOfChannels, 类型为 unsigned long,默认为 1

    OfflineAudioContext 的通道数。

    sampleRate, 类型为 float

    OfflineAudioContext 的采样率。

    renderSizeHint, 类型为 (AudioContextRenderSizeCategory 或 unsigned long),默认为 "default"

    OfflineAudioContext渲染量子大小 提示。

    1.3.5. OfflineAudioCompletionEvent 接口

    这是一个 Event 对象,出于遗留原因,它被分发给 OfflineAudioContext

    [Exposed=Window]
    interface OfflineAudioCompletionEvent : Event {
        constructor (DOMString type, OfflineAudioCompletionEventInit eventInitDict);
        readonly attribute AudioBuffer renderedBuffer;
    };
    
    1.3.5.1. 属性
    renderedBuffer, 类型为 AudioBuffer,只读

    包含渲染出的音频数据的 AudioBuffer

    1.3.5.2. OfflineAudioCompletionEventInit
    dictionary OfflineAudioCompletionEventInit : EventInit {
        required AudioBuffer renderedBuffer;
    };
    
    1.3.5.2.1. 字典 OfflineAudioCompletionEventInit 成员
    renderedBuffer, 类型为 AudioBuffer

    要分配给事件的 renderedBuffer 属性的值。

    1.4. AudioBuffer 接口

    此接口表示驻留在内存中的音频资源。它可以包含一个或多个通道,每个通道呈现为标称范围为 \([-1,1]\) 的 32 位浮点 线性 PCM 值,但数值不限于此范围。通常,PCM 数据的长度预计会比较短(通常少于一分钟)。对于较长的声音(例如电影原声带),应使用 audio 元素和 MediaElementAudioSourceNode 进行流式传输。

    AudioBuffer 可以被一个或多个 AudioContext 使用,并且可以在 OfflineAudioContextAudioContext 之间共享。

    AudioBuffer 有四个内部槽位

    [[number of channels]]

    AudioBuffer 的音频通道数,是一个 unsigned long。

    [[length]]

    AudioBuffer 中每个通道的长度,是一个 unsigned long。

    [[sample rate]]

    AudioBuffer 的采样率(以 Hz 为单位),是一个 float。

    [[internal data]]

    一个保存音频样本数据的 数据块

    [Exposed=Window]
    interface AudioBuffer {
        constructor (AudioBufferOptions options);
        readonly attribute float sampleRate;
        readonly attribute unsigned long length;
        readonly attribute double duration;
        readonly attribute unsigned long numberOfChannels;
        Float32Array getChannelData (unsigned long channel);
        undefined copyFromChannel (Float32Array destination,
                                   unsigned long channelNumber,
                                   optional unsigned long bufferOffset = 0);
        undefined copyToChannel (Float32Array source,
                                 unsigned long channelNumber,
                                 optional unsigned long bufferOffset = 0);
    };
    

    1.4.1. 构造函数

    AudioBuffer(options)
    1. 如果 options 中的任何值超出其标称范围,则抛出 NotSupportedError 异常并中止以下步骤。

    2. b 为一个新的 AudioBuffer 对象。

    3. 分别将构造函数中传入的 AudioBufferOptionsnumberOfChannelslengthsampleRate 属性值分配给内部槽位 [[number of channels]][[length]][[sample rate]]

    4. 将此 AudioBuffer 的内部槽位 [[internal data]] 设置为调用 CreateByteDataBlock([[length]] * [[number of channels]]) 的结果。

      注意:这将底层存储初始化为零。

    5. 返回 b

    AudioBuffer.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    options AudioBufferOptions 一个确定此 AudioBuffer 属性的 AudioBufferOptions

    1.4.2. 属性

    duration, 类型为 double,只读

    PCM 音频数据的持续时间(以秒为单位)。

    这是通过将 AudioBuffer[[length]] 除以 [[sample rate]] 计算得出的。

    length, 类型为 unsigned long,只读

    PCM 音频数据的长度(以采样帧为单位)。这必须返回 [[length]] 的值。

    numberOfChannels, 类型为 unsigned long,只读

    离散音频通道的数量。这必须返回 [[number of channels]] 的值。

    sampleRate, 类型为 float,只读

    PCM 音频数据的采样率(以每秒采样数为单位)。这必须返回 [[sample rate]] 的值。

    1.4.3. 方法

    copyFromChannel(destination, channelNumber, bufferOffset)

    copyFromChannel() 方法将样本从 AudioBuffer 的指定通道复制到 destination 数组中。

    buffer 为包含 \(N_b\) 帧的 AudioBuffer,设 \(N_f\) 为 destination 数组中的元素数量,设 \(k\) 为 bufferOffset 的值。那么从 buffer 复制到 destination 的帧数为 \(\max(0, \min(N_b - k, N_f))\)。如果该值小于 \(N_f\),则 destination 的其余元素不会被修改。

    AudioBuffer.copyFromChannel() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destination Float32Array 将要复制通道数据到的数组。
    channelNumber unsigned long 要复制数据的通道索引。如果 channelNumber 大于或等于 AudioBuffer 的通道数,则必须抛出 IndexSizeError
    bufferOffset unsigned long 一个可选的偏移量,默认为 0。从该偏移量开始的 AudioBuffer 数据将被复制到 destination
    返回类型: undefined
    copyToChannel(source, channelNumber, bufferOffset)

    copyToChannel() 方法将 source 数组中的采样点复制到 AudioBuffer 的指定通道。

    如果无法将 source 复制到缓冲区,可能会抛出 UnknownError

    buffer 为包含 \(N_b\) 帧的 AudioBuffer,设 \(N_f\) 为 source 数组中的元素数量,设 \(k\) 为 bufferOffset 的值。那么从 source 复制到 buffer 的帧数为 \(\max(0, \min(N_b - k, N_f))\)。如果该值小于 \(N_f\),则 buffer 的其余元素不会被修改。

    AudioBuffer.copyToChannel() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    source Float32Array 将要从中复制通道数据的数组。
    channelNumber unsigned long 要复制数据到的通道索引。如果 channelNumber 大于或等于 AudioBuffer 的通道数,则必须抛出 IndexSizeError
    bufferOffset unsigned long 一个可选的偏移量,默认为 0。来自 source 的数据将从该偏移量开始复制到 AudioBuffer
    返回类型: undefined
    getChannelData(channel)

    根据 获取内容 中描述的规则,允许 写入获取副本 存储在 [[internal data]] 中的字节,并返回一个新的 Float32Array

    如果无法创建 [[internal data]] 或新的 Float32Array,可能会抛出 UnknownError

    AudioBuffer.getChannelData() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    channel unsigned long 此参数是一个索引,表示要获取数据的特定通道。索引值 0 表示第一个通道。此索引值必须小于 [[number of channels]],否则必须抛出 IndexSizeError 异常。
    返回类型: Float32Array

    注意: 方法 copyToChannel()copyFromChannel() 可用于填充数组的一部分,通过传入一个更大的数组的 Float32Array 视图。当从 AudioBuffer 的通道中读取数据,并且可以分块处理数据时,应优先使用 copyFromChannel(),而不是调用 getChannelData() 并访问生成的数组,因为这样可以避免不必要的内存分配和复制。

    当某些 API 实现需要 AudioBuffer 的内容时,会调用内部操作 获取 AudioBuffer 的内容。此操作向调用者返回不可变的通道数据。

    当在 AudioBuffer 上发生 获取内容 操作时,执行以下步骤
    1. 如果任何 AudioBufferArrayBuffer分离 (detached),则返回 true,中止这些步骤,并向调用者返回一个零长度的通道数据缓冲区。

    2. 分离AudioBuffer 上先前通过 getChannelData() 返回的所有数组的 ArrayBuffer

      注意: 因为 AudioBuffer 只能通过 createBuffer()AudioBuffer 构造函数创建,所以这不会抛出异常。

    3. 保留来自这些 ArrayBuffer 的底层 [[internal data]],并将它们的引用返回给调用者。

    4. 将包含数据副本的 ArrayBuffer 附加到 AudioBuffer,以便在下一次调用 getChannelData() 时返回。

    获取 AudioBuffer 的内容 操作在以下情况下被调用

    注意: 这意味着 copyToChannel() 不能用于更改当前正被某个 AudioNode 使用的 AudioBuffer 的内容,因为该 AudioNode 已经 获取了 AudioBuffer 的内容,并且将继续使用先前获取的数据。

    1.4.4. AudioBufferOptions

    这指定了用于构建 AudioBuffer 的选项。lengthsampleRate 成员是必需的。

    dictionary AudioBufferOptions {
        unsigned long numberOfChannels = 1;
        required unsigned long length;
        required float sampleRate;
    };
    
    1.4.4.1. 字典 AudioBufferOptions 成员

    此字典成员的允许值受到限制。请参阅 createBuffer()

    length, 类型为 unsigned long

    缓冲区的采样帧长度。请参阅 length 了解限制。

    numberOfChannels, 类型为 unsigned long,默认为 1

    缓冲区的通道数。请参阅 numberOfChannels 了解限制。

    sampleRate, 类型为 float

    缓冲区的采样率(以 Hz 为单位)。请参阅 sampleRate 了解限制。

    1.5. AudioNode 接口

    AudioNodeAudioContext 的构建块。此接口代表音频源、音频目标和中间处理模块。这些模块可以连接在一起,形成 处理图 以便将音频渲染到音频硬件。每个节点可以有 输入 和/或 输出源节点 没有输入,只有一个输出。大多数处理节点(如滤波器)有一个输入和一个输出。每种类型的 AudioNode 在处理或合成音频的具体细节上有所不同。但是,通常情况下,AudioNode 会处理其输入(如果有的话),并为其输出生成音频(如果有的话)。

    每个输出都有一个或多个通道。确切的通道数取决于特定 AudioNode 的细节。

    一个输出可以连接到一个或多个 AudioNode 输入,因此支持 扇出 (fan-out)。一个输入最初没有连接,但可以从一个或多个 AudioNode 输出连接,因此支持 扇入 (fan-in)。当调用 connect() 方法将 AudioNode 的输出连接到 AudioNode 的输入时,我们将此称为到该输入的 连接

    每个 AudioNode输入 在任何给定时间都有特定数量的通道。这个数字可能会随着对该输入进行的 连接 而改变。如果输入没有连接,则它有一个静音的通道。

    对于每个 输入AudioNode 对所有到该输入的连接进行混合。有关规范要求和详细信息,请参阅 § 4 通道上混和下混

    无论节点是否连接了输出,也无论这些输出最终是否到达 AudioContextAudioDestinationNodeAudioNode 的输入处理和内部操作都会相对于 AudioContext 时间持续进行。

    [Exposed=Window]
    interface AudioNode : EventTarget {
        AudioNode connect (AudioNode destinationNode,
                           optional unsigned long output = 0,
                           optional unsigned long input = 0);
        undefined connect (AudioParam destinationParam, optional unsigned long output = 0);
        undefined disconnect ();
        undefined disconnect (unsigned long output);
        undefined disconnect (AudioNode destinationNode);
        undefined disconnect (AudioNode destinationNode, unsigned long output);
        undefined disconnect (AudioNode destinationNode,
                              unsigned long output,
                              unsigned long input);
        undefined disconnect (AudioParam destinationParam);
        undefined disconnect (AudioParam destinationParam, unsigned long output);
        readonly attribute BaseAudioContext context;
        readonly attribute unsigned long numberOfInputs;
        readonly attribute unsigned long numberOfOutputs;
        attribute unsigned long channelCount;
        attribute ChannelCountMode channelCountMode;
        attribute ChannelInterpretation channelInterpretation;
    };
    

    1.5.1. AudioNode 创建

    AudioNode 可以通过两种方式创建:使用该特定接口的构造函数,或使用 BaseAudioContextAudioContext 上的 工厂方法

    作为 AudioNode 构造函数的第一个参数传递的 BaseAudioContext 被称为要创建的 AudioNode关联 BaseAudioContext。类似地,使用工厂方法时,AudioNode关联 BaseAudioContext 就是调用该工厂方法的 BaseAudioContext

    若要使用在 BaseAudioContext c 上调用的 工厂方法 创建特定类型 n 的新 AudioNode,请执行以下步骤
    1. node 为类型 n 的新对象。

    2. option关联 到该工厂方法的接口 关联 的字典类型。

    3. 对于传递给工厂方法的每个参数,将 option 上同名的字典成员设置为该参数的值。

    4. coption 作为参数,在 node 上调用 n 的构造函数。

    5. 返回 node

    初始化 一个继承自 AudioNode 的对象 o,意味着给定传递给该接口构造函数的参数 contextdict,执行以下步骤。
    1. o 的关联 BaseAudioContext 设置为 context

    2. 将其 numberOfInputsnumberOfOutputschannelCountchannelCountModechannelInterpretation 的值设置为每个 AudioNode 章节中概述的该特定接口的默认值。

    3. 对于传递进来的 dict 的每个成员,执行这些步骤,其中 k 为成员的键,v 为其值。如果在执行这些步骤时抛出任何异常,则中止迭代并将异常传播给算法的调用者(构造函数或工厂方法)。

      1. 如果 k 是此接口上某个 AudioParam 的名称,则将该 AudioParamvalue 属性设置为 v

      2. 否则,如果 k 是此接口上某个属性的名称,则将与该属性关联的对象设置为 v

    工厂方法的 关联接口 是该方法返回的对象的接口。关联选项对象 是可以传递给该接口构造函数的选项对象。

    AudioNodeEventTarget,如 [DOM] 中所述。这意味着可以像其他 EventTarget 接受事件一样,向 AudioNode 分发事件。

    enum ChannelCountMode {
        "max",
        "clamped-max",
        "explicit"
    };
    

    ChannelCountMode 结合节点的 channelCountchannelInterpretation 值,用于确定控制如何混合到节点输入的 computedNumberOfChannels(计算出的通道数)computedNumberOfChannels 的确定方式如下所示。有关如何进行混合的更多信息,请参阅 § 4 通道上混和下混

    ChannelCountMode 枚举描述
    枚举值描述
    "max" computedNumberOfChannels 是所有到输入的连接中通道数的最大值。在此模式下,channelCount 被忽略。
    "clamped-max" computedNumberOfChannels 的确定方式与 "max" 相同,然后被限制为给定的 channelCount 的最大值。
    "explicit" computedNumberOfChannels 是由 channelCount 指定的精确值。
    enum ChannelInterpretation {
        "speakers",
        "discrete"
    };
    
    ChannelInterpretation 枚举描述
    枚举值描述
    "speakers"使用 上混公式下混公式。如果通道数与任何这些基本扬声器布局不匹配,则回退到 "discrete"。
    "discrete"通过填充通道直到耗尽来上混,然后将剩余通道置零。通过填充尽可能多的通道来下混,然后丢弃剩余通道。

    1.5.2. AudioNode 尾音 (Tail-Time)

    AudioNode 可以具有 尾音时长。这意味着即使在 AudioNode 被输入静音时,输出也可能不是静音的。

    如果 AudioNode 具有内部处理状态,使得过去的输入会影响未来的输出,则它具有非零的尾音时长。AudioNode 即使在输入从非静音变为静音后,也可能在计算出的尾音时长内继续产生非静音输出。

    1.5.3. AudioNode 生命周期

    如果满足以下任一条件,AudioNode渲染量子 (render quantum) 期间可以是 主动处理的

    注意: 这考虑到了具有 尾音时长AudioNode

    主动处理的 AudioNode 输出单通道静音。

    1.5.4. 属性

    channelCount, 类型为 unsigned long

    channelCount 是上混和下混到节点任何输入的连接时使用的通道数。默认值为 2,但特定节点除外,其值是专门确定的。此属性对于没有输入的节点无效。如果此值设置为零或大于实现的最大通道数的值,实现必须抛出 NotSupportedError 异常。

    此外,某些节点对通道数可能的值有额外的 channelCount 约束

    AudioDestinationNode

    行为取决于目标节点是 AudioContext 还是 OfflineAudioContext 的目标

    AudioContext

    通道数必须在 1 和 maxChannelCount 之间。任何在此时范围之外设置通道数的尝试都必须抛出 IndexSizeError 异常。

    OfflineAudioContext

    通道数无法更改。任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    AudioWorkletNode

    请参阅 § 1.32.4.3.2 使用 AudioWorkletNodeOptions 配置通道

    ChannelMergerNode

    通道数无法更改,且任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    ChannelSplitterNode

    通道数无法更改,且任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    ConvolverNode

    通道数不能大于 2,且任何尝试将其更改为大于 2 的值的行为都必须抛出 NotSupportedError 异常。

    DynamicsCompressorNode

    通道数不能大于 2,且任何尝试将其更改为大于 2 的值的行为都必须抛出 NotSupportedError 异常。

    PannerNode

    通道数不能大于 2,且任何尝试将其更改为大于 2 的值的行为都必须抛出 NotSupportedError 异常。

    ScriptProcessorNode

    通道数无法更改,且任何尝试更改该值的行为都必须抛出 NotSupportedError 异常。

    StereoPannerNode

    通道数不能大于 2,且任何尝试将其更改为大于 2 的值的行为都必须抛出 NotSupportedError 异常。

    有关此属性的更多信息,请参阅 § 4 通道上混和下混

    channelCountMode, 类型为 ChannelCountMode

    channelCountMode 决定了在对节点任何输入的连接进行上混和下混时如何计算通道。默认值为 "max"。此属性对于没有输入的节点无效。

    此外,某些节点对通道计数模式可能的值有额外的 channelCountMode 约束

    AudioDestinationNode

    如果 AudioDestinationNodeOfflineAudioContextdestination 节点,则通道计数模式无法更改。任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    ChannelMergerNode

    通道计数模式无法从 "explicit" 更改,且任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    ChannelSplitterNode

    通道计数模式无法从 "explicit" 更改,且任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    ConvolverNode

    通道计数模式无法设置为 "max",且任何尝试将其设置为 "max" 的行为都必须抛出 NotSupportedError 异常。

    DynamicsCompressorNode

    通道计数模式无法设置为 "max",且任何尝试将其设置为 "max" 的行为都必须抛出 NotSupportedError 异常。

    PannerNode

    通道计数模式无法设置为 "max",且任何尝试将其设置为 "max" 的行为都必须抛出 NotSupportedError 异常。

    ScriptProcessorNode

    通道计数模式无法从 "explicit" 更改,且任何尝试更改该值的行为都必须抛出 NotSupportedError 异常。

    StereoPannerNode

    通道计数模式无法设置为 "max",且任何尝试将其设置为 "max" 的行为都必须抛出 NotSupportedError 异常。

    有关此属性的更多信息,请参阅 § 4 通道上混和下混 章节。

    channelInterpretation, 类型为 ChannelInterpretation

    channelInterpretation 决定了在对节点任何输入的连接进行上混和下混时如何对待各个通道。默认值为 "speakers"。此属性对于没有输入的节点无效。

    此外,某些节点对通道解释可能的值有额外的 channelInterpretation 约束

    ChannelSplitterNode

    通道解释无法从 "discrete" 更改,且任何尝试更改该值的行为都必须抛出 InvalidStateError 异常。

    有关此属性的更多信息,请参阅 § 4 通道上混和下混

    context, 类型为 BaseAudioContext,只读

    拥有此 AudioNodeBaseAudioContext

    numberOfInputs, 类型为 unsigned long,只读

    馈入 AudioNode 的输入数量。对于 源节点,此值为 0。此属性对于许多 AudioNode 类型是预先确定的,但某些 AudioNode(如 ChannelMergerNodeAudioWorkletNode)具有可变的输入数量。

    numberOfOutputs, 类型为 unsigned long,只读

    来自 AudioNode 的输出数量。此属性对于某些 AudioNode 类型是预先确定的,但可以是可变的,例如 ChannelSplitterNodeAudioWorkletNode

    1.5.5. 方法

    connect(destinationNode, output, input)

    一个特定节点的给定输出与另一个特定节点的给定输入之间只能有一个连接。具有相同端点的多个连接将被忽略。

    例如
    nodeA.connect(nodeB);
    nodeA.connect(nodeB);
    

    将产生与以下相同的效果

    nodeA.connect(nodeB);
    

    此方法返回 destination AudioNode 对象。

    AudioNode.connect(destinationNode, output, input) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationNode destination 参数是要连接到的 AudioNode如果 destination 参数是使用另一个 AudioContext 创建的 AudioNode,则必须抛出 InvalidAccessError 也就是说,AudioNode 不能在 AudioContext 之间共享。多个 AudioNode 可以连接到同一个 AudioNode,这在 通道上混和下混 章节中有描述。
    output unsigned long output 参数是一个索引,描述要连接 AudioNode 的哪个输出。如果此参数越界,则必须抛出 IndexSizeError 异常。 可以通过多次调用 connect() 将一个 AudioNode 输出连接到多个输入。因此,支持 "扇出"。
    input (输入) input 参数是一个索引,描述要连接到目标 AudioNode 的哪个输入。如果此参数越界,则必须抛出 IndexSizeError 异常。 可以将一个 AudioNode 连接到另一个 AudioNode,从而创建一个 循环 (cycle):一个 AudioNode 可以连接到另一个 AudioNode,该节点又连接回第一个 AudioNode 的输入或 AudioParam
    返回类型: AudioNode
    connect(destinationParam, output)

    AudioNode 连接到 AudioParam,使用 a-rate 信号控制参数值。

    可以通过多次调用 connect() 将一个 AudioNode 输出连接到多个 AudioParam。因此,支持 "扇出"。

    可以通过多次调用 connect() 将多个 AudioNode 输出连接到单个 AudioParam。因此,支持 "扇入"。

    AudioParam 将从连接到它的任何 AudioNode 输出中获取渲染后的音频数据,如果不已经是单声道,则通过下混 将其转换为单声道,然后将其与其他此类输出混合,最后与 固有 (intrinsic) 参数值(在没有任何音频连接的情况下 AudioParam 通常具有的 value)进行混合,包括为该参数调度的任何时间轴更改。

    下混至单声道等同于 AudioNode 的下混,其中 channelCount = 1,channelCountMode = "explicit",并且 channelInterpretation = "speakers"。

    一个特定节点的给定输出与特定 AudioParam 之间只能有一个连接。具有相同端点的多个连接将被忽略。

    例如
    nodeA.connect(param);
    nodeA.connect(param);
    

    将产生与以下相同的效果

    nodeA.connect(param);
    
    AudioNode.connect(destinationParam, output) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationParam AudioParam destination 参数是要连接到的 AudioParam。此方法不返回 destination AudioParam 对象。如果 destinationParam 属于一个 AudioNode,而该节点又属于一个与调用此方法的 BaseAudioContext 不同的 BaseAudioContext,则必须抛出 InvalidAccessError
    output unsigned long output 参数是一个索引,描述要连接 AudioNode 的哪个输出。如果 parameter 越界,则必须抛出 IndexSizeError 异常。
    返回类型: undefined
    disconnect()

    断开 AudioNode 的所有传出连接。

    无参数。
    返回类型: undefined
    disconnect(output)

    断开 AudioNode 的单个输出与它连接到的任何其他 AudioNodeAudioParam 对象之间的连接。

    AudioNode.disconnect(output) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    output unsigned long 此参数是一个索引,描述要断开 AudioNode 的哪个输出。它断开从给定输出发出的所有传出连接。如果此参数越界,则必须抛出 IndexSizeError 异常。
    返回类型: undefined
    disconnect(destinationNode)

    断开 AudioNode 指向特定目标 AudioNode 的所有输出。

    AudioNode.disconnect(destinationNode) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationNode destinationNode 参数是要断开连接的 AudioNode。它断开所有指向给定 destinationNode 的传出连接。如果没有到 destinationNode 的连接,则必须抛出 InvalidAccessError 异常。
    返回类型: undefined
    disconnect(destinationNode, output)

    断开 AudioNode 的特定输出与某些目标 AudioNode 的任何和所有输入之间的连接。

    AudioNode.disconnect(destinationNode, output) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationNode destinationNode 参数是要断开连接的 AudioNode如果给定输出没有到 destinationNode 的连接,则必须抛出 InvalidAccessError 异常。
    output unsigned long output 参数是一个索引,描述要断开 AudioNode 的哪个输出。如果此参数越界,则必须抛出 IndexSizeError 异常。
    返回类型: undefined
    disconnect(destinationNode, output, input)

    断开 AudioNode 的特定输出与某些目标 AudioNode 的特定输入之间的连接。

    AudioNode.disconnect(destinationNode, output, input) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationNode destinationNode 参数是要断开连接的 AudioNode如果给定输出没有到给定输入的 destinationNode 的连接,则必须抛出 InvalidAccessError 异常。
    output unsigned long output 参数是一个索引,描述要断开 AudioNode 的哪个输出。如果此参数越界,则必须抛出 IndexSizeError 异常。
    input (输入) input 参数是一个索引,描述要断开目标 AudioNode 的哪个输入。如果此参数越界,则必须抛出 IndexSizeError 异常。
    返回类型: undefined
    disconnect(destinationParam)

    断开 AudioNode 指向特定目标 AudioParam 的所有输出。当此操作生效时,此 AudioNode 对计算参数值的贡献变为 0。固有参数值不受此操作的影响。

    AudioNode.disconnect(destinationParam) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationParam AudioParam destinationParam 参数是要断开连接的 AudioParam如果没有到 destinationParam 的连接,则必须抛出 InvalidAccessError 异常。
    返回类型: undefined
    disconnect(destinationParam, output)

    断开 AudioNode 的特定输出与特定目标 AudioParam 之间的连接。当此操作生效时,此 AudioNode 对计算参数值的贡献变为 0。固有参数值不受此操作的影响。

    AudioNode.disconnect(destinationParam, output) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    destinationParam AudioParam destinationParam 参数是要断开连接的 AudioParam如果没有到 destinationParam 的连接,则必须抛出 InvalidAccessError 异常。
    output unsigned long output 参数是一个索引,描述要断开 AudioNode 的哪个输出。如果 parameter 越界,则必须抛出 IndexSizeError 异常。
    返回类型: undefined

    1.5.6. AudioNodeOptions

    这指定了可用于构建所有 AudioNode 的选项。所有成员都是可选的。但是,每个节点使用的具体值取决于实际节点。

    dictionary AudioNodeOptions {
        unsigned long channelCount;
        ChannelCountMode channelCountMode;
        ChannelInterpretation channelInterpretation;
    };
    
    1.5.6.1. 字典 AudioNodeOptions 成员
    channelCount, 类型为 unsigned long

    channelCount 属性所需的通道数。

    channelCountMode, 类型为 ChannelCountMode

    channelCountMode 属性所需的模式。

    channelInterpretation, 类型为 ChannelInterpretation

    channelInterpretation 属性所需的模式。

    1.6. AudioParam 接口

    AudioParam 控制 AudioNode 功能的各个方面,例如音量。参数可以使用 value 属性立即设置为特定值。或者,可以安排在非常精确的时间点(在 AudioContextcurrentTime 属性坐标系中)进行值更改,用于包络、音量淡入淡出、LFO、滤波器扫描、颗粒窗口等。通过这种方式,可以在任何 AudioParam 上设置任意基于时间轴的自动化曲线。此外,来自 AudioNode 输出的音频信号可以连接到 AudioParam,并与 固有 参数值求和。

    一些合成和处理 AudioNode 具有作为属性的 AudioParam,其值必须在每个音频采样基础上考虑。对于其他 AudioParam,采样精度并不重要,值更改可以更粗略地采样。每个单独的 AudioParam 将指定它是 a-rate 参数(意味着其值必须在每个音频采样基础上考虑),还是 k-rate 参数。

    实现必须使用块处理,每个 AudioNode 处理一个 渲染量子

    对于每个 渲染量子k-rate 参数的值必须在第一个采样帧时采样,并且该值必须用于整个块。a-rate 参数必须为块的每个采样帧进行采样。根据 AudioParam,其速率可以通过将 automationRate 属性设置为 "a-rate" 或 "k-rate" 来控制。有关更多详细信息,请参阅各个 AudioParam 的说明。

    每个 AudioParam 都包含 minValuemaxValue 属性,它们共同构成了参数的简单标称范围。实际上,参数的值会被钳位(clamp)到范围 \([\mathrm{minValue}, \mathrm{maxValue}]\) 中。详细信息请参阅 § 1.6.3 数值计算

    对于许多 AudioParam 而言,minValuemaxValue 旨在被设置为最大可能的范围。在这种情况下,maxValue 应设置为 最大正单精度浮点数,即 3.4028235e38。(然而,在仅支持 IEEE-754 双精度浮点值的 JavaScript 中,必须写作 3.4028234663852886e38。)同样地,minValue 应设置为 最小负单精度浮点数,即 最大正单精度浮点数 的负值:-3.4028235e38。(类似地,在 JavaScript 中必须写作 -3.4028234663852886e38。)

    AudioParam 维护一个包含零个或多个 自动化事件 的列表。每个自动化事件指定了参数值在特定时间范围内的变化,该时间是相对于 AudioContextcurrentTime 属性所处时间坐标系下的 自动化事件时间。自动化事件列表按自动化事件时间的升序进行维护。

    给定自动化事件的行为是 AudioContext 当前时间,以及该事件和列表中相邻事件的自动化事件时间的函数。以下 自动化方法 通过向事件列表添加特定于该方法类型的事件来更改事件列表:

    调用这些方法时适用以下规则:

    注意: AudioParam 属性除 value 属性外均为只读。

    AudioParam 的自动化速率可以通过设置 automationRate 属性并赋予以下值之一来选择。然而,一些 AudioParam 对能否更改自动化速率有约束。

    enum AutomationRate {
        "a-rate",
        "k-rate"
    };
    
    AutomationRate 枚举描述
    枚举值描述
    "a-rate"AudioParam 设置为 a-rate 处理。
    "k-rate"AudioParam 设置为 k-rate 处理。

    每个 AudioParam 都有一个内部槽位 [[current value]],初始值设为 AudioParamdefaultValue

    [Exposed=Window]
    interface AudioParam {
        attribute float value;
        attribute AutomationRate automationRate;
        readonly attribute float defaultValue;
        readonly attribute float minValue;
        readonly attribute float maxValue;
        AudioParam setValueAtTime (float value, double startTime);
        AudioParam linearRampToValueAtTime (float value, double endTime);
        AudioParam exponentialRampToValueAtTime (float value, double endTime);
        AudioParam setTargetAtTime (float target, double startTime, float timeConstant);
        AudioParam setValueCurveAtTime (sequence<float> values,
                                        double startTime,
                                        double duration);
        AudioParam cancelScheduledValues (double cancelTime);
        AudioParam cancelAndHoldAtTime (double cancelTime);
    };
    

    1.6.1. 属性

    automationRate, 类型为 AutomationRate

    AudioParam 的自动化速率。默认值取决于具体的 AudioParam;关于默认值,请参阅每个单独 AudioParam 的描述。

    某些节点具有额外的 自动化速率约束,如下所示:

    AudioBufferSourceNode

    AudioParamplaybackRatedetune 必须为 "k-rate"。 如果速率更改为 "a-rate",则必须抛出 InvalidStateError

    DynamicsCompressorNode

    AudioParamthresholdkneeratioattackrelease 必须为 "k-rate"。 如果速率更改为 "a-rate",则必须抛出 InvalidStateError

    PannerNode

    如果 panningModel 为 "HRTF",则 PannerNode 的任何 AudioParamautomationRate 设置都将被忽略。同样,AudioListener 的任何 AudioParamautomationRate 设置也会被忽略。在这种情况下,AudioParam 的行为表现得就像 automationRate 被设置为 "k-rate" 一样。

    defaultValue, 类型为 float,只读

    value 属性的初始值。

    maxValue, 类型为 float,只读

    参数可以取的标称最大值。与 minValue 一起,构成了该参数的 标称范围

    minValue, 类型为 float,只读

    参数可以取的标称最小值。与 maxValue 一起,构成了该参数的 标称范围

    value, 类型为 float

    参数的浮点数值。此属性初始化为 defaultValue

    获取此属性将返回 [[current value]] 槽位的内容。关于返回值的算法,请参阅 § 1.6.3 数值计算

    设置此属性的效果是将请求的值分配给 [[current value]] 槽位,并以当前 AudioContextcurrentTime[[current value]] 调用 setValueAtTime() 方法。setValueAtTime() 抛出的任何异常也将在设置此属性时抛出。

    1.6.2. 方法

    cancelAndHoldAtTime(cancelTime)

    这与 cancelScheduledValues() 类似,都会取消所有时间大于或等于 cancelTime 的计划参数更改。然而,它额外将本应在 cancelTime 发生的自动化值保持,并持续到引入其他自动化事件为止。

    当自动化正在运行,并且可以在调用 cancelAndHoldAtTime() 之后且达到 cancelTime 之前的任何时间点引入新自动化时,时间线的行为非常复杂。因此,cancelAndHoldAtTime() 的行为在以下算法中指定。

    设 \(t_c\) 为 cancelTime 的值。那么:
    1. 设 \(E_1\) 为时间 \(t_1\) 处的事件(如果存在),其中 \(t_1\) 是满足 \(t_1 \le t_c\) 的最大数。

    2. 设 \(E_2\) 为时间 \(t_2\) 处的事件(如果存在),其中 \(t_2\) 是满足 \(t_c \lt t_2\) 的最小数。

    3. 如果 \(E_2\) 存在

      1. 如果 \(E_2\) 是线性或指数斜坡,

        1. 实际上将 \(E_2\) 重写为同类型的斜坡,结束于时间 \(t_c\),且结束值应为原始斜坡在时间 \(t_c\) 时的值。 当在此时间调用 linearRampToValueAtTime 时调用 cancelAndHoldAtTime 的图形表示。

        2. 转至第 5 步。

      2. 否则,转至第 4 步。

    4. 如果 \(E_1\) 存在

      1. 如果 \(E_1\) 是 setTarget 事件,

        1. 在时间 \(t_c\) 处隐式插入一个 setValueAtTime 事件,其值为 setTarget 在时间 \(t_c\) 时应有的值。 当在此时间调用 setTargetAtTime 时调用 cancelAndHoldAtTime 的图形表示

        2. 转至第 5 步。

      2. 如果 \(E_1\) 是开始时间为 \(t_3\)、持续时间为 \(d\) 的 setValueCurve

        1. 如果 \(t_c \gt t_3 + d\),转至第 5 步。

        2. 否则,

          1. 实际上将此事件替换为开始时间为 \(t_3\)、新持续时间为 \(t_c-t_3\) 的 setValueCurve 事件。然而,这不是真正的替换;此自动化必须确保产生与原始输出相同的输出,而不是使用不同持续时间计算出的输出。(那会导致以略微不同的方式对值曲线进行采样,从而产生不同的结果。) 当在此时间调用 setValueCurve 时调用 cancelAndHoldAtTime 的图形表示

          2. 转至第 5 步。

    5. 移除所有时间大于 \(t_c\) 的事件。

    如果没有添加任何事件,则 cancelAndHoldAtTime() 之后的自动化值即为原始时间线在时间 \(t_c\) 时的常量值。

    AudioParam.cancelAndHoldAtTime() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    cancelTime double 在此时间之后,任何先前计划的参数更改都将被取消。它与 AudioContextcurrentTime 属性处于相同的时间坐标系中。 如果 cancelTime 为负数,则必须抛出 RangeError 异常。如果 cancelTime 小于 currentTime,则将其钳位到 currentTime
    返回类型: AudioParam
    cancelScheduledValues(cancelTime)

    取消所有时间大于或等于 cancelTime 的计划参数更改。取消计划的参数更改意味着从事件列表中删除该计划的事件。任何 自动化事件时间 小于 cancelTime 的活动自动化也会被取消,此类取消可能会导致不连续性,因为原始值(在此类自动化之前的值)会立即恢复。如果由 cancelAndHoldAtTime() 计划的保持值在 cancelTime 之后发生,则也会被移除。

    对于 setValueCurveAtTime(),设 \(T_0\) 和 \(T_D\) 分别为该事件的相应 startTimeduration。那么,如果 cancelTime 在范围 \([T_0, T_0 + T_D]\) 内,则从时间线中移除该事件。

    AudioParam.cancelScheduledValues() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    cancelTime double 在此时间之后,任何先前计划的参数更改都将被取消。它与 AudioContextcurrentTime 属性处于相同的时间坐标系中。 如果 cancelTime 为负数,则必须抛出 RangeError 异常。 如果 cancelTime 小于 currentTime,则将其钳位到 currentTime
    返回类型: AudioParam
    exponentialRampToValueAtTime(value, endTime)

    计划从上一个计划参数值到给定值的指数连续参数值变化。由于人类感知声音的方式,代表滤波器频率和播放速率的参数最好以指数方式进行更改。

    时间间隔 \(T_0 \leq t < T_1\) 内的值(其中 \(T_0\) 是上一个事件的时间,\(T_1\) 是传入此方法的 endTime 参数)将按如下计算:

    $$
        v(t) = V_0 \left(\frac{V_1}{V_0}\right)^\frac{t - T_0}{T_1 - T_0}
    $$
    

    其中 \(V_0\) 是时间 \(T_0\) 处的值,\(V_1\) 是传入此方法的 value 参数。如果 \(V_0\) 和 \(V_1\) 符号相反,或者 \(V_0\) 为零,则对于 \(T_0 \leq t < T_1\),\(v(t) = V_0\)。

    这也意味着指数斜坡到 0 是不可能的。使用 setTargetAtTime() 和适当选择的时间常数可以实现很好的近似。

    如果在此 ExponentialRampToValue 事件之后没有更多事件,则对于 \(t \geq T_1\),\(v(t) = V_1\)。

    如果没有事件在该事件之前,指数斜坡的行为就好像调用了 setValueAtTime(value, currentTime),其中 value 是属性的当前值,而 currentTime 是调用 exponentialRampToValueAtTime() 时上下文的 currentTime

    如果前一个事件是 SetTarget 事件,则 \(T_0\) 和 \(V_0\) 从 SetTarget 自动化的当前时间和值中选择。即,如果 SetTarget 事件尚未开始,\(T_0\) 为该事件的开始时间,\(V_0\) 为 SetTarget 事件开始前的值。在这种情况下,ExponentialRampToValue 事件有效地取代了 SetTarget 事件。如果 SetTarget 事件已经开始,\(T_0\) 为当前的上下文时间,\(V_0\) 为时间 \(T_0\) 处 SetTarget 自动化的当前值。在这两种情况下,自动化曲线都是连续的。

    AudioParam.exponentialRampToValueAtTime() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    value float 参数将在给定时间指数级斜坡到达的值。 如果此值等于 0,则必须抛出 RangeError 异常。
    endTime double AudioContextcurrentTime 属性处于相同时间坐标系下指数斜坡结束的时间。 如果 endTime 为负数或不是有限数字,则必须抛出 RangeError 异常。 如果 endTime 小于 currentTime,则将其钳位到 currentTime
    返回类型: AudioParam
    linearRampToValueAtTime(value, endTime)

    计划从上一个计划参数值到给定值的线性连续参数值变化。

    时间间隔 \(T_0 \leq t < T_1\) 内的值(其中 \(T_0\) 是上一个事件的时间,\(T_1\) 是传入此方法的 endTime 参数)将按如下计算:

    $$
        v(t) = V_0 + (V_1 - V_0) \frac{t - T_0}{T_1 - T_0}
    $$
    

    其中 \(V_0\) 是时间 \(T_0\) 处的值,\(V_1\) 是传入此方法的 value 参数。

    如果在此 LinearRampToValue 事件之后没有更多事件,则对于 \(t \geq T_1\),\(v(t) = V_1\)。

    如果没有事件在该事件之前,线性斜坡的行为就好像调用了 setValueAtTime(value, currentTime),其中 value 是属性的当前值,而 currentTime 是调用 linearRampToValueAtTime() 时上下文的 currentTime

    如果前一个事件是 SetTarget 事件,则 \(T_0\) 和 \(V_0\) 从 SetTarget 自动化的当前时间和值中选择。即,如果 SetTarget 事件尚未开始,\(T_0\) 为该事件的开始时间,\(V_0\) 为 SetTarget 事件开始前的值。在这种情况下,LinearRampToValue 事件有效地取代了 SetTarget 事件。如果 SetTarget 事件已经开始,\(T_0\) 为当前的上下文时间,\(V_0\) 为时间 \(T_0\) 处 SetTarget 自动化的当前值。在这两种情况下,自动化曲线都是连续的。

    AudioParam.linearRampToValueAtTime() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    value float 参数将在给定时间线性斜坡到达的值。
    endTime double AudioContextcurrentTime 属性处于相同时间坐标系下,自动化结束的时间。 如果 endTime 为负数或不是有限数字,则必须抛出 RangeError 异常。 如果 endTime 小于 currentTime,则将其钳位到 currentTime
    返回类型: AudioParam
    setTargetAtTime(target, startTime, timeConstant)

    在给定时间以给定的时间常数开始以指数方式趋向于目标值。除其他用途外,这对于实现 ADSR 包络的“衰减”和“释放”部分非常有用。请注意,参数值在给定时间不会立即变为目标值,而是逐渐变为目标值。

    在时间间隔 \(T_0 \leq t\) 期间,其中 \(T_0\) 是 startTime 参数:

    $$
        v(t) = V_1 + (V_0 - V_1)\, e^{-\left(\frac{t - T_0}{\tau}\right)}
    $$
    

    其中 \(V_0\) 是 \(T_0\) (startTime 参数)时的初始值([[current value]] 属性),\(V_1\) 等于 target 参数,\(\tau\) 是 timeConstant 参数。

    如果 LinearRampToValueExponentialRampToValue 事件跟随此事件,其行为分别在 linearRampToValueAtTime()exponentialRampToValueAtTime() 中描述。对于所有其他事件,SetTarget 事件在下一个事件的时间结束。

    AudioParam.setTargetAtTime() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    target float 参数将在给定时间开始更改到的值。
    startTime double 指数趋近开始的时间,与 AudioContextcurrentTime 属性处于相同时间坐标系中。 如果 start 为负数或不是有限数字,则必须抛出 RangeError 异常。 如果 startTime 小于 currentTime,则将其钳位到 currentTime
    timeConstant float 一阶滤波器(指数)趋向目标值的时间常数值。此值越大,过渡越慢。 该值必须是非负数,否则必须抛出 RangeError 异常。 如果 timeConstant 为零,输出值会立即跳变至最终值。更准确地说,timeConstant 是一阶线性连续时不变系统在给定阶跃输入响应(从 0 到 1 值的过渡)时达到值 \(1 - 1/e\)(约 63.2%)所需的时间。
    返回类型: AudioParam
    setValueAtTime(value, startTime)

    计划在给定时间更改参数值。

    如果在此 SetValue 事件之后没有更多事件,则对于 \(t \geq T_0\),\(v(t) = V\),其中 \(T_0\) 是 startTime 参数,\(V\) 是 value 参数。换句话说,该值将保持不变。

    如果此 SetValue 事件之后的下一个事件(时间为 \(T_1\))不是 LinearRampToValueExponentialRampToValue 类型,则对于 \(T_0 \leq t < T_1\)

    $$
        v(t) = V
    $$
    

    换句话说,该值在此时间间隔内将保持不变,允许创建“阶梯”函数。

    如果此 SetValue 事件之后的下一个事件是 LinearRampToValueExponentialRampToValue 类型,请分别参阅 linearRampToValueAtTime()exponentialRampToValueAtTime()

    AudioParam.setValueAtTime() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    value float 参数将在给定时间更改到的值。
    startTime double BaseAudioContextcurrentTime 属性处于相同时间坐标系下,参数更改为给定值的时间。 如果 startTime 为负数或不是有限数字,则必须抛出 RangeError 异常。 如果 startTime 小于 currentTime,则将其钳位到 currentTime
    返回类型: AudioParam
    setValueCurveAtTime(values, startTime, duration)

    设置一系列任意参数值,从给定时间开始持续给定持续时间。值的数量将被缩放以适合所需的持续时间。

    设 \(T_0\) 为 startTime,\(T_D\) 为 duration,\(V\) 为 values 数组,\(N\) 为 values 数组的长度。那么,在时间间隔 \(T_0 \le t < T_0 + T_D\) 期间,设

    $$
        \begin{align*} k &= \left\lfloor \frac{N - 1}{T_D}(t-T_0) \right\rfloor \\
        \end{align*}
    $$
    

    那么 \(v(t)\) 通过在 \(V[k]\) 和 \(V[k+1]\) 之间进行线性插值计算得出,

    在曲线时间间隔结束(\(t \ge T_0 + T_D\))之后,该值将保持在最终曲线值不变,直到出现另一个自动化事件(如果有)。

    在时间 \(T_0 + T_D\) 处对 setValueAtTime() 进行隐式调用,值为 \(V[N-1]\),以便后续自动化将从 setValueCurveAtTime() 事件的末尾开始。

    AudioParam.setValueCurveAtTime() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    sequence<float> 代表参数值曲线的浮点值序列。这些值将从给定时间开始应用,并持续给定的持续时间。当调用此方法时,会出于自动化目的创建曲线的内部副本。因此,后续对传入数组内容的修改对 AudioParam 没有影响。 如果此属性是一个长度小于 2 的 sequence<float> 对象,则必须抛出 InvalidStateError 异常。
    startTime double AudioContextcurrentTime 属性处于相同时间坐标系下,将应用值曲线的开始时间。 如果 startTime 为负数或不是有限数字,则必须抛出 RangeError 异常。 如果 startTime 小于 currentTime,则将其钳位到 currentTime
    duration double (在 startTime 参数之后)值将根据 values 参数计算的时间秒数。 如果 duration 不是严格正数或不是有限数字,则必须抛出 RangeError 异常。
    返回类型: AudioParam

    1.6.3. 数值计算

    AudioParam 有两种不同类型,简单参数复合参数简单参数(默认值)单独使用,用于计算 AudioNode 的最终音频输出。复合参数 是与其他 AudioParam 一起使用的 AudioParam,用于计算一个值,该值随后被用作输入来计算 AudioNode 的输出。

    computedValue 是控制音频 DSP 的最终值,由音频渲染线程在每个渲染时间量(render quantum)内进行计算。

    AudioParam 值的计算由两部分组成:

    这些值必须按如下方式计算:

    1. paramIntrinsicValue 将在每个时间点进行计算,该值要么直接设置为 value 属性,要么如果有任何在此时间或之前的时间点发生的 自动化事件,则计算出的值源自这些事件。如果从给定时间范围中移除了自动化事件,则 paramIntrinsicValue 值将保持不变,直到直接设置 value 属性或为该时间范围添加了自动化事件。

    2. 在该 渲染时间量 的开始时,将 [[current value]] 设置为 paramIntrinsicValue 的值。

    3. paramComputedValueparamIntrinsicValue 值和 输入 AudioParam 缓冲区 值之和。如果和为 NaN,则用 defaultValue 替换该和。

    4. 如果此 AudioParam 是一个 复合参数,则与其他 AudioParam 一起计算其最终值。

    5. computedValue 设置为 paramComputedValue

    computedValue标称范围 是此参数可以有效具有的低值和高值。对于 简单参数computedValue 被钳位到该参数的 简单标称范围复合参数在根据它们组成的各种 AudioParam 值计算后,其最终值被钳位到它们的 标称范围

    当使用自动化方法时,仍然适用钳位。然而,自动化的运行就好像完全没有钳位一样。只有当自动化值要应用于输出时,才按照上述指定进行钳位。

    例如,考虑一个节点 \(N\) 具有一个标称范围为 \([0, 1]\) 的 AudioParam \(p\),以及以下自动化序列:N.p.setValueAtTime(0, 0); N.p.linearRampToValueAtTime(4, 1); N.p.linearRampToValueAtTime(0, 2);

    曲线的初始斜率为 4,直到达到最大值 1,此时输出保持恒定。最后,在时间 2 附近,曲线斜率为 -4。这在下图中得到说明,其中虚线表示没有裁切时会发生的情况,实线表示由于钳位到标称范围而导致的 audioparam 的实际预期行为。

    AudioParam automation clipping to nominal
    AudioParam 自动化从标称范围裁切的示例。

    1.6.4. AudioParam 自动化示例
    AudioParam automation
    参数自动化示例。
    const curveLength = 44100;const curve = new Float32Array(curveLength);for (const i = 0; i < curveLength; ++i)    curve[i] = Math.sin(Math.PI * i / curveLength);const t0 = 0;const t1 = 0.1;const t2 = 0.2;const t3 = 0.3;const t4 = 0.325;const t5 = 0.5;const t6 = 0.6;const t7 = 0.7;const t8 = 1.0;const timeConstant = 0.1;param.setValueAtTime(0.2, t0);param.setValueAtTime(0.3, t1);param.setValueAtTime(0.4, t2);param.linearRampToValueAtTime(1, t3);param.linearRampToValueAtTime(0.8, t4);param.setTargetAtTime(.5, t4, timeConstant);// Compute where the setTargetAtTime will be at time t5 so we can make// the following exponential start at the right point so there’s no// jump discontinuity. From the spec, we have// v(t) = 0.5 + (0.8 - 0.5)*exp(-(t-t4)/timeConstant)// Thus v(t5) = 0.5 + (0.8 - 0.5)*exp(-(t5-t4)/timeConstant)param.setValueAtTime(0.5 + (0.8 - 0.5)*Math.exp(-(t5 - t4)/timeConstant), t5);param.exponentialRampToValueAtTime(0.75, t6);param.exponentialRampToValueAtTime(0.05, t7);param.setValueCurveAtTime(curve, t7, t8 - t7);

    1.7. AudioScheduledSourceNode 接口

    该接口代表了源节点的共同特征,例如 AudioBufferSourceNodeConstantSourceNodeOscillatorNode

    在源开始(通过调用 start())之前,源节点必须输出静音(0)。在源停止(通过调用 stop())之后,源必须输出静音(0)。

    AudioScheduledSourceNode 不能直接实例化,而是由源节点的具体接口扩展。

    AudioScheduledSourceNode 关联的 BaseAudioContextcurrentTime 大于或等于设置的开始时间,且小于设置的停止时间时,称该 AudioScheduledSourceNode正在播放

    AudioScheduledSourceNode 创建时带有一个内部布尔槽位 [[source started]],初始值设为 false。

    [Exposed=Window]
    interface AudioScheduledSourceNode : AudioNode {
        attribute EventHandler onended;
        undefined start(optional double when = 0);
        undefined stop(optional double when = 0);
    };
    

    1.7.1. 属性
    onended, 类型为 EventHandler

    用于设置 ended 事件类型 事件处理器 的属性,该事件类型被分发给 AudioScheduledSourceNode 节点类型。当源节点停止播放时(由具体节点确定),将向事件处理器分发一个使用 Event 接口的事件。

    对于所有 AudioScheduledSourceNode,当达到由 stop() 确定的停止时间时,将分发 ended 事件。对于 AudioBufferSourceNode,如果达到了 duration,或者如果整个 buffer 已播放完毕,也会分发该事件。

    1.7.2. 方法
    start(when)

    计划在精确的时间播放声音。

    调用此方法时,执行以下步骤:
    1. 如果此 AudioScheduledSourceNode 内部槽位 [[source started]] 为 true,则必须抛出 InvalidStateError 异常。

    2. 检查是否因下述参数约束而必须抛出任何错误。如果在执行此步骤期间抛出任何异常,请中止这些步骤。

    3. 将此 AudioScheduledSourceNode 上的内部槽位 [[source started]] 设置为 true

    4. 排队一个控制消息以启动 AudioScheduledSourceNode,并在消息中包含参数值。

    5. 仅在满足以下所有条件时,向关联的 AudioContext 发送一条 控制消息开始运行其渲染线程

      1. 该上下文的 [[control thread state]] 为 "suspended"。

      2. 上下文 允许启动

      3. [[suspended by user]] 标志为 false

      注意: 这允许 start() 启动一个当前 允许启动 但先前被阻止启动的 AudioContext

    AudioScheduledSourceNode.start(when) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    when double when 参数描述声音应在何时(以秒为单位)开始播放。它与 AudioContextcurrentTime 属性处于相同时间坐标系中。当 AudioScheduledSourceNode 发出的信号取决于声音的开始时间时,when 的精确值始终被使用,而不会四舍五入到最近的采样帧。如果此值传入 0,或者如果该值小于 currentTime,则声音将立即开始播放。 如果 when 为负数,则必须抛出 RangeError 异常。
    返回类型: undefined
    stop(when)

    计划在精确的时间停止声音播放。如果已经调用过 stop 后再次调用,则只有最后一次调用会被应用;先前的调用设置的停止时间将不会被应用,除非缓冲区在随后的任何调用之前已经停止。如果缓冲区已经停止,则后续调用 stop 将无效。如果停止时间早于计划的开始时间,则声音不会播放。

    调用此方法时,执行以下步骤:
    1. 如果此 AudioScheduledSourceNode 内部槽位 [[source started]] 不为 true,则必须抛出 InvalidStateError 异常。

    2. 检查是否因下述参数约束而必须抛出任何错误。

    3. 排队一个控制消息以停止 AudioScheduledSourceNode,并在消息中包含参数值。

    如果节点是 AudioBufferSourceNode,运行一个 控制消息 以停止 AudioBufferSourceNode 意味着在 播放算法 中调用 handleStop() 函数。
    AudioScheduledSourceNode.stop(when) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    when double when 参数描述源应在何时(以秒为单位)停止播放。它与 AudioContextcurrentTime 属性处于相同时间坐标系中。如果此值传入 0,或者如果该值小于 currentTime,则声音将立即停止播放。 如果 when 为负数,则必须抛出 RangeError 异常。
    返回类型: undefined

    1.8. AnalyserNode 接口

    此接口代表一个能够提供实时频率和时域分析信息的节点。音频流将未经处理地从输入传送到输出。

    [Exposed=Window]
    interface AnalyserNode : AudioNode {
        constructor (BaseAudioContext context, optional AnalyserOptions options = {});
        undefined getFloatFrequencyData (Float32Array array);
        undefined getByteFrequencyData (Uint8Array array);
        undefined getFloatTimeDomainData (Float32Array array);
        undefined getByteTimeDomainData (Uint8Array array);
        attribute unsigned long fftSize;
        readonly attribute unsigned long frequencyBinCount;
        attribute double minDecibels;
        attribute double maxDecibels;
        attribute double smoothingTimeConstant;
    };
    

    1.8.1. 构造函数
    AnalyserNode(context, options)

    当使用 BaseAudioContext c 和一个选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    AnalyserNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 AnalyserNode关联BaseAudioContext
    options AnalyserOptions AnalyserNode 的可选初始参数值。

    1.8.2. 属性
    fftSize, 类型为 unsigned long

    用于频域分析的 FFT 大小(以采样帧为单位)。 这必须是 32 到 32768 范围内的 2 的幂,否则必须抛出 IndexSizeError 异常。 默认值为 2048。注意,较大的 FFT 大小计算成本较高。

    如果 fftSize 更改为不同的值,则与频率数据平滑相关的所有状态(对于 getByteFrequencyData()getFloatFrequencyData())都将重置。也就是说,用于 随时间平滑前一个块 \(\hat{X}_{-1}[k]\) 被设置为所有 \(k\) 的 0。

    注意,增加 fftSize 确实意味着必须扩展 当前时域数据 以包含其之前未包含的过去帧。这意味着 AnalyserNode 有效地必须保留最后 32768 个采样帧,且 当前时域数据 是其中最近的 fftSize 个采样帧。

    frequencyBinCount, 类型为 unsigned long,只读

    FFT 大小的一半。

    maxDecibels, 类型为 double

    maxDecibels 是 FFT 分析数据转换为无符号字节值时缩放范围内的最大功率值。默认值为 -30。 如果此属性的值设置为小于或等于 minDecibels 的值,则必须抛出 IndexSizeError 异常。

    minDecibels, 类型为 double

    minDecibels 是 FFT 分析数据转换为无符号字节值时缩放范围内的最小功率值。默认值为 -100。 如果此属性的值设置为大于或等于 maxDecibels 的值,则必须抛出 IndexSizeError 异常。

    smoothingTimeConstant, 类型为 double

    一个从 0 到 1 的值,其中 0 表示不与上一个分析帧进行时间平均。默认值为 0.8。 如果此属性的值设置为小于 0 或大于 1,则必须抛出 IndexSizeError 异常。

    1.8.3. 方法
    getByteFrequencyData(array)

    当前频率数据 写入array 中。如果 array字节长度 小于 frequencyBinCount,多出的元素将被丢弃。如果 array字节长度 大于 frequencyBinCount,多出的元素将被忽略。计算频率数据时使用最近的 fftSize 个帧。

    如果另一次 getByteFrequencyData()getFloatFrequencyData() 调用发生在与上一次调用相同的 渲染时间量 内,则 当前频率数据 不会使用相同数据更新。相反,返回先前计算的数据。

    存储在无符号字节数组中的值按以下方式计算。设 \(Y[k]\) 为 FFT 窗口与平滑 中描述的 当前频率数据。那么字节值 \(b[k]\) 为:

    $$
        b[k] = \left\lfloor
                \frac{255}{\mbox{dB}_{max} - \mbox{dB}_{min}}
                \left(Y[k] - \mbox{dB}_{min}\right)
            \right\rfloor
    $$
    

    其中 \(\mbox{dB}_{min}\) 为 minDecibels,\(\mbox{dB}_{max}\) 为 maxDecibels。如果 \(b[k]\) 超出 0 到 255 的范围,则将 \(b[k]\) 钳位到该范围内。

    AnalyserNode.getByteFrequencyData() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    array Uint8Array 此参数是存储频域分析数据的目标位置。
    返回类型: undefined
    getByteTimeDomainData(array)

    当前时域数据(波形数据)写入array 中。如果 array字节长度 小于 fftSize,多出的元素将被丢弃。如果 array字节长度 大于 fftSize,多出的元素将被忽略。计算字节数据时使用最近的 fftSize 个帧。

    存储在无符号字节数组中的值按以下方式计算。设 \(x[k]\) 为时域数据。那么字节值 \(b[k]\) 为:

    $$
        b[k] = \left\lfloor 128(1 + x[k]) \right\rfloor.
    $$
    

    如果 \(b[k]\) 超出 0 到 255 的范围,则将 \(b[k]\) 钳位到该范围内。

    AnalyserNode.getByteTimeDomainData() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    array Uint8Array 此参数是存储时域采样数据的目标位置。
    返回类型: undefined
    getFloatFrequencyData(array)

    当前频率数据 写入array 中。如果 array 的元素少于 frequencyBinCount,多出的元素将被丢弃。如果 array 的元素多于 frequencyBinCount,多出的元素将被忽略。计算频率数据时使用最近的 fftSize 个帧。

    如果另一次 getFloatFrequencyData()getByteFrequencyData() 调用发生在与上一次调用相同的 渲染时间量 内,则 当前频率数据 不会使用相同数据更新。相反,返回先前计算的数据。

    频率数据以 dB 为单位。

    AnalyserNode.getFloatFrequencyData() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    array Float32Array 此参数是存储频域分析数据的目标位置。
    返回类型: undefined
    getFloatTimeDomainData(array)

    写入当前时域数据(波形数据)到 array 中。如果 array 的元素个数少于 fftSize 的值,多余的元素将被丢弃。如果 array 的元素个数多于 fftSize 的值,多余的元素将被忽略。写入的是最近的 fftSize 帧(在降混之后)。

    AnalyserNode.getFloatTimeDomainData() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    array Float32Array 此参数是存储时域采样数据的目标位置。
    返回类型: undefined

    1.8.4. AnalyserOptions

    此项指定构造 AnalyserNode 时使用的选项。所有成员均为可选;如果未指定,则使用正常的默认值来构造节点。

    dictionary AnalyserOptions : AudioNodeOptions {
        unsigned long fftSize = 2048;
        double maxDecibels = -30;
        double minDecibels = -100;
        double smoothingTimeConstant = 0.8;
    };
    
    1.8.4.1. 字典 AnalyserOptions 成员
    fftSize类型为 unsigned long,默认为 2048

    用于频域分析的期望 FFT 初始大小。

    maxDecibels类型为 double,默认为 -30

    用于 FFT 分析的期望初始最大功率(dB)。

    minDecibels类型为 double,默认为 -100

    用于 FFT 分析的期望初始最小功率(dB)。

    smoothingTimeConstant类型为 double,默认为 0.8

    用于 FFT 分析的期望初始平滑常数。

    1.8.5. 时域降混

    当计算当前时域数据时,输入信号必须降混为单声道,就如同 channelCount 为 1,channelCountMode 为 "max",且 channelInterpretation 为 "speakers" 一样。这与 AnalyserNode 本身的设置无关。最近的 fftSize 帧被用于降混操作。

    1.8.6. FFT 加窗与时间平滑

    当计算当前频率数据时,应执行以下操作

    在下文中,令 \(N\) 为该 AnalyserNodefftSize 属性值。

    应用 Blackman 窗 包含对时域输入数据执行以下操作。令 \(x[n]\)(其中 \(n = 0, \ldots, N - 1\))为时域数据。Blackman 窗定义为
    $$
    \begin{align*}
        \alpha &= \mbox{0.16} \\ a_0 &= \frac{1-\alpha}{2} \\
        a_1 &= \frac{1}{2} \\
        a_2 &= \frac{\alpha}{2} \\
        w[n] &= a_0 - a_1 \cos\frac{2\pi n}{N} + a_2 \cos\frac{4\pi n}{N}, \mbox{ for } n = 0, \ldots, N - 1
    \end{align*}
    $$
    

    加窗后的信号 \(\hat{x}[n]\) 为

    $$
        \hat{x}[n] = x[n] w[n], \mbox{ for } n = 0, \ldots, N - 1
    $$
    
    应用傅里叶变换 包含以如下方式计算傅里叶变换。令 \(X[k]\) 为复数频域数据,\(\hat{x}[n]\) 为上述计算得到的加窗时域数据。则
    $$
        X[k] = \frac{1}{N} \sum_{n = 0}^{N - 1} \hat{x}[n]\, W^{-kn}_{N}
    $$
    

    对于 \(k = 0, \dots, N/2-1\),其中 \(W_N = e^{2\pi i/N}\)。

    时间平滑 频率数据包含以下操作

    则平滑后的值 \(\hat{X}[k]\) 计算方式为

    $$
        \hat{X}[k] = \tau\, \hat{X}_{-1}[k] + (1 - \tau)\, \left|X[k]\right|
    $$
    
    • 如果 \(\hat{X}[k]\) 为 NaN、正无穷大或负无穷大,则将 \(\hat{X}[k]\) 设为 0。

    对于 \(k = 0, \ldots, N - 1\)。

    转换为 dB 包含以下操作,其中 \(\hat{X}[k]\) 是在时间平滑中计算得出的
    $$
        Y[k] = 20\log_{10}\hat{X}[k]
    $$
    

    对于 \(k = 0, \ldots, N-1\)。

    该数组 \(Y[k]\) 被复制到 getFloatFrequencyData() 的输出数组中。对于 getByteFrequencyData(),\(Y[k]\) 会被裁剪在 minDecibelsmaxDecibels 之间,并进行缩放以适应无符号字节(unsigned byte),使得 minDecibels 对应值 0,而 maxDecibels 对应值 255。

    1.9. AudioBufferSourceNode 接口

    此接口表示来自内存中 AudioBuffer 音频资产的音频源。它对于播放需要高度调度灵活性和准确性的音频资产非常有用。如果需要对网络或磁盘上的资产进行精确采样播放,实现者应使用 AudioWorkletNode 来实现播放。

    start() 方法用于调度声音何时开始播放。start() 方法不能被多次调用。当缓冲区的音频数据完全播放完毕(如果 loop 属性为 false),或者当调用了 stop() 方法且到达了指定时间时,播放将自动停止。请参阅 start()stop() 的描述以了解更多详情。

    输出的通道数等于分配给 buffer 属性的 AudioBuffer 的通道数,如果 buffernull,则为一个通道的静音。

    此外,如果缓冲区具有多于一个通道,那么 AudioBufferSourceNode 的输出必须在满足以下任一条件的渲染量子(render quantum)开始时变为单通道静音

    AudioBufferSourceNode播放头位置 定义为任何表示以秒为单位的时间偏移量,相对于缓冲区中第一采样帧的时间坐标。此类值应独立于节点的 playbackRatedetune 参数来考虑。通常,播放头位置可能是亚采样(subsample)精度的,无需引用确切的采样帧位置。它们可以取 0 到缓冲区持续时间之间的有效值。

    playbackRatedetune 属性构成一个 复合参数。它们共同用于确定一个 computedPlaybackRate 值。

    computedPlaybackRate(t) = playbackRate(t) * pow(2, detune(t) / 1200)
    

    复合参数标称范围 为 \((-\infty, \infty)\)。

    AudioBufferSourceNode 在创建时带有一个内部布尔槽 [[buffer set]],初始设置为 false。

    [Exposed=Window]
    interface AudioBufferSourceNode : AudioScheduledSourceNode {
        constructor (BaseAudioContext context,
                     optional AudioBufferSourceOptions options = {});
        attribute AudioBuffer? buffer;
        readonly attribute AudioParam playbackRate;
        readonly attribute AudioParam detune;
        attribute boolean loop;
        attribute double loopStart;
        attribute double loopEnd;
        undefined start (optional double when = 0,
                         optional double offset,
                         optional double duration);
    };
    

    1.9.1. 构造函数

    AudioBufferSourceNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须使用 contextoptions 作为参数初始化 AudioNode this

    AudioBufferSourceNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 AudioBufferSourceNode关联到的 BaseAudioContext
    options AudioBufferSourceOptions AudioBufferSourceNode 的可选初始参数值。

    1.9.2. 属性

    buffer类型为 AudioBuffer,可为空(nullable)

    表示要播放的音频资产。

    要设置 buffer 属性,请执行以下步骤
    1. new buffer 为要分配给 bufferAudioBuffernull 值。

    2. 如果 new buffer 不为 null[[buffer set]] 为 true,则抛出 InvalidStateError 并中止这些步骤。

    3. 如果 new buffer 不为 null,将 [[buffer set]] 设置为 true。

    4. new buffer 分配给 buffer 属性。

    5. 如果之前已在此节点上调用过 start(),则对 buffer 执行获取内容操作。

    detune类型为 AudioParam,只读

    一个额外的参数(以音分为单位),用于调制渲染音频流的速度。此参数是与 playbackRate 组合形成的复合参数,用于形成 computedPlaybackRate

    loop类型为 boolean

    指示是否应连续循环播放由 loopStartloopEnd 指定的音频数据区域。默认值为 false

    loopEnd类型为 double

    如果 loop 属性为 true,则为可选的播放头位置,循环应在此处结束。其值不包含循环内容。其默认 value 为 0,通常可设置为 0 与缓冲区持续时间之间的任意值。如果 loopEnd 小于或等于 0,或者大于缓冲区持续时间,循环将在缓冲区末尾结束。

    loopStart类型为 double

    如果 loop 属性为 true,则为可选的播放头位置,循环应在此处开始。其默认 value 为 0,通常可设置为 0 与缓冲区持续时间之间的任意值。如果 loopStart 小于 0,循环将在 0 处开始。如果 loopStart 大于缓冲区持续时间,循环将在缓冲区末尾开始。

    playbackRate类型为 AudioParam,只读

    渲染音频流的速度。这是一个与 detune 结合使用的复合参数,用于形成 computedPlaybackRate

    1.9.3. 方法

    start(when, offset, duration)

    计划在精确的时间播放声音。

    调用此方法时,执行以下步骤:
    1. 如果此 AudioBufferSourceNode 的内部槽 [[source started]]true,则必须抛出 InvalidStateError 异常。

    2. 检查是否因下述参数约束而必须抛出任何错误。如果在执行此步骤期间抛出任何异常,请中止这些步骤。

    3. 将此 AudioBufferSourceNode 上的内部槽 [[source started]] 设置为 true

    4. 排队一个控制消息以启动 AudioBufferSourceNode,并在消息中包含参数值。

    5. 如果已设置 buffer,则获取 buffer 的内容。

    6. 仅在满足以下所有条件时,向关联的 AudioContext 发送控制消息开始运行其渲染线程

      1. 上下文的 [[control thread state]]suspended

      2. 上下文被允许启动

      3. [[suspended by user]] 标志为 false

      注意:这可以允许 start() 启动一个当前被允许启动但之前被阻止启动的 AudioContext

    运行控制消息以启动 AudioBufferSourceNode 意味着调用下文播放算法中的 handleStart() 函数。
    AudioBufferSourceNode.start(when, offset, duration) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    when double when 参数描述声音应在什么时间(以秒为单位)开始播放。它与 AudioContextcurrentTime 属性处于相同的时间坐标系中。如果为此值传入 0,或者如果该值小于 currentTime,则声音将立即开始播放。 如果 when 为负数,则必须抛出 RangeError 异常。
    offset double offset 参数提供了一个播放将要开始的播放头位置。如果为此值传入 0,则播放将从缓冲区开头开始。如果 offset 为负数,则必须抛出 RangeError 异常。 如果 offset 大于 loopEnd,且 playbackRate 为正数或零,并且 looptrue,则播放将从 loopEnd 开始。如果 offset 大于 loopStart,且 playbackRate 为负数,并且 looptrue,则播放将从 loopStart 开始。当到达 startTime 时,offset 会被静默截断为 [0, duration],其中 duration 是设置为此 AudioBufferSourceNodebuffer 属性的 AudioBufferduration 属性值。
    duration double duration 参数描述要播放的声音持续时间,表示为要输出的缓冲区内容的总秒数,包括任何完整或部分的循环迭代。duration 的单位独立于 playbackRate 的影响。例如,持续时间为 5 秒且播放速率为 0.5 时,将以半速输出 5 秒的缓冲区内容,产生 10 秒的可听输出。如果 duration 为负数,则必须抛出 RangeError 异常。
    返回类型: undefined

    1.9.4. AudioBufferSourceOptions

    此项指定用于构造 AudioBufferSourceNode 的选项。所有成员均为可选;如果未指定,则使用正常的默认值来构造节点。

    dictionary AudioBufferSourceOptions {
        AudioBuffer? buffer;
        float detune = 0;
        boolean loop = false;
        double loopEnd = 0;
        double loopStart = 0;
        float playbackRate = 1;
    };
    
    1.9.4.1. 字典 AudioBufferSourceOptions 成员
    buffer类型为 AudioBuffer,可为空

    要播放的音频资产。这等同于将 buffer 分配给 AudioBufferSourceNodebuffer 属性。

    detune类型为 float,默认为 0

    detune AudioParam 的初始值。

    loop类型为 boolean,默认为 false

    loop 属性的初始值。

    loopEnd类型为 double,默认为 0

    loopEnd 属性的初始值。

    loopStart类型为 double,默认为 0

    loopStart 属性的初始值。

    playbackRate类型为 float,默认为 1

    playbackRate AudioParam 的初始值。

    1.9.5. 循环

    本节是非规范性的。请参阅播放算法以了解规范性要求。

    一旦播放了循环区域的任何部分,将 loop 属性设置为 true,将导致由终点 loopStartloopEnd 定义的缓冲区区域无限期循环播放。当 loop 保持为 true 时,循环播放将持续,直到发生以下情况之一

    • 调用了 stop()

    • 已到达预定的停止时间,

    • 已超过 duration(如果调用 start() 时带有了 duration 值)。

    循环主体被视为占据从 loopStart 到但不包括 loopEnd 的区域。循环区域的播放方向遵循节点的播放速率的符号。对于正向播放速率,循环从 loopStartloopEnd 进行;对于负向速率,循环从 loopEndloopStart 进行。

    循环不会影响 start()offset 参数的解释。播放始终从请求的偏移量开始,循环仅在播放期间遇到循环主体时才开始。

    有效的循环起点和终点必须位于零和缓冲区持续时间的范围内,如下面的算法中所述。 loopEnd 进一步被限制为必须在 loopStart 处或之后。如果违反了这些限制中的任何一个,循环将被视为包含整个缓冲区内容。

    循环端点具有亚采样精度。当端点未落在精确的采样帧偏移量上,或者当播放速率不等于 1 时,循环播放会进行插值以拼接循环的开头和结尾,就像循环音频出现在缓冲区中连续、非循环的区域中一样。

    循环相关属性可能会在缓冲区播放期间变化,通常在下一个渲染量子生效。确切结果由下文的规范性播放算法定义。

    loopStartloopEnd 属性的默认值均为 0。由于 loopEnd 为零等同于缓冲区的长度,因此默认端点会导致整个缓冲区被包含在循环中。

    注意,循环端点的值表示为相对于缓冲区采样率的时间偏移量,这意味着这些值独立于节点的 playbackRate 参数,该参数在播放过程中可能会动态变化。

    1.9.6. AudioBuffer 内容的播放

    此规范性部分规定了缓冲区内容的播放,考虑到播放受到以下因素共同影响的事实

    • 起始偏移量,可以以亚采样精度表示。

    • 循环点,可以以亚采样精度表示,并在播放期间动态变化。

    • 播放速率和失谐(detuning)参数,它们组合产生一个单一的 computedPlaybackRate,该值可以取正数或负数的有限值。

    内部遵循以从 AudioBufferSourceNode 生成输出的算法符合以下原则

    • UA 可能在任何期望的点随意执行缓冲区的重采样,以提高输出的效率或质量。

    • 亚采样起始偏移量或循环点可能需要在采样帧之间进行额外的插值。

    • 循环缓冲区的播放行为应与包含循环音频内容连续出现的非循环缓冲区行为相同,不包括插值的影响。

    该算法的描述如下

    let buffer; // AudioBuffer employed by this nodelet context; // AudioContext employed by this node// The following variables capture attribute and AudioParam values for the node.// They are updated on a k-rate basis, prior to each invocation of process().let loop;let detune;let loopStart;let loopEnd;let playbackRate;// Variables for the node's playback parameterslet start = 0, offset = 0, duration = Infinity; // Set by start()let stop = Infinity; // Set by stop()// Variables for tracking node's playback statelet bufferTime = 0, started = false, enteredLoop = false;let bufferTimeElapsed = 0;let dt = 1 / context.sampleRate;// Handle invocation of start method callfunction handleStart(when, pos, dur) {    if (arguments.length >= 1) {        start = when;    }    offset = pos;    if (arguments.length >= 3) {        duration = dur;    }}// Handle invocation of stop method callfunction handleStop(when) {    if (arguments.length >= 1) {        stop = when;    } else {        stop = context.currentTime;    }}// Interpolate a multi-channel signal value for some sample frame.// Returns an array of signal values.function playbackSignal(position) {    /*        This function provides the playback signal function for buffer, which is a        function that maps from a playhead position to a set of output signal        values, one for each output channel. If |position| corresponds to the        location of an exact sample frame in the buffer, this function returns        that frame. Otherwise, its return value is determined by a UA-supplied        algorithm that interpolates sample frames in the neighborhood of        |position|.        If |position| is greater than or equal to |loopEnd| and there is no subsequent        sample frame in buffer, then interpolation should be based on the sequence        of subsequent frames beginning at |loopStart|.     */     ...}// Generate a single render quantum of audio to be placed// in the channel arrays defined by output. Returns an array// of |numberOfFrames| sample frames to be output.function process(numberOfFrames) {    let currentTime = context.currentTime; // context time of next rendered frame    const output = []; // accumulates rendered sample frames    // Combine the two k-rate parameters affecting playback rate    const computedPlaybackRate = playbackRate * Math.pow(2, detune / 1200);    // Determine loop endpoints as applicable    let actualLoopStart, actualLoopEnd;    if (loop && buffer != null) {        if (loopStart >= 0 && loopEnd > 0 && loopStart < loopEnd) {            actualLoopStart = loopStart;            actualLoopEnd = Math.min(loopEnd, buffer.duration);        } else {            actualLoopStart = 0;            actualLoopEnd = buffer.duration;        }    } else {        // If the loop flag is false, remove any record of the loop having been entered        enteredLoop = false;    }    // Handle null buffer case    if (buffer == null) {        stop = currentTime; // force zero output for all time    }    // Render each sample frame in the quantum    for (let index = 0; index < numberOfFrames; index++) {        // Check that currentTime and bufferTimeElapsed are        // within allowable range for playback        if (currentTime < start || currentTime >= stop || bufferTimeElapsed >= duration) {            output.push(0); // this sample frame is silent            currentTime += dt;            continue;        }        if (!started) {            // Take note that buffer has started playing and get initial            // playhead position.            if (loop && computedPlaybackRate >= 0 && offset >= actualLoopEnd) {                offset = actualLoopEnd;            }            if (computedPlaybackRate < 0 && loop && offset < actualLoopStart) {                offset = actualLoopStart;            }            bufferTime = offset;            started = true;        }        // Handle loop-related calculations        if (loop) {            // Determine if looped portion has been entered for the first time            if (!enteredLoop) {                if (offset < actualLoopEnd && bufferTime >= actualLoopStart) {                    // playback began before or within loop, and playhead is                    // now past loop start                    enteredLoop = true;                }                if (offset >= actualLoopEnd && bufferTime < actualLoopEnd) {                    // playback began after loop, and playhead is now prior                    // to the loop end                    enteredLoop = true;                }            }            // Wrap loop iterations as needed. Note that enteredLoop            // may become true inside the preceding conditional.            if (enteredLoop) {                while (bufferTime >= actualLoopEnd) {                    bufferTime -= actualLoopEnd - actualLoopStart;                }                while (bufferTime < actualLoopStart) {                    bufferTime += actualLoopEnd - actualLoopStart;                }            }        }        if (bufferTime >= 0 && bufferTime < buffer.duration) {            output.push(playbackSignal(bufferTime));        } else {            output.push(0); // past end of buffer, so output silent frame        }        bufferTime += dt * computedPlaybackRate;        bufferTimeElapsed += dt * computedPlaybackRate;        currentTime += dt;    } // End of render quantum loop    if (currentTime >= stop) {        // End playback state of this node.  No further invocations of process()        // will occur.  Schedule a change to set the number of output channels to 1.    }    return output;}

    以下非规范性图表展示了算法在各种关键场景下的行为。未考虑缓冲区的动态重采样,但只要循环位置的时间不发生变化,这不会实质性影响最终的播放。在所有图表中,适用以下约定

    • 上下文采样率为 1000 Hz

    • AudioBuffer 内容显示在 x 原点处具有第一采样帧。

    • 输出信号显示在 x 原点处具有位于 start 时间的采样帧。

    • 通篇描绘了线性插值,尽管 UA 可以采用其他插值技术。

    • 图中注明的 duration 值是指 buffer,而不是 start() 的参数。

    此图展示了缓冲区的基本播放,带有一个简单的循环,该循环在缓冲区中的最后一个采样帧之后结束。

    AudioBufferSourceNode basic playback
    AudioBufferSourceNode 基本播放

    此图展示了 playbackRate 插值,显示了缓冲区内容的半速播放,其中每隔一个输出采样帧都经过插值。特别值得注意的是循环输出中的最后一个采样帧,它是使用循环起点进行插值的。

    AudioBufferSourceNode playbackRate interpolation
    AudioBufferSourceNode playbackRate 插值

    此图展示了采样率插值,显示了采样率为上下文采样率 50% 的缓冲区的播放,导致计算出的播放速率为 0.5,该速率修正了缓冲区和上下文之间采样率的差异。最终的输出与前一个示例相同,但原因不同。

    AudioBufferSourceNode sample rate interpolation
    AudioBufferSourceNode 采样率插值。

    此图展示了亚采样偏移播放,其中缓冲区内的偏移量从正好半个采样帧处开始。因此,每个输出帧都经过了插值。

    AudioBufferSourceNode subsample offset playback
    AudioBufferSourceNode 亚采样偏移播放

    此图展示了亚采样循环播放,显示循环端点中的分数帧偏移量如何映射到缓冲区中的插值数据点,这些数据点尊重这些偏移量,就像它们是对确切采样帧的引用一样。

    AudioBufferSourceNode subsample loop playback
    AudioBufferSourceNode 亚采样循环播放

    1.10. AudioDestinationNode 接口

    这是一个表示最终音频目的地的 AudioNode,是用户最终将听到的内容。它通常可以被认为是一个连接到扬声器的音频输出设备。所有待听取的已渲染音频都将路由到此节点,这是 AudioContext 路由图中的一个“终端”节点。每个 AudioContext 只有一个 AudioDestinationNode,通过 AudioContextdestination 属性提供。

    AudioDestinationNode 的输出是通过对其输入进行求和产生的,从而可以将 AudioContext 的输出捕获到例如 MediaStreamAudioDestinationNodeMediaRecorder(详见 [mediastream-recording])中。

    AudioDestinationNode 可以是 AudioContextOfflineAudioContext 的目的地,通道属性取决于上下文的类型。

    对于 AudioContext,默认值为

    channelCount 可以设置为小于或等于 maxChannelCount 的任何值。如果该值不在有效范围内,则必须抛出 IndexSizeError 异常。 给出一个具体示例,如果音频硬件支持 8 通道输出,那么我们可以将 channelCount 设置为 8,并渲染 8 个通道的输出。

    对于 OfflineAudioContext,默认值为

    其中 numberOfChannels 是构造 OfflineAudioContext 时指定的通道数。此值不能更改;如果 channelCount 被更改为不同的值,必须抛出 NotSupportedError 异常

    [Exposed=Window]
    interface AudioDestinationNode : AudioNode {
        readonly attribute unsigned long maxChannelCount;
    };
    

    1.10.1. 属性

    maxChannelCount类型为 unsigned long,只读

    channelCount 属性可以设置为的最大通道数。如果音频硬件是多通道的,则表示音频硬件终点(通常情况)的 AudioDestinationNode 可能输出超过 2 个通道的音频。maxChannelCount 是此硬件能够支持的最大通道数。

    1.11. The AudioListener Interface

    此接口表示收听音频场景的人的位置和方向。所有 PannerNode 对象都相对于 BaseAudioContextlistener 进行空间化。有关空间化的更多详细信息,请参阅 § 6 空间化/声像控制

    positionXpositionYpositionZ 参数表示收听者在 3D 笛卡尔坐标空间中的位置。PannerNode 对象使用此位置相对于单个音频源进行空间化。

    forwardXforwardYforwardZ 参数表示 3D 空间中的方向向量。forward 向量和 up 向量都用于确定收听者的方向。用简单的人类语言来说,forward 向量表示人鼻子指向的方向。up 向量表示人头顶指向的方向。这两个向量应是线性独立的。关于如何解释这些值的规范性要求,请参阅 § 6 空间化/声像控制 部分。

    [Exposed=Window]
    interface AudioListener {
        readonly attribute AudioParam positionX;
        readonly attribute AudioParam positionY;
        readonly attribute AudioParam positionZ;
        readonly attribute AudioParam forwardX;
        readonly attribute AudioParam forwardY;
        readonly attribute AudioParam forwardZ;
        readonly attribute AudioParam upX;
        readonly attribute AudioParam upY;
        readonly attribute AudioParam upZ;
        undefined setPosition (float x, float y, float z);
        undefined setOrientation (float x, float y, float z, float xUp, float yUp, float zUp);
    };
    

    1.11.1. 属性

    forwardX类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置收听者指向的前向方向的 x 坐标分量。

    forwardY类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置收听者指向的前向方向的 y 坐标分量。

    forwardZ类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置收听者指向的前向方向的 z 坐标分量。

    参数
    defaultValue -1
    minValue most-negative-single-float 约为 -3.4028235e38
    maxValue most-positive-single-float 约为 3.4028235e38
    automationRate "a-rate"
    positionX类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置音频收听者的 x 坐标位置。

    positionY类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置音频收听者的 y 坐标位置。

    positionZ类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置音频收听者的 z 坐标位置。

    upX类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置收听者指向的上方方向的 x 坐标分量。

    upY类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置收听者指向的上方方向的 y 坐标分量。

    upZ类型为 AudioParam,只读

    在 3D 笛卡尔坐标空间中设置收听者指向的上方方向的 z 坐标分量。

    1.11.2. 方法

    setOrientation(x, y, z, xUp, yUp, zUp)

    此方法已弃用。它等同于直接使用给定的 xyzxUpyUpzUp 值分别设置 forwardX.valueforwardY.valueforwardZ.valueupX.valueupY.valueupZ.value

    因此,如果在调用此方法时,forwardXforwardYforwardZupXupYupZ AudioParam 中的任何一个已使用 setValueCurveAtTime() 设置了自动化曲线,则必须抛出 NotSupportedError 异常。

    setOrientation() 描述了收听者在 3D 笛卡尔坐标空间中指向的方向。同时提供了前向向量和向上向量。用简单的人类语言来说,前向向量表示人鼻子指向的方向。 向上 向量表示人头顶指向的方向。这两个向量应是线性独立的。关于如何解释这些值的规范性要求,请参阅 § 6 空间化/声像控制

    xyz 参数表示 3D 空间中的前向方向向量,默认值为 (0,0,-1)。

    xUpyUpzUp 参数表示 3D 空间中的向上方向向量,默认值为 (0,1,0)。

    AudioListener.setOrientation() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    x float AudioListener 的前向 x 方向
    y float AudioListener 的前向 y 方向
    z float AudioListener 的前向 z 方向
    xUp float AudioListener 的向上 x 方向
    yUp float AudioListener 的向上 y 方向
    zUp float AudioListener 的向上 z 方向
    返回类型: undefined
    setPosition(x, y, z)

    此方法已弃用。它等同于直接使用给定的 xyz 值分别设置 positionX.valuepositionY.valuepositionZ.value

    因此,如果在调用此方法时,该 AudioListener 的任何 positionXpositionYpositionZ AudioParams 已使用 setValueCurveAtTime() 设置了自动化曲线,则必须抛出 NotSupportedError 异常。

    setPosition() 在 3D 笛卡尔坐标空间中设置收听者的位置。PannerNode 对象使用此位置相对于单个音频源进行空间化。

    xyz 参数表示 3D 空间中的坐标。

    默认值为 (0,0,0)。

    AudioListener.setPosition() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    x float AudioListener 位置的 x 坐标
    y float AudioListener 位置的 y 坐标
    z float AudioListener 位置的 z 坐标

    1.11.3. 处理

    由于 AudioListener 的参数可以与 AudioNode 连接,并且它们还会影响同一图中 PannerNode 的输出,因此节点排序算法在计算处理顺序时应考虑 AudioListener。出于这个原因,图中的所有 PannerNode 均以 AudioListener 作为输入。

    1.12. The AudioProcessingEvent Interface - 已弃用

    这是一个被分发给 ScriptProcessorNode 节点的 Event 对象。当 ScriptProcessorNode 被移除时,它也将被移除,因为替代品 AudioWorkletNode 使用了不同的方法。

    事件处理程序通过访问 inputBuffer 属性中的音频数据来处理来自输入(如果有)的音频。处理结果产生的音频数据(如果没有输入,则为合成数据)随后被放置到 outputBuffer 中。

    [Exposed=Window]
    interface AudioProcessingEvent : Event {
        constructor (DOMString type, AudioProcessingEventInit eventInitDict);
        readonly attribute double playbackTime;
        readonly attribute AudioBuffer inputBuffer;
        readonly attribute AudioBuffer outputBuffer;
    };
    

    1.12.1. 属性

    inputBuffer类型为 AudioBuffer,只读

    一个包含输入音频数据的 AudioBuffer。它将具有与 createScriptProcessor() 方法的 numberOfInputChannels 参数相等的通道数。此 AudioBuffer 仅在 audioprocess 事件处理函数的作用域内有效。其值在此作用域之外将毫无意义。

    outputBuffer类型为 AudioBuffer,只读

    一个必须写入输出音频数据的 AudioBuffer。它将具有与 createScriptProcessor() 方法的 numberOfOutputChannels 参数相等的通道数。audioprocess 事件处理函数作用域内的脚本代码应修改此 AudioBuffer 中表示通道数据的 Float32Array 数组。在此作用域之外对该 AudioBuffer 进行的任何脚本修改都不会产生任何可听效果。

    playbackTime类型为 double,只读

    音频将在与 AudioContextcurrentTime 相同的时间坐标系中播放的时间。

    1.12.2. AudioProcessingEventInit

    dictionary AudioProcessingEventInit : EventInit {
        required double playbackTime;
        required AudioBuffer inputBuffer;
        required AudioBuffer outputBuffer;
    };
    
    1.12.2.1. 字典 AudioProcessingEventInit 成员
    inputBuffer类型为 AudioBuffer

    要分配给事件的 inputBuffer 属性的值。

    outputBuffer类型为 AudioBuffer

    要分配给事件的 outputBuffer 属性的值。

    playbackTime类型为 double

    要分配给事件的 playbackTime 属性的值。

    1.13. The BiquadFilterNode Interface

    BiquadFilterNode 是实现非常常见的低阶滤波器的 AudioNode 处理器。

    低阶滤波器是基本音调控制(低音、中音、高音)、图形均衡器和更高级滤波器的构建块。可以将多个 BiquadFilterNode 滤波器组合起来形成更复杂的滤波器。滤波器的参数(如 frequency)可以随时间改变,用于滤波器扫描等。每个 BiquadFilterNode 都可以配置为多种常见滤波器类型中的一种,如下面的 IDL 所示。默认滤波器类型为 "lowpass"

    frequencydetune 均构成一个复合参数,且两者均为a-rate。它们共同用于确定一个 computedFrequency 值。

    computedFrequency(t) = frequency(t) * pow(2, detune(t) / 1200)
    

    复合参数标称范围为 [0, 奈奎斯特频率]。

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2
    channelCountMode "max"
    channelInterpretation "speakers"
    tail-time 继续在无输入的情况下输出非静音音频。由于这是一个 IIR 滤波器,该滤波器会永远产生非零输入,但在实践中,这可以在某个有限时间后限制,此时输出已足够接近零。实际时间取决于滤波器系数。

    输出的通道数始终等于输入的通道数。

    enum BiquadFilterType {
        "lowpass",
        "highpass",
        "bandpass",
        "lowshelf",
        "highshelf",
        "peaking",
        "notch",
        "allpass"
    };
    
    BiquadFilterType 枚举描述
    枚举值描述
    "lowpass"低通滤波器 (lowpass filter) 允许截止频率以下的频率通过,并衰减截止频率以上的频率。它实现了一个标准的二阶谐振低通滤波器,滚降斜率为 12dB/倍频程。
    frequency

    截止频率

    变量 A

    控制在截止频率处响应的峰值程度。值越大,响应的峰值越明显。

    gain

    此滤波器类型不使用

    "highpass"高通滤波器 (highpass filter) 与低通滤波器相反。它允许截止频率以上的频率通过,而衰减截止频率以下的频率。它实现了一个标准的二阶谐振高通滤波器,滚降斜率为 12dB/倍频程。
    frequency

    截止频率,低于此频率的频率将被衰减

    变量 A

    控制在截止频率处响应的峰值程度。值越大,响应的峰值越明显。

    gain

    此滤波器类型不使用

    "bandpass"带通滤波器 (bandpass filter) 允许一定范围内的频率通过,并衰减此频率范围之外(以下和以上)的频率。它实现了一个二阶带通滤波器。
    frequency

    频带的中心

    变量 A

    控制频带的宽度。Q 值增加,带宽变窄。

    gain

    此滤波器类型不使用

    "lowshelf"低架滤波器 (lowshelf filter) 允许所有频率通过,但会对较低频率进行增强(或衰减)。它实现了一个二阶低架滤波器。
    frequency

    应用增强(或衰减)频率的上限。

    变量 A

    此滤波器类型不使用。

    gain

    要应用的增强增益(以 dB 为单位)。如果该值为负,则频率被衰减。

    "highshelf"高架滤波器 (highshelf filter) 与低架滤波器相反,允许所有频率通过,但会对较高频率进行增强。它实现了一个二阶高架滤波器。
    frequency

    应用增强(或衰减)频率的下限。

    变量 A

    此滤波器类型不使用。

    gain

    要应用的增强增益(以 dB 为单位)。如果该值为负,则频率被衰减。

    "peaking"峰值滤波器 (peaking filter) 允许所有频率通过,但会对一定范围内的频率进行增强(或衰减)。
    frequency

    应用增强的中心频率。

    变量 A

    控制被增强的频带宽度。较大的值意味着较窄的宽度。

    gain

    要应用的增强增益(以 dB 为单位)。如果该值为负,则频率被衰减。

    "notch"陷波滤波器 (notch filter)(也称为 带阻滤波器)与带通滤波器相反。它允许除一组特定频率之外的所有频率通过。
    frequency

    应用陷波的中心频率。

    变量 A

    控制被衰减的频带宽度。较大的值意味着较窄的宽度。

    gain

    此滤波器类型不使用。

    "allpass"全通滤波器 (allpass filter) 允许所有频率通过,但会改变各频率之间的相位关系。它实现了一个二阶全通滤波器。
    frequency

    相位转换中心发生的频率。换个角度看,这是具有最大 群延迟 (group delay) 的频率。

    变量 A

    控制中心频率处相位转换的尖锐程度。较大的值意味着更尖锐的转换和更大的群延迟。

    gain

    此滤波器类型不使用。

    BiquadFilterNode 的所有属性均为 a-rate AudioParam

    [Exposed=Window]
    interface BiquadFilterNode : AudioNode {
        constructor (BaseAudioContext context, optional BiquadFilterOptions options = {});
        attribute BiquadFilterType type;
        readonly attribute AudioParam frequency;
        readonly attribute AudioParam detune;
        readonly attribute AudioParam Q;
        readonly attribute AudioParam gain;
        undefined getFrequencyResponse (Float32Array frequencyHz,
                                        Float32Array magResponse,
                                        Float32Array phaseResponse);
    };
    

    1.13.1. 构造函数

    BiquadFilterNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    BiquadFilterNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 BiquadFilterNode关联 到的 BaseAudioContext
    options BiquadFilterOptions BiquadFilterNode 的可选初始参数值。

    1.13.2. 属性

    Q, 类型为 AudioParam, 只读

    滤波器的 Q 值 (Q factor)

    对于 lowpasshighpass 滤波器,Q 值被解释为以 dB 为单位。对于这些滤波器,标称范围是 \([-Q_{lim}, Q_{lim}]\),其中 \(Q_{lim}\) 是 \(10^{Q/20}\) 不会溢出的最大值。这大约是 \(770.63678\)。

    对于 bandpassnotchallpasspeaking 滤波器,该值是一个线性值。该值与滤波器的带宽相关,因此应为正值。标称范围是 \([0, 3.4028235e38]\),上限为 最大正单精度浮点数

    此属性不用于 lowshelfhighshelf 滤波器。

    参数
    defaultValue 1
    minValue most-negative-single-float 大约 -3.4028235e38,但请参阅上文了解不同滤波器的实际限制。
    maxValue most-positive-single-float 大约 3.4028235e38,但请参阅上文了解不同滤波器的实际限制。
    automationRate "a-rate"
    detune, 类型为 AudioParam, 只读

    频率的失谐值(以音分为单位)。它与 frequency 形成一个 复合参数,构成 计算频率 (computedFrequency)

    参数
    defaultValue 0
    minValue \(\approx -153600\)
    maxValue \(\approx 153600\)该值大约为 \(1200\ \log_2 \mathrm{FLT\_MAX}\),其中 FLT_MAX 是最大的 float 值。
    automationRate "a-rate"
    frequency, 类型为 AudioParam, 只读

    BiquadFilterNode 工作的频率(以 Hz 为单位)。它与 detune 形成一个 复合参数,构成 计算频率

    gain, 类型为 AudioParam, 只读

    滤波器的增益。其值以 dB 为单位。增益仅用于 lowshelfhighshelfpeaking 滤波器。

    参数
    defaultValue 0
    minValue most-negative-single-float 约为 -3.4028235e38
    maxValue \(\approx 1541\)该值大约为 \(40\ \log_{10} \mathrm{FLT\_MAX}\),其中 FLT_MAX 是最大的 float 值。
    automationRate "a-rate"
    type, 类型为 BiquadFilterType

    BiquadFilterNode 的类型。其默认值为 "lowpass"。其他参数的确切含义取决于 type 属性的值。

    1.13.3. 方法

    getFrequencyResponse(frequencyHz, magResponse, phaseResponse)

    给定每个滤波器参数的 [[当前值]],同步计算指定频率的频率响应。这三个参数必须是相同长度的 Float32Array,否则必须抛出 InvalidAccessError

    返回的频率响应必须使用当前处理块中采样的 AudioParam 计算。

    BiquadFilterNode.getFrequencyResponse() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    frequencyHz Float32Array 此参数指定一个频率数组(以 Hz 为单位),响应值将在这些频率下计算。
    magResponse Float32Array 此参数指定一个输出数组,用于接收线性幅值响应值。如果 frequencyHz 参数中的某个值不在 [0, sampleRate/2] 范围内(其中 sampleRateAudioContextsampleRate 属性值),则 magResponse 数组中对应索引处的值必须为 NaN
    phaseResponse Float32Array 此参数指定一个输出数组,用于接收弧度制的相位响应值。如果 frequencyHz 参数中的某个值不在 [0, sampleRate/2] 范围内(其中 sampleRateAudioContextsampleRate 属性值),则 phaseResponse 数组中对应索引处的值必须为 NaN
    返回类型: undefined

    1.13.4. BiquadFilterOptions

    这指定了构建 BiquadFilterNode 时使用的选项。所有成员均为可选;如果未指定,则使用正常的默认值构建节点。

    dictionary BiquadFilterOptions : AudioNodeOptions {
        BiquadFilterType type = "lowpass";
        float Q = 1;
        float detune = 0;
        float frequency = 350;
        float gain = 0;
    };
    
    1.13.4.1. 字典 BiquadFilterOptions 成员
    Q, 类型为 float, 默认值为 1

    Q 的期望初始值。

    detune, 类型为 float, 默认值为 0

    detune 的期望初始值。

    frequency, 类型为 float, 默认值为 350

    frequency 的期望初始值。

    gain, 类型为 float, 默认值为 0

    gain 的期望初始值。

    type, 类型为 BiquadFilterType, 默认值为 "lowpass"

    滤波器的期望初始类型。

    1.13.5. 滤波器特性

    通过 BiquadFilterNode 可用的滤波器类型有多种实现方式,每种都有非常不同的特性。本节中的公式描述了 符合规范的实现 必须实现的滤波器,因为它们决定了不同滤波器类型的特性。它们灵感来源于 Audio EQ Cookbook 中的公式。

    BiquadFilterNode 处理音频的传递函数为

    $$
     H(z) = \frac{\frac{b_0}{a_0} + \frac{b_1}{a_0}z^{-1} + \frac{b_2}{a_0}z^{-2}}
                                              {1+\frac{a_1}{a_0}z^{-1}+\frac{a_2}{a_0}z^{-2}}
    $$
    

    这等同于以下时域方程

    $$
    a_0 y(n) + a_1 y(n-1) + a_2 y(n-2) =
        b_0 x(n) + b_1 x(n-1) + b_2 x(n-2)
    $$
    

    初始滤波器状态为 0。

    注意: 虽然固定滤波器是稳定的,但使用 AudioParam 的自动化功能可能会创建不稳定的双二阶 (biquad) 滤波器。开发者有责任管理这一点。

    注意: 用户代理 (UA) 可能会产生警告,通知用户滤波器状态中出现了 NaN 值。这通常表明滤波器不稳定。

    上述传递函数中的系数对于每种节点类型都是不同的。基于 BiquadFilterNodeAudioParam计算值,计算它们需要以下中间变量。

    • 令 \(F_s\) 为此 AudioContextsampleRate 属性值。

    • 令 \(f_0\) 为 计算频率 的值。

    • 令 \(G\) 为 gain AudioParam 的值。

    • 令 \(Q\) 为 Q AudioParam 的值。

    • 最后令

      $$
      \begin{align*}
          A &= 10^{\frac{G}{40}} \\
          \omega_0 &= 2\pi\frac{f_0}{F_s} \\
          \alpha_Q &= \frac{\sin\omega_0}{2Q} \\
          \alpha_{Q_{dB}} &= \frac{\sin\omega_0}{2 \cdot 10^{Q/20}} \\
          S &= 1 \\
          \alpha_S &= \frac{\sin\omega_0}{2}\sqrt{\left(A+\frac{1}{A}\right)\left(\frac{1}{S}-1\right)+2}
      \end{align*}
      $$
      

    每种滤波器类型的六个系数 (\(b_0, b_1, b_2, a_0, a_1, a_2\)) 为

    "lowpass"
    $$
        \begin{align*}
            b_0 &= \frac{1 - \cos\omega_0}{2} \\
            b_1 &= 1 - \cos\omega_0 \\
            b_2 &= \frac{1 - \cos\omega_0}{2} \\
            a_0 &= 1 + \alpha_{Q_{dB}} \\
            a_1 &= -2 \cos\omega_0 \\
            a_2 &= 1 - \alpha_{Q_{dB}}
        \end{align*}
    $$
    
    "highpass"
    $$
        \begin{align*}
            b_0 &= \frac{1 + \cos\omega_0}{2} \\
            b_1 &= -(1 + \cos\omega_0) \\
            b_2 &= \frac{1 + \cos\omega_0}{2} \\
            a_0 &= 1 + \alpha_{Q_{dB}} \\
            a_1 &= -2 \cos\omega_0 \\
            a_2 &= 1 - \alpha_{Q_{dB}}
        \end{align*}
    $$
    
    "bandpass"
    $$
        \begin{align*}
            b_0 &= \alpha_Q \\
            b_1 &= 0 \\
            b_2 &= -\alpha_Q \\
            a_0 &= 1 + \alpha_Q \\
            a_1 &= -2 \cos\omega_0 \\
            a_2 &= 1 - \alpha_Q
        \end{align*}
    $$
    
    "notch"
    $$
        \begin{align*}
            b_0 &= 1 \\
            b_1 &= -2\cos\omega_0 \\
            b_2 &= 1 \\
            a_0 &= 1 + \alpha_Q \\
            a_1 &= -2 \cos\omega_0 \\
            a_2 &= 1 - \alpha_Q
        \end{align*}
    $$
    
    "allpass"
    $$
        \begin{align*}
            b_0 &= 1 - \alpha_Q \\
            b_1 &= -2\cos\omega_0 \\
            b_2 &= 1 + \alpha_Q \\
            a_0 &= 1 + \alpha_Q \\
            a_1 &= -2 \cos\omega_0 \\
            a_2 &= 1 - \alpha_Q
        \end{align*}
    $$
    
    "peaking"
    $$
        \begin{align*}
            b_0 &= 1 + \alpha_Q\, A \\
            b_1 &= -2\cos\omega_0 \\
            b_2 &= 1 - \alpha_Q\,A \\
            a_0 &= 1 + \frac{\alpha_Q}{A} \\
            a_1 &= -2 \cos\omega_0 \\
            a_2 &= 1 - \frac{\alpha_Q}{A}
        \end{align*}
    $$
    
    "lowshelf"
    $$
        \begin{align*}
            b_0 &= A \left[ (A+1) - (A-1) \cos\omega_0 + 2 \alpha_S \sqrt{A})\right] \\
            b_1 &= 2 A \left[ (A-1) - (A+1) \cos\omega_0 )\right] \\
            b_2 &= A \left[ (A+1) - (A-1) \cos\omega_0 - 2 \alpha_S \sqrt{A}) \right] \\
            a_0 &= (A+1) + (A-1) \cos\omega_0 + 2 \alpha_S \sqrt{A} \\
            a_1 &= -2 \left[ (A-1) + (A+1) \cos\omega_0\right] \\
            a_2 &= (A+1) + (A-1) \cos\omega_0 - 2 \alpha_S \sqrt{A})
        \end{align*}
    $$
    
    "highshelf"
    $$
        \begin{align*}
            b_0 &= A\left[ (A+1) + (A-1)\cos\omega_0 + 2\alpha_S\sqrt{A} )\right] \\
            b_1 &= -2A\left[ (A-1) + (A+1)\cos\omega_0 )\right] \\
            b_2 &= A\left[ (A+1) + (A-1)\cos\omega_0 - 2\alpha_S\sqrt{A} )\right] \\
            a_0 &= (A+1) - (A-1)\cos\omega_0 + 2\alpha_S\sqrt{A} \\
            a_1 &= 2\left[ (A-1) - (A+1)\cos\omega_0\right] \\
            a_2 &= (A+1) - (A-1)\cos\omega_0 - 2\alpha_S\sqrt{A}
        \end{align*}
    $$
    

    1.14. ChannelMergerNode 接口

    ChannelMergerNode 用于更高级的应用程序,通常与 ChannelSplitterNode 结合使用。

    此接口表示一个用于将来自多个音频流的通道合并为单个音频流的 AudioNode。它具有可变数量的输入(默认为 6),但并非所有输入都需要连接。它有一个单一的输出,当任何输入处于 活动处理 状态时,其音频流具有与输入数量相等的通道数。如果没有任何输入处于 活动处理 状态,则输出为单个静音通道。

    要将多个输入合并为一个流,每个输入都会根据指定的混合规则向下混合为单个通道(单声道)。未连接的输入在输出中仍计为 一个静音通道。更改输入流 不会 影响输出通道的顺序。

    例如,如果默认的 ChannelMergerNode 有两个连接的立体声输入,第一个和第二个输入将在合并前分别向下混合为单声道。输出将是一个 6 通道流,其前两个通道由前两个(向下混合的)输入填充,其余通道将保持静音。此外,ChannelMergerNode 可用于为多通道扬声器阵列(例如 5.1 环绕声设置)按特定顺序排列多个音频流。合并器不解释通道标识(例如左、右等),而只是按它们输入的顺序合并通道。
    channel merger
    ChannelMerger 图示
    [Exposed=Window]
    interface ChannelMergerNode : AudioNode {
        constructor (BaseAudioContext context, optional ChannelMergerOptions options = {});
    };
    

    1.14.1. 构造函数

    ChannelMergerNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    ChannelMergerNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 ChannelMergerNode关联 到的 BaseAudioContext
    options ChannelMergerOptions ChannelMergerNode 的可选初始参数值。

    1.14.2. ChannelMergerOptions

    dictionary ChannelMergerOptions : AudioNodeOptions {
        unsigned long numberOfInputs = 6;
    };
    
    1.14.2.1. 字典 ChannelMergerOptions 成员
    numberOfInputs, 类型为 unsigned long, 默认值为 6

    ChannelMergerNode 的输入数量。有关此值的约束,请参阅 createChannelMerger()

    1.15. ChannelSplitterNode 接口

    ChannelSplitterNode 用于更高级的应用程序,通常与 ChannelMergerNode 结合使用。

    此接口表示一个用于访问路由图中音频流的各个通道的 AudioNode。它有一个单一的输入和若干“活动”输出,输出数量等于输入音频流中的通道数。例如,如果将立体声输入连接到 ChannelSplitterNode,则活动输出的数量将为两个(一个来自左声道,一个来自右声道)。总输出数量始终为 N(由 AudioContext 方法 createChannelSplitter()numberOfOutputs 参数决定),如果未提供该值,则默认数量为 6。任何非“活动”的输出都将输出静音,且通常不会连接到任何内容。

    channel splitter
    ChannelSplitter 图示

    请注意,在此示例中,分割器 解释通道标识(例如左、右等),而只是按它们输入的顺序分割通道。

    ChannelSplitterNode 的一个应用是进行“矩阵混合”,其中需要对每个通道进行单独的增益控制。

    [Exposed=Window]
    interface ChannelSplitterNode : AudioNode {
        constructor (BaseAudioContext context, optional ChannelSplitterOptions options = {});
    };
    

    1.15.1. 构造函数

    ChannelSplitterNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    ChannelSplitterNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 ChannelSplitterNode关联 到的 BaseAudioContext
    options ChannelSplitterOptions ChannelSplitterNode 的可选初始参数值。

    1.15.2. ChannelSplitterOptions
    dictionary ChannelSplitterOptions : AudioNodeOptions {
        unsigned long numberOfOutputs = 6;
    };
    

    1.15.2.1. 字典 ChannelSplitterOptions 成员
    numberOfOutputs, 类型为 unsigned long, 默认值为 6

    ChannelSplitterNode 的输出数量。有关此值的约束,请参阅 createChannelSplitter()

    1.16. ConstantSourceNode 接口

    此接口表示一个恒定音频源,其输出通常是一个恒定值。它通常作为一种通用的恒定源节点,并且可以通过自动控制其 offset 或将其他节点连接到它,像可构建的 AudioParam 一样使用。

    此节点的单个输出由一个通道(单声道)组成。

    [Exposed=Window]
    interface ConstantSourceNode : AudioScheduledSourceNode {
        constructor (BaseAudioContext context, optional ConstantSourceOptions options = {});
        readonly attribute AudioParam offset;
    };
    

    1.16.1. 构造函数
    ConstantSourceNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    ConstantSourceNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 ConstantSourceNode关联 到的 BaseAudioContext
    options ConstantSourceOptions ConstantSourceNode 的可选初始参数值。

    1.16.2. 属性
    offset, 类型为 AudioParam, 只读

    源的恒定值。

    1.16.3. ConstantSourceOptions

    这指定了用于构建 ConstantSourceNode 的选项。所有成员均为可选;如果未指定,则使用正常的默认值构建节点。

    dictionary ConstantSourceOptions {
        float offset = 1;
    };
    

    1.16.3.1. 字典 ConstantSourceOptions 成员
    offset, 类型为 float, 默认值为 1

    此节点的 offset AudioParam 的初始值。

    1.17. ConvolverNode 接口

    此接口表示一个应用给定脉冲响应进行线性卷积效果的处理节点。

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2 具有 channelCount 约束
    channelCountMode "clamped-max"具有 channelCountMode 约束
    channelInterpretation "speakers"
    tail-time 在输入为零时,继续输出非静音音频,时长为 buffer 的长度。

    此节点的输入是单声道(1 通道)或立体声(2 通道),不能增加。来自具有更多通道的节点的连接将被 适当向下混合

    该节点有 channelCount 约束channelCountMode 约束。这些约束确保该节点的输入是单声道或立体声。

    [Exposed=Window]
    interface ConvolverNode : AudioNode {
        constructor (BaseAudioContext context, optional ConvolverOptions options = {});
        attribute AudioBuffer? buffer;
        attribute boolean normalize;
    };
    

    1.17.1. 构造函数
    ConvolverNode(context, options)

    当使用 BaseAudioContext context 和选项对象 options 调用构造函数时,执行这些步骤。

    1. 将属性 normalize 设置为 disableNormalization 值的倒数。

    2. 如果 buffer 存在,将 buffer 属性设置为其值。

      注意: 这意味着缓冲区将根据 normalize 属性的值进行归一化。

    3. o 为新的 AudioNodeOptions 字典。

    4. 如果 options存在 channelCount,则将 o 上的 channelCount 设置为相同值。

    5. 如果 options存在 channelCountMode,则将 o 上的 channelCountMode 设置为相同值。

    6. 如果 options存在 channelInterpretation,则将 o 上的 channelInterpretation 设置为相同值。

    7. 初始化 AudioNode this,并以 co 作为参数。

    ConvolverNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 ConvolverNode关联 到的 BaseAudioContext
    options ConvolverOptions ConvolverNode 的可选初始参数值。

    1.17.2. 属性
    buffer, 类型为 AudioBuffer, 可为空

    设置此属性时,buffernormalize 属性的状态将用于配置 ConvolverNode,使该脉冲响应具有给定的归一化。此属性的初始值为 null。

    设置 buffer 属性 时,请 同步执行以下步骤
  • 如果缓冲区的 通道数 不是 1、2 或 4,或者缓冲区的 采样率 与其 关联BaseAudioContext采样率 不同,则必须抛出 NotSupportedError

  • 获取 AudioBuffer 的内容。

  • 注意: 如果 buffer 设置为新缓冲区,音频可能会出现故障。如果这是不可取的,建议创建一个新的 ConvolverNode 来替换旧的,可能需要两者之间进行交叉淡入淡出。

    注意: ConvolverNode 仅在存在单个输入通道和单通道 buffer 的特定情况下产生单声道输出。在所有其他情况下,输出均为立体声。特别是,当 buffer 有四个通道且有两个输入通道时,ConvolverNode 执行矩阵“真实”立体声卷积。有关规范信息,请参阅 通道配置图

    normalize, 类型为 boolean

    控制设置 buffer 属性时,是否通过等功率归一化对缓冲区中的脉冲响应进行缩放。其默认值为 true,以便在加载不同的脉冲响应时从卷积器获得更均匀的输出电平。如果 normalize 设置为 false,则卷积将渲染而不对脉冲响应进行任何预处理/缩放。对此值的更改在下次设置 buffer 属性之前不会生效。

    如果设置 buffer 属性时 normalize 属性为 false,则 ConvolverNode 将使用 buffer 中包含的确切脉冲响应执行线性卷积。

    否则,如果设置 buffer 属性时 normalize 属性为 true,则 ConvolverNode 将首先对 buffer 中包含的音频数据执行缩放的 RMS 功率分析,以根据此算法计算 normalizationScale

    function calculateNormalizationScale(buffer) {    const GainCalibration = 0.00125;    const GainCalibrationSampleRate = 44100;    const MinPower = 0.000125;    // Normalize by RMS power.    const numberOfChannels = buffer.numberOfChannels;    const length = buffer.length;    let power = 0;    for (let i = 0; i < numberOfChannels; i++) {        let channelPower = 0;        const channelData = buffer.getChannelData(i);        for (let j = 0; j < length; j++) {            const sample = channelData[j];            channelPower += sample * sample;        }        power += channelPower;    }    power = Math.sqrt(power / (numberOfChannels * length));    // Protect against accidental overload.    if (!isFinite(power) || isNaN(power) || power < MinPower)        power = MinPower;    let scale = 1 / power;    // Calibrate to make perceived volume same as unprocessed.    scale *= GainCalibration;    // Scale depends on sample-rate.    if (buffer.sampleRate)        scale *= GainCalibrationSampleRate / buffer.sampleRate;    // True-stereo compensation.    if (numberOfChannels == 4)        scale *= 0.5;    return scale;}

    在处理过程中,ConvolverNode 将获取此计算出的 normalizationScale 值,并将其与输入与脉冲响应(由 buffer 表示)处理后产生的线性卷积结果相乘,从而产生最终输出。或者可以使用任何数学上等效的操作,例如通过 normalizationScale 预乘输入,或通过 normalizationScale 预乘脉冲响应的某个版本。

    1.17.3. ConvolverOptions

    这指定了用于构建 ConvolverNode 的选项。所有成员均为可选;如果未指定,则节点使用正常的默认值构建。

    dictionary ConvolverOptions : AudioNodeOptions {
        AudioBuffer? buffer;
        boolean disableNormalization = false;
    };
    

    1.17.3.1. 字典 ConvolverOptions 成员
    buffer, 类型为 AudioBuffer, 可为空

    ConvolverNode 的期望缓冲区。此缓冲区将根据 disableNormalization 的值进行归一化。

    disableNormalization, 类型为 boolean, 默认值为 false

    ConvolverNodenormalize 属性期望初始值的相反值。

    1.17.4. 输入、脉冲响应和输出的通道配置

    实现必须支持 ConvolverNode 中允许的脉冲响应通道配置,以实现 1 或 2 个输入通道的各种混响效果。

    如下图所示,单通道卷积在单声道音频输入上运行,使用单声道脉冲响应并生成单声道输出。图中的其余图像说明了支持的单声道和立体声播放情况,其中输入通道数为 1 或 2,buffer 中的通道数为 1、2 或 4。希望进行更复杂和任意矩阵化的开发者可以使用 ChannelSplitterNode、多个单通道 ConvolverNode 和一个 ChannelMergerNode

    如果此节点未处于 活动处理 状态,则输出为单个静音通道。

    注意: 下面的图示显示了 活动处理 时的输出。

    reverb matrixing
    使用 ConvolverNode 时支持的输入和输出通道数可能性的图形表示。

    1.18. DelayNode 接口

    延迟线是音频应用程序中的基本构建块。此接口是一个具有单个输入和单个输出的 AudioNode

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2
    channelCountMode "max"
    channelInterpretation "speakers"
    tail-time 在输入为零时,继续输出非静音音频,时长可达节点的 maxDelayTime

    输出的通道数始终等于输入的通道数。

    它将输入的音频信号延迟一定量。具体来说,在每个时间 t,输入信号为 input(t),延迟时间为 delayTime(t),输出信号为 output(t),输出将为 output(t) = input(t - delayTime(t))。默认的 delayTime 为 0 秒(无延迟)。

    DelayNode 的输入通道数发生变化时(从而也改变了输出通道数),可能会有延迟的音频采样尚未被节点输出,并且是其内部状态的一部分。如果这些采样是在之前以不同的通道数接收的,则在与新接收的输入合并之前,必须对它们进行上混或下混,以便所有内部延迟线混合都使用单一主流的通道布局进行。

    注意: 根据定义,DelayNode 会引入等于延迟量的音频处理延迟。

    [Exposed=Window]
    interface DelayNode : AudioNode {
        constructor (BaseAudioContext context, optional DelayOptions options = {});
        readonly attribute AudioParam delayTime;
    };
    

    1.18.1. 构造函数
    DelayNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    DelayNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 DelayNode关联 到的 BaseAudioContext
    options DelayOptions DelayNode 的可选初始参数值。

    1.18.2. 属性
    delayTime, 类型为 AudioParam, 只读

    表示要应用的延迟量(以秒为单位)的 AudioParam 对象。其默认 value 为 0(无延迟)。最小值为 0,最大值由 maxDelayTime 参数在 AudioContext 方法 createDelay() 中确定,或由 maxDelayTime 成员在 DelayOptions 字典中为 constructor 确定。

    如果 DelayNode循环 的一部分,则 delayTime 属性的值被限制为至少一个 渲染量子

    1.18.3. DelayOptions

    这指定了用于构建 DelayNode 的选项。所有成员均为可选;如果未给出,则节点使用正常的默认值构建。

    dictionary DelayOptions : AudioNodeOptions {
        double maxDelayTime = 1;
        double delayTime = 0;
    };
    

    1.18.3.1. 字典 DelayOptions 成员
    delayTime, 类型为 double, 默认值为 0

    节点的初始延迟时间。

    maxDelayTime, 类型为 double, 默认值为 1

    节点的最大延迟时间。有关约束,请参阅 createDelay(maxDelayTime)

    1.18.4. 处理

    DelayNode 拥有一个内部缓冲区,用于保存 delayTime 秒的音频。

    DelayNode 的处理分为两部分:写入延迟线和从延迟线读取。这是通过两个内部 AudioNode 完成的(作者无法访问这些节点,它们仅用于简化对节点内部工作的描述)。两者都是从 DelayNode 创建的。

    DelayNode 创建 DelayWriter 意味着创建一个对象,该对象具有与 AudioNode 相同的接口,并将输入音频写入 DelayNode 的内部缓冲区。它与创建它的 DelayNode 具有相同的输入连接。

    DelayNode 创建 DelayReader 意味着创建一个对象,该对象具有与 AudioNode 相同的接口,并且可以从 DelayNode 的内部缓冲区读取音频数据。它连接到与创建它的 DelayNode 相同的 AudioNodeDelayReader 是一个 源节点

    处理输入缓冲区时,DelayWriter 必须将音频写入 DelayNode 的内部缓冲区。

    产生输出缓冲区时,DelayReader 必须完全产生 delayTime 秒前写入相应 DelayWriter 的音频。

    注意: 这意味着通道数的变化会在延迟时间过去后反映出来。

    1.19. DynamicsCompressorNode 接口

    DynamicsCompressorNode 是一个实现动态压缩效果的 AudioNode 处理器。

    动态压缩在音乐制作和游戏音频中非常常用。它降低了信号最响亮部分的音量,并提高了最柔和部分的音量。总体而言,可以实现更响亮、更丰富、更饱满的声音。这在同时播放大量单个声音的游戏和音乐应用程序中尤为重要,可以控制整体信号电平并有助于避免音频输出到扬声器时出现削波(失真)。

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2 具有 channelCount 约束
    channelCountMode "clamped-max"具有 channelCountMode 约束
    channelInterpretation "speakers"
    tail-time 此节点具有 尾部时间 (tail-time),使得该节点由于预读延迟,在输入为零时继续输出非静音音频。
    [Exposed=Window]
    interface DynamicsCompressorNode : AudioNode {
        constructor (BaseAudioContext context,
                     optional DynamicsCompressorOptions options = {});
        readonly attribute AudioParam threshold;
        readonly attribute AudioParam knee;
        readonly attribute AudioParam ratio;
        readonly attribute float reduction;
        readonly attribute AudioParam attack;
        readonly attribute AudioParam release;
    };
    

    1.19.1. 构造函数
    DynamicsCompressorNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须 初始化 AudioNode this,并以 contextoptions 作为参数。

    [[内部衰减]]this 上的一个私有插槽,用于保存以分贝为单位的浮点数。将 [[内部衰减]] 设置为 0.0。

    DynamicsCompressorNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 这个新的 DynamicsCompressorNode关联 到的 BaseAudioContext
    options DynamicsCompressorOptions DynamicsCompressorNode 的可选初始参数值。

    1.19.2. 属性
    attack, 类型为 AudioParam, 只读

    将增益降低 10dB 所需的时间量(以秒为单位)。

    knee, 类型为 AudioParam, 只读

    表示阈值以上、曲线平滑过渡到“比率”部分的范围的分贝值。

    ratio, 类型为 AudioParam, 只读

    输入中的 dB 变化量对应于输出中 1 dB 的变化。

    reduction, 类型为 float, 只读

    一个用于计量目的的只读分贝值,表示压缩器当前应用于信号的增益衰减量。如果没有输入信号,该值为 0(无增益衰减)。读取此属性时,返回私有插槽 [[内部衰减]] 的值。

    release, 类型为 AudioParam, 只读

    将增益增加 10dB 所需的时间量(以秒为单位)。

    threshold, 类型为 AudioParam, 只读

    超过该值时压缩将开始生效的分贝值。

    1.19.3. DynamicsCompressorOptions

    这指定了用于构建 DynamicsCompressorNode 的选项。所有成员均为可选;如果未指定,则节点使用正常的默认值构建。

    dictionary DynamicsCompressorOptions : AudioNodeOptions {
        float attack = 0.003;
        float knee = 30;
        float ratio = 12;
        float release = 0.25;
        float threshold = -24;
    };
    

    1.19.3.1. 字典 DynamicsCompressorOptions 成员
    attack, 类型为 float, 默认值为 0.003

    attack AudioParam 的初始值。

    knee, 类型为 float, 默认值为 30

    knee AudioParam 的初始值。

    ratio, 类型为 float, 默认值为 12

    ratio AudioParam 的初始值。

    release, 类型为 float,默认值为 0.25

    release AudioParam 的初始值。

    threshold, 类型为 float,默认值为 -24

    threshold AudioParam 的初始值。

    1.19.4. 处理

    动态压缩可以通过多种方式实现。DynamicsCompressorNode 实现了一个具有以下特性的动态处理器:

    • 固定前瞻(fixed look-ahead)(这意味着 DynamicsCompressorNode 会为信号链增加固定的延迟)。

    • 可配置的启动速度(attack speed)、释放速度(release speed)、阈值(threshold)、拐点硬度(knee hardness)和压缩比(ratio)。

    • 不支持侧链(Side-chaining)。

    • 增益衰减通过 DynamicsCompressorNode 上的 reduction 属性报告。

    • 压缩曲线包含三个部分:

      • 第一部分是恒等式:\(f(x) = x\)。

      • 第二部分是软拐点(soft-knee)部分,必须是单调递增函数。

      • 第三部分是线性函数:\(f(x) = \frac{1}{ratio} \cdot x \)。

      该曲线必须是连续且分段可导的,并根据输入电平对应一个目标输出电平。

    在图形上,这样的曲线看起来大致如下:

    Graphical representation of a compression curve
    典型的压缩曲线,显示了拐点部分(软或硬)以及阈值。

    在内部,DynamicsCompressorNode 通过结合其他 AudioNode 以及一种特殊算法来描述,以计算增益衰减值。

    内部使用以下 AudioNode 图,其中 inputoutput 分别是输入和输出 AudioNodecontext 是此 DynamicsCompressorNodeBaseAudioContext,以及一个名为 EnvelopeFollower 的新类,它实例化一个表现得像 AudioNode 的特殊对象,描述如下:

    const delay = new DelayNode(context, {delayTime: 0.006});
    const gain = new GainNode(context);
    const compression = new EnvelopeFollower();
    
    input.connect(delay).connect(gain).connect(output);
    input.connect(compression).connect(gain.gain);
    
    Schema of
    the internal graph used by the DynamicCompressorNode
    作为 DynamicsCompressorNode 处理算法一部分的内部 AudioNode 图。

    注:这实现了预延迟和衰减增益的应用。

    以下算法描述了 EnvelopeFollower 对象执行的处理,该处理应用于输入信号以产生增益衰减值。EnvelopeFollower 有两个插槽用于存放浮点值。这些值在算法调用期间保持不变。

    • [[detector average]] 为一个浮点数,初始化为 0.0。

    • [[compressor gain]] 为一个浮点数,初始化为 1.0。

    以下算法允许为渲染量子(render quantum)音频的每个输入样本确定 reduction gain(衰减增益)的值。
    1. attackrelease 分别为在处理时采样(这些是 k-rate 参数)的 attackrelease 的值,并乘以该 DynamicsCompressorNode关联BaseAudioContext 的采样率。

    2. detector average 为插槽 [[detector average]] 的值。

    3. compressor gain 为插槽 [[compressor gain]] 的值。

    4. 对于要处理的渲染量子的每个样本 input,执行以下步骤:

      1. 如果 input 的绝对值小于 0.0001,令 attenuation 为 1.0。否则,令 shaped input 为将 压缩曲线 应用于 input 的绝对值所得的值。令 attenuationshaped input 除以 input 的绝对值。

      2. releasingtrue(如果 attenuation 大于 compressor gain),否则为 false

      3. detector rate 为将 检测器曲线 应用于 attenuation 的结果。

      4. attenuation 中减去 detector average,并将结果乘以 detector rate。将此新结果加到 detector average 上。

      5. detector average 钳位(Clamp)至最大值 1.0。

      6. envelope rate 为基于 attackrelease计算包络速率 的结果。

      7. 如果 releasingtrue,将 compressor gain 设置为 compressor gainenvelope rate 的乘积,并钳位至最大值 1.0。

      8. 否则,如果 releasingfalse,令 gain incrementdetector average 减去 compressor gain。将 gain increment 乘以 envelope rate,并将结果加到 compressor gain 上。

      9. 计算 reduction gaincompressor gain 乘以 计算补偿增益 的返回值。

      10. 计算 metering gainreduction gain 转换为分贝 的结果。

    5. [[compressor gain]] 设置为 compressor gain

    6. [[detector average]] 设置为 detector average

    7. 原子地将内部插槽 [[internal reduction]] 设置为 metering gain 的值。

      注:此步骤使测量增益在每个块结束时更新一次。

    补偿增益(makeup gain)是一个固定的增益级,仅取决于压缩器的压缩比、拐点和阈值参数,而不取决于输入信号。其目的是增加压缩器的输出电平,使其与输入电平相当。

    计算补偿增益 意味着执行以下步骤:
    1. full range gain 为通过将 压缩曲线 应用于值 1.0 所返回的值。

    2. full range makeup gainfull range gain 的倒数。

    3. 返回 full range makeup gain 的 0.6 次幂的结果。

    计算包络速率 是通过将函数应用于 compressor gaindetector average 之比来完成的。用户代理可以自由选择包络函数的形状。但是,该函数必须遵守以下约束:
    • 包络速率必须根据 compressor gaindetector average 之比进行计算。

      注:当进行攻击(attacking)时,此数字小于或等于 1;当进行释放(releasing)时,此数字严格大于 1。

    • 攻击曲线必须是区间 \([0, 1]\) 上的连续单调递增函数。此曲线的形状可以由 attack 控制。

    • 释放曲线必须是始终大于 1 的连续单调递减函数。此曲线的形状可以由 release 控制。

    此操作返回通过将该函数应用于 compressor gaindetector average 之比所计算出的值。

    检测器曲线 应用于攻击或释放时的变化率,允许实现 自适应释放(adaptive release)。该函数必须遵守以下约束:

    • 函数的输出必须在 \([0,1]\) 范围内。

    • 函数必须是单调递增且连续的。

    注:例如,允许拥有一个执行 自适应释放 的压缩器,即压缩越强,释放越快;或者拥有形状不同的攻击和释放曲线。

    压缩曲线 应用于值意味着当该样本传递给函数时计算其值,并返回计算后的值。此函数必须遵守以下特性:
    1. thresholdknee 分别为 thresholdknee 的值,转换为线性单位 并在此块处理时采样(作为 k-rate 参数)。

    2. 计算 threshold 加上 knee 的总和,同样在此块处理时采样(作为 k-rate 参数)。

    3. knee end threshold 为此总和 转换为线性单位 的值。

    4. ratioratio 的值,在此块处理时采样(作为 k-rate 参数)。

    5. 该函数在达到线性 threshold 值之前是恒等式(即 \(f(x) = x\))。

    6. thresholdknee end threshold,用户代理可以选择曲线形状。整个函数必须是单调递增且连续的。

      注:如果 knee 为 0,则 DynamicsCompressorNode 被称为硬拐点(hard-knee)压缩器。

    7. 该函数在 threshold 和软拐点之后基于 ratio 呈线性(即 \(f(x) = \frac{1}{ratio} \cdot x \))。

    将值 \(v\) 从 线性增益单位转换为分贝 意味着执行以下步骤:
    1. 如果 \(v\) 等于 0,返回 -1000。

    2. 否则,返回 \( 20 \, \log_{10}{v} \)。

    将值 \(v\) 从 分贝转换为线性增益单位 意味着返回 \(10^{v/20}\)。

    1.20. GainNode 接口

    改变音频信号的增益是音频应用程序中的基本操作。此接口是一个具有单个输入和单个输出的 AudioNode

    GainNode 输入数据的每个通道的每个样本必须乘以 gain AudioParam计算值(computedValue)

    [Exposed=Window]
    interface GainNode : AudioNode {
        constructor (BaseAudioContext context, optional GainOptions options = {});
        readonly attribute AudioParam gain;
    };
    

    1.20.1. 构造函数

    GainNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须使用 contextoptions 作为参数 初始化 AudioNode this

    GainNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 GainNode 将与之 关联BaseAudioContext
    options GainOptions GainNode 的可选初始参数值。

    1.20.2. 属性

    gain, 类型为 AudioParam,只读

    表示要应用的增益量。

    1.20.3. GainOptions

    这指定了构建 GainNode 时使用的选项。所有成员都是可选的;如果未指定,则在构建节点时使用常规默认值。

    dictionary GainOptions : AudioNodeOptions {
        float gain = 1.0;
    };
    
    1.20.3.1. 字典 GainOptions 成员
    gain, 类型为 float,默认值为 1.0

    gain AudioParam 的初始增益值。

    1.21. IIRFilterNode 接口

    IIRFilterNode 是实现通用 IIR 滤波器AudioNode 处理器。通常,最好使用 BiquadFilterNode 来实现高阶滤波器,原因如下:

    • 通常对数值问题不太敏感。

    • 滤波器参数可以自动化。

    • 可用于创建所有偶数阶 IIR 滤波器。

    然而,无法创建奇数阶滤波器,因此如果需要此类滤波器,或者不需要自动化,则 IIR 滤波器可能是合适的。

    一旦创建,IIR 滤波器的系数就无法更改。

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2
    channelCountMode "max"
    channelInterpretation "speakers"
    tail-time 继续在无输入的情况下输出非静音音频。由于这是一个 IIR 滤波器,该滤波器会永远产生非零输入,但在实践中,这可以在某个有限时间后限制,此时输出已足够接近零。实际时间取决于滤波器系数。

    输出的通道数始终等于输入的通道数。

    [Exposed=Window]
    interface IIRFilterNode : AudioNode {
        constructor (BaseAudioContext context, IIRFilterOptions options);
        undefined getFrequencyResponse (Float32Array frequencyHz,
                                        Float32Array magResponse,
                                        Float32Array phaseResponse);
    };
    

    1.21.1. 构造函数

    IIRFilterNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须使用 contextoptions 作为参数 初始化 AudioNode this

    IIRFilterNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 IIRFilterNode 将与之 关联BaseAudioContext
    options IIRFilterOptions IIRFilterNode 的初始参数值。

    1.21.2. 方法

    getFrequencyResponse(frequencyHz, magResponse, phaseResponse)

    给定当前的滤波器参数设置,同步计算指定频率下的频率响应。这三个参数必须是长度相同的 Float32Array,否则必须抛出 InvalidAccessError

    IIRFilterNode.getFrequencyResponse() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    frequencyHz Float32Array 此参数指定一个频率数组(以 Hz 为单位),响应值将在这些频率下计算。
    magResponse Float32Array 此参数指定用于接收线性幅值响应值的输出数组。如果 frequencyHz 参数中的值不在 [0, sampleRate/2] 范围内(其中 sampleRateAudioContextsampleRate 属性的值),则 magResponse 数组中相应索引处的值必须为 NaN
    phaseResponse Float32Array 此参数指定用于接收以弧度为单位的相位响应值的输出数组。如果 frequencyHz 参数中的值不在 [0; sampleRate/2] 范围内(其中 sampleRateAudioContextsampleRate 属性的值),则 phaseResponse 数组中相应索引处的值必须为 NaN
    返回类型: undefined

    1.21.3. IIRFilterOptions

    IIRFilterOptions 字典用于指定 IIRFilterNode 的滤波器系数。

    dictionary IIRFilterOptions : AudioNodeOptions {
        required sequence<double> feedforward;
        required sequence<double> feedback;
    };
    
    1.21.3.1. 字典 IIRFilterOptions 成员
    feedforward, 类型为 sequence<double>

    IIRFilterNode 的前馈(feedforward)系数。此成员是必需的。有关其他约束,请参见 createIIRFilter()feedforward 参数。

    feedback, 类型为 sequence<double>

    IIRFilterNode 的反馈(feedback)系数。此成员是必需的。有关其他约束,请参见 createIIRFilter()feedback 参数。

    1.21.4. 滤波器定义

    令 \(b_m\) 为 feedforward 系数,\(a_n\) 为由 createIIRFilter()constructorIIRFilterOptions 字典指定的 feedback 系数。则通用 IIR 滤波器的传递函数由下式给出:

    $$
        H(z) = \frac{\sum_{m=0}^{M} b_m z^{-m}}{\sum_{n=0}^{N} a_n z^{-n}}
    $$
    

    其中 \(M + 1\) 是 \(b\) 数组的长度,\(N + 1\) 是 \(a\) 数组的长度。系数 \(a_0\) 不能为 0(参见 createIIRFilter()feedback parameter)。至少有一个 \(b_m\) 必须非零(参见 createIIRFilter()feedforward parameter)。

    等效地,时域方程为:

    $$
        \sum_{k=0}^{N} a_k y(n-k) = \sum_{k=0}^{M} b_k x(n-k)
    $$
    

    初始滤波器状态为全零状态。

    注意: 用户代理 (UA) 可能会产生警告,通知用户滤波器状态中出现了 NaN 值。这通常表明滤波器不稳定。

    1.22. MediaElementAudioSourceNode 接口

    此接口表示来自 audiovideo 元素的音频源。

    输出的通道数对应于 HTMLMediaElement 所引用的媒体的通道数。因此,媒体元素的 src 属性的更改可能会改变此节点输出的通道数。

    如果 HTMLMediaElement 的采样率与相关联的 AudioContext 的采样率不同,则来自 HTMLMediaElement 的输出必须重新采样以匹配上下文的 采样率(sample rate)

    MediaElementAudioSourceNode 是在给定 HTMLMediaElement 的情况下,使用 AudioContextcreateMediaElementSource() 方法或 mediaElementMediaElementAudioSourceOptions 字典(用于 constructor)创建的。

    单个输出的通道数等于作为参数传递给 createMediaElementSource()HTMLMediaElement 所引用的音频通道数;如果 HTMLMediaElement 没有音频,则为 1。

    HTMLMediaElement 在创建 MediaElementAudioSourceNode 后必须以相同的方式表现,除了 渲染的音频将不再直接听到,而是作为 MediaElementAudioSourceNode 通过路由图连接的结果而被听到。因此,如果没有MediaElementAudioSourceNode 一起使用,暂停、定位(seeking)、音量、src 属性更改以及 HTMLMediaElement 的其他方面都必须表现得像通常一样。

    const mediaElement = document.getElementById('mediaElementID');
    const sourceNode = context.createMediaElementSource(mediaElement);
    sourceNode.connect(filterNode);
    
    [Exposed=Window]
    interface MediaElementAudioSourceNode : AudioNode {
        constructor (AudioContext context, MediaElementAudioSourceOptions options);
        [SameObject] readonly attribute HTMLMediaElement mediaElement;
    };
    

    1.22.1. 构造函数

    MediaElementAudioSourceNode(context, options)
    1. 使用 contextoptions 作为参数 初始化 AudioNode this

    MediaElementAudioSourceNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context AudioContext 此新 MediaElementAudioSourceNode 将与之 关联AudioContext
    options MediaElementAudioSourceOptions MediaElementAudioSourceNode 的初始参数值。

    1.22.2. 属性

    mediaElement, 类型为 HTMLMediaElement,只读

    构建此 MediaElementAudioSourceNode 时使用的 HTMLMediaElement

    1.22.3. MediaElementAudioSourceOptions

    这指定了构建 MediaElementAudioSourceNode 时使用的选项。

    dictionary MediaElementAudioSourceOptions {
        required HTMLMediaElement mediaElement;
    };
    
    1.22.3.1. 字典 MediaElementAudioSourceOptions 成员
    mediaElement, 类型为 HTMLMediaElement

    将被重新路由的媒体元素。此项必须指定。

    1.22.4. MediaElementAudioSourceNode 和跨源资源的安全性

    HTMLMediaElement 允许播放跨源资源。由于 Web Audio 允许检查资源的内容(例如,使用 MediaElementAudioSourceNode 以及 AudioWorkletNodeScriptProcessorNode 读取样本),如果来自一个 源(origin) 的脚本检查来自另一个 的资源内容,则可能会发生信息泄露。

    为了防止这种情况,如果 MediaElementAudioSourceNode 使用的 HTMLMediaElement 在执行 获取算法(fetch algorithm) [FETCH] 时将资源标记为 CORS-cross-origin,则它必须输出 静音(silence),而不是 HTMLMediaElement 的正常输出。

    1.23. MediaStreamAudioDestinationNode 接口

    此接口是一个音频目的地,表示一个具有单个 MediaStreamTrack(其 kind"audio")的 MediaStream。此 MediaStream 在节点创建时创建,并通过 stream 属性访问。此流的使用方式类似于通过 getUserMedia() 获得的 MediaStream,并且例如可以使用 [webrtc] 中描述的 RTCPeerConnectionaddStream() 方法发送到远程对等方。

    输入端的默认通道数为 2(立体声)。

    [Exposed=Window]
    interface MediaStreamAudioDestinationNode : AudioNode {
        constructor (AudioContext context, optional AudioNodeOptions options = {});
        readonly attribute MediaStream stream;
    };
    

    1.23.1. 构造函数

    MediaStreamAudioDestinationNode(context, options)
    1. 使用 contextoptions 作为参数 初始化 AudioNode this

    MediaStreamAudioDestinationNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context AudioContext 此新 MediaStreamAudioDestinationNode 将与之 关联BaseAudioContext
    options AudioNodeOptions MediaStreamAudioDestinationNode 的可选初始参数值。

    1.23.2. 属性

    stream, 类型为 MediaStream,只读

    一个 MediaStream,包含一个具有与节点本身相同通道数的单个 MediaStreamTrack,其 kind 属性值为 "audio"

    1.24. MediaStreamAudioSourceNode 接口

    此接口表示来自 MediaStream 的音频源。

    输出的通道数对应于 MediaStreamTrack 的通道数。当 MediaStreamTrack 结束时,此 AudioNode 输出一个通道的静音。

    如果 MediaStreamTrack 的采样率与相关联的 AudioContext 的采样率不同,则 MediaStreamTrack 的输出将被重新采样以匹配上下文的 采样率(sample rate)

    [Exposed=Window]
    interface MediaStreamAudioSourceNode : AudioNode {
        constructor (AudioContext context, MediaStreamAudioSourceOptions options);
        [SameObject] readonly attribute MediaStream mediaStream;
    };
    

    1.24.1. 构造函数

    MediaStreamAudioSourceNode(context, options)
    1. 如果 optionsmediaStream 成员未引用一个至少包含一个 kind 属性值为 "audio"MediaStreamTrackMediaStream,则抛出 InvalidStateError 并中止这些步骤。否则,令此流为 inputStream

    2. tracksinputStream 中所有 kind"audio"MediaStreamTrack 列表。

    3. 根据 tracks 元素的 id 属性,使用 代码单元(code unit) 值序列的排序对它们进行排序。

    4. 使用 contextoptions 作为参数 初始化 AudioNode this

    5. 在此 MediaStreamAudioSourceNode 上设置一个内部插槽 [[input track]],使其成为 tracks 的第一个元素。这是用作此 MediaStreamAudioSourceNode 输入音频的轨道。

    构造后,对传递给构造函数的 MediaStream 的任何更改都不会影响此 AudioNode 的底层输出。

    插槽 [[input track]] 仅用于保留对 MediaStreamTrack 的引用。

    注:这意味着当从传递到此构造函数的 MediaStream 中移除由 MediaStreamAudioSourceNode 构造函数选择的轨道时,MediaStreamAudioSourceNode 仍将从同一轨道获取输入。

    注:由于传统原因,选择输出轨道的行为是任意的。可以使用 MediaStreamTrackAudioSourceNode 来明确指定使用哪个轨道作为输入。

    MediaStreamAudioSourceNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context AudioContext 此新 MediaStreamAudioSourceNode 将与之 关联AudioContext
    options MediaStreamAudioSourceOptions MediaStreamAudioSourceNode 的初始参数值。

    1.24.2. 属性

    mediaStream, 类型为 MediaStream,只读

    构建此 MediaStreamAudioSourceNode 时使用的 MediaStream

    1.24.3. MediaStreamAudioSourceOptions

    这指定了构建 MediaStreamAudioSourceNode 时使用的选项。

    dictionary MediaStreamAudioSourceOptions {
        required MediaStream mediaStream;
    };
    
    1.24.3.1. 字典 MediaStreamAudioSourceOptions 成员
    mediaStream, 类型为 MediaStream

    将充当源的媒体流。此项必须指定。

    1.25. MediaStreamTrackAudioSourceNode 接口

    此接口表示来自 MediaStreamTrack 的音频源。

    输出的通道数对应于 mediaStreamTrack 的通道数。

    如果 MediaStreamTrack 的采样率与相关联的 AudioContext 的采样率不同,则 mediaStreamTrack 的输出将被重新采样以匹配上下文的 采样率(sample rate)

    [Exposed=Window]
    interface MediaStreamTrackAudioSourceNode : AudioNode {
        constructor (AudioContext context, MediaStreamTrackAudioSourceOptions options);
    };
    

    1.25.1. 构造函数

    MediaStreamTrackAudioSourceNode(context, options)
    1. 如果 mediaStreamTrackkind 属性不是 "audio",则抛出 InvalidStateError 并中止这些步骤。

    2. 使用 contextoptions 作为参数 初始化 AudioNode this

    MediaStreamTrackAudioSourceNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context AudioContext 此新 MediaStreamTrackAudioSourceNode 将与之 关联AudioContext
    options MediaStreamTrackAudioSourceOptions MediaStreamTrackAudioSourceNode 的初始参数值。

    1.25.2. MediaStreamTrackAudioSourceOptions

    这指定了构建 MediaStreamTrackAudioSourceNode 时使用的选项。此项是必需的。

    dictionary MediaStreamTrackAudioSourceOptions {
        required MediaStreamTrack mediaStreamTrack;
    };
    
    1.25.2.1. 字典 MediaStreamTrackAudioSourceOptions 成员
    mediaStreamTrack, 类型为 MediaStreamTrack

    将充当源的媒体流轨道。 如果此 MediaStreamTrackkind 属性不是 "audio",则必须抛出 InvalidStateError

    1.26. OscillatorNode 接口

    OscillatorNode 表示生成周期性波形的音频源。它可以设置为几种常用的波形。此外,通过使用 PeriodicWave 对象,它可以被设置为任意周期性波形。

    振荡器是音频合成中常见的基础构建模块。OscillatorNode 将在 start() 方法指定的时间开始发声。

    从数学上讲,当在频域考虑时,连续时间周期波形可以包含非常高(或无限高)的频率信息。当该波形以特定采样率作为离散时间数字音频信号进行采样时,必须注意在将波形转换为数字形式之前丢弃(滤除)高于 奈奎斯特频率(Nyquist frequency) 的高频信息。如果不这样做,则高于 奈奎斯特频率 的更高频率的 混叠(aliasing) 将作为镜像折叠回低于 奈奎斯特频率 的频率。在许多情况下,这将导致听觉上令人反感的伪影。这是音频 DSP 的一个基本且众所周知的原理。

    实现可以通过几种实际方法来避免这种混叠。无论采用哪种方法,理想的离散时间数字音频信号在数学上都是定义明确的。实现的权衡是实现成本(就 CPU 使用率而言)与实现这种理想的保真度之间的问题。

    预期实现将对实现这种理想给予一定的关注,但在较低端的硬件上考虑质量较低、成本较低的方法是合理的。

    frequencydetune 都是 a-rate 参数,并形成一个 复合参数(compound parameter)。它们一起使用以确定 computedOscFrequency 值。

    computedOscFrequency(t) = frequency(t) * pow(2, detune(t) / 1200)
    

    OscillatorNode 在每个时间的瞬时相位是 computedOscFrequency 的定积分,假设在节点的精确开始时间相位角为零。其 标称范围 为 [-奈奎斯特频率, 奈奎斯特频率]。

    此节点的单个输出由一个通道(单声道)组成。

    enum OscillatorType {
        "sine",
        "square",
        "sawtooth",
        "triangle",
        "custom"
    };
    
    OscillatorType 枚举描述
    枚举值描述
    "sine"正弦波
    "square"占空比为 0.5 的方波
    "sawtooth"锯齿波
    "triangle"三角波
    "custom"自定义周期波
    [Exposed=Window]
    interface OscillatorNode : AudioScheduledSourceNode {
        constructor (BaseAudioContext context, optional OscillatorOptions options = {});
        attribute OscillatorType type;
        readonly attribute AudioParam frequency;
        readonly attribute AudioParam detune;
        undefined setPeriodicWave (PeriodicWave periodicWave);
    };
    

    1.26.1. 构造函数

    OscillatorNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须使用 contextoptions 作为参数 初始化 AudioNode this

    OscillatorNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 OscillatorNode 将与之 关联BaseAudioContext
    options OscillatorOptions OscillatorNode 的可选初始参数值。

    1.26.2. 属性

    detune, 类型为 AudioParam,只读

    一种失谐值(以 音分(cents) 为单位),它将通过给定金额抵消 frequency。其默认 value 为 0。此参数是 a-rate 的。它与 frequency 形成一个 复合参数,以形成 computedOscFrequency。下面列出的标称范围允许此参数在整个可能的频率范围内对 frequency 进行失谐。

    参数
    defaultValue 0
    minValue \(\approx -153600\)
    maxValue \(\approx 153600\)该值约为 \(1200\ \log_2 \mathrm{FLT\_MAX}\),其中 FLT_MAX 是最大的 float 值。
    automationRate "a-rate"
    frequency, 类型为 AudioParam,只读

    周期波形的频率(以赫兹为单位)。其默认 value 为 440。此参数是 a-rate 的。它与 detune 形成一个 复合参数,以形成 computedOscFrequency。其 标称范围 为 [-奈奎斯特频率, 奈奎斯特频率]。

    type, 类型为 OscillatorType

    周期波形的形状。它可以直接设置为除 "custom" 之外的任何类型常量值。这样做必须抛出 InvalidStateError 异常。 setPeriodicWave() 方法可用于设置自定义波形,这将导致此属性设置为 "custom"。默认值为 "sine"。设置此属性时,振荡器的相位必须保持不变。

    1.26.3. 方法

    setPeriodicWave(periodicWave)

    根据给定的 PeriodicWave 设置任意的自定义周期波形。

    OscillatorNode.setPeriodicWave() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    periodicWave PeriodicWave 振荡器将使用的自定义波形
    返回类型: undefined

    1.26.4. OscillatorOptions

    这指定了在构建 OscillatorNode 时使用的选项。所有成员都是可选的;如果未指定,则使用常规默认值来构建振荡器。

    dictionary OscillatorOptions : AudioNodeOptions {
        OscillatorType type = "sine";
        float frequency = 440;
        float detune = 0;
        PeriodicWave periodicWave;
    };
    
    1.26.4.1. 字典 OscillatorOptions 成员
    detune, 类型为 float,默认值为 0

    OscillatorNode 的初始失谐值。

    frequency, 类型为 float,默认值为 440

    OscillatorNode 的初始频率。

    periodicWave, 类型为 PeriodicWave

    OscillatorNodePeriodicWave。如果指定了此项,则 type 的任何有效值都将被忽略;它将被视为指定了 "custom"。

    type, 类型为 OscillatorType,默认值为 "sine"

    要构建的振荡器类型。如果将其设置为 "custom" 而未同时指定 periodicWave,则 必须抛出 InvalidStateError 异常。如果指定了 periodicWave,则 type 的任何有效值都将被忽略;它将被视为已设置为 "custom"。

    1.26.5. 基本波形相位

    各种振荡器类型的理想数学波形定义如下。总之,所有波形在数学上定义为在时间 0 时具有正斜率的奇函数。振荡器产生的实际波形可能不同,以防止混叠影响。

    振荡器产生的效果必须与使用具有适当 傅里叶级数disableNormalization 设置为 false 的 PeriodicWave 来创建这些基本波形的结果相同。

    "sine"

    正弦振荡器的波形为:

    $$
        x(t) = \sin t
    $$
    
    "square"

    方波振荡器的波形为:

    $$
        x(t) = \begin{cases}
                     1 & \mbox{for } 0≤ t < \pi \\
                     -1 & \mbox{for } -\pi < t < 0.
                     \end{cases}
    $$
    

    通过利用波形是周期为 \(2\pi\) 的奇函数这一事实,将其扩展到所有 \(t\)。

    "sawtooth"

    锯齿波振荡器的波形是斜坡:

    $$
        x(t) = \frac{t}{\pi} \mbox{ for } -\pi < t ≤ \pi;
    $$
    

    通过利用波形是周期为 \(2\pi\) 的奇函数这一事实,将其扩展到所有 \(t\)。

    "triangle"

    三角波振荡器的波形为:

    $$
        x(t) = \begin{cases}
                         \frac{2}{\pi} t & \mbox{for } 0 ≤ t ≤ \frac{\pi}{2} \\
                         1-\frac{2}{\pi} \left(t-\frac{\pi}{2}\right) & \mbox{for }
                         \frac{\pi}{2} < t ≤ \pi.
                     \end{cases}
    $$
    

    通过利用波形是周期为 \(2\pi\) 的奇函数这一事实,将其扩展到所有 \(t\)。

    1.27. PannerNode 接口

    此接口表示一个处理节点,它在三维空间中 定位/空间化 传入的音频流。空间化是相对于 BaseAudioContextAudioListenerlistener 属性)而言的。

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2 具有 channelCount 约束
    channelCountMode "clamped-max"具有 channelCountMode 约束
    channelInterpretation "speakers"
    tail-time 也许如果 panningModel 设置为 "HRTF",由于头部响应的固有处理,该节点将为静音输入产生非静音输出。否则,尾部时间为零。

    此节点的输入为单声道(1 通道)或立体声(2 通道),且无法增加。来自通道数较少或较多节点的连接将进行 适当的上混或下混

    如果节点正在 主动处理,则此节点的输出硬编码为立体声(2 通道),且无法配置。如果节点没有 主动处理,则输出为单个通道的静音。

    PanningModelType 枚举决定将使用哪种空间化算法来在 3D 空间中定位音频。默认值为 "equalpower"。

    enum PanningModelType {
            "equalpower",
            "HRTF"
    };
    
    PanningModelType 枚举描述
    枚举值描述
    "equalpower"一种使用等功率平移(equal-power panning)的简单且高效的空间化算法。注:使用此平移模型时,用于计算此节点输出的所有 AudioParam 均为 a-rate 的。
    "HRTF"一种更高质量的空间化算法,使用与人类受试者测得的脉冲响应进行卷积。此平移方法渲染立体声输出。注:使用此平移模型时,用于计算此节点输出的所有 AudioParam 均为 k-rate 的。

    PannerNodeAudioParam有效自动化速率(effective automation rate)由该 AudioParampanningModelautomationRate 决定。如果 panningModel 为“HRTF”,则有效自动化速率为“k-rate”,与 automationRate 的设置无关。否则,有效自动化速率即为 automationRate 的值。

    DistanceModelType 枚举决定了当音频源远离听者时,用于降低其音量的算法。默认值为“inverse”。

    在下面对每个距离模型的描述中,令 \(d\) 为听者与声源之间的距离;\(d_{ref}\) 为 refDistance 属性的值;\(d_{max}\) 为 maxDistance 属性的值;以及 \(f\) 为 rolloffFactor 属性的值。

    enum DistanceModelType {
        "linear",
        "inverse",
        "exponential"
    };
    
    DistanceModelType 枚举描述
    枚举值描述
    "linear"线性距离模型,根据以下公式计算 distanceGain
    $$
        1 - f\ \frac{\max\left[\min\left(d, d’_{max}\right), d’_{ref}\right] - d’_{ref}}{d’_{max} - d’_{ref}}
    $$
    

    其中 \(d’_{ref} = \min\left(d_{ref}, d_{max}\right)\) 且 \(d’_{max} = \max\left(d_{ref}, d_{max}\right)\)。在 \(d’_{ref} = d’_{max}\) 的情况下,线性模型的值取为 \(1-f\)。

    注意 \(d\) 被限制在区间 \(\left[d’_{ref},\, d’_{max}\right]\) 内。

    "inverse"反向距离模型,根据以下公式计算 distanceGain
    $$
        \frac{d_{ref}}{d_{ref} + f\ \left[\max\left(d, d_{ref}\right) - d_{ref}\right]}
    $$
    

    即 \(d\) 被限制在区间 \(\left[d_{ref},\, \infty\right)\) 内。如果 \(d_{ref} = 0\),则反向模型的值取为 0,与 \(d\) 和 \(f\) 的值无关。

    "exponential"指数距离模型,根据以下公式计算 distanceGain
    $$
        \left[\frac{\max\left(d, d_{ref}\right)}{d_{ref}}\right]^{-f}
    $$
    

    即 \(d\) 被限制在区间 \(\left[d_{ref},\, \infty\right)\) 内。如果 \(d_{ref} = 0\),则指数模型的值取为 0,与 \(d\) 和 \(f\) 无关。

    [Exposed=Window]
    interface PannerNode : AudioNode {
        constructor (BaseAudioContext context, optional PannerOptions options = {});
        attribute PanningModelType panningModel;
        readonly attribute AudioParam positionX;
        readonly attribute AudioParam positionY;
        readonly attribute AudioParam positionZ;
        readonly attribute AudioParam orientationX;
        readonly attribute AudioParam orientationY;
        readonly attribute AudioParam orientationZ;
        attribute DistanceModelType distanceModel;
        attribute double refDistance;
        attribute double maxDistance;
        attribute double rolloffFactor;
        attribute double coneInnerAngle;
        attribute double coneOuterAngle;
        attribute double coneOuterGain;
        undefined setPosition (float x, float y, float z);
        undefined setOrientation (float x, float y, float z);
    };
    

    1.27.1. 构造函数

    PannerNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须初始化 AudioNode this,并以 contextoptions 作为参数。

    PannerNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 PannerNode 将与之关联BaseAudioContext
    options PannerOptions PannerNode 的可选初始参数值。

    1.27.2. 属性

    coneInnerAngle, 类型为 double

    定向音频源的参数,为一个角度(单位:度),在此角度内音量不会降低。默认值为 360。如果角度在区间 [0, 360] 之外,则行为未定义。

    coneOuterAngle, 类型为 double

    定向音频源的参数,为一个角度(单位:度),在此角度外音量将降低至 coneOuterGain 的恒定值。默认值为 360。如果角度在区间 [0, 360] 之外,则行为未定义。

    coneOuterGain, 类型为 double

    定向音频源的参数,表示 coneOuterAngle 之外的增益。默认值为 0。这是一个范围在 [0, 1] 内的线性值(非 dB)。如果参数在此范围之外,必须抛出 InvalidStateError

    distanceModel, 类型为 DistanceModelType

    指定此 PannerNode 使用的距离模型。默认为“inverse”。

    maxDistance, 类型为 double

    声源与听者之间的最大距离,超过该距离后音量将不再降低。默认值为 10000。如果将其设置为非正值,必须抛出 RangeError 异常。

    orientationX, 类型为 AudioParam,只读

    描述 3D 笛卡尔坐标空间中音频源指向的向量的 \(x\) 分量。

    orientationY, 类型为 AudioParam,只读

    描述 3D 笛卡尔坐标空间中音频源指向的向量的 \(y\) 分量。

    orientationZ, 类型为 AudioParam,只读

    描述 3D 笛卡尔坐标空间中音频源指向的向量的 \(z\) 分量。

    panningModel, 类型为 PanningModelType

    指定此 PannerNode 使用的平移模型。默认为“equalpower”。

    positionX, 类型为 AudioParam,只读

    设置 3D 笛卡尔系统中音频源的 \(x\) 坐标位置。

    positionY, 类型为 AudioParam,只读

    设置 3D 笛卡尔系统中音频源的 \(y\) 坐标位置。

    positionZ, 类型为 AudioParam,只读

    设置 3D 笛卡尔系统中音频源的 \(z\) 坐标位置。

    refDistance, 类型为 double

    用于当声源远离听者时降低音量的参考距离。对于小于此值的距离,音量不会降低。默认值为 1。如果设置为负值,必须抛出 RangeError 异常。

    rolloffFactor, 类型为 double

    描述当声源远离听者时音量降低的快慢。默认值为 1。如果设置为负值,必须抛出 RangeError 异常。

    rolloffFactor 的标称范围指定了 rolloffFactor 可取的最小值和最大值。超出范围的值会被限制在此范围内。标称范围取决于 distanceModel,具体如下

    "linear"

    标称范围为 \([0, 1]\)。

    "inverse"

    标称范围为 \([0, \infty)\)。

    "exponential"

    标称范围为 \([0, \infty)\)。

    注意,限制操作作为距离计算处理的一部分发生。属性本身反映了设置的值,且不会被修改。

    1.27.3. 方法

    setOrientation(x, y, z)

    此方法已弃用。它等同于直接设置 orientationX.valueorientationY.valueorientationZ.value 属性,并分别传入 xyz 参数。

    因此,如果在调用此方法时,orientationXorientationYorientationZ AudioParam 中的任何一个通过 setValueCurveAtTime() 设置了自动化曲线,则必须抛出 NotSupportedError

    描述 3D 笛卡尔坐标空间中音频源指向的方向。根据声音的定向性(由 cone 属性控制),背离听者的声音可能会变得非常小或完全静音。

    x, y, z 参数表示 3D 空间中的方向向量。

    默认值为 (1,0,0)。

    PannerNode.setOrientation() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    x float
    y float
    z float
    返回类型: undefined
    setPosition(x, y, z)

    此方法已弃用。它等同于直接设置 positionX.valuepositionY.valuepositionZ.value 属性,并分别传入 xyz 参数。

    因此,如果在调用此方法时,positionXpositionYpositionZ AudioParam 中的任何一个通过 setValueCurveAtTime() 设置了自动化曲线,则必须抛出 NotSupportedError

    设置音频源相对于 listener 属性的位置。使用 3D 笛卡尔坐标系。

    x, y, z 参数表示 3D 空间中的坐标。

    默认值为 (0,0,0)。

    PannerNode.setPosition() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    x float
    y float
    z float
    返回类型: undefined

    1.27.4. PannerOptions

    这指定了构建 PannerNode 的选项。所有成员均为可选;如果未指定,则使用构建该节点的正常默认值。

    dictionary PannerOptions : AudioNodeOptions {
        PanningModelType panningModel = "equalpower";
        DistanceModelType distanceModel = "inverse";
        float positionX = 0;
        float positionY = 0;
        float positionZ = 0;
        float orientationX = 1;
        float orientationY = 0;
        float orientationZ = 0;
        double refDistance = 1;
        double maxDistance = 10000;
        double rolloffFactor = 1;
        double coneInnerAngle = 360;
        double coneOuterAngle = 360;
        double coneOuterGain = 0;
    };
    

    1.27.4.1. 字典 PannerOptions 成员
    coneInnerAngle, 类型为 double,默认为 360

    该节点的 coneInnerAngle 属性的初始值。

    coneOuterAngle, 类型为 double,默认为 360

    该节点的 coneOuterAngle 属性的初始值。

    coneOuterGain, 类型为 double,默认为 0

    该节点的 coneOuterGain 属性的初始值。

    distanceModel, 类型为 DistanceModelType,默认为 "inverse"

    用于该节点的距离模型。

    maxDistance, 类型为 double,默认为 10000

    该节点的 maxDistance 属性的初始值。

    orientationX, 类型为 float,默认为 1

    orientationX AudioParam 的初始 \(x\) 分量值。

    orientationY, 类型为 float,默认为 0

    orientationY AudioParam 的初始 \(y\) 分量值。

    orientationZ, 类型为 float,默认为 0

    orientationZ AudioParam 的初始 \(z\) 分量值。

    panningModel, 类型为 PanningModelType,默认为 "equalpower"

    用于该节点的平移模型。

    positionX, 类型为 float,默认为 0

    positionX AudioParam 的初始 \(x\) 坐标值。

    positionY, 类型为 float,默认为 0

    positionY AudioParam 的初始 \(y\) 坐标值。

    positionZ, 类型为 float,默认为 0

    positionZ AudioParam 的初始 \(z\) 坐标值。

    refDistance, 类型为 double,默认为 1

    该节点的 refDistance 属性的初始值。

    rolloffFactor, 类型为 double,默认为 1

    该节点的 rolloffFactor 属性的初始值。

    1.27.5. 声道限制

    StereoPannerNode声道限制集同样适用于 PannerNode

    1.28. PeriodicWave 接口

    PeriodicWave 表示用于 OscillatorNode 的任意周期波形。

    符合要求的实现必须支持至少 8192 个元素的 PeriodicWave

    [Exposed=Window]
    interface PeriodicWave {
        constructor (BaseAudioContext context, optional PeriodicWaveOptions options = {});
    };
    

    1.28.1. 构造函数
    PeriodicWave(context, options)
    1. p 为新的 PeriodicWave 对象。令 [[real]][[imag]] 为两个类型为 Float32Array 的内部槽位,并令 [[normalize]] 为一个内部槽位。

    2. 根据以下情况之一处理 options

      1. 如果同时提供了 options.realoptions.imag

        1. 如果 options.realoptions.imag 的长度不同,或者任何一个长度小于 2,则抛出 IndexSizeError 并终止此算法。

        2. [[real]][[imag]] 设置为与 options.real 长度相同的新数组。

        3. options.real 中的所有元素复制到 [[real]],并将 options.imag 复制到 [[imag]]

      2. 如果仅提供了 options.real

        1. 如果 options.real 的长度小于 2,则抛出 IndexSizeError 并终止此算法。

        2. [[real]][[imag]] 设置为与 options.real 长度相同的数组。

        3. options.real 复制到 [[real]],并将 [[imag]] 设置为全零数组。

      3. 如果仅提供了 options.imag

        1. 如果 options.imag 的长度小于 2,则抛出 IndexSizeError 并终止此算法。

        2. [[real]][[imag]] 设置为与 options.imag 长度相同的数组。

        3. options.imag 复制到 [[imag]],并将 [[real]] 设置为全零数组。

      4. 否则

        1. [[real]][[imag]] 设置为长度为 2 的全零数组。

        2. [[imag]] 索引为 1 的元素设置为 1。

        注意:OscillatorNode 上设置此 PeriodicWave 等同于使用内置类型“sine”。

    3. [[real]][[imag]] 索引为 0 的元素都设置为 0。(这将直流分量设置为 0。)

    4. [[normalize]] 初始化为 PeriodicWaveOptionsPeriodicWaveConstraintsdisableNormalization 属性的逆值。

    5. 返回 p

    PeriodicWave.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 PeriodicWave 将与之关联BaseAudioContext。与 AudioBuffer 不同,PeriodicWave 不能跨 AudioContextOfflineAudioContext 共享。它与特定的 BaseAudioContext 关联。
    options PeriodicWaveOptions PeriodicWave 的可选初始参数值。

    1.28.2. PeriodicWaveConstraints

    PeriodicWaveConstraints 字典用于指定波形如何进行归一化

    dictionary PeriodicWaveConstraints {
        boolean disableNormalization = false;
    };
    

    1.28.2.1. 字典 PeriodicWaveConstraints 成员
    disableNormalization, 类型为 boolean,默认为 false

    控制周期波是否归一化。如果为 true,则不对波形进行归一化;否则,对波形进行归一化。

    1.28.3. PeriodicWaveOptions

    PeriodicWaveOptions 字典用于指定如何构建波形。如果仅指定了 realimag 中的一个,另一个将被视为长度相同且全为零的数组,具体如字典成员描述中所述。如果两者均未给出,则创建的 PeriodicWave 必须等同于 OscillatorNodetype 为“sine”。如果两者均给出,则序列必须具有相同的长度;否则必须抛出 NotSupportedError 类型的错误

    dictionary PeriodicWaveOptions : PeriodicWaveConstraints {
        sequence<float> real;
        sequence<float> imag;
    };
    

    1.28.3.1. 字典 PeriodicWaveOptions 成员
    imag, 类型为 sequence<float>

    imag 参数表示 sine 项的数组。第一个元素(索引 0)在傅里叶级数中不存在。第二个元素(索引 1)代表基频。第三个代表第一个泛音,依此类推。

    real, 类型为 sequence<float>

    real 参数表示 cosine 项的数组。第一个元素(索引 0)是周期波形的直流偏移(DC-offset)。第二个元素(索引 1)代表基频。第三个代表第一个泛音,依此类推。

    1.28.4. 波形生成

    createPeriodicWave() 方法采用两个数组来指定 PeriodicWave 的傅里叶系数。令 \(a\) 和 \(b\) 分别表示长度为 \(L\) 的 [[real]][[imag]] 数组。则基本时域波形 \(x(t)\) 可以通过以下公式计算

    $$
        x(t) = \sum_{k=1}^{L-1} \left[a[k]\cos2\pi k t + b[k]\sin2\pi k t\right]
    $$
    

    这是基本(未归一化)波形。

    1.28.5. 波形归一化

    如果此 PeriodicWave 的内部槽位 [[normalize]]true(默认值),则上一节中定义的波形将进行归一化,使得最大值为 1。归一化过程如下。

    $$
        \tilde{x}(n) = \sum_{k=1}^{L-1} \left(a[k]\cos\frac{2\pi k n}{N} + b[k]\sin\frac{2\pi k n}{N}\right)
    $$
    

    其中 \(N\) 是 2 的幂。(注意:\(\tilde{x}(n)\) 可以通过使用反傅里叶变换 (IFFT) 方便地计算出来。)固定归一化因子 \(f\) 计算如下。

    $$
        f = \max_{n = 0, \ldots, N - 1} |\tilde{x}(n)|
    $$
    

    因此,实际的归一化波形 \(\hat{x}(n)\) 为

    $$
        \hat{x}(n) = \frac{\tilde{x}(n)}{f}
    $$
    

    该固定归一化因子必须应用于所有生成的波形。

    1.28.6. 振荡器系数

    内置振荡器类型使用 PeriodicWave 对象创建。为完整起见,此处给出了每种内置振荡器类型的 PeriodicWave 系数。这在需要内置类型但不需要默认归一化时非常有用。

    在以下描述中,令 \(a\) 为 createPeriodicWave() 的实系数数组,\(b\) 为虚系数数组。在所有情况下,由于波形是奇函数,所有 \(n\) 的 \(a[n] = 0\)。此外,所有情况下 \(b[0] = 0\)。因此,下面仅指定 \(n \ge 1\) 时的 \(b[n]\)。

    "sine"
    $$
        b[n] = \begin{cases}
                         1 & \mbox{for } n = 1 \\
                         0 & \mbox{otherwise}
                     \end{cases}
    $$
    
    "square"
    $$
        b[n] = \frac{2}{n\pi}\left[1 - (-1)^n\right]
    $$
    
    "sawtooth"
    $$
        b[n] = (-1)^{n+1} \dfrac{2}{n\pi}
    $$
    
    "triangle"
    $$
        b[n] = \frac{8\sin\dfrac{n\pi}{2}}{(\pi n)^2}
    $$
    

    1.29. ScriptProcessorNode 接口 - 已弃用

    此接口是一个 AudioNode,可以使用脚本直接生成、处理或分析音频。此节点类型已弃用,将由 AudioWorkletNode 取代;此文本仅保留供参考,直到实现中移除此节点类型为止。

    ScriptProcessorNode 构建时带有 bufferSize,其值必须为以下之一:256、512、1024、2048、4096、8192、16384。此值控制 audioprocess 事件的分发频率以及每次调用需要处理多少样本帧。audioprocess 事件仅在 ScriptProcessorNode 至少连接了一个输入或一个输出时才会分发。bufferSize 的数值越小,延迟就越低(越好)。数值越大,越能避免音频中断和故障(glitches)。如果未将 createScriptProcessor() 的 bufferSize 参数传入,或者设置为 0,则此值将由实现方选择。

    numberOfInputChannelsnumberOfOutputChannels 决定输入和输出的声道数。numberOfInputChannelsnumberOfOutputChannels 同时为零是无效的。

    [Exposed=Window]
    interface ScriptProcessorNode : AudioNode {
        attribute EventHandler onaudioprocess;
        readonly attribute long bufferSize;
    };
    

    1.29.1. 属性
    bufferSize, 类型为 long,只读

    每次触发 audioprocess 时需要处理的缓冲区大小(以样本帧为单位)。合法值为 (256, 512, 1024, 2048, 4096, 8192, 16384)。

    onaudioprocess, 类型为 EventHandler

    用于设置 事件处理程序的属性,该处理程序用于分发到 ScriptProcessorNode 节点类型的 audioprocess 事件类型。分发到事件处理程序的事件使用 AudioProcessingEvent 接口。

    1.30. StereoPannerNode 接口

    此接口表示一个处理节点,它使用低成本平移算法在立体声图像中定位传入的音频流。这种平移效果在立体声流中定位音频组件时非常常见。

    此节点的输入为立体声(2 声道),无法增加。来自声道更少或更多的节点的连接将适当地进行上混或下混

    此节点的输出硬编码为立体声(2 声道),无法配置。

    [Exposed=Window]
    interface StereoPannerNode : AudioNode {
        constructor (BaseAudioContext context, optional StereoPannerOptions options = {});
        readonly attribute AudioParam pan;
    };
    

    1.30.1. 构造函数
    StereoPannerNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须初始化 AudioNode this,并以 contextoptions 作为参数。

    StereoPannerNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 StereoPannerNode 将与之关联BaseAudioContext
    options StereoPannerOptions StereoPannerNode 的可选初始参数值。

    1.30.2. 属性
    pan, 类型为 AudioParam,只读

    输入在输出立体声图像中的位置。-1 表示完全左侧,+1 表示完全右侧。

    1.30.3. StereoPannerOptions

    这指定了构建 StereoPannerNode 时使用的选项。所有成员均为可选;如果未指定,则使用构建该节点的正常默认值。

    dictionary StereoPannerOptions : AudioNodeOptions {
        float pan = 0;
    };
    

    1.30.3.1. 字典 StereoPannerOptions 成员
    pan, 类型为 float,默认为 0

    pan AudioParam 的初始值。

    1.30.4. 声道限制

    由于其处理受到上述定义的限制,StereoPannerNode 限制为混合不超过 2 个声道音频,并产生恰好 2 个声道。可以使用 ChannelSplitterNode、通过 GainNode 和/或其他节点组成的子图进行中间处理,以及通过 ChannelMergerNode 进行重组,来实现任意平移和混音方法。

    1.31. WaveShaperNode 接口

    WaveShaperNode 是一个实现非线性失真效果的 AudioNode 处理器。

    非线性波形重塑失真通常用于微妙的非线性暖化,或更明显的失真效果。可以指定任意的非线性重塑曲线。

    属性
    numberOfInputs 1
    numberOfOutputs 1
    channelCount 2
    channelCountMode "max"
    channelInterpretation "speakers"
    tail-time 也许仅当 oversample 属性设置为“2x”或“4x”时,才存在尾部时间(tail-time)。此尾部时间的实际持续时间取决于具体实现。

    输出的通道数始终等于输入的通道数。

    enum OverSampleType {
        "none",
        "2x",
        "4x"
    };
    
    OverSampleType 枚举描述
    枚举值描述
    "none"不进行过采样
    "2x"进行 2 倍过采样
    "4x"进行 4 倍过采样
    [Exposed=Window]
    interface WaveShaperNode : AudioNode {
        constructor (BaseAudioContext context, optional WaveShaperOptions options = {});
        attribute Float32Array? curve;
        attribute OverSampleType oversample;
    };
    

    1.31.1. 构造函数
    WaveShaperNode(context, options)

    当使用 BaseAudioContext c 和选项对象 option 调用构造函数时,用户代理必须初始化 AudioNode this,并以 contextoptions 作为参数。

    此外,令 [[curve set]] 为此 WaveShaperNode 的内部槽位。将此槽位初始化为 false。如果给出了 options 并指定了 curve,则将 [[curve set]] 设置为 true

    WaveShaperNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 WaveShaperNode 将与之关联BaseAudioContext
    options WaveShaperOptions WaveShaperNode 的可选初始参数值。

    1.31.2. 属性
    curve, 类型为 Float32Array,可为空

    用于波形重塑效果的重塑曲线。输入信号通常在 [-1, 1] 范围内。在此范围内的每个输入样本都将索引到重塑曲线中,如果曲线数组中的条目数为奇数,则零信号电平对应数组的中心值;如果数组中的条目数为偶数,则在两个最中心的值之间进行插值。任何小于 -1 的样本值将对应曲线数组中的第一个值。任何大于 +1 的样本值将对应曲线数组中的最后一个值。

    实现必须在曲线的相邻点之间执行线性插值。最初 curve 属性为 null,这意味着 WaveShaperNode 将原样传递输入到输出,不做修改。

    曲线的值在 [-1, 1] 范围内均匀分布。这意味着具有偶数个值的 curve 在信号为零时将没有对应值,而具有奇数个值的 curve 在信号为零时将有对应值。输出由以下算法确定。

    1. 令 \(x\) 为输入样本,\(y\) 为节点的对应输出,\(c_k\) 为 curve 的第 \(k\) 个元素,\(N\) 为 curve 的长度。

    2. $$
          \begin{align*}
          v &= \frac{N-1}{2}(x + 1) \\
          k &= \lfloor v \rfloor \\
          f &= v - k
          \end{align*}
      $$
      
    3. 然后

      $$
          \begin{align*}
          y &=
              \begin{cases}
              c_0 & v \lt 0 \\
              c_{N-1} & v \ge N - 1 \\
              (1-f)\,c_k + fc_{k+1} & \mathrm{otherwise}
              \end{cases}
          \end{align*}
      $$
      

    如果此属性设置为长度小于 2 的 Float32Array,则必须抛出 InvalidStateError

    设置此属性时,WaveShaperNode 会创建曲线的内部副本。因此,后续修改用于设置该属性的数组内容将不会产生任何影响。

    要设置 curve 属性,请执行以下步骤
  • new curve 为要分配给 curveFloat32Arraynull

  • 如果 new curve 不为 null[[curve set]] 为 true,则抛出 InvalidStateError 并终止这些步骤。

  • 如果 new curve 不为 null,则将 [[curve set]] 设置为 true。

  • new curve 分配给 curve 属性。

  • 注意: 使用在输入为零时产生非零输出值的曲线,将导致此节点产生直流信号,即使没有输入连接到此节点。这种现象将持续到该节点与下游节点断开连接为止。

    oversample, 类型为 OverSampleType

    指定应用重塑曲线时应使用哪种类型的过采样(如果有)。默认值为“none”,表示曲线将直接应用于输入样本。值为“2x”或“4x”可以通过避免某些混叠来提高处理质量,其中“4x”值可产生最高质量。对于某些应用,最好不使用过采样以获得非常精确的重塑曲线。

    值为“2x”或“4x”意味着必须执行以下步骤
  • 将输入样本上采样至 AudioContext 采样率的 2 倍或 4 倍。因此,对于每个渲染量子(render quantum),生成两倍(2x)或四倍(4x)的样本。

  • 应用重塑曲线。

  • 将结果下采样回 AudioContext 的采样率。从而获取先前处理过的样本,生成单个渲染量子长度的样本作为最终结果。

  • 确切的上采样和下采样滤波器未指定,可以针对音质(低混叠等)、低延迟或性能进行调优。

    注意: 使用过采样由于上采样和下采样滤波器而引入了一定程度的音频处理延迟。这种延迟量在不同实现之间可能有所不同。

    1.31.3. WaveShaperOptions

    这指定了构建 WaveShaperNode 的选项。所有成员均为可选;如果未指定,则使用构建该节点的正常默认值。

    dictionary WaveShaperOptions : AudioNodeOptions {
        sequence<float> curve;
        OverSampleType oversample = "none";
    };
    

    1.31.3.1. 字典 WaveShaperOptions 成员
    curve, 类型为 sequence<float>

    重塑效果的重塑曲线。

    oversample, 类型为 OverSampleType,默认为 "none"

    用于重塑曲线的过采样类型。

    1.32. AudioWorklet 接口
    [Exposed=Window, SecureContext]
    interface AudioWorklet : Worklet {
      readonly attribute MessagePort port;
    };
    

    1.32.1. 属性
    port, 类型为 MessagePort,只读

    连接到 AudioWorkletGlobalScope 上端口的 MessagePort

    注意: 在此 port"message" 事件上注册事件监听器的作者,应在 MessageChannel 的任意一端(在 AudioWorkletAudioWorkletGlobalScope 端)调用 close,以允许资源被回收

    1.32.2. 概念

    AudioWorklet 对象允许开发者提供脚本(如 JavaScript 或 WebAssembly 代码)在渲染线程上处理音频,支持自定义 AudioNode。此处理机制确保了脚本代码与音频图中其他内置 AudioNode 的同步执行。

    为了实现此机制,必须定义一对关联对象:AudioWorkletNodeAudioWorkletProcessor。前者表示主全局作用域的接口,类似于其他 AudioNode 对象;后者在名为 AudioWorkletGlobalScope 的特殊作用域内实现内部音频处理。

    AudioWorklet concept
    AudioWorkletNodeAudioWorkletProcessor

    每个 BaseAudioContext 拥有恰好一个 AudioWorklet

    AudioWorklet工作线程全局作用域类型AudioWorkletGlobalScope

    AudioWorklet工作线程目标类型"audioworklet"

    通过 addModule(moduleUrl) 方法导入脚本,可以在 AudioWorkletGlobalScope 下注册 AudioWorkletProcessor 的类定义。对于导入的类构造函数和从该构造函数创建的活动实例,有两个内部存储区域。

    AudioWorklet 有一个内部槽位

    // bypass-processor.js script file, runs on AudioWorkletGlobalScope
    class BypassProcessor extends AudioWorkletProcessor {
        process (inputs, outputs) {
            // Single input, single channel.
            const input = inputs[0];
            const output = outputs[0];
            output[0].set(input[0]);
    
            // Process only while there are active inputs.
            return false;
        }
    };
    
    registerProcessor('bypass-processor', BypassProcessor);
    
    // The main global scope
    const context = new AudioContext();
    context.audioWorklet.addModule('bypass-processor.js').then(() => {
        const bypassNode = new AudioWorkletNode(context, 'bypass-processor');
    });
    

    在主全局作用域实例化 AudioWorkletNode 时,对应的 AudioWorkletProcessor 也将在 AudioWorkletGlobalScope 中创建。这两个对象通过 § 2 处理模型 中描述的异步消息传递进行通信。

    1.32.3. AudioWorkletGlobalScope 接口

    此特殊执行上下文旨在利用音频渲染线程中的脚本直接启用音频数据的生成、处理和分析。用户提供的脚本代码在此作用域中执行,以定义一个或多个 AudioWorkletProcessor 子类,进而用于实例化 AudioWorkletProcessor,与主作用域中的 AudioWorkletNode 建立 1:1 的关联。

    对于每个包含一个或多个 AudioWorkletNodeAudioContext,均存在且仅存在一个 AudioWorkletGlobalScope。导入脚本的运行由用户代理按照 [HTML] 中的定义执行。作为对 [HTML] 中指定的默认行为的覆盖,用户代理不得随意终止 AudioWorkletGlobalScope

    AudioWorkletGlobalScope 具有以下内部槽位

    注:AudioWorkletGlobalScope 还可以包含由这些实例共享的任何其他数据和代码。例如,多个处理器可以共享一个定义波表或脉冲响应的 ArrayBuffer。

    注:AudioWorkletGlobalScope 与单个 BaseAudioContext 关联,并与该上下文的单个音频渲染线程关联。这可以防止在并发线程中运行的全局作用域代码出现数据竞争。

    callback AudioWorkletProcessorConstructor = AudioWorkletProcessor (object options);
    
    [Global=(Worklet, AudioWorklet), Exposed=AudioWorklet]
    interface AudioWorkletGlobalScope : WorkletGlobalScope {
        undefined registerProcessor (DOMString name,
                                                   AudioWorkletProcessorConstructor processorCtor);
        readonly attribute unsigned long long currentFrame;
        readonly attribute double currentTime;
        readonly attribute float sampleRate;
        readonly attribute unsigned long renderQuantumSize;
        readonly attribute MessagePort port;
    };
    
    1.32.3.1. 属性
    currentFrame类型为 unsigned long long,只读

    正在处理的音频块的当前帧。此值必须等于 BaseAudioContext[[current frame]] 内部槽位的值。

    currentTime类型为 double,只读

    正在处理的音频块的上下文时间。根据定义,此值将等于在控制线程中最近观察到的 BaseAudioContextcurrentTime 属性值。

    sampleRate类型为 float,只读

    关联的 BaseAudioContext 的采样率。

    renderQuantumSize类型为 unsigned long,只读

    关联的 BaseAudioContext 的私有槽位 [[render quantum size]] 的值。

    port类型为 MessagePort,只读

    一个连接到 AudioWorklet 上端口的 MessagePort

    注:在此 port"message" 事件上注册事件监听器的作者,应在 MessageChannel 的任一端(AudioWorkletAudioWorkletGlobalScope 端)调用 close,以允许资源被回收

    1.32.3.2. 方法
    registerProcessor(name, processorCtor)

    注册一个派生自 AudioWorkletProcessor 的类构造函数。

    当调用 registerProcessor(name, processorCtor) 方法时,执行以下步骤。如果在任何步骤中抛出异常,则中止剩余步骤。
    1. 如果 name 为空字符串,则抛出 NotSupportedError

    2. 如果 name 已作为键存在于 节点名称到处理器构造函数映射中,则抛出 NotSupportedError

    3. 如果 IsConstructor(argument=processorCtor) 的结果为 false则抛出 TypeError

    4. prototypeGet(O=processorCtor, P="prototype") 的结果。

    5. 如果 Type(argument=prototype) 的结果不是 Object则抛出 TypeError

    6. parameterDescriptorsValueGet(O=processorCtor, P="parameterDescriptors") 的结果。

    7. 如果 parameterDescriptorsValue 不为 undefined,执行以下步骤

      1. parameterDescriptorSequence 为将 parameterDescriptorsValue 转换为 sequence<AudioParamDescriptor> 类型的 IDL 值的结果。

      2. paramNames 为一个空数组。

      3. 对于 parameterDescriptorSequence 中的每个 descriptor
        1. paramNamedescriptor 中成员 name 的值。如果 paramNames 已包含 paramName 值,则抛出 NotSupportedError

        2. paramName 追加到 paramNames 数组中。

        3. defaultValuedescriptor 中成员 defaultValue 的值。

        4. minValuedescriptor 中成员 minValue 的值。

        5. maxValuedescriptor 中成员 maxValue 的值。

        6. 如果表达式 minValue <= defaultValue <= maxValue 为假,则抛出 InvalidStateError

    8. 将键值对 nameprocessorCtor 追加到关联的 AudioWorkletGlobalScope节点名称到处理器构造函数映射中。

    9. 队列化一个媒体元素任务,将键值对 nameparameterDescriptorSequence 追加到关联的 BaseAudioContext节点名称到参数描述符的映射中。

    注:类构造函数只应查找一次,因此它没有在注册后动态更改的机会。

    AudioWorkletGlobalScope.registerProcessor(name, processorCtor) 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    name DOMString 表示要注册的类构造函数的字符串键。在构建 AudioWorkletNode 时,此键用于查找 AudioWorkletProcessor 的构造函数。
    processorCtor AudioWorkletProcessorConstructor 扩展自 AudioWorkletProcessor 的类构造函数。
    返回类型: undefined
    1.32.3.3. AudioWorkletProcessor 的实例化

    AudioWorkletNode 构造结束时,将准备一个名为 处理器构造数据结构体,用于跨线程传输。此结构体包含以下

    当传输的数据到达 AudioWorkletGlobalScope 时,渲染线程将调用以下算法

    1. constructionData 为从控制线程传输过来的处理器构造数据

    2. processorNamenodeReferenceserializedPort 分别为 constructionData名称节点端口

    3. serializedOptionsconstructionData选项

    4. deserializedPortStructuredDeserialize(serializedPort, 当前领域) 的结果。

    5. deserializedOptionsStructuredDeserialize(serializedOptions, 当前领域) 的结果。

    6. processorCtor 为在 AudioWorkletGlobalScope节点名称到处理器构造函数映射中查找 processorName 的结果。

    7. nodeReferencedeserializedPort 分别存储到此 AudioWorkletGlobalScope挂起的处理器构造数据中的节点引用传输端口

    8. 构建一个回调函数,该函数来自 processorCtor,参数为 deserializedOptions。如果回调中抛出任何异常,则队列化一个任务控制线程,以使用 ErrorEventnodeReference触发一个名为 processorerror 的事件。

    9. 清空挂起的处理器构造数据槽位。

    1.32.4. AudioWorkletNode 接口

    此接口代表一个存在于控制线程上的用户定义 AudioNode。用户可以从 BaseAudioContext 创建 AudioWorkletNode,并且此类节点可以与其他内置 AudioNode 连接以形成音频图。

    每个 AudioWorkletProcessor 都带有一个关联的活动源标志,初始为 true。该标志使节点保留在内存中,即使在没有连接输入的情况下也执行音频处理。

    AudioWorkletNode 发出的所有任务均被发送到其关联的 BaseAudioContext 的任务队列。

    [Exposed=Window]
    interface AudioParamMap {
        readonly maplike<DOMString, AudioParam>;
    };
    

    此接口具有由 readonly maplike 带来的 "entries"、"forEach"、"get"、"has"、"keys"、"values"、@@iterator 方法和一个 "size" 获取器。

    [Exposed=Window, SecureContext]
    interface AudioWorkletNode : AudioNode {
        constructor (BaseAudioContext context, DOMString name,
                   optional AudioWorkletNodeOptions options = {});
        readonly attribute AudioParamMap parameters;
        readonly attribute MessagePort port;
        attribute EventHandler onprocessorerror;
    };
    
    1.32.4.1. 构造函数
    AudioWorkletNode(context, name, options)
    AudioWorkletNode.constructor() 方法的参数。
    参数类型可为空 (Nullable)可选 (Optional)描述
    context BaseAudioContext 此新 AudioWorkletNode 将与之关联BaseAudioContext
    name DOMString 一个字符串,它是 BaseAudioContext节点名称到参数描述符映射的键。
    options AudioWorkletNodeOptions AudioWorkletNode 的可选初始参数值。

    当调用构造函数时,用户代理必须在控制线程上执行以下步骤

    当使用 contextnodeNameoptions 调用 AudioWorkletNode 构造函数时
  • 如果 nodeName 不作为 BaseAudioContext节点名称到参数描述符映射中的键存在,则抛出 InvalidStateError 异常并中止这些步骤。

  • node值。

  • 初始化 AudioNode node,并以 contextoptions 为参数。

  • 配置 node 的输入、输出和输出通道(参数为 options)。如果抛出任何异常,则中止剩余步骤。

  • messageChannel 为一个新的 MessageChannel

  • nodePortmessageChannelport1 属性的值。

  • processorPortOnThisSidemessageChannelport2 属性的值。

  • serializedProcessorPortStructuredSerializeWithTransfer(processorPortOnThisSide, « processorPortOnThisSide ») 的结果。

  • options 字典转换为 optionsObject

  • serializedOptionsStructuredSerialize(optionsObject) 的结果。

  • nodeport 设置为 nodePort

  • parameterDescriptors 为从节点名称到参数描述符映射中检索 nodeName 的结果。

    1. audioParamMap 为一个新的 AudioParamMap 对象。

    2. 对于 parameterDescriptors 中的每个 descriptor

      1. paramNamedescriptorname 成员的值。

      2. audioParam 为一个新的 AudioParam 实例,其 automationRatedefaultValueminValuemaxValue 的值等于 descriptor 上相应成员的值。

      3. 将键值对 paramNameaudioParam 追加到 audioParamMap 的条目中。

    3. 如果 options 上存在 parameterData,则执行以下步骤

      1. parameterDataparameterData 的值。

      2. 对于 parameterData 中的每个 paramNameparamValue

        1. 如果 audioParamMap 上存在键为 paramName 的映射条目,令 audioParamInMap 为该条目。

        2. audioParamInMapvalue 属性设置为 paramValue

    4. nodeparameters 设置为 audioParamMap

  • 队列化一条控制消息,以调用对应 AudioWorkletProcessorconstructor,并传入由以下内容组成的处理器构造数据nodeNamenodeserializedOptionsserializedProcessorPort

  • 1.32.4.2. 属性
    onprocessorerror类型为 EventHandler

    当处理器的 constructorprocess 方法或任何用户定义的类方法抛出未捕获的异常时,处理器将队列化一个媒体元素任务,以使用 ErrorEvent 在关联的 AudioWorkletNode触发一个名为 processorerror 的事件。

    ErrorEvent 是在控制线程上创建并适当初始化其 messagefilenamelinenocolno 属性的。

    注意,一旦抛出未捕获的异常,处理器在其生命周期内将输出静音。

    parameters类型为 AudioParamMap,只读

    parameters 属性是一组带有关联名称的 AudioParam 对象的集合。此映射类对象在实例化时,由 AudioWorkletProcessor 类构造函数中的 AudioParamDescriptor 列表填充。

    port类型为 MessagePort,只读

    每个 AudioWorkletNode 都有一个关联的 port,即 MessagePort。它连接到相应 AudioWorkletProcessor 对象上的端口,允许 AudioWorkletNode 与其 AudioWorkletProcessor 之间进行双向通信。

    注:在此 port"message" 事件上注册事件监听器的作者,应在 MessageChannel 的任一端(AudioWorkletProcessorAudioWorkletNode 端)调用 close,以允许资源被回收

    1.32.4.3. AudioWorkletNodeOptions

    AudioWorkletNodeOptions 字典可用于初始化 AudioWorkletNode 实例中的属性。

    dictionary AudioWorkletNodeOptions : AudioNodeOptions {
        unsigned long numberOfInputs = 1;
        unsigned long numberOfOutputs = 1;
        sequence<unsigned long> outputChannelCount;
        record<DOMString, double> parameterData;
        object processorOptions;
    };
    
    1.32.4.3.1. 字典 AudioWorkletNodeOptions 成员
    numberOfInputs类型为 unsigned long,默认为 1

    此成员用于初始化 AudioNodenumberOfInputs 属性值。

    numberOfOutputs类型为 unsigned long,默认为 1

    此成员用于初始化 AudioNodenumberOfOutputs 属性值。

    outputChannelCount类型为 sequence<unsigned long>

    此数组用于配置每个输出中的通道数。

    parameterData类型为 record<DOMString, double>

    这是一组用户定义的键值对,用于设置 AudioWorkletNode 中匹配名称的 AudioParam 的初始 value

    processorOptions类型为 object

    此成员保存任何用户定义的数据,该数据可用于初始化与 AudioWorkletNode 关联的 AudioWorkletProcessor 实例中的自定义属性。

    1.32.4.3.2. 使用 AudioWorkletNodeOptions 配置通道

    以下算法描述了如何使用 AudioWorkletNodeOptions 来配置各种通道设置。

    1. node 为提供给此算法的 AudioWorkletNode 实例。

    2. 如果 numberOfInputsnumberOfOutputs 均为零,则抛出 NotSupportedError 并中止剩余步骤。

    3. 如果 outputChannelCount 存在

      1. 如果 outputChannelCount 中的任何值小于零或大于实现允许的最大通道数,则抛出 NotSupportedError 并中止剩余步骤。

      2. 如果 outputChannelCount 的长度不等于 numberOfOutputs,则抛出 IndexSizeError 并中止剩余步骤。

      3. 如果 numberOfInputsnumberOfOutputs 均为 1,则将 node 输出的通道计数设置为 outputChannelCount 中的唯一值。

      4. 否则,将 node 的第 k 个输出的通道计数设置为 outputChannelCount 序列的第 k 个元素并返回。

    4. 如果 outputChannelCount存在

      1. 如果 numberOfInputsnumberOfOutputs 均为 1,则将 node 输出的初始通道计数设置为 1 并返回。

        NOTE: 对于这种情况,输出通道计数将在运行时根据输入和 channelCountMode 动态变为 computedNumberOfChannels

      2. 否则,将 node 每个输出的通道计数设置为 1 并返回。

    1.32.5. AudioWorkletProcessor 接口

    此接口代表在音频渲染线程上运行的音频处理代码。它存在于 AudioWorkletGlobalScope 中,类的定义体现了实际的音频处理。请注意,AudioWorkletProcessor 的构建只能作为 AudioWorkletNode 构建的结果发生。

    [Exposed=AudioWorklet]
    interface AudioWorkletProcessor {
        constructor ();
        readonly attribute MessagePort port;
    };
    
    callback AudioWorkletProcessCallback =
      boolean (FrozenArray<FrozenArray<Float32Array>> inputs,
               FrozenArray<FrozenArray<Float32Array>> outputs,
               object parameters);
    

    AudioWorkletProcessor 具有两个内部槽位

    [[node reference]]

    对关联 AudioWorkletNode 的引用。

    [[callable process]]

    一个布尔标志,表示 process() 是否为可调用的有效函数。

    1.32.5.1. 构造函数
    AudioWorkletProcessor()

    当调用 AudioWorkletProcessor 的构造函数时,在渲染线程上执行以下步骤。

    1. nodeReference 为在当前 AudioWorkletGlobalScope挂起的处理器构造数据中查找节点引用的结果。如果该槽位为空,则抛出 TypeError 异常。

    2. processor值。

    3. processor[[node reference]] 设置为 nodeReference

    4. processor[[callable process]] 设置为 true

    5. deserializedPort 为从挂起的处理器构造数据中查找传输端口的结果。

    6. processorport 设置为 deserializedPort

    7. 清空挂起的处理器构造数据槽位。

    1.32.5.2. 属性
    port类型为 MessagePort,只读

    每个 AudioWorkletProcessor 都有一个关联的 port,即 MessagePort。它连接到相应 AudioWorkletNode 对象上的端口,允许 AudioWorkletNode 与其 AudioWorkletProcessor 之间进行双向通信。

    注:在此 port"message" 事件上注册事件监听器的作者,应在 MessageChannel 的任一端(AudioWorkletProcessorAudioWorkletNode 端)调用 close,以允许资源被回收

    1.32.5.3. 回调 AudioWorkletProcessCallback

    用户可以通过扩展 AudioWorkletProcessor 来定义自定义音频处理器。子类必须定义一个名为 process()AudioWorkletProcessCallback,用于实现音频处理算法,并且可以有一个名为 parameterDescriptors 的静态属性,该属性是一个 AudioParamDescriptor 的可迭代对象。

    process() 回调函数按照渲染图时的规定进行处理。

    此回调的返回值控制 AudioWorkletProcessor 关联 AudioWorkletNode 的生命周期。此生命周期策略可以支持内置节点中发现的多种方法,包括以下几种
    • 变换其输入且仅在连接了输入和/或脚本引用存在时才处于活动状态的节点。此类节点应从 process() 返回 false,这允许通过是否有连接的输入来确定 AudioWorkletNode 是否处于主动处理状态

    • 在输入断开后仍保留一段时间尾部时间的节点。在这种情况下,当发现 inputs 包含零个通道时,process() 应返回 true 一段时间。当前时间可以从全局作用域的 currentTime 获取,以衡量此尾部时间间隔的开始和结束,或者该间隔可以根据处理器的内部状态动态计算。

    • 充当输出源(通常具有特定生命周期)的节点。此类节点应从 process() 返回 true,直到它们不再产生输出为止。

    请注意,上述定义意味着当 process() 的实现未提供返回值时,其效果与返回 false 相同(因为有效的返回值是 falsy 值 undefined)。对于任何仅在有活动输入时才处于活动状态的 AudioWorkletProcessor,这是一种合理的行为。

    下面的示例展示了如何在 AudioWorkletProcessor 中定义和使用 AudioParam

    class MyProcessor extends AudioWorkletProcessor {
      static get parameterDescriptors() {
        return [{
          name: 'myParam',
          defaultValue: 0.5,
          minValue: 0,
          maxValue: 1,
          automationRate: "k-rate"
        }];
      }
    
      process(inputs, outputs, parameters) {
        // Get the first input and output.
        const input = inputs[0];
        const output = outputs[0];
        const myParam = parameters.myParam;
    
        // A simple amplifier for single input and output. Note that the
        // automationRate is "k-rate", so it will have a single value at index [0]
        // for each render quantum.
        for (let channel = 0; channel < output.length; ++channel) {
          for (let i = 0; i < output[channel].length; ++i) {
            output[channel][i] = input[channel][i] * myParam[0];
          }
        }
      }
    }
    
    1.32.5.3.1. 回调 AudioWorkletProcessCallback 参数
    以下描述了 AudioWorkletProcessCallback 函数的参数。通常,inputsoutputs 数组会在多次调用之间重复使用,因此不会进行内存分配。但是,如果拓扑结构发生变化(例如,输入或输出中的通道数量发生变化),则会重新分配新的数组。如果 inputsoutputs 数组的任何部分被传输,也会重新分配新的数组。
    inputs,类型为 FrozenArray<FrozenArray<Float32Array>>

    用户代理提供的来自传入连接的输入音频缓冲区。inputs[n][m] 是一个 Float32Array,包含第 \(n\) 个输入的第 \(m\) 个通道的音频采样。虽然输入数量在构建时是固定的,但通道数量可以根据 computedNumberOfChannels 动态更改。

    如果对于当前的渲染量(render quantum),没有连接到 AudioWorkletNode 第 \(n\) 个输入的主动处理状态 AudioNode,则 inputs[n] 的内容是一个空数组,表示没有可用的输入通道。这是 inputs[n] 元素数量可以为零的唯一情况。

    outputs,类型为 FrozenArray<FrozenArray<Float32Array>>

    由用户代理消费的输出音频缓冲区。outputs[n][m] 是一个包含第 \(n\) 个输出的第 \(m\) 个通道音频采样的 Float32Array 对象。每个 Float32Array 均已初始化为零。仅当节点具有单个输出时,输出中的通道数才会与 computedNumberOfChannels 匹配。

    parameters,类型为 object

    一个 nameparameterValues有序映射parameters["name"] 返回 parameterValues,这是一个 FrozenArray<Float32Array>,其中包含该 name AudioParam 的自动控制值。

    对于每个数组,该数组包含渲染量中所有帧参数的计算值。但是,如果在此渲染量期间没有预定自动控制,则数组的长度可以为 1,数组元素为该渲染量AudioParam 的恒定值。

    此对象根据以下步骤被冻结

    1. parameter 为名称和参数值的有序映射

    2. SetIntegrityLevel(parameter, frozen)

    算法中计算出的此冻结有序映射被传递给 parameters 参数。

    注:这意味着该对象无法被修改,因此除非数组长度发生变化,否则同一个对象可以用于连续的调用。

    1.32.5.4. AudioParamDescriptor

    AudioParamDescriptor 字典用于指定在 AudioWorkletNode 中使用的 AudioParam 对象的属性。

    dictionary AudioParamDescriptor {
        required DOMString name;
        float defaultValue = 0;
        float minValue = -3.4028235e38;
        float maxValue = 3.4028235e38;
        AutomationRate automationRate = "a-rate";
    };
    
    1.32.5.4.1. 字典 AudioParamDescriptor 成员

    这些成员的值存在约束。有关约束,请参见处理 AudioParamDescriptor 的算法

    automationRate类型为 AutomationRate,默认为 "a-rate"

    表示默认自动控制速率。

    defaultValue类型为 float,默认为 0

    表示参数的默认值。

    maxValue类型为 float,默认为 3.4028235e38

    表示最大值。

    minValue类型为 float,默认为 -3.4028235e38

    表示最小值。

    name类型为 DOMString

    表示参数的名称。

    1.32.6. AudioWorklet 事件序列

    下图展示了与 AudioWorklet 相关联的理想事件序列

    AudioWorklet 序列

    图中描述的步骤是涉及创建 AudioContext 和关联的 AudioWorkletGlobalScope,随后创建 AudioWorkletNode 及其关联的 AudioWorkletProcessor 的一种可能事件序列。

    1. 创建 AudioContext

    2. 在主作用域中,请求 context.audioWorklet 添加一个脚本模块。

    3. 由于尚不存在,因此创建一个新的 AudioWorkletGlobalScope 并与该上下文关联。这是将评估 AudioWorkletProcessor 类定义的全局作用域。(在后续调用中,将使用此先前创建的作用域。)

    4. 导入的脚本在新创建的全局作用域中运行。

    5. 作为运行导入脚本的一部分,AudioWorkletProcessorAudioWorkletGlobalScope 内的一个键(在上图中为 "custom")下注册。这会填充全局作用域和 AudioContext 中的映射。

    6. addModule() 调用的 promise 已解析。

    7. 在主作用域中,使用用户指定的键以及选项字典创建一个 AudioWorkletNode

    8. 作为节点创建的一部分,此键用于查找正确的 AudioWorkletProcessor 子类以进行实例化。

    9. AudioWorkletProcessor 子类的一个实例使用相同选项字典的结构化克隆进行实例化。此实例与先前创建的 AudioWorkletNode 配对。

    1.32.7. AudioWorklet 示例

    1.32.7.1. BitCrusher 节点

    Bitcrushing 是一种通过量化采样值(模拟较低的位深度)和量化时间分辨率(模拟较低的采样率)来降低音频流质量的机制。此示例展示了如何在 AudioWorkletProcessor 内部使用 AudioParam(在此情况下视为 a-rate)。

    const context = new AudioContext();context.audioWorklet.addModule('bitcrusher.js').then(() => {    const osc = new OscillatorNode(context);    const amp = new GainNode(context);    // Create a worklet node. 'BitCrusher' identifies the    // AudioWorkletProcessor previously registered when    // bitcrusher.js was imported. The options automatically    // initialize the correspondingly named AudioParams.    const bitcrusher = new AudioWorkletNode(context, 'bitcrusher', {        parameterData: {bitDepth: 8}    });    osc.connect(bitcrusher).connect(amp).connect(context.destination);    osc.start();});
    class Bitcrusher extends AudioWorkletProcessor {    static get parameterDescriptors () {        return [{            name: 'bitDepth',            defaultValue: 12,            minValue: 1,            maxValue: 16        }, {            name: 'frequencyReduction',            defaultValue: 0.5,            minValue: 0,            maxValue: 1        }];    }    constructor () {        super();        this._phase = 0;        this._lastSampleValue = 0;    }    process (inputs, outputs, parameters) {        const input = inputs[0];        const output = outputs[0];        const bitDepth = parameters.bitDepth;        const frequencyReduction = parameters.frequencyReduction;        if (bitDepth.length > 1) {            for (let channel = 0; channel < output.length; ++channel) {                for (let i = 0; i < output[channel].length; ++i) {                    let step = Math.pow(0.5, bitDepth[i]);                    // Use modulo for indexing to handle the case where                    // the length of the frequencyReduction array is 1.                    this._phase += frequencyReduction[i % frequencyReduction.length];                    if (this._phase >= 1.0) {                        this._phase -= 1.0;                        this._lastSampleValue =                            step * Math.floor(input[channel][i] / step + 0.5);                    }                    output[channel][i] = this._lastSampleValue;                }            }        } else {            // Because we know bitDepth is constant for this call,            // we can lift the computation of step outside the loop,            // saving many operations.            const step = Math.pow(0.5, bitDepth[0]);            for (let channel = 0; channel < output.length; ++channel) {                for (let i = 0; i < output[channel].length; ++i) {                    this._phase += frequencyReduction[i % frequencyReduction.length];                    if (this._phase >= 1.0) {                        this._phase -= 1.0;                        this._lastSampleValue =                            step * Math.floor(input[channel][i] / step + 0.5);                    }                    output[channel][i] = this._lastSampleValue;                }            }        }        // No need to return a value; this node's lifetime is dependent only on its        // input connections.    }};registerProcessor('bitcrusher', Bitcrusher);

    注:AudioWorkletProcessor 类的定义中,如果作者提供的构造函数具有显式的非 this 返回值或未正确调用 super(),则会抛出 InvalidStateError

    1.32.7.2. VU 表节点

    这个简单的声音电平表示例进一步说明了如何创建一个像原生 AudioNode 一样工作的 AudioWorkletNode 子类,它接受构造函数选项并封装 AudioWorkletNodeAudioWorkletProcessor 之间的跨线程通信(异步)。此节点不使用任何输出。

    /* vumeter-node.js: Main global scope */export default class VUMeterNode extends AudioWorkletNode {    constructor (context, updateIntervalInMS) {        super(context, 'vumeter', {            numberOfInputs: 1,            numberOfOutputs: 0,            channelCount: 1,            processorOptions: {                updateIntervalInMS: updateIntervalInMS || 16.67            }        });        // States in AudioWorkletNode        this._updateIntervalInMS = updateIntervalInMS;        this._volume = 0;        // Handles updated values from AudioWorkletProcessor        this.port.onmessage = event => {            if (event.data.volume)                this._volume = event.data.volume;        }        this.port.start();    }    get updateInterval() {        return this._updateIntervalInMS;    }    set updateInterval(updateIntervalInMS) {        this._updateIntervalInMS = updateIntervalInMS;        this.port.postMessage({updateIntervalInMS: updateIntervalInMS});    }    draw () {        // Draws the VU meter based on the volume value        // every |this._updateIntervalInMS| milliseconds.    }};
    /* vumeter-processor.js: AudioWorkletGlobalScope */const SMOOTHING_FACTOR = 0.9;const MINIMUM_VALUE = 0.00001;registerProcessor('vumeter', class extends AudioWorkletProcessor {    constructor (options) {        super();        this._volume = 0;        this._updateIntervalInMS = options.processorOptions.updateIntervalInMS;        this._nextUpdateFrame = this._updateIntervalInMS;        this.port.onmessage = event => {            if (event.data.updateIntervalInMS)                this._updateIntervalInMS = event.data.updateIntervalInMS;        }    }    get intervalInFrames () {        return this._updateIntervalInMS / 1000 * sampleRate;    }    process (inputs, outputs, parameters) {        const input = inputs[0];        // Note that the input will be down-mixed to mono; however, if no inputs are        // connected then zero channels will be passed in.        if (input.length > 0) {            const samples = input[0];            let sum = 0;            let rms = 0;            // Calculated the squared-sum.            for (let i = 0; i < samples.length; ++i)                sum += samples[i] * samples[i];            // Calculate the RMS level and update the volume.            rms = Math.sqrt(sum / samples.length);            this._volume = Math.max(rms, this._volume * SMOOTHING_FACTOR);            // Update and sync the volume property with the main thread.            this._nextUpdateFrame -= samples.length;            if (this._nextUpdateFrame < 0) {                this._nextUpdateFrame += this.intervalInFrames;                this.port.postMessage({volume: this._volume});            }        }        // Keep on processing if the volume is above a threshold, so that        // disconnecting inputs does not immediately cause the meter to stop        // computing its smoothed value.        return this._volume >= MINIMUM_VALUE;    }});
    /* index.js: Main global scope, entry point */import VUMeterNode from './vumeter-node.js';const context = new AudioContext();context.audioWorklet.addModule('vumeter-processor.js').then(() => {    const oscillator = new OscillatorNode(context);    const vuMeterNode = new VUMeterNode(context, 25);    oscillator.connect(vuMeterNode);    oscillator.start();    function drawMeter () {        vuMeterNode.draw();        requestAnimationFrame(drawMeter);    }    drawMeter();});

    2. 处理模型

    2.1. 背景

    本节是非规范性的。

    需要低延迟的实时音频系统通常使用回调函数实现,当需要计算更多音频以保持播放不间断时,操作系统会回调程序。此类回调理想情况下在优先级较高的线程上调用(通常是系统上的最高优先级)。这意味着处理音频的程序仅执行来自此回调的代码。跨越线程边界或在渲染线程和回调之间添加缓冲,自然会增加延迟或使系统对故障的抵御能力降低。

    因此,Web 平台上执行异步操作的传统方式(事件循环)在此处不起作用,因为线程不是持续执行的。此外,传统的执行上下文(Windows 和 Workers)提供了许多不必要且可能阻塞的操作,这对于达到可接受的性能水平来说并不理想。

    此外,Worker 模型使得为脚本执行上下文创建一个专用线程成为必要,而所有 AudioNode 通常共享同一个执行上下文。

    注:本节规定了最终结果应该是什么样子,而不是应该如何实现。特别是,实现者可以使用线程之间共享的内存来代替使用消息队列,只要内存操作不被重新排序即可。

    2.2. 控制线程和渲染线程

    Web Audio API 必须使用控制线程渲染线程来实现。

    控制线程是实例化 AudioContext 的线程,也是作者操作音频图(即调用 BaseAudioContext 操作)的线程。渲染线程是根据控制线程的调用来计算实际音频输出的线程。如果为 AudioContext 计算音频,它可以是基于回调的实时音频线程;如果为 OfflineAudioContext 计算音频,则可以是普通线程。

    控制线程使用[HTML] 中描述的传统事件循环。

    渲染线程使用专门的渲染循环,在渲染音频图一节中描述。

    控制线程渲染线程的通信是通过控制消息传递完成的。反方向的通信是通过常规事件循环任务完成的。

    每个 AudioContext 都有一个单独的控制消息队列,这是一个控制消息列表,这些消息是在渲染线程上运行的操作。

    队列化一条控制消息是指将消息添加到 BaseAudioContext控制消息队列末尾。

    注:例如,成功在 AudioBufferSourceNode source 上调用 start(),会将一条控制消息添加到关联的 BaseAudioContext控制消息队列中。

    控制消息控制消息队列中按插入时间排序。因此,最早的消息就是位于控制消息队列前端的消息。

    交换一个控制消息队列 QA 与另一个控制消息队列 QB 意味着执行以下步骤
    1. QC 为一个新的、空的控制消息队列

    2. QA 中的所有控制消息移动到 QC

    3. QB 中的所有控制消息移动到 QA

    4. QC 中的所有控制消息移动到 QB

    2.3. 异步操作

    AudioNode 上调用方法实际上是异步的,且必须分两个阶段完成:同步部分和异步部分。对于每个方法,执行的一部分发生在控制线程上(例如,在参数无效时抛出异常),而另一部分发生在渲染线程上(例如,改变 AudioParam 的值)。

    AudioNodeBaseAudioContext 的每项操作描述中,同步部分用 ⌛ 标记。所有其他操作均按照 [HTML] 中的描述并行执行。

    同步部分在控制线程上执行,并立即发生。如果失败,方法执行会终止,并可能抛出异常。如果成功,一个编码了要在渲染线程上执行的操作的控制消息会被放入该渲染线程控制消息队列中。

    同步和异步部分相对于其他事件的顺序必须保持一致:给定两个操作 AB,其各自的同步和异步部分分别为 ASyncAAsync,以及 BSyncBAsync,如果 A 发生在 B 之前,则 ASync 必须发生在 BSync 之前,且 AAsync 必须发生在 BAsync 之前。换句话说,同步部分和异步部分不能重排序。

    2.4. 渲染音频图

    音频图渲染以采样帧块(sample-frames)为单位进行,每个块的大小在 BaseAudioContext 的生命周期内保持不变。一个块中的采样帧数称为渲染量子大小(render quantum size),块本身称为渲染量子(render quantum)。其默认值为 128,可以通过设置 renderSizeHint 进行配置。

    在给定线程上原子地发生的操作,只能在其他线程上没有其他原子操作运行时执行。

    BaseAudioContext G(带有控制消息队列 Q)渲染音频块的算法由多个步骤组成,详细说明请参阅渲染图算法。

    AudioContext 渲染线程系统级音频回调驱动,该回调定期以固定的时间间隔触发。每次调用都有一个系统级音频回调缓冲区大小,这是一个可变的采样帧数,需要在下一个系统级音频回调到达之前计算完成。

    为每个系统级音频回调计算一个负载值(load value),计算方法是将执行持续时间除以(系统级音频回调缓冲区大小除以 sampleRate)。

    理想情况下,负载值低于 1.0,这意味着渲染音频所花费的时间少于播放它所需的时间。当负载值大于 1.0 时,会发生音频缓冲区欠载(audio buffer underrun):系统无法以足够快的速度渲染音频以实现实时播放。

    音频图的渲染量子大小不一定是系统级音频回调缓冲区大小的约数。这会导致音频延迟增加,并在不出现音频缓冲区欠载的情况下降低最大负载能力。

    请注意,系统级音频回调负载值的概念不适用于 OfflineAudioContext

    音频回调也被作为一项任务放入控制消息队列中。UA 必须执行以下算法来处理渲染量子,通过填充请求的缓冲区大小来完成此任务。除了控制消息队列外,每个 AudioContext 都有一个常规的任务队列,称为其关联任务队列,用于处理从控制线程发送到渲染线程的任务。在处理完渲染量子后,会执行额外的微任务检查点,以运行在 AudioWorkletProcessorprocess 方法执行期间可能已排入队列的任何微任务。

    所有从 AudioWorkletNode 发送的任务都会被放入其关联 BaseAudioContext关联任务队列中。

    在渲染循环开始之前,必须执行以下步骤。
    1. BaseAudioContext 的内部槽位 [[current frame]] 设置为 0。同时将 currentTime 设置为 0。

    渲染渲染量子时,必须执行以下步骤。
    1. render resultfalse

    2. 处理控制消息队列

      1. Qrendering 为一个空的控制消息队列原子地交换 Qrendering 与当前的控制消息队列

      2. Qrendering 中有消息时,执行以下步骤

        1. 执行 Qrendering最早消息的异步部分。

        2. 移除 Qrendering最早的消息

    3. 处理 BaseAudioContext关联任务队列

      1. task queueBaseAudioContext关联任务队列

      2. task counttask queue 中的任务数量

      3. task count 不等于 0 时,执行以下步骤

        1. oldest tasktask queue 中的第一个可运行任务,并将其从 task queue 中移除。

        2. 将渲染循环当前运行的任务设置为 oldest task

        3. 执行 oldest task 的步骤。

        4. 将渲染循环当前运行的任务设置回 null

        5. 递减 task count

        6. 执行微任务检查点。

    4. 处理一个渲染量子。

      1. 如果 BaseAudioContext[[rendering thread state]] 不是 running,则返回 false。

      2. 对要处理的 AudioNode 进行排序。

        1. ordered node list 为一个空的 AudioNodeAudioListener 列表。当此排序算法终止时,它将包含 AudioNodeAudioListener 的有序列表。

        2. nodes 为此 BaseAudioContext 创建且仍然存活的所有节点的集合。

        3. AudioListener 添加到 nodes 中。

        4. cycle breakers 为一个空的 DelayNode 集合。它将包含所有属于循环的 DelayNode

        5. 对于 nodes 中的每个 AudioNode node

          1. 如果 node 是一个属于循环的 DelayNode,将其添加到 cycle breakers 并从 nodes 中移除。

        6. 对于 cycle breakers 中的每个 DelayNode delay

          1. delayWriterdelayReader 分别为 delayDelayWriterDelayReader。将 delayWriterdelayReader 添加到 nodes。断开 delay 与其所有输入和输出的连接。

            注:这打破了循环:如果一个 DelayNode 处于循环中,它的两端可以分开考虑,因为在循环中延迟线不能小于一个渲染量子。

        7. 如果 nodes 包含循环,则静音所有属于此循环的 AudioNode,并将它们从 nodes 中移除。

        8. 认为 nodes 中的所有元素均为未标记。当 nodes 中存在未标记元素时

          1. nodes 中选择一个元素 node

          2. 访问 node

          访问节点 意味着执行以下步骤
          1. 如果 node 已被标记,则终止这些步骤。

          2. 标记 node

          3. 如果 node 是一个 AudioNode访问每个连接到 node 输入的 AudioNode

          4. 对于 node 的每个 AudioParam param

            1. 对于每个连接到 paramAudioNode param input node

              1. 访问 param input node

          5. node 添加到 ordered node list 的开头。

        9. 反转 ordered node list 的顺序。

      3. 计算此块中 AudioListenerAudioParam 的值。

      4. 对于 ordered node list 中的每个 AudioNode

        1. 对于此 AudioNode 的每个 AudioParam,执行以下步骤

          1. 如果此 AudioParam 连接有任何 AudioNode汇总所有连接到此 AudioParamAudioNode 可供读取的缓冲区,将结果缓冲区下混(down mix)为单声道,并将此缓冲区称为输入 AudioParam 缓冲区

          2. 计算此块中此 AudioParam 的值。

          3. 将控制消息加入队列,根据 § 1.6.3 数值计算设置此 AudioParam[[current value]] 槽位。

        2. 如果此 AudioNode 的输入连接有任何 AudioNode汇总所有连接到此 AudioNodeAudioNode 可供读取的缓冲区。结果缓冲区称为输入缓冲区上混或下混(Up or down-mix)它以匹配此 AudioNode 的输入通道数。

        3. 如果此 AudioNode 是一个源节点计算音频块,并使其可供读取

        4. 如果此 AudioNode 是一个 AudioWorkletNode,执行这些子步骤

          1. processorAudioWorkletNode 的关联 AudioWorkletProcessor 实例。

          2. O 为对应于 processor 的 ECMAScript 对象。

          3. processCallback 为一个未初始化的变量。

          4. completion 为一个未初始化的变量。

          5. 使用当前设置对象准备运行脚本

          6. 使用当前设置对象准备运行回调

          7. getResultGet(O, "process")。

          8. 如果 getResult 是一个突然完成(abrupt completion),将 completion 设置为 getResult 并跳转到标记为 return 的步骤。

          9. processCallback 设置为 getResult.[[Value]]。

          10. 如果 ! IsCallable(processCallback) 为 false,则

            1. completion 设置为新的 Completion {[[Type]]: throw, [[Value]]: 一个新创建的 TypeError 对象, [[Target]]: empty}。

            2. 跳转到标记为 return 的步骤。

          11. [[callable process]] 设置为 true

          12. 执行以下子步骤

            1. args 为一个 Web IDL 参数列表,由 inputsoutputsparameters 组成。

            2. esArgs 为将 args 转换为 ECMAScript 参数列表的结果。

            3. callResultCall(processCallback, O, esArgs)。此操作计算带有 esArgs 的音频块。函数调用成功后,包含通过 outputs 传递的 Float32Array 元素副本的缓冲区被使其可供读取。在此调用中解决的任何 Promise 都将排入 AudioWorkletGlobalScope 的微任务队列。

            4. 如果 callResult 是一个突然完成,将 completion 设置为 callResult 并跳转到标记为 return 的步骤。

            5. processor活动源标志设置为 ToBoolean(callResult.[[Value]])。

          13. 返回:此时 completion 将被设置为一个 ECMAScript 完成值。

            1. 使用当前设置对象清理运行回调后的环境

            2. 使用当前设置对象清理运行脚本后的环境

            3. 如果 completion 是一个突然完成

              1. [[callable process]] 设置为 false

              2. processor活动源标志设置为 false

              3. 使静默输出缓冲区可供读取.

              4. 将任务放入队列控制线程,以使用 ErrorEvent 在关联的 AudioWorkletNode触发一个事件,名称为 processorerror

        5. 如果此 AudioNode 是一个目标节点,则记录AudioNode 的输入。

        6. 否则,处理输入缓冲区,并使其可供读取结果缓冲区。

      5. 原子地执行以下步骤

        1. [[current frame]] 增加渲染量子大小

        2. currentTime 设置为 [[current frame]] 除以 sampleRate

      6. render result 设置为 true

    5. 执行微任务检查点.

    6. 返回 render result

    静音一个 AudioNode 意味着其输出在渲染此音频块时必须为静音。

    使缓冲区可供读取是指将缓冲区置于一种状态,使得其他连接到此 AudioNodeAudioNode 可以安全地从中读取数据。

    注:例如,实现可以选择分配一个新缓冲区,或者使用更复杂的机制,重用当前未使用的现有缓冲区。

    记录输入是指复制此 AudioNode 的输入数据以供将来使用。

    计算音频块是指运行此 AudioNode 的算法以产生 [[render quantum size]] 个采样帧。

    处理输入缓冲区是指运行 AudioNode 的算法,使用输入缓冲区和此 AudioNodeAudioParam 的值作为算法的输入。

    2.5. AudioContext 上处理系统音频资源错误

    AudioContext audioContext 在发生系统音频资源错误时,在渲染线程上执行以下步骤。

    1. 如果 audioContext[[rendering thread state]]running

      1. 尝试释放系统资源

      2. audioContext[[rendering thread state]] 设置为 suspended

      3. 将媒体元素任务放入队列以执行以下步骤

        1. audioContext触发一个事件,名称为 error

        2. audioContext[[suspended by user]] 设置为 false

        3. audioContext[[control thread state]] 设置为 suspended

        4. audioContextstate 属性设置为 "suspended"。

        5. audioContext触发一个事件,名称为 statechange

      4. 中止这些步骤。

    2. 如果 audioContext[[rendering thread state]]suspended

      1. 将媒体元素任务放入队列以执行以下步骤

        1. audioContext触发一个事件,名称为 error

    注:系统音频资源错误的一个例子是外部或无线音频设备在 AudioContext 活动渲染期间断开连接。

    2.6. 卸载文档

    对于使用 BaseAudioContext 的文档,定义了额外的卸载文档清理步骤
  • 对于相关全局对象与文档关联 Window 相同的每个 AudioContextOfflineAudioContext,以 InvalidStateError 拒绝其 [[pending promises]] 中的所有 Promise。

  • 停止所有 decoding thread

  • 将控制消息加入队列close() AudioContextOfflineAudioContext

  • 3. 动态生命周期

    3.1. 背景

    注:AudioContextAudioNode 生命周期特征的规范描述由 AudioContext 生命周期AudioNode 生命周期描述。

    本节是非规范性的。

    除了允许创建静态路由配置外,还应该能够对具有有限生命周期的动态分配的语音进行自定义效果路由。为了讨论的目的,我们称这些短生命周期的语音为“音符(notes)”。许多音频应用程序结合了音符的概念,例如鼓机、音序器以及根据游戏玩法触发许多一次性声音的 3D 游戏。

    在传统的软件合成器中,音符是从可用资源池中动态分配和释放的。当接收到 MIDI 音符开启消息时,音符被分配。当音符播放结束时,它会被释放,这可能是因为它已经达到了采样数据的结尾(如果是非循环的)、它已经达到了包络线的持续阶段(为零),或者由于 MIDI 音符关闭消息使其进入了包络线的释放阶段。在 MIDI 音符关闭的情况下,音符不会立即释放,只有在释放包络线阶段完成后才会释放。在任何给定时间,可能有大量的音符在播放,但音符集会不断变化,因为新的音符被添加到路由图中,而旧的音符被释放。

    音频系统会自动处理单个“音符”事件的路由图部分的拆除。“音符”由 AudioBufferSourceNode 表示,它可以直接连接到其他处理节点。当音符播放完成时,上下文会自动释放对 AudioBufferSourceNode 的引用,这反过来会释放对它连接的任何节点的引用,以此类推。这些节点将自动从图中断开,并在没有引用时被删除。图中长生命周期且在动态语音之间共享的节点可以明确管理。虽然听起来很复杂,但这都是自动发生的,不需要额外的处理。

    3.2. 示例

    dynamic allocation
    一个包含将提前释放的子图的图。

    低通滤波器、声相器和第二个增益节点直接从一次性声音连接。因此,当它播放完成时,上下文将自动释放它们(虚线内的所有内容)。如果不存任何对一次性声音和已连接节点的引用,它们将立即从图中删除并销毁。流源具有全局引用,并将保持连接,直到被明确断开。这是它在 JavaScript 中的样子

    let context = 0;let compressor = 0;let gainNode1 = 0;let streamingAudioSource = 0;// Initial setup of the "long-lived" part of the routing graphfunction setupAudioContext() {        context = new AudioContext();        compressor = context.createDynamicsCompressor();        gainNode1 = context.createGain();        // Create a streaming audio source.        const audioElement = document.getElementById('audioTagID');        streamingAudioSource = context.createMediaElementSource(audioElement);        streamingAudioSource.connect(gainNode1);        gainNode1.connect(compressor);        compressor.connect(context.destination);}// Later in response to some user action (typically mouse or key event)// a one-shot sound can be played.function playSound() {        const oneShotSound = context.createBufferSource();        oneShotSound.buffer = dogBarkingBuffer;        // Create a filter, panner, and gain node.        const lowpass = context.createBiquadFilter();        const panner = context.createPanner();        const gainNode2 = context.createGain();        // Make connections        oneShotSound.connect(lowpass);        lowpass.connect(panner);        panner.connect(gainNode2);        gainNode2.connect(compressor);        // Play 0.75 seconds from now (to play immediately pass in 0)        oneShotSound.start(context.currentTime + 0.75);}

    4. 通道上混和下混

    本节是规范性的。

    AudioNode 输入具有混合规则,用于组合来自所有连接的通道。作为一个简单的例子,如果输入连接了单声道输出和立体声输出,那么单声道连接通常会被上混为立体声并与立体声连接求和。但是,当然,定义每个 AudioNode 的每个输入的精确混合规则非常重要。所有输入的默认混合规则都是为了使内容“直接工作”而无需过多考虑细节,特别是在单声道和立体声流非常常见的情况下。当然,规则可以针对高级用例进行更改,特别是多通道用例。

    为了定义一些术语,上混(up-mixing) 是指将通道数较少的流转换为通道数较大的流的过程。下混(down-mixing) 是指将通道数较大的流转换为通道数较小的流的过程。

    AudioNode 输入需要混合连接到此输入的所有输出。作为此过程的一部分,它计算一个内部值 computedNumberOfChannels,代表输入在任何给定时间的实际通道数。

    对于 AudioNode 的每个输入,实现必须
  • 计算 computedNumberOfChannels

  • 对于每个输入连接

    1. 根据节点 channelInterpretation 属性给出的 ChannelInterpretation 值,将连接上混下混computedNumberOfChannels

    2. 将其与所有其他混合流(来自其他连接)混合在一起。这是将步骤 1 中为每个连接上混下混的相应通道直接求和。

  • 4.1. 扬声器通道布局

    channelInterpretation 为 "speakers" 时,上混下混是为特定通道布局定义的。

    必须支持单声道(一个通道)、立体声(两个通道)、四声道(四个通道)和 5.1(六个通道)。其他通道布局可能在未来的本规范版本中得到支持。

    4.2. 通道排序

    通道排序由下表定义。个别多通道格式可能不支持所有中间通道。实现必须按照定义的顺序呈现通道,跳过那些不存在的通道。

    顺序Label单声道立体声四声道5.1
    0 SPEAKER_FRONT_LEFT0 0 0 0
    1 SPEAKER_FRONT_RIGHT 1 1 1
    2 SPEAKER_FRONT_CENTER 2
    3 SPEAKER_LOW_FREQUENCY 3
    4 SPEAKER_BACK_LEFT 2 4
    5 SPEAKER_BACK_RIGHT 3 5
    6 SPEAKER_FRONT_LEFT_OF_CENTER
    7 SPEAKER_FRONT_RIGHT_OF_CENTER
    8 SPEAKER_BACK_CENTER
    9 SPEAKER_SIDE_LEFT
    10 SPEAKER_SIDE_RIGHT
    11 SPEAKER_TOP_CENTER
    12 SPEAKER_TOP_FRONT_LEFT
    13 SPEAKER_TOP_FRONT_CENTER
    14 SPEAKER_TOP_FRONT_RIGHT
    15 SPEAKER_TOP_BACK_LEFT
    16 SPEAKER_TOP_BACK_CENTER
    17 SPEAKER_TOP_BACK_RIGHT

    4.3. 尾部时间对输入和输出通道计数的影响

    AudioNode 具有非零 尾部时间(tail-time),且输出通道计数取决于输入通道计数时,在输入通道计数发生变化时,必须考虑 AudioNode尾部时间

    当输入通道计数减少时,输出通道计数的更改必须在以更大通道计数接收的输入不再影响输出时发生。

    当输入通道计数增加时,行为取决于 AudioNode 类型

    • 对于 DelayNodeDynamicsCompressorNode,当以更大通道计数接收的输入开始影响输出时,输出通道数必须增加。

    • 对于具有 尾部时间 的其他 AudioNode,输出通道数必须立即增加。

      注:对于 ConvolverNode,这仅适用于脉冲响应为单声道的情况。否则,无论其输入通道计数如何,ConvolverNode 始终输出立体声信号。

    注:直观地说,这允许在处理过程中不丢失立体声信息:当多个不同通道计数的输入渲染量子对输出渲染量子做出贡献时,输出渲染量子的通道计数是输入渲染量子输入通道计数的超集。

    4.4. 上混扬声器布局

    Mono up-mix:
    
        1 -> 2 : up-mix from mono to stereo
            output.L = input;
            output.R = input;
    
        1 -> 4 : up-mix from mono to quad
            output.L = input;
            output.R = input;
            output.SL = 0;
            output.SR = 0;
    
        1 -> 5.1 : up-mix from mono to 5.1
            output.L = 0;
            output.R = 0;
            output.C = input; // put in center channel
            output.LFE = 0;
            output.SL = 0;
            output.SR = 0;
    
    Stereo up-mix:
    
        2 -> 4 : up-mix from stereo to quad
            output.L = input.L;
            output.R = input.R;
            output.SL = 0;
            output.SR = 0;
    
        2 -> 5.1 : up-mix from stereo to 5.1
            output.L = input.L;
            output.R = input.R;
            output.C = 0;
            output.LFE = 0;
            output.SL = 0;
            output.SR = 0;
    
    Quad up-mix:
    
        4 -> 5.1 : up-mix from quad to 5.1
            output.L = input.L;
            output.R = input.R;
            output.C = 0;
            output.LFE = 0;
            output.SL = input.SL;
            output.SR = input.SR;
    

    4.5. 下混扬声器布局

    例如,如果正在处理 5.1 源材料,但播放为立体声,则需要进行下混。

    Mono down-mix:
    
        2 -> 1 : stereo to mono
            output = 0.5 * (input.L + input.R);
    
        4 -> 1 : quad to mono
            output = 0.25 * (input.L + input.R + input.SL + input.SR);
    
        5.1 -> 1 : 5.1 to mono
            output = sqrt(0.5) * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
    
    Stereo down-mix:
    
        4 -> 2 : quad to stereo
            output.L = 0.5 * (input.L + input.SL);
            output.R = 0.5 * (input.R + input.SR);
    
        5.1 -> 2 : 5.1 to stereo
            output.L = L + sqrt(0.5) * (input.C + input.SL)
            output.R = R + sqrt(0.5) * (input.C + input.SR)
    
    Quad down-mix:
    
        5.1 -> 4 : 5.1 to quad
            output.L = L + sqrt(0.5) * input.C
            output.R = R + sqrt(0.5) * input.C
            output.SL = input.SL
            output.SR = input.SR
    

    4.6. 通道规则示例

    // Set gain node to explicit 2-channels (stereo).gain.channelCount = 2;gain.channelCountMode = "explicit";gain.channelInterpretation = "speakers";// Set "hardware output" to 4-channels for DJ-app with two stereo output busses.context.destination.channelCount = 4;context.destination.channelCountMode = "explicit";context.destination.channelInterpretation = "discrete";// Set "hardware output" to 8-channels for custom multi-channel speaker array// with custom matrix mixing.context.destination.channelCount = 8;context.destination.channelCountMode = "explicit";context.destination.channelInterpretation = "discrete";// Set "hardware output" to 5.1 to play an HTMLAudioElement.context.destination.channelCount = 6;context.destination.channelCountMode = "explicit";context.destination.channelInterpretation = "speakers";// Explicitly down-mix to mono.gain.channelCount = 1;gain.channelCountMode = "explicit";gain.channelInterpretation = "speakers";

    5. 音频信号值

    5.1. 音频采样格式

    线性脉冲编码调制(线性 PCM)描述了一种格式,其中音频值以规则的时间间隔采样,并且两个连续值之间的量化级别是线性均匀的。

    每当在本规范中向脚本公开信号值时,它们都是线性 32 位浮点脉冲编码调制格式(线性 32 位浮点 PCM),通常以 Float32Array 对象的形式。

    5.2. 渲染

    任何音频图目标节点处所有音频信号的范围名义上为 [-1, 1]。此范围之外的信号值的音频再现,或值 NaN、正无穷大或负无穷大的音频再现,在本规范中是未定义的。

    6. 空间化/声相定位

    6.1. 背景

    现代 3D 游戏的一个常见特性需求是能够动态地对 3D 空间中的多个音频源进行空间化和移动。例如 OpenAL 就具备这种能力。

    使用 PannerNode,音频流可以相对于 AudioListener 进行空间化或定位。BaseAudioContext 将包含单个 AudioListener。声相器和监听器在 3D 空间中都有位置,使用右手笛卡尔坐标系。坐标系中使用的单位未定义,也不需要定义,因为使用这些坐标计算的效果独立于或不变量于任何特定单位(如米或英尺)。PannerNode 对象(代表源流)有一个方向向量,表示声音投影的方向。此外,它们有一个声音锥体,表示声音的方向性。例如,声音可以是全向的,在这种情况下,无论其方向如何,都可以在任何地方听到,或者它可以更具方向性,仅当面向监听器时才能听到。AudioListener 对象(代表人的耳朵)具有前向上向向量,表示人面对的方向。

    空间化的坐标系如下图所示,显示了默认值。AudioListenerPannerNode 的位置已从默认位置移动,以便我们可以更清楚地看到。

    panner-coord
    坐标系图,显示了 AudioListener 和 PannerNode 属性。

    在渲染期间,PannerNode 计算方位角仰角。这些值由实现内部使用,以便渲染空间化效果。有关这些值如何使用的详细信息,请参阅声相定位算法部分。

    6.2. 方位角和仰角

    必须使用以下算法来计算 PannerNode方位角仰角。实现必须适当地考虑下方的各个 AudioParam 是 "a-rate" 还是 "k-rate"。

    // Let |context| be a BaseAudioContext and let |panner| be a// PannerNode created in |context|.// Calculate the source-listener vector.const listener = context.listener;const sourcePosition = new Vec3(panner.positionX.value, panner.positionY.value,                                panner.positionZ.value);const listenerPosition =    new Vec3(listener.positionX.value, listener.positionY.value,             listener.positionZ.value);const sourceListener = sourcePosition.diff(listenerPosition).normalize();if (sourceListener.magnitude == 0) {  // Handle degenerate case if source and listener are at the same point.  azimuth = 0;  elevation = 0;  return;}// Align axes.const listenerForward = new Vec3(listener.forwardX.value, listener.forwardY.value,                                 listener.forwardZ.value);const listenerUp =    new Vec3(listener.upX.value, listener.upY.value, listener.upZ.value);const listenerRight = listenerForward.cross(listenerUp);if (listenerRight.magnitude == 0) {  // Handle the case where listener's 'up' and 'forward' vectors are linearly  // dependent, in which case 'right' cannot be determined  azimuth = 0;  elevation = 0;  return;}// Determine a unit vector orthogonal to listener's right, forwardconst listenerRightNorm = listenerRight.normalize();const listenerForwardNorm = listenerForward.normalize();const up = listenerRightNorm.cross(listenerForwardNorm);const upProjection = sourceListener.dot(up);const projectedSource = sourceListener.diff(up.scale(upProjection)).normalize();azimuth = 180 * Math.acos(projectedSource.dot(listenerRightNorm)) / Math.PI;// Source in front or behind the listener.const frontBack = projectedSource.dot(listenerForwardNorm);if (frontBack < 0)  azimuth = 360 - azimuth;// Make azimuth relative to "forward" and not "right" listener vector.if ((azimuth >= 0) && (azimuth <= 270))  azimuth = 90 - azimuth;else  azimuth = 450 - azimuth;elevation = 90 - 180 * Math.acos(sourceListener.dot(up)) / Math.PI;if (elevation > 90)  elevation = 180 - elevation;else if (elevation < -90)  elevation = -180 - elevation;

    6.3. 声相定位算法

    必须支持单声道转立体声立体声转立体声声相定位。当输入的所有连接都是单声道时,使用单声道转立体声处理。否则,使用立体声转立体声处理。

    6.3.1. PannerNode "equalpower" 声相定位

    这是一种简单且相对便宜的算法,它提供了基本但合理的结果。当 panningModel 属性设置为 "equalpower" 时,它用于 PannerNode,此时仰角值被忽略。此算法必须使用 automationRate 指定的适当速率来实现。如果 PannerNode 的任何 AudioParamAudioListenerAudioParam 是 "a-rate",则必须使用 a-rate 处理。

    1. 对于此 AudioNode 要计算的每个采样

      1. azimuth 为在方位角和仰角部分计算的值。

      2. azimuth 值首先被限制在范围 [-90, 90] 内,根据

        // First, clamp azimuth to allowed range of [-180, 180].
        azimuth = max(-180, azimuth);
        azimuth = min(180, azimuth);
        
        // Then wrap to range [-90, 90].
        if (azimuth < -90)
            azimuth = -180 - azimuth;
        else if (azimuth > 90)
            azimuth = 180 - azimuth;
        
      3. 归一化值 xazimuth 计算得到,对于单声道输入为

        x = (azimuth + 90) / 180;
        

        或者对于立体声输入为

        if (azimuth <= 0) { // -90 -> 0
            // Transform the azimuth value from [-90, 0] degrees into the range [-90, 90].
            x = (azimuth + 90) / 90;
        } else { // 0 -> 90
            // Transform the azimuth value from [0, 90] degrees into the range [-90, 90].
            x = azimuth / 90;
        }
        
      4. 左右增益值计算为

        gainL = cos(x * Math.PI / 2);
        gainR = sin(x * Math.PI / 2);
        
      5. 对于单声道输入,立体声输出计算为

        outputL = input * gainL;
        outputR = input * gainR;
        

        否则对于立体声输入,输出计算为

        if (azimuth <= 0) {
            outputL = inputL + inputR * gainL;
            outputR = inputR * gainR;
        } else {
            outputL = inputL * gainL;
            outputR = inputR + inputL * gainR;
        }
        
      6. 应用距离增益和锥体增益,其中距离计算在 距离效果 中描述,锥体增益在 声音锥体 中描述

        let distance = distance();
        let distanceGain = distanceModel(distance);
        let totalGain = coneGain() * distanceGain();
        outputL = totalGain * outputL;
        outputR = totalGain * outputR;
        

    6.3.2. PannerNode "HRTF" 声相定位(仅限立体声)

    这需要一套在各种方位角和仰角下记录的 HRTF(头相关传递函数)脉冲响应。实现需要一个高度优化的卷积函数。它比 "equalpower" 成本稍高,但提供了感知上更空间化的声音。

    显示使用 HRTF 进行声相定位源的过程图。

    6.3.3. StereoPannerNode 声相定位

    对于 StereoPannerNode,必须实现以下算法。
  • 对于此 AudioNode 要计算的每个采样

    1. pan 为此 StereoPannerNodepan AudioParam计算值

    2. pan 钳位到 [-1, 1]。

      pan = max(-1, pan);
      pan = min(1, pan);
      
    3. 通过将 pan 值归一化到 [0, 1] 来计算 x。对于单声道输入

      x = (pan + 1) / 2;
      

      对于立体声输入

      if (pan <= 0)
          x = pan + 1;
      else
          x = pan;
      
    4. 左右增益值计算为

      gainL = cos(x * Math.PI / 2);
      gainR = sin(x * Math.PI / 2);
      
    5. 对于单声道输入,立体声输出计算为

      outputL = input * gainL;
      outputR = input * gainR;
      

      否则对于立体声输入,输出计算为

      if (pan <= 0) {
          outputL = inputL + inputR * gainL;
          outputR = inputR * gainR;
      } else {
          outputL = inputL * gainL;
          outputR = inputR + inputL * gainR;
      }
      
  • 6.4. 距离效果

    较近的声音声音较大,而较远的声音声音较小。声音的音量随与监听器距离的变化而如何变化,取决于 distanceModel 属性。

    在音频渲染期间,将基于声相器和监听器位置计算距离值,根据

    function distance(panner) {  const pannerPosition = new Vec3(panner.positionX.value, panner.positionY.value,                                  panner.positionZ.value);  const listener = context.listener;  const listenerPosition =      new Vec3(listener.positionX.value, listener.positionY.value,               listener.positionZ.value);  return pannerPosition.diff(listenerPosition).magnitude;}

    距离随后将用于计算 distanceGain,这取决于 distanceModel 属性。有关如何为每个距离模型计算此值的详细信息,请参阅 DistanceModelType 部分。

    作为其处理的一部分,PannerNode 将输入音频信号乘以 distanceGain,以使远处的声音更安静,近处的声音更大。

    6.5. 声音锥体

    监听器和每个声源都有一个方向向量,描述它们面对的方向。每个声源的声音投影特性由内部和外部“锥体”描述,描述声音强度作为声源/监听器相对于声源方向向量的角度的函数。因此,指向监听器的声源将比偏轴指向的声音更大。声源也可以是全向的。

    下图说明了声源锥体与监听器的关系。在图中,coneInnerAngle = 50coneOuterAngle = 120。也就是说,内部锥体在方向向量的每一侧延伸 25 度。类似地,外部锥体在每一侧为 60 度。

    cone-diagram
    声源的锥体角度与声源方向以及监听器位置和方向的关系。

    在给定声源(PannerNode)和监听器的情况下,必须使用以下算法来计算由于锥体效果产生的增益贡献

    function coneGain() {  const sourceOrientation =      new Vec3(source.orientationX, source.orientationY, source.orientationZ);  if (sourceOrientation.magnitude == 0 ||      ((source.coneInnerAngle == 360) && (source.coneOuterAngle == 360)))    return 1; // no cone specified - unity gain  // Normalized source-listener vector  const sourcePosition = new Vec3(panner.positionX.value, panner.positionY.value,                                  panner.positionZ.value);  const listenerPosition =      new Vec3(listener.positionX.value, listener.positionY.value,               listener.positionZ.value);  const sourceToListener = sourcePosition.diff(listenerPosition).normalize();  const normalizedSourceOrientation = sourceOrientation.normalize();  // Angle between the source orientation vector and the source-listener vector  const angle = 180 *                Math.acos(sourceToListener.dot(normalizedSourceOrientation)) /                Math.PI;  const absAngle = Math.abs(angle);  // Divide by 2 here since API is entire angle (not half-angle)  const absInnerAngle = Math.abs(source.coneInnerAngle) / 2;  const absOuterAngle = Math.abs(source.coneOuterAngle) / 2;  let gain = 1;  if (absAngle <= absInnerAngle) {    // No attenuation    gain = 1;  } else if (absAngle >= absOuterAngle) {    // Max attenuation    gain = source.coneOuterGain;  } else {    // Between inner and outer cones    // inner -> outer, x goes from 0 -> 1    const x = (absAngle - absInnerAngle) / (absOuterAngle - absInnerAngle);    gain = (1 - x) + source.coneOuterGain * x;  }  return gain;}

    7. 性能注意事项

    7.1. 延迟

    latency
    延迟可能重要的用例

    对于 Web 应用程序,鼠标和键盘事件(keydown、mousedown 等)与听到声音之间的时间延迟非常重要。

    这种时间延迟称为延迟,并由多种因素引起(输入设备延迟、内部缓冲延迟、DSP 处理延迟、输出设备延迟、用户耳朵与扬声器的距离等),并且是累积的。延迟越大,用户的体验就越不令人满意。在极端情况下,这会使音乐制作或游戏无法进行。在适度水平下,它会影响时机,并给人一种声音滞后或游戏无响应的印象。对于音乐应用程序,时机问题会影响节奏。对于游戏,时机问题会影响游戏玩法的精度。对于交互式应用程序,它通常以与非常低的动画帧率相同的方式降低用户体验。根据应用程序的不同,合理的延迟可以从低至 3-6 毫秒到 25-50 毫秒不等。

    实现通常会寻求最小化整体延迟。

    除了最小化整体延迟外,实现通常还会寻求最小化 AudioContextcurrentTimeAudioProcessingEventplaybackTime 之间的差异。随着 ScriptProcessorNode 的弃用,这一考虑将随时间变得不再那么重要。

    此外,一些 AudioNode 可以在音频图的某些路径中增加延迟,特别是

    7.2. 音频缓冲区复制

    当对 AudioBuffer 执行获取内容操作时,整个操作通常可以在不复制通道数据的情况下实现。特别是,最后一步应该在下一次 getChannelData() 调用时惰性执行。这意味着一系列连续的获取内容操作,且中间没有 getChannelData()(例如,多个播放相同 AudioBufferAudioBufferSourceNode),可以在没有任何分配或复制的情况下实现。

    实现可以执行额外的优化:如果在 AudioBuffer 上调用了 getChannelData(),新的 ArrayBuffer 尚未分配,但对 AudioBuffer 上先前获取内容操作的所有调用者都已经停止使用 AudioBuffer 的数据,原始数据缓冲区可以被循环利用以用于新的 AudioBuffer,从而避免任何通道数据的重新分配或复制。

    7.3. AudioParam 转换

    虽然直接设置 AudioParamvalue 属性时不会进行自动平滑处理,但对于某些参数,平滑转换优于直接设置值。

    使用 setTargetAtTime() 方法并配合较小的 timeConstant,允许作者实现平滑的过渡。

    7.4. 音频故障(Audio Glitching)

    音频故障是由连续音频流的正常中断引起的,会导致响亮的咔嗒声和爆音。这被认为是多媒体系统的灾难性故障,必须避免。它可能是由于负责将音频流传送到硬件的线程出现问题所致,例如由于线程缺乏适当的优先级和时间约束而导致的调度延迟。它也可能是由音频 DSP 尝试执行的工作超出了 CPU 速度在实时环境下所能处理的限度所引起。

    8. 安全与隐私考量

    根据 自评问卷:安全与隐私 § 问题

    1. 本规范是否处理个人身份信息?

      使用 Web Audio API 执行听力测试是可能的,从而揭示一个人可听到的频率范围(这会随年龄增长而降低)。很难想象如何在用户不知情且未经同意的情况下做到这一点,因为它需要用户的积极参与。

    2. 本规范是否处理高价值数据?

      否。Web Audio 中不使用信用卡信息等类似信息。虽然可以使用 Web Audio 处理或分析语音数据,这可能涉及隐私问题,但对用户麦克风的访问是通过 getUserMedia() 基于权限的。

    3. 本规范是否为跨浏览会话持久化的源引入了新状态?

      否。AudioWorklet 不会在浏览会话间持久化。

    4. 本规范是否向 Web 暴露了持久的、跨源的状态?

      是,支持的音频采样率和输出设备通道数是公开的。请参阅 AudioContext

    5. 本规范是否向一个源暴露了它目前无法访问的其他数据?

      是。在提供有关可用 AudioNode 的各种信息时,Web Audio API 可能会向任何使用 AudioNode 接口的页面暴露有关客户端特征(例如音频硬件采样率)的信息。此外,可以通过 AnalyserNodeScriptProcessorNode 接口收集计时信息。这些信息随后可用于创建客户端的指纹。

      普林斯顿 CITP 的 Web 透明度和问责项目 的研究表明,DynamicsCompressorNodeOscillatorNode 可用于从客户端收集熵以对设备进行指纹识别。这是由于不同实现之间在 DSP 架构、重采样策略和舍入权衡方面存在微小且通常无法察觉的差异。使用的精确编译器标志以及 CPU 架构(ARM 与 x86)也对此熵有贡献。

      然而在实践中,这仅仅允许推导出可以通过更简单方式(User Agent 字符串)轻松获取的信息,例如“这是在平台 Y 上运行的浏览器 X”。但是,为了减少额外指纹识别的可能性,我们要求浏览器采取行动,减轻可能由任何节点输出产生的指纹识别问题。

      通过时钟偏差进行的指纹识别 已被 Steven J Murdoch 和 Sebastian Zander 描述过。可能可以通过 getOutputTimestamp 确定这一点。基于偏差的指纹识别也已由 Nakibly 等人针对 HTML 展示过。应查阅 高精度时间 § 10. 隐私考量 部分,以获取有关时钟分辨率和漂移的更多信息。

      通过延迟进行指纹识别也是可能的;可能可以通过 baseLatencyoutputLatency 推断出来。缓解策略包括添加抖动(dithering)和量化,使得精确的偏差被错误报告。但请注意,大多数音频系统旨在实现 低延迟,以将 WebAudio 生成的音频与其他音频或视频源或视觉提示同步(例如在游戏、音频录制或音乐制作环境中)。过高的延迟会降低可用性,并可能成为一个可访问性问题。

      通过 AudioContext 的采样率进行指纹识别也是可能的。我们建议采取以下步骤将其最小化

      1. 44.1 kHz 和 48 kHz 被允许作为默认速率;系统将在两者之间选择以获得最佳适用性。(显然,如果音频设备原生为 44.1,则会选择 44.1,以此类推,但系统也可能选择最“兼容”的速率——例如,如果系统原生为 96kHz,则可能会选择 48kHz 而不是 44.1kHz。)

      2. 对于原生处于不同速率的设备,系统应重采样到这两个速率之一,尽管由于重采样音频,这可能会导致额外的电池消耗。(同样,系统将选择最兼容的速率——例如,如果原生系统为 16kHz,预计会选择 48kHz。)

      3. 预计(尽管不是强制性的)浏览器将提供用户界面供用户强制使用原生速率——例如通过在设备上的浏览器中设置标志。此设置不会在 API 中暴露。

      4. 期望的行为是可以在 AudioContext 的构造函数中明确请求不同的速率(这已经在规范中;它通常会导致音频渲染以请求的 sampleRate 完成,然后向上或向下采样到设备输出),并且如果该速率得到原生支持,则渲染可以直接通过。这将使应用程序能够无需用户干预即可渲染到更高的速率(尽管从 Web Audio 中无法观察到音频输出未在输出时进行下采样)——例如,如果 MediaDevices 功能被读取(经用户干预)并表明支持更高的速率。

      通过 AudioContext 的输出通道数进行指纹识别也是可能的。我们建议将 maxChannelCount 设置为二(立体声)。立体声是迄今为止最常见的通道数。

    6. 本规范是否启用了新的脚本执行/加载机制?

      否。它确实使用了该规范中定义的 [HTML] 脚本执行方法。

    7. 本规范是否允许源访问用户位置?

      不。

    8. 本规范是否允许源访问用户设备上的传感器?

      不直接。目前,本文件中未指定音频输入,但它将涉及获得对客户端机器音频输入或麦克风的访问权限。这将需要以适当的方式征求用户许可,可能通过 getUserMedia() API。

      此外,应注意 媒体捕获与流(Media Capture and Streams) 规范中的安全与隐私考量。特别是,对环境音频的分析或播放独特的音频可能使识别用户位置精确到房间级别,甚至可能识别不同用户或设备同时占用一个房间的情况。对音频输出和音频输入的访问也可能使一个浏览器中原本隔离的上下文之间能够进行通信。

    9. 本规范是否允许源访问用户本地计算环境的各个方面?

      不直接;所有请求的采样率均受支持,并在必要时进行向上采样。可以使用媒体捕获与流来探测支持的音频采样率,使用 MediaTrackSupportedConstraints。这需要明确的用户同意。这确实提供了一种小规模的指纹识别手段。然而,在实践中,大多数消费级和准专业级设备使用两种标准化采样率中的一种:44.1kHz(最初由 CD 使用)和 48kHz(最初由 DAT 使用)。资源高度受限的设备可能支持语音质量的 11kHz 采样率,高端设备通常支持 88.2、96 或甚至发烧级的 192kHz 速率。

      要求所有实现都向上采样到单一的、普遍支持的速率(如 48kHz)会增加 CPU 开销却没有任何特殊好处,而要求高端设备使用较低速率只会导致 Web Audio 被贴上不适合专业用途的标签。

    10. 本规范是否允许源访问其他设备?

      它通常不允许访问其他联网设备(高端录音室中的一个例外可能是 Dante 网络设备,尽管它们通常使用单独的专用网络)。它必然允许访问用户的音频输出设备,这些设备有时是与计算机分开的单元。

      对于声控设备,Web Audio API 可能被用于控制其他设备。此外,如果声音驱动的设备对近超声波频率敏感,这种控制可能是无法听到的。这种可能性在 HTML 中也存在,通过 <audio> 或 <video> 元素。在常见的音频采样率下,(按设计)没有足够的余量来包含太多超声波信息。

      人类听力的极限通常表述为 20kHz。对于 44.1kHz 的采样率,奈奎斯特极限为 22.05kHz。鉴于真正的砖墙滤波器无法物理实现,20kHz 和 22.05kHz 之间的空间用于快速滚降滤波器,以强烈衰减所有高于奈奎斯特频率的频率。

      在 48kHz 采样率下,20kHz 到 24kHz 频带内仍然存在快速衰减(但更容易避免通带中的相位纹波误差)。

    11. 本规范是否允许源对用户代理的原生 UI 有一定程度的控制?

      如果 UI 具有音频组件,例如语音助手或屏幕阅读器,Web Audio API 可能会被用于模拟本地 UI 的某些方面,使攻击看起来更像是本地系统事件。这种可能性也存在于 HTML 中,通过 <audio> 元素。

    12. 本规范是否向 Web 暴露临时标识符?

      不。

    13. 本规范是否区分第一方和第三方上下文中的行为?

      不。

    14. 本规范应如何在用户代理的“隐身”模式上下文中工作?

      没有区别。

    15. 本规范是否将数据持久化到用户的本地设备?

      不。

    16. 本规范是否有“安全考虑”和“隐私考虑”部分?

      是的(你正在阅读它)。

    17. 本规范是否允许降低默认安全特性?

      不。

    9. 需求与用例

    请参阅 [webaudio-usecases]

    10. 规范代码的通用定义

    本节描述了本规范中使用的 JavaScript 代码所采用的通用函数和类。

    // Three dimensional vector class.class Vec3 {    // Construct from 3 coordinates.    constructor(x, y, z) {        this.x = x;        this.y = y;        this.z = z;    }    // Dot product with another vector.    dot(v) {        return (this.x * v.x) + (this.y * v.y) + (this.z * v.z);    }    // Cross product with another vector.    cross(v) {        return new Vec3((this.y * v.z) - (this.z * v.y),            (this.z * v.x) - (this.x * v.z),            (this.x * v.y) - (this.y * v.x));    }    // Difference with another vector.    diff(v) {        return new Vec3(this.x - v.x, this.y - v.y, this.z - v.z);    }    // Get the magnitude of this vector.    get magnitude() {        return Math.sqrt(dot(this));    }    // Get a copy of this vector multiplied by a scalar.    scale(s) {        return new Vec3(this.x * s, this.y * s, this.z * s);    }    // Get a normalized copy of this vector.    normalize() {        const m = magnitude;        if (m == 0) {            return new Vec3(0, 0, 0);        }        return scale(1 / m);    }}

    11. 更新日志

    12. 致谢

    本规范是 W3C 音频工作组 的集体成果。

    工作组成员、前成员及本规范贡献者包括(按撰写时字母顺序排列):
    Adenot, Paul (Mozilla Foundation) - 规范共同编辑;Akhgari, Ehsan (Mozilla Foundation);Becker, Steven (Microsoft Corporation);Berkovitz, Joe (受邀专家,隶属于 Noteflight/Hal Leonard) - 2013 年 9 月至 2017 年 12 月任工作组共同主席;Bossart, Pierre (Intel Corporation);Borins, Myles (Google, Inc);Buffa, Michel (NSAU);Caceres, Marcos (受邀专家);Cardoso, Gabriel (INRIA);Carlson, Eric (Apple, Inc);Chen, Bin (Baidu, Inc);Choi, Hongchan (Google, Inc) - 规范共同编辑;Collichio, Lisa (Qualcomm);Geelnard, Marcus (Opera Software);Gehring, Todd (Dolby Laboratories);Goode, Adam (Google, Inc);Gregan, Matthew (Mozilla Foundation);Hikawa, Kazuo (AMEI);Hofmann, Bill (Dolby Laboratories);Jägenstedt, Philip (Google, Inc);Jeong, Paul Changjin (HTML5 融合技术论坛);Kalliokoski, Jussi (受邀专家);Lee, WonSuk (电子通信研究院);Kakishita, Masahiro (AMEI);Kawai, Ryoya (AMEI);Kostiainen, Anssi (Intel Corporation);Lilley, Chris (W3C 工作人员);Lowis, Chris (受邀专家) - 2012 年 12 月至 2013 年 9 月任工作组共同主席,隶属于英国广播公司 (BBC);MacDonald, Alistair (W3C 受邀专家) — 2011 年 3 月至 2012 年 7 月任工作组共同主席;Mandyam, Giridhar (Qualcomm Innovation Center, Inc);Michel, Thierry (W3C/ERCIM);Nair, Varun (Facebook);Needham, Chris (英国广播公司);Noble, Jer (Apple, Inc);O’Callahan, Robert (Mozilla Foundation);Onumonu, Anthony (英国广播公司);Paradis, Matthew (英国广播公司) - 2013 年 9 月至今任工作组共同主席;Pozdnyakov, Mikhail (Intel Corporation);Raman, T.V. (Google, Inc);Rogers, Chris (Google, Inc);Schepers, Doug (W3C/MIT);Schmitz, Alexander (JS Foundation);Shires, Glen (Google, Inc);Smith, Jerry (Microsoft Corporation);Smith, Michael (W3C/Keio);Thereaux, Olivier (英国广播公司);Toy, Raymond (Google, Inc.) - 2017 年 12 月至今任工作组共同主席;Toyoshima, Takashi (Google, Inc);Troncy, Raphael (Institut Telecom);Verdie, Jean-Charles (MStar Semiconductor, Inc.);Wei, James (Intel Corporation);Weitnauer, Michael (IRT);Wilson, Chris (Google, Inc);Zergaoui, Mohamed (INNOVIMAX)

    一致性

    文档约定

    一致性要求通过描述性断言和 RFC 2119 术语相结合来表达。本文档规范性部分中的关键词“MUST”(必须)、“MUST NOT”(不得)、“REQUIRED”(必需)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(推荐)、“SHOULD NOT”(不推荐)、“RECOMMENDED”(建议)、“MAY”(可以)和“OPTIONAL”(可选)应按照 RFC 2119 中的描述进行解释。然而,为了可读性,这些词在本文档中不以全大写形式出现。

    本规范的所有文本均为规范性文本,明确标记为非规范性的部分、示例和注释除外。 [RFC2119]

    本规范中的示例均以“例如”一词引入,或者通过 class="example" 与规范性文本隔开,如下所示

    这是一个说明性示例。

    说明性注释以“Note”一词开头,并使用 class="note" 与规范性文本隔开,如下所示

    注意,这是一个说明性注释。

    一致性算法

    作为算法一部分的祈使语气要求(例如“去除任何前导空格字符”或“返回 false 并中止这些步骤”)应根据引入算法时使用的关键词(“必须”、“应该”、“可以”等)进行解释。

    以算法或具体步骤表述的一致性要求可以用任何方式实现,只要最终结果等效即可。特别地,本规范定义的算法旨在易于理解,而不旨在提高性能。鼓励实现者进行优化。

    索引

    本规范定义的术语

  • channelCountMode 约束(channelCountMode constraints), 位于 § 1.5.4
  • ChannelInterpretation, 位于 § 1.5.1
  • channelInterpretation
  • AudioNode 的属性(attribute for AudioNode), 位于 § 1.5.4
  • AudioNodeOptions 的字典成员(dict-member for AudioNodeOptions), 位于 § 1.5.6.1
  • channelInterpretation 约束(channelInterpretation constraints), 位于 § 1.5.4
  • ChannelMergerNode, 位于 § 1.13.5
  • ChannelMergerNode(context), 位于 § 1.14.1
  • ChannelMergerNode(context, options), 位于 § 1.14.1
  • ChannelMergerOptions, 位于 § 1.14.1
  • ChannelSplitterNode, 位于 § 1.14.2.1
  • ChannelSplitterNode(context), 位于 § 1.15.1
  • ChannelSplitterNode(context, options), 位于 § 1.15.1
  • ChannelSplitterOptions, 位于 § 1.15.1
  • "clamped-max", 位于 § 1.5.1
  • clamped-max, 位于 § 1.5.1
  • close(), 位于 § 1.2.3
  • "closed", 位于 § 1.1
  • closed, 位于 § 1.1
  • complete, 位于 § 1.3.2
  • 复合参数(compound parameter), 位于 § 1.6.3
  • 压缩曲线(compression curve), 位于 § 1.19.4
  • [[compressor gain]], 位于 § 1.19.4
  • computedFrequency, 位于 § 1.13
  • computedNumberOfChannels, 位于 § 1.5.1
  • computedOscFrequency, 位于 § 1.26
  • computedPlaybackRate, 位于 § 1.9
  • computedValue, 位于 § 1.6.3
  • 计算音频块(Computing a block of audio), 位于 § 2.4
  • 计算包络速率(Computing the envelope rate), 位于 § 1.19.4
  • 计算补偿增益(Computing the makeup gain), 位于 § 1.19.4
  • coneInnerAngle
  • coneOuterAngle
  • coneOuterGain
  • connect(destinationNode), 位于 § 1.5.5
  • connect(destinationNode, output), 位于 § 1.5.5
  • connect(destinationNode, output, input), 位于 § 1.5.5
  • connect(destinationParam), 位于 § 1.5.5
  • connect(destinationParam, output), 位于 § 1.5.5
  • 连接(connection), 位于 § 1.5
  • ConstantSourceNode, 位于 § 1.15.2.1
  • ConstantSourceNode(context), 位于 § 1.16.1
  • ConstantSourceNode(context, options), 位于 § 1.16.1
  • ConstantSourceOptions, 位于 § 1.16.2
  • constructor()
  • constructor(context)
  • constructor(context, name), 位于 § 1.32.4.1
  • constructor(context, name, options), 位于 § 1.32.4.1
  • constructor(context, options)
  • constructor(contextOptions)
  • constructor(numberOfChannels, length, sampleRate), 位于 § 1.3.1
  • constructor(options), 位于 § 1.4.1
  • constructor(type), 位于 § 1.2.11
  • constructor(type, eventInitDict)
  • context, 位于 § 1.5.4
  • contextTime, 位于 § 1.2.8.1
  • 控制消息(control message), 位于 § 2.2
  • 控制消息队列(control message queue), 位于 § 2.2
  • 控制线程(control thread), 位于 § 2.2
  • [[control thread state]], 位于 § 1.1
  • 转换为 dB(Conversion to dB), 位于 § 1.8.6
  • ConvolverNode, 位于 § 1.16.3.1
  • ConvolverNode(context), 位于 § 1.17.1
  • ConvolverNode(context, options), 位于 § 1.17.1
  • ConvolverOptions, 位于 § 1.17.2
  • copyFromChannel(destination, channelNumber), 位于 § 1.4.3
  • copyFromChannel(destination, channelNumber, bufferOffset), 位于 § 1.4.3
  • copyToChannel(source, channelNumber), 位于 § 1.4.3
  • copyToChannel(source, channelNumber, bufferOffset), 位于 § 1.4.3
  • createAnalyser(), 位于 § 1.1.2
  • createBiquadFilter(), 位于 § 1.1.2
  • createBuffer(numberOfChannels, length, sampleRate), 位于 § 1.1.2
  • createBufferSource(), 位于 § 1.1.2
  • createChannelMerger(), 位于 § 1.1.2
  • createChannelMerger(numberOfInputs), 位于 § 1.1.2
  • createChannelSplitter(), 位于 § 1.1.2
  • createChannelSplitter(numberOfOutputs), 位于 § 1.1.2
  • createConstantSource(), 位于 § 1.1.2
  • createConvolver(), 位于 § 1.1.2
  • createDelay(), 位于 § 1.1.2
  • createDelay(maxDelayTime), 位于 § 1.1.2
  • createDynamicsCompressor(), 位于 § 1.1.2
  • createGain(), 位于 § 1.1.2
  • createIIRFilter(feedforward, feedback), 位于 § 1.1.2
  • createMediaElementSource(mediaElement), 位于 § 1.2.3
  • createMediaStreamDestination(), 位于 § 1.2.3
  • createMediaStreamSource(mediaStream), 位于 § 1.2.3
  • createMediaStreamTrackSource(mediaStreamTrack), 位于 § 1.2.3
  • createOscillator(), 位于 § 1.1.2
  • createPanner(), 位于 § 1.1.2
  • createPeriodicWave(real, imag), 位于 § 1.1.2
  • createPeriodicWave(real, imag, constraints), 位于 § 1.1.2
  • createScriptProcessor(), 位于 § 1.1.2
  • createScriptProcessor(bufferSize), 位于 § 1.1.2
  • createScriptProcessor(bufferSize, numberOfInputChannels), 位于 § 1.1.2
  • createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels), 位于 § 1.1.2
  • createStereoPanner(), 位于 § 1.1.2
  • createWaveShaper(), 位于 § 1.1.2
  • [[current frame]], 位于 § 2.4
  • currentFrame, 位于 § 1.32.3.1
  • 当前频率数据(current frequency data), 位于 § 1.8.6
  • currentTime
  • 当前时域数据(current time-domain data), 位于 § 1.8.5
  • [[current value]], 位于 § 1.6
  • curve
  • [[curve set]], 位于 § 1.31.1
  • "custom", 位于 § 1.26
  • custom, 位于 § 1.26
  • 周期(cycle), 位于 § 1.5.5
  • 分贝转线性增益单位(decibels to linear gain unit), 位于 § 1.19.4
  • decodeAudioData(audioData), 位于 § 1.1.2
  • decodeAudioData(audioData, successCallback), 位于 § 1.1.2
  • decodeAudioData(audioData, successCallback, errorCallback), 位于 § 1.1.2
  • DecodeErrorCallback, 位于 § 1.1.3
  • DecodeErrorCallback(), 位于 § 1.1.3
  • DecodeSuccessCallback, 位于 § 1.1.2
  • DecodeSuccessCallback(), 位于 § 1.1.2
  • 解码线程(decoding thread), 位于 § 1.1.2
  • "default", 位于 § 1.1
  • default, 位于 § 1.1
  • defaultValue
  • DelayNode, 位于 § 1.17.4
  • DelayNode(context), 位于 § 1.18.1
  • DelayNode(context, options), 位于 § 1.18.1
  • DelayOptions, 位于 § 1.18.2
  • DelayReader, 位于 § 1.18.4
  • delayTime
  • DelayWriter, 位于 § 1.18.4
  • destination, 位于 § 1.1.1
  • 目标节点(destination node), 位于 无编号章节
  • [[detector average]], 位于 § 1.19.4
  • 检测器曲线(detector curve), 位于 § 1.19.4
  • detune
  • disableNormalization
  • disconnect(), 位于 § 1.5.5
  • disconnect(destinationNode), 位于 § 1.5.5
  • disconnect(destinationNode, output), 位于 § 1.5.5
  • disconnect(destinationNode, output, input), 位于 § 1.5.5
  • disconnect(destinationParam), 位于 § 1.5.5
  • disconnect(destinationParam, output), 位于 § 1.5.5
  • disconnect(output), 位于 § 1.5.5
  • "discrete", 位于 § 1.5.1
  • discrete, 位于 § 1.5.1
  • distanceModel
  • DistanceModelType, 位于 § 1.27
  • 下混(down-mixing), 位于 § 4
  • duration, 位于 § 1.4.2
  • DynamicsCompressorNode, 位于 § 1.18.4
  • DynamicsCompressorNode(context), 位于 § 1.19.1
  • DynamicsCompressorNode(context, options), 位于 § 1.19.1
  • DynamicsCompressorOptions, 位于 § 1.19.2
  • 有效自动化速率(effective automation rate), 位于 § 1.27
  • ended, 位于 § 1.7.1
  • 包络跟随器(envelopefollower), 位于 § 1.19.4
  • "equalpower", 位于 § 1.27
  • equalpower, 位于 § 1.27
  • error, 位于 § 1.2.2
  • "explicit", 位于 § 1.5.1
  • explicit, 位于 § 1.5.1
  • "exponential", 位于 § 1.27
  • exponential, 位于 § 1.27
  • exponentialRampToValueAtTime(value, endTime), 位于 § 1.6.2
  • 工厂方法(factory method), 位于 § 1.5.1
  • feedback, 位于 § 1.21.3.1
  • feedforward, 位于 § 1.21.3.1
  • fftSize
  • forward, 位于 § 1.11.2
  • forwardX, 位于 § 1.11.1
  • forwardY, 位于 § 1.11.1
  • forwardZ, 位于 § 1.11.1
  • frequency
  • frequencyBinCount, 位于 § 1.8.2
  • gain
  • GainNode, 位于 § 1.19.4
  • GainNode(context), 位于 § 1.20.1
  • GainNode(context, options), 位于 § 1.20.1
  • GainOptions, 位于 § 1.20.2
  • getByteFrequencyData(array), 位于 § 1.8.3
  • getByteTimeDomainData(array), 位于 § 1.8.3
  • getChannelData(channel), 位于 § 1.4.3
  • getFloatFrequencyData(array), 位于 § 1.8.3
  • getFloatTimeDomainData(array), 位于 § 1.8.3
  • getFrequencyResponse(frequencyHz, magResponse, phaseResponse)
  • getOutputTimestamp(), 位于 § 1.2.3
  • "hardware", 位于 § 1.1
  • hardware, 位于 § 1.1
  • "highpass", 位于 § 1.13
  • highpass, 位于 § 1.13
  • "highshelf", 位于 § 1.13
  • highshelf, 位于 § 1.13
  • "HRTF", 位于 § 1.27
  • HRTF, 位于 § 1.27
  • IIRFilterNode, 位于 § 1.20.3.1
  • IIRFilterNode(context, options), 位于 § 1.21.1
  • IIRFilterOptions, 位于 § 1.21.2
  • [[imag]], 位于 § 1.28.1
  • imag, 位于 § 1.28.3.1
  • 初始化(Initializing), 位于 § 1.5.1
  • 输入(input), 位于 § 1.5
  • 输入 AudioParam 缓冲区(input AudioParam buffer), 位于 § 2.4
  • 输入缓冲区(input buffer), 位于 § 2.4
  • inputBuffer
  • 输入(inputs), 位于 无编号章节
  • [[input track]], 位于 § 1.24.1
  • "interactive", 位于 § 1.2
  • interactive, 位于 § 1.2
  • [[internal data]], 位于 § 1.4
  • [[internal reduction]], 位于 § 1.19.1
  • "inverse", 位于 § 1.27
  • inverse, 位于 § 1.27
  • knee(膝点)
  • "k-rate", 位于 § 1.6
  • k-rate
  • latencyHint, 位于 § 1.2.5.1
  • [[length]], 位于 § 1.4
  • length
  • "linear", 位于 § 1.27
  • linear, 位于 § 1.27
  • 线性增益单位转分贝(linear gain unit to decibel), 位于 § 1.19.4
  • 线性 PCM(linear PCM), 位于 § 5.1
  • linearRampToValueAtTime(value, endTime), 位于 § 1.6.2
  • listener, 位于 § 1.1.1
  • 加载值(load value), 位于 § 2.4
  • loop(循环)
  • loopEnd
  • loopStart
  • "lowpass", 位于 § 1.13
  • lowpass, 位于 § 1.13
  • "lowshelf", 位于 § 1.13
  • lowshelf, 位于 § 1.13
  • 使缓冲区可读(Making a buffer available for reading), 位于 § 2.4
  • "max", 位于 § 1.5.1
  • max, 位于 § 1.5.1
  • maxChannelCount, 位于 § 1.10.1
  • maxDecibels
  • maxDelayTime, 位于 § 1.18.3.1
  • maxDistance
  • maxValue
  • mediaElement
  • MediaElementAudioSourceNode, 位于 § 1.21.4
  • MediaElementAudioSourceNode(context, options), 位于 § 1.22.1
  • MediaElementAudioSourceOptions, 位于 § 1.22.2
  • mediaStream
  • MediaStreamAudioDestinationNode, 位于 § 1.22.4
  • MediaStreamAudioDestinationNode(context), 位于 § 1.23.1
  • MediaStreamAudioDestinationNode(context, options), 位于 § 1.23.1
  • MediaStreamAudioSourceNode, 位于 § 1.23.2
  • MediaStreamAudioSourceNode(context, options), 位于 § 1.24.1
  • MediaStreamAudioSourceOptions, 位于 § 1.24.2
  • mediaStreamTrack, 位于 § 1.25.2.1
  • MediaStreamTrackAudioSourceNode, 位于 § 1.24.3.1
  • MediaStreamTrackAudioSourceNode(context, options), 位于 § 1.25.1
  • MediaStreamTrackAudioSourceOptions, 位于 § 1.25.1
  • minDecibels
  • minValue
  • 混音规则(mixing rules), 位于 § 4
  • most-negative-single-float, 位于 § 1.6
  • most-positive-single-float, 位于 § 1.6
  • 静音(Muting), 位于 § 2.4
  • name
  • node, 位于 § 1.32.3.3
  • 节点名称到参数描述符映射(node name to parameter descriptor map), 位于 § 1.32.2
  • 节点名称到处理器构造函数映射(node name to processor constructor map), 位于 § 1.32.3
  • [[node reference]], 位于 § 1.32.5
  • 节点引用(node reference), 位于 § 1.32.3
  • 标称范围(nominal range), 位于 § 1.6.3
  • "none" (无)
  • none(无)
  • [[normalize]], 位于 § 1.28.1
  • normalize, 位于 § 1.17.2
  • "notch", 位于 § 1.13
  • notch, 位于 § 1.13
  • [[number of channels]], 位于 § 1.4
  • numberOfChannels
  • numberOfInputs
  • numberOfOutputs
  • 奈奎斯特频率(Nyquist frequency), 位于 § 1.1.1
  • OfflineAudioCompletionEvent, 位于 § 1.3.4.1
  • OfflineAudioCompletionEventInit, 位于 § 1.3.5.1
  • OfflineAudioCompletionEvent(type, eventInitDict), 位于 § 1.3.5
  • OfflineAudioContext, 位于 § 1.2.11.1
  • OfflineAudioContext(contextOptions), 位于 § 1.3.1
  • OfflineAudioContext(numberOfChannels, length, sampleRate), 位于 § 1.3.1
  • OfflineAudioContextOptions, 位于 § 1.3.3
  • offset
  • 最旧消息(oldest message), 位于 § 2.2
  • onaudioprocess, 位于 § 1.29.1
  • oncomplete, 位于 § 1.3.2
  • onended, 位于 § 1.7.1
  • onerror, 位于 § 1.2.2
  • onprocessorerror, 位于 § 1.32.4.2
  • onsinkchange, 位于 § 1.2.2
  • onstatechange, 位于 § 1.1.1
  • onupdate, 位于 § 1.2.9.1
  • options, 位于 § 1.32.3.3
  • orientationX
  • orientationY
  • orientationZ
  • OscillatorNode, 位于 § 1.25.2.1
  • OscillatorNode(context), 位于 § 1.26.1
  • OscillatorNode(context, options), 位于 § 1.26.1
  • OscillatorOptions, 位于 § 1.26.3
  • OscillatorType, 位于 § 1.26
  • outputBuffer
  • outputChannelCount, 位于 § 1.32.4.3.1
  • outputLatency, 位于 § 1.2.2
  • 输出(outputs), 位于 无编号章节
  • oversample
  • OverSampleType, 位于 § 1.31
  • pan(声相)
  • PannerNode, 位于 § 1.26.5
  • PannerNode(context), 位于 § 1.27.1
  • PannerNode(context, options), 位于 § 1.27.1
  • PannerOptions, 位于 § 1.27.3
  • panningModel
  • PanningModelType, 位于 § 1.27
  • parameterData, 位于 § 1.32.4.3.1
  • parameterDescriptors, 位于 § 1.32.5.3
  • parameters, 位于 § 1.32.4.2
  • "peaking", 位于 § 1.13
  • peaking, 位于 § 1.13
  • peakLoad
  • 挂起的处理器构建数据(pending processor construction data), 位于 § 1.32.3
  • [[pending promises]], 位于 § 1.1
  • [[pending resume promises]], 位于 § 1.2
  • performanceTime, 位于 § 1.2.8.1
  • PeriodicWave, 位于 § 1.27.5
  • periodicWave, 位于 § 1.26.4.1
  • PeriodicWaveConstraints, 位于 § 1.28.1
  • PeriodicWave(context), 位于 § 1.28.1
  • PeriodicWave(context, options), 位于 § 1.28.1
  • PeriodicWaveOptions, 位于 § 1.28.2.1
  • "playback", 位于 § 1.2
  • playback, 位于 § 1.2
  • playbackRate
  • playbackTime
  • 播放头位置(playhead position), 位于 § 1.9
  • 正在播放(playing), 位于 § 1.7
  • port
  • positionX
  • positionY
  • positionZ
  • 上一个块(previous block), 位于 § 1.8.6
  • process(), 位于 § 1.32.5.3
  • 处理输入缓冲区(Processing an input buffer), 位于 § 2.4
  • 处理器构建数据(processor construction data), 位于 § 1.32.3.3
  • processorerror, 位于 § 1.32.4.2
  • processorOptions, 位于 § 1.32.4.3.1
  • 变量 A
  • 排队(queue a control message), 位于 § 2.2
  • ratio(比率)
  • [[real]], 位于 § 1.28.1
  • real, 位于 § 1.28.3.1
  • 记录输入(Recording the input), 位于 § 2.4
  • reduction, 位于 § 1.19.2
  • refDistance
  • registerProcessor(name, processorCtor),见 § 1.32.3.2
  • release
  • 释放系统资源,见 § 1.1.7
  • renderCapacity,见 § 1.2.2
  • [[rendered buffer]],见 § 1.3.3
  • renderedBuffer
  • [[rendering started]],见 § 1.3.3
  • 渲染线程,见 § 2.2
  • [[渲染线程状态]],见 § 1.1
  • 渲染量子 (render quantum),见 § 2.4
  • [[渲染量子大小]],见 § 1.1
  • 渲染量子大小,见 § 2.4
  • renderQuantumSize
  • renderSizeHint
  • resume()
  • rolloffFactor
  • "running",见 § 1.1
  • running,见 § 1.1
  • [[采样率]],见 § 1.4
  • sampleRate
  • "sawtooth",见 § 1.26
  • sawtooth,见 § 1.26
  • ScriptProcessorNode,见 § 1.28.6
  • setOrientation(x, y, z),见 § 1.27.3
  • setOrientation(x, y, z, xUp, yUp, zUp),见 § 1.11.2
  • setPeriodicWave(periodicWave),见 § 1.26.3
  • setPosition(x, y, z)
  • setSinkId((DOMString or AudioSinkOptions) sinkId),见 § 1.2.3
  • setSinkId(sinkId),见 § 1.2
  • setTargetAtTime(target, startTime, timeConstant),见 § 1.6.2
  • setValueAtTime(value, startTime),见 § 1.6.2
  • setValueCurveAtTime(values, startTime, duration),见 § 1.6.2
  • 简单标称范围,见 § 1.6
  • 简单参数,见 § 1.6.3
  • "sine",见 § 1.26
  • sine,见 § 1.26
  • sinkchange,见 § 1.2.2
  • [[接收器 ID (sink ID)]],见 § 1.2
  • sinkId
  • 时间平滑处理,见 § 1.8.6
  • smoothingTimeConstant
  • 源节点,见 § 未编号章节
  • 源节点 (source nodes),见 § 1.5.4
  • [[源已启动]],见 § 1.7
  • "speakers",见 § 1.5.1
  • speakers,见 § 1.5.1
  • "square",见 § 1.26
  • square,见 § 1.26
  • start()
  • start(options),见 § 1.2.9.2
  • startRendering(),见 § 1.3.3
  • start(when)
  • start(when, offset),见 § 1.9.3
  • start(when, offset, duration),见 § 1.9.3
  • state,见 § 1.1.1
  • statechange,见 § 1.1.1
  • StereoPannerNode,见 § 1.29.1
  • StereoPannerNode(context),见 § 1.30.1
  • StereoPannerNode(context, options),见 § 1.30.1
  • StereoPannerOptions,见 § 1.30.2
  • stop()
  • stop(when),见 § 1.7.2
  • stream,见 § 1.23.2
  • suspend(),见 § 1.2.3
  • "suspended",见 § 1.1
  • suspended,见 § 1.1
  • [[用户已挂起]],见 § 1.2
  • suspend(suspendTime),见 § 1.3.3
  • 交换 (swap),见 § 2.2
  • 系统级音频回调,见 § 2.4
  • 系统级音频回调缓冲区大小,见 § 2.4
  • 尾部时间 (tail-time),见 § 1.5.2
  • threshold(阈值)
  • timestamp(时间戳)
  • 已传输端口,见 § 1.32.3
  • "triangle",见 § 1.26
  • triangle,见 § 1.26
  • type
  • underrunRatio
  • up,见 § 1.11.2
  • update,见 § 1.2.9.1
  • updateInterval,见 § 1.2.10.1
  • 上混音 (up-mixing),见 § 4
  • upX,见 § 1.11.1
  • upY,见 § 1.11.1
  • upZ,见 § 1.11.1
  • value,见 § 1.6.1
  • 访问 (Visit),见 § 2.4
  • WaveShaperNode,见 § 1.30.4
  • WaveShaperNode(context),见 § 1.31.1
  • WaveShaperNode(context, options),见 § 1.31.1
  • WaveShaperOptions,见 § 1.31.2
  • 通过引用定义的术语

    引用

    规范性引用

    [DOM]
    Anne van Kesteren. DOM 标准. Living Standard. URL: https://dom.spec.whatwg.org/
    [ECMASCRIPT]
    ECMAScript 语言规范. URL: https://tc39.es/ecma262/multipage/
    [FETCH]
    Anne van Kesteren. 提取标准 (Fetch Standard). 生活标准. URL: https://fetch.spec.whatwg.org/
    [HR-TIME-3]
    Yoav Weiss. 高分辨率时间。2023 年 7 月 19 日。WD。URL: https://w3org.cn/TR/hr-time-3/
    [HTML]
    Anne van Kesteren; et al. HTML 标准. Living Standard. URL: https://html.whatwg.cn/multipage/
    [INFRA]
    Anne van Kesteren; Domenic Denicola. Infra 标准. Living Standard. URL: https://infra.spec.whatwg.org/
    [MEDIACAPTURE-STREAMS]
    Cullen Jennings 等人。媒体捕获与流 (Media Capture and Streams)。2024 年 10 月 3 日。CR。URL: https://w3org.cn/TR/mediacapture-streams/
    [MIMESNIFF]
    Gordon P. Hemsley. MIME 嗅探标准. 活标准. URL: https://mimesniff.spec.whatwg.org/
    [RFC2119]
    S. Bradner. RFC 中用于指示要求级别的关键词. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
    [SECURITY-PRIVACY-QUESTIONNAIRE]
    Theresa O'Connor; Peter Snyder。自测问卷:安全与隐私 (Self-Review Questionnaire: Security and Privacy)。2021 年 12 月 16 日。NOTE。URL: https://w3org.cn/TR/security-privacy-questionnaire/
    [WEBIDL]
    Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/
    [WEBRTC]
    Cullen Jennings 等人。WebRTC:浏览器中的实时通信 (WebRTC: Real-Time Communication in Browsers)。2024 年 10 月 8 日。REC。URL: https://w3org.cn/TR/webrtc/

    参考资料

    [2DCONTEXT]
    Rik Cabanier 等人。HTML Canvas 2D 上下文 (HTML Canvas 2D Context)。2021 年 1 月 28 日。REC。URL: https://w3org.cn/TR/2dcontext/
    [MEDIASTREAM-RECORDING]
    Miguel Casas-sanchez。媒体流录制 (MediaStream Recording)。2023 年 5 月 11 日。WD。URL: https://w3org.cn/TR/mediastream-recording/
    [WEBAUDIO-USECASES]
    Joe Berkovitz; Olivier Thereaux。Web 音频处理:用例与需求 (Web Audio Processing: Use Cases and Requirements)。2013 年 1 月 29 日。NOTE。URL: https://w3org.cn/TR/webaudio-usecases/
    [WEBCODECS]
    Paul Adenot; Bernard Aboba; Eugene Zemtsov。WebCodecs。2024 年 10 月 8 日。WD。URL: https://w3org.cn/TR/webcodecs/
    [WEBGL]
    Dean Jackson; Jeff Gilbert. WebGL 2.0 Specification (WebGL 2.0 规范). 2017年8月12日. URL: https://www.khronos.org/registry/webgl/specs/latest/2.0/
    [XHR]
    Anne van Kesteren. XMLHttpRequest 标准. Living Standard. URL: https://xhr.spec.whatwg.org/

    IDL 索引

    enum AudioContextState {
        "suspended",
        "running",
        "closed"
    };
    
    enum AudioContextRenderSizeCategory {
        "default",
        "hardware"
    };
    
    callback DecodeErrorCallback = undefined (DOMException error);
    
    callback DecodeSuccessCallback = undefined (AudioBuffer decodedData);
    
    [Exposed=Window]
    interface BaseAudioContext : EventTarget {
        readonly attribute AudioDestinationNode destination;
        readonly attribute float sampleRate;
        readonly attribute double currentTime;
        readonly attribute AudioListener listener;
        readonly attribute AudioContextState state;
        readonly attribute unsigned long renderQuantumSize;
        [SameObject, SecureContext]
        readonly attribute AudioWorklet audioWorklet;
        attribute EventHandler onstatechange;
    
        AnalyserNode createAnalyser ();
        BiquadFilterNode createBiquadFilter ();
        AudioBuffer createBuffer (unsigned long numberOfChannels,
                                    unsigned long length,
                                    float sampleRate);
        AudioBufferSourceNode createBufferSource ();
        ChannelMergerNode createChannelMerger (optional unsigned long numberOfInputs = 6);
        ChannelSplitterNode createChannelSplitter (
            optional unsigned long numberOfOutputs = 6);
        ConstantSourceNode createConstantSource ();
        ConvolverNode createConvolver ();
        DelayNode createDelay (optional double maxDelayTime = 1.0);
        DynamicsCompressorNode createDynamicsCompressor ();
        GainNode createGain ();
        IIRFilterNode createIIRFilter (sequence<double> feedforward,
                                        sequence<double> feedback);
        OscillatorNode createOscillator ();
        PannerNode createPanner ();
        PeriodicWave createPeriodicWave (sequence<float> real,
                                            sequence<float> imag,
                                            optional PeriodicWaveConstraints constraints = {});
        ScriptProcessorNode createScriptProcessor(
            optional unsigned long bufferSize = 0,
            optional unsigned long numberOfInputChannels = 2,
            optional unsigned long numberOfOutputChannels = 2);
        StereoPannerNode createStereoPanner ();
        WaveShaperNode createWaveShaper ();
    
        Promise<AudioBuffer> decodeAudioData (
            ArrayBuffer audioData,
            optional DecodeSuccessCallback? successCallback,
            optional DecodeErrorCallback? errorCallback);
    };
    
    enum AudioContextLatencyCategory {
            "balanced",
            "interactive",
            "playback"
    };
    
    enum AudioSinkType {
        "none"
    };
    
    [Exposed=Window]
    interface AudioContext : BaseAudioContext {
        constructor (optional AudioContextOptions contextOptions = {});
        readonly attribute double baseLatency;
        readonly attribute double outputLatency;
        [SecureContext] readonly attribute (DOMString or AudioSinkInfo) sinkId;
        [SecureContext] readonly attribute AudioRenderCapacity renderCapacity;
        attribute EventHandler onsinkchange;
        attribute EventHandler onerror;
        AudioTimestamp getOutputTimestamp ();
        Promise<undefined> resume ();
        Promise<undefined> suspend ();
        Promise<undefined> close ();
        [SecureContext] Promise<undefined> setSinkId ((DOMString or AudioSinkOptions) sinkId);
        MediaElementAudioSourceNode createMediaElementSource (HTMLMediaElement mediaElement);
        MediaStreamAudioSourceNode createMediaStreamSource (MediaStream mediaStream);
        MediaStreamTrackAudioSourceNode createMediaStreamTrackSource (
            MediaStreamTrack mediaStreamTrack);
        MediaStreamAudioDestinationNode createMediaStreamDestination ();
    };
    
    dictionary AudioContextOptions {
        (AudioContextLatencyCategory or double) latencyHint = "interactive";
        float sampleRate;
        (DOMString or AudioSinkOptions) sinkId;
        (AudioContextRenderSizeCategory or unsigned long) renderSizeHint = "default";
    };
    
    dictionary AudioSinkOptions {
        required AudioSinkType type;
    };
    
    [Exposed=Window]
    interface AudioSinkInfo {
        readonly attribute AudioSinkType type;
    };
    
    dictionary AudioTimestamp {
        double contextTime;
        DOMHighResTimeStamp performanceTime;
    };
    
    [Exposed=Window]
    interface AudioRenderCapacity : EventTarget {
        undefined start(optional AudioRenderCapacityOptions options = {});
            undefined stop();
            attribute EventHandler onupdate;
    };
    
    dictionary AudioRenderCapacityOptions {
            double updateInterval = 1;
    };
    
    [Exposed=Window]
    interface AudioRenderCapacityEvent : Event {
        constructor (DOMString type, optional AudioRenderCapacityEventInit eventInitDict = {});
            readonly attribute double timestamp;
            readonly attribute double averageLoad;
            readonly attribute double peakLoad;
            readonly attribute double underrunRatio;
    };
    
    dictionary AudioRenderCapacityEventInit : EventInit {
        double timestamp = 0;
        double averageLoad = 0;
        double peakLoad = 0;
        double underrunRatio = 0;
    };
    
    [Exposed=Window]
    interface OfflineAudioContext : BaseAudioContext {
        constructor(OfflineAudioContextOptions contextOptions);
        constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate);
        Promise<AudioBuffer> startRendering();
        Promise<undefined> resume();
        Promise<undefined> suspend(double suspendTime);
        readonly attribute unsigned long length;
        attribute EventHandler oncomplete;
    };
    
    dictionary OfflineAudioContextOptions {
        unsigned long numberOfChannels = 1;
        required unsigned long length;
        required float sampleRate;
        (AudioContextRenderSizeCategory or unsigned long) renderSizeHint = "default";
    };
    
    [Exposed=Window]
    interface OfflineAudioCompletionEvent : Event {
        constructor (DOMString type, OfflineAudioCompletionEventInit eventInitDict);
        readonly attribute AudioBuffer renderedBuffer;
    };
    
    dictionary OfflineAudioCompletionEventInit : EventInit {
        required AudioBuffer renderedBuffer;
    };
    
    [Exposed=Window]
    interface AudioBuffer {
        constructor (AudioBufferOptions options);
        readonly attribute float sampleRate;
        readonly attribute unsigned long length;
        readonly attribute double duration;
        readonly attribute unsigned long numberOfChannels;
        Float32Array getChannelData (unsigned long channel);
        undefined copyFromChannel (Float32Array destination,
                                   unsigned long channelNumber,
                                   optional unsigned long bufferOffset = 0);
        undefined copyToChannel (Float32Array source,
                                 unsigned long channelNumber,
                                 optional unsigned long bufferOffset = 0);
    };
    
    dictionary AudioBufferOptions {
        unsigned long numberOfChannels = 1;
        required unsigned long length;
        required float sampleRate;
    };
    
    [Exposed=Window]
    interface AudioNode : EventTarget {
        AudioNode connect (AudioNode destinationNode,
                           optional unsigned long output = 0,
                           optional unsigned long input = 0);
        undefined connect (AudioParam destinationParam, optional unsigned long output = 0);
        undefined disconnect ();
        undefined disconnect (unsigned long output);
        undefined disconnect (AudioNode destinationNode);
        undefined disconnect (AudioNode destinationNode, unsigned long output);
        undefined disconnect (AudioNode destinationNode,
                              unsigned long output,
                              unsigned long input);
        undefined disconnect (AudioParam destinationParam);
        undefined disconnect (AudioParam destinationParam, unsigned long output);
        readonly attribute BaseAudioContext context;
        readonly attribute unsigned long numberOfInputs;
        readonly attribute unsigned long numberOfOutputs;
        attribute unsigned long channelCount;
        attribute ChannelCountMode channelCountMode;
        attribute ChannelInterpretation channelInterpretation;
    };
    
    enum ChannelCountMode {
        "max",
        "clamped-max",
        "explicit"
    };
    
    enum ChannelInterpretation {
        "speakers",
        "discrete"
    };
    
    dictionary AudioNodeOptions {
        unsigned long channelCount;
        ChannelCountMode channelCountMode;
        ChannelInterpretation channelInterpretation;
    };
    
    enum AutomationRate {
        "a-rate",
        "k-rate"
    };
    
    [Exposed=Window]
    interface AudioParam {
        attribute float value;
        attribute AutomationRate automationRate;
        readonly attribute float defaultValue;
        readonly attribute float minValue;
        readonly attribute float maxValue;
        AudioParam setValueAtTime (float value, double startTime);
        AudioParam linearRampToValueAtTime (float value, double endTime);
        AudioParam exponentialRampToValueAtTime (float value, double endTime);
        AudioParam setTargetAtTime (float target, double startTime, float timeConstant);
        AudioParam setValueCurveAtTime (sequence<float> values,
                                        double startTime,
                                        double duration);
        AudioParam cancelScheduledValues (double cancelTime);
        AudioParam cancelAndHoldAtTime (double cancelTime);
    };
    
    [Exposed=Window]
    interface AudioScheduledSourceNode : AudioNode {
        attribute EventHandler onended;
        undefined start(optional double when = 0);
        undefined stop(optional double when = 0);
    };
    
    [Exposed=Window]
    interface AnalyserNode : AudioNode {
        constructor (BaseAudioContext context, optional AnalyserOptions options = {});
        undefined getFloatFrequencyData (Float32Array array);
        undefined getByteFrequencyData (Uint8Array array);
        undefined getFloatTimeDomainData (Float32Array array);
        undefined getByteTimeDomainData (Uint8Array array);
        attribute unsigned long fftSize;
        readonly attribute unsigned long frequencyBinCount;
        attribute double minDecibels;
        attribute double maxDecibels;
        attribute double smoothingTimeConstant;
    };
    
    dictionary AnalyserOptions : AudioNodeOptions {
        unsigned long fftSize = 2048;
        double maxDecibels = -30;
        double minDecibels = -100;
        double smoothingTimeConstant = 0.8;
    };
    
    [Exposed=Window]
    interface AudioBufferSourceNode : AudioScheduledSourceNode {
        constructor (BaseAudioContext context,
                     optional AudioBufferSourceOptions options = {});
        attribute AudioBuffer? buffer;
        readonly attribute AudioParam playbackRate;
        readonly attribute AudioParam detune;
        attribute boolean loop;
        attribute double loopStart;
        attribute double loopEnd;
        undefined start (optional double when = 0,
                         optional double offset,
                         optional double duration);
    };
    
    dictionary AudioBufferSourceOptions {
        AudioBuffer? buffer;
        float detune = 0;
        boolean loop = false;
        double loopEnd = 0;
        double loopStart = 0;
        float playbackRate = 1;
    };
    
    [Exposed=Window]
    interface AudioDestinationNode : AudioNode {
        readonly attribute unsigned long maxChannelCount;
    };
    
    [Exposed=Window]
    interface AudioListener {
        readonly attribute AudioParam positionX;
        readonly attribute AudioParam positionY;
        readonly attribute AudioParam positionZ;
        readonly attribute AudioParam forwardX;
        readonly attribute AudioParam forwardY;
        readonly attribute AudioParam forwardZ;
        readonly attribute AudioParam upX;
        readonly attribute AudioParam upY;
        readonly attribute AudioParam upZ;
        undefined setPosition (float x, float y, float z);
        undefined setOrientation (float x, float y, float z, float xUp, float yUp, float zUp);
    };
    
    [Exposed=Window]
    interface AudioProcessingEvent : Event {
        constructor (DOMString type, AudioProcessingEventInit eventInitDict);
        readonly attribute double playbackTime;
        readonly attribute AudioBuffer inputBuffer;
        readonly attribute AudioBuffer outputBuffer;
    };
    
    dictionary AudioProcessingEventInit : EventInit {
        required double playbackTime;
        required AudioBuffer inputBuffer;
        required AudioBuffer outputBuffer;
    };
    
    enum BiquadFilterType {
        "lowpass",
        "highpass",
        "bandpass",
        "lowshelf",
        "highshelf",
        "peaking",
        "notch",
        "allpass"
    };
    
    [Exposed=Window]
    interface BiquadFilterNode : AudioNode {
        constructor (BaseAudioContext context, optional BiquadFilterOptions options = {});
        attribute BiquadFilterType type;
        readonly attribute AudioParam frequency;
        readonly attribute AudioParam detune;
        readonly attribute AudioParam Q;
        readonly attribute AudioParam gain;
        undefined getFrequencyResponse (Float32Array frequencyHz,
                                        Float32Array magResponse,
                                        Float32Array phaseResponse);
    };
    
    dictionary BiquadFilterOptions : AudioNodeOptions {
        BiquadFilterType type = "lowpass";
        float Q = 1;
        float detune = 0;
        float frequency = 350;
        float gain = 0;
    };
    
    [Exposed=Window]
    interface ChannelMergerNode : AudioNode {
        constructor (BaseAudioContext context, optional ChannelMergerOptions options = {});
    };
    
    dictionary ChannelMergerOptions : AudioNodeOptions {
        unsigned long numberOfInputs = 6;
    };
    
    [Exposed=Window]
    interface ChannelSplitterNode : AudioNode {
        constructor (BaseAudioContext context, optional ChannelSplitterOptions options = {});
    };
    
    dictionary ChannelSplitterOptions : AudioNodeOptions {
        unsigned long numberOfOutputs = 6;
    };
    
    [Exposed=Window]
    interface ConstantSourceNode : AudioScheduledSourceNode {
        constructor (BaseAudioContext context, optional ConstantSourceOptions options = {});
        readonly attribute AudioParam offset;
    };
    
    dictionary ConstantSourceOptions {
        float offset = 1;
    };
    
    [Exposed=Window]
    interface ConvolverNode : AudioNode {
        constructor (BaseAudioContext context, optional ConvolverOptions options = {});
        attribute AudioBuffer? buffer;
        attribute boolean normalize;
    };
    
    dictionary ConvolverOptions : AudioNodeOptions {
        AudioBuffer? buffer;
        boolean disableNormalization = false;
    };
    
    [Exposed=Window]
    interface DelayNode : AudioNode {
        constructor (BaseAudioContext context, optional DelayOptions options = {});
        readonly attribute AudioParam delayTime;
    };
    
    dictionary DelayOptions : AudioNodeOptions {
        double maxDelayTime = 1;
        double delayTime = 0;
    };
    
    [Exposed=Window]
    interface DynamicsCompressorNode : AudioNode {
        constructor (BaseAudioContext context,
                     optional DynamicsCompressorOptions options = {});
        readonly attribute AudioParam threshold;
        readonly attribute AudioParam knee;
        readonly attribute AudioParam ratio;
        readonly attribute float reduction;
        readonly attribute AudioParam attack;
        readonly attribute AudioParam release;
    };
    
    dictionary DynamicsCompressorOptions : AudioNodeOptions {
        float attack = 0.003;
        float knee = 30;
        float ratio = 12;
        float release = 0.25;
        float threshold = -24;
    };
    
    [Exposed=Window]
    interface GainNode : AudioNode {
        constructor (BaseAudioContext context, optional GainOptions options = {});
        readonly attribute AudioParam gain;
    };
    
    dictionary GainOptions : AudioNodeOptions {
        float gain = 1.0;
    };
    
    [Exposed=Window]
    interface IIRFilterNode : AudioNode {
        constructor (BaseAudioContext context, IIRFilterOptions options);
        undefined getFrequencyResponse (Float32Array frequencyHz,
                                        Float32Array magResponse,
                                        Float32Array phaseResponse);
    };
    
    dictionary IIRFilterOptions : AudioNodeOptions {
        required sequence<double> feedforward;
        required sequence<double> feedback;
    };
    
    [Exposed=Window]
    interface MediaElementAudioSourceNode : AudioNode {
        constructor (AudioContext context, MediaElementAudioSourceOptions options);
        [SameObject] readonly attribute HTMLMediaElement mediaElement;
    };
    
    dictionary MediaElementAudioSourceOptions {
        required HTMLMediaElement mediaElement;
    };
    
    [Exposed=Window]
    interface MediaStreamAudioDestinationNode : AudioNode {
        constructor (AudioContext context, optional AudioNodeOptions options = {});
        readonly attribute MediaStream stream;
    };
    
    [Exposed=Window]
    interface MediaStreamAudioSourceNode : AudioNode {
        constructor (AudioContext context, MediaStreamAudioSourceOptions options);
        [SameObject] readonly attribute MediaStream mediaStream;
    };
    
    dictionary MediaStreamAudioSourceOptions {
        required MediaStream mediaStream;
    };
    
    [Exposed=Window]
    interface MediaStreamTrackAudioSourceNode : AudioNode {
        constructor (AudioContext context, MediaStreamTrackAudioSourceOptions options);
    };
    
    dictionary MediaStreamTrackAudioSourceOptions {
        required MediaStreamTrack mediaStreamTrack;
    };
    
    enum OscillatorType {
        "sine",
        "square",
        "sawtooth",
        "triangle",
        "custom"
    };
    
    [Exposed=Window]
    interface OscillatorNode : AudioScheduledSourceNode {
        constructor (BaseAudioContext context, optional OscillatorOptions options = {});
        attribute OscillatorType type;
        readonly attribute AudioParam frequency;
        readonly attribute AudioParam detune;
        undefined setPeriodicWave (PeriodicWave periodicWave);
    };
    
    dictionary OscillatorOptions : AudioNodeOptions {
        OscillatorType type = "sine";
        float frequency = 440;
        float detune = 0;
        PeriodicWave periodicWave;
    };
    
    enum PanningModelType {
            "equalpower",
            "HRTF"
    };
    
    enum DistanceModelType {
        "linear",
        "inverse",
        "exponential"
    };
    
    [Exposed=Window]
    interface PannerNode : AudioNode {
        constructor (BaseAudioContext context, optional PannerOptions options = {});
        attribute PanningModelType panningModel;
        readonly attribute AudioParam positionX;
        readonly attribute AudioParam positionY;
        readonly attribute AudioParam positionZ;
        readonly attribute AudioParam orientationX;
        readonly attribute AudioParam orientationY;
        readonly attribute AudioParam orientationZ;
        attribute DistanceModelType distanceModel;
        attribute double refDistance;
        attribute double maxDistance;
        attribute double rolloffFactor;
        attribute double coneInnerAngle;
        attribute double coneOuterAngle;
        attribute double coneOuterGain;
        undefined setPosition (float x, float y, float z);
        undefined setOrientation (float x, float y, float z);
    };
    
    dictionary PannerOptions : AudioNodeOptions {
        PanningModelType panningModel = "equalpower";
        DistanceModelType distanceModel = "inverse";
        float positionX = 0;
        float positionY = 0;
        float positionZ = 0;
        float orientationX = 1;
        float orientationY = 0;
        float orientationZ = 0;
        double refDistance = 1;
        double maxDistance = 10000;
        double rolloffFactor = 1;
        double coneInnerAngle = 360;
        double coneOuterAngle = 360;
        double coneOuterGain = 0;
    };
    
    [Exposed=Window]
    interface PeriodicWave {
        constructor (BaseAudioContext context, optional PeriodicWaveOptions options = {});
    };
    
    dictionary PeriodicWaveConstraints {
        boolean disableNormalization = false;
    };
    
    dictionary PeriodicWaveOptions : PeriodicWaveConstraints {
        sequence<float> real;
        sequence<float> imag;
    };
    
    [Exposed=Window]
    interface ScriptProcessorNode : AudioNode {
        attribute EventHandler onaudioprocess;
        readonly attribute long bufferSize;
    };
    
    [Exposed=Window]
    interface StereoPannerNode : AudioNode {
        constructor (BaseAudioContext context, optional StereoPannerOptions options = {});
        readonly attribute AudioParam pan;
    };
    
    dictionary StereoPannerOptions : AudioNodeOptions {
        float pan = 0;
    };
    
    enum OverSampleType {
        "none",
        "2x",
        "4x"
    };
    
    [Exposed=Window]
    interface WaveShaperNode : AudioNode {
        constructor (BaseAudioContext context, optional WaveShaperOptions options = {});
        attribute Float32Array? curve;
        attribute OverSampleType oversample;
    };
    
    dictionary WaveShaperOptions : AudioNodeOptions {
        sequence<float> curve;
        OverSampleType oversample = "none";
    };
    
    [Exposed=Window, SecureContext]
    interface AudioWorklet : Worklet {
      readonly attribute MessagePort port;
    };
    
    callback AudioWorkletProcessorConstructor = AudioWorkletProcessor (object options);
    
    [Global=(Worklet, AudioWorklet), Exposed=AudioWorklet]
    interface AudioWorkletGlobalScope : WorkletGlobalScope {
        undefined registerProcessor (DOMString name,
                                                   AudioWorkletProcessorConstructor processorCtor);
        readonly attribute unsigned long long currentFrame;
        readonly attribute double currentTime;
        readonly attribute float sampleRate;
        readonly attribute unsigned long renderQuantumSize;
        readonly attribute MessagePort port;
    };
    
    [Exposed=Window]
    interface AudioParamMap {
        readonly maplike<DOMString, AudioParam>;
    };
    
    [Exposed=Window, SecureContext]
    interface AudioWorkletNode : AudioNode {
        constructor (BaseAudioContext context, DOMString name,
                   optional AudioWorkletNodeOptions options = {});
        readonly attribute AudioParamMap parameters;
        readonly attribute MessagePort port;
        attribute EventHandler onprocessorerror;
    };
    
    dictionary AudioWorkletNodeOptions : AudioNodeOptions {
        unsigned long numberOfInputs = 1;
        unsigned long numberOfOutputs = 1;
        sequence<unsigned long> outputChannelCount;
        record<DOMString, double> parameterData;
        object processorOptions;
    };
    
    [Exposed=AudioWorklet]
    interface AudioWorkletProcessor {
        constructor ();
        readonly attribute MessagePort port;
    };
    
    callback AudioWorkletProcessCallback =
      boolean (FrozenArray<FrozenArray<Float32Array>> inputs,
               FrozenArray<FrozenArray<Float32Array>> outputs,
               object parameters);
    
    dictionary AudioParamDescriptor {
        required DOMString name;
        float defaultValue = 0;
        float minValue = -3.4028235e38;
        float maxValue = 3.4028235e38;
        AutomationRate automationRate = "a-rate";
    };
    
    
    MDN

    AnalyserNode/AnalyserNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/fftSize

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/frequencyBinCount

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/getByteFrequencyData

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/getByteTimeDomainData

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/getFloatFrequencyData

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/getFloatTimeDomainData

    在所有当前引擎中。

    Firefox30+Safari14.1+Chrome35+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/maxDecibels

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/minDecibels

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode/smoothingTimeConstant

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AnalyserNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/AudioBuffer

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView?Samsung Internet6.0+Opera Mobile42+
    MDN

    AudioBuffer/copyFromChannel

    在所有当前引擎中。

    Firefox27+Safari14.1+Chrome43+
    Opera?Edge79+
    Edge (旧版)13+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/copyToChannel

    在所有当前引擎中。

    Firefox27+Safari14.1+Chrome43+
    Opera?Edge79+
    Edge (旧版)13+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/duration

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/getChannelData

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/length

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/numberOfChannels

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer/sampleRate

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBuffer

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/AudioBufferSourceNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/buffer

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/detune

    在所有当前引擎中。

    Firefox40+Safari14.1+Chrome44+
    Opera?Edge79+
    Edge (旧版)13+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/loop

    在所有当前引擎中。

    Firefox25+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/loopEnd

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/loopStart

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/playbackRate

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode/start

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioBufferSourceNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioContext/AudioContext

    在所有当前引擎中。

    Firefox25+Safari14.1+Chrome35+
    Opera22+Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet3.0+Opera Mobile22+
    MDN

    AudioContext/baseLatency

    在所有当前引擎中。

    Firefox70+Safari14.1+Chrome58+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/close

    在所有当前引擎中。

    Firefox40+Safari9+Chrome42+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/createMediaElementSource

    在所有当前引擎中。

    Firefox25+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioContext/createMediaStreamDestination

    在所有当前引擎中。

    Firefox25+Safari11+Chrome25+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioContext/createMediaStreamSource

    在所有当前引擎中。

    Firefox25+Safari11+Chrome22+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioContext/createMediaStreamTrackSource

    仅在一种当前的引擎中可用。

    Firefox68+SafariChrome
    Opera?Edge
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/getOutputTimestamp

    在所有当前引擎中。

    Firefox70+Safari14.1+Chrome57+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/outputLatency

    Firefox70+SafariChrome102+
    Opera?Edge102+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/resume

    在所有当前引擎中。

    Firefox40+Safari9+Chrome41+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/setSinkId

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome110+
    Opera?Edge110+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/sinkchange_event

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome110+
    Opera?Edge110+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/sinkId

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome110+
    Opera?Edge110+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext/suspend

    在所有当前引擎中。

    Firefox40+Safari9+Chrome41+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioContext

    在所有当前引擎中。

    Firefox25+Safari14.1+Chrome35+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioDestinationNode/maxChannelCount

    在所有当前引擎中。

    Firefox25+Safari14.1+Chrome27+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioDestinationNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioListener/forwardX

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/forwardY

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/forwardZ

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/positionX

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/positionY

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/positionZ

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/upX

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/upY

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener/upZ

    FirefoxSafari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioListener

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/channelCount

    在所有当前引擎中。

    Firefox25+Safari7+Chrome27+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/channelCountMode

    在所有当前引擎中。

    Firefox25+Safari7+Chrome27+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/channelInterpretation

    在所有当前引擎中。

    Firefox25+Safari7+Chrome27+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/connect

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/connect

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/context

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/disconnect

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/numberOfInputs

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode/numberOfOutputs

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    AudioParam/cancelAndHoldAtTime

    FirefoxSafari14.1+Chrome57+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioParam/cancelScheduledValues

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParam/defaultValue

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParam/exponentialRampToValueAtTime

    FirefoxSafari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 ChromeAndroid WebView37+Samsung Internet1.0+Opera Mobile14+
    MDN

    AudioParam/linearRampToValueAtTime

    FirefoxSafari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 ChromeAndroid WebView37+Samsung Internet1.0+Opera Mobile14+
    MDN

    AudioParam/maxValue

    在所有当前引擎中。

    Firefox53+Safari6+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioParam/minValue

    在所有当前引擎中。

    Firefox53+Safari6+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioParam/setTargetAtTime

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParam/setValueAtTime

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParam/setValueCurveAtTime

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParam/value

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox25+iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParam

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioParamMap

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioScheduledSourceNode/ended_event

    在所有当前引擎中。

    Firefox25+Safari7+Chrome30+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    AudioScheduledSourceNode/start

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioScheduledSourceNode/stop

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioScheduledSourceNode

    在所有当前引擎中。

    Firefox53+Safari14+Chrome57+
    Opera?Edge79+
    Edge (旧版)IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView57+Samsung Internet?Opera Mobile?
    MDN

    AudioSinkInfo/type

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome110+
    Opera?Edge110+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioSinkInfo

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome110+
    Opera?Edge110+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorklet

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletGlobalScope/currentFrame

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 FirefoxiOS 版 Safari?Android 版 Chrome?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletGlobalScope/currentTime

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 FirefoxiOS 版 Safari?Android 版 Chrome?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletGlobalScope/registerProcessor

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 FirefoxiOS 版 Safari?Android 版 Chrome?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletGlobalScope/sampleRate

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 FirefoxiOS 版 Safari?Android 版 Chrome?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletGlobalScope

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 FirefoxiOS 版 Safari?Android 版 Chrome?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletNode/AudioWorkletNode

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletNode/parameters

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletNode/port

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletNode/processorerror_event

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletNode

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletProcessor/AudioWorkletProcessor

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome64+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletProcessor/port

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome64+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    AudioWorkletProcessor

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome64+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/audioWorklet

    在所有当前引擎中。

    Firefox76+Safari14.1+Chrome66+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createAnalyser

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createBiquadFilter

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createBuffer

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createBufferSource

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createChannelMerger

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createChannelSplitter

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createConstantSource

    在所有当前引擎中。

    Firefox52+Safari14.1+Chrome56+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createConvolver

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createDelay

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createDynamicsCompressor

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createGain

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createIIRFilter

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome49+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createOscillator

    在所有当前引擎中。

    Firefox25+Safari6+Chrome20+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createPanner

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createPeriodicWave

    在所有当前引擎中。

    Firefox25+Safari8+Chrome30+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createStereoPanner

    在所有当前引擎中。

    Firefox37+Safari14.1+Chrome41+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/createWaveShaper

    在所有当前引擎中。

    Firefox25+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/currentTime

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/decodeAudioData

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/destination

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/listener

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/sampleRate

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/state

    在所有当前引擎中。

    Firefox40+Safari9+Chrome41+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BaseAudioContext/statechange_event

    在所有当前引擎中。

    Firefox40+Safari9+Chrome41+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN
    MDN

    BiquadFilterNode/BiquadFilterNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode/Q

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode/detune

    在所有当前引擎中。

    Firefox25+Safari7+Chrome25+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode/frequency

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode/gain

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode/getFrequencyResponse

    在所有当前引擎中。

    Firefox25+Safari6+Chrome17+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode/type

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    BiquadFilterNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    ChannelMergerNode/ChannelMergerNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    ChannelMergerNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    ChannelSplitterNode/ChannelSplitterNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    ChannelSplitterNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    ConstantSourceNode/ConstantSourceNode

    在所有当前引擎中。

    Firefox52+Safari14.1+Chrome56+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    ConstantSourceNode/offset

    在所有当前引擎中。

    Firefox52+Safari14.1+Chrome56+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    ConstantSourceNode

    在所有当前引擎中。

    Firefox52+Safari14.1+Chrome56+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    ConvolverNode/ConvolverNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    ConvolverNode/buffer

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    ConvolverNode/normalize

    在所有当前引擎中。

    Firefox25+Safari6+Chrome18+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    ConvolverNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    DelayNode/DelayNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    DelayNode/delayTime

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DelayNode

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode/DynamicsCompressorNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode/attack

    在所有当前引擎中。

    Firefox25+Safari6+Chrome19+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode/knee

    在所有当前引擎中。

    Firefox25+Safari6+Chrome19+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode/ratio

    在所有当前引擎中。

    Firefox25+Safari6+Chrome19+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode/reduction

    在所有当前引擎中。

    Firefox25+Safari6+Chrome19+
    Opera15+Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet1.0+Opera Mobile14+
    MDN

    DynamicsCompressorNode/release

    在所有当前引擎中。

    Firefox25+Safari6+Chrome20+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode/threshold

    在所有当前引擎中。

    Firefox25+Safari6+Chrome19+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    DynamicsCompressorNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    GainNode/GainNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    GainNode/gain

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    GainNode

    在所有当前引擎中。

    Firefox25+Safari7+Chrome24+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    IIRFilterNode/IIRFilterNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    IIRFilterNode/getFrequencyResponse

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome49+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    IIRFilterNode

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome49+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaElementAudioSourceNode/MediaElementAudioSourceNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaElementAudioSourceNode/mediaElement

    在所有当前引擎中。

    Firefox70+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)?IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    MediaElementAudioSourceNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    MediaStreamAudioDestinationNode/MediaStreamAudioDestinationNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome57+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaStreamAudioDestinationNode/stream

    在所有当前引擎中。

    Firefox25+Safari11+Chrome25+
    Opera?Edge79+
    Edge (旧版)18IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    MediaStreamAudioDestinationNode

    在所有当前引擎中。

    Firefox25+Safari11+Chrome25+
    Opera?Edge79+
    Edge (旧版)18IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    MediaStreamAudioSourceNode/MediaStreamAudioSourceNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaStreamAudioSourceNode/mediaStream

    在所有当前引擎中。

    Firefox70+Safari11+Chrome22+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaStreamAudioSourceNode

    在所有当前引擎中。

    Firefox25+Safari11+Chrome22+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaStreamTrackAudioSourceNode/MediaStreamTrackAudioSourceNode

    仅在一种当前的引擎中可用。

    Firefox68+SafariChrome
    Opera?Edge
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    MediaStreamTrackAudioSourceNode

    仅在一种当前的引擎中可用。

    Firefox68+SafariChrome
    Opera?Edge
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioCompletionEvent/OfflineAudioCompletionEvent

    在所有当前引擎中。

    Firefox53+Safari14+Chrome57+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioCompletionEvent/renderedBuffer

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioCompletionEvent

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?

    OfflineAudioContext/complete_event

    在所有当前引擎中。

    Firefox25+Safari7+Chrome25+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext/OfflineAudioContext

    在所有当前引擎中。

    Firefox25+Safari14.1+Chrome35+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext/complete_event

    在所有当前引擎中。

    Firefox25+Safari7+Chrome25+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext/length

    在所有当前引擎中。

    Firefox49+Safari14.1+Chrome51+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext/resume

    在所有当前引擎中。

    Firefox40+Safari9+Chrome41+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext/startRendering

    在所有当前引擎中。

    Firefox25+Safari7+Chrome25+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext/suspend

    FirefoxSafari9+Chrome41+
    Opera?Edge79+
    Edge (旧版)14+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OfflineAudioContext

    在所有当前引擎中。

    Firefox25+Safari14.1+Chrome35+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OscillatorNode/OscillatorNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OscillatorNode/detune

    在所有当前引擎中。

    Firefox25+Safari6+Chrome20+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OscillatorNode/frequency

    在所有当前引擎中。

    Firefox25+Safari6+Chrome20+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OscillatorNode/setPeriodicWave

    在所有当前引擎中。

    Firefox25+Safari8+Chrome30+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    OscillatorNode/type

    在所有当前引擎中。

    Firefox25+Safari6+Chrome20+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    OscillatorNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome20+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/PannerNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/coneInnerAngle

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/coneOuterAngle

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/coneOuterGain

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/distanceModel

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/maxDistance

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/orientationX

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/orientationY

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/orientationZ

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/panningModel

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/positionX

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/positionY

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/positionZ

    在所有当前引擎中。

    Firefox50+Safari14.1+Chrome52+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PannerNode/refDistance

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode/rolloffFactor

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PannerNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome14+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    PeriodicWave/PeriodicWave

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PeriodicWave

    在所有当前引擎中。

    Firefox25+Safari8+Chrome30+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox26+iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    StereoPannerNode/StereoPannerNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    StereoPannerNode/pan

    在所有当前引擎中。

    Firefox37+Safari14.1+Chrome41+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    StereoPannerNode

    在所有当前引擎中。

    Firefox37+Safari14.1+Chrome41+
    Opera?Edge79+
    Edge (旧版)12+IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    WaveShaperNode/WaveShaperNode

    在所有当前引擎中。

    Firefox53+Safari14.1+Chrome55+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    WaveShaperNode/curve

    在所有当前引擎中。

    Firefox25+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?
    MDN

    WaveShaperNode/oversample

    在所有当前引擎中。

    Firefox26+Safari6+Chrome29+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView37+Samsung Internet?Opera Mobile?
    MDN

    WaveShaperNode

    在所有当前引擎中。

    Firefox25+Safari6+Chrome15+
    Opera?Edge79+
    Edge (旧版)12+IE
    Android 版 Firefox?iOS 版 Safari?Android 版 Chrome?Android WebView4.4.3+Samsung Internet?Opera Mobile?