gpt4 book ai didi

ios - 移动平台上的 Web Audio API 内存泄漏

转载 作者:技术小花猫 更新时间:2023-10-29 10:27:25 31 4
gpt4 key购买 nike

我正在开发一个将大量使用音频的应用程序,并且我正处于决定是否在可以支持它的设备上使用 Web Audio API 的研究阶段。我整理了一个非常简单的测试台,它加载了一个 MP3 Sprite 文件(大小约为 600kB),有一个播放和暂停按钮以及一个销毁按钮,理论上应该允许 GC 回收 Web 音频 API 实现使用的内存.然而,在加载和销毁 ~5 次后,iOS 由于内存不足异常而崩溃。

我在 XCode Instruments 中分析了 MobileSafari,实际上 MobileSafari 不断消耗内存。此外,600kb 的 MP3 在解码时使用了大约 80-90MB 的内存。

我的问题是 - 使用 Web Audio 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>

最佳答案

我在 SoundJS issue tracker 上发帖关于这一点,但我会在这里为任何正在寻找的人重申:

似乎在 iOS Safari 上简单地断开和取消引用 AudioBufferSourceNode 对象是不够的;您需要手动清除对其缓冲区的引用,否则缓冲区本身会泄漏。 (这意味着 AudioBufferSourceNode obj 本身会泄漏,但我们并未将其视为项目中的实际限制。)

不幸的是,要这样做,需要创建一个 1-sample 长的暂存缓冲区,因为分配给 null 会导致异常。该语句也必须被 try-catch 包装,因为 Chrome/FF 会在任何时候重新分配 .buffer 时抛出。

有效的解决方案是:

var ctx = new AudioContext(),
scratchBuffer = ctx.createBuffer(1, 1, 22050);

class WebAudioAdapter extends AudioAdapter {
close() {
if( this.__src ) {
this.__src.onended = null;
this.__src.disconnect(0);
try { this.__src.buffer = scratchBuffer; } catch(e) {}
this.__src = null;
}
}
}

希望这对你们也有帮助!

关于ios - 移动平台上的 Web Audio API 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24119684/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com