Search code examples
html5-audioaudio-streamingweb-audio-apilive-streamingaudiocontext

Web Audio API Stream: why isn't dataArray changing?


EDIT 2: solved. See answer below.

EDIT 1:

I changed my code a little, added a gain node, moved a function. I also found that IF I use the microphone, it will work. Still doesn't work with usb audio input. Any idea? This is my current code:

window.AudioContext = window.AudioContext || window.webkitAudioContext;

window.onload = function(){

  var audioContext = new AudioContext();
  var analyser = audioContext.createAnalyser();
  var gainNode = audioContext.createGain();

  navigator.mediaDevices.getUserMedia({ audio:true, video:false }).then(function(stream){ //MediaStream

    var source = audioContext.createMediaStreamSource(stream);
    source.connect(analyser);
    analyser.connect(gainNode);
    gainNode.connect(audioContext.destination);

    listen();

  });

  function listen(){

    analyser.fftSize = 256;
    var bufferLength = analyser.frequencyBinCount;
    var dataArray = new Uint8Array(bufferLength);
    var index = 0;

    function write(){
      requestAnimationFrame(listen);
      analyser.getByteTimeDomainData(dataArray);
      $('.monitor').html(JSON.stringify(dataArray) + ' -- ' + (index++));
    }

    write();
  }

}

OLD/ORIGINAL POST:

my current code is this, and I currently connected a kewboard via a USB audio interface: I've got signal, already tried with other programs.. So:

window.AudioContext = window.AudioContext || window.webkitAudioContext;

window.onload = function(){

  var audioContext = new AudioContext();
  var analyser = audioContext.createAnalyser();

  navigator.mediaDevices.getUserMedia({ audio:true, video:false }).then(function(stream){ //MediaStream

    var source = audioContext.createMediaStreamSource(stream);
    source.connect(analyser);
    analyser.connect(audioContext.destination);

    analyser.fftSize = 2048;
    var bufferLength = analyser.frequencyBinCount;
    var dataArray = new Uint8Array(bufferLength);

    function listen(){
      requestAnimationFrame(listen);
      analyser.getByteTimeDomainData(dataArray);
      $('.monitor').html(JSON.stringify(dataArray));
    }

    listen();

  });
}

While I'm playing my keyboard, the dataArray doesn't change at all. Why? I'm new to this things so probably I'm doing something wrong...


Solution

  • Ok now it's working. My basic current test code is the following. Html has nothing but a div.monitor to write inside. Currently testing on firefox. My hardware is keyboard > mixer > behringer UCA222 > computer (usb). I get data when playing the keyboard and I'm happy now.

    There are several differences from the original code, but I think the most important is that I'm saving the media source globally (window.audiosource). There are other posts here about a related issue, for example this: Chrome: onaudioprocess stops getting called after a while and this HTML5 Microphone capture stops after 5 seconds in Firefox.

    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    
    navigator.getUserMedia = (navigator.getUserMedia ||
                              navigator.webkitGetUserMedia ||
                              navigator.mozGetUserMedia ||
                              navigator.msGetUserMedia);
    
    var audioContext = new (window.AudioContext || window.webkitAudioContext)();
    var analyser = audioContext.createAnalyser();
    
    if(navigator.getUserMedia){
      navigator.getUserMedia(
        { audio: true }
        ,function(stream){
          window.audiosource = audioContext.createMediaStreamSource(stream);
          audiosource.connect(analyser);
          listen();
        }
        ,function(err){ console.log('The following gUM error occured: ' + err); }
      );
    }
    
    function listen(){
      requestAnimationFrame(listen);
    
      analyser.fftSize = 256;
      var bufferLength = analyser.frequencyBinCount;
      var dataArray = new Uint8Array(bufferLength);
      analyser.getByteTimeDomainData(dataArray);
      $('.monitor').html(JSON.stringify(dataArray));
    }