我正在使用Web Audio Api开发应用程序。我发现Safari处理音频的方式存在内存泄漏,并且没有正确地对音频上下文进行垃圾处理。出于这个原因,我希望加载一个新页面。让该页面创建音频上下文,完成操作然后关闭窗口,以便释放内存。
我已经做了以下工作来实现这一目标。
ref = window.open('record.html', '_self');
这将根据https://wiki.apache.org/cordova/InAppBrowser
1 window.open('local-url.html'); //加载 Cordova WebView
2 window.open('local-url.html','_ self');
//在Cordova WebView中加载
record.html页面加载一个javascript文件,该文件运行我希望运行的操作。这是recordLoad.js文件,它对本机操作进行了一些调用(本机API只有在Cordova Webview中加载时才可用,你可以看到我需要访问文件系统,所以这是我能看到的唯一方法做到这一点。
window.onload = createAudioContext;
ref = null;
function createAudioContext(){
console.log('createAudioContext');
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
window.URL = window.URL || window.webkitURL;
audioContext = new AudioContext;
getDirectory();
}
function getDirectory(){
console.log('getDirectory');
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getFileSystem, fail);
}
function getFileSystem(directory){
console.log('getFileSystem');
var audioPath = localStorage.getItem('audioPath');
directory.root.getFile(audioPath, null, getVocalFile, fail);
}
function getVocalFile(fileEntry){
console.log('getVocalFile');
fileEntry.file(readVocalsToBuffer, fail);
}
function readVocalsToBuffer(file){
console.log('readVocalsToBuffer');
var reader = new FileReader();
reader.onloadend = function(evt){
var x = audioContext.decodeAudioData(evt.target._result, function(buffer){
if(!buffer){
console.log('error decoding file to Audio Buffer');
return;
}
window.voiceBuffer = buffer;
buffer = null;
loadBuffers();
});
}
reader.readAsArrayBuffer(file);
}
//web
function loadBuffers(){
console.log('loadBuffers');
var srcSong = localStorage.getItem('srcSong');
try{
var bufferLoader = new BufferLoader(
audioContext,
[
"."+srcSong
],
createOffLineContext
);
bufferLoader.load()
}
catch(e){
console.log(e.message);
}
}
//
function createOffLineContext(bufferList){
console.log('createOfflineContext');
offline = new webkitOfflineAudioContext(2, window.voiceBuffer.length, 44100);
var vocalSource = offline.createBufferSource();
vocalSource.buffer = window.voiceBuffer;
vocalSource.connect(offline.destination);
var backing = offline.createBufferSource();
backing.buffer = bufferList[0];
backing.connect(offline.destination);
vocalSource.start(0);
backing.start(0);
offline.oncomplete = function(ev){
bufferList = null;
console.log('audioContext');
console.log(audioContext);
audioContext = null;
console.log(audioContext);
vocalSource.stop(0);
backing.stop(0);
vocalSource.disconnect(0);
backing.disconnect(0);
vocalSource = null;
backing = null;
window.voiceBuffer = null;
window.renderedFile = ev.renderedBuffer;
var bufferR = ev.renderedBuffer.getChannelData(0);
var bufferL = ev.renderedBuffer.getChannelData(1);
var interleaved = interleave(bufferL, bufferR);
var dataview = encodeWAV(interleaved);
window.audioBlob = new Blob([dataview], {type: 'Wav'});
saveFile();
}
offline.startRendering();
}
//这个文件非常长,但是一旦完成混合两个音频缓冲区,它就会将一个新文件写入文件系统。当该操作完成后,我使用
function gotFileWriter(writer){
console.log('gotFileWriter');
writer.onwriteend = function(evt){
console.log('onwriteEnd');
console.log(window.audioBlob);
delete window.audioBlob;
console.log(window.audioBlob);
// checkDirectory();
var ref = window.open('index.html', '_self');
// ref.addEventListener('exit', windowClose);
}
writer.write(audioBlob);
}
我返回原始的index.html文件。这解决了内存问题。但是,一旦我尝试第二次运行相同的操作。即加载到record.html文件中,并运行recordLoad.js文件我收到错误ReferenceError:找不到变量:LocalFileSystem
似乎在reload index.html中有一些,但并非所有到Cordova API的链接都丢失了。我仍然可以使用Media Api而不是File Api。我明白这是一个hacky方式,(打开和关闭窗口)解决内存泄漏,但我找不到任何其他方式来做到这一点。我真的需要一些帮助。所以任何指针都非常受欢迎。