我有一台服务器通过网络套接字发送原始音频块。我们的想法是检索这些内容并以尽可能流畅的播放方式播放它们。
这是最重要的一段代码:
ws.onmessage = function (event) {
var view = new Int16Array(event.data);
var viewf = new Float32Array(view.length);
audioBuffer = audioCtx.createBuffer(1, viewf.length, 22050);
audioBuffer.getChannelData(0).set(viewf);
source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioCtx.destination);
source.start(0);
};
这工作得很好,但播放中存在一些裂缝:网络延迟并不总是恒定的,因此最新的数据块不会恰好在播放的前一个数据块结束时到达,所以我最终可以得到以下任一结果:两个缓冲区一起播放很短的时间或根本不播放。
I tried:
- 挂钩
source.onended
在播放下一个时,但它不是无缝的:每个块的末尾都有一个裂缝,并且每个接缝总体上都在累积,因此与流相比,播放变得越来越晚。
- 将新数据附加到当前播放的缓冲区,但这似乎是被禁止的:缓冲区具有固定大小。
是否有适当的解决方案来修复该播放?唯一的要求是播放来自网络套接字的未压缩音频。
编辑:解决方案:鉴于我知道我的缓冲区长度,我可以这样安排播放:
if(nextStartTime == 0) nextStartTime = audioCtx.currentTime + (audioBuffer.length / audioBuffer.sampleRate)/2;
source.start(nextStartTime);
nextStartTime += audioBuffer.length / audioBuffer.sampleRate;
第一次,我将播放的开始时间安排为半个缓冲区之后,以允许最大的意外延迟。然后,我将下一个缓冲区开始时间存储在缓冲区末尾的最末尾。
你可能应该从https://www.html5rocks.com/en/tutorials/audio/scheduling/ https://www.html5rocks.com/en/tutorials/audio/scheduling/这很好地解释了如何在 WebAudio 中安排事情。
对于您的用例,您还应该利用这样一个事实:您知道 PCM 样本的采样率并且知道您读取了多少样本。这决定了播放完缓冲区需要多长时间。用它来确定何时安排下一个缓冲区。
(但请注意,如果 PCM 采样率与audioCtx.sampleRate
,数据将被重新采样,这可能会扰乱您的时间。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)