This code accompanies a tutorial on the Web Audio API.
var context;
try {
// still needed for Safari
window.AudioContext = window.AudioContext || window.webkitAudioContext;
// create an AudioContext
context = new AudioContext();
} catch(e) {
// API not supported
throw new Error('Web Audio API not supported.');
}
var sound;
/**
* Example 1: Load a sound
* @param {String} src Url of the sound to be loaded.
*/
function loadSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
// request.response is encoded... so decode it now
context.decodeAudioData(request.response, function(buffer) {
sound = buffer;
}, function(err) {
throw new Error(err);
});
}
request.send();
}
// loadSound('audio/BaseUnderAttack.mp3');
var format = '.' + (new Audio().canPlayType('audio/ogg') !== '' ? 'ogg' : 'mp3');
// loadSound('audio/baseUnderAttack' + format);
/**
* Example 2: Play a sound
* @param {Object} buffer AudioBuffer object - a loaded sound.
*/
function playSound(buffer) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
}
// playSound(sound);
var sounds = {
laser : {
src : 'audio/laser'
},
coin : {
src : 'audio/coin'
},
explosion : {
src : 'audio/explosion'
}
};
/**
* Example 3a: Modify loadSound fn to accept changed params
* @param {Object} obj Object containing url of sound to be loaded.
*/
function loadSoundObj(obj) {
var request = new XMLHttpRequest();
request.open('GET', obj.src + format, true);
request.responseType = 'arraybuffer';
request.onload = function() {
// request.response is encoded... so decode it now
context.decodeAudioData(request.response, function(buffer) {
obj.buffer = buffer;
}, function(err) {
throw new Error(err);
});
}
request.send();
}
// loadSoundObj({ src : 'audio/baseUnderAttack' });
/**
* Example 3b: Function to loop through and load all sounds
* @param {Object} obj List of sounds to loop through.
*/
function loadSounds(obj) {
var len = obj.length, i;
// iterate over sounds obj
for (i in obj) {
if (obj.hasOwnProperty(i)) {
// load sound
loadSoundObj(obj[i]);
}
}
}
// loadSounds(sounds);
sounds = {
laser : {
src : 'audio/laser',
volume : 2
},
coin : {
src : 'audio/coin',
volume : 1.5
},
explosion : {
src : 'audio/explosion',
volume : 0.5
}
};
/**
* Example 4: Modify the playSoundObj function to accept volume property
* @param {Object} obj Object containing url of sound to be loaded.
*/
function playSoundObj(obj) {
var source = context.createBufferSource();
source.buffer = obj.buffer;
// create a gain node
obj.gainNode = context.createGain();
// connect the source to the gain node
source.connect(obj.gainNode);
// set the gain (volume)
obj.gainNode.gain.value = obj.volume;
// connect gain node to destination
obj.gainNode.connect(context.destination);
// play sound
source.start(0);
}
// loadSounds(sounds);
var nyan = {
src : 'audio/nyan',
volume : 1
};
loadSoundObj(nyan);
/**
* Example 5: Muting a sound
* @param {object} obj Object containing a loaded sound buffer.
*/
function muteSoundObj(obj) {
obj.gainNode.gain.value = 0;
}
// muteSoundObj(nyan);
sounds = {
laser : {
src : 'audio/laser',
volume : 1,
loop: true
},
coin : {
src : 'audio/coin',
volume : 1,
loop: true
},
explosion : {
src : 'audio/explosion',
volume : 1,
loop: true
}
};
/**
* Example 6: Modify the playSoundObj function again to accept a loop property
* @param {Object} obj Object containing url of sound to be loaded.
*/
function playSoundObj(obj) {
var source = context.createBufferSource();
source.buffer = obj.buffer;
// loop the audio?
source.loop = obj.loop;
// create a gain node
obj.gainNode = context.createGain();
// connect the source to the gain node
source.connect(obj.gainNode);
// set the gain (volume)
obj.gainNode.gain.value = obj.volume;
// connect gain node to destination
obj.gainNode.connect(context.destination);
// play sound
source.start(0);
}
// loadSounds(sounds);
var crossfade = {
battle : {
src : 'audio/the-last-encounter',
volume : 1,
loop : true
},
eclipse : {
src : 'audio/red-eclipse',
volume : 0,
loop : true
}
};
/**
* Example 7: Crossfading between two sounds
* @param {Object} a Sound object to fade out.
* @param {Object} b Sound object to fade in.
*/
function crossFadeSounds(a, b) {
var currentTime = context.currentTime,
fadeTime = 3; // 3 seconds fade time
// fade out
a.gainNode.gain.linearRampToValueAtTime(1, currentTime);
a.gainNode.gain.linearRampToValueAtTime(0, currentTime + fadeTime);
// fade in
b.gainNode.gain.linearRampToValueAtTime(0, currentTime);
b.gainNode.gain.linearRampToValueAtTime(1, currentTime + fadeTime);
}
// crossFadeSounds(crossfade.battle, crossfade.eclipse);
Many thanks to OpenGameArt.Org and it's contributors.