【问题标题】:Safari webkitAudioContext.createBuffer API raises NotSupportedError exceptionSafari webkitAudioContext.createBuffer API 引发 NotSupportedError 异常
【发布时间】:2019-07-04 08:17:39
【问题描述】:

我正在使用 JavaScript Web Audio API AudioContext 来播放音频。它适用于其他主要浏览器,但 MacOS 上的 Safari 在调用 webkitAudioContext.createBuffer API 时会引发 NotSupportedError 异常。我发现这个问题,Play PCM with javascript,也表明页面末尾的 Safari 存在这样的问题。因此,我从那里调试了“Working example https://o.lgm.cl/example.html (16-bit LSB)”,并在 Safari 中遇到了同样的问题。

由于我还是 StackOverflow 的新手,我无法将 cmets 添加到该问题中,询问他们如何解决此问题。那么,有人可以帮忙吗?非常感谢!

编辑:

在 Safari 的 JavaScript 控制台中运行这两行代码将重现该问题:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); 
var myAudioBuffer = audioCtx.createBuffer(1, 48000, 16000); 

> NotSupportedError: The operation is not supported.

【问题讨论】:

    标签: javascript safari web-audio-api audiocontext webkitaudiocontext


    【解决方案1】:

    您遇到的错误几乎是意料之中的。 Web Audio 规范说,如果 sampleRate 超出支持范围,则必须抛出 NotSupportedError。但它也表示支持的最低采样率至少应为 8000 Hz。

    https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer

    Safari 的 Web 音频实现仅支持 22050 Hz 及更高频率的 AudioBuffers。因此,我建议创建一个 32000 Hz 的 AudioBuffer,因为 32 是 16 的倍数,这使得下一步更容易推理。

    填充缓冲区时,您需要通过自己插入缺失值来补偿较大的 sampleRate。我认为基本的线性插值应该可以很好地工作。但您也可以使用 OfflineAudioContext 重新采样您的 AudioBuffer。

    在完美的世界中(例如 Firefox、Chrome 或 Opera),您可以像这样重新采样 AudioBuffer:

    // Let's assume you have an AudioBuffer called audioBuffer of 1 second at 16 kHz.
    const offlineAudioContext = new OfflineAudioContext(
        { length: 32000, sampleRate: 32000 }
    );
    const audioBufferSourceNode = new AudioBufferSourceNode(
        offlineAudioContext,
        { buffer: audioBuffer }
    );
    
    audioBufferSourceNode.start(0);
    audioBufferSourceNode.connect(offlineAudioContext.destination);
    
    const resampledAudioBuffer = await offlineAudioContext.startRendering();
    

    变量 resampledAudioBuffer 现在将引用 32 kHz 的重采样 AudioBuffer。

    但是 Safari 中的 Web 音频 API 的实现已经过时且有缺陷。不仅不支持创建低于22050Hz的AudioBuffers,也无法创建低于44100Hz的OfflineAudioContext。

    但是,您的用例只需将数据重新采样两倍即可。从 16 kHz 到 32 kHz 或从 44100 Hz 到 88200 Hz 重新采样理论上是相同的。

    因此,您可以创建一个 44100 Hz 的 AudioBuffer,并用实际为 16 kHz 的数据填充它。然后将该缓冲区重新采样到 88200 Hz。然后,生成的数据将是您在 32 kHz 中的原始数据。

    这一切都非常复杂,但不幸的是,我不知道在 Safari 中还有其他方法可以做到这一点。

    为了避免使用 Safari 仍然需要的过时语法,我建议使用 polyfill。我是standardized-audio-context 的作者,这就是我推荐它的原因,但它不是唯一的。

    【讨论】:

    • 谢谢!您知道是否有任何 JavaScript API 可以即时重新采样缓冲区?我从服务中获得了一些采样率为 16000Hz 的音频,并且必须立即播放。我看到很多使用 OfflineAudioContext 转换采样率的在线答案,但我很难弄清楚如何让它适用于我的场景。非常感谢!
    • 嗨@DatowKing,我通过对重采样步骤的解释扩展了我的答案。我希望它有所帮助。
    • 哇...非常感谢@chrisguttandin 的详细回答!我会努力的,希望我能解决这个问题。顺便说一句,标准化的音频上下文太棒了!!!
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 2016-06-10
    • 2013-01-30
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多