Не работает ScriptProcessorNode с OfflineContext

296
02 ноября 2017, 08:28

Не работает ScriptProcessorNode с OfflineContext.

Работает в Chrome, Mozilla Firefox.

Не работает в Edge 25, Safari 10.

Ошибка в том, что событие onaudioprocess вызывается лишь один раз, когда используется совместно с OfflineContextis.

Пример на jsfiddle без BufferSource.

Пример на jsfiddle основанные на примере из MDN с BufferSource.

console.clear(); 
var playButton = document.querySelector('.play'); 
var playButtonOffline = document.querySelector('.play-offline'); 
 
var current = 0; 
var buffer_size = 4096; 
var buffer_length = buffer_size * 10; 
 
 
var audioCtx = new(window.AudioContext || window.webkitAudioContext)(); 
var scriptNode = audioCtx.createScriptProcessor(buffer_size, 1, 1); 
scriptNode.onaudioprocess = whiteNoise; 
 
 
function whiteNoise(audioProcessingEvent) { 
  console.log('onaudioprocess', current); 
 
  // The output buffer contains the samples that will be modified and played 
  var outputBuffer = audioProcessingEvent.outputBuffer; 
 
  // Loop through the output channel 
  for (var channel = 0; channel < outputBuffer.numberOfChannels; channel++) { 
    var outputData = outputBuffer.getChannelData(channel); 
    for (var sample = 0; sample < buffer_size; sample++) { 
      // add noise to each output sample 
      outputData[sample] += ((Math.random() * 2) - 1); 
    } 
  } 
  current += buffer_size; 
  if (current > buffer_length) 
    scriptNode.disconnect(); 
} 
 
playButton.onclick = function() { 
  current = 0; 
  scriptNode.connect(audioCtx.destination); 
} 
 
playButtonOffline.onclick = function() { 
  var offlineCtx = new(window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, buffer_length, 48000); 
  var scriptNodeOffline = offlineCtx.createScriptProcessor(buffer_size, 1, 1); 
  scriptNodeOffline.onaudioprocess = whiteNoise; 
  current = 0; 
  offlineCtx.oncomplete = function(e) { 
    console.log('rendered buffer', e.renderedBuffer.getChannelData(0).filter(f => f != 0).length); 
  } 
  scriptNodeOffline.connect(offlineCtx.destination); 
  offlineCtx.startRendering(); 
}
<button class="play"> 
  play 
</button> 
<button class="play-offline"> 
  Render offline 
</button>

Update

При нажатии на Render offline несколько раз в Chrome и Firefox получается одинаковый результат.

При нажатии на Render offline несколько раз в Safari and Edge получается разный результат.

Пример на jsfiddle.

// Create AudioContext and buffer source 
console.clear(); 
 
var playButton = document.querySelector('.play'); 
var playButtonOffline = document.querySelector('.play-offline'); 
var myBuffer = null; 
 
var audioCtx = new(window.AudioContext || window.webkitAudioContext)(); 
var source = audioCtx.createBufferSource(); 
 
// Create a ScriptProcessorNode with a bufferSize of 4096 and a single input and output channel 
var scriptNode = audioCtx.createScriptProcessor(4096, 1, 1); 
 
// load in an audio track via XHR and decodeAudioData 
 
function getData() { 
  request = new XMLHttpRequest(); 
  request.open('GET', 'https://s3-ap-northeast-1.amazonaws.com/storage.cowrite.decodeapps.io/Materials/Media/Audio/59f2b85dd3aed-20171027-043853.mp3', true); 
  request.responseType = 'arraybuffer'; 
  request.onload = function() { 
    var audioData = request.response; 
 
    audioCtx.decodeAudioData(audioData, function(buffer) { 
        myBuffer = buffer; 
        source.buffer = myBuffer; 
      }, 
      function(e) { 
        "Error with decoding audio data" + e.err 
      }); 
  } 
  request.send(); 
} 
 
function addNoise(audioProcessingEvent) { 
  console.log("onaudioprocess") 
  // The input buffer is the song we loaded earlier 
  var inputBuffer = audioProcessingEvent.inputBuffer; 
 
  // The output buffer contains the samples that will be modified and played 
  var outputBuffer = audioProcessingEvent.outputBuffer; 
 
  // Loop through the output channels (in this case there is only one) 
  for (var channel = 0; channel < outputBuffer.numberOfChannels; channel++) { 
    var inputData = inputBuffer.getChannelData(channel); 
    var outputData = outputBuffer.getChannelData(channel); 
 
    // Loop through the 4096 samples 
    for (var sample = 0; sample < inputBuffer.length; sample++) { 
      // make output equal to the same as the input 
      outputData[sample] = inputData[sample]; 
 
      // add noise to each output sample 
      outputData[sample] += ((Math.random() * 2) - 1) * 0.2; 
    } 
  } 
} 
 
// Give the node a function to process audio events 
scriptNode.onaudioprocess = addNoise; 
 
getData(); 
 
// wire up play button 
playButton.onclick = function() { 
  source.connect(scriptNode); 
  scriptNode.connect(audioCtx.destination); 
  source.start(); 
} 
 
// When the buffer source stops playing, disconnect everything 
source.onended = function() { 
  source.disconnect(scriptNode); 
  scriptNode.disconnect(audioCtx.destination); 
} 
 
 
// When the buffer source stops playing, disconnect everything 
 
 
// wire up play button 
playButtonOffline.onclick = function() { 
  var offlineCtx = new(window.OfflineAudioContext || window.webkitOfflineAudioContext)(2, 44100 * 40, 44100); 
  var scriptNodeOffline = offlineCtx.createScriptProcessor(4096, 1, 1); 
  var sourceOffline = offlineCtx.createBufferSource(); 
  sourceOffline.buffer = myBuffer; 
  sourceOffline.onended = function() { 
    console.log('sourceOffline.onended'); 
    sourceOffline.disconnect(scriptNodeOffline); 
    scriptNodeOffline.disconnect(offlineCtx.destination); 
  } 
  scriptNodeOffline.onaudioprocess = addNoise; 
  sourceOffline.connect(scriptNodeOffline); 
  scriptNodeOffline.connect(offlineCtx.destination); 
  sourceOffline.start(); 
  offlineCtx.oncomplete = function(e) { 
    console.log('renderedBuffer', e.renderedBuffer.getChannelData(0).filter(f => f != 0).length); 
  }; 
  offlineCtx.startRendering(); 
}
<button class="play"> 
  play 
</button> 
<button class="play-offline"> 
  Render offline 
</button>

READ ALSO
Добавление класса по клику + проверка на наличие класса и добавление класса другому div

Добавление класса по клику + проверка на наличие класса и добавление класса другому div

У меня немного запутанное задание: нужно чтобы при клике на inputinput-checkbox другому div

285
Как правильно доработать скрипт?

Как правильно доработать скрипт?

Добрый день! Помогите, пожалуйста, доработать скриптБлок

312
Почему возвращается объект?

Почему возвращается объект?

Помогите пожалуйста понять что детально происходит при таком вызове:

306
Распознавание голоса Web Kit Speech Recognition не работает

Распознавание голоса Web Kit Speech Recognition не работает

Здравствуйте, я добавил на сайт технологию Web Kit Speech Recognition API, эта технология способна распознавать голосМой сайт находится на локальном сервере,...

231