Я боролся с неуловимой ошибкой искажения звука, используя webkitAudioContext в HTML5 под iOS 6. Это может произойти и при других обстоятельствах, но единственный способ получить 100% воспроизведение - это при первом посещении моей страницы после включения и выключения устройства. Похоже, что если вы посетите любую аудио-совместимую страницу до посещения этой, проблема не возникнет.
Искажение происходит только со звуком, сгенерированным webkitAudioContext.decodeAudioData() и затем воспроизведенным через webkitAudioContext.createBufferSource(). Воспроизведение звука webkitAudioContext.createMediaElementSource() не искажается.
Я пропустил какой-то шаг инициализации? Вот весь код и HTML, которые я отправил в Apple в качестве отчета об ошибке (но не получил ответа):
<!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, но я хочу сказать, что в этой ситуации проблема возникает только при включении питания. Я тоже столкнулся с этой проблемой на iPad Mini версии 6.1.3, но не при включении питания.
Редактировать: несколько вещей, которые я пробовал... Отсрочка создания источника буфера не имеет значения. Использование разных транскодеров для создания воспроизводимого файла .mp3 не имеет значения. Воспроизведение одноразовой тишины в качестве первого звука не имеет значения, поскольку искажение продолжается для каждого звука decodeAudioData, пока страница не перезагрузится. Если источники createMediaElementSource и createBufferSource смешаны на одной и той же странице, только звук createBufferSource (с использованием decodeAudioData) будет искажаться. Когда я проверяю request.response.byteLength в случае сбоя и в случае без сбоя, они одинаковы, предполагая, что XMLHttpRequest не возвращает неверные данные, хотя я думаю, что повреждение данных повредит заголовок MP3 и отобразит файл все равно не воспроизводится.
Существует одно заметное различие между состоянием отказа и состоянием отсутствия отказа. Значение context.sampleRate, доступное только для чтения, будет равно 48000 в состоянии сбоя и 44100 в состоянии без сбоя. (Тем не менее, состояние сбоя звучит более низко, чем состояние без сбоя.) Единственное, что мне приходит в голову, — это хак, когда я обновляю страницу с помощью JavaScript, если в браузере обнаруживается 48000, который должен сообщать 44100, но это серьезный userAgent. скрининг и не очень перспективное, что заставляет меня нервничать.