开发者问题收集

audiocontext Samplerate 在读取 8 次后返回 null

2017-08-06
1787

我创建了一个函数来产生鼓声,但是在调用 4 次之后它停止工作并出现错误:

TypeError: null is not an object (evaluating 'audioCtx.sampleRate') Showing in the console.

这个函数有什么问题? 我的代码是:

drum = function(){
    var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    var frameCount = audioCtx.sampleRate/20
    var myArrayBuffer = audioCtx.createBuffer(1, frameCount, audioCtx.sampleRate);
    var nowBuffering = myArrayBuffer.getChannelData(0);
    for (var i = 0; i < frameCount; i++) {
        nowBuffering[i] =Math.sin(i**(1/1.8)/4)
    }

    var source = audioCtx.createBufferSource();
    source.buffer = myArrayBuffer; source.connect(audioCtx.destination);
    source.start();
}
2个回答

您的 audioCtx 分配应移到 drum() 之外,因为它每次都会被调用,最终会引发异常,因为您无法在文档中创建超过 6 个音频上下文。

dpren
2017-08-06

事实上,重复使用 AudioContext 的一个实例并不是一个好的解决方案,因为它可能会造成内存泄漏。

当浏览器空闲时(当您切换到另一个 iOS 应用程序时),Safari 会终止这种长期存在的 AudioContext 实例。一旦再次打开 Safari,AudioContext 实例将不再可用。

正确的解决方案是每次都创建新的上下文,并在不再需要时将其关闭。

采用这种方法,浏览器不会对 AudioContext 施加任何限制。

const drum = () => {
  const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
  // your stuff here…

  // Return cleanup function and call it when needed
  return () => {
    // Cleanup to prevent memory leaks
    audioCtx
      .close()
      .catch(() => {
        console.log('Closing AudioContext failed')
      })
  }
}
poky
2020-06-17