undefined
undefined

Reputation: 4135

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).");
}

Upvotes: 16

Views: 10113

Answers (2)

Patrick Log&#233;
Patrick Log&#233;

Reputation: 51

Old thread (and very useful! thanks!) , but maybe worth mentioning that in the example above instead of

function update() {
    window.requestAnimationFrame(update);
    info.innerHTML = sound.getCurrentTime().toFixed(1) + '/' + sound.getDuration().toFixed(1);
    }
update(); 

it may be more precise and less resource intensive to use a createScriptProcessor like explained in this post

const audioBuffer = await audioContext.decodeAudioData(response.data);
const chan = audioBuffer.numberOfChannels;
const  scriptNode = audioContext.createScriptProcessor(4096, chan, chan);
scriptNode.connect(audioContext.destination);
scriptNode.onaudioprocess = (e) => {

  // ---> audio loop <----

};

[Update]

Note: As of the August 29 2014 Web Audio API spec publication, this feature has been marked as deprecated, and was replaced by AudioWorklet (see AudioWorkletNode). https://developers.google.com/web/updates/2017/12/audio-worklet

Upvotes: 0

imcg
imcg

Reputation: 2649

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
    };
}

Upvotes: 24

Related Questions