使用网络音频连续播放小声音缓冲区序列 Api

Playing sequence of small sound buffers continuosly with Web Audio Api

我喜欢从任意数学函数 f(x) 生成声音。现在我为此使用 AudioBufferSource,它的 onended 处理程序为下一个缓冲区创建和播放另一个源,依此类推。问题是缓冲区之间的噼啪声。这是我的示例代码:

function init() {
        var contextClass = (AudioContext || webkitAudioContext
                || mozAudioContext || oAudioContext || msAudioContext);
        if (contextClass) {
            // Web Audio API is available.
            context = new contextClass();

            return true;
        } else {
            return false;
        }
    }

// arbitary mathematical function (not just sin)
function mySoundFunction(i, j, k) {
    return j*Math.sin(i/10);
}
function createBufferSource(j) {
        var length = 8092;

        var audioBuffer = context.createBuffer(1, length, 44500);
        var data = audioBuffer.getChannelData(0);
        for (var i = 0; i < length; i++) {
            data[i] = mySoundFunction(i, j, 5);
        }

        var source = context.createBufferSource();
        source.buffer = audioBuffer;
        source.connect(context.destination);
        source.onended = function ended(obj) {
           createBufferSource(j);
    }

        source.start(0);

    }


if (init()) {
    console.log("init was successful");
}
createBufferSource(0.1);

由于用户可以在播放声音时更改数学函数,因此缓冲区大小必须保持较小,并且由于延迟,预缓冲不是一个真正的选择。 ScriptProcessor 可能是替代品,但我猜它的性能太昂贵了。由于功能可以是任何东西,OscillatorNode 也不好。 那么问题来了,如何消除两个缓冲区之间的噼啪声呢? 谢谢

我尝试使用 ScriptProcessor,但它仍然存在问题

function feed() {
    var a = j === 0 ? 5000: 6000;
    for (var i = 0; i < 2048; i++) {
        audata[i] = Math.sin(a*k);
        k++;
    }

    j = 1-j ;
}


function createProcessor() {

    processor = context.createScriptProcessor(2048, 0, 1);

    processor.onaudioprocess = function(e) {;    
        var L = e.outputBuffer.getChannelData(0);

         L.set(audata);
         feed();
           }

        processor.connect(context.destination);

    running=true;
}


if (init()) {
    console.log("init was successful");
}

audata = new Float32Array(2048);
k=0;
j=1;
feed();
createProcessor();

我错过了什么?谢谢

您不想在这里使用onended。这会留下一个间隙,因为它是在音频线程中音频播放完毕后触发的,所以会有很大的间隙。

您今天可能想使用 ScriptProcessor,将来可能想使用 AudioWorkers。