为什么 AudioBufferSourceNode 会在播放时堆叠?

Why AudioBufferSourceNodes stacks on play?

基本上,我正在尝试从来自 WS 套接字的字节构建和播放音频数据。

详细:


我有一个用 Django-Channels 编写的简单 WS 服务器,在连接时 returns 我将音频文件拆分为 blob 对象,每个块有 6144 字节。接下来,我想解码这个 blob 数据并将其转换为声音:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
var play = document.querySelector('#play');
var audioQueue = []

const chatSocket = new WebSocket(
    'ws://'
    + window.location.host
    + 'audio-stream-test'
    + '/'
);

chatSocket.onmessage = function(e) {
    e.data.arrayBuffer().then(buffer => {
        audioCtx.decodeAudioData(buffer, (x)=>{
            source = audioCtx.createBufferSource();
            source.buffer = x;
            source.connect(audioCtx.destination);
            source.loop = false;
            audioQueue.push(source)
        })
    })
}

WS发送完所有数据后,在服务器端关闭。最后一件事是播放来自 audioQueue 数组的排队缓冲区:

play.onclick = function() {
    var playOffset;
    for (let [bufferCount, buffer] of audioQueue.entries()) {
        if (bufferCount == 0) {
            playOffset = 0
        } else {
            playOffset = audioQueue[bufferCount-1].buffer.duration
        }
        buffer.start(when=playOffset)
    }
}

想澄清这一行:playOffset = audioQueue[bufferCount-1].buffer.duration。我想,我写对了,因为我想在旧的(已经播放过的)缓冲区的末尾播放新的缓冲区。

对我来说,作为 服务器端 开发人员,它似乎应该可以正常工作。


但是,主要问题是:audioQueue 数组中的所有缓冲区都一次 播放。 IDK我做错了什么。希望得到您的帮助:)


The song

您需要启动与 AudioContextcurrentTime 相关的每个 AudioBufferSourceNode

play.onclick = function() {
    audioQueue.reduce((startTime, audioBufferSourceNode) => {
        audioBufferSourceNode.start(startTime);

        return startTime + audioBufferSourceNode.buffer.duration;
    }, audioContext.currentTime);
};

上面的代码将遍历 audioQueue 中的所有节点。它通过根据 AudioContext.

currentTime 累积先前节点的持续时间来计算每个 AudioBufferSourceNodestartTime