javascript 使用AudioWorklet播放解码的音频缓冲区

xqk2d5yq  于 2023-02-11  发布在  Java
关注(0)|答案(2)|浏览(295)

我想用AudioWorklet播放从AudioContext.decodeAudioData()获得的AudioBuffer。我目前可以用AudioBufferSourceNode播放解码的音频缓冲区,但如您所知,此方法将在主线程上执行任务,这不是我想要的。我想做的事情是在后台播放音频,这似乎只能与工人一起使用。但是工人不能访问Web Audio Api。所以唯一的办法就是AudioWorklet
设置工作面板:

var audioContext = new AudioContext()
await audioContext.audioWorklet.addModule("./playing-audio-processor.js");
PlayingAudioProcessor= new AudioWorkletNode(
    audioContext,
    "playing-audio-processor"
);
PlayingAudioProcessor.connect(audioContext.destination);
audioContext.resume();

解码并将其发送到worklet(我确信通过的audioBuffer没有任何问题,可以轻松地使用AudioBufferSourceNode播放)

let ctx = new AudioContext();
ctx.decodeAudioData(new Uint8Array(audioData).buffer, (audioBuffer) => {
    //set `audioData` of worklet to a float32array
    myAudioWorklet.port.postMessage(audioBuffer.getChannelData(0))
})

传递的音频数据数组(audioBuffer.getChannelData(0))的长度为960,大于outputs[0][0]的长度,因此我将其拆分(实际上,这似乎不是一个好主意,我认为这就是我没有预期音频输出的原因)

class PlayingAudioProcessor extends AudioWorkletProcessor {
    audioData = []
    constructor() {
        super();
        //set listener to receive audio data
        this.port.onmessage = (data) => {
            this.audioData = data.data
        }
    }

    process(inputs, outputs, parameters) {
        //playing each 128 floats of 960 floats
        for (let i = 0; i < this.audioData.length / 128; i++) {
                for (let b = 0; b < 128; b++) {
                    if ((i * 128) + b <= this.audioData.length) {
                        outputs[0][0][b] = this.audioData[(i * 128) + b];
                    }
                }
            }
        return true;
    }

}

registerProcessor("playing-audio-processor", PlayingAudioProcessor);

现在的问题是音频结果仅仅是无意义的嘈杂声音,其取决于输入数据的响度。
我真的需要解决这个问题,请把任何可能对我有帮助的东西。谢谢。

hujrc8aj

hujrc8aj1#

看起来你在一个process()调用中写入了所有的样本,但实际上你只需要在每个process()调用中写入128个样本就可以达到预期的结果。
第一次调用需要将AudioBuffer中的示例1写入128,第二次调用需要将示例129写入256,依此类推......

au9on6nz

au9on6nz2#

AudioBufferSourceNode不会在主线程上播放音频。AudioNode对象都不会这样做(除了ScriptProcessorNode,Web音频API的所有音频处理和播放都在单独的Web音频线程中执行。只有发送控制消息的音频节点部分在主线程上运行。我的意思是,当您调用start()setValueAtTime()等方法时,会在线程之间发送一条简短的消息。
https://www.w3.org/TR/webaudio/#control-thread-and-rendering-thread

相关问题