Wilf

HTML5 Audio API

Changing the audio tone with JavaScript

To load sounds I'm using this simple script.
Note: the g namespace and AUDIOFORMAT variables are common in my games. I also use jQuery in a few places throughout my game code.


var g = {
    audioContext: null,
    sound: { source : null, gainNode: null, soundname: "beat", buffer: null, volume: 0 }
};
var AUDIOFORMAT = "";

$(document).ready(function(){
    setAudio();
    loadSound(g.sound);
});

function setAudio()
{
    try
    {
        var a = document.createElement('audio');
        if (a)
        {
            g.audioContext = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)();
            if (!g.audioContext) g.audioContext = AudioContext();
            if (g.audioContext)
                AUDIOFORMAT = "mp3";
        } else {
            console.log("No HTML5 audio.");
        }
    }
    catch (e)
    {
        console.log("setAudio: " + e.message);
    }
};

function loadSound(o)
{
    try
    {
        var request = new XMLHttpRequest();
        var url = "sfx/" + o.soundname + "." + AUDIOFORMAT;
        request.open('GET', url, true);
        request.responseType = 'arraybuffer';

        // Decode asynchronously
        request.onload = function ()
        {
            try
            {
                g.audioContext.decodeAudioData(request.response, 
                    function(buffer) 
                    { 
                        o.buffer = buffer;
                        o.volume = 1;
                    }, 
                    function()
                    {
                        console.log("Decode error: " + url + ", " + arguments[0]);
                    }
                );
            }
            catch (e)
            {
                console.log("loadSound(onLoad): " + e.message);
            }
        }
        request.send();
    }
    catch (e)
    {
        console.log("LoadSound: " + e.message);
    }
};

function sfx(o)
{
    try
    {
            var source      = g.audioContext.createBufferSource();
            var gainNode    = g.audioContext.createGain();

            source.buffer   = o.buffer;
            source.loop     = false;
            source.connect(gainNode);
            gainNode.connect(g.audioContext.destination);
            gainNode.gain.value = 1;
            source.start(0);

    }
    catch (e)
    {
        console.log("sfx: " + e.message);
    }
};

I like the idea of creating a game that is set in the dark and the player must locate the exit while being pursued by an unknown threat. If I could use the HTML5 Audio API to programmatically effect the pitch of a sound I might be able to emulate a motion sensor...

playbackRate.value

By adjusting the playbackRate value I can effect a shift in the pitch by slowing down or speed up the playback of the audio. e.g. source.playbackRate.value = 1 is the default.
A value of 0.5 would reduce the pitch and a value of 2 would increase it.
I've amended the sfx() function to allow for a second parameter (r) to be passed in that changes the playbackRate:


function sfx(o,r)
{
    try
    {
            var source      = g.audioContext.createBufferSource();
            var gainNode    = g.audioContext.createGain();

            source.buffer   = o.buffer;
            source.loop     = false;
            source.connect(gainNode);
            gainNode.connect(g.audioContext.destination);
            gainNode.gain.value = 1;
            source.playbackRate.value = r;
            source.start(0);

    }
    catch (e)
    {
        console.log("sfx: " + e.message);
    }
};


I am using a beat sound effect from one of my games as a test: