Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start audio context #322

Merged
merged 8 commits into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"grunt-open": "^0.2.3"
},
"dependencies": {
"startaudiocontext": "^1.2.1",
"tone": "0.10.0"
},
"scripts": {
Expand Down
79 changes: 51 additions & 28 deletions src/audiocontext.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

define(function () {
define(['StartAudioContext'], function (require, StartAudioContext) {
// Create the Audio Context
var audiocontext = new window.AudioContext();

Expand Down Expand Up @@ -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
}
/**
* <p>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
* (<a href="https://goo.gl/7K7WLu">info</a>), iOS Safari, and other browsers.
* </p>
*
* <p>
* userStartAudio() starts the <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioContext"
* target="_blank" title="Audio Context @ MDN">Audio Context</a> on a user gesture. It utilizes
* the <a href="https://github.com/tambien/StartAudioContext">StartAudioContext</a> library by
* Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext.
* </p>
*
* <p>Starting the audio context on a user gesture can be as simple as <code>userStartAudio()</code>.
* 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.</p>
* @param {Element|Array} [element(s)] This argument can be an Element,
* Selector String, NodeList, p5.Element,
* jQuery Element, or an Array of any of those.
* @param {Function} [callback] Callback to invoke when the AudioContext has started
* @return {Promise} Returns a Promise which is resolved when
* the AudioContext state is 'running'
* @method userStartAudio
* @example
* <div><code>
* 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();
* });
* }
* </code></div>
*/
p5.prototype.userStartAudio = function(elements, callback) {
var elt = elements;
if (elements instanceof p5.Element) {
elt = elements.elt;
} else if (elements instanceof Array && elements[0] instanceof p5.Element ) {
elt = elements.map(function(e) { return e.elt});
}
return StartAudioContext(audiocontext, elt, callback);
};

return audiocontext;
});