Я работаю над приложением, которое будет использовать Audio довольно сильно, и я нахожусь на этапах исследования, чтобы решить, использовать ли API Web Audio на устройствах, которые могут его поддерживать. Я собрал очень простой тестовый слой, который загружает файл спрайта MP3 (размером ~ 600 КБ), имеет кнопку воспроизведения и паузы, а также кнопку уничтожения, что теоретически позволяет GC восстановить память, используемую при реализации API Web Audio API, Однако после загрузки и уничтожения ~ 5 раз iOS падает из-за исключения из памяти.
Я профилировал MobileSafari в XCode Instruments, и действительно, MobileSafari постоянно ест память. Кроме того, при декодировании 600kb MP3 будет использовать память ~ 80-90 МБ.
Мой вопрос: при декодировании аудиоданных с использованием API веб-аудио, почему использование памяти настолько велико, а также почему память не восстанавливается? Насколько я понимаю, декодирование - это асинхронная операция для браузера и, по-видимому, происходит в отдельном потоке? Возможно ли, что отдельные ветки браузеров никогда не освобождают память, используемую при декодировании?
Мой код ниже, любая помощь/объяснение очень ценится:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Web Audio Playground</title>
</head>
<body>
<button id="load">
Load
</button>
<button id="play">
Play
</button>
<button id="pause">
Pause
</button>
<button id="destroy">
Destroy
</button>
<script type="application/javascript">
(function () {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var loadButton = document.getElementById('load'),
playButton = document.getElementById('play'),
pauseButton = document.getElementById('pause'),
destroyButton = document.getElementById('destroy'),
audioContext = new window.AudioContext(),
soundBuffer = null,
soundSource = null;
loadButton.addEventListener('click', function () {
var request = new XMLHttpRequest();
request.open('GET', 'live-sprite.mp3', true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function () {
audioContext.decodeAudioData(request.response, function (buffer) {
soundBuffer = buffer;
});
};
request.send();
});
playButton.addEventListener('click', function () {
soundSource = audioContext.createBufferSource();
soundSource.buffer = soundBuffer;
soundSource.connect(audioContext.destination);
soundSource.start(0);
});
pauseButton.addEventListener('click', function () {
if (soundSource) {
soundSource.stop(0);
}
});
destroyButton.addEventListener('click', function () {
if (soundSource) {
soundSource.disconnect(0);
soundSource = null;
soundBuffer = null;
alert('destroyed');
}
});
})();
</script>
</body>
</html>