我正在分析一个音频文件,以便使用channelData来驱动我的网络应用程序的另一部分(基本上是根据音频文件绘制图形)。播放的回调函数如下所示:
successCallback(mediaStream) {
var audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
source = audioContext.createMediaStreamSource(mediaStream);
node = audioContext.createScriptProcessor(256, 1, 1);
node.onaudioprocess = function(data) {
var monoChannel = data.inputBuffer.getChannelData(0);
..
};
不知怎的,我想如果我用同一个文件运行上面的代码,它会一直产生相同的结果。但事实并非如此。例如,同一个音频文件有时会触发 onaudioprocess 函数 70 次,有时 72 次,始终产生不同的数据。 有没有办法在浏览器中获得此类一致的数据?
编辑:我正在从同一页面上的录音功能获取音频。录制完成后,生成的文件将设置为 <audio>
的 src元素。 recorder
是我的MediaRecorder
.
recorder.addEventListener("dataavailable", function(e) {
fileurl = URL.createObjectURL(e.data);
document.querySelector("#localaudio").src = fileurl;
..
最佳答案
回答您原来的问题:getChannelData
是确定性的,即它将从同一 channel 的同一 AudioBuffer 中产生相同的 Float32Array(除非您碰巧传输了支持) ArrayBuffer 到另一个线程,在这种情况下,它将返回一个空的 Float32Array,并从那时起具有分离的后备缓冲区)。
我认为您在这里遇到的问题是线程问题(我的猜测是,在您开始处理其中的音频流之前,MediaStream 已经在播放),但是如果不调试完整的应用程序,很难准确判断(有这里至少有 3 个线程在工作:MediaStream 的音频处理线程、您正在使用的 AudioContext 的音频处理线程以及运行代码的主线程。
Is there a way to get consistent data of that sort in the browser?
是的。
您可以直接获取录音结果 (e.data
),将其读取为 ArrayBuffer,然后将其解码为一个 AudioBuffer,类似:
recorder.addEventListener("dataavailable", function (e) {
let reader = new FileReader();
reader.onload = function (e) {
audioContext.decodeAudioData(e.target.result).then(function (audioBuffer) {
var monoChannel = audioBuffer.getChannelData(0);
// monoChannel contains the entire first channel of your recording as a Float32Array
// ...
});
};
reader.readAsArrayBuffer(e.data);
}
注意:使用异步函数和 Promise,此代码会变得更加简单,但它应该给出如何读取整个完整记录的一般概念。
另请注意:由于跨线程数据复制(尤其是涉及 JS 主线程)固有的性能问题,ScriptProcessorNode 已被弃用。首选替代方案是更先进的 AudioWorklet ,但这是一种在 Web 上执行操作的相当新的方式,需要对工作集有深入的了解。
关于javascript - AudioContext/getChannelData 是确定性的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64479064/