Search code examples
javascriptjqueryiosweb-audio-api

Web audio api on jQuery touch move not working iOS


Here's my code:

$(document).ready(function(){ 

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.type = 'sine';
gainNode.gain.value = 0;
oscillator.start();

document.addEventListener("touchmove", function(e) {
    e.preventDefault();
    var touch = e.touches[0];
    var x = touch.pageX;
    var y = touch.pageY;
    x = Math.round(x);
    y = Math.round(y);

    x = mRound(x, 20);
    y = mRound(y, 10);

    $("#coords").text(x + ", " + y);

    gainNode.gain.value = x / 10;
    oscillator.frequency.value = y;

}, false);

});

function mRound(n, m){

if(n > 0)
    return Math.ceil(n/m) * m;
else if( n < 0)
    return Math.floor(n/m) * m;
else
    return m;

}

This works in chrome and Firefox on android but no sound plays in safari or chrome on iOS. The web audio api does work in safari because I have tested it using a much simpler script and 'touchmove' seems to work because the coordinates come up in #coords.

Thanks.


Solution

  • I'm working on a similar issue. WebKit on iOS is very picky when it comes to the possibility of "autostarting" audio.

    Initiating the AudioContext on the "touchstart" event did the trick on my iPhone SE with iOS 10.1.1:

    $(document).ready(function(){
      var oscillator, gainNode, audioCtx;
    
      var initOnce = false;
    
      document.addEventListener("touchstart", function(e) {
        if (!initOnce){
          initOnce = true;
          audioCtx = new (window.AudioContext || window.webkitAudioContext)();  
          oscillator = audioCtx.createOscillator();
          gainNode = audioCtx.createGain();
          oscillator.connect(gainNode);
          gainNode.connect(audioCtx.destination);
          oscillator.type = 'sine';
          gainNode.gain.value = 0;
          oscillator.start();
        }
      });
    
      document.addEventListener("touchmove", function(e) {
          e.preventDefault();
          var touch = e.touches[0];
          var x = touch.pageX;
          var y = touch.pageY;
          x = Math.round(x);
          y = Math.round(y);
    
          x = mRound(x, 20);
          y = mRound(y, 10);
    
          $("#coords").text(x + ", " + y);
    
          gainNode.gain.value = x / 10;
          oscillator.frequency.value = y;
    
      }, false);
    
    });
    
    function mRound(n, m){
    
    if(n > 0)
        return Math.ceil(n/m) * m;
    else if( n < 0)
        return Math.floor(n/m) * m;
    else
        return m;
    
    }