Everybody dance now
with Web Audio API
Jaume Sanchez @thespite
http://www.clicktorelease.com
Audio on the browser
Flash and other plugins
HTML5 Audio Element
Hybrid approach
http://www.schillmania.com/projects/soundmanager2/
Web Audio API
(and a bit of Mozilla Audio Data API)
The Web Audio API allows developers to manipulate
and play audio assets on a Web page or application.
"Web Audio API is to HTML5 <audio>
what canvas is to <img>"
Mozilla Audio Data API tried with a
JavaScript-centric approach.
How to use
var context = new AudioContext();
Usually you'll want one AudioContext (AC) per page.
Once there's an AC, you can start
adding nodes and connecting them.
Nodes
(nodes everywhere)
Modular routing.
Basic audio operations are performed with audio nodes.
Audio nodes are linked together to form audio routing graphs.
Audio nodes are linked via their inputs and outputs.
This modular design allows the flexibility to create complex
audio functions with dynamic effects.
Routing graphs
Sources
We need some element to input data into the system.
(something has to make noise)
createBufferSource
createMediaElementSource
createMediaStreamSource
createOscillator
var context = new AudioContext();
var source = context.createBufferSource();
source.buffer = buffer;
source.start();
Destinations
Any other node, or the mixer.
The graph usually ends with context.destination
var context = new AudioContext();
var source = context.createBufferSource();
source.buffer = buffer;
source.connect( context.destination );
source.start();
but the combinations are endless
oscillator.connect( gain );
gain.connect( convolver );
convolver.connect( notchFilter );
notchFilter.connect( context.destination );
Buffer Source
Creates an AudioBufferSourceNode interface.
context.createBufferSource();
buffer attribute: IEEE 32 bit float ranging -1 to 1
playbackRate attribute: AudioParam
loop/loopStart/loopEnd attributes
start() and stop() methods
onended event
Buffer Source demo
var context = new AudioContext();
var request = new XMLHttpRequest();
request.open( 'GET', 'sound.mp3', true );
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData( request.response, function( buffer ) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect( context.destination );
source.start();
}, function() {
console.log( 'error' );
} );
};
request.send();
Load Sound Demo
Load Sound reusing AudioBuffer Demo
Analyser
Creates an AnalyserNode to provide real-time
frequency and time-domain analysis information
context.createAnalyser()
fftSize attribute: size of FFT - power of two
getFloatFrequencyData: copies frequency-domain data
getByteFrequencyData: copies frequency-domain data
getByteTimeDomainData: copies time-domain data
Load Sound and show FFT Demo
getUserMedia Demo
AudioParam
float value (and defaultValue)
Allows scheduling of value changes
setValueAtTime
linearRampToValueAtTime
exponentialRampToValueAtTime
setTargetAtTime
setValueCurveAtTime
cancelScheduledValues
Gain
Create a GainNode to control the volume.
context.createGain();
gain attribute: AudioParam
var context = new AudioContext();
var source = context.createBufferSource();
source.buffer = buffer;
var volume = context.createGain();
volume.gain.value = .1;
source.connect( volume );
volume.connect( context.destination );
source.start();
Delay
Creates a DelayNode to add delay.
context.createDelay( maxDelayTime );
delayTime attribute AudioParam
var context = new AudioContext();
var source = context.createBufferSource();
source.buffer = buffer;
var delay = context.createDelay( 100 );
delay.delayTime.value = 3;
source.connect( delay );
delay.connect( context.destination );
source.start();
Delay + Gain = Reverb
Creating a loop between a gain and a delay node
creates a reverb effect on the stream.
var context = new AudioContext();
var a = document.createElement( 'audio' );
a.src = 'track.wav';
a.loop = false;
var audioSource = context.createMediaElementSource( a );
var delayNode = context.createDelay( 1 );
var gainNode = context.createGain();
gainNode.gain.value = .5;
delayNode.delayTime.value = .1;
audioSource.connect( delayNode );
delayNode.connect( gainNode );
gainNode.connect( delayNode );
delayNode.connect( context.destination );
a.play();
Gain + Delay Demo
Oscillator Source
Creates an OscillatorNode.
context.createOscillator();
type attribute:
SINE, SQUARE, SAWTOOTH,
TRIANGLE, CUSTOM
setWaveTable() method for CUSTOM type
frequency attribute AudioParam
var context = new AudioContext();
var oscillator = context.createOscillator();
oscillator.frequency.value = 440;
oscillator.type = 4;
oscillator.connect(context.destination);
oscillator.start();
Filters!
Creates a BiquadFilterNode that provides several
default stock second order filters.
context.createBiquadFilter();
type attribute
LOWPASS, HIGHPASS, BANDPASS,
LOWSHELF, HIGHSHELF, PEAKING,
NOTCH, ALLPASS
frequency attribute AudioParam
Q attribute AudioParam
gain attribute AudioParam
Oscillator and Biquad Filter Demo
Convolution (euh!)
Creates a ConvolverNode for linear convolution effects.
context.createConvolver();
buffer attribute: AudioBuffer with impulse response.
Convolution Demo
Panner
Creates a PannerNode for spatialisation.
context.createPanner();
Defines:
- position, velocity, direction of sample
- distance model
- directional sound cone
Tied to AudioListener (context.listener) for
spatial sound and doppler shift effect.
Other
createChannelMerger
createChannelSplitter
createDynamicsCompressor
createPeriodicWave
createWaveShaper
createJavaScriptNode
All together
There's a main ambient sound loop with gain.
The camera has a sound loop with gain.
Each cube has:
- a basic sound loop with gain
- a proximity sound loop with gain
- an activation sound with gain
- a deactivation sound with gain
- a sound analyser
- a panner
All sounds are merged in a convolver, a filter, a gain
and a dynamics compressor
Awesome.
Now what?
WebRTC getUserMedia
Web MIDI API
Procedural sound generation
Real-time effects
References
The spec
Getting Started with Web Audio API | HTML5 Rocks
Mixing Positional Audio and WebGL | HTML5 Rocks
Thanks!
Questions?
Let's talk!
Jaume Sanchez @thespite
http://www.clicktorelease.com
https://github.com/spite
Barcelona Future JS 2014
By Jaume Sánchez
Barcelona Future JS 2014
- 4,782