зеркало из https://github.com/mozilla/gecko-dev.git
5916 строки
227 KiB
HTML
5916 строки
227 KiB
HTML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<title>Web Audio API</title>
|
|
<meta name="revision"
|
|
content="$Id: Overview.html,v 1.4 2012/07/30 11:44:57 tmichel Exp $" />
|
|
<link rel="stylesheet" href="style.css" type="text/css" />
|
|
<!--
|
|
<script src="section-links.js" type="application/ecmascript"></script>
|
|
<script src="dfn.js" type="application/ecmascript"></script>
|
|
-->
|
|
<!--[if IE]>
|
|
<style type='text/css'>
|
|
.ignore {
|
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
|
|
filter: alpha(opacity=50);
|
|
}
|
|
</style>
|
|
<![endif]-->
|
|
<link rel="stylesheet" href="//www.w3.org/StyleSheets/TR/W3C-ED"
|
|
type="text/css" />
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="head">
|
|
<p><a href="http://www.w3.org/"><img width="72" height="48" alt="W3C"
|
|
src="http://www.w3.org/Icons/w3c_home" /></a> </p>
|
|
|
|
<h1 id="title" class="title">Web Audio API </h1>
|
|
|
|
<h2 id="w3c-date-document"><acronym
|
|
title="World Wide Web Consortium">W3C</acronym> Editor's Draft
|
|
</h2>
|
|
<dl>
|
|
<dt>This version: </dt>
|
|
<dd><a
|
|
href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html</a>
|
|
</dd>
|
|
<dt>Latest published version: </dt>
|
|
<dd><a
|
|
href="http://www.w3.org/TR/webaudio/">http://www.w3.org/TR/webaudio/</a>
|
|
</dd>
|
|
<dt>Previous version: </dt>
|
|
<dd><a
|
|
href="http://www.w3.org/TR/2012/WD-webaudio-20120315/">http://www.w3.org/TR/2012/WD-webaudio-20120315/</a>
|
|
</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
<dt>Editor: </dt>
|
|
<dd>Chris Rogers, Google <crogers@google.com></dd>
|
|
</dl>
|
|
|
|
<p class="copyright"><a
|
|
href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> ©
|
|
2012 <a href="http://www.w3.org/"><acronym
|
|
title="World Wide Web Consortium">W3C</acronym></a><sup>®</sup> (<a
|
|
href="http://www.csail.mit.edu/"><acronym
|
|
title="Massachusetts Institute of Technology">MIT</acronym></a>, <a
|
|
href="http://www.ercim.eu/"><acronym
|
|
title="European Research Consortium for Informatics and Mathematics">ERCIM</acronym></a>,
|
|
<a href="http://www.keio.ac.jp/">Keio</a>), All Rights Reserved. W3C <a
|
|
href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>,
|
|
<a
|
|
href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a>
|
|
and <a href="http://www.w3.org/Consortium/Legal/copyright-documents">document
|
|
use</a> rules apply.</p>
|
|
<hr />
|
|
</div>
|
|
|
|
<div id="abstract-section" class="section">
|
|
<h2 id="abstract">Abstract</h2>
|
|
|
|
<p>This specification describes a high-level JavaScript <acronym
|
|
title="Application Programming Interface">API</acronym> for processing and
|
|
synthesizing audio in web applications. The primary paradigm is of an audio
|
|
routing graph, where a number of <a
|
|
href="#AudioNode-section"><code>AudioNode</code></a> objects are connected
|
|
together to define the overall audio rendering. The actual processing will
|
|
primarily take place in the underlying implementation (typically optimized
|
|
Assembly / C / C++ code), but <a href="#JavaScriptProcessing-section">direct
|
|
JavaScript processing and synthesis</a> is also supported. </p>
|
|
|
|
<p>The <a href="#introduction">introductory</a> section covers the motivation
|
|
behind this specification.</p>
|
|
|
|
<p>This API is designed to be used in conjunction with other APIs and elements
|
|
on the web platform, notably: XMLHttpRequest
|
|
(using the <code>responseType</code> and <code>response</code> attributes). For
|
|
games and interactive applications, it is anticipated to be used with the
|
|
<code>canvas</code> 2D and WebGL 3D graphics APIs. </p>
|
|
</div>
|
|
|
|
<div id="sotd-section" class="section">
|
|
<h2 id="sotd">Status of this Document</h2>
|
|
|
|
|
|
<p><em>This section describes the status of this document at the time of its
|
|
publication. Other documents may supersede this document. A list of current W3C
|
|
publications and the latest revision of this technical report can be found in
|
|
the <a href="http://www.w3.org/TR/">W3C technical reports index</a> at
|
|
http://www.w3.org/TR/. </em></p>
|
|
|
|
<p>This is the Editor's Draft of the <cite>Web Audio API</cite>
|
|
specification. It has been produced by the <a
|
|
href="http://www.w3.org/2011/audio/"><b>W3C Audio Working Group</b></a> , which
|
|
is part of the W3C WebApps Activity.</p>
|
|
|
|
<p></p>
|
|
|
|
<p>Please send comments about this document to <<a
|
|
href="mailto:public-audio@w3.org">public-audio@w3.org</a>> (<a
|
|
href="http://lists.w3.org/Archives/Public/public-audio/">public archives</a> of
|
|
the W3C audio mailing list). Web content and browser developers are encouraged
|
|
to review this draft. </p>
|
|
|
|
<p>Publication as a Working Draft does not imply endorsement by the W3C
|
|
Membership. This is a draft document and may be updated, replaced or obsoleted
|
|
by other documents at any time. It is inappropriate to cite this document as
|
|
other than work in progress.</p>
|
|
|
|
<p> This document was produced by a group operating under the <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 February 2004 W3C Patent Policy</a>. W3C maintains a <a rel="disclosure" href="http://www.w3.org/2004/01/pp-impl/46884/status">public list of any patent disclosures</a> made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential">Essential Claim(s)</a> must disclose the information in accordance with <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure">section 6 of the W3C Patent Policy</a>. </p>
|
|
</div>
|
|
|
|
<div id="toc">
|
|
<h2 id="L13522">Table of Contents</h2>
|
|
|
|
<div class="toc">
|
|
<ul>
|
|
<li><a href="#introduction">1. Introduction</a>
|
|
<ul>
|
|
<li><a href="#Features">1.1. Features</a></li>
|
|
<li><a href="#ModularRouting">1.2. Modular Routing</a></li>
|
|
<li><a href="#APIOverview">1.3. API Overview</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#conformance">2. Conformance</a></li>
|
|
<li><a href="#API-section">4. The Audio API</a>
|
|
<ul>
|
|
<li><a href="#AudioContext-section">4.1. The AudioContext Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioContext">4.1.1. Attributes</a></li>
|
|
<li><a href="#methodsandparams-AudioContext">4.1.2. Methods and
|
|
Parameters</a></li>
|
|
<li><a href="#lifetime-AudioContext">4.1.3. Lifetime</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#OfflineAudioContext-section">4.1b. The OfflineAudioContext Interface</a>
|
|
</li>
|
|
|
|
<li><a href="#AudioNode-section">4.2. The AudioNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioNode">4.2.1. Attributes</a></li>
|
|
<li><a href="#methodsandparams-AudioNode">4.2.2. Methods and
|
|
Parameters</a></li>
|
|
<li><a href="#lifetime-AudioNode">4.2.3. Lifetime</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AudioDestinationNode">4.4. The AudioDestinationNode
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioDestinationNode">4.4.1. Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AudioParam">4.5. The AudioParam Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioParam">4.5.1. Attributes</a></li>
|
|
<li><a href="#methodsandparams-AudioParam">4.5.2. Methods and
|
|
Parameters</a></li>
|
|
<li><a href="#computedValue-AudioParam-section">4.5.3. Computation of Value</a></li>
|
|
<li><a href="#example1-AudioParam-section">4.5.4. AudioParam Automation Example</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#GainNode">4.7. The GainNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-GainNode">4.7.1. Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#DelayNode">4.8. The DelayNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-GainNode_2">4.8.1. Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AudioBuffer">4.9. The AudioBuffer Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioBuffer">4.9.1. Attributes</a></li>
|
|
<li><a href="#methodsandparams-AudioBuffer">4.9.2. Methods and
|
|
Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AudioBufferSourceNode">4.10. The AudioBufferSourceNode
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioBufferSourceNode">4.10.1.
|
|
Attributes</a></li>
|
|
<li><a href="#methodsandparams-AudioBufferSourceNode">4.10.2. Methods and
|
|
Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#MediaElementAudioSourceNode">4.11. The
|
|
MediaElementAudioSourceNode Interface</a></li>
|
|
<li><a href="#ScriptProcessorNode">4.12. The ScriptProcessorNode
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-ScriptProcessorNode">4.12.1. Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AudioProcessingEvent">4.13. The AudioProcessingEvent
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioProcessingEvent">4.13.1. Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#PannerNode">4.14. The PannerNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-PannerNode_attributes">4.14.2.
|
|
Attributes</a></li>
|
|
<li><a href="#Methods_and_Parameters">4.14.3. Methods and
|
|
Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AudioListener">4.15. The AudioListener Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-AudioListener">4.15.1. Attributes</a></li>
|
|
<li><a href="#L15842">4.15.2. Methods and Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#ConvolverNode">4.16. The ConvolverNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-ConvolverNode">4.16.1. Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#AnalyserNode">4.17. The AnalyserNode
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-ConvolverNode_2">4.17.1. Attributes</a></li>
|
|
<li><a href="#methods-and-parameters">4.17.2. Methods and
|
|
Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#ChannelSplitterNode">4.18. The ChannelSplitterNode
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#example-1">Example:</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#ChannelMergerNode">4.19. The ChannelMergerNode Interface</a>
|
|
<ul>
|
|
<li><a href="#example-2">Example:</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#DynamicsCompressorNode">4.20. The DynamicsCompressorNode
|
|
Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-DynamicsCompressorNode">4.20.1.
|
|
Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#BiquadFilterNode">4.21. The BiquadFilterNode Interface</a>
|
|
<ul>
|
|
<li><a href="#BiquadFilterNode-description">4.21.1 Lowpass</a></li>
|
|
<li><a href="#HIGHPASS">4.21.2 Highpass</a></li>
|
|
<li><a href="#BANDPASS">4.21.3 Bandpass</a></li>
|
|
<li><a href="#LOWSHELF">4.21.4 Lowshelf</a></li>
|
|
<li><a href="#L16352">4.21.5 Highshelf</a></li>
|
|
<li><a href="#PEAKING">4.21.6 Peaking</a></li>
|
|
<li><a href="#NOTCH">4.21.7 Notch</a></li>
|
|
<li><a href="#ALLPASS">4.21.8 Allpass</a></li>
|
|
<li><a href="#Methods">4.21.9. Methods</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#WaveShaperNode">4.22. The WaveShaperNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-WaveShaperNode">4.22.1.
|
|
Attributes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#OscillatorNode">4.23. The OscillatorNode Interface</a>
|
|
<ul>
|
|
<li><a href="#attributes-OscillatorNode">4.23.1.
|
|
Attributes</a></li>
|
|
<li><a href="#methodsandparams-OscillatorNode-section">4.23.2. Methods and
|
|
Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#PeriodicWave">4.24. The PeriodicWave Interface</a>
|
|
</li>
|
|
<li><a href="#MediaStreamAudioSourceNode">4.25. The
|
|
MediaStreamAudioSourceNode Interface</a></li>
|
|
<li><a href="#MediaStreamAudioDestinationNode">4.26. The
|
|
MediaStreamAudioDestinationNode Interface</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#MixerGainStructure">6. Mixer Gain Structure</a>
|
|
<ul>
|
|
<li><a href="#background">Background</a></li>
|
|
<li><a href="#SummingJunction">Summing Inputs</a></li>
|
|
<li><a href="#gain-Control">Gain Control</a></li>
|
|
<li><a href="#Example-mixer-with-send-busses">Example: Mixer with Send
|
|
Busses</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#DynamicLifetime">7. Dynamic Lifetime</a>
|
|
<ul>
|
|
<li><a href="#DynamicLifetime-background">Background</a></li>
|
|
<li><a href="#Example-DynamicLifetime">Example</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#UpMix">9. Channel up-mixing and down-mixing</a>
|
|
<ul>
|
|
<li><a href="#ChannelLayouts">9.1. Speaker Channel Layouts</a>
|
|
<ul>
|
|
<li><a href="#ChannelOrdering">9.1.1. Channel Ordering</a></li>
|
|
<li><a href="#UpMix-sub">9.1.2. Up Mixing</a></li>
|
|
<li><a href="#down-mix">9.1.3. Down Mixing</a></li>
|
|
</ul>
|
|
</li>
|
|
|
|
<li><a href="#ChannelRules-section">9.2. Channel Rules Examples</a>
|
|
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Spatialization">11. Spatialization / Panning </a>
|
|
<ul>
|
|
<li><a href="#Spatialization-background">Background</a></li>
|
|
<li><a href="#Spatialization-panning-algorithm">Panning Algorithm</a></li>
|
|
<li><a href="#Spatialization-distance-effects">Distance Effects</a></li>
|
|
<li><a href="#Spatialization-sound-cones">Sound Cones</a></li>
|
|
<li><a href="#Spatialization-doppler-shift">Doppler Shift</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Convolution">12. Linear Effects using Convolution</a>
|
|
<ul>
|
|
<li><a href="#Convolution-background">Background</a></li>
|
|
<li><a href="#Convolution-motivation">Motivation for use as a
|
|
Standard</a></li>
|
|
<li><a href="#Convolution-implementation-guide">Implementation Guide</a></li>
|
|
<li><a href="#Convolution-reverb-effect">Reverb Effect (with
|
|
matrixing)</a></li>
|
|
<li><a href="#recording-impulse-responses">Recording Impulse
|
|
Responses</a></li>
|
|
<li><a href="#tools">Tools</a></li>
|
|
<li><a href="#recording-setup">Recording Setup</a></li>
|
|
<li><a href="#warehouse">The Warehouse Space</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#JavaScriptProcessing">13. JavaScript Synthesis and
|
|
Processing</a>
|
|
<ul>
|
|
<li><a href="#custom-DSP-effects">Custom DSP Effects</a></li>
|
|
<li><a href="#educational-applications">Educational Applications</a></li>
|
|
<li><a href="#javaScript-performance">JavaScript Performance</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Performance">15. Performance Considerations</a>
|
|
<ul>
|
|
<li><a href="#Latency">15.1. Latency: What it is and Why it's
|
|
Important</a></li>
|
|
<li><a href="#audio-glitching">15.2. Audio Glitching</a></li>
|
|
<li><a href="#hardware-scalability">15.3. Hardware Scalability</a>
|
|
<ul>
|
|
<li><a href="#CPU-monitoring">15.3.1. CPU monitoring</a></li>
|
|
<li><a href="#Voice-dropping">15.3.2. Voice Dropping</a></li>
|
|
<li><a href="#Simplification-of-Effects-Processing">15.3.3.
|
|
Simplification of Effects Processing</a></li>
|
|
<li><a href="#Sample-rate">15.3.4. Sample Rate</a></li>
|
|
<li><a href="#pre-flighting">15.3.5. Pre-flighting</a></li>
|
|
<li><a href="#Authoring-for-different-user-agents">15.3.6. Authoring
|
|
for different user agents</a></li>
|
|
<li><a href="#Scalability-of-Direct-JavaScript-Synthesis">15.3.7.
|
|
Scalability of Direct JavaScript Synthesis / Processing</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#JavaScriptPerformance">15.4. JavaScript Issues with
|
|
real-time Processing and Synthesis: </a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#ExampleApplications">16. Example Applications</a>
|
|
<ul>
|
|
<li><a href="#basic-sound-playback">Basic Sound Playback</a></li>
|
|
<li><a href="#threeD-environmentse-and-games">3D Environments and
|
|
Games</a></li>
|
|
<li><a href="#musical-applications">Musical Applications</a></li>
|
|
<li><a href="#music-visualizers">Music Visualizers</a></li>
|
|
<li><a href="#educational-applications_2">Educational
|
|
Applications</a></li>
|
|
<li><a href="#artistic-audio-exploration">Artistic Audio
|
|
Exploration</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#SecurityConsiderations">17. Security Considerations</a></li>
|
|
<li><a href="#PrivacyConsiderations">18. Privacy Considerations</a></li>
|
|
<li><a href="#requirements">19. Requirements and Use Cases</a></li>
|
|
<li><a href="#OldNames">20. Old Names</a></li>
|
|
<li><a href="#L17310">A.References</a>
|
|
<ul>
|
|
<li><a href="#Normative-references">A.1 Normative references</a></li>
|
|
<li><a href="#Informative-references">A.2 Informative references</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#L17335">B.Acknowledgements</a></li>
|
|
<li><a href="#ChangeLog">C. Web Audio API Change Log</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="sections">
|
|
|
|
<div id="div-introduction" class="section">
|
|
<h2 id="introduction">1. Introduction</h2>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<p>Audio on the web has been fairly primitive up to this point and until very
|
|
recently has had to be delivered through plugins such as Flash and QuickTime.
|
|
The introduction of the <code>audio</code> element in HTML5 is very important,
|
|
allowing for basic streaming audio playback. But, it is not powerful enough to
|
|
handle more complex audio applications. For sophisticated web-based games or
|
|
interactive applications, another solution is required. It is a goal of this
|
|
specification to include the capabilities found in modern game audio engines as
|
|
well as some of the mixing, processing, and filtering tasks that are found in
|
|
modern desktop audio production applications. </p>
|
|
|
|
<p>The APIs have been designed with a wide variety of <a
|
|
href="#ExampleApplications-section">use cases</a> in mind. Ideally, it should
|
|
be able to support <i>any</i> use case which could reasonably be implemented
|
|
with an optimized C++ engine controlled via JavaScript and run in a browser.
|
|
That said, modern desktop audio software can have very advanced capabilities,
|
|
some of which would be difficult or impossible to build with this system.
|
|
Apple's Logic Audio is one such application which has support for external MIDI
|
|
controllers, arbitrary plugin audio effects and synthesizers, highly optimized
|
|
direct-to-disk audio file reading/writing, tightly integrated time-stretching,
|
|
and so on. Nevertheless, the proposed system will be quite capable of
|
|
supporting a large range of reasonably complex games and interactive
|
|
applications, including musical ones. And it can be a very good complement to
|
|
the more advanced graphics features offered by WebGL. The API has been designed
|
|
so that more advanced capabilities can be added at a later time. </p>
|
|
|
|
<div id="Features-section" class="section">
|
|
<h2 id="Features">1.1. Features</h2>
|
|
</div>
|
|
|
|
<p>The API supports these primary features: </p>
|
|
<ul>
|
|
<li><a href="#ModularRouting-section">Modular routing</a> for simple or
|
|
complex mixing/effect architectures, including <a
|
|
href="#MixerGainStructure-section">multiple sends and submixes</a>.</li>
|
|
<li><a href="#AudioParam">Sample-accurate scheduled sound
|
|
playback</a> with low <a href="#Latency-section">latency</a> for musical
|
|
applications requiring a very high degree of rhythmic precision such as
|
|
drum machines and sequencers. This also includes the possibility of <a
|
|
href="#DynamicLifetime-section">dynamic creation</a> of effects. </li>
|
|
<li>Automation of audio parameters for envelopes, fade-ins / fade-outs,
|
|
granular effects, filter sweeps, LFOs etc. </li>
|
|
<li>Flexible handling of channels in an audio stream, allowing them to be split and merged.</li>
|
|
|
|
<li>Processing of audio sources from an <code>audio</code> or
|
|
<code>video</code> <a href="#MediaElementAudioSourceNode">media
|
|
element</a>. </li>
|
|
|
|
<li>Processing live audio input using a <a href="#MediaStreamAudioSourceNode">MediaStream</a>
|
|
from getUserMedia().
|
|
</li>
|
|
|
|
<li>Integration with WebRTC
|
|
<ul>
|
|
|
|
|
|
<li>Processing audio received from a remote peer using a <a href="#MediaStreamAudioSourceNode">MediaStream</a>.
|
|
</li>
|
|
|
|
<li>Sending a generated or processed audio stream to a remote peer using a <a href="#MediaStreamAudioDestinationNode">MediaStream</a>.
|
|
</li>
|
|
|
|
</ul>
|
|
</li>
|
|
|
|
<li>Audio stream synthesis and processing <a
|
|
href="#JavaScriptProcessing-section">directly in JavaScript</a>. </li>
|
|
<li><a href="#Spatialization-section">Spatialized audio</a> supporting a wide
|
|
range of 3D games and immersive environments:
|
|
<ul>
|
|
<li>Panning models: equal-power, HRTF, pass-through </li>
|
|
<li>Distance Attenuation </li>
|
|
<li>Sound Cones </li>
|
|
<li>Obstruction / Occlusion </li>
|
|
<li>Doppler Shift </li>
|
|
<li>Source / Listener based</li>
|
|
</ul>
|
|
</li>
|
|
<li>A <a href="#Convolution-section">convolution engine</a> for a wide range
|
|
of linear effects, especially very high-quality room effects. Here are some
|
|
examples of possible effects:
|
|
<ul>
|
|
<li>Small / large room </li>
|
|
<li>Cathedral </li>
|
|
<li>Concert hall </li>
|
|
<li>Cave </li>
|
|
<li>Tunnel </li>
|
|
<li>Hallway </li>
|
|
<li>Forest </li>
|
|
<li>Amphitheater </li>
|
|
<li>Sound of a distant room through a doorway </li>
|
|
<li>Extreme filters</li>
|
|
<li>Strange backwards effects</li>
|
|
<li>Extreme comb filter effects </li>
|
|
</ul>
|
|
</li>
|
|
<li>Dynamics compression for overall control and sweetening of the mix </li>
|
|
<li>Efficient <a href="#AnalyserNode">real-time time-domain and
|
|
frequency analysis / music visualizer support</a></li>
|
|
<li>Efficient biquad filters for lowpass, highpass, and other common filters.
|
|
</li>
|
|
<li>A Waveshaping effect for distortion and other non-linear effects</li>
|
|
<li>Oscillators</li>
|
|
|
|
</ul>
|
|
|
|
<div id="ModularRouting-section">
|
|
<h2 id="ModularRouting">1.2. Modular Routing</h2>
|
|
|
|
<p>Modular routing allows arbitrary connections between different <a
|
|
href="#AudioNode-section"><code>AudioNode</code></a> objects. Each node can
|
|
have <dfn>inputs</dfn> and/or <dfn>outputs</dfn>. A <dfn>source node</dfn> has no inputs
|
|
and a single output. A <dfn>destination node</dfn> has
|
|
one input and no outputs, the most common example being <a
|
|
href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a> the final destination to the audio
|
|
hardware. Other nodes such as filters can be placed between the source and destination nodes.
|
|
The developer doesn't have to worry about low-level stream format details
|
|
when two objects are connected together; <a href="#UpMix-section">the right
|
|
thing just happens</a>. For example, if a mono audio stream is connected to a
|
|
stereo input it should just mix to left and right channels <a
|
|
href="#UpMix-section">appropriately</a>. </p>
|
|
|
|
<p>In the simplest case, a single source can be routed directly to the output.
|
|
All routing occurs within an <a
|
|
href="#AudioContext-section"><code>AudioContext</code></a> containing a single
|
|
<a href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a>:
|
|
</p>
|
|
<img alt="modular routing" src="images/modular-routing1.png" />
|
|
|
|
<p>Illustrating this simple routing, here's a simple example playing a single
|
|
sound: </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">ECMAScript</span> </div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
|
|
var context = new AudioContext();
|
|
|
|
function playSound() {
|
|
var source = context.createBufferSource();
|
|
source.buffer = dogBarkingBuffer;
|
|
source.connect(context.destination);
|
|
source.start(0);
|
|
}
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<p>Here's a more complex example with three sources and a convolution reverb
|
|
send with a dynamics compressor at the final output stage: </p>
|
|
<img alt="modular routing2" src="images/modular-routing2.png" />
|
|
|
|
<div class="example">
|
|
|
|
<div class="exampleHeader">
|
|
Example</div>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">ECMAScript</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
|
|
var context = 0;
|
|
var compressor = 0;
|
|
var reverb = 0;
|
|
|
|
var source1 = 0;
|
|
var source2 = 0;
|
|
var source3 = 0;
|
|
|
|
var lowpassFilter = 0;
|
|
var waveShaper = 0;
|
|
var panner = 0;
|
|
|
|
var dry1 = 0;
|
|
var dry2 = 0;
|
|
var dry3 = 0;
|
|
|
|
var wet1 = 0;
|
|
var wet2 = 0;
|
|
var wet3 = 0;
|
|
|
|
var masterDry = 0;
|
|
var masterWet = 0;
|
|
|
|
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 master wet and dry.
|
|
masterDry = context.createGain();
|
|
masterWet = context.createGain();
|
|
|
|
// Connect final compressor to final destination.
|
|
compressor.connect(context.destination);
|
|
|
|
// Connect master dry and wet to compressor.
|
|
masterDry.connect(compressor);
|
|
masterWet.connect(compressor);
|
|
|
|
// Connect reverb to master wet.
|
|
reverb.connect(masterWet);
|
|
|
|
// 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(masterDry);
|
|
wet1.connect(reverb);
|
|
|
|
// Connect source2
|
|
dry2 = context.createGain();
|
|
wet2 = context.createGain();
|
|
source2.connect(waveShaper);
|
|
waveShaper.connect(dry2);
|
|
waveShaper.connect(wet2);
|
|
dry2.connect(masterDry);
|
|
wet2.connect(reverb);
|
|
|
|
// Connect source3
|
|
dry3 = context.createGain();
|
|
wet3 = context.createGain();
|
|
source3.connect(panner);
|
|
panner.connect(dry3);
|
|
panner.connect(wet3);
|
|
dry3.connect(masterDry);
|
|
wet3.connect(reverb);
|
|
|
|
// Start the sources now.
|
|
source1.start(0);
|
|
source2.start(0);
|
|
source3.start(0);
|
|
}
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div id="APIOverview-section" class="section">
|
|
<h2 id="APIOverview">1.3. API Overview</h2>
|
|
</div>
|
|
|
|
<p>The interfaces defined are: </p>
|
|
<ul>
|
|
<li>An <a class="dfnref" href="#AudioContext-section">AudioContext</a>
|
|
interface, which contains an audio signal graph representing connections
|
|
betweens AudioNodes. </li>
|
|
<li>An <a class="dfnref" href="#AudioNode-section">AudioNode</a> interface,
|
|
which represents audio sources, audio outputs, and intermediate processing
|
|
modules. AudioNodes can be dynamically connected together in a <a
|
|
href="#ModularRouting-section">modular fashion</a>. <code>AudioNodes</code>
|
|
exist in the context of an <code>AudioContext</code> </li>
|
|
<li>An <a class="dfnref"
|
|
href="#AudioDestinationNode-section">AudioDestinationNode</a> interface, an
|
|
AudioNode subclass representing the final destination for all rendered
|
|
audio. </li>
|
|
<li>An <a class="dfnref" href="#AudioBuffer-section">AudioBuffer</a>
|
|
interface, for working with memory-resident audio assets. These can
|
|
represent one-shot sounds, or longer audio clips. </li>
|
|
<li>An <a class="dfnref"
|
|
href="#AudioBufferSourceNode-section">AudioBufferSourceNode</a> interface,
|
|
an AudioNode which generates audio from an AudioBuffer. </li>
|
|
<li>A <a class="dfnref"
|
|
href="#MediaElementAudioSourceNode-section">MediaElementAudioSourceNode</a>
|
|
interface, an AudioNode which is the audio source from an
|
|
<code>audio</code>, <code>video</code>, or other media element. </li>
|
|
<li>A <a class="dfnref"
|
|
href="#MediaStreamAudioSourceNode-section">MediaStreamAudioSourceNode</a>
|
|
interface, an AudioNode which is the audio source from a
|
|
MediaStream such as live audio input, or from a remote peer. </li>
|
|
<li>A <a class="dfnref"
|
|
href="#MediaStreamAudioDestinationNode-section">MediaStreamAudioDestinationNode</a>
|
|
interface, an AudioNode which is the audio destination to a
|
|
MediaStream sent to a remote peer. </li>
|
|
<li>A <a class="dfnref"
|
|
href="#ScriptProcessorNode-section">ScriptProcessorNode</a> interface, an
|
|
AudioNode for generating or processing audio directly in JavaScript. </li>
|
|
<li>An <a class="dfnref"
|
|
href="#AudioProcessingEvent-section">AudioProcessingEvent</a> interface,
|
|
which is an event type used with <code>ScriptProcessorNode</code> objects.
|
|
</li>
|
|
<li>An <a class="dfnref" href="#AudioParam-section">AudioParam</a> interface,
|
|
for controlling an individual aspect of an AudioNode's functioning, such as
|
|
volume. </li>
|
|
<li>An <a class="dfnref" href="#GainNode-section">GainNode</a>
|
|
interface, for explicit gain control. Because inputs to AudioNodes support
|
|
multiple connections (as a unity-gain summing junction), mixers can be <a
|
|
href="#MixerGainStructure-section">easily built</a> with GainNodes.
|
|
</li>
|
|
<li>A <a class="dfnref" href="#BiquadFilterNode-section">BiquadFilterNode</a>
|
|
interface, an AudioNode for common low-order filters such as:
|
|
<ul>
|
|
<li>Low Pass</li>
|
|
<li>High Pass </li>
|
|
<li>Band Pass </li>
|
|
<li>Low Shelf </li>
|
|
<li>High Shelf </li>
|
|
<li>Peaking </li>
|
|
<li>Notch </li>
|
|
<li>Allpass </li>
|
|
</ul>
|
|
</li>
|
|
<li>A <a class="dfnref" href="#DelayNode-section">DelayNode</a> interface, an
|
|
AudioNode which applies a dynamically adjustable variable delay. </li>
|
|
<li>An <a class="dfnref" href="#PannerNode-section">PannerNode</a>
|
|
interface, for spatializing / positioning audio in 3D space. </li>
|
|
<li>An <a class="dfnref" href="#AudioListener-section">AudioListener</a>
|
|
interface, which works with an <code>PannerNode</code> for
|
|
spatialization. </li>
|
|
<li>A <a class="dfnref" href="#ConvolverNode-section">ConvolverNode</a>
|
|
interface, an AudioNode for applying a <a
|
|
href="#Convolution-section">real-time linear effect</a> (such as the sound
|
|
of a concert hall). </li>
|
|
<li>A <a class="dfnref"
|
|
href="#AnalyserNode-section">AnalyserNode</a> interface,
|
|
for use with music visualizers, or other visualization applications. </li>
|
|
<li>A <a class="dfnref"
|
|
href="#ChannelSplitterNode-section">ChannelSplitterNode</a> interface,
|
|
for accessing the individual channels of an audio stream in the routing
|
|
graph. </li>
|
|
<li>A <a class="dfnref"
|
|
href="#ChannelMergerNode-section">ChannelMergerNode</a> interface, for
|
|
combining channels from multiple audio streams into a single audio stream.
|
|
</li>
|
|
<li>A <a
|
|
href="#DynamicsCompressorNode-section">DynamicsCompressorNode</a> interface, an
|
|
AudioNode for dynamics compression. </li>
|
|
<li>A <a class="dfnref" href="#dfn-WaveShaperNode">WaveShaperNode</a>
|
|
interface, an AudioNode which applies a non-linear waveshaping effect for
|
|
distortion and other more subtle warming effects. </li>
|
|
<li>A <a class="dfnref" href="#dfn-OscillatorNode">OscillatorNode</a>
|
|
interface, an audio source generating a periodic waveform. </li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="conformance-section" class="section">
|
|
<h2 id="conformance">2. Conformance</h2>
|
|
|
|
<p>Everything in this specification is normative except for examples and
|
|
sections marked as being informative. </p>
|
|
|
|
<p>The keywords “<span class="rfc2119">MUST</span>”, “<span
|
|
class="rfc2119">MUST NOT</span>”, “<span
|
|
class="rfc2119">REQUIRED</span>”, “<span class="rfc2119">SHALL</span>”,
|
|
“<span class="rfc2119">SHALL NOT</span>”, “<span
|
|
class="rfc2119">RECOMMENDED</span>”, “<span class="rfc2119">MAY</span>”
|
|
and “<span class="rfc2119">OPTIONAL</span>” in this document are to be
|
|
interpreted as described in <cite><a href="http://www.ietf.org/rfc/rfc2119">Key
|
|
words for use in RFCs to Indicate Requirement Levels</a></cite> <a
|
|
href="#RFC2119">[RFC2119]</a>. </p>
|
|
|
|
<p>The following conformance classes are defined by this specification: </p>
|
|
<dl>
|
|
<dt><dfn id="dfn-conforming-implementation">conforming
|
|
implementation</dfn></dt>
|
|
<dd><p>A user agent is considered to be a <a class="dfnref"
|
|
href="#dfn-conforming-implementation">conforming implementation</a> if it
|
|
satisfies all of the <span class="rfc2119">MUST</span>-, <span
|
|
class="rfc2119">REQUIRED</span>- and <span
|
|
class="rfc2119">SHALL</span>-level criteria in this specification that
|
|
apply to implementations. </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="terminology-section" class="section">
|
|
|
|
<div id="API-section-section" class="section">
|
|
<h2 id="API-section">4. The Audio API</h2>
|
|
</div>
|
|
|
|
<div id="AudioContext-section-section" class="section">
|
|
<h2 id="AudioContext-section">4.1. The AudioContext Interface</h2>
|
|
|
|
<p>This interface represents a set of <a
|
|
href="#AudioNode-section"><code>AudioNode</code></a> objects and their
|
|
connections. It allows for arbitrary routing of signals to the <a
|
|
href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a>
|
|
(what the user ultimately hears). Nodes are created from the context and are
|
|
then <a href="#ModularRouting-section">connected</a> together. In most use
|
|
cases, only a single AudioContext is used per document.</p>
|
|
|
|
<br>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-context-idl">
|
|
|
|
callback DecodeSuccessCallback = void (AudioBuffer decodedData);
|
|
callback DecodeErrorCallback = void ();
|
|
|
|
[Constructor]
|
|
interface <dfn id="dfn-AudioContext">AudioContext</dfn> : EventTarget {
|
|
|
|
readonly attribute AudioDestinationNode destination;
|
|
readonly attribute float sampleRate;
|
|
readonly attribute double currentTime;
|
|
readonly attribute AudioListener listener;
|
|
|
|
AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate);
|
|
|
|
void decodeAudioData(ArrayBuffer audioData,
|
|
DecodeSuccessCallback successCallback,
|
|
optional DecodeErrorCallback errorCallback);
|
|
|
|
|
|
<span class="comment">// AudioNode creation </span>
|
|
AudioBufferSourceNode createBufferSource();
|
|
|
|
MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
|
|
|
|
MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
|
|
MediaStreamAudioDestinationNode createMediaStreamDestination();
|
|
|
|
ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
|
|
optional unsigned long numberOfInputChannels = 2,
|
|
optional unsigned long numberOfOutputChannels = 2);
|
|
|
|
AnalyserNode createAnalyser();
|
|
GainNode createGain();
|
|
DelayNode createDelay(optional double maxDelayTime = 1.0);
|
|
BiquadFilterNode createBiquadFilter();
|
|
WaveShaperNode createWaveShaper();
|
|
PannerNode createPanner();
|
|
ConvolverNode createConvolver();
|
|
|
|
ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
|
|
ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
|
|
|
|
DynamicsCompressorNode createDynamicsCompressor();
|
|
|
|
OscillatorNode createOscillator();
|
|
PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioContext-section" class="section">
|
|
<h3 id="attributes-AudioContext">4.1.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-destination"><code>destination</code></dt>
|
|
<dd><p>An <a
|
|
href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a>
|
|
with a single input representing the final destination for all audio.
|
|
Usually this will represent the actual audio hardware.
|
|
All AudioNodes actively rendering
|
|
audio will directly or indirectly connect to <code>destination</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-sampleRate"><code>sampleRate</code></dt>
|
|
<dd><p>The sample rate (in sample-frames per second) at which the
|
|
AudioContext handles audio. It is assumed that all AudioNodes in the
|
|
context run at this rate. In making this assumption, sample-rate
|
|
converters or "varispeed" processors are not supported in real-time
|
|
processing.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-currentTime"><code>currentTime</code></dt>
|
|
<dd><p>This is a time in seconds which starts at zero when the context is
|
|
created and increases in real-time. All scheduled times are relative to
|
|
it. This is not a "transport" time which can be started, paused, and
|
|
re-positioned. It is always moving forward. A GarageBand-like timeline
|
|
transport system can be very easily built on top of this (in JavaScript).
|
|
This time corresponds to an ever-increasing hardware timestamp. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-listener"><code>listener</code></dt>
|
|
<dd><p>An <a href="#AudioListener-section"><code>AudioListener</code></a>
|
|
which is used for 3D <a
|
|
href="#Spatialization-section">spatialization</a>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="methodsandparams-AudioContext-section" class="section">
|
|
<h3 id="methodsandparams-AudioContext">4.1.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-createBuffer">The <code>createBuffer</code> method</dt>
|
|
<dd><p>Creates an AudioBuffer of the given size. The audio data in the
|
|
buffer will be zero-initialized (silent). An NOT_SUPPORTED_ERR exception will be thrown if
|
|
the <code>numberOfChannels</code> or <code>sampleRate</code> are out-of-bounds,
|
|
or if length is 0.</p>
|
|
<p>The <dfn id="dfn-numberOfChannels">numberOfChannels</dfn> parameter
|
|
determines how many channels the buffer will have. An implementation must support at least 32 channels. </p>
|
|
<p>The <dfn id="dfn-length">length</dfn> parameter determines the size of
|
|
the buffer in sample-frames. </p>
|
|
<p>The <dfn id="dfn-sampleRate_2">sampleRate</dfn> parameter describes
|
|
the sample-rate of the linear PCM audio data in the buffer in
|
|
sample-frames per second. An implementation must support sample-rates in at least the range 22050 to 96000.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-decodeAudioData">The <code>decodeAudioData</code> method</dt>
|
|
<dd><p>Asynchronously decodes the audio file data contained in the
|
|
ArrayBuffer. The ArrayBuffer can, for example, be loaded from an XMLHttpRequest's
|
|
<code>response</code> attribute after setting the <code>responseType</code> to "arraybuffer".
|
|
Audio file data can be in any of the
|
|
formats supported by the <code>audio</code> element. </p>
|
|
<p><dfn id="dfn-audioData">audioData</dfn> is an ArrayBuffer containing
|
|
audio file data.</p>
|
|
<p><dfn id="dfn-successCallback">successCallback</dfn> is a callback
|
|
function which will be invoked when the decoding is finished. The single
|
|
argument to this callback is an AudioBuffer representing the decoded PCM
|
|
audio data.</p>
|
|
<p><dfn id="dfn-errorCallback">errorCallback</dfn> is a callback function
|
|
which will be invoked if there is an error decoding the audio file
|
|
data.</p>
|
|
|
|
<p>
|
|
The following steps must be performed:
|
|
</p>
|
|
<ol>
|
|
|
|
<li>Temporarily neuter the <dfn>audioData</dfn> ArrayBuffer in such a way that JavaScript code may not
|
|
access or modify the data.</li>
|
|
<li>Queue a decoding operation to be performed on another thread.</li>
|
|
<li>The decoding thread will attempt to decode the encoded <dfn>audioData</dfn> into linear PCM.
|
|
If a decoding error is encountered due to the audio format not being recognized or supported, or
|
|
because of corrupted/unexpected/inconsistent data then the <dfn>audioData</dfn> neutered state
|
|
will be restored to normal and the <dfn>errorCallback</dfn> will be
|
|
scheduled to run on the main thread's event loop and these steps will be terminated.</li>
|
|
<li>The decoding thread will take the result, representing the decoded linear PCM audio data,
|
|
and resample it to the sample-rate of the AudioContext if it is different from the sample-rate
|
|
of <dfn>audioData</dfn>. The final result (after possibly sample-rate converting) will be stored
|
|
in an AudioBuffer.
|
|
</li>
|
|
<li>The <dfn>audioData</dfn> neutered state will be restored to normal
|
|
</li>
|
|
<li>
|
|
The <dfn>successCallback</dfn> function will be scheduled to run on the main thread's event loop
|
|
given the AudioBuffer from step (4) as an argument.
|
|
</li>
|
|
</ol>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createBufferSource">The <code>createBufferSource</code>
|
|
method</dt>
|
|
<dd><p>Creates an <a
|
|
href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createMediaElementSource">The <code>createMediaElementSource</code>
|
|
method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#MediaElementAudioSourceNode-section"><code>MediaElementAudioSourceNode</code></a> given an HTMLMediaElement.
|
|
As a consequence of calling this method, audio playback from the HTMLMediaElement will be re-routed
|
|
into the processing graph of the AudioContext.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createMediaStreamSource">The <code>createMediaStreamSource</code>
|
|
method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#MediaStreamAudioSourceNode-section"><code>MediaStreamAudioSourceNode</code></a> given a MediaStream.
|
|
As a consequence of calling this method, audio playback from the MediaStream will be re-routed
|
|
into the processing graph of the AudioContext.</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
<dt id="dfn-createMediaStreamDestination">The <code>createMediaStreamDestination</code>
|
|
method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#MediaStreamAudioDestinationNode-section"><code>MediaStreamAudioDestinationNode</code></a>.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
<dt id="dfn-createScriptProcessor">The <code>createScriptProcessor</code>
|
|
method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#ScriptProcessorNode"><code>ScriptProcessorNode</code></a> for
|
|
direct audio processing using JavaScript. An INDEX_SIZE_ERR exception MUST be thrown if <code>bufferSize</code> or <code>numberOfInputChannels</code> or <code>numberOfOutputChannels</code>
|
|
are outside the valid range. </p>
|
|
<p>The <dfn id="dfn-bufferSize">bufferSize</dfn> parameter determines the
|
|
buffer size in units of sample-frames. If it's not passed in, or if the
|
|
value is 0, then the implementation will choose the best buffer size for
|
|
the given environment, which will be constant power of 2 throughout the lifetime
|
|
of the node. Otherwise if the author explicitly specifies the bufferSize,
|
|
it must be one of the following values: 256, 512, 1024, 2048, 4096, 8192,
|
|
16384. This value controls how
|
|
frequently the <code>audioprocess</code> event is dispatched and
|
|
how many sample-frames need to be processed each call. Lower values for
|
|
<code>bufferSize</code> will result in a lower (better) <a
|
|
href="#Latency-section">latency</a>. Higher values will be necessary to
|
|
avoid audio breakup and <a href="#Glitching-section">glitches</a>.
|
|
It is recommended for authors to not specify this buffer size and allow
|
|
the implementation to pick a good buffer size to balance between latency
|
|
and audio quality.
|
|
</p>
|
|
<p>The <dfn id="dfn-numberOfInputChannels">numberOfInputChannels</dfn> parameter (defaults to 2) and
|
|
determines the number of channels for this node's input. Values of up to 32 must be supported. </p>
|
|
<p>The <dfn id="dfn-numberOfOutputChannels">numberOfOutputChannels</dfn> parameter (defaults to 2) and
|
|
determines the number of channels for this node's output. Values of up to 32 must be supported.</p>
|
|
<p>It is invalid for both <code>numberOfInputChannels</code> and
|
|
<code>numberOfOutputChannels</code> to be zero. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createAnalyser">The <code>createAnalyser</code> method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#AnalyserNode-section"><code>AnalyserNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createGain">The <code>createGain</code> method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#GainNode-section"><code>GainNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createDelay">The <code>createDelay</code> method</dt>
|
|
<dd><p>Creates a <a href="#DelayNode-section"><code>DelayNode</code></a>
|
|
representing a variable delay line. The initial default delay time will
|
|
be 0 seconds.</p>
|
|
<p>The <dfn id="dfn-maxDelayTime">maxDelayTime</dfn> parameter is
|
|
optional and specifies the maximum delay time in seconds allowed for the delay line. If specified, this value MUST be
|
|
greater than zero and less than three minutes or a NOT_SUPPORTED_ERR exception will be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createBiquadFilter">The <code>createBiquadFilter</code>
|
|
method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#BiquadFilterNode-section"><code>BiquadFilterNode</code></a>
|
|
representing a second order filter which can be configured as one of
|
|
several common filter types.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createWaveShaper">The <code>createWaveShaper</code>
|
|
method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#WaveShaperNode-section"><code>WaveShaperNode</code></a>
|
|
representing a non-linear distortion.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createPanner">The <code>createPanner</code> method</dt>
|
|
<dd><p>Creates an <a
|
|
href="#PannerNode-section"><code>PannerNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createConvolver">The <code>createConvolver</code> method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#ConvolverNode-section"><code>ConvolverNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createChannelSplitter">The <code>createChannelSplitter</code>
|
|
method</dt>
|
|
<dd><p>Creates an <a
|
|
href="#ChannelSplitterNode-section"><code>ChannelSplitterNode</code></a>
|
|
representing a channel splitter. An exception will be thrown for invalid parameter values.</p>
|
|
<p>The <dfn id="dfn-numberOfOutputs">numberOfOutputs</dfn> parameter
|
|
determines the number of outputs. Values of up to 32 must be supported. If not specified, then 6 will be used. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createChannelMerger">The <code>createChannelMerger</code>
|
|
method</dt>
|
|
<dd><p>Creates an <a
|
|
href="#ChannelMergerNode-section"><code>ChannelMergerNode</code></a>
|
|
representing a channel merger. An exception will be thrown for invalid parameter values.</p>
|
|
<p>The <dfn id="dfn-numberOfInputs">numberOfInputs</dfn> parameter
|
|
determines the number of inputs. Values of up to 32 must be supported. If not specified, then 6 will be used. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createDynamicsCompressor">The
|
|
<code>createDynamicsCompressor</code> method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#DynamicsCompressorNode-section"><code>DynamicsCompressorNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createOscillator">The
|
|
<code>createOscillator</code> method</dt>
|
|
<dd><p>Creates an <a
|
|
href="#OscillatorNode-section"><code>OscillatorNode</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-createPeriodicWave">The
|
|
<code>createPeriodicWave</code> method</dt>
|
|
<dd><p>Creates a <a
|
|
href="#PeriodicWave-section"><code>PeriodicWave</code></a> representing a waveform containing arbitrary harmonic content.
|
|
The <code>real</code> and <code>imag</code> parameters must be of type <code>Float32Array</code> of equal
|
|
lengths greater than zero and less than or equal to 4096 or an exception will be thrown.
|
|
These parameters specify the Fourier coefficients of a
|
|
<a href="http://en.wikipedia.org/wiki/Fourier_series">Fourier series</a> representing the partials of a periodic waveform.
|
|
The created PeriodicWave will be used with an <a href="#OscillatorNode-section"><code>OscillatorNode</code></a>
|
|
and will represent a <em>normalized</em> time-domain waveform having maximum absolute peak value of 1.
|
|
Another way of saying this is that the generated waveform of an <a href="#OscillatorNode-section"><code>OscillatorNode</code></a>
|
|
will have maximum peak value at 0dBFS. Conveniently, this corresponds to the full-range of the signal values used by the Web Audio API.
|
|
Because the PeriodicWave will be normalized on creation, the <code>real</code> and <code>imag</code> parameters
|
|
represent <em>relative</em> values.
|
|
</p>
|
|
<p>The <dfn id="dfn-real">real</dfn> parameter represents an array of <code>cosine</code> terms (traditionally the A terms).
|
|
In audio terminology, the first element (index 0) is the DC-offset of the periodic waveform and is usually set to zero.
|
|
The second element (index 1) represents the fundamental frequency. The third element represents the first overtone, and so on.</p>
|
|
<p>The <dfn id="dfn-imag">imag</dfn> parameter represents an array of <code>sine</code> terms (traditionally the B terms).
|
|
The first element (index 0) should be set to zero (and will be ignored) since this term does not exist in the Fourier series.
|
|
The second element (index 1) represents the fundamental frequency. The third element represents the first overtone, and so on.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 id="lifetime-AudioContext">4.1.3. Lifetime</h3>
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<p>
|
|
Once created, an <code>AudioContext</code> will continue to play sound until it has no more sound to play, or
|
|
the page goes away.
|
|
</p>
|
|
|
|
<div id="OfflineAudioContext-section-section" class="section">
|
|
<h2 id="OfflineAudioContext-section">4.1b. The OfflineAudioContext Interface</h2>
|
|
<p>
|
|
OfflineAudioContext is a particular type of AudioContext for rendering/mixing-down (potentially) faster than real-time.
|
|
It does not render to the audio hardware, but instead renders as quickly as possible, calling a completion event handler
|
|
with the result provided as an AudioBuffer.
|
|
</p>
|
|
|
|
|
|
<p>
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="offline-audio-context-idl">
|
|
[Constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate)]
|
|
interface <dfn id="dfn-OfflineAudioContext">OfflineAudioContext</dfn> : AudioContext {
|
|
|
|
void startRendering();
|
|
|
|
attribute EventHandler oncomplete;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="attributes-OfflineAudioContext-section" class="section">
|
|
<h3 id="attributes-OfflineAudioContext">4.1b.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-oncomplete"><code>oncomplete</code></dt>
|
|
<dd><p>An EventHandler of type <a href="#OfflineAudioCompletionEvent-section">OfflineAudioCompletionEvent</a>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
|
|
<div id="methodsandparams-OfflineAudioContext-section" class="section">
|
|
<h3 id="methodsandparams-OfflineAudioContext">4.1b.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-startRendering">The <code>startRendering</code>
|
|
method</dt>
|
|
<dd><p>Given the current connections and scheduled changes, starts rendering audio. The
|
|
<code>oncomplete</code> handler will be called once the rendering has finished.
|
|
This method must only be called one time or an exception will be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
|
|
<div id="OfflineAudioCompletionEvent-section" class="section">
|
|
<h2 id="OfflineAudioCompletionEvent">4.1c. The OfflineAudioCompletionEvent Interface</h2>
|
|
|
|
<p>This is an <code>Event</code> object which is dispatched to <a
|
|
href="#OfflineAudioContext-section"><code>OfflineAudioContext</code></a>. </p>
|
|
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="offline-audio-completion-event-idl">
|
|
dictionary OfflineAudioCompletionEventInit : EventInit {
|
|
required AudioBuffer renderedBuffer;
|
|
};
|
|
|
|
[Constructor(DOMString type, OfflineAudioCompletionEventInit eventInitDict)]
|
|
interface <dfn id="dfn-OfflineAudioCompletionEvent">OfflineAudioCompletionEvent</dfn> : Event {
|
|
|
|
readonly attribute AudioBuffer renderedBuffer;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-OfflineAudioCompletionEvent-section" class="section">
|
|
<h3 id="attributes-OfflineAudioCompletionEvent">4.1c.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-renderedBuffer"><code>renderedBuffer</code></dt>
|
|
<dd><p>An AudioBuffer containing the rendered audio data once an OfflineAudioContext has finished rendering.
|
|
It will have a number of channels equal to the <code>numberOfChannels</code> parameter
|
|
of the OfflineAudioContext constructor.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="AudioNode-section-section" class="section">
|
|
<h2 id="AudioNode-section">4.2. The AudioNode Interface</h2>
|
|
|
|
<p>AudioNodes are the building blocks of an <a
|
|
href="#AudioContext-section"><code>AudioContext</code></a>. This interface
|
|
represents audio sources, the audio destination, and intermediate processing
|
|
modules. These modules can be connected together to form <a
|
|
href="#ModularRouting-section">processing graphs</a> for rendering audio to the
|
|
audio hardware. Each node can have <dfn>inputs</dfn> and/or <dfn>outputs</dfn>.
|
|
A <dfn>source node</dfn> has no inputs
|
|
and a single output. An <a
|
|
href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a> has
|
|
one input and no outputs and represents the final destination to the audio
|
|
hardware. Most processing nodes such as filters will have one input and one
|
|
output. Each type of <code>AudioNode</code> differs in the details of how it processes or synthesizes audio. But, in general, <code>AudioNodes</code>
|
|
will process its inputs (if it has any), and generate audio for its outputs (if it has any).
|
|
</p>
|
|
|
|
<p>
|
|
Each <dfn>output</dfn> has one or more <dfn>channels</dfn>. The exact number of channels depends on the details of the specific AudioNode.
|
|
</p>
|
|
|
|
<p>
|
|
An output may connect to one or more <code>AudioNode</code> inputs, thus <em>fan-out</em> is supported. An input initially has no connections,
|
|
but may be connected from one
|
|
or more <code>AudioNode</code> outputs, thus <em>fan-in</em> is supported. When the <code>connect()</code> method is called to connect
|
|
an output of an AudioNode to an input of an AudioNode, we call that a <dfn>connection</dfn> to the input.
|
|
</p>
|
|
|
|
<p>
|
|
Each AudioNode <dfn>input</dfn> has a specific number of channels at any given time. This number can change depending on the <dfn>connection(s)</dfn>
|
|
made to the input. If the input has no connections then it has one channel which is silent.
|
|
</p>
|
|
|
|
<p>
|
|
For each <dfn>input</dfn>, an <code>AudioNode</code> performs a mixing (usually an up-mixing) of all connections to that input.
|
|
|
|
Please see <a href="#MixerGainStructure-section">Mixer Gain Structure</a> for more informative details, and the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
|
|
section for normative requirements.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
For performance reasons, practical implementations will need to use block processing, with each <code>AudioNode</code> processing a
|
|
fixed number of sample-frames of size <em>block-size</em>. In order to get uniform behavior across implementations, we will define this
|
|
value explicitly. <em>block-size</em> is defined to be 128 sample-frames which corresponds to roughly 3ms at a sample-rate of 44.1KHz.
|
|
</p>
|
|
|
|
<p>
|
|
AudioNodes are <em>EventTarget</em>s, as described in <cite><a href="http://dom.spec.whatwg.org/">DOM</a></cite>
|
|
<a href="#DOM">[DOM]</a>. This means that it is possible to dispatch events to AudioNodes the same
|
|
way that other EventTargets accept events.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-node-idl">
|
|
|
|
enum <dfn>ChannelCountMode</dfn> {
|
|
"max",
|
|
"clamped-max",
|
|
"explicit"
|
|
};
|
|
|
|
enum <dfn>ChannelInterpretation</dfn> {
|
|
"speakers",
|
|
"discrete"
|
|
};
|
|
|
|
interface <dfn id="dfn-AudioNode">AudioNode</dfn> : EventTarget {
|
|
|
|
void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
|
|
void connect(AudioParam destination, optional unsigned long output = 0);
|
|
void disconnect(optional unsigned long output = 0);
|
|
|
|
readonly attribute AudioContext context;
|
|
readonly attribute unsigned long numberOfInputs;
|
|
readonly attribute unsigned long numberOfOutputs;
|
|
|
|
// Channel up-mixing and down-mixing rules for all inputs.
|
|
attribute unsigned long channelCount;
|
|
attribute ChannelCountMode channelCountMode;
|
|
attribute ChannelInterpretation channelInterpretation;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioNode-section" class="section">
|
|
<h3 id="attributes-AudioNode">4.2.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-context"><code>context</code></dt>
|
|
<dd><p>The AudioContext which owns this AudioNode.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-numberOfInputs_2"><code>numberOfInputs</code></dt>
|
|
<dd><p>The number of inputs feeding into the AudioNode. For <dfn>source nodes</dfn>,
|
|
this will be 0.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-numberOfOutputs_2"><code>numberOfOutputs</code></dt>
|
|
<dd><p>The number of outputs coming out of the AudioNode. This will be 0
|
|
for an AudioDestinationNode.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-channelCount"><code>channelCount</code><dt>
|
|
<dd><p>The number of channels used when up-mixing and down-mixing connections to any inputs to the node. The default value is 2
|
|
except for specific nodes where its value is specially determined.
|
|
This attribute has no effect for nodes with no inputs.
|
|
If this value is set to zero, the implementation MUST raise the
|
|
NOT_SUPPORTED_ERR exception.</p>
|
|
<p>See the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
|
|
section for more information on this attribute.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-channelCountMode"><code>channelCountMode</code><dt>
|
|
<dd><p>Determines how channels will be counted when up-mixing and down-mixing connections to any inputs to the node
|
|
. This attribute has no effect for nodes with no inputs.</p>
|
|
<p>See the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
|
|
section for more information on this attribute.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-channelInterpretation"><code>channelInterpretation</code><dt>
|
|
<dd><p>Determines how individual channels will be treated when up-mixing and down-mixing connections to any inputs to the node.
|
|
This attribute has no effect for nodes with no inputs.</p>
|
|
<p>See the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
|
|
section for more information on this attribute.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="methodsandparams-AudioNode-section" class="section">
|
|
<h3 id="methodsandparams-AudioNode">4.2.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-connect-AudioNode">The <code>connect</code> to AudioNode method</dt>
|
|
<dd><p>Connects the AudioNode to another AudioNode.</p>
|
|
<p>The <dfn id="dfn-destination_2">destination</dfn> parameter is the
|
|
AudioNode to connect to.</p>
|
|
<p>The <dfn id="dfn-output_2">output</dfn> parameter is an index
|
|
describing which output of the AudioNode from which to connect. An
|
|
out-of-bound value throws an exception.</p>
|
|
<p>The <dfn id="dfn-input_2">input</dfn> parameter is an index describing
|
|
which input of the destination AudioNode to connect to. An out-of-bound
|
|
value throws an exception. </p>
|
|
<p>It is possible to connect an AudioNode output to more than one input
|
|
with multiple calls to connect(). Thus, "fan-out" is supported. </p>
|
|
<p>
|
|
It is possible to connect an AudioNode to another AudioNode which creates a <em>cycle</em>.
|
|
In other words, an AudioNode may connect to another AudioNode, which in turn connects back
|
|
to the first AudioNode. This is allowed only if there is at least one
|
|
<a class="dfnref" href="#DelayNode-section">DelayNode</a> in the <em>cycle</em> or an exception will
|
|
be thrown.
|
|
</p>
|
|
|
|
<p>
|
|
There can only be one connection between a given output of one specific node and a given input of another specific node.
|
|
Multiple connections with the same termini are ignored. For example:
|
|
</p>
|
|
|
|
<pre>
|
|
nodeA.connect(nodeB);
|
|
nodeA.connect(nodeB);
|
|
|
|
will have the same effect as
|
|
|
|
nodeA.connect(nodeB);
|
|
</pre>
|
|
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-connect-AudioParam">The <code>connect</code> to AudioParam method</dt>
|
|
<dd><p>Connects the AudioNode to an AudioParam, controlling the parameter
|
|
value with an audio-rate signal.
|
|
</p>
|
|
|
|
<p>The <dfn id="dfn-destination_3">destination</dfn> parameter is the
|
|
AudioParam to connect to.</p>
|
|
<p>The <dfn id="dfn-output_3-destination">output</dfn> parameter is an index
|
|
describing which output of the AudioNode from which to connect. An
|
|
out-of-bound value throws an exception.</p>
|
|
|
|
<p>It is possible to connect an AudioNode output to more than one AudioParam
|
|
with multiple calls to connect(). Thus, "fan-out" is supported. </p>
|
|
<p>It is possible to connect more than one AudioNode output to a single AudioParam
|
|
with multiple calls to connect(). Thus, "fan-in" is supported. </p>
|
|
<p>An AudioParam will take the rendered audio data from any AudioNode output connected to it and <a href="#down-mix">convert it to mono</a> by down-mixing if it is not
|
|
already mono, then mix it together with other such outputs and finally will mix with the <em>intrinsic</em>
|
|
parameter value (the value the AudioParam would normally have without any audio connections), including any timeline changes
|
|
scheduled for the parameter. </p>
|
|
|
|
<p>
|
|
There can only be one connection between a given output of one specific node and a specific AudioParam.
|
|
Multiple connections with the same termini are ignored. For example:
|
|
</p>
|
|
|
|
<pre>
|
|
nodeA.connect(param);
|
|
nodeA.connect(param);
|
|
|
|
will have the same effect as
|
|
|
|
nodeA.connect(param);
|
|
</pre>
|
|
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-disconnect">The <code>disconnect</code> method</dt>
|
|
<dd><p>Disconnects an AudioNode's output.</p>
|
|
<p>The <dfn id="dfn-output_3-disconnect">output</dfn> parameter is an index
|
|
describing which output of the AudioNode to disconnect. An out-of-bound
|
|
value throws an exception.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 id="lifetime-AudioNode">4.2.3. Lifetime</h3>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<p>An implementation may choose any method to avoid unnecessary resource usage and unbounded memory growth of unused/finished
|
|
nodes. The following is a description to help guide the general expectation of how node lifetime would be managed.
|
|
</p>
|
|
|
|
<p>
|
|
An <code>AudioNode</code> will live as long as there are any references to it. There are several types of references:
|
|
</p>
|
|
|
|
<ol>
|
|
<li>A <em>normal</em> JavaScript reference obeying normal garbage collection rules. </li>
|
|
<li>A <em>playing</em> reference for both <code>AudioBufferSourceNodes</code> and <code>OscillatorNodes</code>.
|
|
These nodes maintain a <em>playing</em>
|
|
reference to themselves while they are currently playing.</li>
|
|
<li>A <em>connection</em> reference which occurs if another <code>AudioNode</code> is connected to it. </li>
|
|
<li>A <em>tail-time</em> reference which an <code>AudioNode</code> maintains on itself as long as it has
|
|
any internal processing state which has not yet been emitted. For example, a <code>ConvolverNode</code> has
|
|
a tail which continues to play even after receiving silent input (think about clapping your hands in a large concert
|
|
hall and continuing to hear the sound reverberate throughout the hall). Some <code>AudioNodes</code> have this
|
|
property. Please see details for specific nodes.</li>
|
|
</ol>
|
|
|
|
<p>
|
|
Any <code>AudioNodes</code> which are connected in a cycle <em>and</em> are directly or indirectly connected to the
|
|
<code>AudioDestinationNode</code> of the <code>AudioContext</code> will stay alive as long as the <code>AudioContext</code> is alive.
|
|
</p>
|
|
|
|
<p>
|
|
When an <code>AudioNode</code> has no references it will be deleted. But before it is deleted, it will disconnect itself
|
|
from any other <code>AudioNodes</code> which it is connected to. In this way it releases all connection references (3) it has to other nodes.
|
|
</p>
|
|
|
|
<p>
|
|
Regardless of any of the above references, it can be assumed that the <code>AudioNode</code> will be deleted when its <code>AudioContext</code> is deleted.
|
|
</p>
|
|
|
|
|
|
<div id="AudioDestinationNode-section" class="section">
|
|
<h2 id="AudioDestinationNode">4.4. The AudioDestinationNode Interface</h2>
|
|
|
|
<p>This is an <a href="#AudioNode-section"><code>AudioNode</code></a>
|
|
representing the final audio destination and is what the user will ultimately
|
|
hear. It can often be considered as an audio output device which is connected to
|
|
speakers. All rendered audio to be heard will be routed to this node, a
|
|
"terminal" node in the AudioContext's routing graph. There is only a single
|
|
AudioDestinationNode per AudioContext, provided through the
|
|
<code>destination</code> attribute of <a
|
|
href="#AudioContext-section"><code>AudioContext</code></a>. </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 0
|
|
|
|
channelCount = 2;
|
|
channelCountMode = "explicit";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-destination-node-idl">
|
|
|
|
interface <dfn id="dfn-AudioDestinationNode">AudioDestinationNode</dfn> : AudioNode {
|
|
|
|
readonly attribute unsigned long maxChannelCount;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioDestinationNode-section" class="section">
|
|
<h3 id="attributes-AudioDestinationNode">4.4.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-maxChannelCount"><code>maxChannelCount</code></dt>
|
|
<dd><p>The maximum number of channels that the <code>channelCount</code> attribute can be set to.
|
|
An <code>AudioDestinationNode</code> representing the audio hardware end-point (the normal case) can potentially output more than
|
|
2 channels of audio if the audio hardware is multi-channel. <code>maxChannelCount</code> is the maximum number of channels that
|
|
this hardware is capable of supporting. If this value is 0, then this indicates that <code>channelCount</code> may not be
|
|
changed. This will be the case for an <code>AudioDestinationNode</code> in an <code>OfflineAudioContext</code> and also for
|
|
basic implementations with hardware support for stereo output only.</p>
|
|
|
|
<p><code>channelCount</code> defaults to 2 for a destination in a normal AudioContext, and may be set to any non-zero value less than or equal
|
|
to <code>maxChannelCount</code>. An exception will be thrown if this value is not within the valid range. Giving a concrete example, if
|
|
the audio hardware supports 8-channel output, then we may set <code>numberOfChannels</code> to 8, and render 8-channels of output.
|
|
</p>
|
|
|
|
<p>
|
|
For an AudioDestinationNode in an OfflineAudioContext, the <code>channelCount</code> is determined when the offline context is created and this value
|
|
may not be changed.
|
|
</p>
|
|
|
|
</dd>
|
|
</dl>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="AudioParam-section" class="section">
|
|
<h2 id="AudioParam">4.5. The AudioParam Interface</h2>
|
|
|
|
<p>AudioParam controls an individual aspect of an <a
|
|
href="#AudioNode-section"><code>AudioNode</code></a>'s functioning, such as
|
|
volume. The parameter can be set immediately to a particular value using the
|
|
"value" attribute. Or, value changes can be scheduled to happen at
|
|
very precise times (in the coordinate system of AudioContext.currentTime), for envelopes, volume fades, LFOs, filter sweeps, grain
|
|
windows, etc. In this way, arbitrary timeline-based automation curves can be
|
|
set on any AudioParam. Additionally, audio signals from the outputs of <code>AudioNodes</code> can be connected
|
|
to an <code>AudioParam</code>, summing with the <em>intrinsic</em> parameter value.
|
|
</p>
|
|
|
|
<p>
|
|
Some synthesis and processing <code>AudioNodes</code> have <code>AudioParams</code> as attributes whose values must
|
|
be taken into account on a per-audio-sample basis.
|
|
For other <code>AudioParams</code>, sample-accuracy is not important and the value changes can be sampled more coarsely.
|
|
Each individual <code>AudioParam</code> will specify that it is either an <em>a-rate</em> parameter
|
|
which means that its values must be taken into account on a per-audio-sample basis, or it is a <em>k-rate</em> parameter.
|
|
</p>
|
|
|
|
<p>
|
|
Implementations must use block processing, with each <code>AudioNode</code>
|
|
processing 128 sample-frames in each block.
|
|
</p>
|
|
|
|
<p>
|
|
For each 128 sample-frame block, the value of a <em>k-rate</em> parameter must
|
|
be sampled at the time of the very first sample-frame, and that value must be
|
|
used for the entire block. <em>a-rate</em> parameters must be sampled for each
|
|
sample-frame of the block.
|
|
</p>
|
|
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-param-idl">
|
|
|
|
interface <dfn id="dfn-AudioParam">AudioParam</dfn> {
|
|
|
|
attribute float value;
|
|
readonly attribute float defaultValue;
|
|
|
|
<span class="comment">// Parameter automation. </span>
|
|
void setValueAtTime(float value, double startTime);
|
|
void linearRampToValueAtTime(float value, double endTime);
|
|
void exponentialRampToValueAtTime(float value, double endTime);
|
|
|
|
<span class="comment">// Exponentially approach the target value with a rate having the given time constant. </span>
|
|
void setTargetAtTime(float target, double startTime, double timeConstant);
|
|
|
|
<span class="comment">// Sets an array of arbitrary parameter values starting at time for the given duration. </span>
|
|
<span class="comment">// The number of values will be scaled to fit into the desired duration. </span>
|
|
void setValueCurveAtTime(Float32Array values, double startTime, double duration);
|
|
|
|
<span class="comment">// Cancels all scheduled parameter changes with times greater than or equal to startTime. </span>
|
|
void cancelScheduledValues(double startTime);
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div id="attributes-AudioParam-section" class="section">
|
|
<h3 id="attributes-AudioParam">4.5.1. Attributes</h3>
|
|
|
|
<dl>
|
|
<dt id="dfn-value"><code>value</code></dt>
|
|
<dd><p>The parameter's floating-point value. This attribute is initialized to the
|
|
<code>defaultValue</code>. If a value is set during a time when there are any automation events scheduled then
|
|
it will be ignored and no exception will be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-defaultValue"><code>defaultValue</code></dt>
|
|
<dd><p>Initial value for the value attribute</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="methodsandparams-AudioParam-section" class="section">
|
|
<h3 id="methodsandparams-AudioParam">4.5.2. Methods and Parameters</h3>
|
|
|
|
<p>
|
|
An <code>AudioParam</code> maintains a time-ordered event list which is initially empty. The times are in
|
|
the time coordinate system of AudioContext.currentTime. The events define a mapping from time to value. The following methods
|
|
can change the event list by adding a new event into the list of a type specific to the method. Each event
|
|
has a time associated with it, and the events will always be kept in time-order in the list. These
|
|
methods will be called <em>automation</em> methods:</p>
|
|
|
|
<ul>
|
|
<li>setValueAtTime() - <em>SetValue</em></li>
|
|
<li>linearRampToValueAtTime() - <em>LinearRampToValue</em></li>
|
|
<li>exponentialRampToValueAtTime() - <em>ExponentialRampToValue</em></li>
|
|
<li>setTargetAtTime() - <em>SetTarget</em></li>
|
|
<li>setValueCurveAtTime() - <em>SetValueCurve</em></li>
|
|
</ul>
|
|
|
|
<p>
|
|
The following rules will apply when calling these methods:
|
|
</p>
|
|
<ul>
|
|
<li>If one of these events is added at a time where there is already an event of the exact same type, then the new event will replace the old
|
|
one.</li>
|
|
<li>If one of these events is added at a time where there is already one or more events of a different type, then it will be
|
|
placed in the list after them, but before events whose times are after the event. </li>
|
|
<li>If setValueCurveAtTime() is called for time T and duration D and there are any events having a time greater than T, but less than
|
|
T + D, then an exception will be thrown. In other words, it's not ok to schedule a value curve during a time period containing other events.</li>
|
|
<li>Similarly an exception will be thrown if any <em>automation</em> method is called at a time which is inside of the time interval
|
|
of a <em>SetValueCurve</em> event at time T and duration D.</li>
|
|
</ul>
|
|
<p>
|
|
</p>
|
|
|
|
<dl>
|
|
<dt id="dfn-setValueAtTime">The <code>setValueAtTime</code> method</dt>
|
|
<dd><p>Schedules a parameter value change at the given time.</p>
|
|
<p>The <dfn id="dfn-value_2">value</dfn> parameter is the value the
|
|
parameter will change to at the given time.</p>
|
|
<p>The <dfn id="dfn-startTime_2">startTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
|
|
<p>
|
|
If there are no more events after this <em>SetValue</em> event, then for t >= startTime, v(t) = value. In other words, the value will remain constant.
|
|
</p>
|
|
<p>
|
|
If the next event (having time T1) after this <em>SetValue</em> event is not of type <em>LinearRampToValue</em> or <em>ExponentialRampToValue</em>,
|
|
then, for t: startTime <= t < T1, v(t) = value.
|
|
In other words, the value will remain constant during this time interval, allowing the creation of "step" functions.
|
|
</p>
|
|
<p>
|
|
If the next event after this <em>SetValue</em> event is of type <em>LinearRampToValue</em> or <em>ExponentialRampToValue</em> then please
|
|
see details below.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-linearRampToValueAtTime">The <code>linearRampToValueAtTime</code>
|
|
method</dt>
|
|
<dd><p>Schedules a linear continuous change in parameter value from the
|
|
previous scheduled parameter value to the given value.</p>
|
|
<p>The <dfn id="dfn-value_3">value</dfn> parameter is the value the
|
|
parameter will linearly ramp to at the given time.</p>
|
|
<p>The <dfn id="dfn-endTime_3">endTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
|
|
|
|
<p>
|
|
The value during the time interval T0 <= t < T1 (where T0 is the time of the previous event and T1 is the endTime parameter passed into this method)
|
|
will be calculated as:
|
|
</p>
|
|
<pre>
|
|
v(t) = V0 + (V1 - V0) * ((t - T0) / (T1 - T0))
|
|
</pre>
|
|
<p>
|
|
Where V0 is the value at the time T0 and V1 is the value parameter passed into this method.
|
|
</p>
|
|
<p>
|
|
If there are no more events after this LinearRampToValue event then for t >= T1, v(t) = V1
|
|
</p>
|
|
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-exponentialRampToValueAtTime">The
|
|
<code>exponentialRampToValueAtTime</code> method</dt>
|
|
<dd><p>Schedules an exponential continuous change in parameter value from
|
|
the previous scheduled parameter value to the given value. Parameters
|
|
representing filter frequencies and playback rate are best changed
|
|
exponentially because of the way humans perceive sound. </p>
|
|
<p>The <dfn id="dfn-value_4">value</dfn> parameter is the value the
|
|
parameter will exponentially ramp to at the given time. An exception will be thrown if this value is less than
|
|
or equal to 0, or if the value at the time of the previous event is less than or equal to 0.</p>
|
|
<p>The <dfn id="dfn-endTime_4">endTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
|
|
<p>
|
|
The value during the time interval T0 <= t < T1 (where T0 is the time of the previous event and T1 is the endTime parameter passed into this method)
|
|
will be calculated as:
|
|
</p>
|
|
<pre>
|
|
v(t) = V0 * (V1 / V0) ^ ((t - T0) / (T1 - T0))
|
|
</pre>
|
|
<p>
|
|
Where V0 is the value at the time T0 and V1 is the value parameter passed into this method.
|
|
</p>
|
|
<p>
|
|
If there are no more events after this ExponentialRampToValue event then for t >= T1, v(t) = V1
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-setTargetAtTime">The <code>setTargetAtTime</code>
|
|
method</dt>
|
|
<dd><p>Start exponentially approaching the target value at the given time
|
|
with a rate having the given time constant. Among other uses, this is
|
|
useful for implementing the "decay" and "release" portions of an ADSR
|
|
envelope. Please note that the parameter value does not immediately
|
|
change to the target value at the given time, but instead gradually
|
|
changes to the target value.</p>
|
|
<p>The <dfn id="dfn-target">target</dfn> parameter is the value
|
|
the parameter will <em>start</em> changing to at the given time.</p>
|
|
<p>The <dfn id="dfn-startTime">startTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
|
|
<p>The <dfn id="dfn-timeConstant">timeConstant</dfn> parameter is the
|
|
time-constant value of first-order filter (exponential) approach to the
|
|
target value. The larger this value is, the slower the transition will
|
|
be.</p>
|
|
<p>
|
|
More precisely, <em>timeConstant</em> is the time it takes a first-order linear continuous time-invariant system
|
|
to reach the value 1 - 1/e (around 63.2%) given a step input response (transition from 0 to 1 value).
|
|
</p>
|
|
<p>
|
|
During the time interval: <em>T0</em> <= t < <em>T1</em>, where T0 is the <em>startTime</em> parameter and T1 represents the time of the event following this
|
|
event (or <em>infinity</em> if there are no following events):
|
|
</p>
|
|
<pre>
|
|
v(t) = V1 + (V0 - V1) * exp(-(t - T0) / <em>timeConstant</em>)
|
|
</pre>
|
|
<p>
|
|
Where V0 is the initial value (the .value attribute) at T0 (the <em>startTime</em> parameter) and V1 is equal to the <em>target</em>
|
|
parameter.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-setValueCurveAtTime">The <code>setValueCurveAtTime</code>
|
|
method</dt>
|
|
<dd><p>Sets an array of arbitrary parameter values starting at the given
|
|
time for the given duration. The number of values will be scaled to fit
|
|
into the desired duration. </p>
|
|
<p>The <dfn id="dfn-values">values</dfn> parameter is a Float32Array
|
|
representing a parameter value curve. These values will apply starting at
|
|
the given time and lasting for the given duration. </p>
|
|
<p>The <dfn id="dfn-startTime_5">startTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
|
|
<p>The <dfn id="dfn-duration_5">duration</dfn> parameter is the
|
|
amount of time in seconds (after the <em>time</em> parameter) where values will be calculated according to the <em>values</em> parameter..</p>
|
|
<p>
|
|
During the time interval: <em>startTime</em> <= t < <em>startTime</em> + <em>duration</em>, values will be calculated:
|
|
</p>
|
|
<pre>
|
|
v(t) = values[N * (t - startTime) / duration], where <em>N</em> is the length of the <em>values</em> array.
|
|
</pre>
|
|
<p>
|
|
After the end of the curve time interval (t >= <em>startTime</em> + <em>duration</em>), the value will remain constant at the final curve value,
|
|
until there is another automation event (if any).
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-cancelScheduledValues">The <code>cancelScheduledValues</code>
|
|
method</dt>
|
|
<dd><p>Cancels all scheduled parameter changes with times greater than or
|
|
equal to startTime.</p>
|
|
<p>The <dfn>startTime</dfn> parameter is the starting
|
|
time at and after which any previously scheduled parameter changes will
|
|
be cancelled. It is a time in the same time coordinate system as AudioContext.currentTime.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div id="computedValue-AudioParam-section" class="section">
|
|
<h3>4.5.3. Computation of Value</h3>
|
|
|
|
<p>
|
|
<dfn>computedValue</dfn> is the final value controlling the audio DSP and is computed by the audio rendering thread during each rendering time quantum.
|
|
It must be internally computed as follows:
|
|
</p>
|
|
|
|
<ol>
|
|
<li>An <em>intrinsic</em> parameter value will be calculated at each time, which is either the value set directly to the .value attribute,
|
|
or, if there are any scheduled parameter changes (automation events) with times before or at this time,
|
|
the value as calculated from these events. If the .value attribute
|
|
is set after any automation events have been scheduled, then these events will be removed. When read, the .value attribute
|
|
always returns the <em>intrinsic</em> value for the current time. If automation events are removed from a given time range, then the
|
|
<em>intrinsic</em> value will remain unchanged and stay at its previous value until either the .value attribute is directly set, or automation events are added
|
|
for the time range.
|
|
</li>
|
|
|
|
<li>
|
|
An AudioParam will take the rendered audio data from any AudioNode output connected to it and <a href="#down-mix">convert it to mono</a> by down-mixing if it is not
|
|
already mono, then mix it together with other such outputs. If there are no AudioNodes connected to it, then this value is 0, having no
|
|
effect on the <em>computedValue</em>.
|
|
</li>
|
|
|
|
<li>
|
|
The <em>computedValue</em> is the sum of the <em>intrinsic</em> value and the value calculated from (2).
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</div>
|
|
|
|
|
|
<div id="example1-AudioParam-section" class="section">
|
|
<h3 id="example1-AudioParam">4.5.4. AudioParam Automation Example</h3>
|
|
|
|
|
|
|
|
<div class="example">
|
|
|
|
<div class="exampleHeader">
|
|
Example</div>
|
|
<img alt="AudioParam automation" src="images/audioparam-automation1.png" />
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">ECMAScript</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
var t0 = 0;
|
|
var t1 = 0.1;
|
|
var t2 = 0.2;
|
|
var t3 = 0.3;
|
|
var t4 = 0.4;
|
|
var t5 = 0.6;
|
|
var t6 = 0.7;
|
|
var t7 = 1.0;
|
|
|
|
var curveLength = 44100;
|
|
var curve = new Float32Array(curveLength);
|
|
for (var i = 0; i < curveLength; ++i)
|
|
curve[i] = Math.sin(Math.PI * i / curveLength);
|
|
|
|
param.setValueAtTime(0.2, t0);
|
|
param.setValueAtTime(0.3, t1);
|
|
param.setValueAtTime(0.4, t2);
|
|
param.linearRampToValueAtTime(1, t3);
|
|
param.linearRampToValueAtTime(0.15, t4);
|
|
param.exponentialRampToValueAtTime(0.75, t5);
|
|
param.exponentialRampToValueAtTime(0.05, t6);
|
|
param.setValueCurveAtTime(curve, t6, t7 - t6);
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="GainNode-section" class="section">
|
|
<h2 id="GainNode">4.7. The GainNode Interface</h2>
|
|
|
|
<p>Changing the gain of an audio signal is a fundamental operation in audio
|
|
applications. The <code>GainNode</code> is one of the building blocks for creating <a
|
|
href="#MixerGainStructure-section">mixers</a>.
|
|
This interface is an AudioNode with a single input and single
|
|
output: </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCountMode = "max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>It multiplies the input audio signal by the (possibly time-varying) <code>gain</code> attribute, copying the result to the output.
|
|
By default, it will take the input and pass it through to the output unchanged, which represents a constant gain change
|
|
of 1.
|
|
</p>
|
|
|
|
<p>
|
|
As with other <code>AudioParams</code>, the <code>gain</code> parameter represents a mapping from time
|
|
(in the coordinate system of AudioContext.currentTime) to floating-point value.
|
|
|
|
Every PCM audio sample in the input is multiplied by the <code>gain</code> parameter's value for the specific time
|
|
corresponding to that audio sample. This multiplied value represents the PCM audio sample for the output.
|
|
</p>
|
|
|
|
<p>
|
|
The number of channels of the output will always equal the number of channels of the input, with each channel
|
|
of the input being multiplied by the <code>gain</code> values and being copied into the corresponding channel
|
|
of the output.
|
|
</p>
|
|
|
|
<p>
|
|
The implementation must make
|
|
gain changes to the audio stream smoothly, without introducing noticeable
|
|
clicks or glitches. This process is called "de-zippering". </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="gain-node-idl">
|
|
|
|
interface <dfn id="dfn-GainNode">GainNode</dfn> : AudioNode {
|
|
|
|
readonly attribute AudioParam gain;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-GainNode-section" class="section">
|
|
<h3 id="attributes-GainNode">4.7.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-gain"><code>gain</code></dt>
|
|
<dd><p>Represents the amount of gain to apply. Its
|
|
default <code>value</code> is 1 (no gain change). The nominal <code>minValue</code> is 0, but may be
|
|
set negative for phase inversion. The nominal <code>maxValue</code> is 1, but higher values are allowed (no
|
|
exception thrown).This parameter is <em>a-rate</em> </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="DelayNode-section" class="section">
|
|
<h2 id="DelayNode">4.8. The DelayNode Interface</h2>
|
|
|
|
<p>A delay-line is a fundamental building block in audio applications. This
|
|
interface is an AudioNode with a single input and single output: </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCountMode = "max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>
|
|
The number of channels of the output always equals the number of channels of the input.
|
|
</p>
|
|
|
|
<p>It delays the incoming audio signal by a certain amount. The default
|
|
amount is 0 seconds (no delay). When the delay time is changed, the
|
|
implementation must make the transition smoothly, without introducing
|
|
noticeable clicks or glitches to the audio stream. </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="delay-node-idl">
|
|
|
|
interface <dfn id="dfn-DelayNode">DelayNode</dfn> : AudioNode {
|
|
|
|
readonly attribute AudioParam delayTime;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-GainNode-section_2" class="section">
|
|
<h3 id="attributes-GainNode_2">4.8.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-delayTime_2"><code>delayTime</code></dt>
|
|
<dd><p>An AudioParam object representing the amount of delay (in seconds)
|
|
to apply. The default value (<code>delayTime.value</code>) is 0 (no
|
|
delay). The minimum value is 0 and the maximum value is determined by the <em>maxDelayTime</em>
|
|
argument to the <code>AudioContext</code> method <code>createDelay</code>. This parameter is <em>a-rate</em></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="AudioBuffer-section" class="section">
|
|
<h2 id="AudioBuffer">4.9. The AudioBuffer Interface</h2>
|
|
|
|
<p>This interface represents a memory-resident audio asset (for one-shot sounds
|
|
and other short audio clips). Its format is non-interleaved IEEE 32-bit linear PCM with a
|
|
nominal range of -1 -> +1. It can contain one or more channels. Typically, it would be expected that the length
|
|
of the PCM data would be fairly short (usually somewhat less than a minute).
|
|
For longer sounds, such as music soundtracks, streaming should be used with the
|
|
<code>audio</code> element and <code>MediaElementAudioSourceNode</code>. </p>
|
|
|
|
<p>
|
|
An AudioBuffer may be used by one or more AudioContexts.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-buffer-idl">
|
|
|
|
interface <dfn id="dfn-AudioBuffer">AudioBuffer</dfn> {
|
|
|
|
readonly attribute float sampleRate;
|
|
readonly attribute long length;
|
|
|
|
<span class="comment">// in seconds </span>
|
|
readonly attribute double duration;
|
|
|
|
readonly attribute long numberOfChannels;
|
|
|
|
Float32Array getChannelData(unsigned long channel);
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioBuffer-section" class="section">
|
|
<h3 id="attributes-AudioBuffer">4.9.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-sampleRate_AudioBuffer"><code>sampleRate</code></dt>
|
|
<dd><p>The sample-rate for the PCM audio data in samples per second.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-length_AudioBuffer"><code>length</code></dt>
|
|
<dd><p>Length of the PCM audio data in sample-frames.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-duration_AudioBuffer"><code>duration</code></dt>
|
|
<dd><p>Duration of the PCM audio data in seconds.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-numberOfChannels_AudioBuffer"><code>numberOfChannels</code></dt>
|
|
<dd><p>The number of discrete audio channels.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="methodsandparams-AudioBuffer-section" class="section">
|
|
<h3 id="methodsandparams-AudioBuffer">4.9.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-getChannelData">The <code>getChannelData</code> method</dt>
|
|
<dd><p>Returns the <code>Float32Array</code> representing the PCM audio data for the specific channel.</p>
|
|
<p>The <dfn id="dfn-channel">channel</dfn> parameter is an index
|
|
representing the particular channel to get data for. An index value of 0 represents
|
|
the first channel. This index value MUST be less than <code>numberOfChannels</code>
|
|
or an exception will be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="AudioBufferSourceNode-section" class="section">
|
|
<h2 id="AudioBufferSourceNode">4.10. The AudioBufferSourceNode Interface</h2>
|
|
|
|
<p>This interface represents an audio source from an in-memory audio asset in
|
|
an <code>AudioBuffer</code>. It is useful for playing short audio assets
|
|
which require a high degree of scheduling flexibility (can playback in
|
|
rhythmically perfect ways). The start() method is used to schedule when
|
|
sound playback will happen. The playback will stop automatically when
|
|
the buffer's audio data has been completely
|
|
played (if the <code>loop</code> attribute is false), or when the stop()
|
|
method has been called and the specified time has been reached. Please see more
|
|
details in the start() and stop() description. start() and stop() may not be issued
|
|
multiple times for a given
|
|
AudioBufferSourceNode. </p>
|
|
<pre> numberOfInputs : 0
|
|
numberOfOutputs : 1
|
|
</pre>
|
|
|
|
<p>
|
|
The number of channels of the output always equals the number of channels of the AudioBuffer
|
|
assigned to the .buffer attribute, or is one channel of silence if .buffer is NULL.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-buffer-source-node-idl">
|
|
|
|
interface <dfn id="dfn-AudioBufferSourceNode">AudioBufferSourceNode</dfn> : AudioNode {
|
|
|
|
attribute AudioBuffer? buffer;
|
|
|
|
readonly attribute AudioParam playbackRate;
|
|
|
|
attribute boolean loop;
|
|
attribute double loopStart;
|
|
attribute double loopEnd;
|
|
|
|
void start(optional double when = 0, optional double offset = 0, optional double duration);
|
|
void stop(optional double when = 0);
|
|
|
|
attribute EventHandler onended;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioBufferSourceNode-section" class="section">
|
|
<h3 id="attributes-AudioBufferSourceNode">4.10.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-buffer_AudioBufferSourceNode"><code>buffer</code></dt>
|
|
<dd><p>Represents the audio asset to be played. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-playbackRate_AudioBufferSourceNode"><code>playbackRate</code></dt>
|
|
<dd><p>The speed at which to render the audio stream. The default
|
|
playbackRate.value is 1. This parameter is <em>a-rate</em> </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-loop_AudioBufferSourceNode"><code>loop</code></dt>
|
|
<dd><p>Indicates if the audio data should play in a loop. The default value is false. </p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
<dt id="dfn-loopStart_AudioBufferSourceNode"><code>loopStart</code></dt>
|
|
<dd><p>An optional value in seconds where looping should begin if the <code>loop</code> attribute is true.
|
|
Its default value is 0, and it may usefully be set to any value between 0 and the duration of the buffer.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-loopEnd_AudioBufferSourceNode"><code>loopEnd</code></dt>
|
|
<dd><p>An optional value in seconds where looping should end if the <code>loop</code> attribute is true.
|
|
Its default value is 0, and it may usefully be set to any value between 0 and the duration of the buffer.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-onended_AudioBufferSourceNode"><code>onended</code></dt>
|
|
<dd><p>A property used to set the <code>EventHandler</code> (described in <cite><a
|
|
href="http://www.whatwg.org/specs/web-apps/current-work/#eventhandler">HTML</a></cite>)
|
|
for the ended event that is dispatched to <a
|
|
href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>
|
|
node types. When the playback of the buffer for an <code>AudioBufferSourceNode</code>
|
|
is finished, an event of type <code>Event</code> (described in <cite><a
|
|
href="http://www.whatwg.org/specs/web-apps/current-work/#event">HTML</a></cite>)
|
|
will be dispatched to the event handler. </p>
|
|
</dd>
|
|
</dl>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="methodsandparams-AudioBufferSourceNode-section" class="section">
|
|
<h3 id="methodsandparams-AudioBufferSourceNode">4.10.2. Methods and
|
|
Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-start">The <code>start</code> method</dt>
|
|
<dd><p>Schedules a sound to playback at an exact time.</p>
|
|
<p>The <dfn id="dfn-when">when</dfn> parameter describes at what time (in
|
|
seconds) the sound should start playing. It is in the same
|
|
time coordinate system as AudioContext.currentTime. If 0 is passed in for
|
|
this value or if the value is less than <b>currentTime</b>, then the
|
|
sound will start playing immediately. <code>start</code> may only be called one time
|
|
and must be called before <code>stop</code> is called or an exception will be thrown.</p>
|
|
<p>The <dfn id="dfn-offset">offset</dfn> parameter describes
|
|
the offset time in the buffer (in seconds) where playback will begin. If 0 is passed
|
|
in for this value, then playback will start from the beginning of the buffer.</p>
|
|
<p>The <dfn id="dfn-duration">duration</dfn> parameter
|
|
describes the duration of the portion (in seconds) to be played. If this parameter is not passed,
|
|
the duration will be equal to the total duration of the AudioBuffer minus the <code>offset</code> parameter.
|
|
Thus if neither <code>offset</code> nor <code>duration</code> are specified then the implied duration is
|
|
the total duration of the AudioBuffer.
|
|
</p>
|
|
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-stop">The <code>stop</code> method</dt>
|
|
<dd><p>Schedules a sound to stop playback at an exact time.</p>
|
|
<p>The <dfn id="dfn-when_AudioBufferSourceNode_2">when</dfn> parameter
|
|
describes at what time (in seconds) the sound should stop playing.
|
|
It is in the same time coordinate system as AudioContext.currentTime.
|
|
If 0 is passed in for this value or if the value is less than
|
|
<b>currentTime</b>, then the sound will stop playing immediately.
|
|
<code>stop</code> must only be called one time and only after a call to <code>start</code> or <code>stop</code>,
|
|
or an exception will be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="looping-AudioBufferSourceNode-section" class="section">
|
|
<h3 id="looping-AudioBufferSourceNode">4.10.3. Looping</h3>
|
|
<p>
|
|
If the <code>loop</code> attribute is true when <code>start()</code> is called, then playback will continue indefinitely
|
|
until <code>stop()</code> is called and the stop time is reached. We'll call this "loop" mode. Playback always starts at the point in the buffer indicated
|
|
by the <code>offset</code> argument of <code>start()</code>, and in <em>loop</em> mode will continue playing until it reaches the <em>actualLoopEnd</em> position
|
|
in the buffer (or the end of the buffer), at which point it will wrap back around to the <em>actualLoopStart</em> position in the buffer, and continue
|
|
playing according to this pattern.
|
|
</p>
|
|
|
|
<p>
|
|
In <em>loop</em> mode then the <em>actual</em> loop points are calculated as follows from the <code>loopStart</code> and <code>loopEnd</code> attributes:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
if ((loopStart || loopEnd) && loopStart >= 0 && loopEnd > 0 && loopStart < loopEnd) {
|
|
actualLoopStart = loopStart;
|
|
actualLoopEnd = min(loopEnd, buffer.length);
|
|
} else {
|
|
actualLoopStart = 0;
|
|
actualLoopEnd = buffer.length;
|
|
}
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>
|
|
Note that the default values for <code>loopStart</code> and <code>loopEnd</code> are both 0, which indicates that looping should occur from the very start
|
|
to the very end of the buffer.
|
|
</p>
|
|
|
|
<p>
|
|
Please note that as a low-level implementation detail, the AudioBuffer is at a specific sample-rate (usually the same as the AudioContext sample-rate), and
|
|
that the loop times (in seconds) must be converted to the appropriate sample-frame positions in the buffer according to this sample-rate.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div id="MediaElementAudioSourceNode-section" class="section">
|
|
<h2 id="MediaElementAudioSourceNode">4.11. The MediaElementAudioSourceNode
|
|
Interface</h2>
|
|
|
|
<p>This interface represents an audio source from an <code>audio</code> or
|
|
<code>video</code> element. </p>
|
|
<pre> numberOfInputs : 0
|
|
numberOfOutputs : 1
|
|
</pre>
|
|
|
|
<p>
|
|
The number of channels of the output corresponds to the number of channels of the media referenced by the HTMLMediaElement.
|
|
Thus, changes to the media element's .src attribute can change the number of channels output by this node.
|
|
If the .src attribute is not set, then the number of channels output will be one silent channel.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="media-element-audio-source-node-idl">
|
|
|
|
interface <dfn id="dfn-MediaElementAudioSourceNode">MediaElementAudioSourceNode</dfn> : AudioNode {
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p>A MediaElementAudioSourceNode
|
|
is created given an HTMLMediaElement using the AudioContext <a href="#dfn-createMediaElementSource">createMediaElementSource()</a> method. </p>
|
|
|
|
<p>
|
|
The number of channels of the single output equals the number of channels of the audio referenced by
|
|
the HTMLMediaElement passed in as the argument to createMediaElementSource(), or is 1 if the HTMLMediaElement
|
|
has no audio.
|
|
</p>
|
|
|
|
<p>
|
|
The HTMLMediaElement must behave in an identical fashion after the MediaElementAudioSourceNode has
|
|
been created, <em>except</em> that the rendered audio will no longer be heard directly, but instead will be heard
|
|
as a consequence of the MediaElementAudioSourceNode being connected through the routing graph. Thus pausing, seeking,
|
|
volume, <code>.src</code> attribute changes, and other aspects of the HTMLMediaElement must behave as they normally would
|
|
if <em>not</em> used with a MediaElementAudioSourceNode.
|
|
</p>
|
|
|
|
<div class="example">
|
|
|
|
<div class="exampleHeader">
|
|
Example</div>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">ECMAScript</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
var mediaElement = document.getElementById('mediaElementID');
|
|
var sourceNode = context.createMediaElementSource(mediaElement);
|
|
sourceNode.connect(filterNode);
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="ScriptProcessorNode-section" class="section">
|
|
<h2 id="ScriptProcessorNode">4.12. The ScriptProcessorNode Interface</h2>
|
|
|
|
<p>This interface is an AudioNode which can generate, process, or analyse audio
|
|
directly using JavaScript. </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCount = numberOfInputChannels;
|
|
channelCountMode = "explicit";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>The ScriptProcessorNode is constructed with a <code>bufferSize</code> which
|
|
must be one of the following values: 256, 512, 1024, 2048, 4096, 8192, 16384.
|
|
This value controls how frequently the <code>audioprocess</code> event
|
|
is dispatched and how many sample-frames need to be processed each call.
|
|
Lower numbers for <code>bufferSize</code> will result in a lower (better) <a
|
|
href="#Latency-section">latency</a>. Higher numbers will be necessary to avoid
|
|
audio breakup and <a href="#Glitching-section">glitches</a>.
|
|
This value will be picked by the implementation if the bufferSize argument
|
|
to <code>createScriptProcessor</code> is not passed in, or is set to 0.</p>
|
|
|
|
<p><code>numberOfInputChannels</code> and <code>numberOfOutputChannels</code>
|
|
determine the number of input and output channels. It is invalid for both
|
|
<code>numberOfInputChannels</code> and <code>numberOfOutputChannels</code> to
|
|
be zero. </p>
|
|
<pre> var node = context.createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels);
|
|
</pre>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="script-processor-node-idl">
|
|
|
|
interface <dfn id="dfn-ScriptProcessorNode">ScriptProcessorNode</dfn> : AudioNode {
|
|
|
|
attribute EventHandler onaudioprocess;
|
|
|
|
readonly attribute long bufferSize;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-ScriptProcessorNode-section" class="section">
|
|
<h3 id="attributes-ScriptProcessorNode">4.12.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-onaudioprocess"><code>onaudioprocess</code></dt>
|
|
<dd><p>A property used to set the <code>EventHandler</code> (described in <cite><a
|
|
href="http://www.whatwg.org/specs/web-apps/current-work/#eventhandler">HTML</a></cite>)
|
|
for the audioprocess event that is dispatched to <a
|
|
href="#ScriptProcessorNode-section"><code>ScriptProcessorNode</code></a>
|
|
node types. An event of type <a
|
|
href="#AudioProcessingEvent-section"><code>AudioProcessingEvent</code></a>
|
|
will be dispatched to the event handler. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-bufferSize_ScriptProcessorNode"><code>bufferSize</code></dt>
|
|
<dd><p>The size of the buffer (in sample-frames) which needs to be
|
|
processed each time <code>onprocessaudio</code> is called. Legal values
|
|
are (256, 512, 1024, 2048, 4096, 8192, 16384). </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="AudioProcessingEvent-section" class="section">
|
|
<h2 id="AudioProcessingEvent">4.13. The AudioProcessingEvent Interface</h2>
|
|
|
|
<p>This is an <code>Event</code> object which is dispatched to <a
|
|
href="#ScriptProcessorNode-section"><code>ScriptProcessorNode</code></a> nodes. </p>
|
|
|
|
<p>The event handler processes audio from the input (if any) by accessing the
|
|
audio data from the <code>inputBuffer</code> attribute. The audio data which is
|
|
the result of the processing (or the synthesized data if there are no inputs)
|
|
is then placed into the <code>outputBuffer</code>. </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-processing-event-idl">
|
|
|
|
interface <dfn id="dfn-AudioProcessingEvent">AudioProcessingEvent</dfn> : Event {
|
|
|
|
readonly attribute double playbackTime;
|
|
readonly attribute AudioBuffer inputBuffer;
|
|
readonly attribute AudioBuffer outputBuffer;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioProcessingEvent-section" class="section">
|
|
<h3 id="attributes-AudioProcessingEvent">4.13.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-playbackTime"><code>playbackTime</code></dt>
|
|
<dd><p>The time when the audio will be played in the same time coordinate system as AudioContext.currentTime.
|
|
<code>playbackTime</code> allows for very tight synchronization between
|
|
processing directly in JavaScript with the other events in the context's
|
|
rendering graph. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-inputBuffer"><code>inputBuffer</code></dt>
|
|
<dd><p>An AudioBuffer containing the input audio data. It will have a number of channels equal to the <code>numberOfInputChannels</code> parameter
|
|
of the createScriptProcessor() method. This AudioBuffer is only valid while in the scope of the <code>onaudioprocess</code>
|
|
function. Its values will be meaningless outside of this scope.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-outputBuffer"><code>outputBuffer</code></dt>
|
|
<dd><p>An AudioBuffer where the output audio data should be written. It will have a number of channels equal to the
|
|
<code>numberOfOutputChannels</code> parameter of the createScriptProcessor() method.
|
|
Script code within the scope of the <code>onaudioprocess</code> function is expected to modify the
|
|
<code>Float32Array</code> arrays representing channel data in this AudioBuffer.
|
|
Any script modifications to this AudioBuffer outside of this scope will not produce any audible effects.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="PannerNode-section" class="section">
|
|
<h2 id="PannerNode">4.14. The PannerNode Interface</h2>
|
|
|
|
<p>This interface represents a processing node which <a
|
|
href="#Spatialization-section">positions / spatializes</a> an incoming audio
|
|
stream in three-dimensional space. The spatialization is in relation to the <a
|
|
href="#AudioContext-section"><code>AudioContext</code></a>'s <a
|
|
href="#AudioListener-section"><code>AudioListener</code></a>
|
|
(<code>listener</code> attribute). </p>
|
|
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCount = 2;
|
|
channelCountMode = "clamped-max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>
|
|
The audio stream from the input will be either mono or stereo, depending on the connection(s) to the input.
|
|
</p>
|
|
|
|
<p>
|
|
The output of this node is hard-coded to stereo (2 channels) and <em>currently</em> cannot be configured.
|
|
</p>
|
|
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="panner-node-idl">
|
|
|
|
enum <dfn>PanningModelType</dfn> {
|
|
"equalpower",
|
|
"HRTF"
|
|
};
|
|
|
|
enum <dfn>DistanceModelType</dfn> {
|
|
"linear",
|
|
"inverse",
|
|
"exponential"
|
|
};
|
|
|
|
interface <dfn id="dfn-PannerNode">PannerNode</dfn> : AudioNode {
|
|
|
|
<span class="comment">// Default for stereo is HRTF </span>
|
|
attribute PanningModelType panningModel;
|
|
|
|
<span class="comment">// Uses a 3D cartesian coordinate system </span>
|
|
void setPosition(double x, double y, double z);
|
|
void setOrientation(double x, double y, double z);
|
|
void setVelocity(double x, double y, double z);
|
|
|
|
<span class="comment">// Distance model and attributes </span>
|
|
attribute DistanceModelType distanceModel;
|
|
attribute double refDistance;
|
|
attribute double maxDistance;
|
|
attribute double rolloffFactor;
|
|
|
|
<span class="comment">// Directional sound cone </span>
|
|
attribute double coneInnerAngle;
|
|
attribute double coneOuterAngle;
|
|
attribute double coneOuterGain;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-PannerNode_attributes-section" class="section">
|
|
<h3 id="attributes-PannerNode_attributes">4.14.2. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-panningModel"><code>panningModel</code></dt>
|
|
<dd><p>Determines which spatialization algorithm will be used to position
|
|
the audio in 3D space. The default is "HRTF". </p>
|
|
|
|
<dl>
|
|
<dt id="dfn-EQUALPOWER"><code>"equalpower"</code></dt>
|
|
<dd><p>A simple and efficient spatialization algorithm using equal-power
|
|
panning. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-HRTF"><code>"HRTF"</code></dt>
|
|
<dd><p>A higher quality spatialization algorithm using a convolution with
|
|
measured impulse responses from human subjects. This panning method
|
|
renders stereo output. </p>
|
|
</dd>
|
|
</dl>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-distanceModel"><code>distanceModel</code></dt>
|
|
<dd><p>Determines which algorithm will be used to reduce the volume of an
|
|
audio source as it moves away from the listener. The default is "inverse".
|
|
</p>
|
|
|
|
<dl>
|
|
<dt id="dfn-LINEAR_DISTANCE"><code>"linear"</code></dt>
|
|
<dd><p>A linear distance model which calculates <em>distanceGain</em> according to: </p>
|
|
<pre>
|
|
1 - rolloffFactor * (distance - refDistance) / (maxDistance - refDistance)
|
|
</pre>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-INVERSE_DISTANCE"><code>"inverse"</code></dt>
|
|
<dd><p>An inverse distance model which calculates <em>distanceGain</em> according to: </p>
|
|
<pre>
|
|
refDistance / (refDistance + rolloffFactor * (distance - refDistance))
|
|
</pre>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-EXPONENTIAL_DISTANCE"><code>"exponential"</code></dt>
|
|
<dd><p>An exponential distance model which calculates <em>distanceGain</em> according to: </p>
|
|
<pre>
|
|
pow(distance / refDistance, -rolloffFactor)
|
|
</pre>
|
|
</dd>
|
|
</dl>
|
|
|
|
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-refDistance"><code>refDistance</code></dt>
|
|
<dd><p>A reference distance for reducing volume as source move further from
|
|
the listener. The default value is 1. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-maxDistance"><code>maxDistance</code></dt>
|
|
<dd><p>The maximum distance between source and listener, after which the
|
|
volume will not be reduced any further. The default value is 10000. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-rolloffFactor"><code>rolloffFactor</code></dt>
|
|
<dd><p>Describes how quickly the volume is reduced as source moves away
|
|
from listener. The default value is 1. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-coneInnerAngle"><code>coneInnerAngle</code></dt>
|
|
<dd><p>A parameter for directional audio sources, this is an angle, inside
|
|
of which there will be no volume reduction. The default value is 360. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-coneOuterAngle"><code>coneOuterAngle</code></dt>
|
|
<dd><p>A parameter for directional audio sources, this is an angle, outside
|
|
of which the volume will be reduced to a constant value of
|
|
<b>coneOuterGain</b>. The default value is 360. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-coneOuterGain"><code>coneOuterGain</code></dt>
|
|
<dd><p>A parameter for directional audio sources, this is the amount of
|
|
volume reduction outside of the <b>coneOuterAngle</b>. The default value is 0. </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<h3 id="Methods_and_Parameters">4.14.3. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-setPosition">The <code>setPosition</code> method</dt>
|
|
<dd><p>Sets the position of the audio source relative to the
|
|
<b>listener</b> attribute. A 3D cartesian coordinate system is used.</p>
|
|
<p>The <dfn id="dfn-x">x, y, z</dfn> parameters represent the coordinates
|
|
in 3D space. </p>
|
|
<p>The default value is (0,0,0)
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-setOrientation">The <code>setOrientation</code> method</dt>
|
|
<dd><p>Describes which direction the audio source is pointing in the 3D
|
|
cartesian coordinate space. Depending on how directional the sound is
|
|
(controlled by the <b>cone</b> attributes), a sound pointing away from
|
|
the listener can be very quiet or completely silent.</p>
|
|
<p>The <dfn id="dfn-x_2">x, y, z</dfn> parameters represent a direction
|
|
vector in 3D space. </p>
|
|
<p>The default value is (1,0,0)
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-setVelocity">The <code>setVelocity</code> method</dt>
|
|
<dd><p>Sets the velocity vector of the audio source. This vector controls
|
|
both the direction of travel and the speed in 3D space. This velocity
|
|
relative to the listener's velocity is used to determine how much doppler
|
|
shift (pitch change) to apply. The units used for this vector is <em>meters / second</em>
|
|
and is independent of the units used for position and orientation vectors.</p>
|
|
<p>The <dfn id="dfn-x_3">x, y, z</dfn> parameters describe a direction
|
|
vector indicating direction of travel and intensity. </p>
|
|
<p>The default value is (0,0,0)
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<div id="AudioListener-section" class="section">
|
|
<h2 id="AudioListener">4.15. The AudioListener Interface</h2>
|
|
|
|
<p>This interface represents the position and orientation of the person
|
|
listening to the audio scene. All <a
|
|
href="#PannerNode-section"><code>PannerNode</code></a> objects
|
|
spatialize in relation to the AudioContext's <code>listener</code>. See <a
|
|
href="#Spatialization-section">this</a> section for more details about
|
|
spatialization. </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="audio-listener-idl">
|
|
|
|
interface <dfn id="dfn-AudioListener">AudioListener</dfn> {
|
|
|
|
attribute double dopplerFactor;
|
|
attribute double speedOfSound;
|
|
|
|
<span class="comment">// Uses a 3D cartesian coordinate system </span>
|
|
void setPosition(double x, double y, double z);
|
|
void setOrientation(double x, double y, double z, double xUp, double yUp, double zUp);
|
|
void setVelocity(double x, double y, double z);
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-AudioListener-section" class="section">
|
|
<h3 id="attributes-AudioListener">4.15.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-dopplerFactor"><code>dopplerFactor</code></dt>
|
|
<dd><p>A constant used to determine the amount of pitch shift to use when
|
|
rendering a doppler effect. The default value is 1. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-speedOfSound"><code>speedOfSound</code></dt>
|
|
<dd><p>The speed of sound used for calculating doppler shift. The default
|
|
value is 343.3. </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<h3 id="L15842">4.15.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-setPosition_2">The <code>setPosition</code> method</dt>
|
|
<dd><p>Sets the position of the listener in a 3D cartesian coordinate
|
|
space. <code>PannerNode</code> objects use this position relative to
|
|
individual audio sources for spatialization.</p>
|
|
<p>The <dfn id="dfn-x_AudioListener">x, y, z</dfn> parameters represent
|
|
the coordinates in 3D space. </p>
|
|
<p>The default value is (0,0,0)
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-setOrientation_2">The <code>setOrientation</code> method</dt>
|
|
<dd><p>Describes which direction the listener is pointing in the 3D
|
|
cartesian coordinate space. Both a <b>front</b> vector and an <b>up</b>
|
|
vector are provided. In simple human terms, the <b>front</b> vector represents which
|
|
direction the person's nose is pointing. The <b>up</b> vector represents the
|
|
direction the top of a person's head is pointing. These values are expected to
|
|
be linearly independent (at right angles to each other). For normative requirements
|
|
of how these values are to be interpreted, see the
|
|
<a href="#Spatialization-section">spatialization section</a>.
|
|
</p>
|
|
<p>The <dfn id="dfn-x_setOrientation">x, y, z</dfn> parameters represent
|
|
a <b>front</b> direction vector in 3D space, with the default value being (0,0,-1) </p>
|
|
<p>The <dfn id="dfn-x_setOrientation_2">xUp, yUp, zUp</dfn> parameters
|
|
represent an <b>up</b> direction vector in 3D space, with the default value being (0,1,0) </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-setVelocity_4">The <code>setVelocity</code> method</dt>
|
|
<dd><p>Sets the velocity vector of the listener. This vector controls both
|
|
the direction of travel and the speed in 3D space. This velocity relative to
|
|
an audio source's velocity is used to determine how much doppler shift
|
|
(pitch change) to apply. The units used for this vector is <em>meters / second</em>
|
|
and is independent of the units used for position and orientation vectors.</p>
|
|
<p>The <dfn id="dfn-x_setVelocity_5">x, y, z</dfn> parameters describe a
|
|
direction vector indicating direction of travel and intensity. </p>
|
|
<p>The default value is (0,0,0)
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<div id="ConvolverNode-section" class="section">
|
|
<h2 id="ConvolverNode">4.16. The ConvolverNode Interface</h2>
|
|
|
|
<p>This interface represents a processing node which applies a <a
|
|
href="#Convolution-section">linear convolution effect</a> given an impulse
|
|
response. Normative requirements for multi-channel convolution matrixing are described
|
|
<a href="#Convolution-reverb-effect">here</a>. </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCount = 2;
|
|
channelCountMode = "clamped-max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="convolver-node-idl">
|
|
|
|
interface <dfn id="dfn-ConvolverNode">ConvolverNode</dfn> : AudioNode {
|
|
|
|
attribute AudioBuffer? buffer;
|
|
attribute boolean normalize;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-ConvolverNode-section" class="section">
|
|
<h3 id="attributes-ConvolverNode">4.16.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-buffer_ConvolverNode"><code>buffer</code></dt>
|
|
<dd><p>A mono, stereo, or 4-channel <code>AudioBuffer</code> containing the (possibly multi-channel) impulse response
|
|
used by the ConvolverNode. This <code>AudioBuffer</code> must be of the same sample-rate as the AudioContext or an exception will
|
|
be thrown. At the time when this attribute is set, the <em>buffer</em> and the state of the <em>normalize</em>
|
|
attribute will be used to configure the ConvolverNode with this impulse response having the given normalization.
|
|
The initial value of this attribute is null.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-normalize"><code>normalize</code></dt>
|
|
<dd><p>Controls whether the impulse response from the buffer will be scaled
|
|
by an equal-power normalization when the <code>buffer</code> atttribute
|
|
is set. Its default value is <code>true</code> in order to achieve a more
|
|
uniform output level from the convolver when loaded with diverse impulse
|
|
responses. If <code>normalize</code> is set to <code>false</code>, then
|
|
the convolution will be rendered with no pre-processing/scaling of the
|
|
impulse response. Changes to this value do not take effect until the next time
|
|
the <em>buffer</em> attribute is set. </p>
|
|
|
|
</dd>
|
|
</dl>
|
|
|
|
<p>
|
|
If the <em>normalize</em> attribute is false when the <em>buffer</em> attribute is set then the
|
|
ConvolverNode will perform a linear convolution given the exact impulse response contained within the <em>buffer</em>.
|
|
</p>
|
|
<p>
|
|
Otherwise, if the <em>normalize</em> attribute is true when the <em>buffer</em> attribute is set then the
|
|
ConvolverNode will first perform a scaled RMS-power analysis of the audio data contained within <em>buffer</em> to calculate a
|
|
<em>normalizationScale</em> given this algorithm:
|
|
</p>
|
|
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
|
|
float calculateNormalizationScale(buffer)
|
|
{
|
|
const float GainCalibration = 0.00125;
|
|
const float GainCalibrationSampleRate = 44100;
|
|
const float MinPower = 0.000125;
|
|
|
|
// Normalize by RMS power.
|
|
size_t numberOfChannels = buffer->numberOfChannels();
|
|
size_t length = buffer->length();
|
|
|
|
float power = 0;
|
|
|
|
for (size_t i = 0; i < numberOfChannels; ++i) {
|
|
float* sourceP = buffer->channel(i)->data();
|
|
float channelPower = 0;
|
|
|
|
int n = length;
|
|
while (n--) {
|
|
float sample = *sourceP++;
|
|
channelPower += sample * sample;
|
|
}
|
|
|
|
power += channelPower;
|
|
}
|
|
|
|
power = sqrt(power / (numberOfChannels * length));
|
|
|
|
// Protect against accidental overload.
|
|
if (isinf(power) || isnan(power) || power < MinPower)
|
|
power = MinPower;
|
|
|
|
float 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 (buffer->numberOfChannels() == 4)
|
|
scale *= 0.5;
|
|
|
|
return scale;
|
|
}
|
|
</code></pre>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p>
|
|
During processing, the ConvolverNode will then take this calculated <em>normalizationScale</em> value and multiply it by the result of the linear convolution
|
|
resulting from processing the input with the impulse response (represented by the <em>buffer</em>) to produce the
|
|
final output. Or any mathematically equivalent operation may be used, such as pre-multiplying the
|
|
input by <em>normalizationScale</em>, or pre-multiplying a version of the impulse-response by <em>normalizationScale</em>.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div id="AnalyserNode-section" class="section">
|
|
<h2 id="AnalyserNode">4.17. The AnalyserNode Interface</h2>
|
|
|
|
<p>This interface represents a node which is able to provide real-time
|
|
frequency and time-domain <a href="#AnalyserNode">analysis</a>
|
|
information. The audio stream will be passed un-processed from input to output.
|
|
</p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1 <em>Note that this output may be left unconnected.</em>
|
|
|
|
channelCount = 1;
|
|
channelCountMode = "explicit";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="analyser-node-idl">
|
|
|
|
interface <dfn id="dfn-AnalyserNode">AnalyserNode</dfn> : AudioNode {
|
|
|
|
<span class="comment">// Real-time frequency-domain data </span>
|
|
void getFloatFrequencyData(Float32Array array);
|
|
void getByteFrequencyData(Uint8Array array);
|
|
|
|
<span class="comment">// Real-time waveform data </span>
|
|
void getByteTimeDomainData(Uint8Array array);
|
|
|
|
attribute unsigned long fftSize;
|
|
readonly attribute unsigned long frequencyBinCount;
|
|
|
|
attribute double minDecibels;
|
|
attribute double maxDecibels;
|
|
|
|
attribute double smoothingTimeConstant;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-ConvolverNode-section_2" class="section">
|
|
<h3 id="attributes-ConvolverNode_2">4.17.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-fftSize"><code>fftSize</code></dt>
|
|
<dd><p>The size of the FFT used for frequency-domain analysis. This must be
|
|
a non-zero power of two in the range 32 to 2048, otherwise an INDEX_SIZE_ERR exception MUST be thrown.
|
|
The default value is 2048.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-frequencyBinCount"><code>frequencyBinCount</code></dt>
|
|
<dd><p>Half the FFT size. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-minDecibels"><code>minDecibels</code></dt>
|
|
<dd><p>The minimum power value in the scaling range for the FFT analysis
|
|
data for conversion to unsigned byte values.
|
|
The default value is -100.
|
|
If the value of this attribute is set to a value more than or equal to <code>maxDecibels</code>,
|
|
an INDEX_SIZE_ERR exception MUST be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-maxDecibels"><code>maxDecibels</code></dt>
|
|
<dd><p>The maximum power value in the scaling range for the FFT analysis
|
|
data for conversion to unsigned byte values.
|
|
The default value is -30.
|
|
If the value of this attribute is set to a value less than or equal to <code>minDecibels</code>,
|
|
an INDEX_SIZE_ERR exception MUST be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-smoothingTimeConstant"><code>smoothingTimeConstant</code></dt>
|
|
<dd><p>A value from 0 -> 1 where 0 represents no time averaging
|
|
with the last analysis frame.
|
|
The default value is 0.8.
|
|
If the value of this attribute is set to a value less than 0 or more than 1,
|
|
an INDEX_SIZE_ERR exception MUST be thrown.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<h3 id="methods-and-parameters">4.17.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-getFloatFrequencyData">The <code>getFloatFrequencyData</code>
|
|
method</dt>
|
|
<dd><p>Copies the current frequency data into the passed floating-point
|
|
array. If the array has fewer elements than the frequencyBinCount, the
|
|
excess elements will be dropped. If the array has more elements than
|
|
the frequencyBinCount, the excess elements will be ignored.</p>
|
|
<p>The <dfn id="dfn-array">array</dfn> parameter is where
|
|
frequency-domain analysis data will be copied. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-getByteFrequencyData">The <code>getByteFrequencyData</code>
|
|
method</dt>
|
|
<dd><p>Copies the current frequency data into the passed unsigned byte
|
|
array. If the array has fewer elements than the frequencyBinCount, the
|
|
excess elements will be dropped. If the array has more elements than
|
|
the frequencyBinCount, the excess elements will be ignored.</p>
|
|
<p>The <dfn id="dfn-array_2">array</dfn> parameter is where
|
|
frequency-domain analysis data will be copied. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-getByteTimeDomainData">The <code>getByteTimeDomainData</code>
|
|
method</dt>
|
|
<dd><p>Copies the current time-domain (waveform) data into the passed
|
|
unsigned byte array. If the array has fewer elements than the
|
|
fftSize, the excess elements will be dropped. If the array has more
|
|
elements than fftSize, the excess elements will be ignored.</p>
|
|
<p>The <dfn id="dfn-array_3">array</dfn> parameter is where time-domain
|
|
analysis data will be copied. </p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<div id="ChannelSplitterNode-section" class="section">
|
|
<h2 id="ChannelSplitterNode">4.18. The ChannelSplitterNode Interface</h2>
|
|
|
|
<p>The <code>ChannelSplitterNode</code> is for use in more advanced
|
|
applications and would often be used in conjunction with <a
|
|
href="#ChannelMergerNode-section"><code>ChannelMergerNode</code></a>. </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : Variable N (defaults to 6) // number of "active" (non-silent) outputs is determined by number of channels in the input
|
|
|
|
channelCountMode = "max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>This interface represents an AudioNode for accessing the individual channels
|
|
of an audio stream in the routing graph. It has a single input, and a number of
|
|
"active" outputs which equals the number of channels in the input audio stream.
|
|
For example, if a stereo input is connected to an
|
|
<code>ChannelSplitterNode</code> then the number of active outputs will be two
|
|
(one from the left channel and one from the right). There are always a total
|
|
number of N outputs (determined by the <code>numberOfOutputs</code> parameter to the AudioContext method <code>createChannelSplitter()</code>),
|
|
The default number is 6 if this value is not provided. Any outputs
|
|
which are not "active" will output silence and would typically not be connected
|
|
to anything. </p>
|
|
|
|
<h3 id="example-1">Example:</h3>
|
|
<img alt="channel splitter" src="images/channel-splitter.png" />
|
|
|
|
<p>Please note that in this example, the splitter does <b>not</b> interpret the channel identities (such as left, right, etc.), but
|
|
simply splits out channels in the order that they are input.</p>
|
|
|
|
<p>One application for <code>ChannelSplitterNode</code> is for doing "matrix
|
|
mixing" where individual gain control of each channel is desired. </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="channel-splitter-node-idl">
|
|
|
|
interface <dfn id="dfn-ChannelSplitterNode">ChannelSplitterNode</dfn> : AudioNode {
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="ChannelMergerNode-section" class="section">
|
|
<h2 id="ChannelMergerNode">4.19. The ChannelMergerNode Interface</h2>
|
|
|
|
<p>The <code>ChannelMergerNode</code> is for use in more advanced applications
|
|
and would often be used in conjunction with <a
|
|
href="#ChannelSplitterNode-section"><code>ChannelSplitterNode</code></a>. </p>
|
|
<pre>
|
|
numberOfInputs : Variable N (default to 6) // number of connected inputs may be less than this
|
|
numberOfOutputs : 1
|
|
|
|
channelCountMode = "max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>This interface represents an AudioNode for combining channels from multiple
|
|
audio streams into a single audio stream. It has a variable number of inputs (defaulting to 6), but not all of them
|
|
need be connected. There is a single output whose audio stream has a number of
|
|
channels equal to the sum of the numbers of channels of all the connected
|
|
inputs. For example, if an <code>ChannelMergerNode</code> has two connected
|
|
inputs (both stereo), then the output will be four channels, the first two from
|
|
the first input and the second two from the second input. In another example
|
|
with two connected inputs (both mono), the output will be two channels
|
|
(stereo), with the left channel coming from the first input and the right
|
|
channel coming from the second input. </p>
|
|
|
|
<h3 id="example-2">Example:</h3>
|
|
<img alt="channel merger" src="images/channel-merger.png" />
|
|
|
|
<p>Please note that in this example, the merger does <b>not</b> interpret the channel identities (such as left, right, etc.), but
|
|
simply combines channels in the order that they are input.</p>
|
|
|
|
|
|
<p>Be aware that it is possible to connect an <code>ChannelMergerNode</code>
|
|
in such a way that it outputs an audio stream with a large number of channels
|
|
greater than the maximum supported by the audio hardware. In this case where such an output is connected
|
|
to the AudioContext .destination (the audio hardware), then the extra channels will be ignored.
|
|
Thus, the <code>ChannelMergerNode</code> should be used in situations where the number
|
|
of channels is well understood. </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="channel-merger-node-idl">
|
|
|
|
interface <dfn id="dfn-ChannelMergerNode">ChannelMergerNode</dfn> : AudioNode {
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="DynamicsCompressorNode-section" class="section">
|
|
<h2 id="DynamicsCompressorNode">4.20. The DynamicsCompressorNode Interface</h2>
|
|
|
|
<p>DynamicsCompressorNode is an AudioNode processor implementing a dynamics
|
|
compression effect. </p>
|
|
|
|
<p>Dynamics compression is very commonly used in musical production and game
|
|
audio. It lowers the volume of the loudest parts of the signal and raises the
|
|
volume of the softest parts. Overall, a louder, richer, and fuller sound can be
|
|
achieved. It is especially important in games and musical applications where
|
|
large numbers of individual sounds are played simultaneous to control the
|
|
overall signal level and help avoid clipping (distorting) the audio output to
|
|
the speakers. </p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCount = 2;
|
|
channelCountMode = "explicit";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="dynamics-compressor-node-idl">
|
|
|
|
interface <dfn id="dfn-DynamicsCompressorNode">DynamicsCompressorNode</dfn> : AudioNode {
|
|
|
|
readonly attribute AudioParam threshold; // in Decibels
|
|
readonly attribute AudioParam knee; // in Decibels
|
|
readonly attribute AudioParam ratio; // unit-less
|
|
readonly attribute AudioParam reduction; // in Decibels
|
|
readonly attribute AudioParam attack; // in Seconds
|
|
readonly attribute AudioParam release; // in Seconds
|
|
|
|
};
|
|
</code>
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-DynamicsCompressorNode-section" class="section">
|
|
<h3 id="attributes-DynamicsCompressorNode">4.20.1. Attributes</h3>
|
|
<p>
|
|
All parameters are <em>k-rate</em>
|
|
</p>
|
|
|
|
<dl>
|
|
<dt id="dfn-threshold"><code>threshold</code></dt>
|
|
<dd><p>The decibel value above which the compression will start taking
|
|
effect. Its default value is -24, with a nominal range of -100 to 0. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-knee"><code>knee</code></dt>
|
|
<dd><p>A decibel value representing the range above the threshold where the
|
|
curve smoothly transitions to the "ratio" portion. Its default value is 30, with a nominal range of 0 to 40. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-ratio"><code>ratio</code></dt>
|
|
<dd><p>The amount of dB change in input for a 1 dB change in output. Its default value is 12, with a nominal range of 1 to 20. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-reduction"><code>reduction</code></dt>
|
|
<dd><p>A read-only decibel value for metering purposes, representing the
|
|
current amount of gain reduction that the compressor is applying to the
|
|
signal. If fed no signal the value will be 0 (no gain reduction). The nominal range is -20 to 0. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-attack"><code>attack</code></dt>
|
|
<dd><p>The amount of time (in seconds) to reduce the gain by 10dB. Its default value is 0.003, with a nominal range of 0 to 1. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-release"><code>release</code></dt>
|
|
<dd><p>The amount of time (in seconds) to increase the gain by 10dB. Its default value is 0.250, with a nominal range of 0 to 1. </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="BiquadFilterNode-section" class="section">
|
|
<h2 id="BiquadFilterNode">4.21. The BiquadFilterNode Interface</h2>
|
|
|
|
<p>BiquadFilterNode is an AudioNode processor implementing very common
|
|
low-order filters. </p>
|
|
|
|
<p>Low-order filters are the building blocks of basic tone controls (bass, mid,
|
|
treble), graphic equalizers, and more advanced filters. Multiple
|
|
BiquadFilterNode filters can be combined to form more complex filters. The
|
|
filter parameters such as "frequency" can be changed over time for filter
|
|
sweeps, etc. Each BiquadFilterNode can be configured as one of a number of
|
|
common filter types as shown in the IDL below. The default filter type
|
|
is "lowpass".</p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCountMode = "max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
<p>
|
|
The number of channels of the output always equals the number of channels of the input.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="biquad-filter-node-idl">
|
|
|
|
enum <dfn>BiquadFilterType</dfn> {
|
|
"lowpass",
|
|
"highpass",
|
|
"bandpass",
|
|
"lowshelf",
|
|
"highshelf",
|
|
"peaking",
|
|
"notch",
|
|
"allpass"
|
|
};
|
|
|
|
interface <dfn id="dfn-BiquadFilterNode">BiquadFilterNode</dfn> : AudioNode {
|
|
|
|
attribute BiquadFilterType type;
|
|
readonly attribute AudioParam frequency; // in Hertz
|
|
readonly attribute AudioParam detune; // in Cents
|
|
readonly attribute AudioParam Q; // Quality factor
|
|
readonly attribute AudioParam gain; // in Decibels
|
|
|
|
void getFrequencyResponse(Float32Array frequencyHz,
|
|
Float32Array magResponse,
|
|
Float32Array phaseResponse);
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p>The filter types are briefly described below. We note that all of these
|
|
filters are very commonly used in audio processing. In terms of implementation,
|
|
they have all been derived from standard analog filter prototypes. For more
|
|
technical details, we refer the reader to the excellent <a
|
|
href="http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt">reference</a> by
|
|
Robert Bristow-Johnson.</p>
|
|
|
|
<p>
|
|
All parameters are <em>k-rate</em> with the following default parameter values:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>350Hz, with a nominal range of 10 to the Nyquist frequency (half the sample-rate).
|
|
</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>1, with a nominal range of 0.0001 to 1000.</dd>
|
|
<dt>gain</dt>
|
|
<dd>0, with a nominal range of -40 to 40.</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
|
|
|
|
<div id="BiquadFilterNode-description-section" class="section">
|
|
<h3 id="BiquadFilterNode-description">4.21.1 "lowpass"</h3>
|
|
|
|
<p>A <a href="http://en.wikipedia.org/wiki/Low-pass_filter">lowpass filter</a>
|
|
allows frequencies below the cutoff frequency to pass through and attenuates
|
|
frequencies above the cutoff. It implements a standard second-order
|
|
resonant lowpass filter with 12dB/octave rolloff.</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The cutoff frequency</dd>
|
|
<dt>Q</dt>
|
|
<dd>Controls how peaked the response will be at the cutoff frequency. A
|
|
large value makes the response more peaked. Please note that for this filter type, this
|
|
value is not a traditional Q, but is a resonance value in decibels.</dd>
|
|
<dt>gain</dt>
|
|
<dd>Not used in this filter type</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="HIGHPASS">4.21.2 "highpass"</h3>
|
|
|
|
<p>A <a href="http://en.wikipedia.org/wiki/High-pass_filter">highpass
|
|
filter</a> is the opposite of a lowpass filter. Frequencies above the cutoff
|
|
frequency are passed through, but frequencies below the cutoff are attenuated.
|
|
It implements a standard second-order resonant highpass filter with
|
|
12dB/octave rolloff.</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The cutoff frequency below which the frequencies are attenuated</dd>
|
|
<dt>Q</dt>
|
|
<dd>Controls how peaked the response will be at the cutoff frequency. A
|
|
large value makes the response more peaked. Please note that for this filter type, this
|
|
value is not a traditional Q, but is a resonance value in decibels.</dd>
|
|
<dt>gain</dt>
|
|
<dd>Not used in this filter type</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="BANDPASS">4.21.3 "bandpass"</h3>
|
|
|
|
<p>A <a href="http://en.wikipedia.org/wiki/Band-pass_filter">bandpass
|
|
filter</a> allows a range of frequencies to pass through and attenuates the
|
|
frequencies below and above this frequency range. It implements a
|
|
second-order bandpass filter.</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The center of the frequency band</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>Controls the width of the band. The width becomes narrower as the Q
|
|
value increases.</dd>
|
|
<dt>gain</dt>
|
|
<dd>Not used in this filter type</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="LOWSHELF">4.21.4 "lowshelf"</h3>
|
|
|
|
<p>The lowshelf filter allows all frequencies through, but adds a boost (or
|
|
attenuation) to the lower frequencies. It implements a second-order
|
|
lowshelf filter.</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The upper limit of the frequences where the boost (or attenuation) is
|
|
applied.</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>Not used in this filter type.</dd>
|
|
<dt>gain</dt>
|
|
<dd>The boost, in dB, to be applied. If the value is negative, the
|
|
frequencies are attenuated.</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="L16352">4.21.5 "highshelf"</h3>
|
|
|
|
<p>The highshelf filter is the opposite of the lowshelf filter and allows all
|
|
frequencies through, but adds a boost to the higher frequencies. It
|
|
implements a second-order highshelf filter</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The lower limit of the frequences where the boost (or attenuation) is
|
|
applied.</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>Not used in this filter type.</dd>
|
|
<dt>gain</dt>
|
|
<dd>The boost, in dB, to be applied. If the value is negative, the
|
|
frequencies are attenuated.</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="PEAKING">4.21.6 "peaking"</h3>
|
|
|
|
<p>The peaking filter allows all frequencies through, but adds a boost (or
|
|
attenuation) to a range of frequencies. </p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The center frequency of where the boost is applied.</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>Controls the width of the band of frequencies that are boosted. A
|
|
large value implies a narrow width.</dd>
|
|
<dt>gain</dt>
|
|
<dd>The boost, in dB, to be applied. If the value is negative, the
|
|
frequencies are attenuated.</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="NOTCH">4.21.7 "notch"</h3>
|
|
|
|
<p>The notch filter (also known as a <a
|
|
href="http://en.wikipedia.org/wiki/Band-stop_filter">band-stop or
|
|
band-rejection filter</a>) is the opposite of a bandpass filter. It allows all
|
|
frequencies through, except for a set of frequencies.</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The center frequency of where the notch is applied.</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>Controls the width of the band of frequencies that are attenuated. A
|
|
large value implies a narrow width.</dd>
|
|
<dt>gain</dt>
|
|
<dd>Not used in this filter type.</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="ALLPASS">4.21.8 "allpass"</h3>
|
|
|
|
<p>An <a
|
|
href="http://en.wikipedia.org/wiki/All-pass_filter#Digital_Implementation">allpass
|
|
filter</a> allows all frequencies through, but changes the phase relationship
|
|
between the various frequencies. It implements a second-order allpass
|
|
filter</p>
|
|
|
|
<blockquote>
|
|
<dl>
|
|
<dt>frequency</dt>
|
|
<dd>The frequency where the center of the phase transition occurs. Viewed
|
|
another way, this is the frequency with maximal <a
|
|
href="http://en.wikipedia.org/wiki/Group_delay">group delay</a>.</dd>
|
|
<dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
|
|
<dd>Controls how sharp the phase transition is at the center frequency. A
|
|
larger value implies a sharper transition and a larger group delay.</dd>
|
|
<dt>gain</dt>
|
|
<dd>Not used in this filter type.</dd>
|
|
</dl>
|
|
</blockquote>
|
|
|
|
<h3 id="Methods">4.21.9. Methods</h3>
|
|
<dl>
|
|
<dt id="dfn-getFrequencyResponse">The <code>getFrequencyResponse</code>
|
|
method</dt>
|
|
<dd><p>Given the current filter parameter settings, calculates the
|
|
frequency response for the specified frequencies. </p>
|
|
<p>The <dfn id="dfn-frequencyHz">frequencyHz</dfn> parameter specifies an
|
|
array of frequencies at which the response values will be calculated.</p>
|
|
<p>The <dfn id="dfn-magResponse">magResponse</dfn> parameter specifies an
|
|
output array receiving the linear magnitude response values.</p>
|
|
<p>The <dfn id="dfn-phaseResponse">phaseResponse</dfn> parameter
|
|
specifies an output array receiving the phase response values in
|
|
radians.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div id="WaveShaperNode-section" class="section">
|
|
<h2 id="WaveShaperNode">4.22. The WaveShaperNode Interface</h2>
|
|
|
|
<p>WaveShaperNode is an AudioNode processor implementing non-linear distortion
|
|
effects. </p>
|
|
|
|
<p>Non-linear waveshaping distortion is commonly used for both subtle
|
|
non-linear warming, or more obvious distortion effects. Arbitrary non-linear
|
|
shaping curves may be specified.</p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 1
|
|
|
|
channelCountMode = "max";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>
|
|
The number of channels of the output always equals the number of channels of the input.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="wave-shaper-node-idl">
|
|
|
|
enum <dfn>OverSampleType</dfn> {
|
|
"none",
|
|
"2x",
|
|
"4x"
|
|
};
|
|
|
|
interface <dfn id="dfn-WaveShaperNode">WaveShaperNode</dfn> : AudioNode {
|
|
|
|
attribute Float32Array? curve;
|
|
attribute OverSampleType oversample;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-WaveShaperNode-section" class="section">
|
|
<h3 id="attributes-WaveShaperNode">4.22.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-curve"><code>curve</code></dt>
|
|
<dd><p>The shaping curve used for the waveshaping effect. The input signal
|
|
is nominally within the range -1 -> +1. Each input sample within this
|
|
range will index into the shaping curve with a signal level of zero
|
|
corresponding to the center value of the curve array. Any sample value
|
|
less than -1 will correspond to the first value in the curve array. Any
|
|
sample value greater than +1 will correspond to the last value in
|
|
the curve array. The implementation must perform linear interpolation between
|
|
adjacent points in the curve. Initially the curve attribute is null, which means that
|
|
the WaveShaperNode will pass its input to its output without modification.</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
<dt id="dfn-oversample"><code>oversample</code></dt>
|
|
<dd><p>Specifies what type of oversampling (if any) should be used when applying the shaping curve.
|
|
The default value is "none", meaning the curve will be applied directly to the input samples.
|
|
A value of "2x" or "4x" can improve the quality of the processing by avoiding some aliasing, with
|
|
the "4x" value yielding the highest quality. For some applications, it's better to use no oversampling
|
|
in order to get a very precise shaping curve.
|
|
</p>
|
|
<p>
|
|
A value of "2x" or "4x" means that the following steps must be performed:
|
|
<ol>
|
|
<li>Up-sample the input samples to 2x or 4x the sample-rate of the AudioContext. Thus for each
|
|
processing block of 128 samples, generate 256 (for 2x) or 512 (for 4x) samples.</li>
|
|
<li>Apply the shaping curve.</li>
|
|
<li>Down-sample the result back to the sample-rate of the AudioContext. Thus taking the 256 (or 512) processed samples, generating 128 as
|
|
the final result.
|
|
</ol>
|
|
The exact up-sampling and down-sampling filters are not specified, and can be tuned for sound quality (low aliasing, etc.), low latency, and performance.
|
|
</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="OscillatorNode-section" class="section">
|
|
<h2 id="OscillatorNode">4.23. The OscillatorNode Interface</h2>
|
|
|
|
<p>OscillatorNode represents an audio source generating a periodic waveform. It can be set to
|
|
a few commonly used waveforms. Additionally, it can be set to an arbitrary periodic
|
|
waveform through the use of a <a href="#PeriodicWave-section"><code>PeriodicWave</code></a> object. </p>
|
|
|
|
<p>Oscillators are common foundational building blocks in audio synthesis. An OscillatorNode will start emitting sound at the time
|
|
specified by the <code>start()</code> method. </p>
|
|
|
|
<p>
|
|
Mathematically speaking, a <em>continuous-time</em> periodic waveform can have very high (or infinitely high) frequency information when considered
|
|
in the frequency domain. When this waveform is sampled as a discrete-time digital audio signal at a particular sample-rate,
|
|
then care must be taken to discard (filter out) the high-frequency information higher than the <em>Nyquist</em> frequency (half the sample-rate)
|
|
before converting the waveform to a digital form. If this is not done, then <em>aliasing</em> of higher frequencies (than the Nyquist frequency) will fold
|
|
back as mirror images into frequencies lower than the Nyquist frequency. In many cases this will cause audibly objectionable artifacts.
|
|
This is a basic and well understood principle of audio DSP.
|
|
</p>
|
|
|
|
<p>
|
|
There are several practical approaches that an implementation may take to avoid this aliasing.
|
|
But regardless of approach, the <em>idealized</em> discrete-time digital audio signal is well defined mathematically.
|
|
The trade-off for the implementation is a matter of implementation cost (in terms of CPU usage) versus fidelity to
|
|
achieving this ideal.
|
|
</p>
|
|
|
|
<p>
|
|
It is expected that an implementation will take some care in achieving this ideal, but it is reasonable to consider lower-quality,
|
|
less-costly approaches on lower-end hardware.
|
|
</p>
|
|
|
|
<p>
|
|
Both .frequency and .detune are <em>a-rate</em> parameters and are used together to determine a <em>computedFrequency</em> value:
|
|
</p>
|
|
|
|
<pre>
|
|
computedFrequency(t) = frequency(t) * pow(2, detune(t) / 1200)
|
|
</pre>
|
|
|
|
<p>
|
|
The OscillatorNode's instantaneous phase at each time is the time integral of <em>computedFrequency</em>.
|
|
</p>
|
|
|
|
<pre> numberOfInputs : 0
|
|
numberOfOutputs : 1 (mono output)
|
|
</pre>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="oscillator-node-idl">
|
|
|
|
enum <dfn>OscillatorType</dfn> {
|
|
"sine",
|
|
"square",
|
|
"sawtooth",
|
|
"triangle",
|
|
"custom"
|
|
};
|
|
|
|
interface <dfn id="dfn-OscillatorNode">OscillatorNode</dfn> : AudioNode {
|
|
|
|
attribute OscillatorType type;
|
|
|
|
readonly attribute AudioParam frequency; // in Hertz
|
|
readonly attribute AudioParam detune; // in Cents
|
|
|
|
void start(double when);
|
|
void stop(double when);
|
|
void setPeriodicWave(PeriodicWave periodicWave);
|
|
|
|
attribute EventHandler onended;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-OscillatorNode-section" class="section">
|
|
<h3 id="attributes-OscillatorNode">4.23.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-type"><code>type</code></dt>
|
|
<dd><p>The shape of the periodic waveform. It may directly be set to any of the type constant values except for "custom".
|
|
The <a href="#dfn-setPeriodicWave"><code>setPeriodicWave()</code></a> method can be used to set a custom waveform, which results in this attribute
|
|
being set to "custom". The default value is "sine". </p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
<dt id="dfn-frequency"><code>frequency</code></dt>
|
|
<dd><p>The frequency (in Hertz) of the periodic waveform. This parameter is <em>a-rate</em> </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-detune"><code>detune</code></dt>
|
|
<dd><p>A detuning value (in Cents) which will offset the <code>frequency</code> by the given amount.
|
|
This parameter is <em>a-rate</em> </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-onended"><code>onended</code></dt>
|
|
<dd><p>A property used to set the <code>EventHandler</code> (described in <cite><a
|
|
href="http://www.whatwg.org/specs/web-apps/current-work/#eventhandler">HTML</a></cite>)
|
|
for the ended event that is dispatched to <a
|
|
href="#OscillatorNode-section"><code>OscillatorNode</code></a>
|
|
node types. When the playback of the buffer for an <code>OscillatorNode</code>
|
|
is finished, an event of type <code>Event</code> (described in <cite><a
|
|
href="http://www.whatwg.org/specs/web-apps/current-work/#event">HTML</a></cite>)
|
|
will be dispatched to the event handler. </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="methodsandparams-OscillatorNode-section" class="section">
|
|
<h3 id="methodsandparams-OscillatorNode">4.23.2. Methods and Parameters</h3>
|
|
<dl>
|
|
<dt id="dfn-setPeriodicWave">The <code>setPeriodicWave</code>
|
|
method</dt>
|
|
<dd><p>Sets an arbitrary custom periodic waveform given a <a href="#PeriodicWave-section"><code>PeriodicWave</code></a>.</p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-start-AudioBufferSourceNode">The <code>start</code>
|
|
method</dt>
|
|
<dd><p>defined as in <a href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>. </p>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dt id="dfn-stop-AudioBufferSourceNode">The <code>stop</code>
|
|
method</dt>
|
|
<dd><p>defined as in <a href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>. </p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
|
|
<div id="PeriodicWave-section" class="section">
|
|
<h2 id="PeriodicWave">4.24. The PeriodicWave Interface</h2>
|
|
|
|
<p>PeriodicWave represents an arbitrary periodic waveform to be used with an <a href="#OscillatorNode-section"><code>OscillatorNode</code></a>.
|
|
Please see <a href="#dfn-createPeriodicWave">createPeriodicWave()</a> and <a href="#dfn-setPeriodicWave">setPeriodicWave()</a> and for more details. </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="wavetable-idl">
|
|
|
|
interface <dfn id="dfn-PeriodicWave">PeriodicWave</dfn> {
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="MediaStreamAudioSourceNode-section" class="section">
|
|
<h2 id="MediaStreamAudioSourceNode">4.25. The MediaStreamAudioSourceNode
|
|
Interface</h2>
|
|
|
|
<p>This interface represents an audio source from a <code>MediaStream</code>.
|
|
The first <code>AudioMediaStreamTrack</code> from the <code>MediaStream</code> will be
|
|
used as a source of audio.</p>
|
|
<pre> numberOfInputs : 0
|
|
numberOfOutputs : 1
|
|
</pre>
|
|
|
|
<p>
|
|
The number of channels of the output corresponds to the number of channels of the <code>AudioMediaStreamTrack</code>.
|
|
If there is no valid audio track, then the number of channels output will be one silent channel.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="media-stream-audio-source-node-idl">
|
|
|
|
interface <dfn id="dfn-MediaStreamAudioSourceNode">MediaStreamAudioSourceNode</dfn> : AudioNode {
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="MediaStreamAudioDestinationNode-section" class="section">
|
|
<h2 id="MediaStreamAudioDestinationNode">4.26. The MediaStreamAudioDestinationNode
|
|
Interface</h2>
|
|
|
|
<p>This interface is an audio destination representing a <code>MediaStream</code> with a single <code>AudioMediaStreamTrack</code>.
|
|
This MediaStream is created when the node is created and is accessible via the <dfn>stream</dfn> attribute.
|
|
This stream can be used in a similar way as a MediaStream obtained via getUserMedia(), and
|
|
can, for example, be sent to a remote peer using the RTCPeerConnection addStream() method.
|
|
</p>
|
|
<pre>
|
|
numberOfInputs : 1
|
|
numberOfOutputs : 0
|
|
|
|
channelCount = 2;
|
|
channelCountMode = "explicit";
|
|
channelInterpretation = "speakers";
|
|
</pre>
|
|
|
|
<p>
|
|
The number of channels of the input is by default 2 (stereo). Any connections to the input
|
|
are up-mixed/down-mixed to the number of channels of the input.
|
|
</p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">Web IDL</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code" id="media-stream-audio-destination-node-idl">
|
|
|
|
interface <dfn id="dfn-MediaStreamAudioDestinationNode">MediaStreamAudioDestinationNode</dfn> : AudioNode {
|
|
|
|
readonly attribute MediaStream stream;
|
|
|
|
};
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="attributes-MediaStreamAudioDestinationNode-section" class="section">
|
|
<h3 id="attributes-MediaStreamAudioDestinationNode">4.26.1. Attributes</h3>
|
|
<dl>
|
|
<dt id="dfn-stream"><code>stream</code></dt>
|
|
<dd><p>A MediaStream containing a single AudioMediaStreamTrack with the same number of channels
|
|
as the node itself.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div id="MixerGainStructure-section" class="section">
|
|
<h2 id="MixerGainStructure">6. Mixer Gain Structure</h2>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<h3 id="background">Background</h3>
|
|
|
|
<p>One of the most important considerations when dealing with audio processing
|
|
graphs is how to adjust the gain (volume) at various points. For example, in a
|
|
standard mixing board model, each input bus has pre-gain, post-gain, and
|
|
send-gains. Submix and master out busses also have gain control. The gain
|
|
control described here can be used to implement standard mixing boards as well
|
|
as other architectures. </p>
|
|
|
|
<div id="SummingJunction-section" class="section">
|
|
<h3 id="SummingJunction">Summing Inputs</h3>
|
|
</div>
|
|
|
|
<p>The inputs to <a href="#AudioNode-section"><code>AudioNodes</code></a> have
|
|
the ability to accept connections from multiple outputs. The input then acts as
|
|
a unity gain summing junction with each output signal being added with the
|
|
others: </p>
|
|
<img alt="unity gain summing junction"
|
|
src="images/unity-gain-summing-junction.png" />
|
|
|
|
<p>In cases where the channel layouts of the outputs do not match, a mix (usually up-mix) will occur according to the <a
|
|
href="#UpMix-section">mixing rules</a>.
|
|
</p>
|
|
|
|
<h3 id="gain-Control">Gain Control</h3>
|
|
|
|
<p>But many times, it's important to be able to control the gain for each of
|
|
the output signals. The <a
|
|
href="#GainNode-section"><code>GainNode</code></a> gives this
|
|
control: </p>
|
|
<img alt="mixer architecture new" src="images/mixer-architecture-new.png" />
|
|
|
|
<p>Using these two concepts of unity gain summing junctions and GainNodes,
|
|
it's possible to construct simple or complex mixing scenarios. </p>
|
|
|
|
<h3 id="Example-mixer-with-send-busses">Example: Mixer with Send Busses</h3>
|
|
|
|
<p>In a routing scenario involving multiple sends and submixes, explicit
|
|
control is needed over the volume or "gain" of each connection to a mixer. Such
|
|
routing topologies are very common and exist in even the simplest of electronic
|
|
gear sitting around in a basic recording studio. </p>
|
|
|
|
<p>Here's an example with two send mixers and a main mixer. Although possible,
|
|
for simplicity's sake, pre-gain control and insert effects are not illustrated:
|
|
</p>
|
|
<img alt="mixer gain structure" src="images/mixer-gain-structure.png" />
|
|
|
|
<p>This diagram is using a shorthand notation where "send 1", "send 2", and
|
|
"main bus" are actually inputs to AudioNodes, but here are represented as
|
|
summing busses, where the intersections g2_1, g3_1, etc. represent the "gain"
|
|
or volume for the given source on the given mixer. In order to expose this
|
|
gain, an <a href="#dfn-GainNode"><code>GainNode</code></a> is used:
|
|
</p>
|
|
|
|
<p>Here's how the above diagram could be constructed in JavaScript: </p>
|
|
|
|
<div class="example">
|
|
|
|
<div class="exampleHeader">
|
|
Example</div>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">ECMAScript</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
|
|
var context = 0;
|
|
var compressor = 0;
|
|
var reverb = 0;
|
|
var delay = 0;
|
|
var s1 = 0;
|
|
var s2 = 0;
|
|
|
|
var source1 = 0;
|
|
var source2 = 0;
|
|
var g1_1 = 0;
|
|
var g2_1 = 0;
|
|
var g3_1 = 0;
|
|
var g1_2 = 0;
|
|
var g2_2 = 0;
|
|
var g3_2 = 0;
|
|
|
|
<span class="comment">// Setup routing graph </span>
|
|
function setupRoutingGraph() {
|
|
context = new AudioContext();
|
|
|
|
compressor = context.createDynamicsCompressor();
|
|
|
|
<span class="comment">// Send1 effect </span>
|
|
reverb = context.createConvolver();
|
|
<span class="comment">// Convolver impulse response may be set here or later </span>
|
|
|
|
<span class="comment">// Send2 effect </span>
|
|
delay = context.createDelay();
|
|
|
|
<span class="comment">// Connect final compressor to final destination </span>
|
|
compressor.connect(context.destination);
|
|
|
|
<span class="comment">// Connect sends 1 & 2 through effects to main mixer </span>
|
|
s1 = context.createGain();
|
|
reverb.connect(s1);
|
|
s1.connect(compressor);
|
|
|
|
s2 = context.createGain();
|
|
delay.connect(s2);
|
|
s2.connect(compressor);
|
|
|
|
<span class="comment">// Create a couple of sources </span>
|
|
source1 = context.createBufferSource();
|
|
source2 = context.createBufferSource();
|
|
source1.buffer = manTalkingBuffer;
|
|
source2.buffer = footstepsBuffer;
|
|
|
|
<span class="comment">// Connect source1 </span>
|
|
g1_1 = context.createGain();
|
|
g2_1 = context.createGain();
|
|
g3_1 = context.createGain();
|
|
source1.connect(g1_1);
|
|
source1.connect(g2_1);
|
|
source1.connect(g3_1);
|
|
g1_1.connect(compressor);
|
|
g2_1.connect(reverb);
|
|
g3_1.connect(delay);
|
|
|
|
<span class="comment">// Connect source2 </span>
|
|
g1_2 = context.createGain();
|
|
g2_2 = context.createGain();
|
|
g3_2 = context.createGain();
|
|
source2.connect(g1_2);
|
|
source2.connect(g2_2);
|
|
source2.connect(g3_2);
|
|
g1_2.connect(compressor);
|
|
g2_2.connect(reverb);
|
|
g3_2.connect(delay);
|
|
|
|
<span class="comment">// We now have explicit control over all the volumes g1_1, g2_1, ..., s1, s2 </span>
|
|
g2_1.gain.value = 0.2; <span class="comment"> // For example, set source1 reverb gain </span>
|
|
|
|
<span class="comment"> // Because g2_1.gain is an "AudioParam", </span>
|
|
<span class="comment"> // an automation curve could also be attached to it. </span>
|
|
<span class="comment"> // A "mixing board" UI could be created in canvas or WebGL controlling these gains. </span>
|
|
}
|
|
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br />
|
|
|
|
|
|
<div id="DynamicLifetime-section">
|
|
<h2 id="DynamicLifetime">7. Dynamic Lifetime</h2>
|
|
|
|
<h3 id="DynamicLifetime-background">Background</h3>
|
|
|
|
<p class="norm">This section is informative. Please see <a href="#lifetime-AudioContext">AudioContext lifetime</a>
|
|
and <a href="#lifetime-AudioNode">AudioNode lifetime</a> for normative requirements
|
|
</p>
|
|
|
|
<p>In addition to allowing the creation of static routing configurations, it
|
|
should also be possible to do custom effect routing on dynamically allocated
|
|
voices which have a limited lifetime. For the purposes of this discussion,
|
|
let's call these short-lived voices "notes". Many audio applications
|
|
incorporate the ideas of notes, examples being drum machines, sequencers, and
|
|
3D games with many one-shot sounds being triggered according to game play. </p>
|
|
|
|
<p>In a traditional software synthesizer, notes are dynamically allocated and
|
|
released from a pool of available resources. The note is allocated when a MIDI
|
|
note-on message is received. It is released when the note has finished playing
|
|
either due to it having reached the end of its sample-data (if non-looping), it
|
|
having reached a sustain phase of its envelope which is zero, or due to a MIDI
|
|
note-off message putting it into the release phase of its envelope. In the MIDI
|
|
note-off case, the note is not released immediately, but only when the release
|
|
envelope phase has finished. At any given time, there can be a large number of
|
|
notes playing but the set of notes is constantly changing as new notes are
|
|
added into the routing graph, and old ones are released. </p>
|
|
|
|
<p>The audio system automatically deals with tearing-down the part of the
|
|
routing graph for individual "note" events. A "note" is represented by an
|
|
<code>AudioBufferSourceNode</code>, which can be directly connected to other
|
|
processing nodes. When the note has finished playing, the context will
|
|
automatically release the reference to the <code>AudioBufferSourceNode</code>,
|
|
which in turn will release references to any nodes it is connected to, and so
|
|
on. The nodes will automatically get disconnected from the graph and will be
|
|
deleted when they have no more references. Nodes in the graph which are
|
|
long-lived and shared between dynamic voices can be managed explicitly.
|
|
Although it sounds complicated, this all happens automatically with no extra
|
|
JavaScript handling required. </p>
|
|
|
|
<h3 id="Example-DynamicLifetime">Example</h3>
|
|
|
|
<div class="example">
|
|
|
|
<div class="exampleHeader">
|
|
Example</div>
|
|
<img alt="dynamic allocation" src="images/dynamic-allocation.png" />
|
|
|
|
<p>The low-pass filter, panner, and second gain nodes are directly connected
|
|
from the one-shot sound. So when it has finished playing the context will
|
|
automatically release them (everything within the dotted line). If there are no
|
|
longer any JavaScript references to the one-shot sound and connected nodes,
|
|
then they will be immediately removed from the graph and deleted. The streaming
|
|
source, has a global reference and will remain connected until it is explicitly
|
|
disconnected. Here's how it might look in JavaScript: </p>
|
|
|
|
<div class="block">
|
|
|
|
<div class="blockTitleDiv">
|
|
<span class="blockTitle">ECMAScript</span></div>
|
|
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
|
|
var context = 0;
|
|
var compressor = 0;
|
|
var gainNode1 = 0;
|
|
var streamingAudioSource = 0;
|
|
|
|
<span class="comment">// Initial setup of the "long-lived" part of the routing graph </span>
|
|
function setupAudioContext() {
|
|
context = new AudioContext();
|
|
|
|
compressor = context.createDynamicsCompressor();
|
|
gainNode1 = context.createGain();
|
|
|
|
// Create a streaming audio source.
|
|
var audioElement = document.getElementById('audioTagID');
|
|
streamingAudioSource = context.createMediaElementSource(audioElement);
|
|
streamingAudioSource.connect(gainNode1);
|
|
|
|
gainNode1.connect(compressor);
|
|
compressor.connect(context.destination);
|
|
}
|
|
|
|
<span class="comment">// Later in response to some user action (typically mouse or key event) </span>
|
|
<span class="comment">// a one-shot sound can be played. </span>
|
|
function playSound() {
|
|
var oneShotSound = context.createBufferSource();
|
|
oneShotSound.buffer = dogBarkingBuffer;
|
|
|
|
<span class="comment">// Create a filter, panner, and gain node. </span>
|
|
var lowpass = context.createBiquadFilter();
|
|
var panner = context.createPanner();
|
|
var gainNode2 = context.createGain();
|
|
|
|
<span class="comment">// Make connections </span>
|
|
oneShotSound.connect(lowpass);
|
|
lowpass.connect(panner);
|
|
panner.connect(gainNode2);
|
|
gainNode2.connect(compressor);
|
|
|
|
<span class="comment">// Play 0.75 seconds from now (to play immediately pass in 0)</span>
|
|
oneShotSound.start(context.currentTime + 0.75);
|
|
}
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div id="UpMix-section" class="section">
|
|
<h2 id="UpMix">9. Channel up-mixing and down-mixing</h2>
|
|
|
|
<p class="norm">This section is normative.</p>
|
|
|
|
<img src="images/unity-gain-summing-junction.png">
|
|
|
|
<p>
|
|
<a href="#MixerGainStructure-section">Mixer Gain Structure</a>
|
|
describes how an <dfn>input</dfn> to an AudioNode can be connected from one or more <dfn>outputs</dfn>
|
|
of an AudioNode. Each of these connections from an output represents a stream with
|
|
a specific non-zero number of channels. An input has <em>mixing rules</em> for combining the channels
|
|
from all of the connections to it. As a simple example, if an input is connected from a mono output and
|
|
a stereo output, then the mono connection will usually be up-mixed to stereo and summed with
|
|
the stereo connection. But, of course, it's important to define the exact <em>mixing rules</em> for
|
|
every input to every AudioNode. The default mixing rules for all of the inputs have been chosen so that
|
|
things "just work" without worrying too much about the details, especially in the very common
|
|
case of mono and stereo streams. But the rules can be changed for advanced use cases, especially
|
|
multi-channel.
|
|
</p>
|
|
|
|
<p>
|
|
To define some terms, <em>up-mixing</em> refers to the process of taking a stream with a smaller
|
|
number of channels and converting it to a stream with a larger number of channels. <em>down-mixing</em>
|
|
refers to the process of taking a stream with a larger number of channels and converting it to a stream
|
|
with a smaller number of channels.
|
|
</p>
|
|
|
|
<p>
|
|
An AudioNode input use three basic pieces of information to determine how to mix all the outputs
|
|
connected to it. As part of this process it computes an internal value <dfn>computedNumberOfChannels</dfn>
|
|
representing the actual number of channels of the input at any given time:
|
|
</p>
|
|
|
|
<p>
|
|
The AudioNode attributes involved in channel up-mixing and down-mixing rules are defined
|
|
<a href="#attributes-AudioNode-section">above</a>. The following is a more precise specification
|
|
on what each of them mean.
|
|
</p>
|
|
|
|
<ul>
|
|
<li><dfn>channelCount</dfn> is used to help compute <dfn>computedNumberOfChannels</dfn>.</li>
|
|
|
|
<li><dfn>channelCountMode</dfn> determines how <dfn>computedNumberOfChannels</dfn> will be computed.
|
|
Once this number is computed, all of the connections will be up or down-mixed to that many channels. For most nodes,
|
|
the default value is "max".
|
|
<ul>
|
|
<li>“max”: <dfn>computedNumberOfChannels</dfn> is computed as the maximum of the number of channels of all connections.
|
|
In this mode <dfn>channelCount</dfn> is ignored.</li>
|
|
<li>“clamped-max”: same as “max” up to a limit of the <dfn>channelCount</dfn></li>
|
|
<li>“explicit”: <dfn>computedNumberOfChannels</dfn> is the exact value as specified in <dfn>channelCount</dfn></li>
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li><dfn>channelInterpretation</dfn> determines how the individual channels will be treated.
|
|
For example, will they be treated as speakers having a specific layout, or will they
|
|
be treated as simple discrete channels? This value influences exactly how the up and down mixing is
|
|
performed. The default value is "speakers".
|
|
|
|
<ul>
|
|
<li>“speakers”: use <a href="#ChannelLayouts">up-down-mix equations for mono/stereo/quad/5.1</a>.
|
|
In cases where the number of channels do not match any of these basic speaker layouts, revert
|
|
to "discrete".
|
|
</li>
|
|
<li>“discrete”: up-mix by filling channels until they run out then zero out remaining channels.
|
|
down-mix by filling as many channels as possible, then dropping remaining channels</li>
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
<p>
|
|
For each input of an AudioNode, an implementation must:
|
|
</p>
|
|
|
|
<ol>
|
|
<li>Compute <dfn>computedNumberOfChannels</dfn>.</li>
|
|
<li>For each connection to the input:
|
|
<ul>
|
|
<li> up-mix or down-mix the connection to <dfn>computedNumberOfChannels</dfn> according to <dfn>channelInterpretation</dfn>.</li>
|
|
<li> Mix it together with all of the other mixed streams (from other connections). This is a straight-forward mixing together of each of the corresponding channels from each
|
|
connection.</li>
|
|
</ul>
|
|
</li>
|
|
</ol>
|
|
|
|
|
|
|
|
|
|
<div id="ChannelLayouts-section" class="section">
|
|
<h3 id="ChannelLayouts">9.1. Speaker Channel Layouts</h3>
|
|
|
|
<p class="norm">This section is normative.</p>
|
|
|
|
<p>
|
|
When <dfn>channelInterpretation</dfn> is "speakers" then the up-mixing and down-mixing
|
|
is defined for specific channel layouts.
|
|
</p>
|
|
|
|
<p>It's important to define the channel ordering (and define some
|
|
abbreviations) for these speaker layouts.</p>
|
|
|
|
<p>
|
|
For now, only considers cases for mono, stereo, quad, 5.1. Later other channel
|
|
layouts can be defined.
|
|
</p>
|
|
|
|
<h4 id ="ChannelOrdering">9.1.1. Channel ordering</h4>
|
|
|
|
<pre> Mono
|
|
0: M: mono
|
|
|
|
Stereo
|
|
0: L: left
|
|
1: R: right
|
|
</pre>
|
|
|
|
<pre> Quad
|
|
0: L: left
|
|
1: R: right
|
|
2: SL: surround left
|
|
3: SR: surround right
|
|
|
|
5.1
|
|
0: L: left
|
|
1: R: right
|
|
2: C: center
|
|
3: LFE: subwoofer
|
|
4: SL: surround left
|
|
5: SR: surround right
|
|
</pre>
|
|
</div>
|
|
|
|
<h4 id="UpMix-sub">9.1.2. Up Mixing speaker layouts</h4>
|
|
|
|
<pre>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 stereo 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;</pre>
|
|
|
|
<h4 id="down-mix">9.1.3. Down Mixing speaker layouts</h4>
|
|
|
|
<p>A down-mix will be necessary, for example, if processing 5.1 source
|
|
material, but playing back stereo. </p>
|
|
<pre>
|
|
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 = 0.7071 * (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 + 0.7071 * (input.C + input.SL)
|
|
output.R = R + 0.7071 * (input.C + input.SR)
|
|
|
|
Quad down-mix:
|
|
|
|
5.1 -> 4 : 5.1 to quad
|
|
output.L = L + 0.7071 * input.C
|
|
output.R = R + 0.7071 * input.C
|
|
output.SL = input.SL
|
|
output.SR = input.SR
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<h3 id="ChannelRules-section">9.2. Channel Rules Examples</h3>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<div class="block">
|
|
<div class="blockTitleDiv">
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code">
|
|
// 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";
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="Spatialization-section" class="section">
|
|
<h2 id="Spatialization">11. Spatialization / Panning </h2>
|
|
|
|
<h3 id="Spatialization-background">Background</h3>
|
|
|
|
<p>A common feature requirement for modern 3D games is the ability to
|
|
dynamically spatialize and move multiple audio sources in 3D space. Game audio
|
|
engines such as OpenAL, FMOD, Creative's EAX, Microsoft's XACT Audio, etc. have
|
|
this ability. </p>
|
|
|
|
<p>Using an <code>PannerNode</code>, an audio stream can be spatialized or
|
|
positioned in space relative to an <code>AudioListener</code>. An <a
|
|
href="#AudioContext-section"><code>AudioContext</code></a> will contain a
|
|
single <code>AudioListener</code>. Both panners and listeners have a position
|
|
in 3D space using a right-handed cartesian coordinate system.
|
|
The units used in the coordinate system are not defined, and do not need to be
|
|
because the effects calculated with these coordinates are independent/invariant
|
|
of any particular units such as meters or feet. <code>PannerNode</code>
|
|
objects (representing the source stream) have an <code>orientation</code>
|
|
vector representing in which direction the sound is projecting. Additionally,
|
|
they have a <code>sound cone</code> representing how directional the sound is.
|
|
For example, the sound could be omnidirectional, in which case it would be
|
|
heard anywhere regardless of its orientation, or it can be more directional and
|
|
heard only if it is facing the listener. <code>AudioListener</code> objects
|
|
(representing a person's ears) have an <code>orientation</code> and
|
|
<code>up</code> vector representing in which direction the person is facing.
|
|
Because both the source stream and the listener can be moving, they both have a
|
|
<code>velocity</code> vector representing both the speed and direction of
|
|
movement. Taken together, these two velocities can be used to generate a
|
|
doppler shift effect which changes the pitch. </p>
|
|
|
|
<p>
|
|
During rendering, the <code>PannerNode</code> calculates an <em>azimuth</em>
|
|
and <em>elevation</em>. These values are used internally by the implementation in
|
|
order to render the spatialization effect. See the <a href="#Spatialization-panning-algorithm">Panning Algorithm</a> section
|
|
for details of how these values are used.
|
|
</p>
|
|
|
|
<p>
|
|
The following algorithm must be used to calculate the <em>azimuth</em>
|
|
and <em>elevation</em>:
|
|
</p>
|
|
|
|
<div class="block">
|
|
<div class="blockTitleDiv">
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="es-code">
|
|
// Calculate the source-listener vector.
|
|
vec3 sourceListener = source.position - listener.position;
|
|
|
|
if (sourceListener.isZero()) {
|
|
// Handle degenerate case if source and listener are at the same point.
|
|
azimuth = 0;
|
|
elevation = 0;
|
|
return;
|
|
}
|
|
|
|
sourceListener.normalize();
|
|
|
|
// Align axes.
|
|
vec3 listenerFront = listener.orientation;
|
|
vec3 listenerUp = listener.up;
|
|
vec3 listenerRight = listenerFront.cross(listenerUp);
|
|
listenerRight.normalize();
|
|
|
|
vec3 listenerFrontNorm = listenerFront;
|
|
listenerFrontNorm.normalize();
|
|
|
|
vec3 up = listenerRight.cross(listenerFrontNorm);
|
|
|
|
float upProjection = sourceListener.dot(up);
|
|
|
|
vec3 projectedSource = sourceListener - upProjection * up;
|
|
projectedSource.normalize();
|
|
|
|
azimuth = 180 * acos(projectedSource.dot(listenerRight)) / PI;
|
|
|
|
// Source in front or behind the listener.
|
|
double frontBack = projectedSource.dot(listenerFrontNorm);
|
|
if (frontBack < 0)
|
|
azimuth = 360 - azimuth;
|
|
|
|
// Make azimuth relative to "front" and not "right" listener vector.
|
|
if ((azimuth >= 0) && (azimuth <= 270))
|
|
azimuth = 90 - azimuth;
|
|
else
|
|
azimuth = 450 - azimuth;
|
|
|
|
elevation = 90 - 180 * acos(sourceListener.dot(up)) / PI;
|
|
|
|
if (elevation > 90)
|
|
elevation = 180 - elevation;
|
|
else if (elevation < -90)
|
|
elevation = -180 - elevation;
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 id="Spatialization-panning-algorithm">Panning Algorithm</h3>
|
|
|
|
<p>
|
|
<em>mono->stereo</em> and <em>stereo->stereo</em> panning must be supported.
|
|
<em>mono->stereo</em> processing is used when all connections to the input are mono.
|
|
Otherwise <em>stereo->stereo</em> processing is used.</p>
|
|
|
|
<p>The following algorithms must be implemented: </p>
|
|
<ul>
|
|
<li>Equal-power (Vector-based) panning
|
|
<p>This is a simple and relatively inexpensive algorithm which provides
|
|
basic, but reasonable results. It is commonly used when panning musical sources.
|
|
</p>
|
|
The <em>elevation</em> value is ignored in this panning algorithm.
|
|
|
|
<p>
|
|
The following steps are used for processing:
|
|
</p>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
<p>
|
|
The <em>azimuth</em> value is first contained to be within the range -90 <= <em>azimuth</em> <= +90 according to:
|
|
</p>
|
|
<pre>
|
|
// Clamp azimuth to allowed range of -180 -> +180.
|
|
azimuth = max(-180, azimuth);
|
|
azimuth = min(180, azimuth);
|
|
|
|
// Now wrap to range -90 -> +90.
|
|
if (azimuth < -90)
|
|
azimuth = -180 - azimuth;
|
|
else if (azimuth > 90)
|
|
azimuth = 180 - azimuth;
|
|
</pre>
|
|
</li>
|
|
|
|
<li>
|
|
<p>
|
|
A 0 -> 1 normalized value <em>x</em> is calculated from <em>azimuth</em> for <em>mono->stereo</em> as:
|
|
</p>
|
|
<pre>
|
|
x = (azimuth + 90) / 180
|
|
</pre>
|
|
|
|
<p>
|
|
Or for <em>stereo->stereo</em> as:
|
|
</p>
|
|
<pre>
|
|
if (azimuth <= 0) { // from -90 -> 0
|
|
// inputL -> outputL and "equal-power pan" inputR as in mono case
|
|
// by transforming the "azimuth" value from -90 -> 0 degrees into the range -90 -> +90.
|
|
x = (azimuth + 90) / 90;
|
|
} else { // from 0 -> +90
|
|
// inputR -> outputR and "equal-power pan" inputL as in mono case
|
|
// by transforming the "azimuth" value from 0 -> +90 degrees into the range -90 -> +90.
|
|
x = azimuth / 90;
|
|
}
|
|
</pre>
|
|
</li>
|
|
|
|
<li>
|
|
<p>
|
|
Left and right gain values are then calculated:
|
|
</p>
|
|
<pre>
|
|
gainL = cos(0.5 * PI * x);
|
|
gainR = sin(0.5 * PI * x);
|
|
</pre>
|
|
</li>
|
|
|
|
<li>
|
|
<p>For <em>mono->stereo</em>, the output is calculated as:</p>
|
|
<pre>
|
|
outputL = input * gainL
|
|
outputR = input * gainR
|
|
</pre>
|
|
<p>Else for <em>stereo->stereo</em>, the output is calculated as:</p>
|
|
<pre>
|
|
if (azimuth <= 0) { // from -90 -> 0
|
|
outputL = inputL + inputR * gainL;
|
|
outputR = inputR * gainR;
|
|
} else { // from 0 -> +90
|
|
outputL = inputL * gainL;
|
|
outputR = inputR + inputL * gainR;
|
|
}
|
|
</pre>
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
|
|
|
|
</li>
|
|
<li><a
|
|
href="http://en.wikipedia.org/wiki/Head-related_transfer_function">HRTF</a>
|
|
panning (stereo only)
|
|
<p>This requires a set of HRTF impulse responses recorded at a variety of
|
|
azimuths and elevations. There are a small number of open/free impulse
|
|
responses available. The implementation requires a highly optimized
|
|
convolution function. It is somewhat more costly than "equal-power", but
|
|
provides a more spatialized sound. </p>
|
|
<img alt="HRTF panner" src="images/HRTF_panner.png" /></li>
|
|
</ul>
|
|
|
|
<h3 id="Spatialization-distance-effects">Distance Effects</h3>
|
|
<p>
|
|
Sounds which are closer are louder, while sounds further away are quieter.
|
|
Exactly <em>how</em> a sound's volume changes according to distance from the listener
|
|
depends on the <em>distanceModel</em> attribute.
|
|
</p>
|
|
|
|
|
|
<p>
|
|
During audio rendering, a <em>distance</em> value will be calculated based on the panner and listener positions according to:
|
|
</p>
|
|
<pre>
|
|
v = panner.position - listener.position
|
|
</pre>
|
|
<pre>
|
|
distance = sqrt(dot(v, v))
|
|
</pre>
|
|
|
|
<p>
|
|
<em>distance</em> will then be used to calculate <em>distanceGain</em> which depends
|
|
on the <em>distanceModel</em> attribute. See the <a href="#dfn-distanceModel">distanceModel</a> section for details of
|
|
how this is calculated for each distance model.
|
|
</p>
|
|
<p>As part of its processing, the <code>PannerNode</code> scales/multiplies the input audio signal by <em>distanceGain</em>
|
|
to make distant sounds quieter and nearer ones louder.
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<h3 id="Spatialization-sound-cones">Sound Cones</h3>
|
|
|
|
<p>The listener and each sound source have an orientation vector describing
|
|
which way they are facing. Each sound source's sound projection characteristics
|
|
are described by an inner and outer "cone" describing the sound intensity as a
|
|
function of the source/listener angle from the source's orientation vector.
|
|
Thus, a sound source pointing directly at the listener will be louder than if
|
|
it is pointed off-axis. Sound sources can also be omni-directional. </p>
|
|
|
|
<p>
|
|
The following algorithm must be used to calculate the gain contribution due
|
|
to the cone effect, given the source (the <code>PannerNode</code>) and the listener:
|
|
</p>
|
|
|
|
<div class="block">
|
|
<div class="blockTitleDiv">
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code">
|
|
if (source.orientation.isZero() || ((source.coneInnerAngle == 360) && (source.coneOuterAngle == 360)))
|
|
return 1; // no cone specified - unity gain
|
|
|
|
// Normalized source-listener vector
|
|
vec3 sourceToListener = listener.position - source.position;
|
|
sourceToListener.normalize();
|
|
|
|
vec3 normalizedSourceOrientation = source.orientation;
|
|
normalizedSourceOrientation.normalize();
|
|
|
|
// Angle between the source orientation vector and the source-listener vector
|
|
double dotProduct = sourceToListener.dot(normalizedSourceOrientation);
|
|
double angle = 180 * acos(dotProduct) / PI;
|
|
double absAngle = fabs(angle);
|
|
|
|
// Divide by 2 here since API is entire angle (not half-angle)
|
|
double absInnerAngle = fabs(source.coneInnerAngle) / 2;
|
|
double absOuterAngle = fabs(source.coneOuterAngle) / 2;
|
|
double 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
|
|
double x = (absAngle - absInnerAngle) / (absOuterAngle - absInnerAngle);
|
|
gain = (1 - x) + source.coneOuterGain * x;
|
|
}
|
|
|
|
return gain;
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 id="Spatialization-doppler-shift">Doppler Shift</h3>
|
|
<ul>
|
|
<li>Introduces a pitch shift which can realistically simulate moving
|
|
sources.</li>
|
|
<li>Depends on: source / listener velocity vectors, speed of sound, doppler
|
|
factor.</li>
|
|
</ul>
|
|
|
|
<p>
|
|
The following algorithm must be used to calculate the doppler shift value which is used
|
|
as an additional playback rate scalar for all AudioBufferSourceNodes connecting directly or
|
|
indirectly to the AudioPannerNode:
|
|
</p>
|
|
|
|
<div class="block">
|
|
<div class="blockTitleDiv">
|
|
<div class="blockContent">
|
|
<pre class="code"><code class="idl-code">
|
|
double dopplerShift = 1; // Initialize to default value
|
|
double dopplerFactor = listener.dopplerFactor;
|
|
|
|
if (dopplerFactor > 0) {
|
|
double speedOfSound = listener.speedOfSound;
|
|
|
|
// Don't bother if both source and listener have no velocity.
|
|
if (!source.velocity.isZero() || !listener.velocity.isZero()) {
|
|
// Calculate the source to listener vector.
|
|
vec3 sourceToListener = source.position - listener.position;
|
|
|
|
double sourceListenerMagnitude = sourceToListener.length();
|
|
|
|
double listenerProjection = sourceToListener.dot(listener.velocity) / sourceListenerMagnitude;
|
|
double sourceProjection = sourceToListener.dot(source.velocity) / sourceListenerMagnitude;
|
|
|
|
listenerProjection = -listenerProjection;
|
|
sourceProjection = -sourceProjection;
|
|
|
|
double scaledSpeedOfSound = speedOfSound / dopplerFactor;
|
|
listenerProjection = min(listenerProjection, scaledSpeedOfSound);
|
|
sourceProjection = min(sourceProjection, scaledSpeedOfSound);
|
|
|
|
dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection));
|
|
fixNANs(dopplerShift); // Avoid illegal values
|
|
|
|
// Limit the pitch shifting to 4 octaves up and 3 octaves down.
|
|
dopplerShift = min(dopplerShift, 16);
|
|
dopplerShift = max(dopplerShift, 0.125);
|
|
}
|
|
}
|
|
</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<div id="Convolution-section" class="section">
|
|
<h2 id="Convolution">12. Linear Effects using Convolution</h2>
|
|
|
|
<h3 id="Convolution-background">Background</h3>
|
|
|
|
<p><a href="http://en.wikipedia.org/wiki/Convolution">Convolution</a> is a
|
|
mathematical process which can be applied to an audio signal to achieve many
|
|
interesting high-quality linear effects. Very often, the effect is used to
|
|
simulate an acoustic space such as a concert hall, cathedral, or outdoor
|
|
amphitheater. It can also be used for complex filter effects, like a muffled
|
|
sound coming from inside a closet, sound underwater, sound coming through a
|
|
telephone, or playing through a vintage speaker cabinet. This technique is very
|
|
commonly used in major motion picture and music production and is considered to
|
|
be extremely versatile and of high quality. </p>
|
|
|
|
<p>Each unique effect is defined by an <code>impulse response</code>. An
|
|
impulse response can be represented as an audio file and <a
|
|
href="#recording-impulse-responses">can be recorded</a> from a real acoustic
|
|
space such as a cave, or can be synthetically generated through a great variety
|
|
of techniques. </p>
|
|
|
|
<h3 id="Convolution-motivation">Motivation for use as a Standard</h3>
|
|
|
|
<p>A key feature of many game audio engines (OpenAL, FMOD, Creative's EAX,
|
|
Microsoft's XACT Audio, etc.) is a reverberation effect for simulating the
|
|
sound of being in an acoustic space. But the code used to generate the effect
|
|
has generally been custom and algorithmic (generally using a hand-tweaked set
|
|
of delay lines and allpass filters which feedback into each other). In nearly
|
|
all cases, not only is the implementation custom, but the code is proprietary
|
|
and closed-source, each company adding its own "black magic" to achieve its
|
|
unique quality. Each implementation being custom with a different set of
|
|
parameters makes it impossible to achieve a uniform desired effect. And the
|
|
code being proprietary makes it impossible to adopt a single one of the
|
|
implementations as a standard. Additionally, algorithmic reverberation effects
|
|
are limited to a relatively narrow range of different effects, regardless of
|
|
how the parameters are tweaked. </p>
|
|
|
|
<p>A convolution effect solves these problems by using a very precisely defined
|
|
mathematical algorithm as the basis of its processing. An impulse response
|
|
represents an exact sound effect to be applied to an audio stream and is easily
|
|
represented by an audio file which can be referenced by URL. The range of
|
|
possible effects is enormous. </p>
|
|
|
|
<h3 id="Convolution-implementation-guide">Implementation Guide</h3>
|
|
<p>
|
|
Linear convolution can be implemented efficiently.
|
|
Here are some <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/convolution.html">notes</a>
|
|
describing how it can be practically implemented.
|
|
</p>
|
|
|
|
<h3 id="Convolution-reverb-effect">Reverb Effect (with matrixing)</h3>
|
|
|
|
<p class="norm">This section is normative.</p>
|
|
|
|
<p>
|
|
In the general case the source
|
|
has N input channels, the impulse response has K channels, and the playback
|
|
system has M output channels. Thus it's a matter of how to matrix these
|
|
channels to achieve the final result.
|
|
</p>
|
|
|
|
<p>
|
|
The subset of N, M, K below must be implemented (note that the first image in the diagram is just illustrating
|
|
the general case and is not normative, while the following images are normative).
|
|
Without loss of generality, developers desiring more complex and arbitrary matrixing can use multiple <code>ConvolverNode</code>
|
|
objects in conjunction with an <code>ChannelMergerNode</code>.
|
|
</p>
|
|
|
|
|
|
<p>Single channel convolution operates on a mono audio input, using a mono
|
|
impulse response, and generating a mono output. But to achieve a more spacious sound, 2 channel audio
|
|
inputs and 1, 2, or 4 channel impulse responses will be considered. The following diagram, illustrates the
|
|
common cases for stereo playback where N and M are 1 or 2 and K is 1, 2, or 4.
|
|
</p>
|
|
<img alt="reverb matrixing" src="images/reverb-matrixing.png" />
|
|
|
|
<h3 id="recording-impulse-responses">Recording Impulse Responses</h3>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
<img alt="impulse response" src="images/impulse-response.png" /> <br />
|
|
<br />
|
|
|
|
|
|
<p>The most <a
|
|
href="http://pcfarina.eng.unipr.it/Public/Papers/226-AES122.pdf">modern</a> and
|
|
accurate way to record the impulse response of a real acoustic space is to use
|
|
a long exponential sine sweep. The test-tone can be as long as 20 or 30
|
|
seconds, or longer. <br />
|
|
Several recordings of the test tone played through a speaker can be made with
|
|
microphones placed and oriented at various positions in the room. It's
|
|
important to document speaker placement/orientation, the types of microphones,
|
|
their settings, placement, and orientations for each recording taken. </p>
|
|
|
|
<p>Post-processing is required for each of these recordings by performing an
|
|
inverse-convolution with the test tone, yielding the impulse response of the
|
|
room with the corresponding microphone placement. These impulse responses are
|
|
then ready to be loaded into the convolution reverb engine to re-create the
|
|
sound of being in the room. </p>
|
|
|
|
<h3 id="tools">Tools</h3>
|
|
|
|
<p>Two command-line tools have been written: <br />
|
|
<code>generate_testtones</code> generates an exponential sine-sweep test-tone
|
|
and its inverse. Another tool <code>convolve</code> was written for
|
|
post-processing. With these tools, anybody with recording equipment can record
|
|
their own impulse responses. To test the tools in practice, several recordings
|
|
were made in a warehouse space with interesting acoustics. These were later
|
|
post-processed with the command-line tools. </p>
|
|
<pre>% generate_testtones -h
|
|
Usage: generate_testtone
|
|
[-o /Path/To/File/To/Create] Two files will be created: .tone and .inverse
|
|
[-rate <sample rate>] sample rate of the generated test tones
|
|
[-duration <duration>] The duration, in seconds, of the generated files
|
|
[-min_freq <min_freq>] The minimum frequency, in hertz, for the sine sweep
|
|
|
|
% convolve -h
|
|
Usage: convolve input_file impulse_response_file output_file</pre>
|
|
<br />
|
|
|
|
|
|
<h3 id="recording-setup">Recording Setup</h3>
|
|
<img alt="recording setup" src="images/recording-setup.png" /> <br />
|
|
<br />
|
|
Audio Interface: Metric Halo Mobile I/O 2882 <br />
|
|
<br />
|
|
<br />
|
|
<br />
|
|
<img alt="microphones speaker" src="images/microphones-speaker.png" /> <br />
|
|
<br />
|
|
<img alt="microphone" src="images/microphone.png" /> <img alt="speaker"
|
|
src="images/speaker.png" /> <br />
|
|
<br />
|
|
Microphones: AKG 414s, Speaker: Mackie HR824 <br />
|
|
<br />
|
|
<br />
|
|
|
|
|
|
<h3 id="warehouse">The Warehouse Space</h3>
|
|
<img alt="warehouse" src="images/warehouse.png" /> <br />
|
|
<br />
|
|
</div>
|
|
|
|
<div id="JavaScriptProcessing-section" class="section">
|
|
<h2 id="JavaScriptProcessing">13. JavaScript Synthesis and Processing</h2>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<p>The Mozilla project has conducted <a
|
|
href="https://wiki.mozilla.org/Audio_Data_API">Experiments</a> to synthesize
|
|
and process audio directly in JavaScript. This approach is interesting for a
|
|
certain class of audio processing and they have produced a number of impressive
|
|
demos. This specification includes a means of synthesizing and processing
|
|
directly using JavaScript by using a special subtype of <a
|
|
href="#AudioNode-section"><code>AudioNode</code></a> called <a
|
|
href="#ScriptProcessorNode-section"><code>ScriptProcessorNode</code></a>. </p>
|
|
|
|
<p>Here are some interesting examples where direct JavaScript processing can be
|
|
useful: </p>
|
|
|
|
<h3 id="custom-DSP-effects">Custom DSP Effects</h3>
|
|
|
|
<p>Unusual and interesting custom audio processing can be done directly in JS.
|
|
It's also a good test-bed for prototyping new algorithms. This is an extremely
|
|
rich area. </p>
|
|
|
|
<h3 id="educational-applications">Educational Applications</h3>
|
|
|
|
<p>JS processing is ideal for illustrating concepts in computer music synthesis
|
|
and processing, such as showing the de-composition of a square wave into its
|
|
harmonic components, FM synthesis techniques, etc. </p>
|
|
|
|
<h3 id="javaScript-performance">JavaScript Performance</h3>
|
|
|
|
<p>JavaScript has a variety of <a
|
|
href="#JavaScriptPerformance-section">performance issues</a> so it is not
|
|
suitable for all types of audio processing. The approach proposed in this
|
|
document includes the ability to perform computationally intensive aspects of
|
|
the audio processing (too expensive for JavaScript to compute in real-time)
|
|
such as multi-source 3D spatialization and convolution in optimized C++ code.
|
|
Both direct JavaScript processing and C++ optimized code can be combined due to
|
|
the APIs <a href="#ModularRouting-section">modular approach</a>. </p>
|
|
|
|
<div id="Performance-section" class="section">
|
|
<h2 id="Performance">15. Performance Considerations</h2>
|
|
|
|
<div id="Latency-section" class="section">
|
|
<h3 id="Latency">15.1. Latency: What it is and Why it's Important</h3>
|
|
</div>
|
|
<img alt="latency" src="images/latency.png" />
|
|
|
|
<p>For web applications, the time delay between mouse and keyboard events
|
|
(keydown, mousedown, etc.) and a sound being heard is important. </p>
|
|
|
|
<p>This time delay is called latency and is caused by several factors (input
|
|
device latency, internal buffering latency, DSP processing latency, output
|
|
device latency, distance of user's ears from speakers, etc.), and is
|
|
cummulative. The larger this latency is, the less satisfying the user's
|
|
experience is going to be. In the extreme, it can make musical production or
|
|
game-play impossible. At moderate levels it can affect timing and give the
|
|
impression of sounds lagging behind or the game being non-responsive. For
|
|
musical applications the timing problems affect rhythm. For gaming, the timing
|
|
problems affect precision of gameplay. For interactive applications, it
|
|
generally cheapens the users experience much in the same way that very low
|
|
animation frame-rates do. Depending on the application, a reasonable latency
|
|
can be from as low as 3-6 milliseconds to 25-50 milliseconds. </p>
|
|
|
|
<div id="Glitching-section" class="section">
|
|
<h3 id="audio-glitching">15.2. Audio Glitching</h3>
|
|
</div>
|
|
|
|
<p>Audio glitches are caused by an interruption of the normal continuous audio
|
|
stream, resulting in loud clicks and pops. It is considered to be a
|
|
catastrophic failure of a multi-media system and must be avoided. It can be
|
|
caused by problems with the threads responsible for delivering the audio stream
|
|
to the hardware, such as scheduling latencies caused by threads not having the
|
|
proper priority and time-constraints. It can also be caused by the audio DSP
|
|
trying to do more work than is possible in real-time given the CPU's speed. </p>
|
|
|
|
<h3 id="hardware-scalability">15.3. Hardware Scalability</h3>
|
|
|
|
<p>The system should gracefully degrade to allow audio processing under
|
|
resource constrained conditions without dropping audio frames. </p>
|
|
|
|
<p>First of all, it should be clear that regardless of the platform, the audio
|
|
processing load should never be enough to completely lock up the machine.
|
|
Second, the audio rendering needs to produce a clean, un-interrupted audio
|
|
stream without audible <a href="#Glitching-section">glitches</a>. </p>
|
|
|
|
<p>The system should be able to run on a range of hardware, from mobile phones
|
|
and tablet devices to laptop and desktop computers. But the more limited
|
|
compute resources on a phone device make it necessary to consider techniques to
|
|
scale back and reduce the complexity of the audio rendering. For example,
|
|
voice-dropping algorithms can be implemented to reduce the total number of
|
|
notes playing at any given time. </p>
|
|
|
|
<p>Here's a list of some techniques which can be used to limit CPU usage: </p>
|
|
|
|
<h4 id="CPU-monitoring">15.3.1. CPU monitoring</h4>
|
|
|
|
<p>In order to avoid audio breakup, CPU usage must remain below 100%. </p>
|
|
|
|
<p>The relative CPU usage can be dynamically measured for each AudioNode (and
|
|
chains of connected nodes) as a percentage of the rendering time quantum. In a
|
|
single-threaded implementation, overall CPU usage must remain below 100%. The
|
|
measured usage may be used internally in the implementation for dynamic
|
|
adjustments to the rendering. It may also be exposed through a
|
|
<code>cpuUsage</code> attribute of <code>AudioNode</code> for use by
|
|
JavaScript. </p>
|
|
|
|
<p>In cases where the measured CPU usage is near 100% (or whatever threshold is
|
|
considered too high), then an attempt to add additional <code>AudioNodes</code>
|
|
into the rendering graph can trigger voice-dropping. </p>
|
|
|
|
<h4 id="Voice-dropping">15.3.2. Voice Dropping</h4>
|
|
|
|
<p>Voice-dropping is a technique which limits the number of voices (notes)
|
|
playing at the same time to keep CPU usage within a reasonable range. There can
|
|
either be an upper threshold on the total number of voices allowed at any given
|
|
time, or CPU usage can be dynamically monitored and voices dropped when CPU
|
|
usage exceeds a threshold. Or a combination of these two techniques can be
|
|
applied. When CPU usage is monitored for each voice, it can be measured all the
|
|
way from a source node through any effect processing nodes which apply
|
|
uniquely to that voice. </p>
|
|
|
|
<p>When a voice is "dropped", it needs to happen in such a way that it doesn't
|
|
introduce audible clicks or pops into the rendered audio stream. One way to
|
|
achieve this is to quickly fade-out the rendered audio for that voice before
|
|
completely removing it from the rendering graph. </p>
|
|
|
|
<p>When it is determined that one or more voices must be dropped, there are
|
|
various strategies for picking which voice(s) to drop out of the total ensemble
|
|
of voices currently playing. Here are some of the factors which can be used in
|
|
combination to help with this decision: </p>
|
|
<ul>
|
|
<li>Older voices, which have been playing the longest can be dropped instead
|
|
of more recent voices. </li>
|
|
<li>Quieter voices, which are contributing less to the overall mix may be
|
|
dropped instead of louder ones. </li>
|
|
<li>Voices which are consuming relatively more CPU resources may be dropped
|
|
instead of less "expensive" voices.</li>
|
|
<li>An AudioNode can have a <code>priority</code> attribute to help determine
|
|
the relative importance of the voices.</li>
|
|
</ul>
|
|
|
|
<h4 id="Simplification-of-Effects-Processing">15.3.3. Simplification of Effects
|
|
Processing</h4>
|
|
|
|
<p>Most of the effects described in this document are relatively inexpensive
|
|
and will likely be able to run even on the slower mobile devices. However, the
|
|
<a href="#ConvolverNode-section">convolution effect</a> can be configured with
|
|
a variety of impulse responses, some of which will likely be too heavy for
|
|
mobile devices. Generally speaking, CPU usage scales with the length of the
|
|
impulse response and the number of channels it has. Thus, it is reasonable to
|
|
consider that impulse responses which exceed a certain length will not be
|
|
allowed to run. The exact limit can be determined based on the speed of the
|
|
device. Instead of outright rejecting convolution with these long responses, it
|
|
may be interesting to consider truncating the impulse responses to the maximum
|
|
allowed length and/or reducing the number of channels of the impulse response.
|
|
</p>
|
|
|
|
<p>In addition to the convolution effect. The <a
|
|
href="#PannerNode-section"><code>PannerNode</code></a> may also be
|
|
expensive if using the HRTF panning model. For slower devices, a cheaper
|
|
algorithm such as EQUALPOWER can be used to conserve compute resources. </p>
|
|
|
|
<h4 id="Sample-rate">15.3.4. Sample Rate</h4>
|
|
|
|
<p>For very slow devices, it may be worth considering running the rendering at
|
|
a lower sample-rate than normal. For example, the sample-rate can be reduced
|
|
from 44.1KHz to 22.05KHz. This decision must be made when the
|
|
<code>AudioContext</code> is created, because changing the sample-rate
|
|
on-the-fly can be difficult to implement and will result in audible glitching
|
|
when the transition is made. </p>
|
|
|
|
<h4 id="pre-flighting">15.3.5. Pre-flighting</h4>
|
|
|
|
<p>It should be possible to invoke some kind of "pre-flighting" code (through
|
|
JavaScript) to roughly determine the power of the machine. The JavaScript code
|
|
can then use this information to scale back any more intensive processing it
|
|
may normally run on a more powerful machine. Also, the underlying
|
|
implementation may be able to factor in this information in the voice-dropping
|
|
algorithm. </p>
|
|
|
|
<p><span class="ednote">TODO: add specification and more detail here </span></p>
|
|
|
|
<h4 id="Authoring-for-different-user-agents">15.3.6. Authoring for different
|
|
user agents</h4>
|
|
JavaScript code can use information about user-agent to scale back any more
|
|
intensive processing it may normally run on a more powerful machine.
|
|
|
|
<h4 id="Scalability-of-Direct-JavaScript-Synthesis">15.3.7. Scalability of
|
|
Direct JavaScript Synthesis / Processing</h4>
|
|
|
|
<p>Any audio DSP / processing code done directly in JavaScript should also be
|
|
concerned about scalability. To the extent possible, the JavaScript code itself
|
|
needs to monitor CPU usage and scale back any more ambitious processing when
|
|
run on less powerful devices. If it's an "all or nothing" type of processing,
|
|
then user-agent check or pre-flighting should be done to avoid generating an
|
|
audio stream with audio breakup. </p>
|
|
|
|
<div id="JavaScriptPerformance-section" class="section">
|
|
<h3 id="JavaScriptPerformance">15.4. JavaScript Issues with real-time
|
|
Processing and Synthesis: </h3>
|
|
</div>
|
|
While processing audio in JavaScript, it is extremely challenging to get
|
|
reliable, glitch-free audio while achieving a reasonably low-latency,
|
|
especially under heavy processor load.
|
|
<ul>
|
|
<li>JavaScript is very much slower than heavily optimized C++ code and is not
|
|
able to take advantage of SSE optimizations and multi-threading which is
|
|
critical for getting good performance on today's processors. Optimized
|
|
native code can be on the order of twenty times faster for processing FFTs
|
|
as compared with JavaScript. It is not efficient enough for heavy-duty
|
|
processing of audio such as convolution and 3D spatialization of large
|
|
numbers of audio sources. </li>
|
|
<li>setInterval() and XHR handling will steal time from the audio processing.
|
|
In a reasonably complex game, some JavaScript resources will be needed for
|
|
game physics and graphics. This creates challenges because audio rendering
|
|
is deadline driven (to avoid glitches and get low enough latency).</li>
|
|
<li>JavaScript does not run in a real-time processing thread and thus can be
|
|
pre-empted by many other threads running on the system.</li>
|
|
<li>Garbage Collection (and autorelease pools on Mac OS X) can cause
|
|
unpredictable delay on a JavaScript thread. </li>
|
|
<li>Multiple JavaScript contexts can be running on the main thread, stealing
|
|
time from the context doing the processing. </li>
|
|
<li>Other code (other than JavaScript) such as page rendering runs on the
|
|
main thread. </li>
|
|
<li>Locks can be taken and memory is allocated on the JavaScript thread. This
|
|
can cause additional thread preemption. </li>
|
|
</ul>
|
|
The problems are even more difficult with today's generation of mobile devices
|
|
which have processors with relatively poor performance and power consumption /
|
|
battery-life issues. <br />
|
|
<br />
|
|
|
|
|
|
<div id="ExampleApplications-section" class="section">
|
|
<h2 id="ExampleApplications">16. Example Applications</h2>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<p>Please see the <a
|
|
href="http://chromium.googlecode.com/svn/trunk/samples/audio/index.html">demo</a>
|
|
page for working examples. </p>
|
|
|
|
<p>Here are some of the types of applications a web audio system should be able
|
|
to support: </p>
|
|
|
|
<h3 id="basic-sound-playback">Basic Sound Playback</h3>
|
|
|
|
<p>Simple and <a href="#Latency-section"><strong>low-latency</strong></a>
|
|
playback of sound effects in response to simple user actions such as mouse
|
|
click, roll-over, key press. </p>
|
|
<br />
|
|
|
|
|
|
<h3 id="threeD-environmentse-and-games">3D Environments and Games</h3>
|
|
<img alt="quake" src="http://payload48.cargocollective.com/1/2/66805/3278334/redteam_680.jpg" />
|
|
<br />
|
|
<br />
|
|
|
|
|
|
<p>Electronic Arts has produced an impressive immersive game called
|
|
<a href="http://sophie-lu.com/Strike-Fortress-EA">Strike Fortress</a>,
|
|
taking advantage of 3D spatialization and convolution for room simulation.</p>
|
|
|
|
<img alt="beach demo" src="images/beach-demo.png" />
|
|
|
|
<p>3D environments with audio are common in games made for desktop applications
|
|
and game consoles. Imagine a 3D island environment with spatialized audio,
|
|
seagulls flying overhead, the waves crashing against the shore, the crackling
|
|
of the fire, the creaking of the bridge, and the rustling of the trees in the
|
|
wind. The sounds can be positioned naturally as one moves through the scene.
|
|
Even going underwater, low-pass filters can be tweaked for just the right
|
|
underwater sound. </p>
|
|
<br />
|
|
<br />
|
|
<img alt="box2d" src="images/box2d.png" /> <img alt="8-ball"
|
|
src="images/8-ball.png" /> <br />
|
|
<br />
|
|
|
|
|
|
<p><a href="http://box2d.org/">Box2D</a> is an interesting open-source
|
|
library for 2D game physics. It has various implementations, including one
|
|
based on Canvas 2D. A demo has been created with dynamic sound effects for each
|
|
of the object collisions, taking into account the velocities vectors and
|
|
positions to spatialize the sound events, and modulate audio effect parameters
|
|
such as filter cutoff. </p>
|
|
|
|
<p>A virtual pool game with multi-sampled sound effects has also been created.
|
|
</p>
|
|
<br />
|
|
|
|
|
|
<h3 id="musical-applications">Musical Applications</h3>
|
|
<img alt="garageband" src="images/garage-band.png" /> <img
|
|
alt="shiny drum machine" src="images/shiny-drum-machine.png" /> <img
|
|
alt="tonecraft" src="images/tonecraft.png" /> <br />
|
|
<br />
|
|
Many music composition and production applications are possible. Applications
|
|
requiring tight scheduling of audio events can be implemented and can be both
|
|
educational and entertaining. Drum machines, digital DJ applications, and even
|
|
timeline-based digital music production software with some of the features of
|
|
<a href="http://en.wikipedia.org/wiki/GarageBand">GarageBand</a> can be
|
|
written. <br />
|
|
<br />
|
|
|
|
|
|
<h3 id="music-visualizers">Music Visualizers</h3>
|
|
<img alt="music visualizer" src="images/music-visualizer.png" /> <br />
|
|
<br />
|
|
When combined with WebGL GLSL shaders, realtime analysis data can be presented
|
|
in entertaining ways. These can be as advanced as any found in iTunes. <br />
|
|
<br />
|
|
|
|
|
|
<h3 id="educational-applications_2">Educational Applications</h3>
|
|
<img alt="javascript processing" src="images/javascript-processing.png" />
|
|
|
|
<p>A variety of educational applications can be written, illustrating concepts
|
|
in music theory and computer music synthesis and processing. </p>
|
|
<br />
|
|
|
|
|
|
<h3 id="artistic-audio-exploration">Artistic Audio Exploration</h3>
|
|
|
|
<p>There are many creative possibilites for artistic sonic environments for
|
|
installation pieces. </p>
|
|
<br />
|
|
</div>
|
|
|
|
<div id="SecurityConsiderations-section" class="section">
|
|
<h2 id="SecurityConsiderations">17. Security Considerations</h2>
|
|
|
|
<p>This section is <em>informative.</em> </p>
|
|
</div>
|
|
|
|
<div id="PrivacyConsiderations-section" class="section">
|
|
<h2 id="PrivacyConsiderations">18. Privacy Considerations</h2>
|
|
|
|
<p>This section is <em>informative</em>. When giving various information on
|
|
available AudioNodes, the Web Audio API potentially exposes information on
|
|
characteristic features of the client (such as audio hardware sample-rate) to
|
|
any page that makes use of the AudioNode interface. Additionally, timing
|
|
information can be collected through the RealtimeAnalyzerNode or
|
|
ScriptProcessorNode interface. The information could subsequently be used to
|
|
create a fingerprint of the client. </p>
|
|
|
|
<p>Currently audio input is not specified in this document, but it will involve
|
|
gaining access to the client machine's audio input or microphone. This will
|
|
require asking the user for permission in an appropriate way, probably via the
|
|
<a href="http://developers.whatwg.org/">getUserMedia()
|
|
API</a>. </p>
|
|
</div>
|
|
|
|
<div id="requirements-section" class="section">
|
|
<h2 id="requirements">19. Requirements and Use Cases</h2>
|
|
|
|
<p>Please see <a href="#ExampleApplications-section">Example Applications</a>
|
|
</p>
|
|
</div>
|
|
|
|
<div id="oldnames-section" class="section">
|
|
<h2 id="OldNames">20. Old Names</h2>
|
|
|
|
<p class="norm">This section is informative.</p>
|
|
|
|
<p>Some method and attribute names have been improved during API review.
|
|
The new names are described in the main body of this specification in the
|
|
description for each node type, etc. Here's a description of the older names
|
|
to help content authors migrate to the latest spec. Note that the partial
|
|
interfaces are not normative and are only descriptive:
|
|
</p>
|
|
<blockquote>
|
|
<pre>
|
|
|
|
partial interface <dfn>AudioBufferSourceNode</dfn> {
|
|
// Same as start()
|
|
void noteOn(double when);
|
|
void noteGrainOn(double when, double grainOffset, double grainDuration);
|
|
|
|
// Same as stop()
|
|
void noteOff(double when);
|
|
};
|
|
|
|
partial interface <dfn>AudioContext</dfn> {
|
|
// Same as createGain()
|
|
GainNode createGainNode();
|
|
|
|
// Same as createDelay()
|
|
DelayNode createDelayNode(optional double maxDelayTime = 1.0);
|
|
|
|
// Same as createScriptProcessor()
|
|
ScriptProcessorNode createJavaScriptNode(optional unsigned long bufferSize = 0,
|
|
optional unsigned long numberOfInputChannels = 2,
|
|
optional unsigned long numberOfOutputChannels = 2);
|
|
};
|
|
|
|
partial interface <dfn>OscillatorNode</dfn> {
|
|
// Same as start()
|
|
void noteOn(double when);
|
|
|
|
// Same as stop()
|
|
void noteOff(double when);
|
|
};
|
|
|
|
partial interface <dfn>AudioParam</dfn> {
|
|
// Same as setTargetAtTime()
|
|
void setTargetValueAtTime(float target, double startTime, double timeConstant);
|
|
};
|
|
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>Some attributes taking constant values have changed during API review.
|
|
The old way used integer values, while the new way uses Web IDL string values.
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
// PannerNode constants for the .panningModel attribute
|
|
|
|
// Old way
|
|
const unsigned short EQUALPOWER = 0;
|
|
const unsigned short HRTF = 1;
|
|
|
|
// New way
|
|
enum <dfn>PanningModelType</dfn> {
|
|
"equalpower",
|
|
"HRTF"
|
|
};
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
// PannerNode constants for the .distanceModel attribute
|
|
|
|
// Old way
|
|
const unsigned short LINEAR_DISTANCE = 0;
|
|
const unsigned short INVERSE_DISTANCE = 1;
|
|
const unsigned short EXPONENTIAL_DISTANCE = 2;
|
|
|
|
// New way
|
|
enum <dfn>DistanceModelType</dfn> {
|
|
"linear",
|
|
"inverse",
|
|
"exponential"
|
|
};
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
|
|
<blockquote>
|
|
<pre>
|
|
// BiquadFilterNode constants for the .type attribute
|
|
|
|
// Old way
|
|
const unsigned short LOWPASS = 0;
|
|
const unsigned short HIGHPASS = 1;
|
|
const unsigned short BANDPASS = 2;
|
|
const unsigned short LOWSHELF = 3;
|
|
const unsigned short HIGHSHELF = 4;
|
|
const unsigned short PEAKING = 5;
|
|
const unsigned short NOTCH = 6;
|
|
const unsigned short ALLPASS = 7;
|
|
|
|
// New way
|
|
enum <dfn>BiquadFilterType</dfn> {
|
|
"lowpass",
|
|
"highpass",
|
|
"bandpass",
|
|
"lowshelf",
|
|
"highshelf",
|
|
"peaking",
|
|
"notch",
|
|
"allpass"
|
|
};
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
// OscillatorNode constants for the .type attribute
|
|
|
|
// Old way
|
|
const unsigned short SINE = 0;
|
|
const unsigned short SQUARE = 1;
|
|
const unsigned short SAWTOOTH = 2;
|
|
const unsigned short TRIANGLE = 3;
|
|
const unsigned short CUSTOM = 4;
|
|
|
|
// New way
|
|
enum <dfn>OscillatorType</dfn> {
|
|
"sine",
|
|
"square",
|
|
"sawtooth",
|
|
"triangle",
|
|
"custom"
|
|
};
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="appendix section" id="references">
|
|
<h2 id="L17310">A.References</h2>
|
|
|
|
<div class="section" id="normative-references">
|
|
<h3 id="Normative-references">A.1 Normative references</h3>
|
|
<dl>
|
|
<dt id="DOM">[DOM] </dt>
|
|
<dd><a href="http://dom.spec.whatwg.org/">DOM</a>,
|
|
A. van Kesteren, A. Gregor, Ms2ger. WHATWG.</dd>
|
|
<dt id="HTML">[HTML] </dt>
|
|
<dd><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">HTML</a>,
|
|
I. Hickson. WHATWG.</dd>
|
|
<dt id="RFC2119">[RFC2119] </dt>
|
|
<dd>S. Bradner. <a
|
|
href="http://www.ietf.org/rfc/rfc2119.txt"><cite><span>Key words for use
|
|
in RFCs to Indicate Requirement Levels.</span></cite></a> Internet RFC
|
|
2119. URL: <a
|
|
href="http://www.ietf.org/rfc/rfc2119.txt">http://www.ietf.org/rfc/rfc2119.txt</a>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div class="section" id="informative-references">
|
|
<h3 id="Informative-references">A.2 Informative references</h3>
|
|
|
|
<p>No informative references.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section" id="acknowledgements">
|
|
<h2 id="L17335">B.Acknowledgements</h2>
|
|
|
|
<p>Special thanks to the W3C <a href="http://www.w3.org/2011/audio/">Audio
|
|
Working Group</a>. Members of the Working Group are (at the time of writing,
|
|
and by alphabetical order): <br />
|
|
Berkovitz, Joe (public Invited expert);Cardoso, Gabriel (INRIA);Carlson, Eric
|
|
(Apple, Inc.);Gregan, Matthew (Mozilla Foundation);Jägenstedt, Philip (Opera
|
|
Software);Kalliokoski, Jussi (public Invited expert);Lowis, Chris (British
|
|
Broadcasting Corporation);MacDonald, Alistair (W3C Invited Experts);Michel,
|
|
Thierry (W3C/ERCIM);Noble, Jer (Apple, Inc.);O'Callahan, Robert(Mozilla
|
|
Foundation);Paradis, Matthew (British Broadcasting Corporation);Raman, T.V.
|
|
(Google, Inc.);Rogers, Chris (Google, Inc.);Schepers, Doug (W3C/MIT);Shires,
|
|
Glen (Google, Inc.);Smith, Michael (W3C/Keio);Thereaux, Olivier (British
|
|
Broadcasting Corporation);Wei, James (Intel Corporation);Wilson, Chris (Google,
|
|
Inc.); </p>
|
|
</div>
|
|
|
|
<div class="section" id="ChangeLog-section">
|
|
<h2 id="ChangeLog">C. Web Audio API Change Log</h2>
|
|
<pre>
|
|
user: crogers
|
|
date: Sun Dec 09 17:13:56 2012 -0800
|
|
summary: Basic description of OfflineAudioContext
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 15:59:30 2012 -0800
|
|
summary: minor correction to wording for minValue and maxValue
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 15:49:29 2012 -0800
|
|
summary: Bug 20161: Make decodeAudioData neuter its array buffer argument when it begins decoding a buffer, and bring it back to normal when the decoding is finished
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 15:35:17 2012 -0800
|
|
summary: Bug 20039: Refine description of audio decoding
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 15:23:07 2012 -0800
|
|
summary: elaborate on decoding steps for AudioContext createBuffer() and decodeAudioData()
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 14:56:19 2012 -0800
|
|
summary: Bug 19770: Note that if the last event for an AudioParam is a setCurveValue event, the computed value after that event will be equal to the latest curve value
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 14:48:04 2012 -0800
|
|
summary: Bug 19769: Note that before the first automation event, the computed AudioParam value will be AudioParam.value
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 14:40:51 2012 -0800
|
|
summary: Bug 19768: Explicitly mention that the initial value of AudioParam.value will be defaultValue
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 14:35:59 2012 -0800
|
|
summary: Bug 19767: Explicitly mention that the 2nd component of AudioParam.computedValue will be 0 if there are no AudioNodes connected to it
|
|
|
|
user: crogers
|
|
date: Tue Dec 04 14:30:08 2012 -0800
|
|
summary: Bug 19764: Note in the spec that AudioParam.minValue/maxValue are merely informational
|
|
|
|
user: crogers
|
|
date: Mon Dec 03 18:03:13 2012 -0800
|
|
summary: Convert integer constants to Web IDL enum string constants
|
|
|
|
user: crogers
|
|
date: Mon Dec 03 15:19:22 2012 -0800
|
|
summary: Bug 17411: (AudioPannerNodeUnits): AudioPannerNode units are underspecified
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Thu Nov 29 15:59:38 2012 -0500
|
|
summary: Change the Web IDL description of decodeAudioData arguments
|
|
|
|
user: crogers
|
|
date: Wed Nov 14 13:24:01 2012 -0800
|
|
summary: Bug 17393: (UseDoubles): float/double inconsistency
|
|
|
|
user: crogers
|
|
date: Wed Nov 14 13:16:57 2012 -0800
|
|
summary: Bug 17356: (AudioListenerOrientation): AudioListener.setOrientation vectors
|
|
|
|
user: crogers
|
|
date: Wed Nov 14 12:56:06 2012 -0800
|
|
summary: Bug 19957: PannerNode.coneGain is unused
|
|
|
|
user: crogers
|
|
date: Wed Nov 14 12:40:46 2012 -0800
|
|
summary: Bug 17412: AudioPannerNodeVectorNormalization): AudioPannerNode orientation normalization unspecified
|
|
|
|
user: crogers
|
|
date: Wed Nov 14 12:16:41 2012 -0800
|
|
summary: Bug 17411: (AudioPannerNodeUnits): AudioPannerNode units are underspecified
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 16:14:22 2012 -0800
|
|
summary: be more explicit about maxDelayTime units
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 16:02:50 2012 -0800
|
|
summary: Bug 19766: Clarify that reading AudioParam.computedValue will return the latest computed value for the latest audio quantum
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 15:47:25 2012 -0800
|
|
summary: Bug 19872: Should specify the defaults for PannerNode's position, ...
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 15:27:53 2012 -0800
|
|
summary: Bug 17390: (Joe Berkovitz): Loop start/stop points
|
|
|
|
user: croger
|
|
date: Tue Nov 13 14:49:20 2012 -0800
|
|
summary: Bug 19765: Note that setting AudioParam.value will be ignored when any automation events have been set on the object
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 14:39:07 2012 -0800
|
|
summary: Bug 19873: Clarify PannerNode.listener
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 13:35:21 2012 -0800
|
|
summary: Bug 19900: Clarify the default values for the AudioParam attributes of BiquadFilterNode
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 13:06:38 2012 -0800
|
|
summary: Bug 19884: Specify the default value and ranges for the DynamicsCompressorNode AudioParam members
|
|
|
|
user: crogers
|
|
date: Tue Nov 13 12:57:02 2012 -0800
|
|
summary: Bug 19910: Disallow AudioContext.createDelay(max) where max <= 0
|
|
|
|
user: crogers
|
|
date: Mon Nov 12 12:02:18 2012 -0800
|
|
summary: Add example code for more complex example
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Thu Nov 01 11:32:39 2012 -0400
|
|
summary: Specify the default value for the AudioContext.createDelay() optional argument in Web IDL
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Tue Oct 30 20:29:48 2012 -0400
|
|
summary: Mark the AudioParam members as readonly
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Tue Oct 30 20:24:52 2012 -0400
|
|
summary: Make GainNode and DelayNode valid Web IDL
|
|
|
|
user: crogers
|
|
date: Mon Oct 29 14:29:23 2012 -0700
|
|
summary: consolidate AudioBufferSourceNode start() method
|
|
|
|
user: crogers
|
|
date: Fri Oct 19 15:15:28 2012 -0700
|
|
summary: Bug 18332: Node creation method naming inconsistencies
|
|
|
|
user: crogers
|
|
date: Mon Oct 15 17:22:54 2012 -0700
|
|
summary: Bug 17407: Interface naming inconsistency
|
|
|
|
user: crogers
|
|
date: Tue Oct 09 17:21:19 2012 -0700
|
|
summary: Bug 17369: Oscillator.detune attribute not defined
|
|
|
|
user: crogers
|
|
date: Tue Oct 09 16:08:50 2012 -0700
|
|
summary: Bug 17346: HTMLMediaElement integration
|
|
|
|
user: crogers
|
|
date: Tue Oct 09 15:20:50 2012 -0700
|
|
summary: Bug 17354: AudioListener default position, orientation and velocity
|
|
|
|
user: crogers
|
|
date: Tue Oct 09 15:02:04 2012 -0700
|
|
summary: Bug 17795: Behavior of multiple connections to same node needs to be explicitly defined
|
|
|
|
user: crogers
|
|
date: Mon Oct 08 13:18:45 2012 -0700
|
|
summary: Add missing AudioContext.createWaveShaper() method
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 18:13:44 2012 -0700
|
|
summary: Bug 17399: AudioParam sampling is undefined
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 17:41:52 2012 -0700
|
|
summary: Bug 17386: Realtime Analysis empty section
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 17:38:14 2012 -0700
|
|
summary: minor tweak to down-mix section
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 17:35:05 2012 -0700
|
|
summary: Bug 17380: Channel down mixing incomplete
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 15:40:57 2012 -0700
|
|
summary: Bug 17375: MixerGainStructure should be marked as informative
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 14:29:20 2012 -0700
|
|
summary: Bug 17381: (EventScheduling): Event Scheduling ('Need more detail here')
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 13:12:46 2012 -0700
|
|
summary: Fix 18663: Need a method to get a readonly reading of the combined value when using AudioParam automation curve
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 12:48:36 2012 -0700
|
|
summary: Fix 18662: Setting audioparam value while there is an automation curve will cancel that automation curve and set value immediately
|
|
|
|
user: crogers
|
|
date: Fri Oct 05 12:26:28 2012 -0700
|
|
summary: Fix 18661: Use startTime / endTime parameter names for AudioParam automation methods
|
|
|
|
user: crogers
|
|
date: Wed Oct 03 12:26:39 2012 -0700
|
|
summary: Specify default value for .distanceModel
|
|
|
|
user: crogers
|
|
date: Tue Oct 02 12:33:36 2012 -0700
|
|
summary: Fix Issues 17338 and 17337: AudioGain interface is not needed (Part 2)
|
|
|
|
user: crogers
|
|
date: Tue Oct 02 12:28:55 2012 -0700
|
|
summary: Fix Issues 17338 and 17337: AudioGain interface is not needed
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Sep 26 18:22:36 2012 -0400
|
|
summary: Make AudioBufferSourceNode.buffer nullable
|
|
|
|
user: crogers
|
|
date: Tue Sep 25 12:56:14 2012 -0700
|
|
summary: noteOn/noteOff changed to start/stop -- added deprecation notes
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Fri Aug 24 18:27:29 2012 -0400
|
|
summary: Make the AudioContext object have a constructor
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Fri Aug 24 15:54:10 2012 -0400
|
|
summary: Denote IDL definitions as Web IDL
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Fri Aug 24 15:04:37 2012 -0400
|
|
summary: Use `long` instead of `int`, since the int type doesn't exist in Web IDL
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Fri Aug 24 15:02:43 2012 -0400
|
|
summary: Add a missing attribute keyword in AudioProcessingEvent
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Tue Aug 21 15:36:48 2012 -0400
|
|
summary: Remove the 'raises' notation from the IDLs
|
|
|
|
user: crogers
|
|
date: Thu Aug 16 16:30:55 2012 -0700
|
|
summary: Issue 17398: Add more detailed information about how AudioParam value is calculated
|
|
|
|
user: crogers
|
|
date: Thu Aug 16 15:21:38 2012 -0700
|
|
summary: another try with the style sheet
|
|
|
|
user: crogers
|
|
date: Thu Aug 16 14:53:54 2012 -0700
|
|
summary: use local style sheet to avoid https errors
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 23:05:49 2012 -0400
|
|
summary: Replace the white-space based indentation of Web IDL code with a CSS-based one
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:56:03 2012 -0400
|
|
summary: Remove more useless trailing whitespaces
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:47:21 2012 -0400
|
|
summary: Remove the optional 'in' keyword from the Web IDL method declarations
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:42:03 2012 -0400
|
|
summary: Add trailing semicolons for Web IDL interface declarations
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:37:32 2012 -0400
|
|
summary: Remove useless trailing spaces
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:35:33 2012 -0400
|
|
summary: Use the correct Web IDL notation for the AudioBufferCallback callback type
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:28:37 2012 -0400
|
|
summary: Remove the extra semicolon in the IDL file for AudioContext
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Wed Aug 15 22:24:02 2012 -0400
|
|
summary: Replace the old [Optional] IDL tag with the Web IDL optional keyword
|
|
|
|
user: Ehsan Akhgari (Mozilla)
|
|
date: Tue Aug 14 10:18:19 2012 -0400
|
|
summary: Empty changeset to test my commit access
|
|
|
|
date: Mon Aug 13 13:26:52 2012 -0700
|
|
* Integrate Thierry Michel's 3rd public working draft edits
|
|
|
|
date: Tue Jun 26 15:56:31 2012 -0700
|
|
* add MediaStreamAudioSourceNode
|
|
|
|
date: Mon Jun 18 13:26:21 2012 -0700
|
|
* minor formatting fix
|
|
|
|
date: Mon Jun 18 13:19:34 2012 -0700
|
|
* Add details for azimuth/elevation calculation
|
|
|
|
date: Fri Jun 15 17:35:27 2012 -0700
|
|
* Add equal-power-panning details
|
|
|
|
date: Thu Jun 14 17:31:16 2012 -0700
|
|
* Add equations for distance models
|
|
|
|
date: Wed Jun 13 17:40:49 2012 -0700
|
|
* Bug 17334: Add precise equations for AudioParam.setTargetValueAtTime()
|
|
|
|
date: Fri Jun 08 17:44:26 2012 -0700
|
|
* fix small typo
|
|
|
|
date: Fri Jun 08 16:54:04 2012 -0700
|
|
* Bug 17413: AudioBuffers' relationship to AudioContext
|
|
|
|
date: Fri Jun 08 16:05:45 2012 -0700
|
|
* Bug 17359: Add much more detail about ConvolverNode
|
|
|
|
date: Fri Jun 08 12:59:29 2012 -0700
|
|
* minor formatting fix
|
|
|
|
date: Fri Jun 08 12:57:11 2012 -0700
|
|
* Bug 17335: Add much more technical detail to setValueCurveAtTime()
|
|
|
|
date: Wed Jun 06 16:34:43 2012 -0700
|
|
*Add much more detail about parameter automation, including an example
|
|
|
|
date: Mon Jun 04 17:25:08 2012 -0700
|
|
* ISSUE-85: OscillatorNode folding considerations
|
|
|
|
date: Mon Jun 04 17:02:20 2012 -0700
|
|
* ISSUE-45: AudioGain scale underdefined
|
|
|
|
date: Mon Jun 04 16:40:43 2012 -0700
|
|
* ISSUE-41: AudioNode as input to AudioParam underdefined
|
|
|
|
date: Mon Jun 04 16:14:48 2012 -0700
|
|
* ISSUE-20: Relationship to currentTime
|
|
|
|
date: Mon Jun 04 15:48:49 2012 -0700
|
|
* ISSUE-94: Dynamic Lifetime
|
|
|
|
date: Mon Jun 04 13:59:31 2012 -0700
|
|
* ISSUE-42: add more detail about AudioParam sampling and block processing
|
|
|
|
date: Mon Jun 04 12:28:48 2012 -0700
|
|
* fix typo - minor edits
|
|
|
|
date: Thu May 24 18:01:20 2012 -0700
|
|
* ISSUE-69: add implementors guide for linear convolution
|
|
|
|
date: Thu May 24 17:35:45 2012 -0700
|
|
* ISSUE-49: better define AudioBuffer audio data access
|
|
|
|
date: Thu May 24 17:15:29 2012 -0700
|
|
* fix small typo
|
|
|
|
date: Thu May 24 17:13:34 2012 -0700
|
|
* ISSUE-24: define circular routing behavior
|
|
|
|
date: Thu May 24 16:35:24 2012 -0700
|
|
* ISSUE-42: specify a-rate or k-rate for each AudioParam
|
|
|
|
date: Fri May 18 17:01:36 2012 -0700
|
|
* ISSUE-53: noteOn and noteOff interaction
|
|
|
|
date: Fri May 18 16:33:29 2012 -0700
|
|
* ISSUE-34: Remove .name attribute from AudioParam
|
|
|
|
date: Fri May 18 16:27:19 2012 -0700
|
|
* ISSUE-33: Add maxNumberOfChannels attribute to AudioDestinationNode
|
|
|
|
date: Fri May 18 15:50:08 2012 -0700
|
|
* ISSUE-19: added more info about AudioBuffer - IEEE 32-bit
|
|
|
|
date: Fri May 18 15:37:27 2012 -0700
|
|
* ISSUE-29: remove reference to webkitAudioContext
|
|
|
|
date: Fri Apr 27 12:36:54 2012 -0700
|
|
* fix two small typos reported by James Wei
|
|
|
|
date: Tue Apr 24 12:27:11 2012 -0700
|
|
* small cleanup to ChannelSplitterNode and ChannelMergerNode
|
|
|
|
date: Tue Apr 17 11:35:56 2012 -0700
|
|
* small fix to createWaveTable()
|
|
|
|
date: Tue Apr 13 2012
|
|
* Cleanup AudioNode connect() and disconnect() method descriptions.
|
|
* Add AudioNode connect() to AudioParam method.
|
|
|
|
date: Tue Apr 13 2012
|
|
* Add OscillatorNode and WaveTable
|
|
* Define default values for optional arguments in createJavaScriptNode(), createChannelSplitter(), createChannelMerger()
|
|
* Define default filter type for BiquadFilterNode as LOWPASS
|
|
|
|
date: Tue Apr 11 2012
|
|
* add AudioContext .activeSourceCount attribute
|
|
* createBuffer() methods can throw exceptions
|
|
* add AudioContext method createMediaElementSource()
|
|
* update AudioContext methods createJavaScriptNode() (clean up description of parameters)
|
|
* update AudioContext method createChannelSplitter() (add numberOfOutputs parameter)
|
|
* update AudioContext method createChannelMerger() (add numberOfInputs parameter)
|
|
* update description of out-of-bounds AudioParam values (exception will not be thrown)
|
|
* remove AudioBuffer .gain attribute
|
|
* remove AudioBufferSourceNode .gain attribute
|
|
* remove AudioListener .gain attribute
|
|
* add AudioBufferSourceNode .playbackState attribute and state constants
|
|
* AnalyserNode no longer requires its output be connected to anything
|
|
* update ChannelMergerNode section describing numberOfOutputs (defaults to 6 but settable in constructor)
|
|
* update ChannelSplitterNode section describing numberOfInputs (defaults to 6 but settable in constructor)
|
|
* add note in Spatialization sections about potential to get arbitrary convolution matrixing
|
|
|
|
date: Tue Apr 10 2012
|
|
* Rebased editor's draft document based on edits from Thierry Michel (from 2nd public working draft).
|
|
|
|
date: Tue Mar 13 12:13:41 2012 -0100
|
|
* fixed all the HTML errors
|
|
* added ids to all Headings
|
|
* added alt attribute to all img
|
|
* fix broken anchors
|
|
* added a new status of this document section
|
|
* added mandatory spec headers
|
|
* generated a new table of content
|
|
* added a Reference section
|
|
* added an Acknowledgments section
|
|
* added a Web Audio API Change Log
|
|
|
|
date: Fri Mar 09 15:12:42 2012 -0800
|
|
* add optional maxDelayTime argument to createDelay()
|
|
* add more detail about playback state to AudioBufferSourceNode
|
|
* upgrade noteOn(), noteGrainOn(), noteOff() times to double from float
|
|
|
|
date: Mon Feb 06 16:52:39 2012 -0800
|
|
* Cleanup ScriptProcessorNode section
|
|
* Add distance model constants for PannerNode according to the OpenAL spec
|
|
* Add .normalize attribute to ConvolverNode
|
|
* Add getFrequencyResponse() method to BiquadFilterNode
|
|
* Tighten up the up-mix equations
|
|
|
|
date: Fri Nov 04 15:40:58 2011 -0700
|
|
summary: Add more technical detail to BiquadFilterNode description (contributed by Raymond Toy)
|
|
|
|
date: Sat Oct 15 19:08:15 2011 -0700
|
|
summary: small edits to the introduction
|
|
|
|
date: Sat Oct 15 19:00:15 2011 -0700
|
|
summary: initial commit
|
|
|
|
date: Tue Sep 13 12:49:11 2011 -0700
|
|
summary: add convolution reverb design document
|
|
|
|
date: Mon Aug 29 17:05:58 2011 -0700
|
|
summary: document the decodeAudioData() method
|
|
|
|
date: Mon Aug 22 14:36:33 2011 -0700
|
|
summary: fix broken MediaElementAudioSourceNode link
|
|
|
|
date: Mon Aug 22 14:33:57 2011 -0700
|
|
summary: refine section describing integration with HTMLMediaElement
|
|
|
|
date: Mon Aug 01 12:05:53 2011 -0700
|
|
summary: add Privacy section
|
|
|
|
date: Mon Jul 18 17:53:50 2011 -0700
|
|
summary: small update - tweak musical applications thumbnail images
|
|
|
|
date: Mon Jul 18 17:23:00 2011 -0700
|
|
summary: initial commit of Web Audio API specification</pre>
|
|
</div>
|
|
</body>
|
|
</html>
|