diff --git a/Gruntfile.js b/Gruntfile.js index 82ab664f..0e97715d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -44,6 +44,20 @@ module.exports = function(grunt) { } } }); + } else if (path.indexOf('node_modules/startaudiocontext') > -1) { + // return '/** StartAudioContext.js by Yotam Mann, MIT License 2017 https://github.com/tambien/StartAudioContext http://opensource.org/licenses/MIT **/\n' + + return require('amdclean').clean({ + code: contents, + escodegen: { + comment: false, + format: { + indent: { + style: ' ', + adjustMultiLineComment: true + } + } + } + }); } else { return require('amdclean').clean({ 'code':contents, @@ -63,6 +77,7 @@ module.exports = function(grunt) { out: 'lib/p5.sound.js', paths: { 'Tone' : 'node_modules/tone/Tone', + 'StartAudioContext' : 'node_modules/startaudiocontext/StartAudioContext', 'automation-timeline': 'node_modules/web-audio-automation-timeline/build/automation-timeline-amd', 'panner' : 'src/panner', 'shims': 'src/shims', diff --git a/package.json b/package.json index e8e08cd7..91d39d1b 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "grunt-open": "^0.2.3" }, "dependencies": { + "startaudiocontext": "^1.2.1", "tone": "0.10.0" }, "scripts": { diff --git a/src/audiocontext.js b/src/audiocontext.js index ec43d34c..28ac40dd 100644 --- a/src/audiocontext.js +++ b/src/audiocontext.js @@ -1,6 +1,6 @@ 'use strict'; -define(function () { +define(['StartAudioContext'], function (require, StartAudioContext) { // Create the Audio Context var audiocontext = new window.AudioContext(); @@ -42,34 +42,57 @@ define(function () { return audiocontext; }; - // if it is iOS, we have to have a user interaction to start Web Audio - // http://paulbakaus.com/tutorials/html5/web-audio-on-ios/ - var iOS = navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false ; - if (iOS) { - var iosStarted = false; - var startIOS = function() { - if (iosStarted) return; - // create empty buffer - var buffer = audiocontext.createBuffer(1, 1, 22050); - var source = audiocontext.createBufferSource(); - source.buffer = buffer; - - // connect to output (your speakers) - source.connect(audiocontext.destination); - // play the file - source.start(0); - console.log('start ios!'); - - if (audiocontext.state === 'running') { - iosStarted = true; - } - }; - document.addEventListener('touchend', startIOS, false); - document.addEventListener('touchstart', startIOS, false); - - // TO DO: fake touch event so that audio will just start - } + /** + *
It is a good practice to give users control over starting audio playback. + * This practice is enforced by Google Chrome's autoplay policy as of r70 + * (info), iOS Safari, and other browsers. + *
+ * + *+ * userStartAudio() starts the Audio Context on a user gesture. It utilizes + * the StartAudioContext library by + * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext. + *
+ * + *Starting the audio context on a user gesture can be as simple as userStartAudio()
.
+ * Optional parameters let you decide on a specific element that will start the audio context,
+ * and/or call a function once the audio context is started.
+ * function setup() {
+ * var myDiv = createDiv('click to start audio');
+ * myDiv.position(0, 0);
+ *
+ * var mySynth = new p5.MonoSynth();
+ *
+ * // This won't play until the context has started
+ * mySynth.play('A6');
+ *
+ * // Start the audio context on a click/touch event
+ * userStartAudio().then(function() {
+ * myDiv.remove();
+ * });
+ * }
+ *