Search code examples
javascriptaudioweb-audio-api

Webaudio, play sound twice


I am experimenting with WebAudio and I am loading in a sound with the following javascript code.

function playAudio(){
    var audio = document.getElementById('music');
    var audioContext = new webkitAudioContext();
    var analyser = audioContext.createAnalyser();
    var source = audioContext.createMediaElementSource(audio);
    source.connect(analyser);
    analyser.connect(audioContext.destination);
    audio.play();
}

I also want to analyse the sound can visualise it with canvas, hence the analyser. It works fine the first time but if I run this function twice I get an error.

> playAudio(); // works fine, i can hear a sound
> playAudio(); // error 
InvalidStateError: Failed to execute 'createMediaElementSource' on 'AudioContext': invalid HTMLMediaElement.

What is causing this error? I know that the error is caused by this line of code:

var source = audioContext.createMediaElementSource(audio);

I am creating a new audio context, so I would assume that I can re-use the same audio element in my html.


Solution

  • By creating the audio element dynamically (as shown in this fiddle, http://jsfiddle.net/ikerr/WcXHK/), I was able to play the song repeatedly.

    function createAudioElement(urls) {
        var audioElement = document.createElement("audio");
    
        audioElement.autoplay = true;
        audioElement.loop = false;
    
        for (var i = 0; i < urls.length; ++i) {
            var typeStr = "audio/" + urls[i].split(".").pop();
    
            if (audioElement.canPlayType === undefined ||
                audioElement.canPlayType(typeStr).replace(/no/, "")) {
                var sourceElement = document.createElement("source");
                sourceElement.type = typeStr;
                sourceElement.src = urls[i];
                audioElement.appendChild(sourceElement);
                console.log("Using audio asset: " + urls[i]);
            }
        }
    
        return audioElement;
    }
    
    var audioContext = new webkitAudioContext();
    
    function playAudio(){
    
        var audio = createAudioElement(['http://www.soundjay.com/button/button-1.mp3' ]);      
    
        if(audio){
            var source = audioContext.createMediaElementSource(audio);
            var analyser = audioContext.createAnalyser();
            source.connect(analyser);
            analyser.connect(audioContext.destination);
            audio.play();
        }
    }
    
    playAudio(); // works fine, i can hear a sound
    playAudio();
    //setTimeout(playAudio,2000);
    

    Demo : http://jsfiddle.net/raathigesh/fueg3mk7/10/