OfflineAudioContext中的内存泄漏

时间:2017-11-20 13:31:14

标签: javascript web-audio

内存泄漏OfflineAudioContext

在chrome中启动任务管理器。运行10次后createBuffer内存使用1.5GB。标签超出RAM限制后,它将中断。

如何避免内存泄漏?

jsfiddle上的示例。



var audioCtx = new(window.AudioContext || window.webkitAudioContext)();

// define variables

var play = document.querySelector('.play');
var stop = document.querySelector('.stop');
var progress = document.querySelector('#progress');
var buffer = document.querySelector('.buffer');
var myBuffer = null;

var rendering = false;
// use XHR to load an audio track, and
// decodeAudioData to decode it and stick it in a buffer.
// Then we put the buffer into the source

function getData() {
  request = new XMLHttpRequest();

  request.open('GET', 'https://s3-ap-northeast-1.amazonaws.com/storage.cowrite.decodeapps.io/Materials/Media/Audio/5a0aca5f35965-20171114-105007.mp3', true);

  request.responseType = 'arraybuffer';

  request.onload = function() {
    progress.innerText = 'loaded';
    var audioData = request.response;
    audioCtx.decodeAudioData(audioData, function(buffer) {
      myBuffer = buffer;

      createBuffer();
    }).catch(function(err) {
      console.log('Rendering failed: ' + err);
      // Note: The promise should reject when startRendering is called a second time on an OfflineAudioContext
    });
  }
  request.send();
}
buffer.setAttribute('disabled', 'disabled');
progress.innerText = 'loading...';
var cntRenfered = 0;

function createBuffer() {
  var offlineCtx = new OfflineAudioContext(2, myBuffer.length, myBuffer.sampleRate);
  var source = offlineCtx.createBufferSource();
  source.buffer = myBuffer;
  source.connect(offlineCtx.destination);
  source.start();
  //source.loop = true;
  offlineCtx.oncomplete = function(e) {
    progress.innerText = 'completed';
    buffer.removeAttribute('disabled');
    source.disconnect(offlineCtx.destination);
    cntRenfered++;
    buffer.innerText = 'reCreateBuffer ' + cntRenfered;
  }
  offlineCtx.startRendering();
}

buffer.onclick = function() {
  progress.innerText = 'rendering...';
  buffer.setAttribute('disabled', 'disabled');
  createBuffer();
}

getData();

<div id="progress">
  loading
</div>


<button class="buffer">
  reCreateBuffer
</button>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我找到了解决方法。

jsfiddle上的示例。

&#13;
&#13;
var audioCtx = new(window.AudioContext || window.webkitAudioContext)();

// define variables

var play = document.querySelector('.play');
var stop = document.querySelector('.stop');
var progress = document.querySelector('#progress');
var buffer = document.querySelector('.buffer');
var myBuffer = null;

var rendering = false;
// use XHR to load an audio track, and
// decodeAudioData to decode it and stick it in a buffer.
// Then we put the buffer into the source

function getData() {
  request = new XMLHttpRequest();

  request.open('GET', 'https://s3-ap-northeast-1.amazonaws.com/storage.cowrite.decodeapps.io/Materials/Media/Audio/5a0aca5f35965-20171114-105007.mp3', true);

  request.responseType = 'arraybuffer';

  request.onload = function() {
    progress.innerText = 'loaded';
    var audioData = request.response;
    audioCtx.decodeAudioData(audioData, function(b) {
      myBuffer = b;
      buffer.removeAttribute('disabled');
    }).catch(function(err) {
      console.log('Rendering failed: ' + err);
      // Note: The promise should reject when startRendering is called a second time on an OfflineAudioContext
    });
  }
  request.send();
}
buffer.setAttribute('disabled', 'disabled');
progress.innerText = 'loading...';
var cntRenfered = 0;

function createBuffer() {
  var offlineCtx = getIFrameOfflineContext(2, myBuffer.length, myBuffer.sampleRate);
  var source = offlineCtx.createBufferSource();
  source.buffer = myBuffer;
  source.connect(offlineCtx.destination);
  source.start();
  //source.loop = true;
  offlineCtx.oncomplete = function(e) {
    console.log('Rendering completed successfully');
    progress.innerText = 'completed';
    buffer.removeAttribute('disabled');
    source.disconnect(offlineCtx.destination);
    cntRenfered++;
    buffer.innerText = 'reCreateBuffer ' + cntRenfered;
    setTimeout(function() {
      IFrameReload();
    });
  }
  offlineCtx.startRendering();
}

buffer.onclick = function() {
  progress.innerText = 'rendering...';
  buffer.setAttribute('disabled', 'disabled');
  createBuffer();
}

getData();
var iFrame;

function createIframe() {
  iFrame = document.createElement('iframe');
  iFrame.style.display = 'none';
  iFrame.onload = () => {
    const script = document.createElement('script');
    script.innerHTML =
      `
        function reload() {
          location.reload();
        }

        function createOfflineContext(NUMBER_OF_CHANNEL, duration, sampleRate) {
          return new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(NUMBER_OF_CHANNEL,duration,sampleRate);
        }
      `;
    iFrame.contentDocument.body.appendChild(script);
  };
  document.body.appendChild(iFrame);
}

function getIFrameOfflineContext(NUMBER_OF_CHANNEL, duration, sampleRate) {
  return iFrame.contentWindow.createOfflineContext(NUMBER_OF_CHANNEL, duration, sampleRate);
}

function IFrameReload() {
  iFrame.contentWindow.reload();
}


createIframe();
&#13;
<div id="progress">
  loading
</div>

<button class="buffer">
  reCreateBuffer
</button>
&#13;
&#13;
&#13;