Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get an AudioBufferSourceNode's current time?

When working with audio elements (<audio>) or contexts(AudioContext), you can check their currentTime property to know exactly the play time of your buffer.

All of this is fine an dandy until I created multiple sources (or AudioBufferSourceNode) in a single AudioContext.

The sources could be played at different times, therefore I would need to know their corresponding currentTime's, to illustrate:

an audio context connected to it's sources with unknown play times.

Some base code for you to work off:

buffer1 = [0,1,0]; //not real buffers
buffer2 = [1,0,1];

ctx = new AudioContext();

source1 = ctx.createBufferSourceNode();
source1.buffer = buffer1;
source1.connect(ctx.destination);
source1.start(0);

source2 = ctx.createBufferSourceNode();
source2.buffer = buffer2;
source2.connect(ctx.destination);
setTimeout(1000/*some time later*/){
    source2.start(0);
}

setTimeout(1500/*some more time later*/){
    getCurrentTime();
}

function getCurrentTime(){
    /* magic */
    /* more magic */
    console.log("the sources currentTime values are obviously 1500 (source1) and 500 (source2).");
}
like image 717
undefined Avatar asked Jul 27 '15 02:07

undefined


1 Answers

What I usually do is create a wrapper for the audio source node that keeps track of the playback state. I've tried to minimise the code below to show the basics.

The core idea is to keep track of the time the sound is started and the time the sound is 'paused' and use those values to get the current time and to resume playback from the paused position.

I put a working example on codepen

function createSound(buffer, context) {
    var sourceNode = null,
        startedAt = 0,
        pausedAt = 0,
        playing = false;

    var play = function() {
        var offset = pausedAt;

        sourceNode = context.createBufferSource();
        sourceNode.connect(context.destination);
        sourceNode.buffer = buffer;
        sourceNode.start(0, offset);

        startedAt = context.currentTime - offset;
        pausedAt = 0;
        playing = true;
    };

    var pause = function() {
        var elapsed = context.currentTime - startedAt;
        stop();
        pausedAt = elapsed;
    };

    var stop = function() {
        if (sourceNode) {          
            sourceNode.disconnect();
            sourceNode.stop(0);
            sourceNode = null;
        }
        pausedAt = 0;
        startedAt = 0;
        playing = false;
    };

    var getPlaying = function() {
        return playing;
    };

    var getCurrentTime = function() {
        if(pausedAt) {
            return pausedAt;
        }
        if(startedAt) {
            return context.currentTime - startedAt;
        }
        return 0;
    };

    var getDuration = function() {
      return buffer.duration;
    };

    return {
        getCurrentTime: getCurrentTime,
        getDuration: getDuration,
        getPlaying: getPlaying,
        play: play,
        pause: pause,
        stop: stop
    };
}
like image 108
imcg Avatar answered Oct 02 '22 08:10

imcg