我一直在努力解决在 iOS 6 下使用 HTML5 中的 webkitAudioContext 难以捉摸的音频失真错误。它可能发生在其他情况下,但我可以获得 100% 重现的唯一方法是在设备重启后首次访问我的页面。似乎如果您在访问此页面之前访问任何支持音频的页面,则不会出现此问题。
失真只发生在由 webkitAudioContext.decodeAudioData() 生成然后通过 webkitAudioContext.createBufferSource() 播放的音频上。webkitAudioContext.createMediaElementSource() 的音频播放不会失真。
我错过了一些初始化步骤吗?以下是我作为错误报告提交给 Apple 的完整代码和 HTML(但未收到回复):
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var buffer = null;
var context = null;
var voice = null;
function load_music(file) {
context = new webkitAudioContext();
voice = context.createBufferSource();
var request = new XMLHttpRequest();
request.onload = function() {
context.decodeAudioData(request.response, function(result) {
buffer = result;
document.getElementById("start").value = "Start";
});
};
var base = window.location.pathname;
base = base.substring(0, base.lastIndexOf("/") + 1);
request.open("GET", base + file, true);
request.responseType = "arraybuffer";
request.send(null);
}
function start_music() {
if (!buffer) {
alert("Not ready yet");
return;
}
voice.buffer = buffer;
voice.connect(context.destination);
voice.noteOn(0);
document.getElementById("compare").style.display = "block";
}
</script>
</head>
<body onload="load_music('music.mp3')">
<p>This is a simple demo page to reproduce a <strong>webkitAudio</strong>
problem occurring in Safari on iOS 6.1.4. This is a stripped down demo
of a phenomenon discovered in our HTML5 game under development,
using different assets.</p>
<p><u>Steps to reproduce:</u></p>
<ol>
<li>Power cycle <strong>iPhone 5 with iOS 6.1.4</strong>.</li>
<li>Launch Safari immediately, and visit this page.</li>
<li>Wait for "Loading..." below to change to
"Start".</li>
<li>Tap "Start".</li>
</ol>
<p><u>Issue:</u></p>
<p>Audio will be excessively distorted and play at wrong pitch. If
another audio-enabled web site is visited before this one, or this
site is reloaded, the audio will fix. The distortion only happens on
the first visit after cold boot. <strong>To reproduce the bug, it is
critical to power cycle before testing.</strong></p>
<p>This bug has not been observed on any other iOS version (e.g. does
not occur on iPad Mini or iPod 5 using iOS 6.1.3).</p>
<input id="start" type="button" value="Loading..." onmousedown="start_music()" />
<span id="compare" style="display:none;"><p><a href="music.mp3">Direct link</a> to audio file, for
comparison.</p></span>
</body>
</html>
注意:正文表明这仅在 iOS 6.1.4 上发生,但我的意思是在这种情况下,仅在电源循环时才会出现问题。我在 6.1.3 以下的 iPad Mini 上也遇到过这个问题,但在电源循环时没有。
编辑:我尝试过的一些事情......推迟创建缓冲区源没有任何区别。使用不同的转码器生成它播放的 .mp3 文件没有区别。播放一次性静音作为第一个声音没有任何区别,因为每个 decodeAudioData 声音都会继续失真,直到页面重新加载。如果 createMediaElementSource 和 createBufferSource 源混合在同一页面中,则只有 createBufferSource 音频(使用 decodeAudioData)会失真。当我在失败情况和非失败情况下检查 request.response.byteLength 时,它们是相同的,表明 XMLHttpRequest 没有返回不正确的数据,尽管我认为数据损坏会损坏 MP3 标头并呈现文件无论如何都无法播放。
故障条件和非故障条件之间存在一个可观察到的差异。只读值 context.sampleRate 在故障状态下为 48000,在非故障状态下为 44100。(但故障状态听起来比非故障状态低。)我唯一发生的事情是一个黑客,如果在应该报告 44100 的浏览器上检测到 48000,我会通过 JavaScript 刷新页面,但这是严重的 userAgent筛选而不是未来的证明,这让我很紧张。