我正在使用 Web Audio Api 开发一个应用程序。我发现 Safari 处理音频的方式存在内存泄漏,并且没有正确地对音频上下文进行垃圾分类。出于这个原因,我希望加载一个新页面。让那个页面创建Audio Context,完成操作然后关闭窗口,这样内存就被释放了。
我已经做了以下事情来实现这一点。
ref = window.open('record.html', '_self');
这将根据https://wiki.apache.org/cordova/InAppBrowser在 Cordova WebView 中打开 record.html 页面
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: Can't find variable: LocalFileSystem
似乎在 reload index.html 中丢失了一些但并非所有指向 Cordova API 的链接。例如,我仍然可以使用 Media Api,但不能使用 File Api。我知道这是一种解决内存泄漏的方法(打开和关闭窗口),但我找不到任何其他方法。我真的需要一些帮助。因此,非常欢迎任何指针。