0

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

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

编辑:

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

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

> NotSupportedError: The operation is not supported.
4

1 回答 1

1

The error you are getting is almost expected. The Web Audio spec says a NotSupportedError must be thrown if the sampleRate is outside of the supported range. But it also says the lowest supported sampleRate should be at least 8000 Hz.

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

Safari's Web Audio implementation does only support AudioBuffers with 22050 Hz and more. I would therefore suggest to create an AudioBuffer at 32000 Hz because 32 is a multiple of 16 which makes the next step a bit easier to reason about.

When filling the buffer you need to compensate for the larger sampleRate by interpolating the missing values yourself. I think a basic linear interpolation should work reasonably well. But you can also use an OfflineAudioContext to resample your AudioBuffer.

In a perfect world (e.g. Firefox, Chrome or Opera) you can resample an AudioBuffer like this:

// 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();

The variable resampledAudioBuffer will now reference a resampled AudioBuffer at 32 kHz.

But the implementation of the Web Audio API in Safari is outdated and buggy. Not only does it not support to create AudioBuffers with less than 22050 Hz, it also can't create an OfflineAudioContext with less than 44100 Hz.

However, all you need for your use case is to resample your data by a factor of two. It's theoretically the same to resample from 16 kHz to 32 kHz or from 44100 Hz to 88200 Hz.

You can therefore create an AudioBuffer at 44100 Hz and fill it with your data which is actually at 16 kHz. Then you resample that buffer to 88200 Hz. The resulting data will then be your original data in 32 kHz.

That's all very complicated but unfortunately I don't know of any other way to do it in Safari.

To avoid the need to use the outdated syntax which is still necessary for Safari, I would recommend to use a polyfill. I'm the author of standardized-audio-context which is why I would recommend that, but it is not the only one.

于 2019-02-13T10:27:46.357 回答