我如何获得AudioBufferSourceNode的当前时间?

问题描述 投票:7回答:2

[当使用音频元素(<audio>)或上下文(AudioContext)时,可以检查它们的currentTime属性以确切了解缓冲区的播放时间。

直到我在单个AudioBufferSourceNode中创建了多个源(或AudioContext)之前,所有这些都是不错的选择。

源可以在不同的时间播放,因此我需要知道它们对应的currentTime,以说明:

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

一些需要您解决的基本代码:

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).");
}
javascript web-audio-api
2个回答
7
投票

我通常要做的是为音频源节点创建一个包装,以跟踪播放状态。我试图最小化下面的代码以显示基础。

核心思想是跟踪声音的开始时间和声音“暂停”的时间,并使用这些值来获取当前时间并从暂停的位置恢复播放。

我放了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
    };
}

0
投票

旧线程(非常有用!谢谢!),但也许值得一提的是example above而不是

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

使用createScriptProcessor可能更精确,资源占用更少就像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 <----

};

[更新]

注:自2014年8月29日Web Audio API规范发布以来,此功能已被标记为已弃用,并已由AudioWorklet取代(请参阅AudioWorkletNode)。 https://developers.google.com/web/updates/2017/12/audio-worklet

© www.soinside.com 2019 - 2024. All rights reserved.