Tone.js/examples/scripts/StartAudioContext.js

180 lines
4.5 KiB
JavaScript
Raw Normal View History

2016-03-04 22:38:32 +00:00
/**
* StartAudioContext.js
* @author Yotam Mann
* @license http://opensource.org/licenses/MIT MIT License
* @copyright 2016 Yotam Mann
*/
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define([], factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory();
} else {
root.StartAudioContext = factory();
}
}(this, function () {
/**
* The StartAudioContext object
*/
var StartAudioContext = {
/**
* The audio context passed in by the user
* @type {AudioContext}
*/
context : null,
/**
* The TapListeners bound to the elements
* @type {Array}
* @private
*/
_tapListeners : [],
/**
* Callbacks to invoke when the audio context is started
* @type {Array}
* @private
*/
_onStarted : [],
};
/**
* Set the context
* @param {AudioContext} ctx
* @returns {StartAudioContext}
*/
StartAudioContext.setContext = function(ctx){
StartAudioContext.context = ctx;
return StartAudioContext;
};
/**
* Add a tap listener to the audio context
* @param {Array|Element|String|jQuery} element
* @returns {StartAudioContext}
*/
StartAudioContext.on = function(element){
if (Array.isArray(element) || (NodeList && element instanceof NodeList)){
for (var i = 0; i < element.length; i++){
StartAudioContext.on(element[i]);
}
} else if (typeof element === "string"){
StartAudioContext.on(document.querySelectorAll(element));
} else if (element.jquery && typeof element.toArray === "function"){
StartAudioContext.on(element.toArray());
} else if (Element && element instanceof Element){
//if it's an element, create a TapListener
var tap = new TapListener(element, onTap);
StartAudioContext._tapListeners.push(tap);
}
return StartAudioContext;
};
/**
* Bind a callback to when the audio context is started.
* @param {Function} cb
* @return {StartAudioContext}
*/
StartAudioContext.onStarted = function(cb){
//if it's already started, invoke the callback
if (StartAudioContext.isStarted()){
cb();
} else {
StartAudioContext._onStarted.push(cb);
}
return StartAudioContext;
};
/**
* returns true if the context is started
* @return {Boolean}
*/
StartAudioContext.isStarted = function(){
return (StartAudioContext.context !== null && StartAudioContext.context.state === "running");
};
/**
* @class Listens for non-dragging tap ends on the given element
* @param {Element} element
* @internal
*/
var TapListener = function(element){
this._dragged = false;
this._element = element;
this._bindedMove = this._moved.bind(this);
this._bindedEnd = this._ended.bind(this);
element.addEventListener("touchmove", this._bindedMove);
element.addEventListener("touchend", this._bindedEnd);
element.addEventListener("mouseup", this._bindedEnd);
};
/**
* drag move event
*/
TapListener.prototype._moved = function(e){
this._dragged = true;
};
/**
* tap ended listener
*/
TapListener.prototype._ended = function(e){
if (!this._dragged){
onTap();
}
this._dragged = false;
};
/**
* remove all the bound events
*/
TapListener.prototype.dispose = function(){
this._element.removeEventListener("touchmove", this._bindedMove);
this._element.removeEventListener("touchend", this._bindedEnd);
this._element.removeEventListener("mouseup", this._bindedEnd);
this._bindedMove = null;
this._bindedEnd = null;
this._element = null;
};
/**
* Invoked the first time of the elements is tapped.
* Creates a silent oscillator when a non-dragging touchend
* event has been triggered.
*/
function onTap(){
//start the audio context with a silent oscillator
if (StartAudioContext.context && !StartAudioContext.isStarted()){
var osc = StartAudioContext.context.createOscillator();
var silent = StartAudioContext.context.createGain();
silent.gain.value = 0;
osc.connect(silent);
silent.connect(StartAudioContext.context.destination);
var now = StartAudioContext.context.currentTime;
osc.start(now);
osc.stop(now+0.5);
}
//dispose all the tap listeners
if (StartAudioContext._tapListeners){
for (var i = 0; i < StartAudioContext._tapListeners.length; i++){
StartAudioContext._tapListeners[i].dispose();
}
StartAudioContext._tapListeners = null;
}
//the onstarted callbacks
if (StartAudioContext._onStarted){
for (var j = 0; j < StartAudioContext._onStarted.length; j++){
StartAudioContext._onStarted[j]();
}
StartAudioContext._onStarted = null;
}
}
return StartAudioContext;
}));