我想用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);
现在的问题是音频结果仅仅是无意义的嘈杂声音,其取决于输入数据的响度。
我真的需要解决这个问题,请把任何可能对我有帮助的东西。谢谢。
2条答案
按热度按时间hujrc8aj1#
看起来你在一个
process()
调用中写入了所有的样本,但实际上你只需要在每个process()
调用中写入128个样本就可以达到预期的结果。第一次调用需要将
AudioBuffer
中的示例1写入128,第二次调用需要将示例129写入256,依此类推......au9on6nz2#
AudioBufferSourceNode
不会在主线程上播放音频。AudioNode
对象都不会这样做(除了ScriptProcessorNode
,Web音频API的所有音频处理和播放都在单独的Web音频线程中执行。只有发送控制消息的音频节点部分在主线程上运行。我的意思是,当您调用start()
或setValueAtTime()
等方法时,会在线程之间发送一条简短的消息。https://www.w3.org/TR/webaudio/#control-thread-and-rendering-thread