diff --git a/lib/p5.sound.js b/lib/p5.sound.js
index 04ff0801..02532895 100644
--- a/lib/p5.sound.js
+++ b/lib/p5.sound.js
@@ -146,7 +146,7 @@
/******/
/******/
/******/ // Load entry module and return exports
-/******/ return __webpack_require__(__webpack_require__.s = 30);
+/******/ return __webpack_require__(__webpack_require__.s = 31);
/******/ })
/************************************************************************/
/******/ ([
@@ -287,7 +287,7 @@ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
-var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(5),__webpack_require__(8),__webpack_require__(21),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){"use strict";return n.Signal=function(){var t=this.optionsObject(arguments,["value","units"],n.Signal.defaults);this.output=this._gain=this.context.createGain(),t.param=this._gain.gain,n.Param.call(this,t),this.input=this._param=this._gain.gain,this.context.getConstant(1).chain(this._gain)},n.extend(n.Signal,n.Param),n.Signal.defaults={value:0,units:n.Type.Default,convert:!0},n.Signal.prototype.connect=n.SignalBase.prototype.connect,n.Signal.prototype.dispose=function(){return n.Param.prototype.dispose.call(this),this._param=null,this._gain.disconnect(),this._gain=null,this},n.Signal}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(5),__webpack_require__(8),__webpack_require__(22),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){"use strict";return n.Signal=function(){var t=this.optionsObject(arguments,["value","units"],n.Signal.defaults);this.output=this._gain=this.context.createGain(),t.param=this._gain.gain,n.Param.call(this,t),this.input=this._param=this._gain.gain,this.context.getConstant(1).chain(this._gain)},n.extend(n.Signal,n.Param),n.Signal.defaults={value:0,units:n.Type.Default,convert:!0},n.Signal.prototype.connect=n.SignalBase.prototype.connect,n.Signal.prototype.dispose=function(){return n.Param.prototype.dispose.call(this),this._param=null,this._gain.disconnect(),this._gain=null,this},n.Signal}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
@@ -307,7 +307,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
!(__WEBPACK_AMD_DEFINE_RESULT__ = (function (require) {
var p5sound = __webpack_require__(1);
- var CrossFade = __webpack_require__(48);
+ var CrossFade = __webpack_require__(50);
/**
* Effect is a base class for audio effects in p5.
* This module handles the nodes and methods that are
@@ -482,7 +482,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
-var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(18)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(e){"use strict";return e.WaveShaper=function(e,t){this._shaper=this.input=this.output=this.context.createWaveShaper(),this._curve=null,Array.isArray(e)?this.curve=e:isFinite(e)||this.isUndef(e)?this._curve=new Float32Array(this.defaultArg(e,1024)):this.isFunction(e)&&(this._curve=new Float32Array(this.defaultArg(t,1024)),this.setMap(e))},e.extend(e.WaveShaper,e.SignalBase),e.WaveShaper.prototype.setMap=function(e){for(var t=0,r=this._curve.length;te)this.cancelScheduledValues(e),this.linearRampToValueAtTime(t,e);else{var n=this._searchAfter(e);n&&(this.cancelScheduledValues(e),n.type===o.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(t,e):n.type===o.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(t,e)),this.setValueAtTime(t,e)}return this},o.TimelineSignal.prototype.linearRampToValueBetween=function(e,t,i){return this.setRampPoint(t),this.linearRampToValueAtTime(e,i),this},o.TimelineSignal.prototype.exponentialRampToValueBetween=function(e,t,i){return this.setRampPoint(t),this.exponentialRampToValueAtTime(e,i),this},o.TimelineSignal.prototype._searchBefore=function(e){return this._events.get(e)},o.TimelineSignal.prototype._searchAfter=function(e){return this._events.getAfter(e)},o.TimelineSignal.prototype.getValueAtTime=function(e){e=this.toSeconds(e);var t=this._searchAfter(e),i=this._searchBefore(e),n=this._initial;if(null===i)n=this._initial;else if(i.type===o.TimelineSignal.Type.Target){var a,l=this._events.getBefore(i.time);a=null===l?this._initial:l.value,n=this._exponentialApproach(i.time,a,i.value,i.constant,e)}else n=i.type===o.TimelineSignal.Type.Curve?this._curveInterpolate(i.time,i.value,i.duration,e):null===t?i.value:t.type===o.TimelineSignal.Type.Linear?this._linearInterpolate(i.time,i.value,t.time,t.value,e):t.type===o.TimelineSignal.Type.Exponential?this._exponentialInterpolate(i.time,i.value,t.time,t.value,e):i.value;return n},o.TimelineSignal.prototype.connect=o.SignalBase.prototype.connect,o.TimelineSignal.prototype._exponentialApproach=function(e,t,i,n,a){return i+(t-i)*Math.exp(-(a-e)/n)},o.TimelineSignal.prototype._linearInterpolate=function(e,t,i,n,a){return t+(a-e)/(i-e)*(n-t)},o.TimelineSignal.prototype._exponentialInterpolate=function(e,t,i,n,a){return(t=Math.max(this._minOutput,t))*Math.pow(n/t,(a-e)/(i-e))},o.TimelineSignal.prototype._curveInterpolate=function(e,t,i,n){var a=t.length;if(e+i<=n)return t[a-1];if(n<=e)return t[0];var l=(n-e)/i,s=Math.floor((a-1)*l),r=Math.ceil((a-1)*l),o=t[s],p=t[r];return r===s?o:this._linearInterpolate(s,o,r,p,l*(a-1))},o.TimelineSignal.prototype.dispose=function(){o.Signal.prototype.dispose.call(this),o.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},o.TimelineSignal}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(2),__webpack_require__(24)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){"use strict";return o.TimelineSignal=function(){var e=this.optionsObject(arguments,["value","units"],o.Signal.defaults);this._events=new o.Timeline(10),o.Signal.apply(this,e),e.param=this._param,o.Param.call(this,e),this._initial=this._fromUnits(this._param.value)},o.extend(o.TimelineSignal,o.Param),o.TimelineSignal.Type={Linear:"linear",Exponential:"exponential",Target:"target",Curve:"curve",Set:"set"},Object.defineProperty(o.TimelineSignal.prototype,"value",{get:function(){var e=this.now(),t=this.getValueAtTime(e);return this._toUnits(t)},set:function(e){var t=this._fromUnits(e);this._initial=t,this.cancelScheduledValues(),this._param.value=t}}),o.TimelineSignal.prototype.setValueAtTime=function(e,t){return e=this._fromUnits(e),t=this.toSeconds(t),this._events.add({type:o.TimelineSignal.Type.Set,value:e,time:t}),this._param.setValueAtTime(e,t),this},o.TimelineSignal.prototype.linearRampToValueAtTime=function(e,t){return e=this._fromUnits(e),t=this.toSeconds(t),this._events.add({type:o.TimelineSignal.Type.Linear,value:e,time:t}),this._param.linearRampToValueAtTime(e,t),this},o.TimelineSignal.prototype.exponentialRampToValueAtTime=function(e,t){t=this.toSeconds(t);var i=this._searchBefore(t);i&&0===i.value&&this.setValueAtTime(this._minOutput,i.time),e=this._fromUnits(e);var n=Math.max(e,this._minOutput);return this._events.add({type:o.TimelineSignal.Type.Exponential,value:n,time:t}),ee)this.cancelScheduledValues(e),this.linearRampToValueAtTime(t,e);else{var n=this._searchAfter(e);n&&(this.cancelScheduledValues(e),n.type===o.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(t,e):n.type===o.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(t,e)),this.setValueAtTime(t,e)}return this},o.TimelineSignal.prototype.linearRampToValueBetween=function(e,t,i){return this.setRampPoint(t),this.linearRampToValueAtTime(e,i),this},o.TimelineSignal.prototype.exponentialRampToValueBetween=function(e,t,i){return this.setRampPoint(t),this.exponentialRampToValueAtTime(e,i),this},o.TimelineSignal.prototype._searchBefore=function(e){return this._events.get(e)},o.TimelineSignal.prototype._searchAfter=function(e){return this._events.getAfter(e)},o.TimelineSignal.prototype.getValueAtTime=function(e){e=this.toSeconds(e);var t=this._searchAfter(e),i=this._searchBefore(e),n=this._initial;if(null===i)n=this._initial;else if(i.type===o.TimelineSignal.Type.Target){var a,l=this._events.getBefore(i.time);a=null===l?this._initial:l.value,n=this._exponentialApproach(i.time,a,i.value,i.constant,e)}else n=i.type===o.TimelineSignal.Type.Curve?this._curveInterpolate(i.time,i.value,i.duration,e):null===t?i.value:t.type===o.TimelineSignal.Type.Linear?this._linearInterpolate(i.time,i.value,t.time,t.value,e):t.type===o.TimelineSignal.Type.Exponential?this._exponentialInterpolate(i.time,i.value,t.time,t.value,e):i.value;return n},o.TimelineSignal.prototype.connect=o.SignalBase.prototype.connect,o.TimelineSignal.prototype._exponentialApproach=function(e,t,i,n,a){return i+(t-i)*Math.exp(-(a-e)/n)},o.TimelineSignal.prototype._linearInterpolate=function(e,t,i,n,a){return t+(a-e)/(i-e)*(n-t)},o.TimelineSignal.prototype._exponentialInterpolate=function(e,t,i,n,a){return(t=Math.max(this._minOutput,t))*Math.pow(n/t,(a-e)/(i-e))},o.TimelineSignal.prototype._curveInterpolate=function(e,t,i,n){var a=t.length;if(e+i<=n)return t[a-1];if(n<=e)return t[0];var l=(n-e)/i,s=Math.floor((a-1)*l),r=Math.ceil((a-1)*l),o=t[s],p=t[r];return r===s?o:this._linearInterpolate(s,o,r,p,l*(a-1))},o.TimelineSignal.prototype.dispose=function(){o.Signal.prototype.dispose.call(this),o.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},o.TimelineSignal}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
@@ -1240,7 +1240,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
/* 15 */
/***/ (function(module, exports, __webpack_require__) {
-var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(7),__webpack_require__(24),__webpack_require__(2),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){"use strict";return n.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new n.Gain,this._neg=new n.Negate,this._param=this.input[1]=new n.Signal(t),this._param.chain(this._neg,this._sum)},n.extend(n.Subtract,n.Signal),n.Subtract.prototype.dispose=function(){return n.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},n.Subtract}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(7),__webpack_require__(25),__webpack_require__(2),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){"use strict";return n.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new n.Gain,this._neg=new n.Negate,this._param=this.input[1]=new n.Signal(t),this._param.chain(this._neg,this._sum)},n.extend(n.Subtract,n.Signal),n.Subtract.prototype.dispose=function(){return n.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},n.Subtract}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
@@ -1251,7 +1251,7 @@ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_
/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
global.TONE_SILENCE_VERSION_LOGGING = true;
-!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(34), __webpack_require__(11), __webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function (StartAudioContext, Context, Tone) {
+!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(35), __webpack_require__(11), __webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function (StartAudioContext, Context, Tone) {
// Create the Audio Context
var audiocontext = new window.AudioContext(); // Tone and p5.sound share the same audio context
@@ -1356,7 +1356,7 @@ global.TONE_SILENCE_VERSION_LOGGING = true;
return audiocontext;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
-/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(33)))
+/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(34)))
/***/ }),
/* 17 */
@@ -1367,34 +1367,44 @@ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_
/***/ }),
/* 18 */
+/***/ (function(module, exports) {
+
+module.exports = {
+ recorderProcessor: 'recorder-processor',
+ soundFileProcessor: 'sound-file-processor',
+ amplitudeProcessor: 'amplitude-processor'
+};
+
+/***/ }),
+/* 19 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(c){"use strict";return c.SignalBase=function(){},c.extend(c.SignalBase),c.SignalBase.prototype.connect=function(e,n,a){return c.Signal&&c.Signal===e.constructor||c.Param&&c.Param===e.constructor||c.TimelineSignal&&c.TimelineSignal===e.constructor?(e._param.cancelScheduledValues(0),e._param.value=0,e.overridden=!0):e instanceof AudioParam&&(e.cancelScheduledValues(0),e.value=0),c.prototype.connect.call(this,e,n,a),this},c.SignalBase}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 19 */
+/* 20 */
/***/ (function(module, exports, __webpack_require__) {
-var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(20)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){return o.Time=function(t,e){if(!(this instanceof o.Time))return new o.Time(t,e);this._plusNow=!1,o.TimeBase.call(this,t,e)},o.extend(o.Time,o.TimeBase),o.Time.prototype._unaryExpressions=Object.create(o.TimeBase.prototype._unaryExpressions),o.Time.prototype._unaryExpressions.quantize={regexp:/^@/,method:function(t){return o.Transport.nextSubdivision(t())}},o.Time.prototype._unaryExpressions.now={regexp:/^\+/,method:function(t){return this._plusNow=!0,t()}},o.Time.prototype.quantize=function(t,e){return e=this.defaultArg(e,1),this._expr=function(t,e,o){return t=t(),e=e.toSeconds(),t+(Math.round(t/e)*e-t)*o}.bind(this,this._expr,new this.constructor(t),e),this},o.Time.prototype.addNow=function(){return this._plusNow=!0,this},o.Time.prototype._defaultExpr=function(){return this._plusNow=!0,this._noOp},o.Time.prototype.copy=function(t){return o.TimeBase.prototype.copy.call(this,t),this._plusNow=t._plusNow,this},o.Time.prototype.toNotation=function(){var t=this.toSeconds(),e=this._toNotationHelper(t,["1m","2n","4n","8n","16n","32n","64n","128n"]),o=this._toNotationHelper(t,["1m","2n","2t","4n","4t","8n","8t","16n","16t","32n","32t","64n","64t","128n"]);return o.split("+").lengththis.memory){var t=this.length-this.memory;this._timeline.splice(0,t)}return this},i.Timeline.prototype.remove=function(e){if(this._iterating)this._toRemove.push(e);else{var i=this._timeline.indexOf(e);-1!==i&&this._timeline.splice(i,1)}return this},i.Timeline.prototype.get=function(e){var i=this._search(e);return-1!==i?this._timeline[i]:null},i.Timeline.prototype.peek=function(){return this._timeline[0]},i.Timeline.prototype.shift=function(){return this._timeline.shift()},i.Timeline.prototype.getAfter=function(e){var i=this._search(e);return i+1=e&&(this._timeline=[]);return this},i.Timeline.prototype.cancelBefore=function(e){if(this._timeline.length){var i=this._search(e);0<=i&&(this._timeline=this._timeline.slice(i+1))}return this},i.Timeline.prototype._search=function(e){var i=0,t=this._timeline.length,n=t;if(0e)return r;s.time>e?n=r:s.time=e;)t--;return this._iterate(i,t+1),this},i.Timeline.prototype.forEachAtTime=function(i,t){var e=this._search(i);return-1!==e&&this._iterate(function(e){e.time===i&&t(e)},0,e),this},i.Timeline.prototype.dispose=function(){i.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},i.Timeline}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 24 */
+/* 25 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(3),__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(t){"use strict";return t.Negate=function(){this._multiply=this.input=this.output=new t.Multiply(-1)},t.extend(t.Negate,t.SignalBase),t.Negate.prototype.dispose=function(){return t.prototype.dispose.call(this),this._multiply.dispose(),this._multiply=null,this},t.Negate}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 25 */
+/* 26 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(2),__webpack_require__(3),__webpack_require__(5)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(e){"use strict";return e.GreaterThanZero=function(){this._thresh=this.output=new e.WaveShaper(function(e){return e<=0?0:1},127),this._scale=this.input=new e.Multiply(1e4),this._scale.connect(this._thresh)},e.extend(e.GreaterThanZero,e.SignalBase),e.GreaterThanZero.prototype.dispose=function(){return e.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},e.GreaterThanZero}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 26 */
+/* 27 */
/***/ (function(module, exports, __webpack_require__) {
-var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(13),__webpack_require__(63),__webpack_require__(17),__webpack_require__(11)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var i=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=i.time,this.isUndef(i.offset)||(this.ticks=i.offset),this.emit("start",i.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",i.time)):e===o.State.Paused&&this.emit("pause",i.time)}var s=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(s),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(13),__webpack_require__(65),__webpack_require__(17),__webpack_require__(11)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var i=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=i.time,this.isUndef(i.offset)||(this.ticks=i.offset),this.emit("start",i.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",i.time)):e===o.State.Paused&&this.emit("pause",i.time)}var s=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(s),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 27 */
+/* 28 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -2033,7 +2043,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
!(__WEBPACK_AMD_DEFINE_RESULT__ = (function (require) {
var p5sound = __webpack_require__(1);
- var AudioVoice = __webpack_require__(28);
+ var AudioVoice = __webpack_require__(29);
var noteToFreq = __webpack_require__(6).noteToFreq;
@@ -2361,7 +2371,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 28 */
+/* 29 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -2428,7 +2438,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 29 */
+/* 30 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -2884,17 +2894,17 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 30 */
+/* 31 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __WEBPACK_AMD_DEFINE_RESULT__;
!(__WEBPACK_AMD_DEFINE_RESULT__ = (function (require) {
- __webpack_require__(31);
-
__webpack_require__(32);
+ __webpack_require__(33);
+
__webpack_require__(16);
var p5SOUND = __webpack_require__(1);
@@ -2903,11 +2913,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__webpack_require__(10);
- __webpack_require__(35);
-
- __webpack_require__(37);
-
- __webpack_require__(38);
+ __webpack_require__(36);
__webpack_require__(39);
@@ -2915,23 +2921,23 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__webpack_require__(41);
- __webpack_require__(22);
+ __webpack_require__(42);
- __webpack_require__(44);
+ __webpack_require__(43);
- __webpack_require__(45);
+ __webpack_require__(23);
__webpack_require__(46);
__webpack_require__(47);
- __webpack_require__(14);
+ __webpack_require__(48);
- __webpack_require__(56);
+ __webpack_require__(49);
- __webpack_require__(58);
+ __webpack_require__(14);
- __webpack_require__(59);
+ __webpack_require__(58);
__webpack_require__(60);
@@ -2939,36 +2945,40 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__webpack_require__(62);
- __webpack_require__(64);
+ __webpack_require__(63);
- __webpack_require__(65);
+ __webpack_require__(64);
__webpack_require__(66);
__webpack_require__(67);
+ __webpack_require__(68);
+
__webpack_require__(69);
__webpack_require__(70);
- __webpack_require__(27);
-
- __webpack_require__(29);
-
__webpack_require__(71);
__webpack_require__(28);
- __webpack_require__(27);
+ __webpack_require__(30);
+
+ __webpack_require__(72);
__webpack_require__(29);
+ __webpack_require__(28);
+
+ __webpack_require__(30);
+
return p5SOUND;
}).call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 31 */
+/* 32 */
/***/ (function(module, exports) {
!function(){var e,t=[];function r(e){var r=this,n={},i=-1;this.parameters.forEach(function(e,o){var s=t[++i]||(t[i]=new Float32Array(r.bufferSize));s.fill(e.value),n[o]=s}),this.processor.realm.exec("self.sampleRate=sampleRate="+this.context.sampleRate+";self.currentTime=currentTime="+this.context.currentTime);var s=o(e.inputBuffer),a=o(e.outputBuffer);this.instance.process([s],[a],n)}function o(e){for(var t=[],r=0;r= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n var output = outputs[0];\n\n for (var channel = 0; channel < output.length; ++channel) {\n var inputChannel = input[channel];\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannel);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannel);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannel);\n }\n }\n\n this.recordedSamples += output[0].length;\n return true;\n }\n }, {\n key: \"record\",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: \"stop\",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: 'buffers',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: \"getBuffers\",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: \"mergeBuffers\",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);");
+/* harmony default export */ __webpack_exports__["default"] = ("function _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \"function\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \"function\") { throw new TypeError(\"Super expression must either be null or a function\"); } if (typeof _cache !== \"undefined\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\"[native code]\") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import processor name via preval.require so that it's available as a value at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === 'start') {\n _this.record(data.duration);\n } else if (data.name === 'stop') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: \"process\",\n value: function process(inputs, outputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n var output = outputs[0];\n\n for (var channel = 0; channel < output.length; ++channel) {\n var inputChannel = input[channel];\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannel);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannel);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannel);\n }\n }\n\n this.recordedSamples += output[0].length;\n return true;\n }\n }, {\n key: \"record\",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: \"stop\",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: 'buffers',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: \"getBuffers\",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: \"mergeBuffers\",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);");
/***/ }),
-/* 37 */
+/* 38 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony default export */ __webpack_exports__["default"] = ("function _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \"function\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \"function\") { throw new TypeError(\"Super expression must either be null or a function\"); } if (typeof _cache !== \"undefined\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\"[native code]\") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import processor name via preval.require so that it's available as a value at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor() {\n _classCallCheck(this, SoundFileProcessor);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).apply(this, arguments));\n }\n\n _createClass(SoundFileProcessor, [{\n key: \"process\",\n value: function process(inputs) {\n var input = inputs[0];\n var inputChannel = input[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: 'position',\n position: position\n });\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);");
+
+/***/ }),
+/* 39 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -3564,7 +3582,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 38 */
+/* 40 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -3582,6 +3600,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
var midiToFreq = __webpack_require__(6).midiToFreq;
var convertToWav = __webpack_require__(6).convertToWav;
+
+ var processorNames = __webpack_require__(18);
/**
*
SoundFile object with a path to a file.
*
@@ -3668,7 +3688,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
this._lastPos = 0;
this._counterNode = null;
- this._scopeNode = null; // array of sources so that they can all be stopped!
+ this._workletNode = null; // array of sources so that they can all be stopped!
this.bufferSourceNodes = []; // current source
@@ -4841,25 +4861,30 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
p5.SoundFile.prototype._initCounterNode = function () {
var self = this;
var now = ac.currentTime;
- var cNode = ac.createBufferSource(); // dispose of scope node if it already exists
-
- if (self._scopeNode) {
- self._scopeNode.disconnect();
+ var cNode = ac.createBufferSource(); // dispose of worklet node if it already exists
- self._scopeNode.removeEventListener('audioprocess', self._onAudioProcess);
+ if (self._workletNode) {
+ self._workletNode.disconnect();
- delete self._scopeNode;
+ delete self._workletNode;
}
- self._scopeNode = ac.createScriptProcessor(256, 1, 1); // create counter buffer of the same length as self.buffer
+ self._workletNode = new AudioWorkletNode(ac, processorNames.soundFileProcessor);
+
+ self._workletNode.port.onmessage = function (event) {
+ if (event.data.name === 'position') {
+ this._lastPos = event.data.position; // do any callbacks that have been scheduled
+
+ this._onTimeUpdate(self._lastPos);
+ }
+ }.bind(self); // create counter buffer of the same length as self.buffer
+
cNode.buffer = _createCounterBuffer(self.buffer);
cNode.playbackRate.setValueAtTime(self.playbackRate, now);
- cNode.connect(self._scopeNode);
-
- self._scopeNode.connect(p5.soundOut._silentNode);
+ cNode.connect(self._workletNode);
- self._scopeNode.addEventListener('audioprocess', self._onAudioProcess);
+ self._workletNode.connect(p5.soundOut._silentNode);
return cNode;
}; // initialize sourceNode, set its initial buffer and playbackRate
@@ -5371,7 +5396,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 39 */
+/* 41 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -5379,6 +5404,8 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
!(__WEBPACK_AMD_DEFINE_RESULT__ = (function (require) {
var p5sound = __webpack_require__(1);
+
+ var processorNames = __webpack_require__(18);
/**
* Amplitude measures volume between 0.0 and 1.0.
* Listens to all p5sound by default, or use setInput()
@@ -5426,27 +5453,42 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
this.bufferSize = 2048; // set audio context
this.audiocontext = p5sound.audiocontext;
- this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1); // for connections
+ this._workletNode = new AudioWorkletNode(this.audiocontext, processorNames.amplitudeProcessor, {
+ outputChannelCount: [1],
+ parameterData: {
+ smoothing: smoothing || 0
+ },
+ processorOptions: {
+ normalize: false
+ }
+ });
+
+ this._workletNode.port.onmessage = function (event) {
+ if (event.data.name === 'amplitude') {
+ this.volume = event.data.volume;
+ this.volNorm = event.data.volNorm;
+ this.stereoVol = event.data.stereoVol;
+ this.stereoVolNorm = event.data.stereoVolNorm;
+ }
+ }.bind(this); // for connections
- this.input = this.processor;
- this.output = this.audiocontext.createGain(); // smoothing defaults to 0
- this.smoothing = smoothing || 0; // the variables to return
+ this.input = this._workletNode;
+ this.output = this.audiocontext.createGain(); // the variables to return
this.volume = 0;
- this.average = 0;
+ this.volNorm = 0;
this.stereoVol = [0, 0];
- this.stereoAvg = [0, 0];
this.stereoVolNorm = [0, 0];
- this.volMax = 0.001;
this.normalize = false;
- this.processor.onaudioprocess = this._audioProcess.bind(this);
- this.processor.connect(this.output);
+
+ this._workletNode.connect(this.output);
+
this.output.gain.value = 0; // this may only be necessary because of a Chrome bug
this.output.connect(this.audiocontext.destination); // connect to p5sound master output by default, unless set by input()
- p5sound.meter.connect(this.processor); // add this p5.SoundFile to the soundArray
+ p5sound.meter.connect(this._workletNode); // add this p5.SoundFile to the soundArray
p5sound.soundArray.push(this);
};
@@ -5492,24 +5534,26 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
p5sound.meter.disconnect();
if (smoothing) {
- this.smoothing = smoothing;
+ this._workletNode.parameters.get('smoothing').value = smoothing;
} // connect to the master out of p5s instance if no snd is provided
if (source == null) {
console.log('Amplitude input source is not ready! Connecting to master output instead');
- p5sound.meter.connect(this.processor);
+ p5sound.meter.connect(this._workletNode);
} // if it is a p5.Signal
else if (source instanceof p5.Signal) {
- source.output.connect(this.processor);
+ source.output.connect(this._workletNode);
} // connect to the sound if it is available
else if (source) {
- source.connect(this.processor);
- this.processor.disconnect();
- this.processor.connect(this.output);
+ source.connect(this._workletNode);
+
+ this._workletNode.disconnect();
+
+ this._workletNode.connect(this.output);
} // otherwise, connect to the master out of p5s instance (default)
else {
- p5sound.meter.connect(this.processor);
+ p5sound.meter.connect(this._workletNode);
}
};
@@ -5529,48 +5573,6 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
if (this.output) {
this.output.disconnect();
}
- }; // TO DO make this stereo / dependent on # of audio channels
-
-
- p5.Amplitude.prototype._audioProcess = function (event) {
- for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) {
- var inputBuffer = event.inputBuffer.getChannelData(channel);
- var bufLength = inputBuffer.length;
- var total = 0;
- var sum = 0;
- var x;
-
- for (var i = 0; i < bufLength; i++) {
- x = inputBuffer[i];
-
- if (this.normalize) {
- total += Math.max(Math.min(x / this.volMax, 1), -1);
- sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);
- } else {
- total += x;
- sum += x * x;
- }
- }
-
- var average = total / bufLength; // ... then take the square root of the sum.
-
- var rms = Math.sqrt(sum / bufLength);
- this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing);
- this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing);
- this.volMax = Math.max(this.stereoVol[channel], this.volMax);
- } // add volume from all channels together
-
-
- var self = this;
- var volSum = this.stereoVol.reduce(function (previousValue, currentValue, index) {
- self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1] / self.volMax, 1), 0);
- self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index] / self.volMax, 1), 0);
- return previousValue + currentValue;
- }); // volume is average of channels
-
- this.volume = volSum / this.stereoVol.length; // normalized value
-
- this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0);
};
/**
* Returns a single Amplitude reading at the moment it is called.
@@ -5638,6 +5640,11 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
} else {
this.normalize = !this.normalize;
}
+
+ this._workletNode.port.postMessage({
+ name: 'toggleNormalize',
+ normalize: this.normalize
+ });
};
/**
* Smooth Amplitude analysis by averaging with the last analysis
@@ -5651,7 +5658,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
p5.Amplitude.prototype.smooth = function (s) {
if (s >= 0 && s < 1) {
- this.smoothing = s;
+ this._workletNode.parameters.get('smoothing').value = s;
} else {
console.log('Error: smoothing must be between 0 and 1');
}
@@ -5672,13 +5679,15 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
delete this.output;
}
- delete this.processor;
+ this._workletNode.disconnect();
+
+ delete this._workletNode;
};
}).call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 40 */
+/* 42 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -6328,7 +6337,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 41 */
+/* 43 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -6505,21 +6514,21 @@ var __WEBPACK_AMD_DEFINE_RESULT__;
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
-/* 42 */
+/* 44 */
/***/ (function(module, exports, __webpack_require__) {
-var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(20)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){o.Frequency=function(e,t){if(!(this instanceof o.Frequency))return new o.Frequency(e,t);o.TimeBase.call(this,e,t)},o.extend(o.Frequency,o.TimeBase),o.Frequency.prototype._primaryExpressions=Object.create(o.TimeBase.prototype._primaryExpressions),o.Frequency.prototype._primaryExpressions.midi={regexp:/^(\d+(?:\.\d+)?midi)/,method:function(e){return this.midiToFrequency(e)}},o.Frequency.prototype._primaryExpressions.note={regexp:/^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,method:function(e,t){var r=n[e.toLowerCase()]+12*(parseInt(t)+1);return this.midiToFrequency(r)}},o.Frequency.prototype._primaryExpressions.tr={regexp:/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,method:function(e,t,r){var n=1;return e&&"0"!==e&&(n*=this._beatsToUnits(this._timeSignature()*parseFloat(e))),t&&"0"!==t&&(n*=this._beatsToUnits(parseFloat(t))),r&&"0"!==r&&(n*=this._beatsToUnits(parseFloat(r)/4)),n}},o.Frequency.prototype.transpose=function(e){return this._expr=function(e,t){return e()*this.intervalToFrequencyRatio(t)}.bind(this,this._expr,e),this},o.Frequency.prototype.harmonize=function(e){return this._expr=function(e,t){for(var r=e(),n=[],o=0;o 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\t/**\n\t\t * the output node(s)\n\t\t * @type {GainNode|Array}\n\t\t */\n\t\tif (this.isUndef(outputs) || outputs === 1){\n\t\t\tthis.output = this.context.createGain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t/**\n\t * Set the parameters at once. Either pass in an\n\t * object mapping parameters to values, or to set a\n\t * single parameter, by passing in a string and value.\n\t * The last argument is an optional ramp time which \n\t * will ramp any signal values to their destination value\n\t * over the duration of the rampTime.\n\t * @param {Object|string} params\n\t * @param {number=} value\n\t * @param {Time=} rampTime\n\t * @returns {Tone} this\n\t * @example\n\t * //set values using an object\n\t * filter.set({\n\t * \t\"frequency\" : 300,\n\t * \t\"type\" : highpass\n\t * });\n\t * @example\n\t * filter.set(\"type\", \"highpass\");\n\t * @example\n\t * //ramp to the value 220 over 3 seconds. \n\t * oscillator.set({\n\t * \t\"frequency\" : 220\n\t * }, 3);\n\t */\n\tTone.prototype.set = function(params, value, rampTime){\n\t\tif (this.isObject(params)){\n\t\t\trampTime = value;\n\t\t} else if (this.isString(params)){\n\t\t\tvar tmpObj = {};\n\t\t\ttmpObj[params] = value;\n\t\t\tparams = tmpObj;\n\t\t}\n\n\t\tparamLoop:\n\t\tfor (var attr in params){\n\t\t\tvalue = params[attr];\n\t\t\tvar parent = this;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var i = 0; i < attrSplit.length - 1; i++){\n\t\t\t\t\tparent = parent[attrSplit[i]];\n\t\t\t\t\tif (parent instanceof Tone) {\n\t\t\t\t\t\tattrSplit.splice(0,i+1);\n\t\t\t\t\t\tvar innerParam = attrSplit.join(\".\");\n\t\t\t\t\t\tparent.set(innerParam, value);\n\t\t\t\t\t\tcontinue paramLoop;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isUndef(param)){\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((Tone.Signal && param instanceof Tone.Signal) || \n\t\t\t\t\t(Tone.Param && param instanceof Tone.Param)){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tif (this.isUndef(rampTime)){\n\t\t\t\t\t\tparam.value = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparam.rampTo(value, rampTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tparam.value = value;\n\t\t\t\t}\t\t\t\t\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tparam.set(value);\n\t\t\t} else if (param !== value){\n\t\t\t\tparent[attr] = value;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the object's attributes. Given no arguments get\n\t * will return all available object properties and their corresponding\n\t * values. Pass in a single attribute to retrieve or an array\n\t * of attributes. The attribute strings can also include a \".\"\n\t * to access deeper properties.\n\t * @example\n\t * osc.get();\n\t * //returns {\"type\" : \"sine\", \"frequency\" : 440, ...etc}\n\t * @example\n\t * osc.get(\"type\");\n\t * //returns { \"type\" : \"sine\"}\n\t * @example\n\t * //use dot notation to access deep properties\n\t * synth.get([\"envelope.attack\", \"envelope.release\"]);\n\t * //returns {\"envelope\" : {\"attack\" : 0.2, \"release\" : 0.4}}\n\t * @param {Array=|string|undefined} params the parameters to get, otherwise will return \n\t * \t\t\t\t\t all available.\n\t * @returns {Object}\n\t */\n\tTone.prototype.get = function(params){\n\t\tif (this.isUndef(params)){\n\t\t\tparams = this._collectDefaults(this.constructor);\n\t\t} else if (this.isString(params)){\n\t\t\tparams = [params];\n\t\t} \n\t\tvar ret = {};\n\t\tfor (var i = 0; i < params.length; i++){\n\t\t\tvar attr = params[i];\n\t\t\tvar parent = this;\n\t\t\tvar subRet = ret;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var j = 0; j < attrSplit.length - 1; j++){\n\t\t\t\t\tvar subAttr = attrSplit[j];\n\t\t\t\t\tsubRet[subAttr] = subRet[subAttr] || {};\n\t\t\t\t\tsubRet = subRet[subAttr];\n\t\t\t\t\tparent = parent[subAttr];\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isObject(params[attr])){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (Tone.Signal && param instanceof Tone.Signal){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (Tone.Param && param instanceof Tone.Param){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (!this.isFunction(param) && !this.isUndef(param)){\n\t\t\t\tsubRet[attr] = param;\n\t\t\t} \n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * collect all of the default attributes in one\n\t * @private\n\t * @param {function} constr the constructor to find the defaults from\n\t * @return {Array} all of the attributes which belong to the class\n\t */\n\tTone.prototype._collectDefaults = function(constr){\n\t\tvar ret = [];\n\t\tif (!this.isUndef(constr.defaults)){\n\t\t\tret = Object.keys(constr.defaults);\n\t\t}\n\t\tif (!this.isUndef(constr._super)){\n\t\t\tvar superDefs = this._collectDefaults(constr._super);\n\t\t\t//filter out repeats\n\t\t\tfor (var i = 0; i < superDefs.length; i++){\n\t\t\t\tif (ret.indexOf(superDefs[i]) === -1){\n\t\t\t\t\tret.push(superDefs[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * @returns {string} returns the name of the class as a string\n\t */\n\tTone.prototype.toString = function(){\n\t\tfor (var className in Tone){\n\t\t\tvar isLetter = className[0].match(/^[A-Z]$/);\n\t\t\tvar sameConstructor = Tone[className] === this.constructor;\n\t\t\tif (this.isFunction(Tone[className]) && isLetter && sameConstructor){\n\t\t\t\treturn className;\n\t\t\t}\n\t\t}\n\t\treturn \"Tone\";\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCLASS VARS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The number of inputs feeding into the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfInputs\", {\n\t\tget : function(){\n\t\t\tif (this.input){\n\t\t\t\tif (this.isArray(this.input)){\n\t\t\t\t\treturn this.input.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The number of outputs coming out of the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfOutputs\", {\n\t\tget : function(){\n\t\t\tif (this.output){\n\t\t\t\tif (this.isArray(this.output)){\n\t\t\t\t\treturn this.output.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\t\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONNECTIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * disconnect and dispose\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.dispose = function(){\n\t\tif (!this.isUndef(this.input)){\n\t\t\tif (this.input instanceof AudioNode){\n\t\t\t\tthis.input.disconnect();\n\t\t\t} \n\t\t\tthis.input = null;\n\t\t}\n\t\tif (!this.isUndef(this.output)){\n\t\t\tif (this.output instanceof AudioNode){\n\t\t\t\tthis.output.disconnect();\n\t\t\t} \n\t\t\tthis.output = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode\n\t * @param {Tone | AudioParam | AudioNode} unit \n\t * @param {number} [outputNum=0] optionally which output to connect from\n\t * @param {number} [inputNum=0] optionally which input to connect to\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connect = function(unit, outputNum, inputNum){\n\t\tif (Array.isArray(this.output)){\n\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\tthis.output[outputNum].connect(unit, 0, inputNum);\n\t\t} else {\n\t\t\tthis.output.connect(unit, outputNum, inputNum);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * disconnect the output\n\t * @param {Number|AudioNode} output Either the output index to disconnect\n\t * if the output is an array, or the\n\t * node to disconnect from.\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.disconnect = function(destination, outputNum, inputNum){\n\t\tif (this.isArray(this.output)){\n\t\t\tif (this.isNumber(destination)){\n\t\t\t\tthis.output[destination].disconnect();\n\t\t\t} else {\n\t\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\t\tthis.output[outputNum].disconnect(destination, 0, inputNum);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.output.disconnect.apply(this.output, arguments);\n\t\t}\n\t};\n\n\t/**\n\t * connect together all of the arguments in series\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connectSeries = function(){\n\t\tif (arguments.length > 1){\n\t\t\tvar currentUnit = arguments[0];\n\t\t\tfor (var i = 1; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Connect the output of this node to the rest of the nodes in series.\n\t * @example\n\t * //connect a node to an effect, panVol and then to the master output\n\t * node.chain(effect, panVol, Tone.Master);\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.chain = function(){\n\t\tif (arguments.length > 0){\n\t\t\tvar currentUnit = this;\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of this node to the rest of the nodes in parallel.\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.fan = function(){\n\t\tif (arguments.length > 0){\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tthis.connect(arguments[i]);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t//give native nodes chain and fan methods\n\tAudioNode.prototype.chain = Tone.prototype.chain;\n\tAudioNode.prototype.fan = Tone.prototype.fan;\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUTILITIES / HELPERS / MATHS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * If the `given` parameter is undefined, use the `fallback`. \n\t * If both `given` and `fallback` are object literals, it will\n\t * return a deep copy which includes all of the parameters from both \n\t * objects. If a parameter is undefined in given, it will return\n\t * the fallback property. \n\t *
\n\t * WARNING: if object is self referential, it will go into an an \n\t * infinite recursive loop.\n\t * \n\t * @param {*} given \n\t * @param {*} fallback \n\t * @return {*} \n\t */\n\tTone.prototype.defaultArg = function(given, fallback){\n\t\tif (this.isObject(given) && this.isObject(fallback)){\n\t\t\tvar ret = {};\n\t\t\t//make a deep copy of the given object\n\t\t\tfor (var givenProp in given) {\n\t\t\t\tret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);\n\t\t\t}\n\t\t\tfor (var fallbackProp in fallback) {\n\t\t\t\tret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn this.isUndef(given) ? fallback : given;\n\t\t}\n\t};\n\n\t/**\n\t * returns the args as an options object with given arguments\n\t * mapped to the names provided. \n\t *\n\t * if the args given is an array containing only one object, it is assumed\n\t * that that's already the options object and will just return it. \n\t * \n\t * @param {Array} values the 'arguments' object of the function\n\t * @param {Array} keys the names of the arguments as they\n\t * should appear in the options object\n\t * @param {Object=} defaults optional defaults to mixin to the returned \n\t * options object \n\t * @return {Object} the options object with the names mapped to the arguments\n\t */\n\tTone.prototype.optionsObject = function(values, keys, defaults){\n\t\tvar options = {};\n\t\tif (values.length === 1 && this.isObject(values[0])){\n\t\t\toptions = values[0];\n\t\t} else {\n\t\t\tfor (var i = 0; i < keys.length; i++){\n\t\t\t\toptions[keys[i]] = values[i];\n\t\t\t}\n\t\t}\n\t\tif (!this.isUndef(defaults)){\n\t\t\treturn this.defaultArg(options, defaults);\n\t\t} else {\n\t\t\treturn options;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// TYPE CHECKING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * test if the arg is undefined\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is undefined\n\t * @function\n\t */\n\tTone.prototype.isUndef = function(val){\n\t\treturn typeof val === \"undefined\";\n\t};\n\n\t/**\n\t * test if the arg is a function\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a function\n\t * @function\n\t */\n\tTone.prototype.isFunction = function(val){\n\t\treturn typeof val === \"function\";\n\t};\n\n\t/**\n\t * Test if the argument is a number.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a number\n\t */\n\tTone.prototype.isNumber = function(arg){\n\t\treturn (typeof arg === \"number\");\n\t};\n\n\t/**\n\t * Test if the given argument is an object literal (i.e. `{}`);\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an object literal.\n\t */\n\tTone.prototype.isObject = function(arg){\n\t\treturn (Object.prototype.toString.call(arg) === \"[object Object]\" && arg.constructor === Object);\n\t};\n\n\t/**\n\t * Test if the argument is a boolean.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a boolean\n\t */\n\tTone.prototype.isBoolean = function(arg){\n\t\treturn (typeof arg === \"boolean\");\n\t};\n\n\t/**\n\t * Test if the argument is an Array\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an array\n\t */\n\tTone.prototype.isArray = function(arg){\n\t\treturn (Array.isArray(arg));\n\t};\n\n\t/**\n\t * Test if the argument is a string.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a string\n\t */\n\tTone.prototype.isString = function(arg){\n\t\treturn (typeof arg === \"string\");\n\t};\n\n \t/**\n\t * An empty function.\n\t * @static\n\t */\n\tTone.noOp = function(){};\n\n\t/**\n\t * Make the property not writable. Internal use only. \n\t * @private\n\t * @param {string} property the property to make not writable\n\t */\n\tTone.prototype._readOnly = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._readOnly(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: false,\n\t\t\t\tenumerable : true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Make an attribute writeable. Interal use only. \n\t * @private\n\t * @param {string} property the property to make writable\n\t */\n\tTone.prototype._writable = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._writable(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Possible play states. \n\t * @enum {string}\n\t */\n\tTone.State = {\n\t\tStarted : \"started\",\n\t\tStopped : \"stopped\",\n\t\tPaused : \"paused\",\n \t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Equal power gain scale. Good for cross-fading.\n\t * @param {NormalRange} percent (0-1)\n\t * @return {Number} output gain (0-1)\n\t */\n\tTone.prototype.equalPowerScale = function(percent){\n\t\tvar piFactor = 0.5 * Math.PI;\n\t\treturn Math.sin(percent * piFactor);\n\t};\n\n\t/**\n\t * Convert decibels into gain.\n\t * @param {Decibels} db\n\t * @return {Number} \n\t */\n\tTone.prototype.dbToGain = function(db) {\n\t\treturn Math.pow(2, db / 6);\n\t};\n\n\t/**\n\t * Convert gain to decibels.\n\t * @param {Number} gain (0-1)\n\t * @return {Decibels} \n\t */\n\tTone.prototype.gainToDb = function(gain) {\n\t\treturn 20 * (Math.log(gain) / Math.LN10);\n\t};\n\n\t/**\n\t * Convert an interval (in semitones) to a frequency ratio.\n\t * @param {Interval} interval the number of semitones above the base note\n\t * @return {number} the frequency ratio\n\t * @example\n\t * tone.intervalToFrequencyRatio(0); // 1\n\t * tone.intervalToFrequencyRatio(12); // 2\n\t * tone.intervalToFrequencyRatio(-12); // 0.5\n\t */\n\tTone.prototype.intervalToFrequencyRatio = function(interval){\n\t\treturn Math.pow(2,(interval/12));\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTIMING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t */\n\tTone.prototype.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t * @static\n\t */\n\tTone.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tINHERITANCE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * have a child inherit all of Tone's (or a parent's) prototype\n\t * to inherit the parent's properties, make sure to call \n\t * Parent.call(this) in the child's constructor\n\t *\n\t * based on closure library's inherit function\n\t *\n\t * @static\n\t * @param {function} \tchild \n\t * @param {function=} parent (optional) parent to inherit from\n\t * if no parent is supplied, the child\n\t * will inherit from Tone\n\t */\n\tTone.extend = function(child, parent){\n\t\tif (Tone.prototype.isUndef(parent)){\n\t\t\tparent = Tone;\n\t\t}\n\t\tfunction TempConstructor(){}\n\t\tTempConstructor.prototype = parent.prototype;\n\t\tchild.prototype = new TempConstructor();\n\t\t/** @override */\n\t\tchild.prototype.constructor = child;\n\t\tchild._super = parent;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONTEXT\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The private audio context shared by all Tone Nodes. \n\t * @private\n\t * @type {Tone.Context|undefined}\n\t */\n\tvar audioContext;\n\n\t/**\n\t * A static pointer to the audio context accessible as Tone.context. \n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone\n\t */\n\tObject.defineProperty(Tone, \"context\", {\n\t\tget : function(){\n\t\t\treturn audioContext;\n\t\t},\n\t\tset : function(context){\n\t\t\tif (Tone.Context && context instanceof Tone.Context){\n\t\t\t\taudioContext = context;\n\t\t\t} else {\n\t\t\t\taudioContext = new Tone.Context(context);\n\t\t\t}\n\t\t\t//initialize the new audio context\n\t\t\tif (Tone.Context){\n\t\t\t\tTone.Context.emit(\"init\", audioContext);\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The AudioContext\n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"context\", {\n\t\tget : function(){\n\t\t\treturn Tone.context;\n\t\t}\n\t});\n\n\t/**\n\t * Tone automatically creates a context on init, but if you are working\n\t * with other libraries which also create an AudioContext, it can be\n\t * useful to set your own. If you are going to set your own context, \n\t * be sure to do it at the start of your code, before creating any objects.\n\t * @static\n\t * @param {AudioContext} ctx The new audio context to set\n\t */\n\tTone.setContext = function(ctx){\n\t\tTone.context = ctx;\n\t};\n\n\t/**\n\t * The number of seconds of 1 processing block (128 samples)\n\t * @type {Number}\n\t * @name blockTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"blockTime\", {\n\t\tget : function(){\n\t\t\treturn 128 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * The duration in seconds of one sample.\n\t * @type {Number}\n\t * @name sampleTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"sampleTime\", {\n\t\tget : function(){\n\t\t\treturn 1 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * Whether or not all the technologies that Tone.js relies on are supported by the current browser. \n\t * @type {Boolean}\n\t * @name supported\n\t * @memberOf Tone\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone, \"supported\", {\n\t\tget : function(){\n\t\t\tvar hasAudioContext = window.hasOwnProperty(\"AudioContext\") || window.hasOwnProperty(\"webkitAudioContext\");\n\t\t\tvar hasPromises = window.hasOwnProperty(\"Promise\");\n\t\t\tvar hasWorkers = window.hasOwnProperty(\"Worker\");\n\t\t\treturn hasAudioContext && hasPromises && hasWorkers;\n\t\t}\n\t});\n\n\tTone.version = \"r10\";\n\n\t// allow optional silencing of this log\n\tif (!window.TONE_SILENCE_VERSION_LOGGING) {\n\t\tconsole.log(\"%c * Tone.js \" + Tone.version + \" * \", \"background: #000; color: #fff\");\n\t}\n\n\treturn Tone;\n});\n","'use strict';\r\n\r\n\r\ndefine(['audiocontext'], function (audiocontext) {\r\n /**\r\n * Master contains AudioContext and the master sound output.\r\n * @for p5\r\n */\r\n var Master = function() {\r\n this.input = audiocontext.createGain();\r\n this.output = audiocontext.createGain();\r\n\r\n //put a hard limiter on the output\r\n this.limiter = audiocontext.createDynamicsCompressor();\r\n this.limiter.threshold.value = -3;\r\n this.limiter.ratio.value = 20;\r\n this.limiter.knee.value = 1;\r\n\r\n this.audiocontext = audiocontext;\r\n\r\n this.output.disconnect();\r\n\r\n // connect input to limiter\r\n this.input.connect(this.limiter);\r\n\r\n // connect limiter to output\r\n this.limiter.connect(this.output);\r\n\r\n // meter is just for global Amplitude / FFT analysis\r\n this.meter = audiocontext.createGain();\r\n this.fftMeter = audiocontext.createGain();\r\n this.output.connect(this.meter);\r\n this.output.connect(this.fftMeter);\r\n\r\n // connect output to destination\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // an array of all sounds in the sketch\r\n this.soundArray = [];\r\n // an array of all musical parts in the sketch\r\n this.parts = [];\r\n\r\n // file extensions to search for\r\n this.extensions = [];\r\n };\r\n\r\n // create a single instance of the p5Sound / master output for use within this sketch\r\n var p5sound = new Master();\r\n\r\n /**\r\n * Returns a number representing the master amplitude (volume) for sound\r\n * in this sketch.\r\n *\r\n * @method getMasterVolume\r\n * @return {Number} Master amplitude (volume) for sound in this sketch.\r\n * Should be between 0.0 (silence) and 1.0.\r\n */\r\n p5.prototype.getMasterVolume = function() {\r\n return p5sound.output.gain.value;\r\n };\r\n\r\n /**\r\n *
Scale the output of all sound in this sketch
\r\n * Scaled between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n *
How This Works: When you load the p5.sound module, it\r\n * creates a single instance of p5sound. All sound objects in this\r\n * module output to p5sound before reaching your computer's output.\r\n * So if you change the amplitude of p5sound, it impacts all of the\r\n * sound in this module.
\r\n *\r\n *
If no value is provided, returns a Web Audio API Gain Node
\r\n *\r\n * @method masterVolume\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.prototype.masterVolume = function(vol, rampTime, tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = p5sound.output.gain.value;\r\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(p5sound.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return p5sound.output.gain;\r\n }\r\n };\r\n\r\n /**\r\n * `p5.soundOut` is the p5.sound master output. It sends output to\r\n * the destination of this window's web audio context. It contains\r\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\r\n * and Gain Nodes for .input and .output.\r\n *\r\n * @property {Object} soundOut\r\n */\r\n p5.prototype.soundOut = p5.soundOut = p5sound;\r\n\r\n /**\r\n * a silent connection to the DesinationNode\r\n * which will ensure that anything connected to it\r\n * will not be garbage collected\r\n *\r\n * @private\r\n */\r\n p5.soundOut._silentNode = p5sound.audiocontext.createGain();\r\n p5.soundOut._silentNode.gain.value = 0;\r\n p5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\r\n\r\n\r\n return p5sound;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/type/Type\", \"Tone/core/Param\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal is an audio-rate value. Tone.Signal is a core component of the library.\n\t * Unlike a number, Signals can be scheduled with sample-level accuracy. Tone.Signal\n\t * has all of the methods available to native Web Audio \n\t * [AudioParam](http://webaudio.github.io/web-audio-api/#the-audioparam-interface)\n\t * as well as additional conveniences. Read more about working with signals \n\t * [here](https://github.com/Tonejs/Tone.js/wiki/Signals).\n\t *\n\t * @constructor\n\t * @extends {Tone.Param}\n\t * @param {Number|AudioParam} [value] Initial value of the signal. If an AudioParam\n\t * is passed in, that parameter will be wrapped\n\t * and controlled by the Signal. \n\t * @param {string} [units=Number] unit The units the signal is in. \n\t * @example\n\t * var signal = new Tone.Signal(10);\n\t */\n\tTone.Signal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\n\t\t/**\n\t\t * The node where the constant signal value is scaled.\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.output = this._gain = this.context.createGain();\n\n\t\toptions.param = this._gain.gain;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The node where the value is set.\n\t\t * @type {Tone.Param}\n\t\t * @private\n\t\t */\n\t\tthis.input = this._param = this._gain.gain;\n\n\t\t//connect the const output to the node output\n\t\tthis.context.getConstant(1).chain(this._gain);\n\t};\n\n\tTone.extend(Tone.Signal, Tone.Param);\n\n\t/**\n\t * The default values\n\t * @type {Object}\n\t * @static\n\t * @const\n\t */\n\tTone.Signal.defaults = {\n\t\t\"value\" : 0,\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t * @method\n\t */\n\tTone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\t/**\n\t * dispose and disconnect\n\t * @returns {Tone.Signal} this\n\t */\n\tTone.Signal.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tthis._gain.disconnect();\n\t\tthis._gain = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Signal;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Multiply two incoming signals. Or, if a number is given in the constructor, \n\t * multiplies the incoming signal by that value. \n\t *\n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value Constant value to multiple. If no value is provided,\n\t * it will return the product of the first and second inputs\n\t * @example\n\t * var mult = new Tone.Multiply();\n\t * var sigA = new Tone.Signal(3);\n\t * var sigB = new Tone.Signal(4);\n\t * sigA.connect(mult, 0, 0);\n\t * sigB.connect(mult, 0, 1);\n\t * //output of mult is 12.\n\t * @example\n\t * var mult = new Tone.Multiply(10);\n\t * var sig = new Tone.Signal(2).connect(mult);\n\t * //the output of mult is 20. \n\t */\n\tTone.Multiply = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the input node is the same as the output node\n\t\t * it is also the GainNode which handles the scaling of incoming signal\n\t\t * \n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._mult = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * the scaling parameter\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[1] = this.output.gain;\n\t\t\n\t\tthis._param.value = this.defaultArg(value, 0);\n\t};\n\n\tTone.extend(Tone.Multiply, Tone.Signal);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Multiply} this\n\t */\n\tTone.Multiply.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._mult.dispose();\n\t\tthis._mult = null;\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Multiply;\n});\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var CrossFade = require('Tone/component/CrossFade');\r\n\r\n /**\r\n * Effect is a base class for audio effects in p5. \r\n * This module handles the nodes and methods that are\r\n * common and useful for current and future effects.\r\n *\r\n *\r\n * This class is extended by p5.Distortion,\r\n * p5.Compressor,\r\n * p5.Delay,\r\n * p5.Filter,\r\n * p5.Reverb.\r\n *\r\n * @class p5.Effect\r\n * @constructor\r\n *\r\n * @param {Object} [ac] Reference to the audio context of the p5 object\r\n * @param {AudioNode} [input] Gain Node effect wrapper\r\n * @param {AudioNode} [output] Gain Node effect wrapper\r\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\r\n * @param {AudioNode} [wet] Effects that extend this class should connect\r\n * to the wet signal to this gain node, so that dry and wet\r\n * signals are mixed properly.\r\n */\r\n p5.Effect = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n /**\r\n *\tThe p5.Effect class is built\r\n * \tusing Tone.js CrossFade\r\n * \t@private\r\n */\r\n\r\n this._drywet = new CrossFade(1);\r\n\r\n /**\r\n *\tIn classes that extend\r\n *\tp5.Effect, connect effect nodes\r\n *\tto the wet parameter\r\n */\r\n this.wet = this.ac.createGain();\r\n\r\n this.input.connect(this._drywet.a);\r\n this.wet.connect(this._drywet.b);\r\n this._drywet.connect(this.output);\r\n\r\n this.connect();\r\n\r\n //Add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the output volume of the filter.\r\n *\r\n * @method amp\r\n * @for p5.Effect\r\n * @param {Number} [vol] amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts until rampTime\r\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\r\n */\r\n p5.Effect.prototype.amp = function(vol, rampTime, tFromNow){\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + .001);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + .001);\r\n };\r\n\r\n /**\r\n * Link effects together in a chain\r\n * Example usage: filter.chain(reverb, delay, panner);\r\n * May be used with an open-ended number of arguments\r\n *\r\n * @method chain\r\n * @for p5.Effect\r\n * @param {Object} [arguments] Chain together multiple sound objects\r\n */\r\n p5.Effect.prototype.chain = function(){\r\n if (arguments.length>0){\r\n this.connect(arguments[0]);\r\n for(var i=1;i\r\n * var notes = [60, 64, 67, 72];\r\n * var i = 0;\r\n *\r\n * function setup() {\r\n * osc = new p5.Oscillator('Triangle');\r\n * osc.start();\r\n * frameRate(1);\r\n * }\r\n *\r\n * function draw() {\r\n * var freq = midiToFreq(notes[i]);\r\n * osc.freq(freq);\r\n * i++;\r\n * if (i >= notes.length){\r\n * i = 0;\r\n * }\r\n * }\r\n * \r\n */\r\n var midiToFreq = p5.prototype.midiToFreq = function(m) {\r\n return 440 * Math.pow(2, (m-69)/12.0);\r\n };\r\n\r\n // This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\r\n var noteToFreq = function(note) {\r\n if (typeof note !== 'string') {\r\n return note;\r\n }\r\n var wholeNotes = {A:21, B:23, C:24, D:26, E:28, F:29, G:31};\r\n var value = wholeNotes[ note[0].toUpperCase() ];\r\n var octave = ~~note.slice(-1);\r\n value += 12 * (octave -1);\r\n\r\n switch(note[1]) {\r\n case '#':\r\n value += 1;\r\n break;\r\n case 'b':\r\n value -= 1;\r\n break;\r\n default:\r\n break;\r\n }\r\n return midiToFreq(value);\r\n };\r\n\r\n /**\r\n * List the SoundFile formats that you will include. LoadSound\r\n * will search your directory for these extensions, and will pick\r\n * a format that is compatable with the client's web browser.\r\n * Here is a free online file\r\n * converter.\r\n *\r\n * @method soundFormats\r\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\r\n * @example\r\n *
\r\n * function preload() {\r\n * // set the global sound formats\r\n * soundFormats('mp3', 'ogg');\r\n *\r\n * // load either beatbox.mp3, or .ogg, depending on browser\r\n * mySound = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * mySound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.soundFormats = function() {\r\n // reset extensions array\r\n p5sound.extensions = [];\r\n // add extensions\r\n for (var i = 0; i < arguments.length; i++) {\r\n arguments[i] = arguments[i].toLowerCase();\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\r\n p5sound.extensions.push(arguments[i]);\r\n } else {\r\n throw arguments[i] + ' is not a valid sound format!';\r\n }\r\n }\r\n };\r\n\r\n p5.prototype.disposeSound = function() {\r\n for (var i = 0; i < p5sound.soundArray.length; i++) {\r\n p5sound.soundArray[i].dispose();\r\n }\r\n };\r\n\r\n // register removeSound to dispose of p5sound SoundFiles, Convolvers,\r\n // Oscillators etc when sketch ends\r\n p5.prototype.registerMethod('remove', p5.prototype.disposeSound);\r\n\r\n p5.prototype._checkFileFormats = function(paths) {\r\n var path;\r\n // if path is a single string, check to see if extension is provided\r\n if (typeof paths === 'string') {\r\n path = paths;\r\n // see if extension is provided\r\n var extTest = path.split('.').pop();\r\n // if an extension is provided...\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\r\n if (p5.prototype.isFileSupported(extTest)) {\r\n path = path;\r\n }\r\n else {\r\n var pathSplit = path.split('.');\r\n var pathCore = pathSplit[pathSplit.length - 1];\r\n for (var i = 0; i 1) {\r\n rightChannel = audioBuffer.getChannelData(1);\r\n } else {\r\n rightChannel = leftChannel;\r\n }\r\n\r\n var interleaved = interleave(leftChannel, rightChannel);\r\n\r\n // create the buffer and view to create the .WAV file\r\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\r\n var view = new window.DataView(buffer);\r\n\r\n // write the WAV container,\r\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\r\n\r\n // RIFF chunk descriptor\r\n writeUTFBytes(view, 0, 'RIFF');\r\n view.setUint32(4, 36 + interleaved.length * 2, true);\r\n writeUTFBytes(view, 8, 'WAVE');\r\n // FMT sub-chunk\r\n writeUTFBytes(view, 12, 'fmt ');\r\n view.setUint32(16, 16, true);\r\n view.setUint16(20, 1, true);\r\n // stereo (2 channels)\r\n view.setUint16(22, 2, true);\r\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\r\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\r\n view.setUint16(32, 4, true);\r\n view.setUint16(34, 16, true);\r\n // data sub-chunk\r\n writeUTFBytes(view, 36, 'data');\r\n view.setUint32(40, interleaved.length * 2, true);\r\n\r\n // write the PCM samples\r\n var lng = interleaved.length;\r\n var index = 44;\r\n var volume = 1;\r\n for (var i = 0; i < lng; i++) {\r\n view.setInt16(index, interleaved[i] * (0x7FFF * volume), true);\r\n index += 2;\r\n }\r\n\r\n return view;\r\n }\r\n\r\n // helper methods to save waves\r\n function interleave(leftChannel, rightChannel) {\r\n var length = leftChannel.length + rightChannel.length;\r\n var result = new Float32Array(length);\r\n\r\n var inputIndex = 0;\r\n\r\n for (var index = 0; index < length;) {\r\n result[index++] = leftChannel[inputIndex];\r\n result[index++] = rightChannel[inputIndex];\r\n inputIndex++;\r\n }\r\n return result;\r\n }\r\n\r\n function writeUTFBytes(view, offset, string) {\r\n var lng = string.length;\r\n for (var i = 0; i < lng; i++) {\r\n view.setUint8(offset + i, string.charCodeAt(i));\r\n }\r\n }\r\n\r\n return {\r\n convertToWav: convertToWav,\r\n midiToFreq: midiToFreq,\r\n noteToFreq: noteToFreq\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Add a signal and a number or two signals. When no value is\n\t * passed into the constructor, Tone.Add will sum input[0]\n\t * and input[1]. If a value is passed into the constructor, \n\t * the it will be added to the input.\n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value If no value is provided, Tone.Add will sum the first\n\t * and second inputs. \n\t * @example\n\t * var signal = new Tone.Signal(2);\n\t * var add = new Tone.Add(2);\n\t * signal.connect(add);\n\t * //the output of add equals 4\n\t * @example\n\t * //if constructed with no arguments\n\t * //it will add the first and second inputs\n\t * var add = new Tone.Add();\n\t * var sig0 = new Tone.Signal(3).connect(add, 0, 0);\n\t * var sig1 = new Tone.Signal(4).connect(add, 0, 1);\n\t * //the output of add equals 7. \n\t */\n\tTone.Add = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.connect(this._sum);\n\t};\n\n\tTone.extend(Tone.Add, Tone.Signal);\n\t\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Add} this\n\t */\n\tTone.Add.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._sum.dispose();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Add;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\", \"Tone/type/Frequency\", \"Tone/type/TransportTime\", \"Tone/core/Context\"],\nfunction (Tone) {\t\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTYPES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Units which a value can take on.\n\t * @enum {String}\n\t */\n\tTone.Type = {\n\t\t/** \n\t\t * Default units\n\t\t * @typedef {Default}\n\t\t */\n\t\tDefault : \"number\",\n\t\t/**\n\t\t * Time can be described in a number of ways. Read more [Time](https://github.com/Tonejs/Tone.js/wiki/Time).\n\t\t *\n\t\t *
\n\t\t *
Numbers, which will be taken literally as the time (in seconds).
\n\t\t *
Notation, (\"4n\", \"8t\") describes time in BPM and time signature relative values.
\n\t\t *
TransportTime, (\"4:3:2\") will also provide tempo and time signature relative times \n\t\t * in the form BARS:QUARTERS:SIXTEENTHS.
\n\t\t *
Frequency, (\"8hz\") is converted to the length of the cycle in seconds.
\n\t\t *
Now-Relative, (\"+1\") prefix any of the above with \"+\" and it will be interpreted as \n\t\t * \"the current time plus whatever expression follows\".
\n\t\t *
Expressions, (\"3:0 + 2 - (1m / 7)\") any of the above can also be combined \n\t\t * into a mathematical expression which will be evaluated to compute the desired time.
\n\t\t *
No Argument, for methods which accept time, no argument will be interpreted as \n\t\t * \"now\" (i.e. the currentTime).
\n\t\t *
\n\t\t * \n\t\t * @typedef {Time}\n\t\t */\n\t\tTime : \"time\",\n\t\t/**\n\t\t * Frequency can be described similar to time, except ultimately the\n\t\t * values are converted to frequency instead of seconds. A number\n\t\t * is taken literally as the value in hertz. Additionally any of the \n\t\t * Time encodings can be used. Note names in the form\n\t\t * of NOTE OCTAVE (i.e. C4) are also accepted and converted to their\n\t\t * frequency value. \n\t\t * @typedef {Frequency}\n\t\t */\n\t\tFrequency : \"frequency\",\n\t\t/**\n\t\t * TransportTime describes a position along the Transport's timeline. It is\n\t\t * similar to Time in that it uses all the same encodings, but TransportTime specifically\n\t\t * pertains to the Transport's timeline, which is startable, stoppable, loopable, and seekable. \n\t\t * [Read more](https://github.com/Tonejs/Tone.js/wiki/TransportTime)\n\t\t * @typedef {TransportTime}\n\t\t */\n\t\tTransportTime : \"transportTime\",\n\t\t/** \n\t\t * Ticks are the basic subunit of the Transport. They are\n\t\t * the smallest unit of time that the Transport supports.\n\t\t * @typedef {Ticks}\n\t\t */\n\t\tTicks : \"ticks\",\n\t\t/** \n\t\t * Normal values are within the range [0, 1].\n\t\t * @typedef {NormalRange}\n\t\t */\n\t\tNormalRange : \"normalRange\",\n\t\t/** \n\t\t * AudioRange values are between [-1, 1].\n\t\t * @typedef {AudioRange}\n\t\t */\n\t\tAudioRange : \"audioRange\",\n\t\t/** \n\t\t * Decibels are a logarithmic unit of measurement which is useful for volume\n\t\t * because of the logarithmic way that we perceive loudness. 0 decibels \n\t\t * means no change in volume. -10db is approximately half as loud and 10db \n\t\t * is twice is loud. \n\t\t * @typedef {Decibels}\n\t\t */\n\t\tDecibels : \"db\",\n\t\t/** \n\t\t * Half-step note increments, i.e. 12 is an octave above the root. and 1 is a half-step up.\n\t\t * @typedef {Interval}\n\t\t */\n\t\tInterval : \"interval\",\n\t\t/** \n\t\t * Beats per minute. \n\t\t * @typedef {BPM}\n\t\t */\n\t\tBPM : \"bpm\",\n\t\t/** \n\t\t * The value must be greater than or equal to 0.\n\t\t * @typedef {Positive}\n\t\t */\n\t\tPositive : \"positive\",\n\t\t/** \n\t\t * A cent is a hundredth of a semitone. \n\t\t * @typedef {Cents}\n\t\t */\n\t\tCents : \"cents\",\n\t\t/** \n\t\t * Angle between 0 and 360. \n\t\t * @typedef {Degrees}\n\t\t */\n\t\tDegrees : \"degrees\",\n\t\t/** \n\t\t * A number representing a midi note.\n\t\t * @typedef {MIDI}\n\t\t */\n\t\tMIDI : \"midi\",\n\t\t/** \n\t\t * A colon-separated representation of time in the form of\n\t\t * Bars:Beats:Sixteenths. \n\t\t * @typedef {BarsBeatsSixteenths}\n\t\t */\n\t\tBarsBeatsSixteenths : \"barsBeatsSixteenths\",\n\t\t/** \n\t\t * Sampling is the reduction of a continuous signal to a discrete signal.\n\t\t * Audio is typically sampled 44100 times per second. \n\t\t * @typedef {Samples}\n\t\t */\n\t\tSamples : \"samples\",\n\t\t/** \n\t\t * Hertz are a frequency representation defined as one cycle per second.\n\t\t * @typedef {Hertz}\n\t\t */\n\t\tHertz : \"hertz\",\n\t\t/** \n\t\t * A frequency represented by a letter name, \n\t\t * accidental and octave. This system is known as\n\t\t * [Scientific Pitch Notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation).\n\t\t * @typedef {Note}\n\t\t */\n\t\tNote : \"note\",\n\t\t/** \n\t\t * One millisecond is a thousandth of a second. \n\t\t * @typedef {Milliseconds}\n\t\t */\n\t\tMilliseconds : \"milliseconds\",\n\t\t/** \n\t\t * Seconds are the time unit of the AudioContext. In the end, \n\t\t * all values need to be evaluated to seconds. \n\t\t * @typedef {Seconds}\n\t\t */\n\t\tSeconds : \"seconds\",\n\t\t/** \n\t\t * A string representing a duration relative to a measure. \n\t\t *
\n\t\t * \t
\"4n\" = quarter note
\n\t\t * \t
\"2m\" = two measures
\n\t\t * \t
\"8t\" = eighth-note triplet
\n\t\t *
\n\t\t * @typedef {Notation}\n\t\t */\n\t\tNotation : \"notation\",\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// AUGMENT TONE's PROTOTYPE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert Time into seconds.\n\t * \n\t * Unlike the method which it overrides, this takes into account \n\t * transporttime and musical notation.\n\t *\n\t * Time : 1.40\n\t * Notation: 4n|1m|2t\n\t * Now Relative: +3n\n\t * Math: 3n+16n or even complicated expressions ((3n*2)/6 + 1)\n\t *\n\t * @param {Time} time \n\t * @return {Seconds} \n\t */\n\tTone.prototype.toSeconds = function(time){\n\t\tif (this.isNumber(time)){\n\t\t\treturn time;\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn this.now();\t\t\t\n\t\t} else if (this.isString(time)){\n\t\t\treturn (new Tone.Time(time)).toSeconds();\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toSeconds();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a frequency representation into a number.\n\t * @param {Frequency} freq \n\t * @return {Hertz} the frequency in hertz\n\t */\n\tTone.prototype.toFrequency = function(freq){\n\t\tif (this.isNumber(freq)){\n\t\t\treturn freq;\n\t\t} else if (this.isString(freq) || this.isUndef(freq)){\n\t\t\treturn (new Tone.Frequency(freq)).valueOf();\n\t\t} else if (freq instanceof Tone.TimeBase){\n\t\t\treturn freq.toFrequency();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a time representation into ticks.\n\t * @param {Time} time\n\t * @return {Ticks} the time in ticks\n\t */\n\tTone.prototype.toTicks = function(time){\n\t\tif (this.isNumber(time) || this.isString(time)){\n\t\t\treturn (new Tone.TransportTime(time)).toTicks();\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn Tone.Transport.ticks;\t\t\t\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toTicks();\n\t\t}\n\t};\n\n\treturn Tone;\n});","define([\"Tone/core/Tone\", \"Tone/core/Param\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * createGain shim\n\t * @private\n\t */\n\tif (window.GainNode && !AudioContext.prototype.createGain){\n\t\tAudioContext.prototype.createGain = AudioContext.prototype.createGainNode;\n\t}\n\n\t/**\n\t * @class A thin wrapper around the Native Web Audio GainNode.\n\t * The GainNode is a basic building block of the Web Audio\n\t * API and is useful for routing audio and adjusting gains. \n\t * @extends {Tone}\n\t * @param {Number=} gain The initial gain of the GainNode\n\t * @param {Tone.Type=} units The units of the gain parameter. \n\t */\n\tTone.Gain = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"gain\", \"units\"], Tone.Gain.defaults);\n\n\t\t/**\n\t\t * The GainNode\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.input = this.output = this._gainNode = this.context.createGain();\n\n\t\t/**\n\t\t * The gain parameter of the gain node.\n\t\t * @type {Tone.Param}\n\t\t * @signal\n\t\t */\n\t\tthis.gain = new Tone.Param({\n\t\t\t\"param\" : this._gainNode.gain, \n\t\t\t\"units\" : options.units,\n\t\t\t\"value\" : options.gain,\n\t\t\t\"convert\" : options.convert\n\t\t});\n\t\tthis._readOnly(\"gain\");\n\t};\n\n\tTone.extend(Tone.Gain);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Gain.defaults = {\n\t\t\"gain\" : 1,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Gain} this\n\t */\n\tTone.Gain.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._gainNode.disconnect();\n\t\tthis._gainNode = null;\n\t\tthis._writable(\"gain\");\n\t\tthis.gain.dispose();\n\t\tthis.gain = null;\n\t};\n\n\t//STATIC///////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Create input and outputs for this object.\n\t * @param {Number} input The number of inputs\n\t * @param {Number=} outputs The number of outputs\n\t * @return {Tone} this\n\t * @internal\n\t */\n\tTone.prototype.createInsOuts = function(inputs, outputs){\n\n\t\tif (inputs === 1){\n\t\t\tthis.input = new Tone.Gain();\n\t\t} else if (inputs > 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\tif (outputs === 1){\n\t\t\tthis.output = new Tone.Gain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\n\treturn Tone.Gain;\n});","'use strict';\r\n\r\ndefine(function () {\r\n /*\r\n Helper function to generate an error\r\n with a custom stack trace that points to the sketch\r\n and removes other parts of the stack trace.\r\n\r\n @private\r\n @class customError\r\n @constructor\r\n @param {String} name custom error name\r\n @param {String} errorTrace custom error trace\r\n @param {String} failedPath path to the file that failed to load\r\n @property {String} name custom error name\r\n @property {String} message custom error message\r\n @property {String} stack trace the error back to a line in the user's sketch.\r\n Note: this edits out stack trace within p5.js and p5.sound.\r\n @property {String} originalStack unedited, original stack trace\r\n @property {String} failedPath path to the file that failed to load\r\n @return {Error} returns a custom Error object\r\n */\r\n var CustomError = function(name, errorTrace, failedPath) {\r\n var err = new Error();\r\n var tempStack, splitStack;\r\n\r\n err.name = name;\r\n err.originalStack = err.stack + errorTrace;\r\n tempStack = err.stack + errorTrace;\r\n err.failedPath = failedPath;\r\n\r\n // only print the part of the stack trace that refers to the user code:\r\n var splitStack = tempStack.split('\\n');\r\n splitStack = splitStack.filter(function(ln) {\r\n return !ln.match(/(p5.|native code|globalInit)/g);\r\n });\r\n err.stack = splitStack.join('\\n');\r\n\r\n return err; // TODO: is this really a constructor?\r\n };\r\n\r\n return CustomError;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Emitter\"], function (Tone) {\n\n\t/**\n\t * shim\n\t * @private\n\t */\n\tif (!window.hasOwnProperty(\"AudioContext\") && window.hasOwnProperty(\"webkitAudioContext\")){\n\t\twindow.AudioContext = window.webkitAudioContext;\n\t}\n\n\t/**\n\t * @class Wrapper around the native AudioContext.\n\t * @extends {Tone.Emitter}\n\t * @param {AudioContext=} context optionally pass in a context\n\t */\n\tTone.Context = function(context){\n\n\t\tTone.Emitter.call(this);\n\n\t\tif (!context){\n\t\t\tcontext = new window.AudioContext();\n\t\t}\n\t\tthis._context = context;\n\t\t// extend all of the methods\n\t\tfor (var prop in this._context){\n\t\t\tthis._defineProperty(this._context, prop);\n\t\t}\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// WORKER\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\t/**\n\t\t * The default latency hint\n\t\t * @type {String}\n\t\t * @private\n\t\t */\n\t\tthis._latencyHint = \"interactive\";\n\n\t\t/**\n\t\t * The amount of time events are scheduled\n\t\t * into the future\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._lookAhead = 0.1;\n\n\t\t/**\n\t\t * How often the update look runs\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._updateInterval = this._lookAhead/3;\n\n\t\t/**\n\t\t * A reference to the actual computed update interval\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._computedUpdateInterval = 0;\n\n\t\t/**\n\t\t * The web worker which is used to update Tone.Clock\n\t\t * @private\n\t\t * @type {WebWorker}\n\t\t */\n\t\tthis._worker = this._createWorker();\n\n\t\t/**\n\t\t * An object containing all of the constants AudioBufferSourceNodes\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t\tthis._constants = {};\n\n\t};\n\n\tTone.extend(Tone.Context, Tone.Emitter);\n\tTone.Emitter.mixin(Tone.Context);\n\n\t/**\n\t * Define a property on this Tone.Context. \n\t * This is used to extend the native AudioContext\n\t * @param {AudioContext} context\n\t * @param {String} prop \n\t * @private\n\t */\n\tTone.Context.prototype._defineProperty = function(context, prop){\n\t\tif (this.isUndef(this[prop])){\n\t\t\tObject.defineProperty(this, prop, {\n\t\t\t\tget : function(){\n\t\t\t\t\tif (typeof context[prop] === \"function\"){\n\t\t\t\t\t\treturn context[prop].bind(context);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn context[prop];\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tset : function(val){\n\t\t\t\t\tcontext[prop] = val;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * The current audio context time\n\t * @return {Number}\n\t */\n\tTone.Context.prototype.now = function(){\n\t\treturn this._context.currentTime;\n\t};\n\n\t/**\n\t * Generate a web worker\n\t * @return {WebWorker}\n\t * @private\n\t */\n\tTone.Context.prototype._createWorker = function(){\n\t\t\n\t\t//URL Shim\n\t\twindow.URL = window.URL || window.webkitURL;\n\n\t\tvar blob = new Blob([\n\t\t\t//the initial timeout time\n\t\t\t\"var timeoutTime = \"+(this._updateInterval * 1000).toFixed(1)+\";\" +\n\t\t\t//onmessage callback\n\t\t\t\"self.onmessage = function(msg){\" +\n\t\t\t\"\ttimeoutTime = parseInt(msg.data);\" + \n\t\t\t\"};\" + \n\t\t\t//the tick function which posts a message\n\t\t\t//and schedules a new tick\n\t\t\t\"function tick(){\" +\n\t\t\t\"\tsetTimeout(tick, timeoutTime);\" +\n\t\t\t\"\tself.postMessage('tick');\" +\n\t\t\t\"}\" +\n\t\t\t//call tick initially\n\t\t\t\"tick();\"\n\t\t]);\n\t\tvar blobUrl = URL.createObjectURL(blob);\n\t\tvar worker = new Worker(blobUrl);\n\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\t// tick the clock\n\t\t\tthis.emit(\"tick\");\n\t\t}.bind(this));\n\n\t\t//lag compensation\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\tvar now = this.now();\n\t\t\tif (this.isNumber(this._lastUpdate)){\n\t\t\t\tvar diff = now - this._lastUpdate;\n\t\t\t\tthis._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);\n\t\t\t}\n\t\t\tthis._lastUpdate = now;\n\t\t}.bind(this));\n\n\t\treturn worker;\n\t};\n\n\t/**\n\t * Generate a looped buffer at some constant value.\n\t * @param {Number} val\n\t * @return {BufferSourceNode}\n\t */\n\tTone.Context.prototype.getConstant = function(val){\n\t\tif (this._constants[val]){\n\t\t\treturn this._constants[val];\n\t\t} else {\n\t\t\tvar buffer = this._context.createBuffer(1, 128, this._context.sampleRate);\n\t\t\tvar arr = buffer.getChannelData(0);\n\t\t\tfor (var i = 0; i < arr.length; i++){\n\t\t\t\tarr[i] = val;\n\t\t\t}\n\t\t\tvar constant = this._context.createBufferSource();\n\t\t\tconstant.channelCount = 1;\n\t\t\tconstant.channelCountMode = \"explicit\";\n\t\t\tconstant.buffer = buffer;\n\t\t\tconstant.loop = true;\n\t\t\tconstant.start(0);\n\t\t\tthis._constants[val] = constant;\n\t\t\treturn constant;\n\t\t}\n\t};\n\n\t/**\n\t * This is the time that the clock is falling behind\n\t * the scheduled update interval. The Context automatically\n\t * adjusts for the lag and schedules further in advance.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lag\n\t * @static\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lag\", {\n\t\tget : function(){\n\t\t\tvar diff = this._computedUpdateInterval - this._updateInterval;\n\t\t\tdiff = Math.max(diff, 0);\n\t\t\treturn diff;\n\t\t}\n\t});\n\n\t/**\n\t * The amount of time in advance that events are scheduled.\n\t * The lookAhead will adjust slightly in response to the \n\t * measured update time to try to avoid clicks.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lookAhead\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lookAhead\", {\n\t\tget : function(){\n\t\t\treturn this._lookAhead;\n\t\t},\n\t\tset : function(lA){\n\t\t\tthis._lookAhead = lA;\n\t\t}\n\t});\n\n\t/**\n\t * How often the Web Worker callback is invoked.\n\t * This number corresponds to how responsive the scheduling\n\t * can be. Context.updateInterval + Context.lookAhead gives you the\n\t * total latency between scheduling an event and hearing it.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name updateInterval\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"updateInterval\", {\n\t\tget : function(){\n\t\t\treturn this._updateInterval;\n\t\t},\n\t\tset : function(interval){\n\t\t\tthis._updateInterval = Math.max(interval, Tone.prototype.blockTime);\n\t\t\tthis._worker.postMessage(Math.max(interval * 1000, 1));\n\t\t}\n\t});\n\n\t/**\n\t * The type of playback, which affects tradeoffs between audio \n\t * output latency and responsiveness. \n\t * \n\t * In addition to setting the value in seconds, the latencyHint also\n\t * accepts the strings \"interactive\" (prioritizes low latency), \n\t * \"playback\" (prioritizes sustained playback), \"balanced\" (balances\n\t * latency and performance), and \"fastest\" (lowest latency, might glitch more often). \n\t * @type {String|Seconds}\n\t * @memberOf Tone.Context#\n\t * @name latencyHint\n\t * @static\n\t * @example\n\t * //set the lookAhead to 0.3 seconds\n\t * Tone.context.latencyHint = 0.3;\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"latencyHint\", {\n\t\tget : function(){\n\t\t\treturn this._latencyHint;\n\t\t},\n\t\tset : function(hint){\n\t\t\tvar lookAhead = hint;\n\t\t\tthis._latencyHint = hint;\n\t\t\tif (this.isString(hint)){\n\t\t\t\tswitch(hint){\n\t\t\t\t\tcase \"interactive\" :\n\t\t\t\t\t\tlookAhead = 0.1;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"playback\" :\n\t\t\t\t\t\tlookAhead = 0.8;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"balanced\" :\n\t\t\t\t\t\tlookAhead = 0.25;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"fastest\" :\n\t\t\t\t\t\tlookAhead = 0.01;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.lookAhead = lookAhead;\n\t\t\tthis.updateInterval = lookAhead/3;\n\t\t}\n\t});\n\n\t/**\n\t * Shim all connect/disconnect and some deprecated methods which are still in\n\t * some older implementations.\n\t * @private\n\t */\n\tfunction shimConnect(){\n\n\t\tvar nativeConnect = AudioNode.prototype.connect;\n\t\tvar nativeDisconnect = AudioNode.prototype.disconnect;\n\n\t\t//replace the old connect method\n\t\tfunction toneConnect(B, outNum, inNum){\n\t\t\tif (B.input){\n\t\t\t\tif (Array.isArray(B.input)){\n\t\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\t\tinNum = 0;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connect(B.input[inNum]);\n\t\t\t\t} else {\n\t\t\t\t\tthis.connect(B.input, outNum, inNum);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (B instanceof AudioNode){\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum, inNum);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error connecting to node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//replace the old disconnect method\n\t\tfunction toneDisconnect(B, outNum, inNum){\n\t\t\tif (B && B.input && Array.isArray(B.input)){\n\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\tinNum = 0;\n\t\t\t\t}\n\t\t\t\tthis.disconnect(B.input[inNum], outNum, inNum);\n\t\t\t} else if (B && B.input){\n\t\t\t\tthis.disconnect(B.input, outNum, inNum);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tnativeDisconnect.apply(this, arguments);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error disconnecting node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (AudioNode.prototype.connect !== toneConnect){\n\t\t\tAudioNode.prototype.connect = toneConnect;\n\t\t\tAudioNode.prototype.disconnect = toneDisconnect;\n\t\t}\n\t}\n\n\t// set the audio context initially\n\tif (Tone.supported){\n\t\tshimConnect();\n\t\tTone.context = new Tone.Context();\n\t} else {\n\t\tconsole.warn(\"This browser does not support Tone.js\");\n\t}\n\n\treturn Tone.Context;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\t\n\t/**\n\t * @class Performs a linear scaling on an input signal.\n\t * Scales a NormalRange input to between\n\t * outputMin and outputMax.\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {number} [outputMin=0] The output value when the input is 0. \n\t * @param {number} [outputMax=1]\tThe output value when the input is 1. \n\t * @example\n\t * var scale = new Tone.Scale(50, 100);\n\t * var signal = new Tone.Signal(0.5).connect(scale);\n\t * //the output of scale equals 75\n\t */\n\tTone.Scale = function(outputMin, outputMax){\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMin = this.defaultArg(outputMin, 0);\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMax = this.defaultArg(outputMax, 1);\n\n\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(1);\n\t\t\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Add}\n\t\t * @private\n\t\t */\n\t\tthis._add = this.output = new Tone.Add(0);\n\n\t\tthis._scale.connect(this._add);\n\t\tthis._setRange();\n\t};\n\n\tTone.extend(Tone.Scale, Tone.SignalBase);\n\n\t/**\n\t * The minimum output value. This number is output when \n\t * the value input value is 0. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name min\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"min\", {\n\t\tget : function(){\n\t\t\treturn this._outputMin;\n\t\t},\n\t\tset : function(min){\n\t\t\tthis._outputMin = min;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * The maximum output value. This number is output when \n\t * the value input value is 1. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name max\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"max\", {\n\t\tget : function(){\n\t\t\treturn this._outputMax;\n\t\t},\n\t\tset : function(max){\n\t\t\tthis._outputMax = max;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * set the values\n\t * @private\n\t */\n\tTone.Scale.prototype._setRange = function() {\n\t\tthis._add.value = this._outputMin;\n\t\tthis._scale.value = this._outputMax - this._outputMin;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Scale} this\n\t */\n\tTone.Scale.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._add.dispose();\n\t\tthis._add = null;\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Scale;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Timeline\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal which adds the method getValueAtTime. \n\t * Code and inspiration from https://github.com/jsantell/web-audio-automation-timeline\n\t * @extends {Tone.Param}\n\t * @param {Number=} value The initial value of the signal\n\t * @param {String=} units The conversion units of the signal.\n\t */\n\tTone.TimelineSignal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\t\t\n\t\t/**\n\t\t * The scheduled events\n\t\t * @type {Tone.Timeline}\n\t\t * @private\n\t\t */\n\t\tthis._events = new Tone.Timeline(10);\n\n\t\t//constructors\n\t\tTone.Signal.apply(this, options);\n\t\toptions.param = this._param;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The initial scheduled value\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._initial = this._fromUnits(this._param.value);\n\t};\n\n\tTone.extend(Tone.TimelineSignal, Tone.Param);\n\n\t/**\n\t * The event types of a schedulable signal.\n\t * @enum {String}\n\t * @private\n\t */\n\tTone.TimelineSignal.Type = {\n\t\tLinear : \"linear\",\n\t\tExponential : \"exponential\",\n\t\tTarget : \"target\",\n\t\tCurve : \"curve\",\n\t\tSet : \"set\"\n\t};\n\n\t/**\n\t * The current value of the signal. \n\t * @memberOf Tone.TimelineSignal#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.TimelineSignal.prototype, \"value\", {\n\t\tget : function(){\n\t\t\tvar now = this.now();\n\t\t\tvar val = this.getValueAtTime(now);\n\t\t\treturn this._toUnits(val);\n\t\t},\n\t\tset : function(value){\n\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\tthis._initial = convertedVal;\n\t\t\tthis.cancelScheduledValues();\n\t\t\tthis._param.value = convertedVal;\n\t\t}\n\t});\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tSCHEDULING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.TimelineSignal} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Set,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime\n\t\t});\n\t\t//invoke the original event\n\t\tthis._param.setValueAtTime(value, startTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tendTime = this.toSeconds(endTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Linear,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\tthis._param.linearRampToValueAtTime(value, endTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {\n\t\t//get the previous event and make sure it's not starting from 0\n\t\tendTime = this.toSeconds(endTime);\n\t\tvar beforeEvent = this._searchBefore(endTime);\n\t\tif (beforeEvent && beforeEvent.value === 0){\n\t\t\t//reschedule that event\n\t\t\tthis.setValueAtTime(this._minOutput, beforeEvent.time);\n\t\t}\n\t\tvalue = this._fromUnits(value);\n\t\tvar setValue = Math.max(value, this._minOutput);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Exponential,\n\t\t\t\"value\" : setValue,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\t//if the ramped to value is 0, make it go to the min output, and then set to 0.\n\t\tif (value < this._minOutput){\n\t\t\tthis._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);\n\t\t\tthis.setValueAtTime(0, endTime);\n\t\t} else {\n\t\t\tthis._param.exponentialRampToValueAtTime(value, endTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Target,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime,\n\t\t\t\"constant\" : timeConstant\n\t\t});\n\t\tthis._param.setTargetAtTime(value, startTime, timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Set an array of arbitrary values starting at the given time for the given duration.\n\t * @param {Float32Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration\n\t * @param {NormalRange} [scaling=1] If the values in the curve should be scaled by some value\n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {\n\t\tscaling = this.defaultArg(scaling, 1);\n\t\t//copy the array\n\t\tvar floats = new Array(values.length);\n\t\tfor (var i = 0; i < floats.length; i++){\n\t\t\tfloats[i] = this._fromUnits(values[i]) * scaling;\n\t\t}\n\t\tstartTime = this.toSeconds(startTime);\n\t\tduration = this.toSeconds(duration);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Curve,\n\t\t\t\"value\" : floats,\n\t\t\t\"time\" : startTime,\n\t\t\t\"duration\" : duration\n\t\t});\n\t\t//set the first value\n\t\tthis._param.setValueAtTime(floats[0], startTime);\n\t\t//schedule a lienar ramp for each of the segments\n\t\tfor (var j = 1; j < floats.length; j++){\n\t\t\tvar segmentTime = startTime + (j / (floats.length - 1) * duration);\n\t\t\tthis._param.linearRampToValueAtTime(floats[j], segmentTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.cancelScheduledValues = function (after) {\n\t\tafter = this.toSeconds(after);\n\t\tthis._events.cancel(after);\n\t\tthis._param.cancelScheduledValues(after);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets the computed value at the given time. This provides\n\t * a point from which a linear or exponential curve\n\t * can be scheduled after. Will cancel events after \n\t * the given time and shorten the currently scheduled\n\t * linear or exponential ramp so that it ends at `time` .\n\t * This is to avoid discontinuities and clicks in envelopes. \n\t * @param {Time} time When to set the ramp point\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.setRampPoint = function (time) {\n\t\ttime = this.toSeconds(time);\n\t\t//get the value at the given time\n\t\tvar val = this._toUnits(this.getValueAtTime(time));\n\t\t//if there is an event at the given time\n\t\t//and that even is not a \"set\"\n\t\tvar before = this._searchBefore(time);\n\t\tif (before && before.time === time){\n\t\t\t//remove everything after\n\t\t\tthis.cancelScheduledValues(time + this.sampleTime);\n\t\t} else if (before && \n\t\t\t\t before.type === Tone.TimelineSignal.Type.Curve &&\n\t\t\t\t before.time + before.duration > time){\n\t\t\t//if the curve is still playing\n\t\t\t//cancel the curve\n\t\t\tthis.cancelScheduledValues(time);\n\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t} else {\n\t\t\t//reschedule the next event to end at the given time\n\t\t\tvar after = this._searchAfter(time);\n\t\t\tif (after){\n\t\t\t\t//cancel the next event(s)\n\t\t\t\tthis.cancelScheduledValues(time);\n\t\t\t\tif (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\t\t\tthis.exponentialRampToValueAtTime(val, time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.setValueAtTime(val, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a linear ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the linear ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.linearRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a exponential ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the exponential ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.exponentialRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tGETTING SCHEDULED VALUES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value before or equal to the given time\n\t * @param {Number} time The time to query\n\t * @return {Object} The event at or before the given time.\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchBefore = function(time){\n\t\treturn this._events.get(time);\n\t};\n\n\t/**\n\t * The event after the given time\n\t * @param {Number} time The time to query.\n\t * @return {Object} The next event after the given time\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchAfter = function(time){\n\t\treturn this._events.getAfter(time);\n\t};\n\n\t/**\n\t * Get the scheduled value at the given time. This will\n\t * return the unconverted (raw) value.\n\t * @param {Number} time The time in seconds.\n\t * @return {Number} The scheduled value at the given time.\n\t */\n\tTone.TimelineSignal.prototype.getValueAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tvar after = this._searchAfter(time);\n\t\tvar before = this._searchBefore(time);\n\t\tvar value = this._initial;\n\t\t//if it was set by\n\t\tif (before === null){\n\t\t\tvalue = this._initial;\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Target){\n\t\t\tvar previous = this._events.getBefore(before.time);\n\t\t\tvar previouVal;\n\t\t\tif (previous === null){\n\t\t\t\tpreviouVal = this._initial;\n\t\t\t} else {\n\t\t\t\tpreviouVal = previous.value;\n\t\t\t}\n\t\t\tvalue = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Curve){\n\t\t\tvalue = this._curveInterpolate(before.time, before.value, before.duration, time);\n\t\t} else if (after === null){\n\t\t\tvalue = before.value;\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\tvalue = this._linearInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\tvalue = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else {\n\t\t\tvalue = before.value;\n\t\t}\n\t\treturn value;\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.TimelineSignal} this\n\t * @method\n\t */\n\tTone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUTOMATION CURVE CALCULATIONS\n\t//\tMIT License, copyright (c) 2014 Jordan Santell\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Calculates the the value along the curve produced by setTargetAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {\n\t\treturn v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by linearRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {\n\t\treturn v0 + (v1 - v0) * ((t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by exponentialRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {\n\t\tv0 = Math.max(this._minOutput, v0);\n\t\treturn v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by setValueCurveAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {\n\t\tvar len = curve.length;\n\t\t// If time is after duration, return the last curve value\n\t\tif (time >= start + duration) {\n\t\t\treturn curve[len - 1];\n\t\t} else if (time <= start){\n\t\t\treturn curve[0];\n\t\t} else {\n\t\t\tvar progress = (time - start) / duration;\n\t\t\tvar lowerIndex = Math.floor((len - 1) * progress);\n\t\t\tvar upperIndex = Math.ceil((len - 1) * progress);\n\t\t\tvar lowerVal = curve[lowerIndex];\n\t\t\tvar upperVal = curve[upperIndex];\n\t\t\tif (upperIndex === lowerIndex){\n\t\t\t\treturn lowerVal;\n\t\t\t} else {\n\t\t\t\treturn this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.dispose = function(){\n\t\tTone.Signal.prototype.dispose.call(this);\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._events.dispose();\n\t\tthis._events = null;\n\t};\n\n\treturn Tone.TimelineSignal;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Effect = require('effect');\r\n\r\n /**\r\n *
A p5.Filter uses a Web Audio Biquad Filter to filter\r\n * the frequency response of an input source. Subclasses\r\n * include:
\r\n * p5.LowPass:\r\n * Allows frequencies below the cutoff frequency to pass through,\r\n * and attenuates frequencies above the cutoff. \r\n * p5.HighPass:\r\n * The opposite of a lowpass filter. \r\n * p5.BandPass:\r\n * Allows a range of frequencies to pass through and attenuates\r\n * the frequencies below and above this frequency range. \r\n *\r\n * The .res() method controls either width of the\r\n * bandpass, or resonance of the low/highpass cutoff frequency.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Filter\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\r\n * @example\r\n *
\r\n * var fft, noise, filter;\r\n *\r\n * function setup() {\r\n * fill(255, 40, 255);\r\n *\r\n * filter = new p5.BandPass();\r\n *\r\n * noise = new p5.Noise();\r\n * // disconnect unfiltered noise,\r\n * // and connect to filter\r\n * noise.disconnect();\r\n * noise.connect(filter);\r\n * noise.start();\r\n *\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n *\r\n * // set the BandPass frequency based on mouseX\r\n * var freq = map(mouseX, 0, width, 20, 10000);\r\n * filter.freq(freq);\r\n * // give the filter a narrow band (lower res = wider bandpass)\r\n * filter.res(50);\r\n *\r\n * // draw filtered spectrum\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * for (var i = 0; i < spectrum.length; i++) {\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width/spectrum.length, h);\r\n * }\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * noise.amp(0.5, 0.2);\r\n * } else {\r\n * noise.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Filter = function (type) {\r\n\r\n Effect.call(this);\r\n //add extend Effect by adding a Biquad Filter\r\n\r\n /**\r\n * The p5.Filter is built with a\r\n * \r\n * Web Audio BiquadFilter Node.\r\n *\r\n * @property {DelayNode} biquadFilter\r\n\t */\r\n\r\n this.biquad = this.ac.createBiquadFilter();\r\n\r\n this.input.connect(this.biquad);\r\n\r\n this.biquad.connect(this.wet);\r\n\r\n if (type) {\r\n this.setType(type);\r\n }\r\n\r\n //Properties useful for the toggle method.\r\n this._on = true;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n p5.Filter.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Filter an audio signal according to a set\r\n * of filter parameters.\r\n *\r\n * @method process\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance/Width of the filter frequency\r\n * from 0.001 to 1000\r\n */\r\n p5.Filter.prototype.process = function(src, freq, res, time) {\r\n src.connect(this.input);\r\n this.set(freq, res, time);\r\n };\r\n\r\n\r\n /**\r\n * Set the frequency and the resonance of the filter.\r\n *\r\n * @method set\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Filter.prototype.set = function(freq, res, time) {\r\n if (freq) {\r\n this.freq(freq, time);\r\n }\r\n if (res) {\r\n this.res(res, time);\r\n }\r\n };\r\n\r\n /**\r\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\r\n * human hearing, although in reality most people hear in a narrower\r\n * range).\r\n *\r\n * @method freq\r\n * @param {Number} freq Filter Frequency\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current frequency value\r\n */\r\n p5.Filter.prototype.freq = function(freq, time) {\r\n var t = time || 0;\r\n if (freq <= 0) {\r\n freq = 1;\r\n }\r\n if (typeof freq === 'number') {\r\n this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t);\r\n } else if (freq) {\r\n freq.connect(this.biquad.frequency);\r\n }\r\n return this.biquad.frequency.value;\r\n };\r\n\r\n /**\r\n * Controls either width of a bandpass frequency,\r\n * or the resonance of a low/highpass cutoff frequency.\r\n *\r\n * @method res\r\n * @param {Number} res Resonance/Width of filter freq\r\n * from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current res value\r\n */\r\n p5.Filter.prototype.res = function(res, time) {\r\n var t = time || 0;\r\n if (typeof res === 'number') {\r\n this.biquad.Q.value = res;\r\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);\r\n } else if (res) {\r\n res.connect(this.biquad.Q);\r\n }\r\n return this.biquad.Q.value;\r\n };\r\n\r\n /**\r\n * Controls the gain attribute of a Biquad Filter.\r\n * This is distinctly different from .amp() which is inherited from p5.Effect\r\n * .amp() controls the volume via the output gain node\r\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\r\n *\r\n * @method gain\r\n * @param {Number} gain\r\n * @return {Number} Returns the current or updated gain value\r\n */\r\n p5.Filter.prototype.gain = function(gain, time) {\r\n var t = time || 0;\r\n if (typeof gain === 'number') {\r\n this.biquad.gain.value = gain;\r\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t);\r\n } else if (gain) {\r\n gain.connect(this.biquad.gain);\r\n }\r\n return this.biquad.gain.value;\r\n };\r\n\r\n\r\n /**\r\n * Toggle function. Switches between the specified type and allpass\r\n *\r\n * @method toggle\r\n * @return {boolean} [Toggle value]\r\n */\r\n p5.Filter.prototype.toggle = function() {\r\n this._on = !this._on;\r\n\r\n if (this._on === true) {\r\n this.biquad.type = this._untoggledType;\r\n } else if (this._on === false) {\r\n this.biquad.type = 'allpass';\r\n }\r\n\r\n return this._on;\r\n };\r\n\r\n /**\r\n * Set the type of a p5.Filter. Possible types include:\r\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\r\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\r\n * \"allpass\".\r\n *\r\n * @method setType\r\n * @param {String} t\r\n */\r\n p5.Filter.prototype.setType = function(t) {\r\n this.biquad.type = t;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n\r\n p5.Filter.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n Effect.prototype.dispose.apply(this);\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n delete this.biquad;\r\n }\r\n };\r\n\r\n /**\r\n * Constructor: new p5.LowPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('lowpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.LowPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.LowPass = function() {\r\n p5.Filter.call(this, 'lowpass');\r\n };\r\n p5.LowPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.HighPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('highpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.HighPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.HighPass = function() {\r\n p5.Filter.call(this, 'highpass');\r\n };\r\n p5.HighPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.BandPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('bandpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.BandPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.BandPass = function() {\r\n p5.Filter.call(this, 'bandpass');\r\n };\r\n p5.BandPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n return p5.Filter;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Negate\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Subtract the signal connected to input[1] from the signal connected \n\t * to input[0]. If an argument is provided in the constructor, the \n\t * signals .value will be subtracted from the incoming signal.\n\t *\n\t * @extends {Tone.Signal}\n\t * @constructor\n\t * @param {number=} value The value to subtract from the incoming signal. If the value\n\t * is omitted, it will subtract the second signal from the first.\n\t * @example\n\t * var sub = new Tone.Subtract(1);\n\t * var sig = new Tone.Signal(4).connect(sub);\n\t * //the output of sub is 3. \n\t * @example\n\t * var sub = new Tone.Subtract();\n\t * var sigA = new Tone.Signal(10);\n\t * var sigB = new Tone.Signal(2.5);\n\t * sigA.connect(sub, 0, 0);\n\t * sigB.connect(sub, 0, 1);\n\t * //output of sub is 7.5\n\t */\n\tTone.Subtract = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * negate the input of the second input before connecting it\n\t\t * to the summing node.\n\t\t * @type {Tone.Negate}\n\t\t * @private\n\t\t */\n\t\tthis._neg = new Tone.Negate();\n\n\t\t/**\n\t\t * the node where the value is set\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.chain(this._neg, this._sum);\n\t};\n\n\tTone.extend(Tone.Subtract, Tone.Signal);\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.Subtract.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._neg.dispose();\n\t\tthis._neg = null;\n\t\tthis._sum.disconnect();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Subtract;\n});","'use strict';\r\n\r\nglobal.TONE_SILENCE_VERSION_LOGGING = true;\r\n\r\ndefine(['startaudiocontext', 'Tone/core/Context', 'Tone/core/Tone'], function (StartAudioContext, Context, Tone) {\r\n // Create the Audio Context\r\n const audiocontext = new window.AudioContext();\r\n\r\n // Tone and p5.sound share the same audio context\r\n Tone.context.dispose();\r\n Tone.setContext(audiocontext);\r\n\r\n /**\r\n *
Returns the Audio Context for this sketch. Useful for users\r\n * who would like to dig deeper into the Web Audio API\r\n * .
\r\n *\r\n *
Some browsers require users to startAudioContext\r\n * with a user gesture, such as touchStarted in the example below.
\r\n *\r\n * @method getAudioContext\r\n * @return {Object} AudioContext for this sketch\r\n * @example\r\n *
\r\n * function draw() {\r\n * background(255);\r\n * textAlign(CENTER);\r\n *\r\n * if (getAudioContext().state !== 'running') {\r\n * text('click to start audio', width/2, height/2);\r\n * } else {\r\n * text('audio is enabled', width/2, height/2);\r\n * }\r\n * }\r\n *\r\n * function touchStarted() {\r\n * if (getAudioContext().state !== 'running') {\r\n * getAudioContext().resume();\r\n * }\r\n * var synth = new p5.MonoSynth();\r\n * synth.play('A4', 0.5, 0, 0.2);\r\n * }\r\n *\r\n *
It is a good practice to give users control over starting audio playback.\r\n * This practice is enforced by Google Chrome's autoplay policy as of r70\r\n * (info), iOS Safari, and other browsers.\r\n *
\r\n *\r\n *
\r\n * userStartAudio() starts the Audio Context on a user gesture. It utilizes\r\n * the StartAudioContext library by\r\n * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext.\r\n *
\r\n *\r\n *
Starting the audio context on a user gesture can be as simple as userStartAudio().\r\n * Optional parameters let you decide on a specific element that will start the audio context,\r\n * and/or call a function once the audio context is started.
\r\n * @param {Element|Array} [element(s)] This argument can be an Element,\r\n * Selector String, NodeList, p5.Element,\r\n * jQuery Element, or an Array of any of those.\r\n * @param {Function} [callback] Callback to invoke when the AudioContext has started\r\n * @return {Promise} Returns a Promise which is resolved when\r\n * the AudioContext state is 'running'\r\n * @method userStartAudio\r\n * @for p5\r\n * @example\r\n *
\r\n * function setup() {\r\n * var myDiv = createDiv('click to start audio');\r\n * myDiv.position(0, 0);\r\n *\r\n * var mySynth = new p5.MonoSynth();\r\n *\r\n * // This won't play until the context has started\r\n * mySynth.play('A6');\r\n *\r\n * // Start the audio context on a click/touch event\r\n * userStartAudio().then(function() {\r\n * myDiv.remove();\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.prototype.userStartAudio = function(elements, callback) {\r\n var elt = elements;\r\n if (elements instanceof p5.Element) {\r\n elt = elements.elt;\r\n } else if (elements instanceof Array && elements[0] instanceof p5.Element ) {\r\n elt = elements.map(function(e) { return e.elt});\r\n }\r\n return StartAudioContext(audiocontext, elt, callback);\r\n };\r\n\r\n return audiocontext;\r\n});\r\n","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Emitter gives classes which extend it\n\t * the ability to listen for and emit events. \n\t * Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).\n\t * MIT (c) 2011 Jerome Etienne.\n\t * \n\t * @extends {Tone}\n\t */\n\tTone.Emitter = function(){\n\t\t/**\n\t\t * Contains all of the events.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t\tthis._events = {};\n\t};\n\n\tTone.extend(Tone.Emitter);\n\n\t/**\n\t * Bind a callback to a specific event.\n\t * @param {String} event The name of the event to listen for.\n\t * @param {Function} callback The callback to invoke when the\n\t * event is emitted\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.on = function(event, callback){\n\t\t//split the event\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var i = 0; i < events.length; i++){\n\t\t\tvar eventName = events[i];\n\t\t\tif (!this._events.hasOwnProperty(eventName)){\n\t\t\t\tthis._events[eventName] = [];\n\t\t\t}\n\t\t\tthis._events[eventName].push(callback);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove the event listener.\n\t * @param {String} event The event to stop listening to.\n\t * @param {Function=} callback The callback which was bound to \n\t * the event with Tone.Emitter.on.\n\t * If no callback is given, all callbacks\n\t * events are removed.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.off = function(event, callback){\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var ev = 0; ev < events.length; ev++){\n\t\t\tevent = events[ev];\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tif (Tone.prototype.isUndef(callback)){\n\t\t\t\t\tthis._events[event] = [];\n\t\t\t\t} else {\n\t\t\t\t\tvar eventList = this._events[event];\n\t\t\t\t\tfor (var i = 0; i < eventList.length; i++){\n\t\t\t\t\t\tif (eventList[i] === callback){\n\t\t\t\t\t\t\teventList.splice(i, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Invoke all of the callbacks bound to the event\n\t * with any arguments passed in. \n\t * @param {String} event The name of the event.\n\t * @param {*...} args The arguments to pass to the functions listening.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.emit = function(event){\n\t\tif (this._events){\n\t\t\tvar args = Array.apply(null, arguments).slice(1);\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tvar eventList = this._events[event];\n\t\t\t\tfor (var i = 0, len = eventList.length; i < len; i++){\n\t\t\t\t\teventList[i].apply(this, args);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add Emitter functions (on/off/emit) to the object\n\t * @param {Object|Function} object The object or class to extend.\n\t */\n\tTone.Emitter.mixin = function(object){\n\t\tvar functions = [\"on\", \"off\", \"emit\"];\n\t\tobject._events = {};\n\t\tfor (var i = 0; i < functions.length; i++){\n\t\t\tvar func = functions[i];\n\t\t\tvar emitterFunc = Tone.Emitter.prototype[func];\n\t\t\tobject[func] = emitterFunc;\n\t\t}\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._events = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Emitter;\n});","define([\"Tone/core/Tone\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Base class for all Signals. Used Internally. \n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t */\n\tTone.SignalBase = function(){};\n\n\tTone.extend(Tone.SignalBase);\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.SignalBase.prototype.connect = function(node, outputNumber, inputNumber){\n\t\t//zero it out so that the signal can have full control\n\t\tif ((Tone.Signal && Tone.Signal === node.constructor) || \n\t\t\t\t(Tone.Param && Tone.Param === node.constructor) || \n\t\t\t\t(Tone.TimelineSignal && Tone.TimelineSignal === node.constructor)){\n\t\t\t//cancel changes\n\t\t\tnode._param.cancelScheduledValues(0);\n\t\t\t//reset the value\n\t\t\tnode._param.value = 0;\n\t\t\t//mark the value as overridden\n\t\t\tnode.overridden = true;\n\t\t} else if (node instanceof AudioParam){\n\t\t\tnode.cancelScheduledValues(0);\n\t\t\tnode.value = 0;\n\t\t} \n\t\tTone.prototype.connect.call(this, node, outputNumber, inputNumber);\n\t\treturn this;\n\t};\n\n\treturn Tone.SignalBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Time is a primitive type for encoding Time values. \n\t * Eventually all time values are evaluated to seconds\n\t * using the `eval` method. Tone.Time can be constructed\n\t * with or without the `new` keyword. Tone.Time can be passed\n\t * into the parameter of any method which takes time as an argument. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * var t = Tone.Time(\"4n\");//encodes a quarter note\n\t * t.mult(4); // multiply that value by 4\n\t * t.toNotation(); //returns \"1m\"\n\t */\n\tTone.Time = function(val, units){\n\t\tif (this instanceof Tone.Time){\n\n\t\t\t/**\n\t\t\t * If the current clock time should\n\t\t\t * be added to the output\n\t\t\t * @type {Boolean}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._plusNow = false;\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Time(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Time, Tone.TimeBase);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);\n\n\t/*\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\treturn Tone.Transport.nextSubdivision(rh());\n\t\t}\n\t};\n\n\t/*\n\t * Adds an additional unary expression\n\t * which adds the current clock time.\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.now = {\n\t\tregexp : /^\\+/,\n\t\tmethod : function(lh){\n\t\t\tthis._plusNow = true;\n\t\t\treturn lh();\n\t\t}\n\t};\n\n\t/**\n\t * Quantize the time by the given subdivision. Optionally add a\n\t * percentage which will move the time value towards the ideal\n\t * quantized value by that percentage. \n\t * @param {Number|Time} val The subdivision to quantize to\n\t * @param {NormalRange} [percent=1] Move the time value\n\t * towards the quantized value by\n\t * a percentage.\n\t * @return {Tone.Time} this\n\t * @example\n\t * Tone.Time(21).quantize(2) //returns 22\n\t * Tone.Time(0.6).quantize(\"4n\", 0.5) //returns 0.55\n\t */\n\tTone.Time.prototype.quantize = function(subdiv, percent){\n\t\tpercent = this.defaultArg(percent, 1);\n\t\tthis._expr = function(expr, subdivision, percent){\n\t\t\texpr = expr();\n\t\t\tsubdivision = subdivision.toSeconds();\n\t\t\tvar multiple = Math.round(expr / subdivision);\n\t\t\tvar ideal = multiple * subdivision;\n\t\t\tvar diff = ideal - expr;\n\t\t\treturn expr + diff * percent;\n\t\t}.bind(this, this._expr, new this.constructor(subdiv), percent);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Adds the clock time to the time expression at the \n\t * moment of evaluation. \n\t * @return {Tone.Time} this\n\t */\n\tTone.Time.prototype.addNow = function(){\n\t\tthis._plusNow = true;\n\t\treturn this;\n\t};\n\n\t/**\n\t * @override\n\t * Override the default value return when no arguments are passed in.\n\t * The default value is 'now'\n\t * @private\n\t */\n\tTone.Time.prototype._defaultExpr = function(){\n\t\tthis._plusNow = true;\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.Time} time\n\t * @return {Time}\n\t */\n\tTone.Time.prototype.copy = function(time){\n\t\tTone.TimeBase.prototype.copy.call(this, time);\n\t\tthis._plusNow = time._plusNow;\n\t\treturn this;\n\t};\n\n\t//CONVERSIONS//////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert a Time to Notation. Values will be thresholded to the nearest 128th note. \n\t * @return {Notation} \n\t * @example\n\t * //if the Transport is at 120bpm:\n\t * Tone.Time(2).toNotation();//returns \"1m\"\n\t */\n\tTone.Time.prototype.toNotation = function(){\n\t\tvar time = this.toSeconds();\n\t\tvar testNotations = [\"1m\", \"2n\", \"4n\", \"8n\", \"16n\", \"32n\", \"64n\", \"128n\"];\n\t\tvar retNotation = this._toNotationHelper(time, testNotations);\n\t\t//try the same thing but with tripelets\n\t\tvar testTripletNotations = [\"1m\", \"2n\", \"2t\", \"4n\", \"4t\", \"8n\", \"8t\", \"16n\", \"16t\", \"32n\", \"32t\", \"64n\", \"64t\", \"128n\"];\n\t\tvar retTripletNotation = this._toNotationHelper(time, testTripletNotations);\n\t\t//choose the simpler expression of the two\n\t\tif (retTripletNotation.split(\"+\").length < retNotation.split(\"+\").length){\n\t\t\treturn retTripletNotation;\n\t\t} else {\n\t\t\treturn retNotation;\n\t\t}\n\t};\n\n\t/**\n\t * Helper method for Tone.toNotation\n\t * @param {Number} units \n\t * @param {Array} testNotations\n\t * @return {String}\n\t * @private\n\t */\n\tTone.Time.prototype._toNotationHelper = function(units, testNotations){\n\t\t//the threshold is the last value in the array\n\t\tvar threshold = this._notationToUnits(testNotations[testNotations.length - 1]);\n\t\tvar retNotation = \"\";\n\t\tfor (var i = 0; i < testNotations.length; i++){\n\t\t\tvar notationTime = this._notationToUnits(testNotations[i]);\n\t\t\t//account for floating point errors (i.e. round up if the value is 0.999999)\n\t\t\tvar multiple = units / notationTime;\n\t\t\tvar floatingPointError = 0.000001;\n\t\t\tif (1 - multiple % 1 < floatingPointError){\n\t\t\t\tmultiple += floatingPointError;\n\t\t\t}\n\t\t\tmultiple = Math.floor(multiple);\n\t\t\tif (multiple > 0){\n\t\t\t\tif (multiple === 1){\n\t\t\t\t\tretNotation += testNotations[i];\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += multiple.toString() + \"*\" + testNotations[i];\n\t\t\t\t}\n\t\t\t\tunits -= multiple * notationTime;\n\t\t\t\tif (units < threshold){\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += \" + \";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (retNotation === \"\"){\n\t\t\tretNotation = \"0\";\n\t\t}\n\t\treturn retNotation;\n\t};\n\n\t/**\n\t * Convert a notation value to the current units\n\t * @param {Notation} notation \n\t * @return {Number} \n\t * @private\n\t */\n\tTone.Time.prototype._notationToUnits = function(notation){\n\t\tvar primaryExprs = this._primaryExpressions;\n\t\tvar notationExprs = [primaryExprs.n, primaryExprs.t, primaryExprs.m];\n\t\tfor (var i = 0; i < notationExprs.length; i++){\n\t\t\tvar expr = notationExprs[i];\n\t\t\tvar match = notation.match(expr.regexp);\n\t\t\tif (match){\n\t\t\t\treturn expr.method.call(this, match[1]);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Return the time encoded as Bars:Beats:Sixteenths.\n\t * @return {BarsBeatsSixteenths}\n\t */\n\tTone.Time.prototype.toBarsBeatsSixteenths = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.toSeconds() / quarterTime;\n\t\tvar measures = Math.floor(quarters / this._timeSignature());\n\t\tvar sixteenths = (quarters % 1) * 4;\n\t\tquarters = Math.floor(quarters) % this._timeSignature();\n\t\tsixteenths = sixteenths.toString();\n\t\tif (sixteenths.length > 3){\n\t\t\tsixteenths = parseFloat(sixteenths).toFixed(3);\n\t\t}\n\t\tvar progress = [measures, quarters, sixteenths];\n\t\treturn progress.join(\":\");\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.Time.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time in samples\n\t * @return {Samples} \n\t */\n\tTone.Time.prototype.toSamples = function(){\n\t\treturn this.toSeconds() * this.context.sampleRate;\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t * @example\n\t * Tone.Time(2).toFrequency(); //0.5\n\t */\n\tTone.Time.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.toSeconds = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in milliseconds.\n\t * @return {Milliseconds} \n\t */\n\tTone.Time.prototype.toMilliseconds = function(){\n\t\treturn this.toSeconds() * 1000;\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.valueOf = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow?this.now():0);\n\t};\n\n\treturn Tone.Time;\n});","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TimeBase is a flexible encoding of time\n\t * which can be evaluated to and from a string.\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t * @extends {Tone}\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @example\n\t * Tone.TimeBase(4, \"n\")\n\t * Tone.TimeBase(2, \"t\")\n\t * Tone.TimeBase(\"2t\").add(\"1m\")\n\t * Tone.TimeBase(\"2t + 1m\");\n\t */\n\tTone.TimeBase = function(val, units){\n\n\t\t//allows it to be constructed with or without 'new'\n\t\tif (this instanceof Tone.TimeBase) {\n\n\t\t\t/**\n\t\t\t * Any expressions parsed from the Time\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._expr = this._noOp;\n\n\t\t\tif (val instanceof Tone.TimeBase){\n\t\t\t\tthis.copy(val);\n\t\t\t} else if (!this.isUndef(units) || this.isNumber(val)){\n\t\t\t\t//default units\n\t\t\t\tunits = this.defaultArg(units, this._defaultUnits);\n\t\t\t\tvar method = this._primaryExpressions[units].method;\n\t\t\t\tthis._expr = method.bind(this, val);\n\t\t\t} else if (this.isString(val)){\n\t\t\t\tthis.set(val);\n\t\t\t} else if (this.isUndef(val)){\n\t\t\t\t//default expression\n\t\t\t\tthis._expr = this._defaultExpr();\n\t\t\t}\n\t\t} else {\n\n\t\t\treturn new Tone.TimeBase(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TimeBase);\n\n\t/**\n\t * Repalce the current time value with the value\n\t * given by the expression string.\n\t * @param {String} exprString\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.set = function(exprString){\n\t\tthis._expr = this._parseExprString(exprString);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Return a clone of the TimeBase object.\n\t * @return {Tone.TimeBase} The new cloned Tone.TimeBase\n\t */\n\tTone.TimeBase.prototype.clone = function(){\n\t\tvar instance = new this.constructor();\n\t\tinstance.copy(this);\n\t\treturn instance;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.TimeBase} time\n\t * @return {TimeBase}\n\t */\n\tTone.TimeBase.prototype.copy = function(time){\n\t\tvar val = time._expr();\n\t\treturn this.set(val);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tABSTRACT SYNTAX TREE PARSER\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * All the primary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._primaryExpressions = {\n\t\t\"n\" : {\n\t\t\tregexp : /^(\\d+)n/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\tif (value === 1){\n\t\t\t\t\treturn this._beatsToUnits(this._timeSignature());\n\t\t\t\t} else {\n\t\t\t\t\treturn this._beatsToUnits(4 / value);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"t\" : {\n\t\t\tregexp : /^(\\d+)t/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\treturn this._beatsToUnits(8 / (parseInt(value) * 3));\n\t\t\t}\n\t\t},\n\t\t\"m\" : {\n\t\t\tregexp : /^(\\d+)m/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._beatsToUnits(parseInt(value) * this._timeSignature());\n\t\t\t}\n\t\t},\n\t\t\"i\" : {\n\t\t\tregexp : /^(\\d+)i/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._ticksToUnits(parseInt(value));\n\t\t\t}\n\t\t},\n\t\t\"hz\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)hz/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._frequencyToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"tr\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\t\tvar total = 0;\n\t\t\t\tif (m && m !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t\t}\n\t\t\t\tif (q && q !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(q));\n\t\t\t\t}\n\t\t\t\tif (s && s !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t\t}\n\t\t\t\treturn total;\n\t\t\t}\n\t\t},\n\t\t\"s\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?s)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._secondsToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"samples\" : {\n\t\t\tregexp : /^(\\d+)samples/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn parseInt(value) / this.context.sampleRate;\n\t\t\t}\n\t\t},\n\t\t\"default\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._primaryExpressions[this._defaultUnits].method.call(this, value);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the binary expressions that TimeBase can accept.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._binaryExpressions = {\n\t\t\"+\" : {\n\t\t\tregexp : /^\\+/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() + rh();\n\t\t\t}\n\t\t},\n\t\t\"-\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() - rh();\n\t\t\t}\n\t\t},\n\t\t\"*\" : {\n\t\t\tregexp : /^\\*/,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() * rh();\n\t\t\t}\n\t\t},\n\t\t\"/\" : {\n\t\t\tregexp : /^\\//,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() / rh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the unary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._unaryExpressions = {\n\t\t\"neg\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tmethod : function(lh){\n\t\t\t\treturn -lh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Syntactic glue which holds expressions together\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._syntaxGlue = {\n\t\t\"(\" : {\n\t\t\tregexp : /^\\(/\n\t\t},\n\t\t\")\" : {\n\t\t\tregexp : /^\\)/\n\t\t}\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.TimeBase.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr, this);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr, context){\n\t\t\tvar expressions = [\"_binaryExpressions\", \"_unaryExpressions\", \"_primaryExpressions\", \"_syntaxGlue\"];\n\t\t\tfor (var i = 0; i < expressions.length; i++){\n\t\t\t\tvar group = context[expressions[i]];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tmethod : op.method,\n\t\t\t\t\t\t\tprecedence : op.precedence,\n\t\t\t\t\t\t\tregexp : op.regexp,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * Given a token, find the value within the groupName\n\t * @param {Object} token\n\t * @param {String} groupName\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._matchGroup = function(token, group, prec) {\n\t\tvar ret = false;\n\t\tif (!this.isUndef(token)){\n\t\t\tfor (var opName in group){\n\t\t\t\tvar op = group[opName];\n\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\tif (!this.isUndef(prec)){\n\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\treturn op;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn op;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * Match a binary expression given the token and the precedence\n\t * @param {Lexer} lexer\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseBinary = function(lexer, precedence){\n\t\tif (this.isUndef(precedence)){\n\t\t\tprecedence = 2;\n\t\t}\n\t\tvar expr;\n\t\tif (precedence < 0){\n\t\t\texpr = this._parseUnary(lexer);\n\t\t} else {\n\t\t\texpr = this._parseBinary(lexer, precedence - 1);\n\t\t}\n\t\tvar token = lexer.peek();\n\t\twhile (token && this._matchGroup(token, this._binaryExpressions, precedence)){\n\t\t\ttoken = lexer.next();\n\t\t\texpr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));\n\t\t\ttoken = lexer.peek();\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * Match a unary expression.\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseUnary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tvar op = this._matchGroup(token, this._unaryExpressions);\n\t\tif (op) {\n\t\t\ttoken = lexer.next();\n\t\t\texpr = this._parseUnary(lexer);\n\t\t\treturn op.method.bind(this, expr);\n\t\t}\n\t\treturn this._parsePrimary(lexer);\n\t};\n\n\t/**\n\t * Match a primary expression (a value).\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parsePrimary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tif (this.isUndef(token)) {\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected end of expression\");\n\t\t}\n\t\tif (this._matchGroup(token, this._primaryExpressions)) {\n\t\t\ttoken = lexer.next();\n\t\t\tvar matching = token.value.match(token.regexp);\n\t\t\treturn token.method.bind(this, matching[1], matching[2], matching[3]);\n\t\t}\n\t\tif (token && token.value === \"(\"){\n\t\t\tlexer.next();\n\t\t\texpr = this._parseBinary(lexer);\n\t\t\ttoken = lexer.next();\n\t\t\tif (!(token && token.value === \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\t\tthrow new SyntaxError(\"Tone.TimeBase: Cannot process token \" + token.value);\n\t};\n\n\t/**\n\t * Recursively parse the string expression into a syntax tree.\n\t * @param {string} expr \n\t * @return {Function} the bound method to be evaluated later\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseExprString = function(exprString){\n\t\tif (!this.isString(exprString)){\n\t\t\texprString = exprString.toString();\n\t\t}\n\t\tvar lexer = this._tokenize(exprString);\n\t\tvar tree = this._parseBinary(lexer);\n\t\treturn tree;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tDEFAULTS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The initial expression value\n\t * @return {Number} The initial value 0\n\t * @private\n\t */\n\tTone.TimeBase.prototype._noOp = function(){\n\t\treturn 0;\n\t};\n\n\t/**\n\t * The default expression value if no arguments are given\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultExpr = function(){\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultUnits = \"s\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._frequencyToUnits = function(freq){\n\t\treturn 1/freq;\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._beatsToUnits = function(beats){\n\t\treturn (60 / Tone.Transport.bpm.value) * beats;\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._secondsToUnits = function(seconds){\n\t\treturn seconds;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._ticksToUnits = function(ticks){\n\t\treturn ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time signature.\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._timeSignature = function(){\n\t\treturn Tone.Transport.timeSignature;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Push an expression onto the expression list\n\t * @param {Time} val\n\t * @param {String} type\n\t * @param {String} units\n\t * @return {Tone.TimeBase} \n\t * @private\n\t */\n\tTone.TimeBase.prototype._pushExpr = function(val, name, units){\n\t\t//create the expression\n\t\tif (!(val instanceof Tone.TimeBase)){\n\t\t\tval = new this.constructor(val, units);\n\t\t}\n\t\tthis._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add to the current value.\n\t * @param {Time} val The value to add\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").add(\"1m\"); //\"3m\"\n\t */\n\tTone.TimeBase.prototype.add = function(val, units){\n\t\treturn this._pushExpr(val, \"+\", units);\n\t};\n\n\t/**\n\t * Subtract the value from the current time.\n\t * @param {Time} val The value to subtract\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").sub(\"1m\"); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.sub = function(val, units){\n\t\treturn this._pushExpr(val, \"-\", units);\n\t};\n\n\t/**\n\t * Multiply the current value by the given time.\n\t * @param {Time} val The value to multiply\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").mult(\"2\"); //\"4m\"\n\t */\n\tTone.TimeBase.prototype.mult = function(val, units){\n\t\treturn this._pushExpr(val, \"*\", units);\n\t};\n\n\t/**\n\t * Divide the current value by the given time.\n\t * @param {Time} val The value to divide by\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").div(2); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.div = function(val, units){\n\t\treturn this._pushExpr(val, \"/\", units);\n\t};\n\n\t/**\n\t * Evaluate the time value. Returns the time\n\t * in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.TimeBase.prototype.valueOf = function(){\n\t\treturn this._expr();\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.dispose = function(){\n\t\tthis._expr = null;\n\t};\n\n\treturn Tone.TimeBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Param wraps the native Web Audio's AudioParam to provide\n\t * additional unit conversion functionality. It also\n\t * serves as a base-class for classes which have a single,\n\t * automatable parameter. \n\t * @extends {Tone}\n\t * @param {AudioParam} param The parameter to wrap.\n\t * @param {Tone.Type} units The units of the audio param.\n\t * @param {Boolean} convert If the param should be converted.\n\t */\n\tTone.Param = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"param\", \"units\", \"convert\"], Tone.Param.defaults);\n\n\t\t/**\n\t\t * The native parameter to control\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input = options.param;\n\n\t\t/**\n\t\t * The units of the parameter\n\t\t * @type {Tone.Type}\n\t\t */\n\t\tthis.units = options.units;\n\n\t\t/**\n\t\t * If the value should be converted or not\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis.convert = options.convert;\n\n\t\t/**\n\t\t * True if the signal value is being overridden by \n\t\t * a connected signal.\n\t\t * @readOnly\n\t\t * @type {boolean}\n\t\t * @private\n\t\t */\n\t\tthis.overridden = false;\n\n\t\t/**\n\t\t * If there is an LFO, this is where it is held.\n\t\t * @type {Tone.LFO}\n\t\t * @private\n\t\t */\n\t\tthis._lfo = null;\n\n\t\tif (this.isObject(options.lfo)){\n\t\t\tthis.value = options.lfo;\n\t\t} else if (!this.isUndef(options.value)){\n\t\t\tthis.value = options.value;\n\t\t}\n\t};\n\n\tTone.extend(Tone.Param);\n\t\n\t/**\n\t * Defaults\n\t * @type {Object}\n\t * @const\n\t */\n\tTone.Param.defaults = {\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t\t\"param\" : undefined\n\t};\n\n\t/**\n\t * The current value of the parameter. \n\t * @memberOf Tone.Param#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._toUnits(this._param.value);\n\t\t},\n\t\tset : function(value){\n\t\t\tif (this.isObject(value)){\n\t\t\t\t//throw an error if the LFO needs to be included\n\t\t\t\tif (this.isUndef(Tone.LFO)){\n\t\t\t\t\tthrow new Error(\"Include 'Tone.LFO' to use an LFO as a Param value.\");\n\t\t\t\t}\n\t\t\t\t//remove the old one\n\t\t\t\tif (this._lfo){\n\t\t\t\t\tthis._lfo.dispose();\n\t\t\t\t}\n\t\t\t\tthis._lfo = new Tone.LFO(value).start();\n\t\t\t\tthis._lfo.connect(this.input);\n\t\t\t} else {\n\t\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\t\tthis._param.cancelScheduledValues(0);\n\t\t\t\tthis._param.value = convertedVal;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Convert the given value from the type specified by Tone.Param.units\n\t * into the destination value (such as Gain or Frequency).\n\t * @private\n\t * @param {*} val the value to convert\n\t * @return {number} the number which the value should be set to\n\t */\n\tTone.Param.prototype._fromUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Time: \n\t\t\t\t\treturn this.toSeconds(val);\n\t\t\t\tcase Tone.Type.Frequency: \n\t\t\t\t\treturn this.toFrequency(val);\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.dbToGain(val);\n\t\t\t\tcase Tone.Type.NormalRange: \n\t\t\t\t\treturn Math.min(Math.max(val, 0), 1);\n\t\t\t\tcase Tone.Type.AudioRange: \n\t\t\t\t\treturn Math.min(Math.max(val, -1), 1);\n\t\t\t\tcase Tone.Type.Positive: \n\t\t\t\t\treturn Math.max(val, 0);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * Convert the parameters value into the units specified by Tone.Param.units.\n\t * @private\n\t * @param {number} val the value to convert\n\t * @return {number}\n\t */\n\tTone.Param.prototype._toUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.gainToDb(val);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * the minimum output value\n\t * @type {Number}\n\t * @private\n\t */\n\tTone.Param.prototype._minOutput = 0.00001;\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.Param} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.Param.prototype.setValueAtTime = function(value, time){\n\t\tvalue = this._fromUnits(value);\n\t\ttime = this.toSeconds(time);\n\t\tif (time <= this.now() + this.blockTime){\n\t\t\tthis._param.value = value;\n\t\t} else {\n\t\t\tthis._param.setValueAtTime(value, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Creates a schedule point with the current value at the current time.\n\t * This is useful for creating an automation anchor point in order to \n\t * schedule changes from the current value. \n\t *\n\t * @param {number=} now (Optionally) pass the now value in. \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setRampPoint = function(now){\n\t\tnow = this.defaultArg(now, this.now());\n\t\tvar currentVal = this._param.value;\n\t\t// exponentialRampToValueAt cannot ever ramp from or to 0\n\t\t// More info: https://bugzilla.mozilla.org/show_bug.cgi?id=1125600#c2\n\t\tif (currentVal === 0){\n\t\t\tcurrentVal = this._minOutput;\n\t\t}\n\t\tthis._param.setValueAtTime(currentVal, now);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.linearRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tthis._param.linearRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.exponentialRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\tthis._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //exponentially ramp to the value 2 over 4 seconds. \n\t * signal.exponentialRampToValue(2, 4);\n\t */\n\tTone.Param.prototype.exponentialRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an linear continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //linearly ramp to the value 4 over 3 seconds. \n\t * signal.linearRampToValue(4, 3);\n\t */\n\tTone.Param.prototype.linearRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.Param} this \n\t */\n\tTone.Param.prototype.setTargetAtTime = function(value, startTime, timeConstant){\n\t\tvalue = this._fromUnits(value);\n\t\t// The value will never be able to approach without timeConstant > 0.\n\t\t// http://www.w3.org/TR/webaudio/#dfn-setTargetAtTime, where the equation\n\t\t// is described. 0 results in a division by 0.\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tthis._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets an array of arbitrary parameter values starting at the given time\n\t * for the given duration.\n\t * \t\n\t * @param {Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setValueCurveAtTime = function(values, startTime, duration){\n\t\tfor (var i = 0; i < values.length; i++){\n\t\t\tvalues[i] = this._fromUnits(values[i]);\n\t\t}\n\t\tthis._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.cancelScheduledValues = function(startTime){\n\t\tthis._param.cancelScheduledValues(this.toSeconds(startTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Ramps to the given value over the duration of the rampTime. \n\t * Automatically selects the best ramp type (exponential or linear)\n\t * depending on the `units` of the signal\n\t * \n\t * @param {number} value \n\t * @param {Time} rampTime \tThe time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //ramp to the value either linearly or exponentially \n\t * //depending on the \"units\" value of the signal\n\t * signal.rampTo(0, 10);\n\t * @example\n\t * //schedule it to ramp starting at a specific time\n\t * signal.rampTo(0, 10, 5)\n\t */\n\tTone.Param.prototype.rampTo = function(value, rampTime, startTime){\n\t\trampTime = this.defaultArg(rampTime, 0);\n\t\tif (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels){\n\t\t\tthis.exponentialRampToValue(value, rampTime, startTime);\n\t\t} else {\n\t\t\tthis.linearRampToValue(value, rampTime, startTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * The LFO created by the signal instance. If none\n\t * was created, this is null.\n\t * @type {Tone.LFO}\n\t * @readOnly\n\t * @memberOf Tone.Param#\n\t * @name lfo\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"lfo\", {\n\t\tget : function(){\n\t\t\treturn this._lfo;\n\t\t}\n\t});\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tif (this._lfo){\n\t\t\tthis._lfo.dispose();\n\t\t\tthis._lfo = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\treturn Tone.Param;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
Creates a signal that oscillates between -1.0 and 1.0.\r\n * By default, the oscillation takes the form of a sinusoidal\r\n * shape ('sine'). Additional types include 'triangle',\r\n * 'sawtooth' and 'square'. The frequency defaults to\r\n * 440 oscillations per second (440Hz, equal to the pitch of an\r\n * 'A' note).
\r\n *\r\n *
Set the type of oscillation with setType(), or by instantiating a\r\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\r\n *
\r\n *\r\n * @class p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] frequency defaults to 440Hz\r\n * @param {String} [type] type of oscillator. Options:\r\n * 'sine' (default), 'triangle',\r\n * 'sawtooth', 'square'\r\n * @example\r\n *
\r\n * var osc;\r\n * var playing = false;\r\n *\r\n * function setup() {\r\n * backgroundColor = color(255,0,255);\r\n * textAlign(CENTER);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.setType('sine');\r\n * osc.freq(240);\r\n * osc.amp(0);\r\n * osc.start();\r\n * }\r\n *\r\n * function draw() {\r\n * background(backgroundColor)\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * if (!playing) {\r\n * // ramp amplitude to 0.5 over 0.05 seconds\r\n * osc.amp(0.5, 0.05);\r\n * playing = true;\r\n * backgroundColor = color(0,255,255);\r\n * } else {\r\n * // ramp amplitude to 0 over 0.5 seconds\r\n * osc.amp(0, 0.5);\r\n * playing = false;\r\n * backgroundColor = color(255,0,255);\r\n * }\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Oscillator = function(freq, type) {\r\n if (typeof freq === 'string') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n } if (typeof type === 'number') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n }\r\n this.started = false;\r\n\r\n // components\r\n this.phaseAmount = undefined;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.f = freq || 440.0; // frequency\r\n this.oscillator.type = type || 'sine';\r\n this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime);\r\n\r\n // connections\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this._freqMods = []; // modulators connected to this oscillator's frequency\r\n\r\n // set default output gain to 0.5\r\n this.output.gain.value = 0.5;\r\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\r\n\r\n this.oscillator.connect(this.output);\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.connection = p5sound.input; // connect to p5sound by default\r\n this.panner = new p5.Panner(this.output, this.connection, 1);\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.output];\r\n\r\n // add to the soundArray so we can dispose of the osc later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start an oscillator. Accepts an optional parameter to\r\n * determine how long (in seconds from now) until the\r\n * oscillator starts.\r\n *\r\n * @method start\r\n * @for p5.Oscillator\r\n * @param {Number} [time] startTime in seconds from now.\r\n * @param {Number} [frequency] frequency in Hz.\r\n */\r\n p5.Oscillator.prototype.start = function(time, f) {\r\n if (this.started) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n }\r\n if (!this.started) {\r\n var freq = f || this.f;\r\n var type = this.oscillator.type;\r\n\r\n // set old osc free to be garbage collected (memory)\r\n if (this.oscillator) {\r\n this.oscillator.disconnect();\r\n delete this.oscillator;\r\n }\r\n\r\n // var detune = this.oscillator.frequency.value;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.oscillator.frequency.value = Math.abs(freq);\r\n this.oscillator.type = type;\r\n // this.oscillator.detune.value = detune;\r\n this.oscillator.connect(this.output);\r\n time = time || 0;\r\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\r\n this.freqNode = this.oscillator.frequency;\r\n\r\n // if other oscillators are already connected to this osc's freq\r\n for (var i in this._freqMods) {\r\n if (typeof this._freqMods[i].connect !== 'undefined') {\r\n this._freqMods[i].connect(this.oscillator.frequency);\r\n }\r\n }\r\n\r\n this.started = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop an oscillator. Accepts an optional parameter\r\n * to determine how long (in seconds from now) until the\r\n * oscillator stops.\r\n *\r\n * @method stop\r\n * @for p5.Oscillator\r\n * @param {Number} secondsFromNow Time, in seconds from now.\r\n */\r\n p5.Oscillator.prototype.stop = function(time) {\r\n if (this.started) {\r\n var t = time || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.oscillator.stop(t + now);\r\n this.started = false;\r\n }\r\n };\r\n\r\n /**\r\n * Set the amplitude between 0 and 1.0. Or, pass in an object\r\n * such as an oscillator to modulate amplitude with an audio signal.\r\n *\r\n * @method amp\r\n * @for p5.Oscillator\r\n * @param {Number|Object} vol between 0 and 1.0\r\n * or a modulating signal/oscillator\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {AudioParam} gain If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's\r\n * gain/amplitude/volume)\r\n */\r\n p5.Oscillator.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var self = this;\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n\r\n else if (vol) {\r\n vol.connect(self.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // these are now the same thing\r\n p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;\r\n\r\n p5.Oscillator.prototype.getAmp = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set frequency of an oscillator to a value. Or, pass in an object\r\n * such as an oscillator to modulate the frequency with an audio signal.\r\n *\r\n * @method freq\r\n * @for p5.Oscillator\r\n * @param {Number|Object} Frequency Frequency in Hz\r\n * or modulating signal/oscillator\r\n * @param {Number} [rampTime] Ramp time (in seconds)\r\n * @param {Number} [timeFromNow] Schedule this event to happen\r\n * at x seconds from now\r\n * @return {AudioParam} Frequency If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's frequency\r\n * @example\r\n *
\r\n * var osc = new p5.Oscillator(300);\r\n * osc.start();\r\n * osc.freq(40, 10);\r\n *
\r\n */\r\n p5.Oscillator.prototype.freq = function(val, rampTime, tFromNow) {\r\n if (typeof val === 'number' && !isNaN(val)) {\r\n this.f = val;\r\n var now = p5sound.audiocontext.currentTime;\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var t = now + tFromNow + rampTime;\r\n // var currentFreq = this.oscillator.frequency.value;\r\n // this.oscillator.frequency.cancelScheduledValues(now);\r\n\r\n if (rampTime === 0) {\r\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\r\n } else {\r\n if (val > 0 ) {\r\n this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);\r\n } else {\r\n this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now);\r\n }\r\n }\r\n\r\n // reset phase if oscillator has a phase\r\n if (this.phaseAmount) {\r\n this.phase(this.phaseAmount);\r\n }\r\n\r\n } else if (val) {\r\n if (val.output) {\r\n val = val.output;\r\n }\r\n val.connect(this.oscillator.frequency);\r\n\r\n // keep track of what is modulating this param\r\n // so it can be re-connected if\r\n this._freqMods.push( val );\r\n } else {\r\n // return the Frequency Node\r\n return this.oscillator.frequency;\r\n }\r\n };\r\n\r\n p5.Oscillator.prototype.getFreq = function() {\r\n return this.oscillator.frequency.value;\r\n };\r\n\r\n /**\r\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\r\n *\r\n * @method setType\r\n * @for p5.Oscillator\r\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\r\n */\r\n p5.Oscillator.prototype.setType = function(type) {\r\n this.oscillator.type = type;\r\n };\r\n\r\n p5.Oscillator.prototype.getType = function() {\r\n return this.oscillator.type;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.Oscillator\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.Oscillator.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n this.connection = unit.input;\r\n }\r\n else {\r\n this.panner.connect(unit);\r\n this.connection = unit;\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.Oscillator\r\n */\r\n p5.Oscillator.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n if (this.output) {\r\n this.output.connect(this.panner);\r\n }\r\n }\r\n this.oscMods = [];\r\n };\r\n\r\n /**\r\n * Pan between Left (-1) and Right (1)\r\n *\r\n * @method pan\r\n * @for p5.Oscillator\r\n * @param {Number} panning Number between -1 and 1\r\n * @param {Number} timeFromNow schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Oscillator.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n p5.Oscillator.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n // get rid of the oscillator\r\n p5.Oscillator.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.oscillator) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n this.disconnect();\r\n this.panner = null;\r\n this.oscillator = null;\r\n }\r\n // if it is a Pulse\r\n if (this.osc2) {\r\n this.osc2.dispose();\r\n }\r\n };\r\n\r\n /**\r\n * Set the phase of an oscillator between 0.0 and 1.0.\r\n * In this implementation, phase is a delay time\r\n * based on the oscillator's current frequency.\r\n *\r\n * @method phase\r\n * @for p5.Oscillator\r\n * @param {Number} phase float between 0.0 and 1.0\r\n */\r\n p5.Oscillator.prototype.phase = function(p) {\r\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1/this.f);\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n this.phaseAmount = p;\r\n\r\n if (!this.dNode) {\r\n // create a delay node\r\n this.dNode = p5sound.audiocontext.createDelay();\r\n // put the delay node in between output and panner\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.dNode);\r\n this.dNode.connect(this.output);\r\n }\r\n\r\n // set delay time to match phase:\r\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\r\n };\r\n\r\n // ========================== //\r\n // SIGNAL MATH FOR MODULATION //\r\n // ========================== //\r\n\r\n // return sigChain(this, scale, thisChain, nextChain, Scale);\r\n var sigChain = function(o, mathObj, thisChain, nextChain, type) {\r\n var chainSource = o.oscillator;\r\n // if this type of math already exists in the chain, replace it\r\n for (var i in o.mathOps) {\r\n if (o.mathOps[i] instanceof type) {\r\n chainSource.disconnect();\r\n o.mathOps[i].dispose();\r\n thisChain = i;\r\n // assume nextChain is output gain node unless...\r\n if (thisChain < o.mathOps.length - 2) {\r\n nextChain = o.mathOps[i+1];\r\n }\r\n }\r\n }\r\n if (thisChain === o.mathOps.length - 1) {\r\n o.mathOps.push(nextChain);\r\n }\r\n // assume source is the oscillator unless i > 0\r\n if (i > 0) {\r\n chainSource = o.mathOps[i-1];\r\n }\r\n chainSource.disconnect();\r\n chainSource.connect(mathObj);\r\n mathObj.connect(nextChain);\r\n o.mathOps[thisChain] = mathObj;\r\n return o;\r\n };\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method again\r\n * will override the initial add() with a new value.\r\n *\r\n * @method add\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n *\r\n */\r\n p5.Oscillator.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Oscillator's output amplitude\r\n * by a fixed value (i.e. turn it up!). Calling this method\r\n * again will override the initial mult() with a new value.\r\n *\r\n * @method mult\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with multiplied output\r\n */\r\n p5.Oscillator.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this oscillator's amplitude values to a given\r\n * range, and return the oscillator. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Oscillator\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n */\r\n p5.Oscillator.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, scale, thisChain, nextChain, Scale);\r\n\r\n // this.output.disconnect();\r\n // this.output.connect(scale)\r\n };\r\n\r\n // ============================== //\r\n // SinOsc, TriOsc, SqrOsc, SawOsc //\r\n // ============================== //\r\n\r\n /**\r\n * Constructor: new p5.SinOsc().\r\n * This creates a Sine Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sine')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sine').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SinOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SinOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sine');\r\n };\r\n\r\n p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.TriOsc().\r\n * This creates a Triangle Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('triangle')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('triangle').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.TriOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.TriOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'triangle');\r\n };\r\n\r\n p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SawOsc().\r\n * This creates a SawTooth Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sawtooth')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sawtooth').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SawOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SawOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sawtooth');\r\n };\r\n\r\n p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SqrOsc().\r\n * This creates a Square Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('square')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('square').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SqrOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SqrOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'square');\r\n };\r\n\r\n p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline class for scheduling and maintaining state\n\t * along a timeline. All events must have a \"time\" property. \n\t * Internally, events are stored in time order for fast \n\t * retrieval.\n\t * @extends {Tone}\n\t * @param {Positive} [memory=Infinity] The number of previous events that are retained.\n\t */\n\tTone.Timeline = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"memory\"], Tone.Timeline.defaults);\n\n\t\t/**\n\t\t * The array of scheduled timeline events\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._timeline = [];\n\n\t\t/**\n\t\t * An array of items to remove from the list. \n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._toRemove = [];\n\n\t\t/**\n\t\t * Flag if the tieline is mid iteration\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._iterating = false;\n\n\t\t/**\n\t\t * The memory of the timeline, i.e.\n\t\t * how many events in the past it will retain\n\t\t * @type {Positive}\n\t\t */\n\t\tthis.memory = options.memory;\n\t};\n\n\tTone.extend(Tone.Timeline);\n\n\t/**\n\t * the default parameters\n\t * @static\n\t * @const\n\t */\n\tTone.Timeline.defaults = {\n\t\t\"memory\" : Infinity\n\t};\n\n\t/**\n\t * The number of items in the timeline.\n\t * @type {Number}\n\t * @memberOf Tone.Timeline#\n\t * @name length\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Timeline.prototype, \"length\", {\n\t\tget : function(){\n\t\t\treturn this._timeline.length;\n\t\t}\n\t});\n\n\t/**\n\t * Insert an event object onto the timeline. Events must have a \"time\" attribute.\n\t * @param {Object} event The event object to insert into the \n\t * timeline. \n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.add = function(event){\n\t\t//the event needs to have a time attribute\n\t\tif (this.isUndef(event.time)){\n\t\t\tthrow new Error(\"Tone.Timeline: events must have a time attribute\");\n\t\t}\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(event.time);\n\t\t\tthis._timeline.splice(index + 1, 0, event);\n\t\t} else {\n\t\t\tthis._timeline.push(event);\t\t\t\n\t\t}\n\t\t//if the length is more than the memory, remove the previous ones\n\t\tif (this.length > this.memory){\n\t\t\tvar diff = this.length - this.memory;\n\t\t\tthis._timeline.splice(0, diff);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove an event from the timeline.\n\t * @param {Object} event The event object to remove from the list.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.remove = function(event){\n\t\tif (this._iterating){\n\t\t\tthis._toRemove.push(event);\n\t\t} else {\n\t\t\tvar index = this._timeline.indexOf(event);\n\t\t\tif (index !== -1){\n\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the nearest event whose time is less than or equal to the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object set after that time.\n\t */\n\tTone.Timeline.prototype.get = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index !== -1){\n\t\t\treturn this._timeline[index];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Return the first event in the timeline without removing it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.peek = function(){\n\t\treturn this._timeline[0];\n\t};\n\n\t/**\n\t * Return the first event in the timeline and remove it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.shift = function(){\n\t\treturn this._timeline.shift();\n\t};\n\n\t/**\n\t * Get the event which is scheduled after the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object after the given time\n\t */\n\tTone.Timeline.prototype.getAfter = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index + 1 < this._timeline.length){\n\t\t\treturn this._timeline[index + 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Get the event before the event at the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object before the given time\n\t */\n\tTone.Timeline.prototype.getBefore = function(time){\n\t\tvar len = this._timeline.length;\n\t\t//if it's after the last item, return the last item\n\t\tif (len > 0 && this._timeline[len - 1].time < time){\n\t\t\treturn this._timeline[len - 1];\n\t\t}\n\t\tvar index = this._search(time);\n\t\tif (index - 1 >= 0){\n\t\t\treturn this._timeline[index - 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Cancel events after the given time\n\t * @param {Number} time The time to query.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancel = function(after){\n\t\tif (this._timeline.length > 1){\n\t\t\tvar index = this._search(after);\n\t\t\tif (index >= 0){\n\t\t\t\tif (this._timeline[index].time === after){\n\t\t\t\t\t//get the first item with that time\n\t\t\t\t\tfor (var i = index; i >= 0; i--){\n\t\t\t\t\t\tif (this._timeline[i].time === after){\n\t\t\t\t\t\t\tindex = i;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index);\n\t\t\t\t} else {\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t} else if (this._timeline.length === 1){\n\t\t\t//the first item's time\n\t\t\tif (this._timeline[0].time >= after){\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancel events before or equal to the given time.\n\t * @param {Number} time The time to cancel before.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancelBefore = function(time){\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(time);\n\t\t\tif (index >= 0){\n\t\t\t\tthis._timeline = this._timeline.slice(index + 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Does a binary serach on the timeline array and returns the \n\t * nearest event index whose time is after or equal to the given time.\n\t * If a time is searched before the first index in the timeline, -1 is returned.\n\t * If the time is after the end, the index of the last item is returned.\n\t * @param {Number} time \n\t * @return {Number} the index in the timeline array \n\t * @private\n\t */\n\tTone.Timeline.prototype._search = function(time){\n\t\tvar beginning = 0;\n\t\tvar len = this._timeline.length;\n\t\tvar end = len;\n\t\tif (len > 0 && this._timeline[len - 1].time <= time){\n\t\t\treturn len - 1;\n\t\t}\n\t\twhile (beginning < end){\n\t\t\t// calculate the midpoint for roughly equal partition\n\t\t\tvar midPoint = Math.floor(beginning + (end - beginning) / 2);\n\t\t\tvar event = this._timeline[midPoint];\n\t\t\tvar nextEvent = this._timeline[midPoint + 1];\n\t\t\tif (event.time === time){\n\t\t\t\t//choose the last one that has the same time\n\t\t\t\tfor (var i = midPoint; i < this._timeline.length; i++){\n\t\t\t\t\tvar testEvent = this._timeline[i];\n\t\t\t\t\tif (testEvent.time === time){\n\t\t\t\t\t\tmidPoint = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time < time && nextEvent.time > time){\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time > time){\n\t\t\t\t//search lower\n\t\t\t\tend = midPoint;\n\t\t\t} else if (event.time < time){\n\t\t\t\t//search upper\n\t\t\t\tbeginning = midPoint + 1;\n\t\t\t} \n\t\t}\n\t\treturn -1;\n\t};\n\n\t/**\n\t * Internal iterator. Applies extra safety checks for \n\t * removing items from the array. \n\t * @param {Function} callback \n\t * @param {Number=} lowerBound \n\t * @param {Number=} upperBound \n\t * @private\n\t */\n\tTone.Timeline.prototype._iterate = function(callback, lowerBound, upperBound){\n\t\tthis._iterating = true;\n\t\tlowerBound = this.defaultArg(lowerBound, 0);\n\t\tupperBound = this.defaultArg(upperBound, this._timeline.length - 1);\n\t\tfor (var i = lowerBound; i <= upperBound; i++){\n\t\t\tcallback(this._timeline[i]);\n\t\t}\n\t\tthis._iterating = false;\n\t\tif (this._toRemove.length > 0){\n\t\t\tfor (var j = 0; j < this._toRemove.length; j++){\n\t\t\t\tvar index = this._timeline.indexOf(this._toRemove[j]);\n\t\t\t\tif (index !== -1){\n\t\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._toRemove = [];\n\t\t}\n\t};\n\n\t/**\n\t * Iterate over everything in the array\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEach = function(callback){\n\t\tthis._iterate(callback);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or before the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachBefore = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(callback, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array after the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAfter = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or after the given time. Similar to \n\t * forEachAfter, but includes the item(s) at the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachFrom = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\t//work backwards until the event time is less than time\n\t\twhile (lowerBound >= 0 && this._timeline[lowerBound].time >= time){\n\t\t\tlowerBound--;\n\t\t}\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at the given time\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAtTime = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(function(event){\n\t\t\t\tif (event.time === time){\n\t\t\t\t\tcallback(event);\n\t\t\t\t} \n\t\t\t}, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._timeline = null;\n\t\tthis._toRemove = null;\n\t};\n\n\treturn Tone.Timeline;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Negate the incoming signal. i.e. an input signal of 10 will output -10\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var neg = new Tone.Negate();\n\t * var sig = new Tone.Signal(-2).connect(neg);\n\t * //output of neg is positive 2. \n\t */\n\tTone.Negate = function(){\n\t\t/**\n\t\t * negation is done by multiplying by -1\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = this.input = this.output = new Tone.Multiply(-1);\n\t};\n\n\tTone.extend(Tone.Negate, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Negate} this\n\t */\n\tTone.Negate.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Negate;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Multiply\", \"Tone/signal/WaveShaper\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class GreaterThanZero outputs 1 when the input is strictly greater than zero\n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var gt0 = new Tone.GreaterThanZero();\n\t * var sig = new Tone.Signal(0.01).connect(gt0);\n\t * //the output of gt0 is 1. \n\t * sig.value = 0;\n\t * //the output of gt0 is 0. \n\t */\n\tTone.GreaterThanZero = function(){\n\t\t\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._thresh = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val <= 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}, 127);\n\n\t\t/**\n\t\t * scale the first thresholded signal by a large value.\n\t\t * this will help with values which are very close to 0\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(10000);\n\n\t\t//connections\n\t\tthis._scale.connect(this._thresh);\n\t};\n\n\tTone.extend(Tone.GreaterThanZero, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThanZero} this\n\t */\n\tTone.GreaterThanZero.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\tthis._thresh.dispose();\n\t\tthis._thresh = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThanZero;\n});","define([\"Tone/core/Tone\", \"Tone/signal/TimelineSignal\", \"Tone/core/TimelineState\", \n\t\"Tone/core/Emitter\", \"Tone/core/Context\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A sample accurate clock which provides a callback at the given rate. \n\t * While the callback is not sample-accurate (it is still susceptible to\n\t * loose JS timing), the time passed in as the argument to the callback\n\t * is precise. For most applications, it is better to use Tone.Transport\n\t * instead of the Clock by itself since you can synchronize multiple callbacks.\n\t *\n\t * \t@constructor\n\t * @extends {Tone.Emitter}\n\t * \t@param {function} callback The callback to be invoked with the time of the audio event\n\t * \t@param {Frequency} frequency The rate of the callback\n\t * \t@example\n\t * //the callback will be invoked approximately once a second\n\t * //and will print the time exactly once a second apart.\n\t * var clock = new Tone.Clock(function(time){\n\t * \tconsole.log(time);\n\t * }, 1);\n\t */\n\tTone.Clock = function(){\n\n\t\tTone.Emitter.call(this);\n\n\t\tvar options = this.optionsObject(arguments, [\"callback\", \"frequency\"], Tone.Clock.defaults);\n\n\t\t/**\n\t\t * The callback function to invoke at the scheduled tick.\n\t\t * @type {Function}\n\t\t */\n\t\tthis.callback = options.callback;\n\n\t\t/**\n\t\t * The next time the callback is scheduled.\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._nextTick = 0;\n\n\t\t/**\n\t\t * The last state of the clock.\n\t\t * @type {State}\n\t\t * @private\n\t\t */\n\t\tthis._lastState = Tone.State.Stopped;\n\n\t\t/**\n\t\t * The rate the callback function should be invoked. \n\t\t * @type {BPM}\n\t\t * @signal\n\t\t */\n\t\tthis.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);\n\t\tthis._readOnly(\"frequency\");\n\n\t\t/**\n\t\t * The number of times the callback was invoked. Starts counting at 0\n\t\t * and increments after the callback was invoked. \n\t\t * @type {Ticks}\n\t\t * @readOnly\n\t\t */\n\t\tthis.ticks = 0;\n\n\t\t/**\n\t\t * The state timeline\n\t\t * @type {Tone.TimelineState}\n\t\t * @private\n\t\t */\n\t\tthis._state = new Tone.TimelineState(Tone.State.Stopped);\n\n\t\t/**\n\t\t * The loop function bound to its context. \n\t\t * This is necessary to remove the event in the end.\n\t\t * @type {Function}\n\t\t * @private\n\t\t */\n\t\tthis._boundLoop = this._loop.bind(this);\n\n\t\t//bind a callback to the worker thread\n \tthis.context.on(\"tick\", this._boundLoop);\n\t};\n\n\tTone.extend(Tone.Clock, Tone.Emitter);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Clock.defaults = {\n\t\t\"callback\" : Tone.noOp,\n\t\t\"frequency\" : 1,\n\t\t\"lookAhead\" : \"auto\",\n\t};\n\n\t/**\n\t * Returns the playback state of the source, either \"started\", \"stopped\" or \"paused\".\n\t * @type {Tone.State}\n\t * @readOnly\n\t * @memberOf Tone.Clock#\n\t * @name state\n\t */\n\tObject.defineProperty(Tone.Clock.prototype, \"state\", {\n\t\tget : function(){\n\t\t\treturn this._state.getValueAtTime(this.now());\n\t\t}\n\t});\n\n\t/**\n\t * Start the clock at the given time. Optionally pass in an offset\n\t * of where to start the tick counter from.\n\t * @param {Time} time The time the clock should start\n\t * @param {Ticks=} offset Where the tick counter starts counting from.\n\t * @return {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.start = function(time, offset){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) !== Tone.State.Started){\n\t\t\tthis._state.add({\n\t\t\t\t\"state\" : Tone.State.Started, \n\t\t\t\t\"time\" : time,\n\t\t\t\t\"offset\" : offset\n\t\t\t});\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * Stop the clock. Stopping the clock resets the tick counter to 0.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t * @example\n\t * clock.stop();\n\t */\n\tTone.Clock.prototype.stop = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tthis._state.cancel(time);\n\t\tthis._state.setStateAtTime(Tone.State.Stopped, time);\n\t\treturn this;\t\n\t};\n\n\n\t/**\n\t * Pause the clock. Pausing does not reset the tick counter.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.pause = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) === Tone.State.Started){\n\t\t\tthis._state.setStateAtTime(Tone.State.Paused, time);\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * The scheduling loop.\n\t * @param {Number} time The current page time starting from 0\n\t * when the page was loaded.\n\t * @private\n\t */\n\tTone.Clock.prototype._loop = function(){\n\t\t//get the frequency value to compute the value of the next loop\n\t\tvar now = this.now();\n\t\t//if it's started\n\t\tvar lookAhead = this.context.lookAhead;\n\t\tvar updateInterval = this.context.updateInterval;\n\t\tvar lagCompensation = this.context.lag * 2;\n\t\tvar loopInterval = now + lookAhead + updateInterval + lagCompensation;\n\t\twhile (loopInterval > this._nextTick && this._state){\n\t\t\tvar currentState = this._state.getValueAtTime(this._nextTick);\n\t\t\tif (currentState !== this._lastState){\n\t\t\t\tthis._lastState = currentState;\n\t\t\t\tvar event = this._state.get(this._nextTick);\n\t\t\t\t// emit an event\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\t//correct the time\n\t\t\t\t\tthis._nextTick = event.time;\n\t\t\t\t\tif (!this.isUndef(event.offset)){\n\t\t\t\t\t\tthis.ticks = event.offset;\n\t\t\t\t\t}\n\t\t\t\t\tthis.emit(\"start\", event.time, this.ticks);\n\t\t\t\t} else if (currentState === Tone.State.Stopped){\n\t\t\t\t\tthis.ticks = 0;\n\n\t\t\t\t\tthis.emit(\"stop\", event.time);\n\t\t\t\t} else if (currentState === Tone.State.Paused){\n\t\t\t\t\tthis.emit(\"pause\", event.time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar tickTime = this._nextTick;\n\t\t\tif (this.frequency){\n\t\t\t\tthis._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\tthis.callback(tickTime);\n\t\t\t\t\tthis.ticks++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state at the given time.\n\t * @param {Time} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t * @example\n\t * clock.start(\"+0.1\");\n\t * clock.getStateAtTime(\"+0.1\"); //returns \"started\"\n\t */\n\tTone.Clock.prototype.getStateAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\treturn this._state.getValueAtTime(time);\n\t};\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.dispose = function(){\n\t\tTone.Emitter.prototype.dispose.call(this);\n\t\tthis.context.off(\"tick\", this._boundLoop);\n\t\tthis._writable(\"frequency\");\n\t\tthis.frequency.dispose();\n\t\tthis.frequency = null;\n\t\tthis._boundLoop = null;\n\t\tthis._nextTick = Infinity;\n\t\tthis.callback = null;\n\t\tthis._state.dispose();\n\t\tthis._state = null;\n\t};\n\n\treturn Tone.Clock;\n});","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var AudioVoice = require('audioVoice');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n var DEFAULT_SUSTAIN = 0.15;\r\n\r\n /**\r\n * A MonoSynth is used as a single voice for sound synthesis.\r\n * This is a class to be used in conjunction with the PolySynth\r\n * class. Custom synthetisers should be built inheriting from\r\n * this class.\r\n *\r\n * @class p5.MonoSynth\r\n * @constructor\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 0.25;\r\n * // velocity (volume, from 0 to 1)\r\n * var v = 0.2;\r\n *\r\n * monoSynth.play(\"G3\", v, time, dur);\r\n * monoSynth.play(\"C4\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n\r\n p5.MonoSynth = function () {\r\n AudioVoice.call(this);\r\n\r\n this.oscillator = new p5.Oscillator();\r\n\r\n this.env = new p5.Envelope();\r\n this.env.setRange(1, 0);\r\n this.env.setExp(true);\r\n\r\n //set params\r\n this.setADSR(0.02, 0.25, 0.05, 0.35);\r\n\r\n // oscillator --> env --> this.output (gain) --> p5.soundOut\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.output);\r\n\r\n this.env.disconnect();\r\n this.env.setInput(this.output.gain);\r\n\r\n // reset oscillator gain to 1.0\r\n this.oscillator.output.gain.value = 1.0;\r\n\r\n this.oscillator.start();\r\n this.connect();\r\n\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);\r\n\r\n /**\r\n * Play tells the MonoSynth to start playing a note. This method schedules\r\n * the calling of .triggerAttack and .triggerRelease.\r\n *\r\n * @method play\r\n * @for p5.MonoSynth\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 1/6;\r\n * // note velocity (volume, from 0 to 1)\r\n * var v = random();\r\n *\r\n * monoSynth.play(\"Fb3\", v, 0, dur);\r\n * monoSynth.play(\"Gb3\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n *\r\n */\r\n p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) {\r\n this.triggerAttack(note, velocity, ~~secondsFromNow);\r\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @method triggerAttack\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n var secondsFromNow = ~~secondsFromNow;\r\n var freq = noteToFreq(note);\r\n var vel = velocity || 0.1;\r\n this.oscillator.freq(freq, 0, secondsFromNow);\r\n this.env.ramp(this.output.gain, secondsFromNow, vel);\r\n };\r\n\r\n /**\r\n * Trigger the release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @method triggerRelease\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) {\r\n var secondsFromNow = secondsFromNow || 0;\r\n this.env.ramp(this.output.gain, secondsFromNow, 0);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.MonoSynth\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n */\r\n p5.MonoSynth.prototype.setADSR = function (attack,decay,sustain,release) {\r\n this.env.setADSR(attack, decay, sustain, release);\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters\r\n * @property {Number} attack\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} decay\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} sustain\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} release\r\n * @for p5.MonoSynth\r\n */\r\n Object.defineProperties(p5.MonoSynth.prototype, {\r\n 'attack': {\r\n get : function() {\r\n return this.env.aTime;\r\n },\r\n set : function(attack) {\r\n this.env.setADSR(attack, this.env.dTime,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'decay': {\r\n get : function() {\r\n return this.env.dTime;\r\n },\r\n set : function(decay) {\r\n this.env.setADSR(this.env.aTime, decay,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'sustain': {\r\n get : function() {\r\n return this.env.sPercent;\r\n },\r\n set : function(sustain) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n sustain, this.env.rTime);\r\n }\r\n },\r\n 'release': {\r\n get : function() {\r\n return this.env.rTime;\r\n },\r\n set : function(release) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n this.env.sPercent, release);\r\n }\r\n },\r\n });\r\n\r\n\r\n /**\r\n * MonoSynth amp\r\n * @method amp\r\n * @for p5.MonoSynth\r\n * @param {Number} vol desired volume\r\n * @param {Number} [rampTime] Time to reach new volume\r\n * @return {Number} new volume value\r\n */\r\n p5.MonoSynth.prototype.amp = function(vol, rampTime) {\r\n var t = rampTime || 0;\r\n if (typeof vol !== 'undefined') {\r\n this.oscillator.amp(vol, t);\r\n }\r\n return this.oscillator.amp().value;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.MonoSynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n\r\n p5.MonoSynth.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.dispose = function() {\r\n AudioVoice.prototype.dispose.apply(this);\r\n\r\n if (this.env) {\r\n this.env.dispose();\r\n }\r\n if (this.oscillator) {\r\n this.oscillator.dispose();\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\ndefine(function() {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * Base class for monophonic synthesizers. Any extensions of this class\r\n * should follow the API and implement the methods below in order to\r\n * remain compatible with p5.PolySynth();\r\n *\r\n * @class p5.AudioVoice\r\n * @constructor\r\n */\r\n p5.AudioVoice = function () {\r\n\t this.ac = p5sound.audiocontext;\r\n\t this.output = this.ac.createGain();\r\n\t this.connect();\r\n\t p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.amp = function(vol, rampTime) {\r\n };\r\n\r\n /**\r\n * Connect to p5 objects or Web Audio Nodes\r\n * @method connect\r\n * @for p5.AudioVoice\r\n * @param {Object} unit\r\n */\r\n p5.AudioVoice.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect from soundOut\r\n * @method disconnect\r\n * @for p5.AudioVoice\r\n */\r\n p5.AudioVoice.prototype.disconnect = function() {\r\n this.output.disconnect();\r\n };\r\n\r\n p5.AudioVoice.prototype.dispose = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n return p5.AudioVoice;\r\n});\r\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n /**\r\n * An AudioVoice is used as a single voice for sound synthesis.\r\n * The PolySynth class holds an array of AudioVoice, and deals\r\n * with voices allocations, with setting notes to be played, and\r\n * parameters to be set.\r\n *\r\n * @class p5.PolySynth\r\n * @constructor\r\n *\r\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\r\n * the AudioVoice class. Defaults to p5.MonoSynth\r\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 1.5;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * // notes can overlap with each other\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, time += 1/3, dur);\r\n * polySynth.play(\"G3\", vel, time += 1/3, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n p5.PolySynth = function(audioVoice, maxVoices) {\r\n //audiovoices will contain maxVoices many monophonic synths\r\n this.audiovoices = [];\r\n\r\n /**\r\n * An object that holds information about which notes have been played and\r\n * which notes are currently being played. New notes are added as keys\r\n * on the fly. While a note has been attacked, but not released, the value of the\r\n * key is the audiovoice which is generating that note. When notes are released,\r\n * the value of the key becomes undefined.\r\n * @property notes\r\n */\r\n this.notes = {};\r\n\r\n //indices of the most recently used, and least recently used audiovoice\r\n this._newest = 0;\r\n this._oldest = 0;\r\n\r\n /**\r\n * A PolySynth must have at least 1 voice, defaults to 8\r\n * @property polyvalue\r\n */\r\n this.maxVoices = maxVoices || 8;\r\n\r\n /**\r\n * Monosynth that generates the sound for each note that is triggered. The\r\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\r\n * @property AudioVoice\r\n */\r\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\r\n\r\n /**\r\n * This value must only change as a note is attacked or released. Due to delay\r\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\r\n\t * @private\r\n * @property {Tone.TimelineSignal} _voicesInUse\r\n */\r\n this._voicesInUse = new TimelineSignal(0);\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n this.connect();\r\n\r\n //Construct the appropriate number of audiovoices\r\n this._allocateVoices();\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Construct the appropriate number of audiovoices\r\n * @private\r\n * @for p5.PolySynth\r\n * @method _allocateVoices\r\n */\r\n p5.PolySynth.prototype._allocateVoices = function() {\r\n for(var i = 0; i< this.maxVoices; i++) {\r\n this.audiovoices.push(new this.AudioVoice());\r\n this.audiovoices[i].disconnect();\r\n this.audiovoices[i].connect(this.output);\r\n }\r\n };\r\n\r\n /**\r\n * Play a note by triggering noteAttack and noteRelease with sustain time\r\n *\r\n * @method play\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 0.1;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, 0, dur);\r\n * polySynth.play(\"G3\", vel, 0, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.play = function (note,velocity, secondsFromNow, susTime) {\r\n var susTime = susTime || 1;\r\n this.noteAttack(note, velocity, secondsFromNow);\r\n this.noteRelease(note, secondsFromNow + susTime);\r\n };\r\n\r\n\r\n /**\r\n * noteADSR sets the envelope for a specific note that has just been triggered.\r\n * Using this method modifies the envelope of whichever audiovoice is being used\r\n * to play the desired note. The envelope should be reset before noteRelease is called\r\n * in order to prevent the modified envelope from being used on other notes.\r\n *\r\n * @method noteADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [note] Midi note on which ADSR should be set.\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n\r\n p5.PolySynth.prototype.noteADSR = function (note,a,d,s,r,timeFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var timeFromNow = timeFromNow || 0;\r\n var t = now + timeFromNow\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].setADSR(a,d,s,r);\r\n };\r\n\r\n\r\n /**\r\n * Set the PolySynths global envelope. This method modifies the envelopes of each\r\n * monosynth so that all notes are played with this envelope.\r\n *\r\n * @method setADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n p5.PolySynth.prototype.setADSR = function(a,d,s,r) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.setADSR(a,d,s,r);\r\n });\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of a MonoSynth.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @method noteAttack\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\r\n * @param {Number} [secondsFromNow] time from now (in seconds)\r\n * @example\r\n *
\r\n * var polySynth = new p5.PolySynth();\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) {\r\n //this value goes to the audiovoices which handle their own scheduling\r\n var secondsFromNow = ~~secondsFromNow;\r\n\r\n //this value is used by this._voicesInUse\r\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\r\n\r\n //Convert note to frequency if necessary. This is because entries into this.notes\r\n //should be based on frequency for the sake of consistency.\r\n var note = noteToFreq(_note);\r\n var velocity = _velocity || 0.1;\r\n\r\n var currentVoice;\r\n\r\n //Release the note if it is already playing\r\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\r\n this.noteRelease(note, 0);\r\n }\r\n\r\n //Check to see how many voices are in use at the time the note will start\r\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\r\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\r\n }\r\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\r\n //with a new note\r\n else {\r\n currentVoice = this._oldest;\r\n\r\n var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value);\r\n this.noteRelease(oldestNote);\r\n this._oldest = ( this._oldest + 1 ) % (this.maxVoices - 1);\r\n }\r\n\r\n //Overrite the entry in the notes object. A note (frequency value)\r\n //corresponds to the index of the audiovoice that is playing it\r\n this.notes[note] = new TimelineSignal();\r\n this.notes[note].setValueAtTime(currentVoice, acTime);\r\n\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //Add 1 and schedule this value at time 't', when this note will start playing\r\n var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value;\r\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\r\n\r\n //Then update all scheduled values that follow to increase by 1\r\n this._updateAfter(acTime, 1);\r\n\r\n this._newest = currentVoice;\r\n //The audiovoice handles the actual scheduling of the note\r\n if (typeof velocity === 'number') {\r\n var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2;\r\n velocity = velocity > maxRange ? maxRange : velocity;\r\n }\r\n this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);\r\n };\r\n\r\n /**\r\n * Private method to ensure accurate values of this._voicesInUse\r\n * Any time a new value is scheduled, it is necessary to increment all subsequent\r\n * scheduledValues after attack, and decrement all subsequent\r\n * scheduledValues after release\r\n *\r\n * @private\r\n * @for p5.PolySynth\r\n * @param {[type]} time [description]\r\n * @param {[type]} value [description]\r\n * @return {[type]} [description]\r\n */\r\n p5.PolySynth.prototype._updateAfter = function(time, value) {\r\n if(this._voicesInUse._searchAfter(time) === null) {\r\n return;\r\n } else{\r\n this._voicesInUse._searchAfter(time).value += value;\r\n var nextTime = this._voicesInUse._searchAfter(time).time;\r\n this._updateAfter(nextTime, value);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Trigger the Release of an AudioVoice note. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method noteRelease\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * If no value is provided, all notes will be released.\r\n * @param {Number} [secondsFromNow] time to trigger the release\r\n * @example\r\n *
\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n * var polySynth = new p5.PolySynth();\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n *\r\n */\r\n p5.PolySynth.prototype.noteRelease = function (_note,secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n // if a note value is not provided, release all voices\r\n if (!_note) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.triggerRelease(tFromNow)\r\n });\r\n this._voicesInUse.setValueAtTime(0, t);\r\n for (var n in this.notes) {\r\n this.notes[n].dispose();\r\n delete this.notes[n];\r\n }\r\n return;\r\n }\r\n\r\n //Make sure note is in frequency inorder to query the this.notes object\r\n var note = noteToFreq(_note);\r\n\r\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\r\n console.warn('Cannot release a note that is not already playing');\r\n } else {\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //subtract 1 and schedule this value at time 't', when this note will stop playing\r\n var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);\r\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\r\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\r\n if (previousVal > 0) {\r\n this._updateAfter(t, -1);\r\n }\r\n\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].triggerRelease(tFromNow);\r\n this.notes[note].dispose();\r\n delete this.notes[note];\r\n\r\n this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\r\n }\r\n\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.PolySynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.PolySynth.prototype.connect = function (unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.dispose = function() {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.dispose();\r\n });\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n require('audioworklet-polyfill');\r\n require('shims');\r\n require('audiocontext');\r\n var p5SOUND = require('master');\r\n require('helpers');\r\n require('errorHandler');\r\n require('audioWorklet');\r\n require('panner');\r\n require('soundfile');\r\n require('amplitude');\r\n require('fft');\r\n require('signal');\r\n require('oscillator');\r\n require('envelope');\r\n require('pulse');\r\n require('noise');\r\n require('audioin');\r\n require('filter');\r\n require('eq');\r\n require('panner3d');\r\n require('listener3d');\r\n require('delay');\r\n require('reverb');\r\n require('metro');\r\n require('looper');\r\n require('soundLoop');\r\n require('compressor');\r\n require('soundRecorder');\r\n require('peakDetect');\r\n require('gain');\r\n require('monosynth');\r\n require('polysynth');\r\n require('distortion');\r\n require('audioVoice');\r\n require('monosynth');\r\n require('polysynth');\r\n\r\n return p5SOUND;\r\n\r\n});\r\n","!function(){var e,t=[];function r(e){var r=this,n={},i=-1;this.parameters.forEach(function(e,o){var s=t[++i]||(t[i]=new Float32Array(r.bufferSize));s.fill(e.value),n[o]=s}),this.processor.realm.exec(\"self.sampleRate=sampleRate=\"+this.context.sampleRate+\";self.currentTime=currentTime=\"+this.context.currentTime);var s=o(e.inputBuffer),a=o(e.outputBuffer);this.instance.process([s],[a],n)}function o(e){for(var t=[],r=0;r= this.sampleLimit) {\\n this.stop();\\n return true;\\n }\\n\\n var input = inputs[0];\\n var output = outputs[0];\\n\\n for (var channel = 0; channel < output.length; ++channel) {\\n var inputChannel = input[channel];\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannel);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n }\\n\\n this.recordedSamples += output[0].length;\\n return true;\\n }\\n }, {\\n key: \\\"record\\\",\\n value: function record(duration) {\\n if (duration) {\\n this.sampleLimit = Math.round(duration * sampleRate);\\n }\\n\\n this.recording = true;\\n }\\n }, {\\n key: \\\"stop\\\",\\n value: function stop() {\\n this.recording = false;\\n var buffers = this.getBuffers();\\n var leftBuffer = buffers[0].buffer;\\n var rightBuffer = buffers[1].buffer;\\n this.port.postMessage({\\n name: 'buffers',\\n leftBuffer: leftBuffer,\\n rightBuffer: rightBuffer\\n }, [leftBuffer, rightBuffer]);\\n this.clear();\\n }\\n }, {\\n key: \\\"getBuffers\\\",\\n value: function getBuffers() {\\n var buffers = [];\\n buffers.push(this.mergeBuffers(this.leftBuffers));\\n buffers.push(this.mergeBuffers(this.rightBuffers));\\n return buffers;\\n }\\n }, {\\n key: \\\"mergeBuffers\\\",\\n value: function mergeBuffers(channelBuffer) {\\n var result = new Float32Array(this.recordedSamples);\\n var offset = 0;\\n var lng = channelBuffer.length;\\n\\n for (var i = 0; i < lng; i++) {\\n var buffer = channelBuffer[i];\\n result.set(buffer, offset);\\n offset += buffer.length;\\n }\\n\\n return result;\\n }\\n }, {\\n key: \\\"clear\\\",\\n value: function clear() {\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.recordedSamples = 0;\\n this.sampleLimit = null;\\n }\\n }]);\\n\\n return RecorderProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);\"","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n\r\n // Stereo panner\r\n // if there is a stereo panner node use it\r\n if(typeof ac.createStereoPanner !== 'undefined') {\r\n p5.Panner = function (input, output) {\r\n this.stereoPanner = this.input = ac.createStereoPanner();\r\n input.connect(this.stereoPanner);\r\n this.stereoPanner.connect(output);\r\n };\r\n\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n\r\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\r\n };\r\n\r\n //not implemented because stereopanner\r\n //node does not require this and will automatically\r\n //convert single channel or multichannel to stereo.\r\n //tested with single and stereo, not with (>2) multichannel\r\n p5.Panner.prototype.inputChannels = function() {};\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.stereoPanner.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.stereoPanner) {\r\n this.stereoPanner.disconnect();\r\n }\r\n };\r\n\r\n } else {\r\n // if there is no createStereoPanner object\r\n // such as in safari 7.1.7 at the time of writing this\r\n // use this method to create the effect\r\n p5.Panner = function(input, output, numInputChannels) {\r\n this.input = ac.createGain();\r\n input.connect(this.input);\r\n\r\n this.left = ac.createGain();\r\n this.right = ac.createGain();\r\n this.left.channelInterpretation = 'discrete';\r\n this.right.channelInterpretation = 'discrete';\r\n\r\n // if input is stereo\r\n if (numInputChannels > 1) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n this.input.connect(this.splitter);\r\n\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n else {\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n }\r\n\r\n this.output = ac.createChannelMerger(2);\r\n this.left.connect(this.output, 0, 1);\r\n this.right.connect(this.output, 0, 0);\r\n this.output.connect(output);\r\n };\r\n\r\n // -1 is left, +1 is right\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n var v = (val + 1) / 2;\r\n var rightVal = Math.cos(v*Math.PI/2);\r\n var leftVal = Math.sin(v * Math.PI/2);\r\n this.left.gain.linearRampToValueAtTime(leftVal, t);\r\n this.right.gain.linearRampToValueAtTime(rightVal, t);\r\n };\r\n\r\n p5.Panner.prototype.inputChannels = function(numChannels) {\r\n if (numChannels === 1) {\r\n this.input.disconnect();\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n } else if (numChannels === 2) {\r\n if (typeof(this.splitter === 'undefined')) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n }\r\n this.input.disconnect();\r\n this.input.connect(this.splitter);\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n };\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.output.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var CustomError = require('errorHandler');\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n var midiToFreq = require('helpers').midiToFreq;\r\n var convertToWav = require('helpers').convertToWav;\r\n\r\n /**\r\n *
SoundFile object with a path to a file.
\r\n *\r\n *
The p5.SoundFile may not be available immediately because\r\n * it loads the file information asynchronously.
\r\n *\r\n *
To do something with the sound as soon as it loads\r\n * pass the name of a function as the second parameter.
\r\n *\r\n *
Only one file path is required. However, audio file formats\r\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\r\n * web browsers. If you want to ensure compatability, instead of a single\r\n * file path, you may include an Array of filepaths, and the browser will\r\n * choose a format that works.
\r\n *\r\n * @class p5.SoundFile\r\n * @constructor\r\n * @param {String|Array} path path to a sound file (String). Optionally,\r\n * you may include multiple file formats in\r\n * an array. Alternately, accepts an object\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if file fails to\r\n * load. This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\r\n * is loading. That function will\r\n * receive progress of the request to\r\n * load the sound file\r\n * (between 0 and 1) as its first\r\n * parameter. This progress\r\n * does not account for the additional\r\n * time needed to decode the audio data.\r\n *\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile = function(paths, onload, onerror, whileLoading) {\r\n if (typeof paths !== 'undefined') {\r\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\r\n var path = p5.prototype._checkFileFormats(paths);\r\n this.url = path;\r\n }\r\n else if(typeof paths === 'object') {\r\n if (!(window.File && window.FileReader && window.FileList && window.Blob)) {\r\n // The File API isn't supported in this browser\r\n throw 'Unable to load file because the File API is not supported';\r\n }\r\n }\r\n\r\n // if type is a p5.File...get the actual file\r\n if (paths.file) {\r\n paths = paths.file;\r\n }\r\n\r\n this.file = paths;\r\n }\r\n\r\n // private _onended callback, set by the method: onended(callback)\r\n this._onended = function() {};\r\n\r\n this._looping = false;\r\n this._playing = false;\r\n this._paused = false;\r\n this._pauseTime = 0;\r\n\r\n // cues for scheduling events with addCue() removeCue()\r\n this._cues = [];\r\n this._cueIDCounter = 0;\r\n\r\n // position of the most recently played sample\r\n this._lastPos = 0;\r\n this._counterNode = null;\r\n this._scopeNode = null;\r\n\r\n // array of sources so that they can all be stopped!\r\n this.bufferSourceNodes = [];\r\n\r\n // current source\r\n this.bufferSourceNode = null;\r\n\r\n this.buffer = null;\r\n this.playbackRate = 1;\r\n\r\n this.input = p5sound.audiocontext.createGain();\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.reversed = false;\r\n\r\n // start and end of playback / loop\r\n this.startTime = 0;\r\n this.endTime = null;\r\n this.pauseTime = 0;\r\n\r\n // \"restart\" would stop playback before retriggering\r\n this.mode = 'sustain';\r\n\r\n // time that playback was started, in millis\r\n this.startMillis = null;\r\n\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.panner = new p5.Panner(this.output, p5sound.input, 2);\r\n\r\n // it is possible to instantiate a soundfile with no path\r\n if (this.url || this.file) {\r\n this.load(onload, onerror);\r\n }\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n\r\n if (typeof whileLoading === 'function') {\r\n this._whileLoading = whileLoading;\r\n } else {\r\n this._whileLoading = function() {};\r\n }\r\n\r\n this._onAudioProcess = _onAudioProcess.bind(this);\r\n this._clearOnEnd = _clearOnEnd.bind(this);\r\n };\r\n\r\n // register preload handling of loadSound\r\n p5.prototype.registerPreloadMethod('loadSound', p5.prototype);\r\n\r\n /**\r\n * loadSound() returns a new p5.SoundFile from a specified\r\n * path. If called during preload(), the p5.SoundFile will be ready\r\n * to play in time for setup() and draw(). If called outside of\r\n * preload, the p5.SoundFile will not be ready immediately, so\r\n * loadSound accepts a callback as the second parameter. Using a\r\n * \r\n * local server is recommended when loading external files.\r\n *\r\n * @method loadSound\r\n * @for p5\r\n * @param {String|Array} path Path to the sound file, or an array with\r\n * paths to soundfiles in multiple formats\r\n * i.e. ['sound.ogg', 'sound.mp3'].\r\n * Alternately, accepts an object: either\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is\r\n * an error loading the file.\r\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\r\n * This function will receive the percentage loaded\r\n * so far, from 0.0 to 1.0.\r\n * @return {SoundFile} Returns a p5.SoundFile\r\n * @example\r\n *
\r\n */\r\n p5.prototype.loadSound = function(path, callback, onerror, whileLoading) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined' ) {\r\n window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n\r\n var self = this;\r\n var s = new p5.SoundFile(path, function() {\r\n if(typeof callback === 'function') {\r\n callback.apply(self, arguments);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, onerror, whileLoading);\r\n\r\n return s;\r\n };\r\n\r\n /**\r\n * This is a helper function that the p5.SoundFile calls to load\r\n * itself. Accepts a callback (the name of another function)\r\n * as an optional parameter.\r\n *\r\n * @private\r\n * @for p5.SoundFile\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is an error\r\n */\r\n p5.SoundFile.prototype.load = function(callback, errorCallback) {\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n\r\n if (this.url !== undefined && this.url !== '') {\r\n var request = new XMLHttpRequest();\r\n request.addEventListener('progress', function(evt) {\r\n self._updateProgress(evt);\r\n }, false);\r\n request.open('GET', this.url, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on sucess loading file:\r\n if (!self.panner) return;\r\n ac.decodeAudioData(request.response,\r\n // success decoding buffer:\r\n function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n if (!self.panner) return;\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n if (!self.panner) return;\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url + '. The request status was: ' +\r\n request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n\r\n request.send();\r\n }\r\n else if (this.file !== undefined) {\r\n var reader = new FileReader();\r\n reader.onload = function() {\r\n if (!self.panner) return;\r\n ac.decodeAudioData(reader.result, function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n });\r\n };\r\n reader.onerror = function(e) {\r\n if (!self.panner) return;\r\n if (onerror) {\r\n onerror(e);\r\n }\r\n };\r\n reader.readAsArrayBuffer(this.file);\r\n }\r\n };\r\n\r\n // TO DO: use this method to create a loading bar that shows progress during file upload/decode.\r\n p5.SoundFile.prototype._updateProgress = function(evt) {\r\n if (evt.lengthComputable) {\r\n var percentComplete = evt.loaded / evt.total * 0.99;\r\n this._whileLoading(percentComplete, evt);\r\n // ...\r\n } else {\r\n // Unable to compute progress information since the total size is unknown\r\n this._whileLoading('size unknown');\r\n }\r\n };\r\n\r\n /**\r\n * Returns true if the sound file finished loading successfully.\r\n *\r\n * @method isLoaded\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLoaded = function() {\r\n if (this.buffer) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n };\r\n\r\n /**\r\n * Play the p5.SoundFile\r\n *\r\n * @method play\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) amplitude (volume)\r\n * of playback\r\n * @param {Number} [cueStart] (optional) cue start time in seconds\r\n * @param {Number} [duration] (optional) duration of playback in seconds\r\n */\r\n p5.SoundFile.prototype.play = function(startTime, rate, amp, _cueStart, duration) {\r\n if (!this.output) {\r\n console.warn('SoundFile.play() called after dispose');\r\n return;\r\n }\r\n\r\n var self = this;\r\n var now = p5sound.audiocontext.currentTime;\r\n var cueStart, cueEnd;\r\n var time = startTime || 0;\r\n if (time < 0) {\r\n time = 0;\r\n }\r\n\r\n time = time + now;\r\n\r\n if (typeof rate !== 'undefined') {\r\n this.rate(rate);\r\n }\r\n\r\n if (typeof amp !== 'undefined') {\r\n this.setVolume(amp);\r\n }\r\n\r\n // TO DO: if already playing, create array of buffers for easy stop()\r\n if (this.buffer) {\r\n\r\n // reset the pause time (if it was paused)\r\n this._pauseTime = 0;\r\n\r\n // handle restart playmode\r\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\r\n this.bufferSourceNode.stop(time);\r\n this._counterNode.stop(time);\r\n }\r\n\r\n //dont create another instance if already playing\r\n if (this.mode === 'untildone' && this.isPlaying()) {\r\n return;\r\n }\r\n // make a new source and counter. They are automatically assigned playbackRate and buffer\r\n this.bufferSourceNode = this._initSourceNode();\r\n\r\n // garbage collect counterNode and create a new one\r\n delete this._counterNode;\r\n this._counterNode = this._initCounterNode();\r\n\r\n if (_cueStart) {\r\n if (_cueStart >=0 && _cueStart < this.buffer.duration) {\r\n // this.startTime = cueStart;\r\n cueStart = _cueStart;\r\n } else { throw 'start time out of range'; }\r\n } else {\r\n cueStart = 0;\r\n }\r\n\r\n if (duration) {\r\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\r\n duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration;\r\n }\r\n\r\n // if it was paused, play at the pause position\r\n if (this._paused) {\r\n this.bufferSourceNode.start(time, this.pauseTime, duration);\r\n this._counterNode.start(time, this.pauseTime, duration);\r\n } else {\r\n this.bufferSourceNode.start(time, cueStart, duration);\r\n this._counterNode.start(time, cueStart, duration);\r\n }\r\n\r\n this._playing = true;\r\n this._paused = false;\r\n\r\n // add source to sources array, which is used in stopAll()\r\n this.bufferSourceNodes.push(this.bufferSourceNode);\r\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\r\n\r\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\r\n }\r\n // If soundFile hasn't loaded the buffer yet, throw an error\r\n else {\r\n throw 'not ready to play file, buffer has yet to load. Try preload()';\r\n }\r\n\r\n // if looping, will restart at original time\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n\r\n if (this._looping === true) {\r\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\r\n this.bufferSourceNode.loopStart = cueStart;\r\n this.bufferSourceNode.loopEnd = cueEnd;\r\n this._counterNode.loopStart = cueStart;\r\n this._counterNode.loopEnd = cueEnd;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * p5.SoundFile has two play modes: restart and\r\n * sustain. Play Mode determines what happens to a\r\n * p5.SoundFile if it is triggered while in the middle of playback.\r\n * In sustain mode, playback will continue simultaneous to the\r\n * new playback. In restart mode, play() will stop playback\r\n * and start over. With untilDone, a sound will play only if it's\r\n * not already playing. Sustain is the default mode.\r\n *\r\n * @method playMode\r\n * @for p5.SoundFile\r\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\r\n * @example\r\n *
\r\n * var mySound;\r\n * function preload(){\r\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n * function mouseClicked() {\r\n * mySound.playMode('sustain');\r\n * mySound.play();\r\n * }\r\n * function keyPressed() {\r\n * mySound.playMode('restart');\r\n * mySound.play();\r\n * }\r\n *\r\n *
\r\n */\r\n p5.SoundFile.prototype.playMode = function(str) {\r\n var s = str.toLowerCase();\r\n\r\n // if restart, stop all other sounds from playing\r\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNodes[i].stop(now);\r\n }\r\n }\r\n\r\n // set play mode to effect future playback\r\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\r\n this.mode = s;\r\n } else {\r\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\r\n }\r\n };\r\n\r\n /**\r\n * Pauses a file that is currently playing. If the file is not\r\n * playing, then nothing will happen.\r\n *\r\n * After pausing, .play() will resume from the paused\r\n * position.\r\n * If p5.SoundFile had been set to loop before it was paused,\r\n * it will continue to loop after it is unpaused with .play().\r\n *\r\n * @method pause\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.pause = function(startTime) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = startTime || 0;\r\n var pTime = time + now;\r\n\r\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\r\n this.pauseTime = this.currentTime();\r\n this.bufferSourceNode.stop(pTime);\r\n this._counterNode.stop(pTime);\r\n this._paused = true;\r\n this._playing = false;\r\n\r\n this._pauseTime = this.currentTime();\r\n // TO DO: make sure play() still starts from orig start position\r\n } else {\r\n this._pauseTime = 0;\r\n }\r\n };\r\n\r\n /**\r\n * Loop the p5.SoundFile. Accepts optional parameters to set the\r\n * playback rate, playback volume, loopStart, loopEnd.\r\n *\r\n * @method loop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) playback volume\r\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\r\n * @param {Number} [duration] (optional) loop duration in seconds\r\n */\r\n p5.SoundFile.prototype.loop = function(startTime, rate, amp, loopStart, duration) {\r\n this._looping = true;\r\n this.play(startTime, rate, amp, loopStart, duration);\r\n };\r\n\r\n /**\r\n * Set a p5.SoundFile's looping flag to true or false. If the sound\r\n * is currently playing, this change will take effect when it\r\n * reaches the end of the current playback.\r\n *\r\n * @method setLoop\r\n * @for p5.SoundFile\r\n * @param {Boolean} Boolean set looping to true or false\r\n */\r\n p5.SoundFile.prototype.setLoop = function(bool) {\r\n if (bool === true) {\r\n this._looping = true;\r\n }\r\n else if (bool === false) {\r\n this._looping = false;\r\n }\r\n else {\r\n throw 'Error: setLoop accepts either true or false';\r\n }\r\n if (this.bufferSourceNode) {\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n }\r\n };\r\n\r\n /**\r\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\r\n *\r\n * @method isLooping\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLooping = function() {\r\n if (!this.bufferSourceNode) {\r\n return false;\r\n }\r\n if (this._looping === true && this.isPlaying() === true) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\r\n * paused or stopped).\r\n *\r\n * @method isPlaying\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPlaying = function() {\r\n return this._playing;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\r\n * playing or stopped).\r\n *\r\n * @method isPaused\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPaused = function() {\r\n return this._paused;\r\n };\r\n\r\n /**\r\n * Stop soundfile playback.\r\n *\r\n * @method stop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * in seconds from now\r\n */\r\n p5.SoundFile.prototype.stop = function(timeFromNow) {\r\n var time = timeFromNow || 0;\r\n\r\n if (this.mode === 'sustain' || this.mode === 'untildone') {\r\n this.stopAll(time);\r\n this._playing = false;\r\n this.pauseTime = 0;\r\n this._paused = false;\r\n }\r\n else if (this.buffer && this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = time || 0;\r\n this.pauseTime = 0;\r\n this.bufferSourceNode.stop(now + t);\r\n this._counterNode.stop(now + t);\r\n this._playing = false;\r\n this._paused = false;\r\n }\r\n };\r\n\r\n /**\r\n * Stop playback on all of this soundfile's sources.\r\n * @private\r\n */\r\n p5.SoundFile.prototype.stopAll = function(_time) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = _time || 0;\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i in this.bufferSourceNodes) {\r\n const bufferSourceNode = this.bufferSourceNodes[i];\r\n if (!!bufferSourceNode) {\r\n try {\r\n bufferSourceNode.stop(now + time);\r\n } catch(e) {\r\n // this was throwing errors only on Safari\r\n }\r\n }\r\n }\r\n this._counterNode.stop(now + time);\r\n this._onended(this);\r\n }\r\n };\r\n\r\n /**\r\n * Multiply the output volume (amplitude) of a sound file\r\n * between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n * @method setVolume\r\n * @for p5.SoundFile\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.SoundFile.prototype.setVolume = function(vol, _rampTime, _tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = _rampTime || 0;\r\n var tFromNow = _tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(this.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // same as setVolume, to match Processing Sound\r\n p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;\r\n\r\n // these are the same thing\r\n p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;\r\n\r\n p5.SoundFile.prototype.getVolume = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set the stereo panning of a p5.sound object to\r\n * a floating point number between -1.0 (left) and 1.0 (right).\r\n * Default is 0.0 (center).\r\n *\r\n * @method pan\r\n * @for p5.SoundFile\r\n * @param {Number} [panValue] Set the stereo panner\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @example\r\n *
\r\n *\r\n * var ball = {};\r\n * var soundFile;\r\n *\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n * soundFile = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * ball.x = constrain(mouseX, 0, width);\r\n * ellipse(ball.x, height/2, 20, 20)\r\n * }\r\n *\r\n * function mousePressed(){\r\n * // map the ball's x location to a panning degree\r\n * // between -1.0 (left) and 1.0 (right)\r\n * var panning = map(ball.x, 0., width,-1.0, 1.0);\r\n * soundFile.pan(panning);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n /**\r\n * Returns the current stereo pan position (-1.0 to 1.0)\r\n *\r\n * @method getPan\r\n * @for p5.SoundFile\r\n * @return {Number} Returns the stereo pan setting of the Oscillator\r\n * as a number between -1.0 (left) and 1.0 (right).\r\n * 0.0 is center and default.\r\n */\r\n p5.SoundFile.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n /**\r\n * Set the playback rate of a sound file. Will change the speed and the pitch.\r\n * Values less than zero will reverse the audio buffer.\r\n *\r\n * @method rate\r\n * @for p5.SoundFile\r\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\r\n * .5 is half-speed, 2.0 is twice as fast.\r\n * Values less than zero play backwards.\r\n * @example\r\n *
\r\n * var song;\r\n *\r\n * function preload() {\r\n * song = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * song.loop();\r\n * }\r\n *\r\n * function draw() {\r\n * background(200);\r\n *\r\n * // Set the rate to a range between 0.1 and 4\r\n * // Changing the rate also alters the pitch\r\n * var speed = map(mouseY, 0.1, height, 0, 2);\r\n * speed = constrain(speed, 0.01, 4);\r\n * song.rate(speed);\r\n *\r\n * // Draw a circle to show what is going on\r\n * stroke(0);\r\n * fill(51, 100);\r\n * ellipse(mouseX, 100, 48, 48);\r\n * }\r\n *\r\n * \r\n *
\r\n *\r\n */\r\n p5.SoundFile.prototype.rate = function(playbackRate) {\r\n var reverse = false;\r\n if (typeof playbackRate === 'undefined') {\r\n return this.playbackRate;\r\n }\r\n\r\n this.playbackRate = playbackRate;\r\n\r\n if (playbackRate === 0) {\r\n playbackRate = 0.0000000000001;\r\n }\r\n\r\n else if (playbackRate < 0 && !this.reversed) {\r\n playbackRate = Math.abs(playbackRate);\r\n reverse = true;\r\n }\r\n\r\n else if (playbackRate > 0 && this.reversed) {\r\n reverse = true;\r\n }\r\n\r\n if (this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\r\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n this._counterNode.playbackRate.cancelScheduledValues(now);\r\n this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n }\r\n\r\n if (reverse) {\r\n this.reverseBuffer();\r\n }\r\n return this.playbackRate;\r\n };\r\n\r\n // TO DO: document this\r\n p5.SoundFile.prototype.setPitch = function(num) {\r\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\r\n this.rate(newPlaybackRate);\r\n };\r\n\r\n p5.SoundFile.prototype.getPlaybackRate = function() {\r\n return this.playbackRate;\r\n };\r\n\r\n /**\r\n * Returns the duration of a sound file in seconds.\r\n *\r\n * @method duration\r\n * @for p5.SoundFile\r\n * @return {Number} The duration of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.duration = function() {\r\n // Return Duration\r\n if (this.buffer) {\r\n return this.buffer.duration;\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n /**\r\n * Return the current position of the p5.SoundFile playhead, in seconds.\r\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\r\n * has been called, currentTime will count backwards.\r\n *\r\n * @method currentTime\r\n * @for p5.SoundFile\r\n * @return {Number} currentTime of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.currentTime = function() {\r\n return this.reversed\r\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\r\n : this._lastPos / ac.sampleRate;\r\n };\r\n\r\n /**\r\n * Move the playhead of the song to a position, in seconds. Start timing\r\n * and playback duration. If none are given, will reset the file to play\r\n * entire duration from start to finish.\r\n *\r\n * @method jump\r\n * @for p5.SoundFile\r\n * @param {Number} cueTime cueTime of the soundFile in seconds.\r\n * @param {Number} duration duration in seconds.\r\n */\r\n p5.SoundFile.prototype.jump = function(cueTime, duration) {\r\n if (cueTime < 0 || cueTime > this.buffer.duration) {\r\n throw 'jump time out of range';\r\n }\r\n if (duration > this.buffer.duration - cueTime) {\r\n throw 'end time out of range';\r\n }\r\n\r\n var cTime = cueTime || 0;\r\n var dur = duration || undefined;\r\n if (this.isPlaying()) {\r\n this.stop(0);\r\n }\r\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\r\n };\r\n\r\n /**\r\n * Return the number of channels in a sound file.\r\n * For example, Mono = 1, Stereo = 2.\r\n *\r\n * @method channels\r\n * @for p5.SoundFile\r\n * @return {Number} [channels]\r\n */\r\n p5.SoundFile.prototype.channels = function() {\r\n return this.buffer.numberOfChannels;\r\n };\r\n\r\n /**\r\n * Return the sample rate of the sound file.\r\n *\r\n * @method sampleRate\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleRate]\r\n */\r\n p5.SoundFile.prototype.sampleRate = function() {\r\n return this.buffer.sampleRate;\r\n };\r\n\r\n /**\r\n * Return the number of samples in a sound file.\r\n * Equal to sampleRate * duration.\r\n *\r\n * @method frames\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleCount]\r\n */\r\n p5.SoundFile.prototype.frames = function() {\r\n return this.buffer.length;\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\r\n * used to draw a static waveform. Scans through the p5.SoundFile's\r\n * audio buffer to find the greatest amplitudes. Accepts one\r\n * parameter, 'length', which determines size of the array.\r\n * Larger arrays result in more precise waveform visualizations.\r\n *\r\n * Inspired by Wavesurfer.js.\r\n *\r\n * @method getPeaks\r\n * @for p5.SoundFile\r\n * @params {Number} [length] length is the size of the returned array.\r\n * Larger length results in more precision.\r\n * Defaults to 5*width of the browser window.\r\n * @returns {Float32Array} Array of peaks.\r\n */\r\n p5.SoundFile.prototype.getPeaks = function(length) {\r\n\r\n if (this.buffer) {\r\n // set length to window's width if no length is provided\r\n if (!length) {\r\n length = window.width*5;\r\n }\r\n if (this.buffer) {\r\n var buffer = this.buffer;\r\n var sampleSize = buffer.length / length;\r\n var sampleStep = ~~(sampleSize / 10) || 1;\r\n var channels = buffer.numberOfChannels;\r\n var peaks = new Float32Array(Math.round(length));\r\n\r\n for (var c = 0; c < channels; c++) {\r\n var chan = buffer.getChannelData(c);\r\n for (var i = 0; i < length; i++) {\r\n var start = ~~(i*sampleSize);\r\n var end = ~~(start + sampleSize);\r\n var max = 0;\r\n for (var j = start; j < end; j+= sampleStep) {\r\n var value = chan[j];\r\n if (value > max) {\r\n max = value;\r\n // faster than Math.abs\r\n } else if (-value > max) {\r\n max = value;\r\n }\r\n }\r\n if (c === 0 || Math.abs(max) > peaks[i]) {\r\n peaks[i] = max;\r\n }\r\n }\r\n }\r\n\r\n return peaks;\r\n }\r\n }\r\n\r\n else {\r\n throw 'Cannot load peaks yet, buffer is not loaded';\r\n }\r\n };\r\n\r\n /**\r\n * Reverses the p5.SoundFile's buffer source.\r\n * Playback must be handled separately (see example).\r\n *\r\n * @method reverseBuffer\r\n * @for p5.SoundFile\r\n * @example\r\n *
\r\n * var drum;\r\n *\r\n * function preload() {\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * drum.reverseBuffer();\r\n * drum.play();\r\n * }\r\n *\r\n * \r\n *
\r\n */\r\n p5.SoundFile.prototype.reverseBuffer = function() {\r\n if (this.buffer) {\r\n var currentPos = this._lastPos / ac.sampleRate;\r\n var curVol = this.getVolume();\r\n this.setVolume(0, 0.001);\r\n\r\n const numChannels = this.buffer.numberOfChannels;\r\n for (var i = 0; i < numChannels; i++) {\r\n this.buffer.getChannelData(i).reverse();\r\n }\r\n // set reversed flag\r\n this.reversed = !this.reversed;\r\n\r\n if (currentPos) {\r\n this.jump(this.duration() - currentPos);\r\n }\r\n this.setVolume(curVol, 0.001);\r\n } else {\r\n throw 'SoundFile is not done loading';\r\n }\r\n };\r\n\r\n /**\r\n * Schedule an event to be called when the soundfile\r\n * reaches the end of a buffer. If the soundfile is\r\n * playing through once, this will be called when it\r\n * ends. If it is looping, it will be called when\r\n * stop is called.\r\n *\r\n * @method onended\r\n * @for p5.SoundFile\r\n * @param {Function} callback function to call when the\r\n * soundfile has ended.\r\n */\r\n p5.SoundFile.prototype.onended = function(callback) {\r\n this._onended = callback;\r\n return this;\r\n };\r\n\r\n p5.SoundFile.prototype.add = function() {\r\n // TO DO\r\n };\r\n\r\n p5.SoundFile.prototype.dispose = function() {\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n // remove reference to soundfile\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop(now);\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n if (this.bufferSourceNodes[i] !== null) {\r\n this.bufferSourceNodes[i].disconnect();\r\n try {\r\n this.bufferSourceNodes[i].stop(now);\r\n } catch(e) {\r\n console.warning('no buffer source node to dispose');\r\n }\r\n this.bufferSourceNodes[i] = null;\r\n }\r\n }\r\n if ( this.isPlaying() ) {\r\n try {\r\n this._counterNode.stop(now);\r\n } catch(e) {\r\n console.log(e);\r\n }\r\n this._counterNode = null;\r\n }\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n this.output = null;\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n this.panner = null;\r\n }\r\n };\r\n\r\n /**\r\n * Connects the output of a p5sound object to input of another\r\n * p5.sound object. For example, you may connect a p5.SoundFile to an\r\n * FFT or an Effect. If no parameter is given, it will connect to\r\n * the master output. Most p5sound objects connect to the master\r\n * output when they are created.\r\n *\r\n * @method connect\r\n * @for p5.SoundFile\r\n * @param {Object} [object] Audio object that accepts an input\r\n */\r\n p5.SoundFile.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else {\r\n if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n } else {\r\n this.panner.connect(unit);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Disconnects the output of this p5sound object.\r\n *\r\n * @method disconnect\r\n * @for p5.SoundFile\r\n */\r\n p5.SoundFile.prototype.disconnect = function() {\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n */\r\n p5.SoundFile.prototype.getLevel = function() {\r\n console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead');\r\n };\r\n\r\n /**\r\n * Reset the source for this SoundFile to a\r\n * new path (URL).\r\n *\r\n * @method setPath\r\n * @for p5.SoundFile\r\n * @param {String} path path to audio file\r\n * @param {Function} callback Callback\r\n */\r\n p5.SoundFile.prototype.setPath = function(p, callback) {\r\n var path = p5.prototype._checkFileFormats(p);\r\n this.url = path;\r\n this.load(callback);\r\n };\r\n\r\n /**\r\n * Replace the current Audio Buffer with a new Buffer.\r\n *\r\n * @method setBuffer\r\n * @for p5.SoundFile\r\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\r\n * will create a stereo source. 1 will create\r\n * a mono source.\r\n */\r\n p5.SoundFile.prototype.setBuffer = function(buf) {\r\n var numChannels = buf.length;\r\n var size = buf[0].length;\r\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\r\n\r\n if (!(buf[0] instanceof Float32Array)) {\r\n buf[0] = new Float32Array(buf[0]);\r\n }\r\n\r\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\r\n var channel = newBuffer.getChannelData( channelNum );\r\n channel.set(buf[channelNum]);\r\n }\r\n\r\n this.buffer = newBuffer;\r\n\r\n // set numbers of channels on input to the panner\r\n this.panner.inputChannels(numChannels);\r\n };\r\n\r\n //////////////////////////////////////////////////\r\n // script processor node with an empty buffer to help\r\n // keep a sample-accurate position in playback buffer.\r\n // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV\r\n // Copyright [2015] [Sonoport (Asia) Pte. Ltd.],\r\n // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0\r\n ////////////////////////////////////////////////////////////////////////////////////\r\n\r\n var _createCounterBuffer = function(buffer) {\r\n const len = buffer.length;\r\n const audioBuf = ac.createBuffer( 1, buffer.length, ac.sampleRate );\r\n const arrayBuffer = audioBuf.getChannelData(0);\r\n for (var index = 0; index < len; index++) {\r\n arrayBuffer[index] = index;\r\n }\r\n return audioBuf;\r\n };\r\n\r\n // initialize counterNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initCounterNode = function() {\r\n var self = this;\r\n var now = ac.currentTime;\r\n var cNode = ac.createBufferSource();\r\n\r\n // dispose of scope node if it already exists\r\n if (self._scopeNode) {\r\n self._scopeNode.disconnect();\r\n self._scopeNode.removeEventListener('audioprocess', self._onAudioProcess);\r\n delete self._scopeNode;\r\n }\r\n self._scopeNode = ac.createScriptProcessor( 256, 1, 1 );\r\n\r\n // create counter buffer of the same length as self.buffer\r\n cNode.buffer = _createCounterBuffer( self.buffer );\r\n\r\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\r\n\r\n cNode.connect( self._scopeNode );\r\n self._scopeNode.connect( p5.soundOut._silentNode );\r\n\r\n self._scopeNode.addEventListener('audioprocess', self._onAudioProcess);\r\n\r\n return cNode;\r\n };\r\n\r\n // initialize sourceNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initSourceNode = function() {\r\n var bufferSourceNode = ac.createBufferSource();\r\n bufferSourceNode.buffer = this.buffer;\r\n bufferSourceNode.playbackRate.value = this.playbackRate;\r\n bufferSourceNode.connect(this.output);\r\n return bufferSourceNode;\r\n };\r\n\r\n /**\r\n * processPeaks returns an array of timestamps where it thinks there is a beat.\r\n *\r\n * This is an asynchronous function that processes the soundfile in an offline audio context,\r\n * and sends the results to your callback function.\r\n *\r\n * The process involves running the soundfile through a lowpass filter, and finding all of the\r\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\r\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\r\n *\r\n * @method processPeaks\r\n * @for p5.SoundFile\r\n * @param {Function} callback a function to call once this data is returned\r\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\r\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\r\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\r\n * @return {Array} Array of timestamped peaks\r\n */\r\n p5.SoundFile.prototype.processPeaks = function(callback, _initThreshold, _minThreshold, _minPeaks) {\r\n var bufLen = this.buffer.length;\r\n var sampleRate = this.buffer.sampleRate;\r\n var buffer = this.buffer;\r\n var allPeaks = [];\r\n\r\n var initialThreshold = _initThreshold || 0.9,\r\n threshold = initialThreshold,\r\n minThreshold = _minThreshold || 0.22,\r\n minPeaks = _minPeaks || 200;\r\n\r\n // Create offline context\r\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\r\n\r\n // create buffer source\r\n var source = offlineContext.createBufferSource();\r\n source.buffer = buffer;\r\n\r\n // Create filter. TO DO: allow custom setting of filter\r\n var filter = offlineContext.createBiquadFilter();\r\n filter.type = 'lowpass';\r\n source.connect(filter);\r\n filter.connect(offlineContext.destination);\r\n\r\n // start playing at time:0\r\n source.start(0);\r\n offlineContext.startRendering(); // Render the song\r\n\r\n // act on the result\r\n offlineContext.oncomplete = function(e) {\r\n if (!self.panner) return;\r\n var filteredBuffer = e.renderedBuffer;\r\n var bufferData = filteredBuffer.getChannelData(0);\r\n\r\n\r\n // step 1:\r\n // create Peak instances, add them to array, with strength and sampleIndex\r\n do {\r\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\r\n threshold -= 0.005;\r\n } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold);\r\n\r\n\r\n // step 2:\r\n // find intervals for each peak in the sampleIndex, add tempos array\r\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\r\n\r\n // step 3: find top tempos\r\n var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate);\r\n\r\n // sort top intervals\r\n var topTempos = groups.sort(function(intA, intB) {\r\n return intB.count - intA.count;\r\n\r\n }).splice(0,5);\r\n\r\n // set this SoundFile's tempo to the top tempo ??\r\n this.tempo = topTempos[0].tempo;\r\n\r\n // step 4:\r\n // new array of peaks at top tempo within a bpmVariance\r\n var bpmVariance = 5;\r\n var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance);\r\n\r\n callback(tempoPeaks);\r\n };\r\n };\r\n\r\n // process peaks\r\n var Peak = function(amp, i) {\r\n this.sampleIndex = i;\r\n this.amplitude = amp;\r\n this.tempos = [];\r\n this.intervals = [];\r\n };\r\n\r\n // 1. for processPeaks() Function to identify peaks above a threshold\r\n // returns an array of peak indexes as frames (samples) of the original soundfile\r\n function getPeaksAtThreshold(data, threshold) {\r\n var peaksObj = {};\r\n var length = data.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (data[i] > threshold) {\r\n var amp = data[i];\r\n var peak = new Peak(amp, i);\r\n peaksObj[i] = peak;\r\n // Skip forward ~ 1/8s to get past this peak.\r\n i += 6000;\r\n }\r\n i++;\r\n }\r\n return peaksObj;\r\n }\r\n\r\n // 2. for processPeaks()\r\n function countIntervalsBetweenNearbyPeaks(peaksObj) {\r\n var intervalCounts = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n for (var index = 0; index < peaksArray.length; index++) {\r\n\r\n // find intervals in comparison to nearby peaks\r\n for (var i = 0; i < 10; i++) {\r\n var startPeak = peaksObj[peaksArray[index]];\r\n var endPeak = peaksObj[peaksArray[index + i]];\r\n\r\n if (startPeak && endPeak) {\r\n var startPos = startPeak.sampleIndex;\r\n var endPos = endPeak.sampleIndex;\r\n var interval = endPos - startPos;\r\n\r\n // add a sample interval to the startPeak in the allPeaks array\r\n if (interval > 0) {\r\n startPeak.intervals.push(interval);\r\n }\r\n\r\n // tally the intervals and return interval counts\r\n var foundInterval = intervalCounts.some(function(intervalCount) {\r\n if (intervalCount.interval === interval) {\r\n intervalCount.count++;\r\n return intervalCount;\r\n }\r\n });\r\n\r\n // store with JSON like formatting\r\n if (!foundInterval) {\r\n intervalCounts.push({\r\n interval: interval,\r\n count: 1,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return intervalCounts;\r\n }\r\n\r\n\r\n // 3. for processPeaks --> find tempo\r\n function groupNeighborsByTempo(intervalCounts, sampleRate) {\r\n var tempoCounts = [];\r\n\r\n intervalCounts.forEach(function(intervalCount) {\r\n\r\n try {\r\n // Convert an interval to tempo\r\n var theoreticalTempo = Math.abs( 60 / (intervalCount.interval / sampleRate ) );\r\n\r\n theoreticalTempo = mapTempo(theoreticalTempo);\r\n\r\n var foundTempo = tempoCounts.some(function(tempoCount) {\r\n if (tempoCount.tempo === theoreticalTempo)\r\n return tempoCount.count += intervalCount.count;\r\n });\r\n if (!foundTempo) {\r\n if (isNaN(theoreticalTempo)) {\r\n return;\r\n }\r\n tempoCounts.push({\r\n tempo: Math.round(theoreticalTempo),\r\n count: intervalCount.count\r\n });\r\n }\r\n } catch(e) {\r\n throw e;\r\n }\r\n\r\n });\r\n\r\n return tempoCounts;\r\n }\r\n\r\n // 4. for processPeaks - get peaks at top tempo\r\n function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\r\n var peaksAtTopTempo = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n // TO DO: filter out peaks that have the tempo and return\r\n for (var i = 0; i < peaksArray.length; i++) {\r\n var key = peaksArray[i];\r\n var peak = peaksObj[key];\r\n\r\n for (var j = 0; j < peak.intervals.length; j++) {\r\n var intervalBPM = Math.round(Math.abs( 60 / (peak.intervals[j] / sampleRate) ) );\r\n\r\n intervalBPM = mapTempo(intervalBPM);\r\n\r\n if ( Math.abs(intervalBPM - tempo) < bpmVariance ) {\r\n // convert sampleIndex to seconds\r\n peaksAtTopTempo.push(peak.sampleIndex/sampleRate);\r\n }\r\n }\r\n }\r\n\r\n // filter out peaks that are very close to each other\r\n peaksAtTopTempo = peaksAtTopTempo.filter(function(peakTime, index, arr) {\r\n var dif = arr[index + 1] - peakTime;\r\n if (dif > 0.01) {\r\n return true;\r\n }\r\n });\r\n\r\n return peaksAtTopTempo;\r\n }\r\n\r\n // helper function for processPeaks\r\n function mapTempo(theoreticalTempo) {\r\n // these scenarios create infinite while loop\r\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0 ) {\r\n return;\r\n }\r\n\r\n // Adjust the tempo to fit within the 90-180 BPM range\r\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\r\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\r\n\r\n return theoreticalTempo;\r\n }\r\n\r\n\r\n /*** SCHEDULE EVENTS ***/\r\n\r\n // Cue inspired by JavaScript setTimeout, and the\r\n // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\r\n var Cue = function(callback, time, id, val) {\r\n this.callback = callback;\r\n this.time = time;\r\n this.id = id;\r\n this.val = val;\r\n };\r\n\r\n /**\r\n * Schedule events to trigger every time a MediaElement\r\n * (audio/video) reaches a playback cue point.\r\n *\r\n * Accepts a callback function, a time (in seconds) at which to trigger\r\n * the callback, and an optional parameter for the callback.\r\n *\r\n * Time will be passed as the first parameter to the callback function,\r\n * and param will be the second parameter.\r\n *\r\n *\r\n * @method addCue\r\n * @for p5.SoundFile\r\n * @param {Number} time Time in seconds, relative to this media\r\n * element's playback. For example, to trigger\r\n * an event every time playback reaches two\r\n * seconds, pass in the number 2. This will be\r\n * passed as the first parameter to\r\n * the callback function.\r\n * @param {Function} callback Name of a function that will be\r\n * called at the given time. The callback will\r\n * receive time and (optionally) param as its\r\n * two parameters.\r\n * @param {Object} [value] An object to be passed as the\r\n * second parameter to the\r\n * callback function.\r\n * @return {Number} id ID of this cue,\r\n * useful for removeCue(id)\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.addCue = function(time, callback, val) {\r\n var id = this._cueIDCounter++;\r\n\r\n var cue = new Cue(callback, time, id, val);\r\n this._cues.push(cue);\r\n\r\n // if (!this.elt.ontimeupdate) {\r\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\r\n // }\r\n\r\n return id;\r\n };\r\n\r\n /**\r\n * Remove a callback based on its ID. The ID is returned by the\r\n * addCue method.\r\n *\r\n * @method removeCue\r\n * @for p5.SoundFile\r\n * @param {Number} id ID of the cue, as returned by addCue\r\n */\r\n p5.SoundFile.prototype.removeCue = function(id) {\r\n var cueLength = this._cues.length;\r\n for (var i = 0; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n if (cue.id === id) {\r\n this._cues.splice(i, 1);\r\n break;\r\n }\r\n }\r\n\r\n if (this._cues.length === 0) {\r\n // TO DO: remove callback\r\n // this.elt.ontimeupdate = null\r\n }\r\n };\r\n\r\n /**\r\n * Remove all of the callbacks that had originally been scheduled\r\n * via the addCue method.\r\n *\r\n * @method clearCues\r\n */\r\n p5.SoundFile.prototype.clearCues = function() {\r\n this._cues = [];\r\n // this.elt.ontimeupdate = null;\r\n };\r\n\r\n // private method that checks for cues to be fired if events\r\n // have been scheduled using addCue(callback, time).\r\n p5.SoundFile.prototype._onTimeUpdate = function(position) {\r\n var playbackTime = position/this.buffer.sampleRate;\r\n var cueLength = this._cues.length;\r\n\r\n for (var i = 0 ; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n var callbackTime = cue.time;\r\n var val = cue.val;\r\n\r\n if (this._prevTime < callbackTime && callbackTime <= playbackTime) {\r\n\r\n // pass the scheduled callbackTime as parameter to the callback\r\n cue.callback(val);\r\n }\r\n\r\n }\r\n\r\n this._prevTime = playbackTime;\r\n };\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device. To upload a file to a server, see\r\n * getBlob\r\n *\r\n * @method save\r\n * @for p5.SoundFile\r\n * @param {String} [fileName] name of the resulting .wav file.\r\n * @example\r\n *
\r\n * var inp, button, mySound;\r\n * var fileName = 'cool';\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n * function setup() {\r\n * btn = createButton('click to save file');\r\n * btn.position(0, 0);\r\n * btn.mouseClicked(handleMouseClick);\r\n * }\r\n *\r\n * function handleMouseClick() {\r\n * mySound.save(fileName);\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.save = function(fileName) {\r\n const dataView = convertToWav(this.buffer);\r\n p5.prototype.saveSound([dataView], fileName, 'wav');\r\n };\r\n\r\n /**\r\n * This method is useful for sending a SoundFile to a server. It returns the\r\n * .wav-encoded audio data as a \"Blob\".\r\n * A Blob is a file-like data object that can be uploaded to a server\r\n * with an http request. We'll\r\n * use the `httpDo` options object to send a POST request with some\r\n * specific options: we encode the request as `multipart/form-data`,\r\n * and attach the blob as one of the form values using `FormData`.\r\n *\r\n *\r\n * @method getBlob\r\n * @for p5.SoundFile\r\n * @returns {Blob} A file-like data object\r\n * @example\r\n *
\r\n *\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noCanvas();\r\n * var soundBlob = mySound.getBlob();\r\n *\r\n * // Now we can send the blob to a server...\r\n * var serverUrl = 'https://jsonplaceholder.typicode.com/posts';\r\n * var httpRequestOptions = {\r\n * method: 'POST',\r\n * body: new FormData().append('soundBlob', soundBlob),\r\n * headers: new Headers({\r\n * 'Content-Type': 'multipart/form-data'\r\n * })\r\n * };\r\n * httpDo(serverUrl, httpRequestOptions);\r\n *\r\n * // We can also create an `ObjectURL` pointing to the Blob\r\n * var blobUrl = URL.createObjectURL(soundBlob);\r\n *\r\n * // The `
\r\n */\r\n p5.SoundFile.prototype.getBlob = function() {\r\n const dataView = convertToWav(this.buffer);\r\n return new Blob([dataView], { type: 'audio/wav' });\r\n };\r\n\r\n // event handler to keep track of current position\r\n function _onAudioProcess(processEvent) {\r\n var inputBuffer = processEvent.inputBuffer.getChannelData(0);\r\n\r\n this._lastPos = inputBuffer[inputBuffer.length - 1] || 0;\r\n\r\n // do any callbacks that have been scheduled\r\n this._onTimeUpdate(self._lastPos);\r\n }\r\n\r\n // event handler to remove references to the bufferSourceNode when it is done playing\r\n function _clearOnEnd(e) {\r\n const thisBufferSourceNode = e.target;\r\n const soundFile = this;\r\n\r\n // delete this.bufferSourceNode from the sources array when it is done playing:\r\n thisBufferSourceNode._playing = false;\r\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\r\n\r\n // call the onended callback\r\n soundFile._onended(soundFile);\r\n\r\n soundFile.bufferSourceNodes.forEach(function (n, i) {\r\n if (n._playing === false) {\r\n soundFile.bufferSourceNodes.splice(i);\r\n }\r\n });\r\n\r\n if (soundFile.bufferSourceNodes.length === 0) {\r\n soundFile._playing = false;\r\n }\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * Amplitude measures volume between 0.0 and 1.0.\r\n * Listens to all p5sound by default, or use setInput()\r\n * to listen to a specific sound source. Accepts an optional\r\n * smoothing value, which defaults to 0.\r\n *\r\n * @class p5.Amplitude\r\n * @constructor\r\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\r\n * amplitude readings (defaults to 0)\r\n * @example\r\n *
\r\n * var sound, amplitude, cnv;\r\n *\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * amplitude = new p5.Amplitude();\r\n *\r\n * // start / stop the sound when canvas is clicked\r\n * cnv.mouseClicked(function() {\r\n * if (sound.isPlaying() ){\r\n * sound.stop();\r\n * } else {\r\n * sound.play();\r\n * }\r\n * });\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n *\r\n *
\r\n */\r\n p5.Amplitude = function(smoothing) {\r\n\r\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\r\n this.bufferSize = 2048;\r\n\r\n // set audio context\r\n this.audiocontext = p5sound.audiocontext;\r\n this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1);\r\n\r\n // for connections\r\n this.input = this.processor;\r\n\r\n this.output = this.audiocontext.createGain();\r\n // smoothing defaults to 0\r\n this.smoothing = smoothing || 0;\r\n\r\n\r\n // the variables to return\r\n this.volume = 0;\r\n this.average = 0;\r\n\r\n this.stereoVol = [0, 0];\r\n this.stereoAvg = [0, 0];\r\n this.stereoVolNorm = [0, 0];\r\n\r\n this.volMax = 0.001;\r\n this.normalize = false;\r\n\r\n this.processor.onaudioprocess = this._audioProcess.bind(this);\r\n\r\n\r\n this.processor.connect(this.output);\r\n this.output.gain.value = 0;\r\n\r\n // this may only be necessary because of a Chrome bug\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // connect to p5sound master output by default, unless set by input()\r\n p5sound.meter.connect(this.processor);\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connects to the p5sound instance (master output) by default.\r\n * Optionally, you can pass in a specific source (i.e. a soundfile).\r\n *\r\n * @method setInput\r\n * @for p5.Amplitude\r\n * @param {soundObject|undefined} [snd] set the sound source\r\n * (optional, defaults to\r\n * master output)\r\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\r\n * to smooth amplitude readings\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound1 = loadSound('assets/beat.mp3');\r\n * sound2 = loadSound('assets/drum.mp3');\r\n * }\r\n * function setup(){\r\n * amplitude = new p5.Amplitude();\r\n * sound1.play();\r\n * sound2.play();\r\n * amplitude.setInput(sound2);\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound1.stop();\r\n * sound2.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.setInput = function(source, smoothing) {\r\n\r\n p5sound.meter.disconnect();\r\n\r\n if (smoothing) {\r\n this.smoothing = smoothing;\r\n }\r\n\r\n // connect to the master out of p5s instance if no snd is provided\r\n if (source == null) {\r\n console.log('Amplitude input source is not ready! Connecting to master output instead');\r\n p5sound.meter.connect(this.processor);\r\n }\r\n\r\n // if it is a p5.Signal\r\n else if (source instanceof p5.Signal) {\r\n source.output.connect(this.processor);\r\n }\r\n // connect to the sound if it is available\r\n else if (source) {\r\n source.connect(this.processor);\r\n this.processor.disconnect();\r\n this.processor.connect(this.output);\r\n }\r\n\r\n // otherwise, connect to the master out of p5s instance (default)\r\n else {\r\n p5sound.meter.connect(this.processor);\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n } else {\r\n this.output.connect(unit);\r\n }\r\n } else {\r\n this.output.connect(this.panner.connect(p5sound.input));\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n // TO DO make this stereo / dependent on # of audio channels\r\n p5.Amplitude.prototype._audioProcess = function(event) {\r\n\r\n for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) {\r\n var inputBuffer = event.inputBuffer.getChannelData(channel);\r\n var bufLength = inputBuffer.length;\r\n\r\n var total = 0;\r\n var sum = 0;\r\n var x;\r\n\r\n for (var i = 0; i < bufLength; i++) {\r\n x = inputBuffer[i];\r\n if (this.normalize) {\r\n total += Math.max(Math.min(x/this.volMax, 1), -1);\r\n sum += Math.max(Math.min(x/this.volMax, 1), -1) * Math.max(Math.min(x/this.volMax, 1), -1);\r\n }\r\n else {\r\n total += x;\r\n sum += x * x;\r\n }\r\n }\r\n var average = total/ bufLength;\r\n\r\n // ... then take the square root of the sum.\r\n var rms = Math.sqrt(sum / bufLength);\r\n\r\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing);\r\n this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing);\r\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\r\n }\r\n\r\n // add volume from all channels together\r\n var self = this;\r\n var volSum = this.stereoVol.reduce(function(previousValue, currentValue, index) {\r\n self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1]/self.volMax, 1), 0);\r\n self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index]/self.volMax, 1), 0);\r\n\r\n return previousValue + currentValue;\r\n });\r\n\r\n // volume is average of channels\r\n this.volume = volSum / this.stereoVol.length;\r\n\r\n // normalized value\r\n this.volNorm = Math.max(Math.min(this.volume/this.volMax, 1), 0);\r\n\r\n\r\n };\r\n\r\n /**\r\n * Returns a single Amplitude reading at the moment it is called.\r\n * For continuous readings, run in the draw loop.\r\n *\r\n * @method getLevel\r\n * @for p5.Amplitude\r\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\r\n * @return {Number} Amplitude as a number between 0.0 and 1.0\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * amplitude = new p5.Amplitude();\r\n * sound.play();\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.getLevel = function(channel) {\r\n if (typeof channel !== 'undefined') {\r\n if (this.normalize) {\r\n return this.stereoVolNorm[channel];\r\n } else {\r\n return this.stereoVol[channel];\r\n }\r\n }\r\n else if (this.normalize) {\r\n return this.volNorm;\r\n }\r\n else {\r\n return this.volume;\r\n }\r\n };\r\n\r\n /**\r\n * Determines whether the results of Amplitude.process() will be\r\n * Normalized. To normalize, Amplitude finds the difference the\r\n * loudest reading it has processed and the maximum amplitude of\r\n * 1.0. Amplitude adds this difference to all values to produce\r\n * results that will reliably map between 0.0 and 1.0. However,\r\n * if a louder moment occurs, the amount that Normalize adds to\r\n * all the values will change. Accepts an optional boolean parameter\r\n * (true or false). Normalizing is off by default.\r\n *\r\n * @method toggleNormalize\r\n * @for p5.Amplitude\r\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\r\n */\r\n p5.Amplitude.prototype.toggleNormalize = function(bool) {\r\n if (typeof bool === 'boolean') {\r\n this.normalize = bool;\r\n }\r\n else {\r\n this.normalize = !this.normalize;\r\n }\r\n };\r\n\r\n /**\r\n * Smooth Amplitude analysis by averaging with the last analysis\r\n * frame. Off by default.\r\n *\r\n * @method smooth\r\n * @for p5.Amplitude\r\n * @param {Number} set smoothing from 0.0 <= 1\r\n */\r\n p5.Amplitude.prototype.smooth = function(s) {\r\n if (s >= 0 && s < 1) {\r\n this.smoothing = s;\r\n } else {\r\n console.log('Error: smoothing must be between 0 and 1');\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n\r\n delete this.processor;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n *
FFT (Fast Fourier Transform) is an analysis algorithm that\r\n * isolates individual\r\n * \r\n * audio frequencies within a waveform.
\r\n *\r\n *
Once instantiated, a p5.FFT object can return an array based on\r\n * two types of analyses: • FFT.waveform() computes\r\n * amplitude values along the time domain. The array indices correspond\r\n * to samples across a brief moment in time. Each value represents\r\n * amplitude of the waveform at that sample of time. \r\n * • FFT.analyze() computes amplitude values along the\r\n * frequency domain. The array indices correspond to frequencies (i.e.\r\n * pitches), from the lowest to the highest that humans can hear. Each\r\n * value represents amplitude at that slice of the frequency spectrum.\r\n * Use with getEnergy() to measure amplitude at specific\r\n * frequencies, or within a range of frequencies.
\r\n *\r\n *
FFT analyzes a very short snapshot of sound called a sample\r\n * buffer. It returns an array of amplitude measurements, referred\r\n * to as bins. The array is 1024 bins long by default.\r\n * You can change the bin array length, but it must be a power of 2\r\n * between 16 and 1024 in order for the FFT algorithm to function\r\n * correctly. The actual size of the FFT buffer is twice the\r\n * number of bins, so given a standard sample rate, the buffer is\r\n * 2048/44100 seconds long.
\r\n *\r\n *\r\n * @class p5.FFT\r\n * @constructor\r\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\r\n * 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n * @param {Number} [bins] Length of resulting array.\r\n * Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup(){\r\n * var cnv = createCanvas(100,100);\r\n * cnv.mouseClicked(togglePlay);\r\n * fft = new p5.FFT();\r\n * sound.amp(0.2);\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h )\r\n * }\r\n *\r\n * var waveform = fft.waveform();\r\n * noFill();\r\n * beginShape();\r\n * stroke(255,0,0); // waveform is red\r\n * strokeWeight(1);\r\n * for (var i = 0; i< waveform.length; i++){\r\n * var x = map(i, 0, waveform.length, 0, width);\r\n * var y = map( waveform[i], -1, 1, 0, height);\r\n * vertex(x,y);\r\n * }\r\n * endShape();\r\n *\r\n * text('click to play/pause', 4, 10);\r\n * }\r\n *\r\n * // fade sound if mouse is over canvas\r\n * function togglePlay() {\r\n * if (sound.isPlaying()) {\r\n * sound.pause();\r\n * } else {\r\n * sound.loop();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.FFT = function(smoothing, bins) {\r\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\r\n\r\n Object.defineProperties(this, {\r\n bins: {\r\n get: function() {\r\n return this.analyser.fftSize / 2;\r\n },\r\n set: function(b) {\r\n this.analyser.fftSize = b * 2;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n },\r\n smoothing: {\r\n get: function() {\r\n return this.analyser.smoothingTimeConstant;\r\n },\r\n set: function(s) {\r\n this.analyser.smoothingTimeConstant = s;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n }\r\n });\r\n\r\n // set default smoothing and bins\r\n this.smooth(smoothing);\r\n this.bins = bins || 1024;\r\n\r\n // default connections to p5sound fftMeter\r\n p5sound.fftMeter.connect(this.analyser);\r\n\r\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n\r\n // predefined frequency ranges, these will be tweakable\r\n this.bass = [20, 140];\r\n this.lowMid = [140, 400];\r\n this.mid = [400, 2600];\r\n this.highMid = [2600, 5200];\r\n this.treble = [5200, 14000];\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the input source for the FFT analysis. If no source is\r\n * provided, FFT will analyze all sound in the sketch.\r\n *\r\n * @method setInput\r\n * @for p5.FFT\r\n * @param {Object} [source] p5.sound object (or web audio API source node)\r\n */\r\n p5.FFT.prototype.setInput = function(source) {\r\n if (!source) {\r\n p5sound.fftMeter.connect(this.analyser);\r\n } else {\r\n if (source.output) {\r\n source.output.connect(this.analyser);\r\n } else if (source.connect) {\r\n source.connect(this.analyser);\r\n }\r\n p5sound.fftMeter.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\r\n * a snapshot of amplitude readings in a single buffer. Length will be\r\n * equal to bins (defaults to 1024). Can be used to draw the waveform\r\n * of a sound.\r\n *\r\n * @method waveform\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {String} [precision] If any value is provided, will return results\r\n * in a Float32 Array which is more precise\r\n * than a regular array.\r\n * @return {Array} Array Array of amplitude values (-1 to 1)\r\n * over time. Array length = bins.\r\n *\r\n */\r\n p5.FFT.prototype.waveform = function() {\r\n var bins, mode, normalArray;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n bins = arguments[i];\r\n this.analyser.fftSize = bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\r\n if (mode && !p5.prototype._isSafari()) {\r\n timeToFloat(this, this.timeDomain);\r\n this.analyser.getFloatTimeDomainData(this.timeDomain);\r\n return this.timeDomain;\r\n } else {\r\n timeToInt(this, this.timeDomain);\r\n this.analyser.getByteTimeDomainData(this.timeDomain);\r\n var normalArray = new Array();\r\n for (var j = 0; j < this.timeDomain.length; j++) {\r\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\r\n normalArray.push(scaled);\r\n }\r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between 0 and 255)\r\n * across the frequency spectrum. Length is equal to FFT bins\r\n * (1024 by default). The array indices correspond to frequencies\r\n * (i.e. pitches), from the lowest to the highest that humans can\r\n * hear. Each value represents amplitude at that slice of the\r\n * frequency spectrum. Must be called prior to using\r\n * getEnergy().\r\n *\r\n * @method analyze\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {Number} [scale] If \"dB,\" returns decibel\r\n * float measurements between\r\n * -140 and 0 (max).\r\n * Otherwise returns integers from 0-255.\r\n * @return {Array} spectrum Array of energy (amplitude/volume)\r\n * values across the frequency spectrum.\r\n * Lowest energy (silence) = 0, highest\r\n * possible is 255.\r\n * @example\r\n *
\r\n * var osc;\r\n * var fft;\r\n *\r\n * function setup(){\r\n * createCanvas(100,100);\r\n * osc = new p5.Oscillator();\r\n * osc.amp(0);\r\n * osc.start();\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var freq = map(mouseX, 0, 800, 20, 15000);\r\n * freq = constrain(freq, 1, 20000);\r\n * osc.freq(freq);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h );\r\n * }\r\n *\r\n * stroke(255);\r\n * text('Freq: ' + round(freq)+'Hz', 10, 10);\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * // only play sound when mouse is over canvas\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * osc.amp(0.5, 0.2);\r\n * } else {\r\n * osc.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n *\r\n *\r\n */\r\n p5.FFT.prototype.analyze = function() {\r\n var mode;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n this.bins = arguments[i];\r\n this.analyser.fftSize = this.bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n if (mode && mode.toLowerCase() === 'db') {\r\n freqToFloat(this);\r\n this.analyser.getFloatFrequencyData(this.freqDomain);\r\n return this.freqDomain;\r\n } else {\r\n freqToInt(this, this.freqDomain);\r\n this.analyser.getByteFrequencyData(this.freqDomain);\r\n var normalArray = Array.apply([], this.freqDomain);\r\n \r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns the amount of energy (volume) at a specific\r\n * \r\n * frequency, or the average amount of energy between two\r\n * frequencies. Accepts Number(s) corresponding\r\n * to frequency (in Hz), or a String corresponding to predefined\r\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\r\n * Returns a range between 0 (no energy/volume at that frequency) and\r\n * 255 (maximum energy).\r\n * NOTE: analyze() must be called prior to getEnergy(). Analyze()\r\n * tells the FFT to analyze frequency data, and getEnergy() uses\r\n * the results determine the value at a specific frequency or\r\n * range of frequencies.
\r\n *\r\n * @method getEnergy\r\n * @for p5.FFT\r\n * @param {Number|String} frequency1 Will return a value representing\r\n * energy at this frequency. Alternately,\r\n * the strings \"bass\", \"lowMid\" \"mid\",\r\n * \"highMid\", and \"treble\" will return\r\n * predefined frequency ranges.\r\n * @param {Number} [frequency2] If a second frequency is given,\r\n * will return average amount of\r\n * energy that exists between the\r\n * two frequencies.\r\n * @return {Number} Energy Energy (volume/amplitude) from\r\n * 0 and 255.\r\n *\r\n */\r\n p5.FFT.prototype.getEnergy = function(frequency1, frequency2) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n\r\n if (frequency1 === 'bass') {\r\n frequency1 = this.bass[0];\r\n frequency2 = this.bass[1];\r\n } else if (frequency1 === 'lowMid') {\r\n frequency1 = this.lowMid[0];\r\n frequency2 = this.lowMid[1];\r\n } else if (frequency1 === 'mid') {\r\n frequency1 = this.mid[0];\r\n frequency2 = this.mid[1];\r\n } else if (frequency1 === 'highMid') {\r\n frequency1 = this.highMid[0];\r\n frequency2 = this.highMid[1];\r\n } else if (frequency1 === 'treble') {\r\n frequency1 = this.treble[0];\r\n frequency2 = this.treble[1];\r\n }\r\n\r\n if (typeof frequency1 !== 'number') {\r\n throw 'invalid input for getEnergy()';\r\n } else if (!frequency2) {\r\n // if only one parameter:\r\n var index = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n return this.freqDomain[index];\r\n } else if (frequency1 && frequency2) {\r\n // if two parameters:\r\n // if second is higher than first\r\n if (frequency1 > frequency2) {\r\n var swap = frequency2;\r\n frequency2 = frequency1;\r\n frequency1 = swap;\r\n }\r\n var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length);\r\n\r\n var total = 0;\r\n var numFrequencies = 0;\r\n // add up all of the values for the frequencies\r\n for (var i = lowIndex; i <= highIndex; i++) {\r\n total += this.freqDomain[i];\r\n numFrequencies += 1;\r\n }\r\n // divide by total number of frequencies\r\n var toReturn = total / numFrequencies;\r\n return toReturn;\r\n } else {\r\n throw 'invalid input for getEnergy()';\r\n }\r\n };\r\n\r\n // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\r\n p5.FFT.prototype.getFreq = function(freq1, freq2) {\r\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\r\n var x = this.getEnergy(freq1, freq2);\r\n return x;\r\n };\r\n\r\n /**\r\n * Returns the\r\n * \r\n * spectral centroid of the input signal.\r\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\r\n * tells the FFT to analyze frequency data, and getCentroid() uses\r\n * the results determine the spectral centroid.\r\n *\r\n * @method getCentroid\r\n * @for p5.FFT\r\n * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz.\r\n *\r\n *\r\n * @example\r\n *
\r\n *\r\n *\r\n *function setup(){\r\n * cnv = createCanvas(100,100);\r\n * sound = new p5.AudioIn();\r\n * sound.start();\r\n * fft = new p5.FFT();\r\n * sound.connect(fft);\r\n *}\r\n *\r\n *\r\n *function draw(){\r\n *\r\n * var centroidplot = 0.0;\r\n * var spectralCentroid = 0;\r\n *\r\n *\r\n * background(0);\r\n * stroke(0,255,0);\r\n * var spectrum = fft.analyze();\r\n * fill(0,255,0); // spectrum is green\r\n *\r\n * //draw the spectrum\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(log(i), 0, log(spectrum.length), 0, width);\r\n * var h = map(spectrum[i], 0, 255, 0, height);\r\n * var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\r\n * rect(x, height, rectangle_width, -h )\r\n * }\r\n\r\n * var nyquist = 22050;\r\n *\r\n * // get the centroid\r\n * spectralCentroid = fft.getCentroid();\r\n *\r\n * // the mean_freq_index calculation is for the display.\r\n * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\r\n *\r\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\r\n *\r\n *\r\n * stroke(255,0,0); // the line showing where the centroid is will be red\r\n *\r\n * rect(centroidplot, 0, width / spectrum.length, height)\r\n * noStroke();\r\n * fill(255,255,255); // text is white\r\n * text(\"centroid: \", 10, 20);\r\n * text(round(spectralCentroid)+\" Hz\", 10, 40);\r\n *}\r\n *
\r\n */\r\n p5.FFT.prototype.getCentroid = function() {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var cumulative_sum = 0;\r\n var centroid_normalization = 0;\r\n\r\n for (var i = 0; i < this.freqDomain.length; i++) {\r\n cumulative_sum += i * this.freqDomain[i];\r\n centroid_normalization += this.freqDomain[i];\r\n }\r\n\r\n var mean_freq_index = 0;\r\n\r\n if (centroid_normalization !== 0) {\r\n mean_freq_index = cumulative_sum / centroid_normalization;\r\n }\r\n\r\n var spec_centroid_freq =\r\n mean_freq_index * (nyquist / this.freqDomain.length);\r\n return spec_centroid_freq;\r\n };\r\n\r\n /**\r\n * Smooth FFT analysis by averaging with the last analysis frame.\r\n *\r\n * @method smooth\r\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n */\r\n p5.FFT.prototype.smooth = function(s) {\r\n if (typeof s !== 'undefined') {\r\n this.smoothing = s;\r\n }\r\n return this.smoothing;\r\n };\r\n\r\n p5.FFT.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.analyser) {\r\n this.analyser.disconnect();\r\n delete this.analyser;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values for a given number\r\n * of frequency bands split equally. N defaults to 16.\r\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and linAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method linAverages\r\n * @for p5.FFT\r\n * @param {Number} N Number of returned frequency groups\r\n * @return {Array} linearAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.linAverages = function(N) {\r\n var N = N || 16; // This prevents undefined, null or 0 values of N\r\n\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n var spectrumStep = Math.floor(spectrumLength / N);\r\n\r\n var linearAverages = new Array(N);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // with only one loop in the spectrum data\r\n var groupIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n linearAverages[groupIndex] =\r\n linearAverages[groupIndex] !== undefined\r\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n\r\n // Increase the group index when the last element of the group is processed\r\n if (specIndex % spectrumStep === spectrumStep - 1) {\r\n groupIndex++;\r\n }\r\n }\r\n\r\n return linearAverages;\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values of the spectrum, for a given\r\n * set of \r\n * Octave Bands\r\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and logAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method logAverages\r\n * @for p5.FFT\r\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\r\n * @return {Array} logAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.logAverages = function(octaveBands) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n\r\n var logAverages = new Array(octaveBands.length);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // With only one loop in the spectrum data\r\n var octaveIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n var specIndexFrequency = Math.round(\r\n specIndex * nyquist / this.freqDomain.length\r\n );\r\n\r\n // Increase the group index if the current frequency exceeds the limits of the band\r\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\r\n octaveIndex++;\r\n }\r\n\r\n logAverages[octaveIndex] =\r\n logAverages[octaveIndex] !== undefined\r\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n }\r\n\r\n return logAverages;\r\n };\r\n\r\n /**\r\n * Calculates and Returns the 1/N\r\n * Octave Bands\r\n * N defaults to 3 and minimum central frequency to 15.625Hz.\r\n * (1/3 Octave Bands ~= 31 Frequency Bands)\r\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\r\n * and produce less frequency groups.\r\n *\r\n * @method getOctaveBands\r\n * @for p5.FFT\r\n * @param {Number} N Specifies the 1/N type of generated octave bands\r\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\r\n * @return {Array} octaveBands Array of octave band objects with their bounds\r\n */\r\n p5.FFT.prototype.getOctaveBands = function(N, fCtr0) {\r\n var N = N || 3; // Default to 1/3 Octave Bands\r\n var fCtr0 = fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\r\n\r\n var octaveBands = [];\r\n var lastFrequencyBand = {\r\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\r\n ctr: fCtr0,\r\n hi: fCtr0 * Math.pow(2, 1 / (2 * N))\r\n };\r\n octaveBands.push(lastFrequencyBand);\r\n\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n while (lastFrequencyBand.hi < nyquist) {\r\n var newFrequencyBand = {};\r\n newFrequencyBand.lo = lastFrequencyBand.hi;\r\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\r\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\r\n\r\n octaveBands.push(newFrequencyBand);\r\n lastFrequencyBand = newFrequencyBand;\r\n }\r\n\r\n return octaveBands;\r\n };\r\n\r\n // helper methods to convert type from float (dB) to int (0-255)\r\n var freqToFloat = function(fft) {\r\n if (fft.freqDomain instanceof Float32Array === false) {\r\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var freqToInt = function(fft) {\r\n if (fft.freqDomain instanceof Uint8Array === false) {\r\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToFloat = function(fft) {\r\n if (fft.timeDomain instanceof Float32Array === false) {\r\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToInt = function(fft) {\r\n if (fft.timeDomain instanceof Uint8Array === false) {\r\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // Signal is built with the Tone.js signal by Yotam Mann\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Signal = require('Tone/signal/Signal');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
p5.Signal is a constant audio-rate signal used by p5.Oscillator\r\n * and p5.Envelope for modulation math.
\r\n *\r\n *
This is necessary because Web Audio is processed on a seprate clock.\r\n * For example, the p5 draw loop runs about 60 times per second. But\r\n * the audio clock must process samples 44100 times per second. If we\r\n * want to add a value to each of those samples, we can't do it in the\r\n * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns\r\n * a Tone.Signal from the Tone.js library by Yotam Mann.\r\n * If you want to work directly with audio signals for modular\r\n * synthesis, check out\r\n * tone.js.
\r\n *\r\n * @class p5.Signal\r\n * @constructor\r\n * @return {Tone.Signal} A Signal object from the Tone.js library\r\n * @example\r\n *
\r\n * function setup() {\r\n * carrier = new p5.Oscillator('sine');\r\n * carrier.amp(1); // set amplitude\r\n * carrier.freq(220); // set frequency\r\n * carrier.start(); // start oscillating\r\n *\r\n * modulator = new p5.Oscillator('sawtooth');\r\n * modulator.disconnect();\r\n * modulator.amp(1);\r\n * modulator.freq(4);\r\n * modulator.start();\r\n *\r\n * // Modulator's default amplitude range is -1 to 1.\r\n * // Multiply it by -200, so the range is -200 to 200\r\n * // then add 220 so the range is 20 to 420\r\n * carrier.freq( modulator.mult(-200).add(220) );\r\n * }\r\n *
\r\n */\r\n p5.Signal = function(value) {\r\n var s = new Signal(value);\r\n // p5sound.soundArray.push(s);\r\n return s; // TODO: is this really a constructor?\r\n };\r\n\r\n /**\r\n * Fade to value, for smooth transitions\r\n *\r\n * @method fade\r\n * @for p5.Signal\r\n * @param {Number} value Value to set this signal\r\n * @param {Number} [secondsFromNow] Length of fade, in seconds from now\r\n */\r\n Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime;\r\n Mult.prototype.fade = Signal.prototype.fade;\r\n Add.prototype.fade = Signal.prototype.fade;\r\n Scale.prototype.fade = Signal.prototype.fade;\r\n\r\n\r\n /**\r\n * Connect a p5.sound object or Web Audio node to this\r\n * p5.Signal so that its amplitude values can be scaled.\r\n *\r\n * @method setInput\r\n * @for p5.Signal\r\n * @param {Object} input\r\n */\r\n Signal.prototype.setInput = function(_input) {\r\n _input.connect(this);\r\n };\r\n Mult.prototype.setInput = Signal.prototype.setInput;\r\n Add.prototype.setInput = Signal.prototype.setInput;\r\n Scale.prototype.setInput = Signal.prototype.setInput;\r\n\r\n\r\n // signals can add / mult / scale themselves\r\n\r\n /**\r\n * Add a constant value to this audio signal,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalAdd.\r\n *\r\n * @method add\r\n * @for p5.Signal\r\n * @param {Number} number\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.add = function(num) {\r\n var add = new Add(num);\r\n // add.setInput(this);\r\n this.connect(add);\r\n return add;\r\n };\r\n Mult.prototype.add = Signal.prototype.add;\r\n Add.prototype.add = Signal.prototype.add;\r\n Scale.prototype.add = Signal.prototype.add;\r\n\r\n /**\r\n * Multiply this signal by a constant value,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalMult.\r\n *\r\n * @method mult\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n // mult.setInput(this);\r\n this.connect(mult);\r\n return mult;\r\n };\r\n Mult.prototype.mult = Signal.prototype.mult;\r\n Add.prototype.mult = Signal.prototype.mult;\r\n Scale.prototype.mult = Signal.prototype.mult;\r\n\r\n /**\r\n * Scale this signal value to a given range,\r\n * and return the result as an audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalScale.\r\n *\r\n * @method scale\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n this.connect(scale);\r\n return scale;\r\n };\r\n Mult.prototype.scale = Signal.prototype.scale;\r\n Add.prototype.scale = Signal.prototype.scale;\r\n Scale.prototype.scale = Signal.prototype.scale;\r\n\r\n});\r\n\r\n\r\n","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Frequency is a primitive type for encoding Frequency values. \n\t * Eventually all time values are evaluated to hertz\n\t * using the `eval` method. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * Tone.Frequency(\"C3\") // 261\n\t * Tone.Frequency(38, \"midi\") //\n\t * Tone.Frequency(\"C3\").transpose(4);\n\t */\n\tTone.Frequency = function(val, units){\n\t\tif (this instanceof Tone.Frequency){\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Frequency(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Frequency, Tone.TimeBase);\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUGMENT BASE EXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);\n\n\t/*\n\t * midi type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.midi = {\n\t\tregexp : /^(\\d+(?:\\.\\d+)?midi)/,\n\t\tmethod : function(value){\n\t\t\treturn this.midiToFrequency(value);\n\t\t}\t\n\t};\n\n\t/*\n\t * note type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.note = {\n\t\tregexp : /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,\n\t\tmethod : function(pitch, octave){\n\t\t\tvar index = noteToScaleIndex[pitch.toLowerCase()];\n\t\t\tvar noteNumber = index + (parseInt(octave) + 1) * 12;\n\t\t\treturn this.midiToFrequency(noteNumber);\n\t\t}\t\n\t};\n\n\t/*\n\t * BeatsBarsSixteenths type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.tr = {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\tvar total = 1;\n\t\t\tif (m && m !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t}\n\t\t\tif (q && q !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(q));\n\t\t\t}\n\t\t\tif (s && s !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t}\n\t\t\treturn total;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Transposes the frequency by the given number of semitones.\n\t * @param {Interval} interval\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").transpose(3); //\"C5\"\n\t */\n\tTone.Frequency.prototype.transpose = function(interval){\n\t\tthis._expr = function(expr, interval){\n\t\t\tvar val = expr();\n\t\t\treturn val * this.intervalToFrequencyRatio(interval);\n\t\t}.bind(this, this._expr, interval);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Takes an array of semitone intervals and returns\n\t * an array of frequencies transposed by those intervals.\n\t * @param {Array} intervals\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").harmonize([0, 3, 7]); //[\"A4\", \"C5\", \"E5\"]\n\t */\n\tTone.Frequency.prototype.harmonize = function(intervals){\n\t\tthis._expr = function(expr, intervals){\n\t\t\tvar val = expr();\n\t\t\tvar ret = [];\n\t\t\tfor (var i = 0; i < intervals.length; i++){\n\t\t\t\tret[i] = val * this.intervalToFrequencyRatio(intervals[i]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t}.bind(this, this._expr, intervals);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the value of the frequency as a MIDI note\n\t * @return {MIDI}\n\t * @example\n\t * Tone.Frequency(\"C4\").toMidi(); //60\n\t */\n\tTone.Frequency.prototype.toMidi = function(){\n\t\treturn this.frequencyToMidi(this.valueOf());\n\t};\n\n\t/**\n\t * Return the value of the frequency in Scientific Pitch Notation\n\t * @return {Note}\n\t * @example\n\t * Tone.Frequency(69, \"midi\").toNote(); //\"A4\"\n\t */\n\tTone.Frequency.prototype.toNote = function(){\n\t\tvar freq = this.valueOf();\n\t\tvar log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;\n\t\tvar noteNumber = Math.round(12 * log) + 57;\n\t\tvar octave = Math.floor(noteNumber/12);\n\t\tif(octave < 0){\n\t\t\tnoteNumber += -12 * octave;\n\t\t}\n\t\tvar noteName = scaleIndexToNote[noteNumber % 12];\n\t\treturn noteName + octave.toString();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.Frequency.prototype.toSeconds = function(){\n\t\treturn 1 / this.valueOf();\n\t};\n\n\t/**\n\t * Return the value in Hertz\n\t * @return {Frequency}\n\t */\n\tTone.Frequency.prototype.toFrequency = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in ticks\n\t * @return {Ticks}\n\t */\n\tTone.Frequency.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS HELPERS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._frequencyToUnits = function(freq){\n\t\treturn freq;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._ticksToUnits = function(ticks){\n\t\treturn 1 / ((ticks * 60) / (Tone.Transport.bpm.value * Tone.Transport.PPQ));\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._beatsToUnits = function(beats){\n\t\treturn 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._secondsToUnits = function(seconds){\n\t\treturn 1 / seconds;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.Frequency.prototype._defaultUnits = \"hz\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tFREQUENCY CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Note to scale index\n\t * @type {Object}\n\t */\n\tvar noteToScaleIndex = {\n\t\t\"cbb\" : -2, \"cb\" : -1, \"c\" : 0, \"c#\" : 1, \"cx\" : 2, \n\t\t\"dbb\" : 0, \"db\" : 1, \"d\" : 2, \"d#\" : 3, \"dx\" : 4,\n\t\t\"ebb\" : 2, \"eb\" : 3, \"e\" : 4, \"e#\" : 5, \"ex\" : 6, \n\t\t\"fbb\" : 3, \"fb\" : 4, \"f\" : 5, \"f#\" : 6, \"fx\" : 7,\n\t\t\"gbb\" : 5, \"gb\" : 6, \"g\" : 7, \"g#\" : 8, \"gx\" : 9,\n\t\t\"abb\" : 7, \"ab\" : 8, \"a\" : 9, \"a#\" : 10, \"ax\" : 11,\n\t\t\"bbb\" : 9, \"bb\" : 10, \"b\" : 11, \"b#\" : 12, \"bx\" : 13,\n\t};\n\n\t/**\n\t * scale index to note (sharps)\n\t * @type {Array}\n\t */\n\tvar scaleIndexToNote = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"];\n\n\t/**\n\t * The [concert pitch](https://en.wikipedia.org/wiki/Concert_pitch)\n\t * A4's values in Hertz. \n\t * @type {Frequency}\n\t * @static\n\t */\n\tTone.Frequency.A4 = 440;\n\n\t/**\n\t * Convert a MIDI note to frequency value. \n\t * @param {MIDI} midi The midi number to convert.\n\t * @return {Frequency} the corresponding frequency value\n\t * @example\n\t * tone.midiToFrequency(69); // returns 440\n\t */\n\tTone.Frequency.prototype.midiToFrequency = function(midi){\n\t\treturn Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);\n\t};\n\n\t/**\n\t * Convert a frequency value to a MIDI note.\n\t * @param {Frequency} frequency The value to frequency value to convert.\n\t * @returns {MIDI}\n\t * @example\n\t * tone.midiToFrequency(440); // returns 69\n\t */\n\tTone.Frequency.prototype.frequencyToMidi = function(frequency){\n\t\treturn 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;\n\t};\n\n\treturn Tone.Frequency;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TransportTime is a the time along the Transport's\n\t * timeline. It is similar to Tone.Time, but instead of evaluating\n\t * against the AudioContext's clock, it is evaluated against\n\t * the Transport's position. See [TransportTime wiki](https://github.com/Tonejs/Tone.js/wiki/TransportTime).\n\t * @constructor\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @extends {Tone.Time}\n\t */\n\tTone.TransportTime = function(val, units){\n\t\tif (this instanceof Tone.TransportTime){\n\t\t\t\n\t\t\tTone.Time.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.TransportTime(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TransportTime, Tone.Time);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);\n\n\t/**\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\tvar subdivision = this._secondsToTicks(rh());\n\t\t\tvar multiple = Math.ceil(Tone.Transport.ticks / subdivision);\n\t\t\treturn this._ticksToUnits(multiple * subdivision);\n\t\t}\n\t};\n\n\t/**\n\t * Convert seconds into ticks\n\t * @param {Seconds} seconds\n\t * @return {Ticks}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._secondsToTicks = function(seconds){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = seconds / quarterTime;\n\t\treturn Math.round(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Evaluate the time expression. Returns values in ticks\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.valueOf = function(){\n\t\tvar val = this._secondsToTicks(this._expr());\n\t\treturn val + (this._plusNow ? Tone.Transport.ticks : 0);\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.toTicks = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.TransportTime.prototype.toSeconds = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow ? Tone.Transport.seconds : 0);\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t */\n\tTone.TransportTime.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\treturn Tone.TransportTime;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n\r\n /**\r\n *
Envelopes are pre-defined amplitude distribution over time.\r\n * Typically, envelopes are used to control the output volume\r\n * of an object, a series of fades referred to as Attack, Decay,\r\n * Sustain and Release (\r\n * ADSR\r\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\r\n * control an Oscillator's frequency like this: osc.freq(env).
\r\n *
Use setRange to change the attack/release level.\r\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.
\r\n *
Use the play method to play the entire envelope,\r\n * the ramp method for a pingable trigger,\r\n * or triggerAttack/\r\n * triggerRelease to trigger noteOn/noteOff.
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope = function(t1, l1, t2, l2, t3, l3) {\r\n /**\r\n * Time until envelope reaches attackLevel\r\n * @property attackTime\r\n */\r\n this.aTime = t1 || 0.1;\r\n /**\r\n * Level once attack is complete.\r\n * @property attackLevel\r\n */\r\n this.aLevel = l1 || 1;\r\n /**\r\n * Time until envelope reaches decayLevel.\r\n * @property decayTime\r\n */\r\n this.dTime = t2 || 0.5;\r\n /**\r\n * Level after decay. The envelope will sustain here until it is released.\r\n * @property decayLevel\r\n */\r\n this.dLevel = l2 || 0;\r\n /**\r\n * Duration of the release portion of the envelope.\r\n * @property releaseTime\r\n */\r\n this.rTime = t3 || 0;\r\n /**\r\n * Level at the end of the release.\r\n * @property releaseLevel\r\n */\r\n this.rLevel = l3 || 0;\r\n\r\n this._rampHighPercentage = 0.98;\r\n\r\n this._rampLowPercentage = 0.02;\r\n\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.control = new TimelineSignal();\r\n\r\n this._init(); // this makes sure the envelope starts at zero\r\n\r\n this.control.connect(this.output); // connect to the output\r\n\r\n this.connection = null; // store connection\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.control];\r\n\r\n //whether envelope should be linear or exponential curve\r\n this.isExponential = false;\r\n\r\n // oscillator or buffer source to clear on env complete\r\n // to save resources if/when it is retriggered\r\n this.sourceToClear = null;\r\n\r\n // set to true if attack is set, then false on release\r\n this.wasTriggered = false;\r\n\r\n\r\n // add to the soundArray so we can dispose of the env later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n // this init function just smooths the starting value to zero and gives a start point for the timeline\r\n // - it was necessary to remove glitches at the beginning.\r\n p5.Envelope.prototype._init = function () {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = now;\r\n this.control.setTargetAtTime(0.00001, t, .001);\r\n //also, compute the correct time constants\r\n this._setRampAD(this.aTime, this.dTime);\r\n };\r\n\r\n /**\r\n * Reset the envelope with a series of time/value pairs.\r\n *\r\n * @method set\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds) before level\r\n * reaches attackLevel\r\n * @param {Number} attackLevel Typically an amplitude between\r\n * 0.0 and 1.0\r\n * @param {Number} decayTime Time\r\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\r\n * decayLevel = sustainLevel)\r\n * @param {Number} releaseTime Release Time (in seconds)\r\n * @param {Number} releaseLevel Amplitude\r\n * @example\r\n *
\r\n * var t1 = 0.1; // attack time in seconds\r\n * var l1 = 0.7; // attack level 0.0 to 1.0\r\n * var t2 = 0.3; // decay time in seconds\r\n * var l2 = 0.1; // decay level 0.0 to 1.0\r\n * var t3 = 0.2; // sustain time in seconds\r\n * var l3 = 0.5; // sustain level 0.0 to 1.0\r\n * // release level defaults to zero\r\n *\r\n * var env;\r\n * var triOsc;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope(t1, l1, t2, l2, t3, l3);\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env); // give the env control of the triOsc's amp\r\n * triOsc.start();\r\n * }\r\n *\r\n * // mouseClick triggers envelope if over canvas\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(triOsc);\r\n * }\r\n * }\r\n *
\r\n *\r\n */\r\n p5.Envelope.prototype.set = function(t1, l1, t2, l2, t3, l3) {\r\n this.aTime = t1;\r\n this.aLevel = l1;\r\n this.dTime = t2 || 0;\r\n this.dLevel = l2 || 0;\r\n this.rTime = t3 || 0;\r\n this.rLevel = l3 || 0;\r\n\r\n // set time constants for ramp\r\n this._setRampAD(t1, t2);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setADSR = function(aTime, dTime, sPercent, rTime) {\r\n this.aTime = aTime;\r\n this.dTime = dTime || 0;\r\n\r\n // lerp\r\n this.sPercent = sPercent || 0;\r\n this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n\r\n this.rTime = rTime || 0;\r\n\r\n // also set time constants for ramp\r\n this._setRampAD(aTime, dTime);\r\n };\r\n\r\n /**\r\n * Set max (attackLevel) and min (releaseLevel) of envelope.\r\n *\r\n * @method setRange\r\n * @for p5.Envelope\r\n * @param {Number} aLevel attack level (defaults to 1)\r\n * @param {Number} rLevel release level (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setRange = function(aLevel, rLevel) {\r\n this.aLevel = aLevel || 1;\r\n this.rLevel = rLevel || 0;\r\n\r\n // not sure if this belongs here:\r\n\r\n // {Number} [dLevel] decay/sustain level (optional)\r\n // if (typeof(dLevel) !== 'undefined') {\r\n // this.dLevel = dLevel\r\n // } else if (this.sPercent) {\r\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n // }\r\n };\r\n\r\n // private (undocumented) method called when ADSR is set to set time constants for ramp\r\n //\r\n // Set the \r\n // time constants for simple exponential ramps.\r\n // The larger the time constant value, the slower the\r\n // transition will be.\r\n //\r\n // method _setRampAD\r\n // param {Number} attackTimeConstant attack time constant\r\n // param {Number} decayTimeConstant decay time constant\r\n //\r\n p5.Envelope.prototype._setRampAD = function(t1, t2) {\r\n this._rampAttackTime = this.checkExpInput(t1);\r\n this._rampDecayTime = this.checkExpInput(t2);\r\n\r\n var TCDenominator = 1.0;\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n // private method\r\n p5.Envelope.prototype.setRampPercentages = function(p1, p2) {\r\n //set the percentages that the simple exponential ramps go to\r\n this._rampHighPercentage = this.checkExpInput(p1);\r\n this._rampLowPercentage = this.checkExpInput(p2);\r\n var TCDenominator = 1.0;\r\n //now re-compute the time constants based on those percentages\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n\r\n /**\r\n * Assign a parameter to be controlled by this envelope.\r\n * If a p5.Sound object is given, then the p5.Envelope will control its\r\n * output gain. If multiple inputs are provided, the env will\r\n * control all of them.\r\n *\r\n * @method setInput\r\n * @for p5.Envelope\r\n * @param {Object} [...inputs] A p5.sound object or\r\n * Web Audio Param.\r\n */\r\n p5.Envelope.prototype.setInput = function() {\r\n for (var i = 0; i\r\n * Web Audio Audio Param.\r\n *\r\n * @method play\r\n * @for p5.Envelope\r\n * @param {Object} unit A p5.sound object or\r\n * Web Audio Param.\r\n * @param {Number} [startTime] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * // trigger env on triOsc, 0 seconds from now\r\n * // After decay, sustain for 0.2 seconds before release\r\n * env.play(triOsc, 0, 0.2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.play = function(unit, secondsFromNow, susTime) {\r\n var tFromNow = secondsFromNow || 0;\r\n var susTime = susTime || 0;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n this.triggerAttack(unit, tFromNow);\r\n\r\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime);\r\n\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go. Input can be\r\n * any p5.sound object, or a \r\n * Web Audio Param.\r\n *\r\n * @method triggerAttack\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time from now (in seconds)\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerAttack = function(unit, secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n this.lastAttack = t;\r\n this.wasTriggered = true;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // after each ramp completes, cancel scheduled values\r\n // (so they can be overridden in case env has been re-triggered)\r\n // then, set current value (with linearRamp to avoid click)\r\n // then, schedule the next automation...\r\n\r\n // attack\r\n t += this.aTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.aLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n\r\n }\r\n\r\n // decay to decay level (if using ADSR, then decay level == sustain level)\r\n t += this.dTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.dLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n };\r\n\r\n /**\r\n * Trigger the Release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method triggerRelease\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerRelease = function(unit, secondsFromNow) {\r\n\r\n // only trigger a release if an attack was triggered\r\n if (!this.wasTriggered) {\r\n // this currently causes a bit of trouble:\r\n // if a later release has been scheduled (via the play function)\r\n // a new earlier release won't interrupt it, because\r\n // this.wasTriggered has already been set to false.\r\n // If we want new earlier releases to override, then we need to\r\n // keep track of the last release time, and if the new release time is\r\n // earlier, then use it.\r\n return;\r\n }\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear or exponential ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // release\r\n t += this.rTime;\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.rLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n this.wasTriggered = false;\r\n };\r\n\r\n /**\r\n * Exponentially ramp to a value using the first two\r\n * values from setADSR(attackTime, decayTime)\r\n * as \r\n * time constants for simple exponential ramps.\r\n * If the value is higher than current value, it uses attackTime,\r\n * while a decrease uses decayTime.\r\n *\r\n * @method ramp\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow When to trigger the ramp\r\n * @param {Number} v Target value\r\n * @param {Number} [v2] Second target value (optional)\r\n * @example\r\n *
\r\n * var env, osc, amp, cnv;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var attackLevel = 1;\r\n * var decayLevel = 0;\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100, 100);\r\n * fill(0,255,0);\r\n * noStroke();\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.amp(env);\r\n * osc.start();\r\n *\r\n * amp = new p5.Amplitude();\r\n *\r\n * cnv.mousePressed(triggerRamp);\r\n * }\r\n *\r\n * function triggerRamp() {\r\n * env.ramp(osc, 0, attackLevel, decayLevel);\r\n * }\r\n *\r\n * function draw() {\r\n * background(20,20,20);\r\n * text('click me', 10, 20);\r\n * var h = map(amp.getLevel(), 0, 0.4, 0, height);;\r\n *\r\n * rect(0, height, width, -h);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.ramp = function(unit, secondsFromNow, v1, v2) {\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n var destination1 = this.checkExpInput(v1);\r\n var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\r\n\r\n // connect env to unit if not already connected\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n //get current value\r\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\r\n // this.control.cancelScheduledValues(t);\r\n\r\n //if it's going up\r\n if (destination1 > currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\r\n t += this._rampAttackTime;\r\n }\r\n\r\n //if it's going down\r\n else if (destination1 < currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\r\n t += this._rampDecayTime;\r\n }\r\n\r\n // Now the second part of envelope begins\r\n if (destination2 === undefined) return;\r\n\r\n //if it's going up\r\n if (destination2 > destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\r\n }\r\n\r\n //if it's going down\r\n else if (destination2 < destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\r\n }\r\n };\r\n\r\n\r\n p5.Envelope.prototype.connect = function(unit) {\r\n this.connection = unit;\r\n\r\n // assume we're talking about output gain\r\n // unless given a different audio param\r\n if (unit instanceof p5.Oscillator ||\r\n unit instanceof p5.SoundFile ||\r\n unit instanceof p5.AudioIn ||\r\n unit instanceof p5.Reverb ||\r\n unit instanceof p5.Noise ||\r\n unit instanceof p5.Filter ||\r\n unit instanceof p5.Delay\r\n ) {\r\n unit = unit.output.gain;\r\n }\r\n if (unit instanceof AudioParam) {\r\n //set the initial value\r\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\r\n }\r\n if (unit instanceof p5.Signal) {\r\n unit.setValue(0);\r\n }\r\n this.output.connect(unit);\r\n };\r\n\r\n p5.Envelope.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n // Signal Math\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method\r\n * again will override the initial add() with new values.\r\n *\r\n * @method add\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Envelope's output amplitude\r\n * by a fixed value. Calling this method\r\n * again will override the initial mult() with new values.\r\n *\r\n * @method mult\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this envelope's amplitude values to a given\r\n * range, and return the envelope. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Envelope\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var scale = new Scale(inMin, inMax, outMin, outMax);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\r\n };\r\n\r\n\r\n // get rid of the oscillator\r\n p5.Envelope.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.disconnect();\r\n if (this.control) {\r\n this.control.dispose();\r\n this.control = null;\r\n }\r\n for (var i = 1; i < this.mathOps.length; i++) {\r\n this.mathOps[i].dispose();\r\n }\r\n };\r\n\r\n // Different name for backwards compatibility, replicates p5.Envelope class\r\n p5.Env = function(t1, l1, t2, l2, t3, l3) {\r\n console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\r\n 'Please use the new p5.Envelope instead.');\r\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\r\n };\r\n p5.Env.prototype = Object.create(p5.Envelope.prototype);\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n require('oscillator');\r\n\r\n /**\r\n * Creates a Pulse object, an oscillator that implements\r\n * Pulse Width Modulation.\r\n * The pulse is created with two oscillators.\r\n * Accepts a parameter for frequency, and to set the\r\n * width between the pulses. See \r\n * p5.Oscillator for a full list of methods.\r\n *\r\n * @class p5.Pulse\r\n * @extends p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\r\n * @param {Number} [w] Width between the pulses (0 to 1.0,\r\n * defaults to 0)\r\n * @example\r\n *
Note: This uses the getUserMedia/\r\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\r\n * is limited to localhost and https, but access over http may be limited.
\r\n *\r\n * @class p5.AudioIn\r\n * @constructor\r\n * @param {Function} [errorCallback] A function to call if there is an error\r\n * accessing the AudioIn. For example,\r\n * Safari and iOS devices do not\r\n * currently allow microphone access.\r\n * @example\r\n *
\r\n * var mic;\r\n * function setup(){\r\n * mic = new p5.AudioIn()\r\n * mic.start();\r\n * }\r\n * function draw(){\r\n * background(0);\r\n * micLevel = mic.getLevel();\r\n * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);\r\n * }\r\n *
\r\n */\r\n p5.AudioIn = function(errorCallback) {\r\n // set up audio input\r\n /**\r\n * @property {GainNode} input\r\n */\r\n this.input = p5sound.audiocontext.createGain();\r\n /**\r\n * @property {GainNode} output\r\n */\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n /**\r\n * @property {MediaStream|null} stream\r\n */\r\n this.stream = null;\r\n /**\r\n * @property {MediaStreamAudioSourceNode|null} mediaStream\r\n */\r\n this.mediaStream = null;\r\n /**\r\n * @property {Number|null} currentSource\r\n */\r\n this.currentSource = null;\r\n\r\n /**\r\n * Client must allow browser to access their microphone / audioin source.\r\n * Default: false. Will become true when the client enables acces.\r\n *\r\n * @property {Boolean} enabled\r\n */\r\n this.enabled = false;\r\n\r\n /**\r\n * Input amplitude, connect to it by default but not to master out\r\n *\r\n * @property {p5.Amplitude} amplitude\r\n */\r\n this.amplitude = new p5.Amplitude();\r\n this.output.connect(this.amplitude.input);\r\n\r\n if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) {\r\n errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices');\r\n }\r\n\r\n // add to soundArray so we can dispose on close\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start processing audio input. This enables the use of other\r\n * AudioIn methods like getLevel(). Note that by default, AudioIn\r\n * is not connected to p5.sound's output. So you won't hear\r\n * anything unless you use the connect() method. \r\n *\r\n * Certain browsers limit access to the user's microphone. For example,\r\n * Chrome only allows access from localhost and over https. For this reason,\r\n * you may want to include an errorCallback—a function that is called in case\r\n * the browser won't provide mic access.\r\n *\r\n * @method start\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] Name of a function to call on\r\n * success.\r\n * @param {Function} [errorCallback] Name of a function to call if\r\n * there was an error. For example,\r\n * some browsers do not support\r\n * getUserMedia.\r\n */\r\n p5.AudioIn.prototype.start = function(successCallback, errorCallback) {\r\n var self = this;\r\n\r\n if (this.stream) {\r\n this.stop();\r\n }\r\n\r\n // set the audio source\r\n var audioSource = p5sound.inputSources[self.currentSource];\r\n var constraints = {\r\n audio: {\r\n sampleRate: p5sound.audiocontext.sampleRate,\r\n echoCancellation: false\r\n }\r\n };\r\n\r\n // if developers determine which source to use\r\n if (p5sound.inputSources[this.currentSource]) {\r\n constraints.audio.deviceId = audioSource.deviceId;\r\n }\r\n\r\n window.navigator.mediaDevices.getUserMedia( constraints )\r\n .then( function(stream) {\r\n self.stream = stream;\r\n self.enabled = true;\r\n // Wrap a MediaStreamSourceNode around the live input\r\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\r\n self.mediaStream.connect(self.output);\r\n // only send to the Amplitude reader, so we can see it but not hear it.\r\n self.amplitude.setInput(self.output);\r\n if (successCallback) successCallback();\r\n })\r\n .catch( function(err) {\r\n if (errorCallback) errorCallback(err);\r\n else console.error(err);\r\n });\r\n };\r\n\r\n /**\r\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\r\n * If re-starting, the user may be prompted for permission access.\r\n *\r\n * @method stop\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.stop = function() {\r\n if (this.stream) {\r\n this.stream.getTracks().forEach(function(track) {\r\n track.stop();\r\n });\r\n\r\n this.mediaStream.disconnect();\r\n\r\n delete this.mediaStream;\r\n delete this.stream;\r\n }\r\n };\r\n\r\n /**\r\n * Connect to an audio unit. If no parameter is provided, will\r\n * connect to the master output (i.e. your speakers). \r\n *\r\n * @method connect\r\n * @for p5.AudioIn\r\n * @param {Object} [unit] An object that accepts audio input,\r\n * such as an FFT\r\n */\r\n p5.AudioIn.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n }\r\n else if (unit.hasOwnProperty('analyser')) {\r\n this.output.connect(unit.analyser);\r\n }\r\n else {\r\n this.output.connect(unit);\r\n }\r\n }\r\n else {\r\n this.output.connect(p5sound.input);\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect the AudioIn from all audio units. For example, if\r\n * connect() had been called, disconnect() will stop sending\r\n * signal to your speakers. \r\n *\r\n * @method disconnect\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n // stay connected to amplitude even if not outputting to p5\r\n this.output.connect(this.amplitude.input);\r\n }\r\n };\r\n\r\n /**\r\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\r\n * class contains its own instance of the Amplitude class to help\r\n * make it easy to get a microphone's volume level. Accepts an\r\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\r\n * .start() before using .getLevel(). \r\n *\r\n * @method getLevel\r\n * @for p5.AudioIn\r\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\r\n * Smooths values based on previous values.\r\n * @return {Number} Volume level (between 0.0 and 1.0)\r\n */\r\n p5.AudioIn.prototype.getLevel = function(smoothing) {\r\n if (smoothing) {\r\n this.amplitude.smoothing = smoothing;\r\n }\r\n return this.amplitude.getLevel();\r\n };\r\n\r\n /**\r\n * Set amplitude (volume) of a mic input between 0 and 1.0. \r\n *\r\n * @method amp\r\n * @for p5.AudioIn\r\n * @param {Number} vol between 0 and 1.0\r\n * @param {Number} [time] ramp time (optional)\r\n */\r\n p5.AudioIn.prototype.amp = function(vol, t) {\r\n if (t) {\r\n var rampTime = t || 0;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime);\r\n this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime);\r\n } else {\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Returns a list of available input sources. This is a wrapper\r\n * for and it returns a Promise.\r\n *\r\n * @method getSources\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] This callback function handles the sources when they\r\n * have been enumerated. The callback function\r\n * receives the deviceList array as its only argument\r\n * @param {Function} [errorCallback] This optional callback receives the error\r\n * message as its argument.\r\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\r\n * to the enumerateDevices() method\r\n * @example\r\n *
\r\n */\r\n p5.AudioIn.prototype.getSources = function (onSuccess, onError) {\r\n return new Promise( function(resolve, reject) {\r\n window.navigator.mediaDevices.enumerateDevices()\r\n .then( function(devices) {\r\n p5sound.inputSources = devices.filter(function(device) {\r\n return device.kind === 'audioinput';\r\n });\r\n resolve(p5sound.inputSources);\r\n if (onSuccess) {\r\n onSuccess(p5sound.inputSources);\r\n }\r\n })\r\n .catch( function(error) {\r\n reject(error);\r\n if (onError) {\r\n onError(error);\r\n } else {\r\n console.error('This browser does not support MediaStreamTrack.getSources()');\r\n }\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Set the input source. Accepts a number representing a\r\n * position in the array returned by getSources().\r\n * This is only available in browsers that support\r\n * navigator.mediaDevices.enumerateDevices(). \r\n *\r\n * @method setSource\r\n * @for p5.AudioIn\r\n * @param {number} num position of input source in the array\r\n */\r\n p5.AudioIn.prototype.setSource = function(num) {\r\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\r\n // set the current source\r\n this.currentSource = num;\r\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\r\n } else {\r\n console.log('unable to set input source');\r\n }\r\n\r\n // restart stream if currently active\r\n if (this.stream && this.stream.active) {\r\n this.start();\r\n }\r\n };\r\n\r\n // private method\r\n p5.AudioIn.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop();\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.amplitude) {\r\n this.amplitude.disconnect();\r\n }\r\n delete this.amplitude;\r\n delete this.output;\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Expr\", \n\t\"Tone/signal/EqualPowerGain\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Crossfade provides equal power fading between two inputs. \n\t * More on crossfading technique [here](https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Crossfading).\n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t * @param {NormalRange} [initialFade=0.5]\n\t * @example\n\t * var crossFade = new Tone.CrossFade(0.5);\n\t * //connect effect A to crossfade from\n\t * //effect output 0 to crossfade input 0\n\t * effectA.connect(crossFade, 0, 0);\n\t * //connect effect B to crossfade from\n\t * //effect output 0 to crossfade input 1\n\t * effectB.connect(crossFade, 0, 1);\n\t * crossFade.fade.value = 0;\n\t * // ^ only effectA is output\n\t * crossFade.fade.value = 1;\n\t * // ^ only effectB is output\n\t * crossFade.fade.value = 0.5;\n\t * // ^ the two signals are mixed equally. \n\t */\t\t\n\tTone.CrossFade = function(initialFade){\n\n\t\tthis.createInsOuts(2, 1);\n\n\t\t/**\n\t\t * Alias for input[0]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.a = this.input[0] = new Tone.Gain();\n\n\t\t/**\n\t\t * Alias for input[1]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.b = this.input[1] = new Tone.Gain();\n\n\t\t/**\n\t\t * \tThe mix between the two inputs. A fade value of 0\n\t\t * \twill output 100% input[0] and \n\t\t * \ta value of 1 will output 100% input[1]. \n\t\t * @type {NormalRange}\n\t\t * @signal\n\t\t */\n\t\tthis.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerA = new Tone.EqualPowerGain();\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerB = new Tone.EqualPowerGain();\n\t\t\n\t\t/**\n\t\t * invert the incoming signal\n\t\t * @private\n\t\t * @type {Tone}\n\t\t */\n\t\tthis._invert = new Tone.Expr(\"1 - $0\");\n\n\t\t//connections\n\t\tthis.a.connect(this.output);\n\t\tthis.b.connect(this.output);\n\t\tthis.fade.chain(this._equalPowerB, this.b.gain);\n\t\tthis.fade.chain(this._invert, this._equalPowerA, this.a.gain);\n\t\tthis._readOnly(\"fade\");\n\t};\n\n\tTone.extend(Tone.CrossFade);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.CrossFade} this\n\t */\n\tTone.CrossFade.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._writable(\"fade\");\n\t\tthis._equalPowerA.dispose();\n\t\tthis._equalPowerA = null;\n\t\tthis._equalPowerB.dispose();\n\t\tthis._equalPowerB = null;\n\t\tthis.fade.dispose();\n\t\tthis.fade = null;\n\t\tthis._invert.dispose();\n\t\tthis._invert = null;\n\t\tthis.a.dispose();\n\t\tthis.a = null;\n\t\tthis.b.dispose();\n\t\tthis.b = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.CrossFade;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Subtract\", \"Tone/signal/Multiply\", \n\t\"Tone/signal/GreaterThan\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Abs\", \"Tone/signal/Negate\", \n\t\"Tone/signal/Modulo\", \"Tone/signal/Pow\", \"Tone/signal/AudioToGain\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Evaluate an expression at audio rate.
\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {string} expr the expression to generate\n\t * @example\n\t * //adds the signals from input[0] and input[1].\n\t * var expr = new Tone.Expr(\"$0 + $1\");\n\t */\n\tTone.Expr = function(){\n\n\t\tvar expr = this._replacements(Array.prototype.slice.call(arguments));\n\t\tvar inputCount = this._parseInputs(expr);\n\n\t\t/**\n\t\t * hold onto all of the nodes for disposal\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._nodes = [];\n\n\t\t/**\n\t\t * The inputs. The length is determined by the expression. \n\t\t * @type {Array}\n\t\t */\n\t\tthis.input = new Array(inputCount);\n\n\t\t//create a gain for each input\n\t\tfor (var i = 0; i < inputCount; i++){\n\t\t\tthis.input[i] = this.context.createGain();\n\t\t}\n\n\t\t//parse the syntax tree\n\t\tvar tree = this._parseTree(expr);\n\t\t//evaluate the results\n\t\tvar result;\n\t\ttry {\n\t\t\tresult = this._eval(tree);\n\t\t} catch (e){\n\t\t\tthis._disposeNodes();\n\t\t\tthrow new Error(\"Tone.Expr: Could evaluate expression: \"+expr);\n\t\t}\n\n\t\t/**\n\t\t * The output node is the result of the expression\n\t\t * @type {Tone}\n\t\t */\n\t\tthis.output = result;\n\t};\n\n\tTone.extend(Tone.Expr, Tone.SignalBase);\n\n\t//some helpers to cut down the amount of code\n\tfunction applyBinary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\tself._eval(args[1]).connect(op, 0, 1);\n\t\treturn op;\n\t}\n\tfunction applyUnary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\treturn op;\n\t}\n\tfunction getNumber(arg){\n\t\treturn arg ? parseFloat(arg) : undefined;\n\t}\n\tfunction literalNumber(arg){\n\t\treturn arg && arg.args ? parseFloat(arg.args) : undefined;\n\t}\n\n\t/*\n\t * the Expressions that Tone.Expr can parse.\n\t *\n\t * each expression belongs to a group and contains a regexp \n\t * for selecting the operator as well as that operators method\n\t * \n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Expr._Expressions = {\n\t\t//values\n\t\t\"value\" : {\n\t\t\t\"signal\" : {\n\t\t\t\tregexp : /^\\d+\\.\\d+|^\\d+/,\n\t\t\t\tmethod : function(arg){\n\t\t\t\t\tvar sig = new Tone.Signal(getNumber(arg));\n\t\t\t\t\treturn sig;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"input\" : {\n\t\t\t\tregexp : /^\\$\\d/,\n\t\t\t\tmethod : function(arg, self){\n\t\t\t\t\treturn self.input[getNumber(arg.substr(1))];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t//syntactic glue\n\t\t\"glue\" : {\n\t\t\t\"(\" : {\n\t\t\t\tregexp : /^\\(/,\n\t\t\t},\n\t\t\t\")\" : {\n\t\t\t\tregexp : /^\\)/,\n\t\t\t},\n\t\t\t\",\" : {\n\t\t\t\tregexp : /^,/,\n\t\t\t}\n\t\t},\n\t\t//functions\n\t\t\"func\" : {\n\t\t\t\"abs\" : {\n\t\t\t\tregexp : /^abs/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Abs)\n\t\t\t},\n\t\t\t\"mod\" : {\n\t\t\t\tregexp : /^mod/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar modulus = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Modulo(modulus);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"pow\" : {\n\t\t\t\tregexp : /^pow/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar exp = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Pow(exp);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"a2g\" : {\n\t\t\t\tregexp : /^a2g/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar op = new Tone.AudioToGain();\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t//binary expressions\n\t\t\"binary\" : {\n\t\t\t\"+\" : {\n\t\t\t\tregexp : /^\\+/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Add)\n\t\t\t},\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\t//both unary and binary op\n\t\t\t\t\tif (args.length === 1){\n\t\t\t\t\t\treturn applyUnary(Tone.Negate, args, self);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn applyBinary(Tone.Subtract, args, self);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"*\" : {\n\t\t\t\tregexp : /^\\*/,\n\t\t\t\tprecedence : 0,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Multiply)\n\t\t\t}\n\t\t},\n\t\t//unary expressions\n\t\t\"unary\" : {\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Negate)\n\t\t\t},\n\t\t\t\"!\" : {\n\t\t\t\tregexp : /^\\!/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.NOT)\n\t\t\t},\n\t\t},\n\t};\n\t\t\n\t/**\n\t * @param {string} expr the expression string\n\t * @return {number} the input count\n\t * @private\n\t */\n\tTone.Expr.prototype._parseInputs = function(expr){\n\t\tvar inputArray = expr.match(/\\$\\d/g);\n\t\tvar inputMax = 0;\n\t\tif (inputArray !== null){\n\t\t\tfor (var i = 0; i < inputArray.length; i++){\n\t\t\t\tvar inputNum = parseInt(inputArray[i].substr(1)) + 1;\n\t\t\t\tinputMax = Math.max(inputMax, inputNum);\n\t\t\t}\n\t\t}\n\t\treturn inputMax;\n\t};\n\n\t/**\n\t * @param {Array} args \tan array of arguments\n\t * @return {string} the results of the replacements being replaced\n\t * @private\n\t */\n\tTone.Expr.prototype._replacements = function(args){\n\t\tvar expr = args.shift();\n\t\tfor (var i = 0; i < args.length; i++){\n\t\t\texpr = expr.replace(/\\%/i, args[i]);\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.Expr.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr){\n\t\t\tfor (var type in Tone.Expr._Expressions){\n\t\t\t\tvar group = Tone.Expr._Expressions[type];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype : type,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t\tmethod : op.method\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * recursively parse the string expression into a syntax tree\n\t * \n\t * @param {string} expr \n\t * @return {Object}\n\t * @private\n\t */\n\tTone.Expr.prototype._parseTree = function(expr){\n\t\tvar lexer = this._tokenize(expr);\n\t\tvar isUndef = this.isUndef.bind(this);\n\n\t\tfunction matchSyntax(token, syn) {\n\t\t\treturn !isUndef(token) && \n\t\t\t\ttoken.type === \"glue\" &&\n\t\t\t\ttoken.value === syn;\n\t\t}\n\n\t\tfunction matchGroup(token, groupName, prec) {\n\t\t\tvar ret = false;\n\t\t\tvar group = Tone.Expr._Expressions[groupName];\n\t\t\tif (!isUndef(token)){\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\t\tif (!isUndef(prec)){\n\t\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\n\t\tfunction parseExpression(precedence) {\n\t\t\tif (isUndef(precedence)){\n\t\t\t\tprecedence = 5;\n\t\t\t}\n\t\t\tvar expr;\n\t\t\tif (precedence < 0){\n\t\t\t\texpr = parseUnary();\n\t\t\t} else {\n\t\t\t\texpr = parseExpression(precedence-1);\n\t\t\t}\n\t\t\tvar token = lexer.peek();\n\t\t\twhile (matchGroup(token, \"binary\", precedence)) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [\n\t\t\t\t\t\texpr,\n\t\t\t\t\t\tparseExpression(precedence-1)\n\t\t\t\t\t]\n\t\t\t\t};\n\t\t\t\ttoken = lexer.peek();\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\n\t\tfunction parseUnary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (matchGroup(token, \"unary\")) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = parseUnary();\n\t\t\t\treturn {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [expr]\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn parsePrimary();\n\t\t}\n\n\t\tfunction parsePrimary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (isUndef(token)) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected termination of expression\");\n\t\t\t}\n\t\t\tif (token.type === \"func\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn parseFunctionCall(token);\n\t\t\t}\n\t\t\tif (token.type === \"value\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn {\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : token.value\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (matchSyntax(token, \"(\")) {\n\t\t\t\tlexer.next();\n\t\t\t\texpr = parseExpression();\n\t\t\t\ttoken = lexer.next();\n\t\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t\t}\n\t\t\t\treturn expr;\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Parse error, cannot process token \" + token.value);\n\t\t}\n\n\t\tfunction parseFunctionCall(func) {\n\t\t\tvar token, args = [];\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \"(\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ( in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\ttoken = lexer.peek();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\targs = parseArgumentList();\n\t\t\t}\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ) in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod : func.method,\n\t\t\t\targs : args,\n\t\t\t\tname : name\n\t\t\t};\n\t\t}\n\n\t\tfunction parseArgumentList() {\n\t\t\tvar token, expr, args = [];\n\t\t\twhile (true) {\n\t\t\t\texpr = parseExpression();\n\t\t\t\tif (isUndef(expr)) {\n\t\t\t\t\t// TODO maybe throw exception?\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\targs.push(expr);\n\t\t\t\ttoken = lexer.peek();\n\t\t\t\tif (!matchSyntax(token, \",\")) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlexer.next();\n\t\t\t}\n\t\t\treturn args;\n\t\t}\n\n\t\treturn parseExpression();\n\t};\n\n\t/**\n\t * recursively evaluate the expression tree\n\t * @param {Object} tree \n\t * @return {AudioNode} the resulting audio node from the expression\n\t * @private\n\t */\n\tTone.Expr.prototype._eval = function(tree){\n\t\tif (!this.isUndef(tree)){\n\t\t\tvar node = tree.method(tree.args, this);\n\t\t\tthis._nodes.push(node);\n\t\t\treturn node;\n\t\t} \n\t};\n\n\t/**\n\t * dispose all the nodes\n\t * @private\n\t */\n\tTone.Expr.prototype._disposeNodes = function(){\n\t\tfor (var i = 0; i < this._nodes.length; i++){\n\t\t\tvar node = this._nodes[i];\n\t\t\tif (this.isFunction(node.dispose)) {\n\t\t\t\tnode.dispose();\n\t\t\t} else if (this.isFunction(node.disconnect)) {\n\t\t\t\tnode.disconnect();\n\t\t\t}\n\t\t\tnode = null;\n\t\t\tthis._nodes[i] = null;\n\t\t}\n\t\tthis._nodes = null;\n\t};\n\n\t/**\n\t * clean up\n\t */\n\tTone.Expr.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._disposeNodes();\n\t};\n\n\treturn Tone.Expr;\n});","define([\"Tone/core/Tone\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Subtract\", \"Tone/signal/Signal\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Output 1 if the signal is greater than the value, otherwise outputs 0.\n\t * can compare two signals or a signal and a number. \n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number} [value=0] the value to compare to the incoming signal\n\t * @example\n\t * var gt = new Tone.GreaterThan(2);\n\t * var sig = new Tone.Signal(4).connect(gt);\n\t * //output of gt is equal 1. \n\t */\n\tTone.GreaterThan = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\t\t\n\t\t/**\n\t\t * subtract the amount from the incoming signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[0] = new Tone.Subtract(value);\n\t\tthis.input[1] = this._param.input[1];\n\n\t\t/**\n\t\t * compare that amount to zero\n\t\t * @type {Tone.GreaterThanZero}\n\t\t * @private\n\t\t */\n\t\tthis._gtz = this.output = new Tone.GreaterThanZero();\n\n\t\t//connect\n\t\tthis._param.connect(this._gtz);\n\t};\n\n\tTone.extend(Tone.GreaterThan, Tone.Signal);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThan} this\n\t */\n\tTone.GreaterThan.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\tthis._gtz.dispose();\n\t\tthis._gtz = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThan;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/SignalBase\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Return the absolute value of an incoming signal. \n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var signal = new Tone.Signal(-1);\n\t * var abs = new Tone.Abs();\n\t * signal.connect(abs);\n\t * //the output of abs is 1. \n\t */\n\tTone.Abs = function(){\n\t\t/**\n\t\t * @type {Tone.LessThan}\n\t\t * @private\n\t\t */\n\t\tthis._abs = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val === 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn Math.abs(val);\n\t\t\t}\n\t\t}, 127);\n\t};\n\n\tTone.extend(Tone.Abs, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.Abs} this\n\t */\n\tTone.Abs.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._abs.dispose();\n\t\tthis._abs = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Abs;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Multiply\", \"Tone/signal/Subtract\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Signal-rate modulo operator. Only works in AudioRange [-1, 1] and for modulus\n\t * values in the NormalRange. \n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {NormalRange} modulus The modulus to apply.\n\t * @example\n\t * var mod = new Tone.Modulo(0.2)\n\t * var sig = new Tone.Signal(0.5).connect(mod);\n\t * //mod outputs 0.1\n\t */\n\tTone.Modulo = function(modulus){\n\n\t\tthis.createInsOuts(1, 0);\n\n\t\t/**\n\t\t * A waveshaper gets the integer multiple of \n\t\t * the input signal and the modulus.\n\t\t * @private\n\t\t * @type {Tone.WaveShaper}\n\t\t */\n\t\tthis._shaper = new Tone.WaveShaper(Math.pow(2, 16));\n\n\t\t/**\n\t\t * the integer multiple is multiplied by the modulus\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = new Tone.Multiply();\n\n\t\t/**\n\t\t * and subtracted from the input signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._subtract = this.output = new Tone.Subtract();\n\n\t\t/**\n\t\t * the modulus signal\n\t\t * @type {Tone.Signal}\n\t\t * @private\n\t\t */\n\t\tthis._modSignal = new Tone.Signal(modulus);\n\n\t\t//connections\n\t\tthis.input.fan(this._shaper, this._subtract);\n\t\tthis._modSignal.connect(this._multiply, 0, 0);\n\t\tthis._shaper.connect(this._multiply, 0, 1);\n\t\tthis._multiply.connect(this._subtract, 0, 1);\n\t\tthis._setWaveShaper(modulus);\n\t};\n\n\tTone.extend(Tone.Modulo, Tone.SignalBase);\n\n\t/**\n\t * @param {number} mod the modulus to apply\n\t * @private\n\t */\n\tTone.Modulo.prototype._setWaveShaper = function(mod){\n\t\tthis._shaper.setMap(function(val){\n\t\t\tvar multiple = Math.floor((val + 0.0001) / mod);\n\t\t\treturn multiple;\n\t\t});\n\t};\n\n\t/**\n\t * The modulus value.\n\t * @memberOf Tone.Modulo#\n\t * @type {NormalRange}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Modulo.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._modSignal.value;\n\t\t},\n\t\tset : function(mod){\n\t\t\tthis._modSignal.value = mod;\n\t\t\tthis._setWaveShaper(mod);\n\t\t}\n\t});\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Modulo} this\n\t */\n\tTone.Modulo.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.dispose();\n\t\tthis._shaper = null;\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\tthis._subtract.dispose();\n\t\tthis._subtract = null;\n\t\tthis._modSignal.dispose();\n\t\tthis._modSignal = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Modulo;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Pow applies an exponent to the incoming signal. The incoming signal\n\t * must be AudioRange.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {Positive} exp The exponent to apply to the incoming signal, must be at least 2. \n\t * @example\n\t * var pow = new Tone.Pow(2);\n\t * var sig = new Tone.Signal(0.5).connect(pow);\n\t * //output of pow is 0.25. \n\t */\n\tTone.Pow = function(exp){\n\n\t\t/**\n\t\t * the exponent\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._exp = this.defaultArg(exp, 1);\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);\n\t};\n\n\tTone.extend(Tone.Pow, Tone.SignalBase);\n\n\t/**\n\t * The value of the exponent.\n\t * @memberOf Tone.Pow#\n\t * @type {number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Pow.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._exp;\n\t\t},\n\t\tset : function(exp){\n\t\t\tthis._exp = exp;\n\t\t\tthis._expScaler.setMap(this._expFunc(this._exp));\n\t\t}\n\t});\n\n\n\t/**\n\t * the function which maps the waveshaper\n\t * @param {number} exp\n\t * @return {function}\n\t * @private\n\t */\n\tTone.Pow.prototype._expFunc = function(exp){\n\t\treturn function(val){\n\t\t\treturn Math.pow(Math.abs(val), exp);\n\t\t};\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Pow} this\n\t */\n\tTone.Pow.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._expScaler.dispose();\n\t\tthis._expScaler = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Pow;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class AudioToGain converts an input in AudioRange [-1,1] to NormalRange [0,1]. \n\t * See Tone.GainToAudio.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var a2g = new Tone.AudioToGain();\n\t */\n\tTone.AudioToGain = function(){\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._norm = this.input = this.output = new Tone.WaveShaper(function(x){\n\t\t\treturn (x + 1) / 2;\n\t\t});\n\t};\n\n\tTone.extend(Tone.AudioToGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.AudioToGain} this\n\t */\n\tTone.AudioToGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._norm.dispose();\n\t\tthis._norm = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.AudioToGain;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Convert an incoming signal between 0, 1 to an equal power gain scale.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var eqPowGain = new Tone.EqualPowerGain();\n\t */\n\tTone.EqualPowerGain = function(){\n\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._eqPower = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (Math.abs(val) < 0.001){\n\t\t\t\t//should output 0 when input is 0\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn this.equalPowerScale(val);\n\t\t\t}\n\t\t}.bind(this), 4096);\n\t};\n\n\tTone.extend(Tone.EqualPowerGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.EqualPowerGain} this\n\t */\n\tTone.EqualPowerGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._eqPower.dispose();\n\t\tthis._eqPower = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.EqualPowerGain;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n var EQFilter = require('eqFilter');\r\n\r\n /**\r\n * p5.EQ is an audio effect that performs the function of a multiband\r\n * audio equalizer. Equalization is used to adjust the balance of\r\n * frequency compoenents of an audio signal. This process is commonly used\r\n * in sound production and recording to change the waveform before it reaches\r\n * a sound output device. EQ can also be used as an audio effect to create\r\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\r\n * built using a chain of Web Audio Biquad Filter Nodes and can be\r\n * instantiated with 3 or 8 bands. Bands can be added or removed from\r\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.EQ\r\n * @constructor\r\n * @extends p5.Effect\r\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\r\n * @return {Object} p5.EQ object\r\n *\r\n * @example\r\n *
\r\n * var eq;\r\n * var band_names;\r\n * var band_index;\r\n *\r\n * var soundFile, play;\r\n *\r\n * function preload() {\r\n * soundFormats('mp3', 'ogg');\r\n * soundFile = loadSound('assets/beat');\r\n * }\r\n *\r\n * function setup() {\r\n * eq = new p5.EQ(3);\r\n * soundFile.disconnect();\r\n * eq.process(soundFile);\r\n *\r\n * band_names = ['lows','mids','highs'];\r\n * band_index = 0;\r\n * play = false;\r\n * textAlign(CENTER);\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n * noStroke();\r\n * fill(255);\r\n * text('click to kill',50,25);\r\n *\r\n * fill(255, 40, 255);\r\n * textSize(26);\r\n * text(band_names[band_index],50,55);\r\n *\r\n * fill(255);\r\n * textSize(9);\r\n * text('space = play/pause',50,80);\r\n * }\r\n *\r\n * //If mouse is over canvas, cycle to the next band and kill the frequency\r\n * function mouseClicked() {\r\n * for (var i = 0; i < eq.bands.length; i++) {\r\n * eq.bands[i].gain(0);\r\n * }\r\n * eq.bands[band_index].gain(-40);\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * band_index === 2 ? band_index = 0 : band_index++;\r\n * }\r\n * }\r\n *\r\n * //use space bar to trigger play / pause\r\n * function keyPressed() {\r\n * if (key===' ') {\r\n * play = !play\r\n * play ? soundFile.loop() : soundFile.pause();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.EQ = function(_eqsize) {\r\n Effect.call(this);\r\n\r\n //p5.EQ can be of size (3) or (8), defaults to 3\r\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\r\n\r\n var factor;\r\n _eqsize === 3 ? factor = Math.pow(2,3) : factor = 2;\r\n\r\n /**\r\n * The p5.EQ is built with abstracted p5.Filter objects.\r\n * To modify any bands, use methods of the \r\n * p5.Filter API, especially `gain` and `freq`.\r\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\r\n * @property {Array} bands\r\n *\r\n */\r\n this.bands = [];\r\n\r\n\r\n var freq, res;\r\n for (var i = 0; i < _eqsize; i++) {\r\n if (i === _eqsize - 1) {\r\n freq = 21000;\r\n res = .01;\r\n } else if (i === 0) {\r\n freq = 100;\r\n res = .1;\r\n }\r\n else if (i===1) {\r\n freq = _eqsize === 3 ? 360 * factor : 360;\r\n res = 1;\r\n }else {\r\n freq = this.bands[i-1].freq() * factor;\r\n res = 1;\r\n }\r\n this.bands[i] = this._newBand(freq, res);\r\n\r\n if (i>0) {\r\n this.bands[i-1].connect(this.bands[i].biquad);\r\n } else {\r\n this.input.connect(this.bands[i].biquad);\r\n }\r\n }\r\n this.bands[_eqsize-1].connect(this.output);\r\n };\r\n p5.EQ.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Process an input by connecting it to the EQ\r\n * @method process\r\n * @param {Object} src Audio source\r\n */\r\n p5.EQ.prototype.process = function (src) {\r\n src.connect(this.input);\r\n };\r\n\r\n // /**\r\n // * Set the frequency and gain of each band in the EQ. This method should be\r\n // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\r\n // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\r\n // *\r\n // * @method set\r\n // * @for p5.EQ\r\n // * @param {Number} [freq0] Frequency value for band with index 0\r\n // * @param {Number} [gain0] Gain value for band with index 0\r\n // * @param {Number} [freq1] Frequency value for band with index 1\r\n // * @param {Number} [gain1] Gain value for band with index 1\r\n // * @param {Number} [freq2] Frequency value for band with index 2\r\n // * @param {Number} [gain2] Gain value for band with index 2\r\n // * @param {Number} [freq3] Frequency value for band with index 3\r\n // * @param {Number} [gain3] Gain value for band with index 3\r\n // * @param {Number} [freq4] Frequency value for band with index 4\r\n // * @param {Number} [gain4] Gain value for band with index 4\r\n // * @param {Number} [freq5] Frequency value for band with index 5\r\n // * @param {Number} [gain5] Gain value for band with index 5\r\n // * @param {Number} [freq6] Frequency value for band with index 6\r\n // * @param {Number} [gain6] Gain value for band with index 6\r\n // * @param {Number} [freq7] Frequency value for band with index 7\r\n // * @param {Number} [gain7] Gain value for band with index 7\r\n // */\r\n p5.EQ.prototype.set = function() {\r\n if (arguments.length === this.bands.length * 2) {\r\n for (var i = 0; i < arguments.length; i+=2) {\r\n this.bands[i/2].freq(arguments[i]);\r\n this.bands[i/2].gain(arguments[i+1]);\r\n }\r\n }\r\n else {\r\n console.error('Argument mismatch. .set() should be called with ' + this.bands.length*2 +\r\n ' arguments. (one frequency and gain value pair for each band of the eq)');\r\n }\r\n };\r\n\r\n /**\r\n * Add a new band. Creates a p5.Filter and strips away everything but\r\n * the raw biquad filter. This method returns an abstracted p5.Filter,\r\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\r\n * @private\r\n * @for p5.EQ\r\n * @method _newBand\r\n * @param {Number} freq\r\n * @param {Number} res\r\n * @return {Object} Abstracted Filter\r\n */\r\n p5.EQ.prototype._newBand = function(freq, res) {\r\n return new EQFilter(freq, res);\r\n };\r\n\r\n p5.EQ.prototype.dispose = function () {\r\n Effect.prototype.dispose.apply(this);\r\n\r\n if (this.bands) {\r\n while (this.bands.length > 0) {\r\n delete this.bands.pop().dispose();\r\n }\r\n delete this.bands;\r\n }\r\n };\r\n\r\n return p5.EQ;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var p5sound = require('master');\r\n\r\n /**\r\n * EQFilter extends p5.Filter with constraints\r\n * necessary for the p5.EQ\r\n *\r\n * @private\r\n */\r\n var EQFilter = function(freq, res) {\r\n Filter.call(this, 'peaking');\r\n this.disconnect();\r\n this.set(freq, res);\r\n this.biquad.gain.value = 0;\r\n delete this.input;\r\n delete this.output;\r\n delete this._drywet;\r\n delete this.wet;\r\n\r\n };\r\n EQFilter.prototype = Object.create(Filter.prototype);\r\n\r\n EQFilter.prototype.amp = function() {\r\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\r\n };\r\n EQFilter.prototype.drywet = function() {\r\n console.warn('`drywet()` is not available for p5.EQ bands.');\r\n };\r\n EQFilter.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n if (this.biquad) {\r\n this.biquad.connect(u.input ? u.input : u);\r\n } else {\r\n this.output.connect(u.input ? u.input : u);\r\n }\r\n };\r\n\r\n EQFilter.prototype.disconnect = function() {\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n }\r\n };\r\n EQFilter.prototype.dispose = function() {\r\n // remove reference form soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n this.disconnect();\r\n delete this.biquad;\r\n };\r\n\r\n return EQFilter;\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Panner3D is based on the \r\n * Web Audio Spatial Panner Node.\r\n * This panner is a spatial processing node that allows audio to be positioned\r\n * and oriented in 3D space.\r\n *\r\n * The position is relative to an \r\n * Audio Context Listener, which can be accessed\r\n * by p5.soundOut.audiocontext.listener\r\n *\r\n *\r\n * @class p5.Panner3D\r\n * @constructor\r\n */\r\n\tp5.Panner3D = function() {\r\n Effect.call(this);\r\n\r\n /**\r\n * \r\n * Web Audio Spatial Panner Node\r\n *\r\n * Properties include\r\n * - panningModel: \"equal power\" or \"HRTF\"\r\n * - distanceModel: \"linear\", \"inverse\", or \"exponential\"\r\n *\r\n * @property {AudioNode} panner\r\n *\r\n */\r\n this.panner = this.ac.createPanner();\r\n this.panner.panningModel = 'HRTF';\r\n this.panner.distanceModel = 'linear';\r\n this.panner.connect(this.output);\r\n this.input.connect(this.panner);\r\n\t};\r\n\r\n p5.Panner3D.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Connect an audio sorce\r\n *\r\n * @method process\r\n * @for p5.Panner3D\r\n * @param {Object} src Input source\r\n */\r\n p5.Panner3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method set\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.set = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.panner.positionX.value,\r\n this.panner.positionY.value,\r\n this.panner.positionZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.positionX.value = xVal;\r\n this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.positionX);\r\n }\r\n return this.panner.positionX.value;\r\n };\r\n p5.Panner3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.positionY.value = yVal;\r\n this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.positionY);\r\n }\r\n return this.panner.positionY.value;\r\n };\r\n p5.Panner3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.positionZ.value = zVal;\r\n this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.positionZ);\r\n }\r\n return this.panner.positionZ.value;\r\n };\r\n\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method orient\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.orient = function(xVal, yVal, zVal, time) {\r\n this.orientX(xVal,time);\r\n this.orientY(yVal,time);\r\n this.orientZ(zVal,time);\r\n return [this.panner.orientationX.value,\r\n this.panner.orientationY.value,\r\n this.panner.orientationZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.orientX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.orientationX.value = xVal;\r\n this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.orientationX);\r\n }\r\n return this.panner.orientationX.value;\r\n };\r\n p5.Panner3D.prototype.orientY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.orientationY.value = yVal;\r\n this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.orientationY);\r\n }\r\n return this.panner.orientationY.value;\r\n };\r\n p5.Panner3D.prototype.orientZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.orientationZ.value = zVal;\r\n this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.orientationZ);\r\n }\r\n return this.panner.orientationZ.value;\r\n };\r\n\r\n /**\r\n * Set the rolloff factor and max distance\r\n * @method setFalloff\r\n * @for p5.Panner3D\r\n * @param {Number} [maxDistance]\r\n * @param {Number} [rolloffFactor]\r\n */\r\n p5.Panner3D.prototype.setFalloff = function(maxDistance, rolloffFactor) {\r\n this.maxDist(maxDistance);\r\n this.rolloff(rolloffFactor);\r\n };\r\n /**\r\n * Maxium distance between the source and the listener\r\n * @method maxDist\r\n * @for p5.Panner3D\r\n * @param {Number} maxDistance\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.maxDist = function(maxDistance){\r\n if (typeof maxDistance === 'number') {\r\n this.panner.maxDistance = maxDistance;\r\n }\r\n return this.panner.maxDistance;\r\n };\r\n\r\n /**\r\n * How quickly the volume is reduced as the source moves away from the listener\r\n * @method rollof\r\n * @for p5.Panner3D\r\n * @param {Number} rolloffFactor\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.rolloff = function(rolloffFactor){\r\n if (typeof rolloffFactor === 'number') {\r\n this.panner.rolloffFactor = rolloffFactor;\r\n }\r\n return this.panner.rolloffFactor;\r\n };\r\n\r\n p5.Panner3D.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n delete this.panner;\r\n }\r\n };\r\n\r\n return p5.Panner3D;\r\n\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n// /**\r\n// * listener is a class that can construct both a Spatial Panner\r\n// * and a Spatial Listener. The panner is based on the \r\n// * Web Audio Spatial Panner Node\r\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\r\n// * This panner is a spatial processing node that allows audio to be positioned\r\n// * and oriented in 3D space. \r\n// *\r\n// * The Listener modifies the properties of the Audio Context Listener. \r\n// * Both objects types use the same methods. The default is a spatial panner.\r\n// *\r\n// * p5.Panner3D - Constructs a Spatial Panner \r\n// * p5.Listener3D - Constructs a Spatial Listener \r\n// *\r\n// * @class listener\r\n// * @constructor\r\n// * @return {Object} p5.Listener3D Object\r\n// *\r\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\r\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\r\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\r\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\r\n// */\r\n \r\n\tp5.Listener3D = function(type) {\r\n this.ac = p5sound.audiocontext;\r\n this.listener = this.ac.listener;\r\n\t}; \r\n\r\n// /**\r\n// * Connect an audio sorce\r\n// * @param {Object} src Input source\r\n// */\r\n p5.Listener3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n// /**\r\n// * Set the X,Y,Z position of the Panner\r\n// * @param {[Number]} xVal\r\n// * @param {[Number]} yVal\r\n// * @param {[Number]} zVal\r\n// * @param {[Number]} time\r\n// * @return {[Array]} [Updated x, y, z values as an array]\r\n// */\r\n p5.Listener3D.prototype.position = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.listener.positionX.value, \r\n this.listener.positionY.value,\r\n this.listener.positionZ.value];\r\n };\r\n\r\n// /**\r\n// * Getter and setter methods for position coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.positionX.value = xVal;\r\n this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.positionX);\r\n }\r\n return this.listener.positionX.value;\r\n };\r\n p5.Listener3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.positionY.value = yVal;\r\n this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.positionY);\r\n }\r\n return this.listener.positionY.value;\r\n };\r\n p5.Listener3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.positionZ.value = zVal;\r\n this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.positionZ);\r\n }\r\n return this.listener.positionZ.value;\r\n };\r\n\r\n// cannot define method when class definition is commented\r\n// /**\r\n// * Overrides the listener orient() method because Listener has slightly\r\n// * different params. In human terms, Forward vectors are the direction the \r\n// * nose is pointing. Up vectors are the direction of the top of the head.\r\n// *\r\n// * @method orient\r\n// * @param {Number} xValF Forward vector X direction\r\n// * @param {Number} yValF Forward vector Y direction\r\n// * @param {Number} zValF Forward vector Z direction\r\n// * @param {Number} xValU Up vector X direction\r\n// * @param {Number} yValU Up vector Y direction\r\n// * @param {Number} zValU Up vector Z direction\r\n// * @param {Number} time \r\n// * @return {Array} All orienation params\r\n// */\r\n p5.Listener3D.prototype.orient = function(xValF, yValF, zValF, \r\n xValU, yValU, zValU, time) {\r\n\r\n if (arguments.length === 3 || arguments.length === 4) {\r\n time = arguments[3];\r\n this.orientForward(xValF, yValF, zValF, time);\r\n } else if (arguments.length === 6 || arguments === 7) {\r\n this.orientForward(xValF, yValF, zValF);\r\n this.orientUp(xValU, yValU, zValU, time);\r\n }\r\n \r\n return [this.listener.forwardX.value, \r\n this.listener.forwardY.value,\r\n this.listener.forwardZ.value,\r\n this.listener.upX.value,\r\n this.listener.upY.value,\r\n this.listener.upZ.value];\r\n };\r\n\r\n\r\n p5.Listener3D.prototype.orientForward = function(xValF, yValF, zValF, time) {\r\n this.forwardX(xValF,time);\r\n this.forwardY(yValF,time);\r\n this.forwardZ(zValF,time);\r\n\r\n return [this.listener.forwardX, \r\n this.listener.forwardY,\r\n this.listener.forwardZ];\r\n };\r\n\r\n p5.Listener3D.prototype.orientUp = function(xValU, yValU, zValU, time) {\r\n this.upX(xValU,time);\r\n this.upY(yValU,time);\r\n this.upZ(zValU,time);\r\n\r\n return [this.listener.upX, \r\n this.listener.upY,\r\n this.listener.upZ];\r\n };\r\n// /**\r\n// * Getter and setter methods for orient coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.forwardX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.forwardX.value = xVal;\r\n this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.forwardX);\r\n }\r\n return this.listener.forwardX.value;\r\n };\r\n p5.Listener3D.prototype.forwardY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.forwardY.value = yVal;\r\n this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.forwardY);\r\n }\r\n return this.listener.forwardY.value;\r\n };\r\n p5.Listener3D.prototype.forwardZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.forwardZ.value = zVal;\r\n this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.forwardZ);\r\n }\r\n return this.listener.forwardZ.value;\r\n };\r\n p5.Listener3D.prototype.upX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.upX.value = xVal;\r\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.upX);\r\n }\r\n return this.listener.upX.value;\r\n };\r\n p5.Listener3D.prototype.upY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.upY.value = yVal;\r\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.upY);\r\n }\r\n return this.listener.upY.value;\r\n };\r\n p5.Listener3D.prototype.upZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.upZ.value = zVal;\r\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.upZ);\r\n }\r\n return this.listener.upZ.value;\r\n };\r\n \r\n return p5.Listener3D;\r\n\r\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Delay is an echo effect. It processes an existing sound source,\r\n * and outputs a delayed version of that sound. The p5.Delay can\r\n * produce different effects depending on the delayTime, feedback,\r\n * filter, and type. In the example below, a feedback of 0.5 (the\r\n * defaul value) will produce a looping delay that decreases in\r\n * volume by 50% each repeat. A filter will cut out the high\r\n * frequencies so that the delay does not sound as piercing as the\r\n * original source.\r\n *\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n * @class p5.Delay\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var noise, env, delay;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * noise = new p5.Noise('brown');\r\n * noise.amp(0);\r\n * noise.start();\r\n *\r\n * delay = new p5.Delay();\r\n *\r\n * // delay.process() accepts 4 parameters:\r\n * // source, delayTime, feedback, filter frequency\r\n * // play with these numbers!!\r\n * delay.process(noise, .12, .7, 2300);\r\n *\r\n * // play the noise with an envelope,\r\n * // a series of fades ( time / value pairs )\r\n * env = new p5.Envelope(.01, 0.2, .2, .1);\r\n * }\r\n *\r\n * // mouseClick triggers envelope\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(noise);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Delay = function() {\r\n \tEffect.call(this);\r\n\r\n this._split = this.ac.createChannelSplitter(2);\r\n this._merge = this.ac.createChannelMerger(2);\r\n\r\n this._leftGain = this.ac.createGain();\r\n this._rightGain = this.ac.createGain();\r\n\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} leftDelay\r\n */\r\n this.leftDelay = this.ac.createDelay();\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} rightDelay\r\n */\r\n this.rightDelay = this.ac.createDelay();\r\n\r\n this._leftFilter = new Filter();\r\n this._rightFilter = new Filter();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n\r\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n\r\n // graph routing\r\n this.input.connect(this._split);\r\n this.leftDelay.connect(this._leftGain);\r\n this.rightDelay.connect(this._rightGain);\r\n this._leftGain.connect(this._leftFilter.input);\r\n this._rightGain.connect(this._rightFilter.input);\r\n this._merge.connect(this.wet);\r\n\r\n\r\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n\r\n // default routing\r\n this.setType(0);\r\n\r\n this._maxDelay = this.leftDelay.delayTime.maxValue;\r\n\r\n // set initial feedback to 0.5\r\n this.feedback(0.5);\r\n\r\n\r\n };\r\n\r\n p5.Delay.prototype = Object.create(Effect.prototype);\r\n /**\r\n * Add delay to an audio signal according to a set\r\n * of delay parameters.\r\n *\r\n * @method process\r\n * @for p5.Delay\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\r\n * Some browsers limit delayTime to\r\n * 1 second.\r\n * @param {Number} [feedback] sends the delay back through itself\r\n * in a loop that decreases in volume\r\n * each time.\r\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\r\n * below the lowPass will be part of the\r\n * delay.\r\n */\r\n p5.Delay.prototype.process = function(src, _delayTime, _feedback, _filter) {\r\n var feedback = _feedback || 0;\r\n var delayTime = _delayTime || 0;\r\n if (feedback >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n if (delayTime >= this._maxDelay) {\r\n throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.');\r\n }\r\n\r\n src.connect(this.input);\r\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this._leftGain.gain.value = feedback;\r\n this._rightGain.gain.value = feedback;\r\n\r\n if (_filter) {\r\n this._leftFilter.freq(_filter);\r\n this._rightFilter.freq(_filter);\r\n }\r\n };\r\n\r\n /**\r\n * Set the delay (echo) time, in seconds. Usually this value will be\r\n * a floating point number between 0.0 and 1.0.\r\n *\r\n * @method delayTime\r\n * @for p5.Delay\r\n * @param {Number} delayTime Time (in seconds) of the delay\r\n */\r\n p5.Delay.prototype.delayTime = function(t) {\r\n // if t is an audio node...\r\n if (typeof t !== 'number') {\r\n t.connect(this.leftDelay.delayTime);\r\n t.connect(this.rightDelay.delayTime);\r\n }\r\n\r\n else {\r\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Feedback occurs when Delay sends its signal back through its input\r\n * in a loop. The feedback amount determines how much signal to send each\r\n * time through the loop. A feedback greater than 1.0 is not desirable because\r\n * it will increase the overall output each time through the loop,\r\n * creating an infinite feedback loop. The default value is 0.5\r\n *\r\n * @method feedback\r\n * @for p5.Delay\r\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\r\n * Oscillator that can be used to\r\n * modulate this param\r\n * @returns {Number} Feedback value\r\n *\r\n */\r\n p5.Delay.prototype.feedback = function(f) {\r\n // if f is an audio node...\r\n if (f && typeof f !== 'number') {\r\n f.connect(this._leftGain.gain);\r\n f.connect(this._rightGain.gain);\r\n }\r\n else if (f >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n else if (typeof f === 'number') {\r\n this._leftGain.gain.value = f;\r\n this._rightGain.gain.value = f;\r\n }\r\n\r\n // return value of feedback\r\n return this._leftGain.gain.value;\r\n };\r\n\r\n /**\r\n * Set a lowpass filter frequency for the delay. A lowpass filter\r\n * will cut off any frequencies higher than the filter frequency.\r\n *\r\n * @method filter\r\n * @for p5.Delay\r\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\r\n * frequencies higher than the filter frequency.\r\n * @param {Number|Object} res Resonance of the filter frequency\r\n * cutoff, or an object (i.e. a p5.Oscillator)\r\n * that can be used to modulate this parameter.\r\n * High numbers (i.e. 15) will produce a resonance,\r\n * low numbers (i.e. .2) will produce a slope.\r\n */\r\n p5.Delay.prototype.filter = function(freq, q) {\r\n this._leftFilter.set(freq, q);\r\n this._rightFilter.set(freq, q);\r\n };\r\n\r\n\r\n /**\r\n * Choose a preset type of delay. 'pingPong' bounces the signal\r\n * from the left to the right channel to produce a stereo effect.\r\n * Any other parameter will revert to the default delay setting.\r\n *\r\n * @method setType\r\n * @for p5.Delay\r\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\r\n */\r\n p5.Delay.prototype.setType = function(t) {\r\n if (t === 1) {\r\n t = 'pingPong';\r\n }\r\n this._split.disconnect();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n this._split.connect(this.leftDelay, 0);\r\n this._split.connect(this.rightDelay, 1);\r\n switch(t) {\r\n case 'pingPong':\r\n this._rightFilter.setType( this._leftFilter.biquad.type );\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.rightDelay);\r\n this._rightFilter.output.connect(this.leftDelay);\r\n break;\r\n default:\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.leftDelay);\r\n this._rightFilter.output.connect(this.rightDelay);\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the delay effect.\r\n *\r\n * @method amp\r\n * @for p5.Delay\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Delay\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Delay\r\n */\r\n\r\n p5.Delay.prototype.dispose = function() {\r\n\r\n Effect.prototype.dispose.apply(this);\r\n\r\n this._split.disconnect();\r\n this._leftFilter.dispose();\r\n this._rightFilter.dispose();\r\n this._merge.disconnect();\r\n this._leftGain.disconnect();\r\n this._rightGain.disconnect();\r\n this.leftDelay.disconnect();\r\n this.rightDelay.disconnect();\r\n\r\n this._split = undefined;\r\n this._leftFilter = undefined;\r\n this._rightFilter = undefined;\r\n this._merge = undefined;\r\n this._leftGain = undefined;\r\n this._rightGain = undefined;\r\n this.leftDelay = undefined;\r\n this.rightDelay = undefined;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var CustomError = require('errorHandler');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Reverb adds depth to a sound through a large number of decaying\r\n * echoes. It creates the perception that sound is occurring in a\r\n * physical space. The p5.Reverb has paramters for Time (how long does the\r\n * reverb last) and decayRate (how much the sound decays with each echo)\r\n * that can be set with the .set() or .process() methods. The p5.Convolver\r\n * extends p5.Reverb allowing you to recreate the sound of actual physical\r\n * spaces through convolution.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Reverb\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var soundFile, reverb;\r\n * function preload() {\r\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * reverb = new p5.Reverb();\r\n * soundFile.disconnect(); // so we'll only hear reverb...\r\n *\r\n * // connect soundFile to reverb, process w/\r\n * // 3 second reverbTime, decayRate of 2%\r\n * reverb.process(soundFile, 3, 2);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n\r\n\r\n p5.Reverb = function() {\r\n Effect.call(this);\r\n\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n // default params\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n\r\n };\r\n\r\n p5.Reverb.prototype = Object.create(Effect.prototype);\r\n\r\n p5.Reverb.prototype._initConvolverNode = function() {\r\n this.convolverNode = this.ac.createConvolver();\r\n this.input.connect(this.convolverNode);\r\n this.convolverNode.connect(this.wet);\r\n };\r\n\r\n p5.Reverb.prototype._teardownConvolverNode = function() {\r\n if (this.convolverNode) {\r\n this.convolverNode.disconnect();\r\n delete this.convolverNode;\r\n }\r\n };\r\n\r\n p5.Reverb.prototype._setBuffer = function(audioBuffer) {\r\n this._teardownConvolverNode();\r\n this._initConvolverNode();\r\n this.convolverNode.buffer = audioBuffer;\r\n };\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Reverb\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.process = function(src, seconds, decayRate, reverse) {\r\n src.connect(this.input);\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n /**\r\n * Set the reverb settings. Similar to .process(), but without\r\n * assigning a new input.\r\n *\r\n * @method set\r\n * @for p5.Reverb\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.set = function(seconds, decayRate, reverse) {\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the reverb effect.\r\n *\r\n * @method amp\r\n * @for p5.Reverb\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Reverb\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Reverb\r\n */\r\n\r\n /**\r\n * Inspired by Simple Reverb by Jordan Santell\r\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\r\n *\r\n * Utility function for building an impulse response\r\n * based on the module parameters.\r\n *\r\n * @private\r\n */\r\n p5.Reverb.prototype._buildImpulse = function() {\r\n var rate = this.ac.sampleRate;\r\n var length = rate*this._seconds;\r\n var decay = this._decay;\r\n var impulse = this.ac.createBuffer(2, length, rate);\r\n var impulseL = impulse.getChannelData(0);\r\n var impulseR = impulse.getChannelData(1);\r\n var n, i;\r\n for (i = 0; i < length; i++) {\r\n n = this._reverse ? length - i : i;\r\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n }\r\n this._setBuffer(impulse);\r\n };\r\n\r\n p5.Reverb.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n this._teardownConvolverNode();\r\n };\r\n\r\n // =======================================================================\r\n // *** p5.Convolver ***\r\n // =======================================================================\r\n\r\n /**\r\n *
p5.Convolver extends p5.Reverb. It can emulate the sound of real\r\n * physical spaces through a process called \r\n * convolution.
\r\n *\r\n *
Convolution multiplies any audio input by an \"impulse response\"\r\n * to simulate the dispersion of sound over time. The impulse response is\r\n * generated from an audio file that you provide. One way to\r\n * generate an impulse response is to pop a balloon in a reverberant space\r\n * and record the echo. Convolution can also be used to experiment with\r\n * sound.
\r\n *\r\n *
Use the method createConvolution(path) to instantiate a\r\n * p5.Convolver with a path to your impulse response audio file.
\r\n *\r\n * @class p5.Convolver\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call when loading succeeds\r\n * @param {Function} [errorCallback] function to call if loading fails.\r\n * This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver = function(path, callback, errorCallback) {\r\n \t p5.Reverb.call(this);\r\n\r\n /**\r\n * Internally, the p5.Convolver uses the a\r\n * \r\n * Web Audio Convolver Node.\r\n *\r\n * @property {ConvolverNode} convolverNode\r\n */\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n if (path) {\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n }\r\n else {\r\n // parameters\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n }\r\n\r\n };\r\n\r\n p5.Convolver.prototype = Object.create(p5.Reverb.prototype);\r\n\r\n p5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\r\n\r\n /**\r\n * Create a p5.Convolver. Accepts a path to a soundfile\r\n * that will be used to generate an impulse response.\r\n *\r\n * @method createConvolver\r\n * @for p5\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call if loading is successful.\r\n * The object will be passed in as the argument\r\n * to the callback function.\r\n * @param {Function} [errorCallback] function to call if loading is not successful.\r\n * A custom error will be passed in as the argument\r\n * to the callback function.\r\n * @return {p5.Convolver}\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.createConvolver = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n var self = this;\r\n var cReverb = new p5.Convolver(path, function(buffer) {\r\n if (typeof callback === 'function') {\r\n callback(buffer);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, errorCallback);\r\n cReverb.impulses = [];\r\n return cReverb;\r\n };\r\n\r\n /**\r\n * Private method to load a buffer as an Impulse Response,\r\n * assign it to the convolverNode, and add to the Array of .impulses.\r\n *\r\n * @param {String} path\r\n * @param {Function} callback\r\n * @param {Function} errorCallback\r\n * @private\r\n */\r\n p5.Convolver.prototype._loadBuffer = function(path, callback, errorCallback) {\r\n var path = p5.prototype._checkFileFormats(path);\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n var ac = p5.prototype.getAudioContext();\r\n\r\n var request = new XMLHttpRequest();\r\n request.open('GET', path, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on success loading file:\r\n ac.decodeAudioData(request.response,\r\n function(buff) {\r\n var buffer = {};\r\n var chunks = path.split('/');\r\n buffer.name = chunks[chunks.length - 1];\r\n buffer.audioBuffer = buff;\r\n self.impulses.push(buffer);\r\n self._setBuffer(buffer.audioBuffer);\r\n if (callback) {\r\n callback(buffer);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url +\r\n '. The request status was: ' + request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n request.send();\r\n };\r\n\r\n p5.Convolver.prototype.set = null;\r\n\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Convolver\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * cVerb = createConvolver('assets/concrete-tunnel.mp3');\r\n *\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with (i.e. connect to) cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver.prototype.process = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * If you load multiple impulse files using the .addImpulse method,\r\n * they will be stored as Objects in this Array. Toggle between them\r\n * with the toggleImpulse(id) method.\r\n *\r\n * @property {Array} impulses\r\n * @for p5.Convolver\r\n */\r\n p5.Convolver.prototype.impulses = [];\r\n\r\n /**\r\n * Load and assign a new Impulse Response to the p5.Convolver.\r\n * The impulse is added to the .impulses array. Previous\r\n * impulses can be accessed with the .toggleImpulse(id)\r\n * method.\r\n *\r\n * @method addImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.addImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * Similar to .addImpulse, except that the .impulses\r\n * Array is reset to save memory. A new .impulses\r\n * array is created with this impulse as the only item.\r\n *\r\n * @method resetImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.resetImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * If you have used .addImpulse() to add multiple impulses\r\n * to a p5.Convolver, then you can use this method to toggle between\r\n * the items in the .impulses Array. Accepts a parameter\r\n * to identify which impulse you wish to use, identified either by its\r\n * original filename (String) or by its position in the .impulses\r\n * Array (Number). \r\n * You can access the objects in the .impulses Array directly. Each\r\n * Object has two attributes: an .audioBuffer (type:\r\n * Web Audio \r\n * AudioBuffer) and a .name, a String that corresponds\r\n * with the original filename.\r\n *\r\n * @method toggleImpulse\r\n * @for p5.Convolver\r\n * @param {String|Number} id Identify the impulse by its original filename\r\n * (String), or by its position in the\r\n * .impulses Array (Number).\r\n */\r\n p5.Convolver.prototype.toggleImpulse = function(id) {\r\n if (typeof id === 'number' && id < this.impulses.length) {\r\n this._setBuffer(this.impulses[id].audioBuffer);\r\n }\r\n if (typeof id === 'string') {\r\n for (var i = 0; i < this.impulses.length; i++) {\r\n if (this.impulses[i].name === id) {\r\n this._setBuffer(this.impulses[i].audioBuffer);\r\n break;\r\n }\r\n }\r\n }\r\n };\r\n\r\n p5.Convolver.prototype.dispose = function() {\r\n p5.Reverb.prototype.dispose.apply(this);\r\n\r\n // remove all the Impulse Response buffers\r\n for (var i in this.impulses) {\r\n if (this.impulses[i]) {\r\n this.impulses[i] = null;\r\n }\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n // requires the Tone.js library's Clock (MIT license, Yotam Mann)\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Clock = require('Tone/core/Clock');\r\n\r\n p5.Metro = function() {\r\n this.clock = new Clock({\r\n 'callback': this.ontick.bind(this)\r\n });\r\n this.syncedParts = [];\r\n this.bpm = 120; // gets overridden by p5.Part\r\n this._init();\r\n\r\n this.prevTick = 0;\r\n this.tatumTime = 0;\r\n\r\n this.tickCallback = function() {};\r\n };\r\n\r\n p5.Metro.prototype.ontick = function(tickTime) {\r\n var elapsedTime = tickTime - this.prevTick;\r\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\r\n if (elapsedTime - this.tatumTime <= -0.02) {\r\n return;\r\n } else {\r\n // console.log('ok', this.syncedParts[0].phrases[0].name);\r\n this.prevTick = tickTime;\r\n\r\n // for all of the active things on the metro:\r\n var self = this;\r\n this.syncedParts.forEach(function(thisPart) {\r\n if (!thisPart.isPlaying) return;\r\n thisPart.incrementStep(secondsFromNow);\r\n // each synced source keeps track of its own beat number\r\n thisPart.phrases.forEach(function(thisPhrase) {\r\n var phraseArray = thisPhrase.sequence;\r\n var bNum = self.metroTicks % phraseArray.length;\r\n if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping) ) {\r\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\r\n }\r\n });\r\n });\r\n this.metroTicks += 1;\r\n this.tickCallback(secondsFromNow);\r\n }\r\n };\r\n\r\n p5.Metro.prototype.setBPM = function(bpm, rampTime) {\r\n var beatTime = 60 / (bpm*this.tatums);\r\n var now = p5sound.audiocontext.currentTime;\r\n this.tatumTime = beatTime;\r\n\r\n var rampTime = rampTime || 0;\r\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\r\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\r\n this.bpm = bpm;\r\n };\r\n\r\n p5.Metro.prototype.getBPM = function() {\r\n return this.clock.getRate() / this.tatums * 60;\r\n };\r\n\r\n p5.Metro.prototype._init = function() {\r\n this.metroTicks = 0;\r\n // this.setBPM(120);\r\n };\r\n\r\n // clear existing synced parts, add only this one\r\n p5.Metro.prototype.resetSync = function(part) {\r\n this.syncedParts = [part];\r\n };\r\n\r\n // push a new synced part to the array\r\n p5.Metro.prototype.pushSync = function(part) {\r\n this.syncedParts.push(part);\r\n };\r\n\r\n p5.Metro.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.start(now + t);\r\n this.setBPM(this.bpm);\r\n };\r\n\r\n p5.Metro.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.stop(now + t);\r\n };\r\n\r\n p5.Metro.prototype.beatLength = function(tatums) {\r\n this.tatums = 1/tatums / 4; // lowest possible division of a beat\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Timeline\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline State. Provides the methods: setStateAtTime(\"state\", time)\n\t * and getValueAtTime(time).\n\t *\n\t * @extends {Tone.Timeline}\n\t * @param {String} initial The initial state of the TimelineState. \n\t * Defaults to undefined\n\t */\n\tTone.TimelineState = function(initial){\n\n\t\tTone.Timeline.call(this);\n\n\t\t/**\n\t\t * The initial state\n\t\t * @private\n\t\t * @type {String}\n\t\t */\n\t\tthis._initial = initial;\n\t};\n\n\tTone.extend(Tone.TimelineState, Tone.Timeline);\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {Number} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t */\n\tTone.TimelineState.prototype.getValueAtTime = function(time){\n\t\tvar event = this.get(time);\n\t\tif (event !== null){\n\t\t\treturn event.state;\n\t\t} else {\n\t\t\treturn this._initial;\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {String} state The name of the state to set.\n\t * @param {Number} time The time to query.\n\t */\n\tTone.TimelineState.prototype.setStateAtTime = function(state, time){\n\t\tthis.add({\n\t\t\t\"state\" : state,\n\t\t\t\"time\" : time\n\t\t});\n\t};\n\n\treturn Tone.TimelineState;\n});","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n var BPM = 120;\r\n\r\n /**\r\n * Set the global tempo, in beats per minute, for all\r\n * p5.Parts. This method will impact all active p5.Parts.\r\n *\r\n * @method setBPM\r\n * @for p5\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.prototype.setBPM = function(bpm, rampTime) {\r\n BPM = bpm;\r\n for (var i in p5sound.parts) {\r\n if (p5sound.parts[i]) {\r\n p5sound.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n *
A phrase is a pattern of musical events over time, i.e.\r\n * a series of notes and rests.
\r\n *\r\n *
Phrases must be added to a p5.Part for playback, and\r\n * each part can play multiple phrases at the same time.\r\n * For example, one Phrase might be a kick drum, another\r\n * could be a snare, and another could be the bassline.
\r\n *\r\n *
The first parameter is a name so that the phrase can be\r\n * modified or deleted later. The callback is a a function that\r\n * this phrase will call at every step—for example it might be\r\n * called playNote(value){}. The array determines\r\n * which value is passed into the callback at each step of the\r\n * phrase. It can be numbers, an object with multiple numbers,\r\n * or a zero (0) indicates a rest so the callback won't be called).
\r\n *\r\n * @class p5.Phrase\r\n * @constructor\r\n * @param {String} name Name so that you can access the Phrase.\r\n * @param {Function} callback The name of a function that this phrase\r\n * will call. Typically it will play a sound,\r\n * and accept two parameters: a time at which\r\n * to play the sound (in seconds from now),\r\n * and a value from the sequence array. The\r\n * time should be passed into the play() or\r\n * start() method to ensure precision.\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n * @example\r\n *
\r\n */\r\n p5.Phrase = function(name, callback, sequence) {\r\n this.phraseStep = 0;\r\n this.name = name;\r\n this.callback = callback;\r\n /**\r\n * Array of values to pass into the callback\r\n * at each step of the phrase. Depending on the callback\r\n * function's requirements, these values may be numbers,\r\n * strings, or an object with multiple parameters.\r\n * Zero (0) indicates a rest.\r\n *\r\n * @property {Array} sequence\r\n */\r\n this.sequence = sequence;\r\n };\r\n\r\n /**\r\n *
A p5.Part plays back one or more p5.Phrases. Instantiate a part\r\n * with steps and tatums. By default, each step represents a 1/16th note.
\r\n *\r\n *
See p5.Phrase for more about musical timing.
\r\n *\r\n * @class p5.Part\r\n * @constructor\r\n * @param {Number} [steps] Steps in the part\r\n * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note)\r\n * @example\r\n *
\r\n * var box, drum, myPart;\r\n * var boxPat = [1,0,0,2,0,2,0,0];\r\n * var drumPat = [0,1,1,0,2,0,1,0];\r\n * var msg = 'click to play';\r\n *\r\n * function preload() {\r\n * box = loadSound('assets/beatbox.mp3');\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * masterVolume(0.1);\r\n *\r\n * var boxPhrase = new p5.Phrase('box', playBox, boxPat);\r\n * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\r\n * myPart = new p5.Part();\r\n * myPart.addPhrase(boxPhrase);\r\n * myPart.addPhrase(drumPhrase);\r\n * myPart.setBPM(60);\r\n * masterVolume(0.1);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * text(msg, width/2, height/2);\r\n * }\r\n *\r\n * function playBox(time, playbackRate) {\r\n * box.rate(playbackRate);\r\n * box.play(time);\r\n * }\r\n *\r\n * function playDrum(time, playbackRate) {\r\n * drum.rate(playbackRate);\r\n * drum.play(time);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * myPart.start();\r\n * msg = 'playing part';\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Part = function(steps, bLength) {\r\n this.length = steps || 0; // how many beats\r\n this.partStep = 0;\r\n this.phrases = [];\r\n this.isPlaying = false;\r\n this.noLoop();\r\n this.tatums = bLength || 0.0625; // defaults to quarter note\r\n\r\n this.metro = new p5.Metro();\r\n this.metro._init();\r\n this.metro.beatLength(this.tatums);\r\n this.metro.setBPM(BPM);\r\n p5sound.parts.push(this);\r\n this.callback = function() {};\r\n };\r\n\r\n /**\r\n * Set the tempo of this part, in Beats Per Minute.\r\n *\r\n * @method setBPM\r\n * @for p5.Part\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} [rampTime] Seconds from now\r\n */\r\n p5.Part.prototype.setBPM = function(tempo, rampTime) {\r\n this.metro.setBPM(tempo, rampTime);\r\n };\r\n\r\n /**\r\n * Returns the tempo, in Beats Per Minute, of this part.\r\n *\r\n * @method getBPM\r\n * @for p5.Part\r\n * @return {Number}\r\n */\r\n p5.Part.prototype.getBPM = function() {\r\n return this.metro.getBPM();\r\n };\r\n\r\n /**\r\n * Start playback of this part. It will play\r\n * through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method start\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.start = function(time) {\r\n if (!this.isPlaying) {\r\n this.isPlaying = true;\r\n this.metro.resetSync(this);\r\n var t = time || 0;\r\n this.metro.start(t);\r\n }\r\n };\r\n\r\n /**\r\n * Loop playback of this part. It will begin\r\n * looping through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method loop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.loop = function(time) {\r\n this.looping = true;\r\n // rest onended function\r\n this.onended = function() {\r\n this.partStep = 0;\r\n };\r\n var t = time || 0;\r\n this.start(t);\r\n };\r\n\r\n /**\r\n * Tell the part to stop looping.\r\n *\r\n * @method noLoop\r\n * @for p5.Part\r\n */\r\n p5.Part.prototype.noLoop = function() {\r\n this.looping = false;\r\n // rest onended function\r\n this.onended = function() {\r\n this.stop();\r\n };\r\n };\r\n\r\n /**\r\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\r\n *\r\n * @method stop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.stop = function(time) {\r\n this.partStep = 0;\r\n this.pause(time);\r\n };\r\n\r\n /**\r\n * Pause the part. Playback will resume\r\n * from the current step.\r\n *\r\n * @method pause\r\n * @for p5.Part\r\n * @param {Number} time seconds from now\r\n */\r\n p5.Part.prototype.pause = function(time) {\r\n this.isPlaying = false;\r\n var t = time || 0;\r\n this.metro.stop(t);\r\n };\r\n\r\n /**\r\n * Add a p5.Phrase to this Part.\r\n *\r\n * @method addPhrase\r\n * @for p5.Part\r\n * @param {p5.Phrase} phrase reference to a p5.Phrase\r\n */\r\n p5.Part.prototype.addPhrase = function(name, callback, array) {\r\n var p;\r\n if (arguments.length === 3) {\r\n p = new p5.Phrase(name, callback, array);\r\n } else if (arguments[0] instanceof p5.Phrase) {\r\n p = arguments[0];\r\n } else {\r\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\r\n }\r\n this.phrases.push(p);\r\n // reset the length if phrase is longer than part's existing length\r\n if (p.sequence.length > this.length) {\r\n this.length = p.sequence.length;\r\n }\r\n };\r\n\r\n /**\r\n * Remove a phrase from this part, based on the name it was\r\n * given when it was created.\r\n *\r\n * @method removePhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.removePhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases.splice(i, 1);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Get a phrase from this part, based on the name it was\r\n * given when it was created. Now you can modify its array.\r\n *\r\n * @method getPhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.getPhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n return this.phrases[i];\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Find all sequences with the specified name, and replace their patterns with the specified array.\r\n *\r\n * @method replaceSequence\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n */\r\n p5.Part.prototype.replaceSequence = function(name, array) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases[i].sequence = array;\r\n }\r\n }\r\n };\r\n\r\n p5.Part.prototype.incrementStep = function(time) {\r\n if (this.partStep < this.length - 1) {\r\n this.callback(time);\r\n this.partStep += 1;\r\n } else {\r\n if (!this.looping && this.partStep === this.length - 1) {\r\n console.log('done');\r\n // this.callback(time);\r\n this.onended();\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the function that will be called at every step. This will clear the previous function.\r\n *\r\n * @method onStep\r\n * @for p5.Part\r\n * @param {Function} callback The name of the callback\r\n * you want to fire\r\n * on every beat/tatum.\r\n */\r\n p5.Part.prototype.onStep = function(callback) {\r\n this.callback = callback;\r\n };\r\n\r\n\r\n // ===============\r\n // p5.Score\r\n // ===============\r\n\r\n /**\r\n * A Score consists of a series of Parts. The parts will\r\n * be played back in order. For example, you could have an\r\n * A part, a B part, and a C part, and play them back in this order\r\n * new p5.Score(a, a, b, a, c)\r\n *\r\n * @class p5.Score\r\n * @constructor\r\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\r\n */\r\n p5.Score = function() {\r\n // for all of the arguments\r\n this.parts = [];\r\n this.currentPart = 0;\r\n\r\n var thisScore = this;\r\n for (var i in arguments) {\r\n if (arguments[i] && this.parts[i]) {\r\n this.parts[i] = arguments[i];\r\n this.parts[i].nextPart = this.parts[i + 1];\r\n this.parts[i].onended = function() {\r\n thisScore.resetPart(i);\r\n playNextPart(thisScore);\r\n };\r\n }\r\n }\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.onended = function() {\r\n if (this.looping) {\r\n // this.resetParts();\r\n this.parts[0].start();\r\n } else {\r\n this.parts[this.parts.length - 1].onended = function() {\r\n this.stop();\r\n this.resetParts();\r\n };\r\n }\r\n this.currentPart = 0;\r\n };\r\n\r\n /**\r\n * Start playback of the score.\r\n *\r\n * @method start\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.start = function() {\r\n this.parts[this.currentPart].start();\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Stop playback of the score.\r\n *\r\n * @method stop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.stop = function() {\r\n this.parts[this.currentPart].stop();\r\n this.currentPart = 0;\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Pause playback of the score.\r\n *\r\n * @method pause\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.pause = function() {\r\n this.parts[this.currentPart].stop();\r\n };\r\n\r\n /**\r\n * Loop playback of the score.\r\n *\r\n * @method loop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.loop = function() {\r\n this.looping = true;\r\n this.start();\r\n };\r\n\r\n /**\r\n * Stop looping playback of the score. If it\r\n * is currently playing, this will go into effect\r\n * after the current round of playback completes.\r\n *\r\n * @method noLoop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.noLoop = function() {\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.resetParts = function() {\r\n var self = this;\r\n this.parts.forEach(function(part) {\r\n self.resetParts[part];\r\n });\r\n };\r\n\r\n p5.Score.prototype.resetPart = function(i) {\r\n this.parts[i].stop();\r\n this.parts[i].partStep = 0;\r\n for (var p in this.parts[i].phrases) {\r\n if (this.parts[i]) {\r\n this.parts[i].phrases[p].phraseStep = 0;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the tempo for all parts in the score\r\n *\r\n * @method setBPM\r\n * @for p5.Score\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.Score.prototype.setBPM = function(bpm, rampTime) {\r\n for (var i in this.parts) {\r\n if (this.parts[i]) {\r\n this.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n function playNextPart(aScore) {\r\n aScore.currentPart++;\r\n if (aScore.currentPart >= aScore.parts.length) {\r\n aScore.scoreStep = 0;\r\n aScore.onended();\r\n } else {\r\n aScore.scoreStep = 0;\r\n aScore.parts[aScore.currentPart - 1].stop();\r\n aScore.parts[aScore.currentPart].start();\r\n }\r\n }\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Clock = require('Tone/core/Clock');\r\n\r\n /**\r\n * SoundLoop\r\n *\r\n * @class p5.SoundLoop\r\n * @constructor\r\n *\r\n * @param {Function} callback this function will be called on each iteration of theloop\r\n * @param {Number|String} [interval] amount of time or beats for each iteration of the loop\r\n * defaults to 1\r\n *\r\n * @example\r\n *
\r\n * var click;\r\n * var looper1;\r\n *\r\n * function preload() {\r\n * click = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * //the looper's callback is passed the timeFromNow\r\n * //this value should be used as a reference point from\r\n * //which to schedule sounds\r\n * looper1 = new p5.SoundLoop(function(timeFromNow){\r\n * click.play(timeFromNow);\r\n * background(255 * (looper1.iterations % 2));\r\n * }, 2);\r\n *\r\n * //stop after 10 iteratios;\r\n * looper1.maxIterations = 10;\r\n * //start the loop\r\n * looper1.start();\r\n * }\r\n *
\r\n */\r\n p5.SoundLoop = function(callback, interval) {\r\n this.callback = callback;\r\n /**\r\n * musicalTimeMode uses Tone.Time convention\r\n\t * true if string, false if number\r\n * @property {Boolean} musicalTimeMode\r\n */\r\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\r\n\r\n this._interval = interval || 1;\r\n\r\n /**\r\n * musicalTimeMode variables\r\n * modify these only when the interval is specified in musicalTime format as a string\r\n */\r\n this._timeSignature = 4;\r\n this._bpm = 60;\r\n\r\n this.isPlaying = false;\r\n\r\n /**\r\n * Set a limit to the number of loops to play. defaults to Infinity\r\n * @property {Number} maxIterations\r\n */\r\n this.maxIterations = Infinity;\r\n var self = this;\r\n\r\n this.clock = new Clock({\r\n 'callback' : function(time) {\r\n var timeFromNow = time - p5sound.audiocontext.currentTime;\r\n /**\r\n * Do not initiate the callback if timeFromNow is < 0\r\n * This ususually occurs for a few milliseconds when the page\r\n * is not fully loaded\r\n *\r\n * The callback should only be called until maxIterations is reached\r\n */\r\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\r\n self.callback(timeFromNow);}\r\n },\r\n 'frequency' : this._calcFreq()\r\n });\r\n };\r\n\r\n /**\r\n * Start the loop\r\n * @method start\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a starting time\r\n */\r\n p5.SoundLoop.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (!this.isPlaying) {\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop the loop\r\n * @method stop\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a stopping time\r\n */\r\n p5.SoundLoop.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.stop(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n /**\r\n * Pause the loop\r\n * @method pause\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a pausing time\r\n */\r\n p5.SoundLoop.prototype.pause = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.pause(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Synchronize loops. Use this method to start two more more loops in synchronization\r\n * or to start a loop in synchronization with a loop that is already playing\r\n * This method will schedule the implicit loop in sync with the explicit master loop\r\n * i.e. loopToStart.syncedStart(loopToSyncWith)\r\n *\r\n * @method syncedStart\r\n * @for p5.SoundLoop\r\n * @param {Object} otherLoop a p5.SoundLoop to sync with\r\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\r\n */\r\n p5.SoundLoop.prototype.syncedStart = function(otherLoop, timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n if (!otherLoop.isPlaying) {\r\n otherLoop.clock.start(now + t);\r\n otherLoop.isPlaying = true;\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n } else if (otherLoop.isPlaying) {\r\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\r\n this.clock.start(now + time);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Updates frequency value, reflected in next callback\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _update\r\n */\r\n p5.SoundLoop.prototype._update = function() {\r\n this.clock.frequency.value = this._calcFreq();\r\n };\r\n\r\n /**\r\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _calcFreq\r\n * @return {Number} new clock frequency value\r\n */\r\n p5.SoundLoop.prototype._calcFreq = function() {\r\n //Seconds mode, bpm / timesignature has no effect\r\n if (typeof this._interval === 'number') {\r\n this.musicalTimeMode = false;\r\n return 1 / this._interval;\r\n }\r\n //Musical timing mode, calculate interval based bpm, interval,and time signature\r\n else if (typeof this._interval === 'string') {\r\n this.musicalTimeMode = true;\r\n return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4);\r\n }\r\n };\r\n\r\n /**\r\n * Convert notation from musical time format to seconds\r\n * Uses Tone.Time convention\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _convertNotation\r\n * @param {String} value value to be converted\r\n * @return {Number} converted value in seconds\r\n */\r\n p5.SoundLoop.prototype._convertNotation = function(value) {\r\n var type = value.slice(-1);\r\n value = Number(value.slice(0,-1));\r\n switch (type) {\r\n case 'm':\r\n return this._measure(value);\r\n case 'n':\r\n return this._note(value);\r\n default:\r\n console.warn('Specified interval is not formatted correctly. See Tone.js '+\r\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time');\r\n }\r\n };\r\n\r\n /**\r\n * Helper conversion methods of measure and note\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _measure\r\n */\r\n p5.SoundLoop.prototype._measure = function(value) {\r\n return value * this._timeSignature;\r\n };\r\n\r\n /**\r\n * @private\r\n * @method _note\r\n * @for p5.SoundLoop\r\n */\r\n p5.SoundLoop.prototype._note = function(value) {\r\n return this._timeSignature / value ;\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters, setting any paramter will result in a change in the clock's\r\n * frequency, that will be reflected after the next callback\r\n * beats per minute (defaults to 60)\r\n * @property {Number} bpm\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'bpm', {\r\n get : function() {\r\n return this._bpm;\r\n },\r\n set : function(bpm) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the BPM in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._bpm = bpm;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * number of quarter notes in a measure (defaults to 4)\r\n * @property {Number} timeSignature\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {\r\n get : function() {\r\n return this._timeSignature;\r\n },\r\n set : function(timeSig) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the timeSignature in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._timeSignature = timeSig;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * length of the loops interval\r\n * @property {Number|String} interval\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'interval', {\r\n get : function() {\r\n return this._interval;\r\n },\r\n set : function(interval) {\r\n this.musicalTimeMode = typeof interval === 'Number'? false : true;\r\n this._interval = interval;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * how many times the callback has been called so far\r\n * @property {Number} iterations\r\n * @for p5.SoundLoop\r\n * @readonly\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'iterations', {\r\n get : function() {\r\n return this.clock.ticks;\r\n }\r\n });\r\n\r\n return p5.SoundLoop;\r\n});\r\n","define(function (require) {\r\n\t'use strict';\r\n\r\n\tvar p5sound = require('master');\r\n\tvar Effect = require('effect');\r\n var CustomError = require('errorHandler');\r\n\r\n /**\r\n * Compressor is an audio effect class that performs dynamics compression\r\n * on an audio input source. This is a very commonly used technique in music\r\n * and sound production. Compression creates an overall louder, richer,\r\n * and fuller sound by lowering the volume of louds and raising that of softs.\r\n * Compression can be used to avoid clipping (sound distortion due to\r\n * peaks in volume) and is especially useful when many sounds are played\r\n * at once. Compression can be used on indivudal sound sources in addition\r\n * to the master output.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Compressor\r\n * @constructor\r\n * @extends p5.Effect\r\n *\r\n *\r\n */\r\n\tp5.Compressor = function() {\r\n\t\tEffect.call(this);\r\n\r\n /**\r\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\r\n * \r\n * @property {AudioNode} compressor\r\n */\r\n\r\n\r\n\t\tthis.compressor = this.ac.createDynamicsCompressor();\r\n\r\n this.input.connect(this.compressor);\r\n this.compressor.connect(this.wet);\r\n\t};\r\n\r\n\tp5.Compressor.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Performs the same function as .connect, but also accepts\r\n * optional parameters to set compressor's audioParams\r\n * @method process\r\n * @for p5.Compressor\r\n *\r\n * @param {Object} src Sound source to be connected\r\n *\r\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n\tp5.Compressor.prototype.process = function(src, attack, knee,\r\n ratio, threshold, release) {\r\n\t\tsrc.connect(this.input);\r\n\t\tthis.set(attack, knee, ratio, threshold, release);\r\n\t};\r\n\r\n /**\r\n * Set the paramters of a compressor.\r\n * @method set\r\n * @for p5.Compressor\r\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} knee A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n p5.Compressor.prototype.set = function (attack, knee,\r\n ratio, threshold, release) {\r\n\r\n if (typeof attack !== 'undefined') {this.attack(attack);}\r\n if (typeof knee !== 'undefined') {this.knee(knee);}\r\n if (typeof ratio !== 'undefined') {this.ratio(ratio);}\r\n if (typeof threshold !== 'undefined') {this.threshold(threshold);}\r\n if (typeof release !== 'undefined') {this.release(release);}\r\n };\r\n\r\n\r\n /**\r\n * Get current attack or set value w/ time ramp\r\n *\r\n *\r\n * @method attack\r\n * @for p5.Compressor\r\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.attack = function (attack, time){\r\n var t = time || 0;\r\n if (typeof attack == 'number'){\r\n this.compressor.attack.value = attack;\r\n this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof attack !== 'undefined') {\r\n attack.connect(this.compressor.attack);\r\n }\r\n return this.compressor.attack.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current knee or set value w/ time ramp\r\n *\r\n * @method knee\r\n * @for p5.Compressor\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.knee = function (knee, time){\r\n var t = time || 0;\r\n if (typeof knee == 'number'){\r\n this.compressor.knee.value = knee;\r\n this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof knee !== 'undefined') {\r\n knee.connect(this.compressor.knee);\r\n }\r\n return this.compressor.knee.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current ratio or set value w/ time ramp\r\n * @method ratio\r\n * @for p5.Compressor\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.ratio = function (ratio, time){\r\n var t = time || 0;\r\n if (typeof ratio == 'number'){\r\n this.compressor.ratio.value = ratio;\r\n this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof ratio !== 'undefined') {\r\n ratio.connect(this.compressor.ratio);\r\n }\r\n return this.compressor.ratio.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current threshold or set value w/ time ramp\r\n * @method threshold\r\n * @for p5.Compressor\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.threshold = function (threshold, time){\r\n var t = time || 0;\r\n if (typeof threshold == 'number'){\r\n this.compressor.threshold.value = threshold;\r\n this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof threshold !== 'undefined') {\r\n threshold.connect(this.compressor.threshold);\r\n }\r\n return this.compressor.threshold.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current release or set value w/ time ramp\r\n * @method release\r\n * @for p5.Compressor\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n *\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.release = function (release, time){\r\n var t = time || 0;\r\n if (typeof release == 'number'){\r\n this.compressor.release.value = release;\r\n this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof number !== 'undefined') {\r\n release.connect(this.compressor.release);\r\n }\r\n return this.compressor.release.value;\r\n };\r\n\r\n /**\r\n * Return the current reduction value\r\n *\r\n * @method reduction\r\n * @for p5.Compressor\r\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\r\n */\r\n p5.Compressor.prototype.reduction =function() {\r\n return this.compressor.reduction.value;\r\n };\r\n\r\n\r\n\tp5.Compressor.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.compressor) {\r\n this.compressor.disconnect();\r\n delete this.compressor;\r\n }\r\n\t};\r\n\r\n return p5.Compressor;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // inspiration: recorder.js, Tone.js & typedarray.org\r\n\r\n var p5sound = require('master');\r\n var convertToWav = require('helpers').convertToWav;\r\n var processorNames = require('./audioWorklet/processorNames');\r\n var ac = p5sound.audiocontext;\r\n\r\n /**\r\n *
Record sounds for playback and/or to save as a .wav file.\r\n * The p5.SoundRecorder records all sound output from your sketch,\r\n * or can be assigned a specific source with setInput().
\r\n *
The record() method accepts a p5.SoundFile as a parameter.\r\n * When playback is stopped (either after the given amount of time,\r\n * or with the stop() method), the p5.SoundRecorder will send its\r\n * recording to that p5.SoundFile for playback.
\r\n * var mic, recorder, soundFile;\r\n * var state = 0;\r\n *\r\n * function setup() {\r\n * background(200);\r\n * // create an audio in\r\n * mic = new p5.AudioIn();\r\n *\r\n * // prompts user to enable their browser mic\r\n * mic.start();\r\n *\r\n * // create a sound recorder\r\n * recorder = new p5.SoundRecorder();\r\n *\r\n * // connect the mic to the recorder\r\n * recorder.setInput(mic);\r\n *\r\n * // this sound file will be used to\r\n * // playback & save the recording\r\n * soundFile = new p5.SoundFile();\r\n *\r\n * text('keyPress to record', 20, 20);\r\n * }\r\n *\r\n * function keyPressed() {\r\n * // make sure user enabled the mic\r\n * if (state === 0 && mic.enabled) {\r\n *\r\n * // record to our p5.SoundFile\r\n * recorder.record(soundFile);\r\n *\r\n * background(255,0,0);\r\n * text('Recording!', 20, 20);\r\n * state++;\r\n * }\r\n * else if (state === 1) {\r\n * background(0,255,0);\r\n *\r\n * // stop recorder and\r\n * // send result to soundFile\r\n * recorder.stop();\r\n *\r\n * text('Stopped', 20, 20);\r\n * state++;\r\n * }\r\n *\r\n * else if (state === 2) {\r\n * soundFile.play(); // play the result!\r\n * save(soundFile, 'mySound.wav');\r\n * state++;\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.SoundRecorder = function() {\r\n this.input = ac.createGain();\r\n this.output = ac.createGain();\r\n\r\n this._inputChannels = 2;\r\n this._outputChannels = 2; // stereo output, even if input is mono\r\n\r\n this._workletNode = new AudioWorkletNode(ac, processorNames.recorderProcessor, {\r\n outputChannelCount: [this._outputChannels],\r\n processorOptions: { numInputChannels: this._inputChannels }\r\n });\r\n\r\n this._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'buffers') {\r\n const buffers = [\r\n new Float32Array(event.data.leftBuffer),\r\n new Float32Array(event.data.rightBuffer)\r\n ];\r\n this._callback(buffers);\r\n }\r\n }.bind(this);\r\n\r\n /**\r\n * callback invoked when the recording is over\r\n * @private\r\n * @type Function(Float32Array)\r\n */\r\n this._callback = function() {};\r\n\r\n // connections\r\n this._workletNode.connect(p5.soundOut._silentNode);\r\n this.setInput();\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a specific device to the p5.SoundRecorder.\r\n * If no parameter is given, p5.SoundRecorer will record\r\n * all audible p5.sound from your sketch.\r\n *\r\n * @method setInput\r\n * @for p5.SoundRecorder\r\n * @param {Object} [unit] p5.sound object or a web audio unit\r\n * that outputs sound\r\n */\r\n p5.SoundRecorder.prototype.setInput = function(unit) {\r\n this.input.disconnect();\r\n this.input = null;\r\n this.input = ac.createGain();\r\n this.input.connect(this._workletNode);\r\n this.input.connect(this.output);\r\n if (unit) {\r\n unit.connect(this.input);\r\n } else {\r\n p5.soundOut.output.connect(this.input);\r\n }\r\n };\r\n\r\n /**\r\n * Start recording. To access the recording, provide\r\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\r\n * will send its recording to that p5.SoundFile for playback once\r\n * recording is complete. Optional parameters include duration\r\n * (in seconds) of the recording, and a callback function that\r\n * will be called once the complete recording has been\r\n * transfered to the p5.SoundFile.\r\n *\r\n * @method record\r\n * @for p5.SoundRecorder\r\n * @param {p5.SoundFile} soundFile p5.SoundFile\r\n * @param {Number} [duration] Time (in seconds)\r\n * @param {Function} [callback] The name of a function that will be\r\n * called once the recording completes\r\n */\r\n p5.SoundRecorder.prototype.record = function(sFile, duration, callback) {\r\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\r\n\r\n if (sFile && callback) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n callback();\r\n };\r\n }\r\n else if (sFile) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Stop the recording. Once the recording is stopped,\r\n * the results will be sent to the p5.SoundFile that\r\n * was given on .record(), and if a callback function\r\n * was provided on record, that function will be called.\r\n *\r\n * @method stop\r\n * @for p5.SoundRecorder\r\n */\r\n p5.SoundRecorder.prototype.stop = function() {\r\n this._workletNode.port.postMessage({ name: 'stop' });\r\n };\r\n\r\n p5.SoundRecorder.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this._callback = function() {};\r\n if (this.input) {\r\n this.input.disconnect();\r\n }\r\n this.input = null;\r\n this._workletNode = null;\r\n };\r\n\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device.\r\n * For uploading audio to a server, use\r\n * `p5.SoundFile.saveBlob`.\r\n *\r\n * @for p5\r\n * @method saveSound\r\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\r\n * @param {String} fileName name of the resulting .wav file.\r\n */\r\n // add to p5.prototype as this is used by the p5 `save()` method.\r\n p5.prototype.saveSound = function (soundFile, fileName) {\r\n const dataView = convertToWav(soundFile.buffer);\r\n p5.prototype.writeFile([dataView], fileName, 'wav');\r\n };\r\n});\r\n","module.exports = {\r\n recorderProcessor: 'recorder-processor'\r\n};\r\n","'use strict';\r\n\r\ndefine(function () {\r\n /**\r\n *
PeakDetect works in conjunction with p5.FFT to\r\n * look for onsets in some or all of the frequency spectrum.\r\n *
\r\n *
\r\n * To use p5.PeakDetect, call update in the draw loop\r\n * and pass in a p5.FFT object.\r\n *
\r\n *
\r\n * You can listen for a specific part of the frequency spectrum by\r\n * setting the range between freq1 and freq2.\r\n *
\r\n *\r\n *
threshold is the threshold for detecting a peak,\r\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\r\n * as 1.0.
\r\n *\r\n *
\r\n * The update method is meant to be run in the draw loop, and\r\n * frames determines how many loops must pass before\r\n * another peak can be detected.\r\n * For example, if the frameRate() = 60, you could detect the beat of a\r\n * 120 beat-per-minute song with this equation:\r\n * framesPerPeak = 60 / (estimatedBPM / 60 );\r\n *
\r\n *\r\n *
\r\n * Based on example contribtued by @b2renger, and a simple beat detection\r\n * explanation by Felix Turner.\r\n *
\r\n *\r\n * @class p5.PeakDetect\r\n * @constructor\r\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\r\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\r\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\r\n * scaled logarithmically where 0.1 is 1/2 the loudness\r\n * of 1.0. Defaults to 0.35.\r\n * @param {Number} [framesPerPeak] Defaults to 20.\r\n * @example\r\n *
\r\n */\r\n p5.PeakDetect = function(freq1, freq2, threshold, _framesPerPeak) {\r\n // framesPerPeak determines how often to look for a beat.\r\n // If a beat is provided, try to look for a beat based on bpm\r\n this.framesPerPeak = _framesPerPeak || 20;\r\n this.framesSinceLastPeak = 0;\r\n this.decayRate = 0.95;\r\n\r\n this.threshold = threshold || 0.35;\r\n this.cutoff = 0;\r\n\r\n // how much to increase the cutoff\r\n // TO DO: document this / figure out how to make it accessible\r\n this.cutoffMult = 1.5;\r\n\r\n this.energy = 0;\r\n this.penergy = 0;\r\n\r\n // TO DO: document this property / figure out how to make it accessible\r\n this.currentValue = 0;\r\n\r\n /**\r\n * isDetected is set to true when a peak is detected.\r\n *\r\n * @attribute isDetected {Boolean}\r\n * @default false\r\n */\r\n this.isDetected = false;\r\n\r\n this.f1 = freq1 || 40;\r\n this.f2 = freq2 || 20000;\r\n\r\n // function to call when a peak is detected\r\n this._onPeak = function() {};\r\n };\r\n\r\n\r\n /**\r\n * The update method is run in the draw loop.\r\n *\r\n * Accepts an FFT object. You must call .analyze()\r\n * on the FFT object prior to updating the peakDetect\r\n * because it relies on a completed FFT analysis.\r\n *\r\n * @method update\r\n * @param {p5.FFT} fftObject A p5.FFT object\r\n */\r\n p5.PeakDetect.prototype.update = function(fftObject) {\r\n var nrg = this.energy = fftObject.getEnergy(this.f1,this.f2)/255;\r\n if (nrg > this.cutoff && nrg > this.threshold && nrg-this.penergy > 0) {\r\n\r\n // trigger callback\r\n this._onPeak();\r\n this.isDetected = true;\r\n\r\n // debounce\r\n this.cutoff = nrg * this.cutoffMult;\r\n this.framesSinceLastPeak = 0;\r\n } else {\r\n this.isDetected = false;\r\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\r\n this.framesSinceLastPeak++;\r\n } else {\r\n this.cutoff *= this.decayRate;\r\n this.cutoff = Math.max(this.cutoff, this.threshold);\r\n }\r\n }\r\n\r\n this.currentValue = nrg;\r\n this.penergy = nrg;\r\n };\r\n\r\n /**\r\n * onPeak accepts two arguments: a function to call when\r\n * a peak is detected. The value of the peak,\r\n * between 0.0 and 1.0, is passed to the callback.\r\n *\r\n * @method onPeak\r\n * @param {Function} callback Name of a function that will\r\n * be called when a peak is\r\n * detected.\r\n * @param {Object} [val] Optional value to pass\r\n * into the function when\r\n * a peak is detected.\r\n * @example\r\n *
\r\n * var cnv, soundFile, fft, peakDetect;\r\n * var ellipseWidth = 0;\r\n *\r\n * function preload() {\r\n * soundFile = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * textAlign(CENTER);\r\n *\r\n * fft = new p5.FFT();\r\n * peakDetect = new p5.PeakDetect();\r\n *\r\n * setupSound();\r\n *\r\n * // when a beat is detected, call triggerBeat()\r\n * peakDetect.onPeak(triggerBeat);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * fft.analyze();\r\n * peakDetect.update(fft);\r\n *\r\n * ellipseWidth *= 0.95;\r\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\r\n * }\r\n *\r\n * // this function is called by peakDetect.onPeak\r\n * function triggerBeat() {\r\n * ellipseWidth = 50;\r\n * }\r\n *\r\n * // mouseclick starts/stops sound\r\n * function setupSound() {\r\n * cnv.mouseClicked( function() {\r\n * if (soundFile.isPlaying() ) {\r\n * soundFile.stop();\r\n * } else {\r\n * soundFile.play();\r\n * }\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.PeakDetect.prototype.onPeak = function(callback, val) {\r\n var self = this;\r\n\r\n self._onPeak = function() {\r\n callback(self.energy, val);\r\n };\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * A gain node is usefull to set the relative volume of sound.\r\n * It's typically used to build mixers.\r\n *\r\n * @class p5.Gain\r\n * @constructor\r\n * @example\r\n *
\r\n *\r\n * // load two soundfile and crossfade beetween them\r\n * var sound1,sound2;\r\n * var gain1, gain2, gain3;\r\n *\r\n * function preload(){\r\n * soundFormats('ogg', 'mp3');\r\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\r\n * sound2 = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * createCanvas(400,200);\r\n *\r\n * // create a 'master' gain to which we will connect both soundfiles\r\n * gain3 = new p5.Gain();\r\n * gain3.connect();\r\n *\r\n * // setup first sound for playing\r\n * sound1.rate(1);\r\n * sound1.loop();\r\n * sound1.disconnect(); // diconnect from p5 output\r\n *\r\n * gain1 = new p5.Gain(); // setup a gain node\r\n * gain1.setInput(sound1); // connect the first sound to its input\r\n * gain1.connect(gain3); // connect its output to the 'master'\r\n *\r\n * sound2.rate(1);\r\n * sound2.disconnect();\r\n * sound2.loop();\r\n *\r\n * gain2 = new p5.Gain();\r\n * gain2.setInput(sound2);\r\n * gain2.connect(gain3);\r\n *\r\n * }\r\n *\r\n * function draw(){\r\n * background(180);\r\n *\r\n * // calculate the horizontal distance beetween the mouse and the right of the screen\r\n * var d = dist(mouseX,0,width,0);\r\n *\r\n * // map the horizontal position of the mouse to values useable for volume control of sound1\r\n * var vol1 = map(mouseX,0,width,0,1);\r\n * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa\r\n *\r\n * gain1.amp(vol1,0.5,0);\r\n * gain2.amp(vol2,0.5,0);\r\n *\r\n * // map the vertical position of the mouse to values useable for 'master volume control'\r\n * var vol3 = map(mouseY,0,height,0,1);\r\n * gain3.amp(vol3,0.5,0);\r\n * }\r\n *
\r\n *\r\n */\r\n\r\n p5.Gain = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n this.input.connect(this.output);\r\n\r\n // add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a source to the gain node.\r\n *\r\n * @method setInput\r\n * @for p5.Gain\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n */\r\n\r\n\r\n p5.Gain.prototype.setInput = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Gain\r\n * @param {Object} unit\r\n */\r\n p5.Gain.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Gain\r\n */\r\n p5.Gain.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Set the output level of the gain node.\r\n *\r\n * @method amp\r\n * @for p5.Gain\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Gain.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n };\r\n\r\n p5.Gain.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n\r\n /*\r\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n */\r\n function makeDistortionCurve(amount) {\r\n var k = typeof amount === 'number' ? amount : 50;\r\n var numSamples = 44100;\r\n var curve = new Float32Array(numSamples);\r\n var deg = Math.PI / 180;\r\n var i = 0;\r\n var x;\r\n for ( ; i < numSamples; ++i ) {\r\n x = i * 2 / numSamples - 1;\r\n curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );\r\n }\r\n return curve;\r\n }\r\n\r\n /**\r\n * A Distortion effect created with a Waveshaper Node,\r\n * with an approach adapted from\r\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Distortion\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n *\r\n */\r\n p5.Distortion = function(amount, oversample) {\r\n Effect.call(this);\r\n\r\n if (typeof amount === 'undefined') {\r\n amount = 0.25;\r\n } if (typeof amount !== 'number') {\r\n throw new Error('amount must be a number');\r\n } if (typeof oversample === 'undefined') {\r\n oversample = '2x';\r\n } if (typeof oversample !== 'string') {\r\n throw new Error('oversample must be a String');\r\n }\r\n\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n\r\n /**\r\n * The p5.Distortion is built with a\r\n * \r\n * Web Audio WaveShaper Node.\r\n *\r\n * @property {AudioNode} WaveShaperNode\r\n */\r\n this.waveShaperNode = this.ac.createWaveShaper();\r\n\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n this.waveShaperNode.oversample = oversample;\r\n\r\n this.input.connect(this.waveShaperNode);\r\n\r\n this.waveShaperNode.connect(this.wet);\r\n };\r\n\r\n p5.Distortion.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Process a sound source, optionally specify amount and oversample values.\r\n *\r\n * @method process\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.process = function(src, amount, oversample) {\r\n src.connect(this.input);\r\n this.set(amount, oversample);\r\n };\r\n\r\n /**\r\n * Set the amount and oversample of the waveshaper distortion.\r\n *\r\n * @method set\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.set = function(amount, oversample) {\r\n if (amount) {\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n }\r\n if (oversample) {\r\n this.waveShaperNode.oversample = oversample;\r\n }\r\n };\r\n\r\n /**\r\n * Return the distortion amount, typically between 0-1.\r\n *\r\n * @method getAmount\r\n * @for p5.Distortion\r\n * @return {Number} Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n */\r\n p5.Distortion.prototype.getAmount = function() {\r\n return this.amount;\r\n };\r\n\r\n /**\r\n * Return the oversampling.\r\n *\r\n * @method getOversample\r\n * @for p5.Distortion\r\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.getOversample = function() {\r\n return this.waveShaperNode.oversample;\r\n };\r\n\r\n\r\n p5.Distortion.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.waveShaperNode) {\r\n this.waveShaperNode.disconnect();\r\n this.waveShaperNode = null;\r\n }\r\n };\r\n});\r\n"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///../node_modules/tone/Tone/core/Tone.js","webpack:///./master.js","webpack:///../node_modules/tone/Tone/signal/Signal.js","webpack:///../node_modules/tone/Tone/signal/Multiply.js","webpack:///./effect.js","webpack:///../node_modules/tone/Tone/signal/WaveShaper.js","webpack:///./helpers.js","webpack:///../node_modules/tone/Tone/signal/Add.js","webpack:///../node_modules/tone/Tone/type/Type.js","webpack:///../node_modules/tone/Tone/core/Gain.js","webpack:///./errorHandler.js","webpack:///../node_modules/tone/Tone/core/Context.js","webpack:///../node_modules/tone/Tone/signal/Scale.js","webpack:///../node_modules/tone/Tone/signal/TimelineSignal.js","webpack:///./filter.js","webpack:///../node_modules/tone/Tone/signal/Subtract.js","webpack:///./audiocontext.js","webpack:///../node_modules/tone/Tone/core/Emitter.js","webpack:///./audioWorklet/processorNames.js","webpack:///../node_modules/tone/Tone/signal/SignalBase.js","webpack:///../node_modules/tone/Tone/type/Time.js","webpack:///../node_modules/tone/Tone/type/TimeBase.js","webpack:///../node_modules/tone/Tone/core/Param.js","webpack:///./oscillator.js","webpack:///../node_modules/tone/Tone/core/Timeline.js","webpack:///../node_modules/tone/Tone/signal/Negate.js","webpack:///../node_modules/tone/Tone/signal/GreaterThanZero.js","webpack:///../node_modules/tone/Tone/core/Clock.js","webpack:///./monosynth.js","webpack:///./audioVoice.js","webpack:///./polysynth.js","webpack:///./app.js","webpack:///../node_modules/audioworklet-polyfill/dist/audioworklet-polyfill.js","webpack:///./shims.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///../node_modules/startaudiocontext/StartAudioContext.js","webpack:///./audioWorklet/index.js","webpack:///./audioWorklet/recorderProcessor.js","webpack:///./audioWorklet/soundFileProcessor.js","webpack:///./panner.js","webpack:///./soundfile.js","webpack:///./amplitude.js","webpack:///./fft.js","webpack:///./signal.js","webpack:///../node_modules/tone/Tone/type/Frequency.js","webpack:///../node_modules/tone/Tone/type/TransportTime.js","webpack:///./envelope.js","webpack:///./pulse.js","webpack:///./noise.js","webpack:///./audioin.js","webpack:///../node_modules/tone/Tone/component/CrossFade.js","webpack:///../node_modules/tone/Tone/signal/Expr.js","webpack:///../node_modules/tone/Tone/signal/GreaterThan.js","webpack:///../node_modules/tone/Tone/signal/Abs.js","webpack:///../node_modules/tone/Tone/signal/Modulo.js","webpack:///../node_modules/tone/Tone/signal/Pow.js","webpack:///../node_modules/tone/Tone/signal/AudioToGain.js","webpack:///../node_modules/tone/Tone/signal/EqualPowerGain.js","webpack:///./eq.js","webpack:///./eqFilter.js","webpack:///./panner3d.js","webpack:///./listener3d.js","webpack:///./delay.js","webpack:///./reverb.js","webpack:///./metro.js","webpack:///../node_modules/tone/Tone/core/TimelineState.js","webpack:///./looper.js","webpack:///./soundLoop.js","webpack:///./compressor.js","webpack:///./soundRecorder.js","webpack:///./peakDetect.js","webpack:///./gain.js","webpack:///./distortion.js","webpack:///./audioWorklet/amplitudeProcessor.js"],"names":["define","Tone","inputs","outputs","this","isUndef","input","context","createGain","Array","output","audioContext","prototype","set","params","value","rampTime","isObject","isString","tmpObj","paramLoop","attr","parent","indexOf","attrSplit","split","i","length","splice","innerParam","join","param","Signal","Param","rampTo","AudioParam","get","_collectDefaults","constructor","ret","subRet","j","subAttr","isFunction","constr","defaults","Object","keys","_super","superDefs","push","toString","className","isLetter","match","sameConstructor","defineProperty","isArray","dispose","AudioNode","disconnect","connect","unit","outputNum","inputNum","defaultArg","destination","isNumber","apply","arguments","connectSeries","currentUnit","toUnit","chain","fan","given","fallback","givenProp","fallbackProp","optionsObject","values","options","val","arg","call","isBoolean","noOp","_readOnly","property","writable","enumerable","_writable","State","Started","Stopped","Paused","equalPowerScale","percent","piFactor","Math","PI","sin","dbToGain","db","pow","gainToDb","gain","log","LN10","intervalToFrequencyRatio","interval","now","extend","child","TempConstructor","Context","emit","setContext","ctx","sampleRate","hasAudioContext","window","hasOwnProperty","hasPromises","hasWorkers","version","TONE_SILENCE_VERSION_LOGGING","console","audiocontext","Master","limiter","createDynamicsCompressor","threshold","ratio","knee","meter","fftMeter","soundArray","parts","extensions","p5sound","p5","getMasterVolume","masterVolume","vol","tFromNow","currentTime","currentVol","cancelScheduledValues","linearRampToValueAtTime","soundOut","_silentNode","_gain","_param","getConstant","units","Type","Default","convert","SignalBase","Multiply","createInsOuts","_mult","Gain","require","CrossFade","Effect","ac","_drywet","wet","a","b","amp","drywet","fade","u","index","undefined","WaveShaper","mapping","bufferLen","_shaper","createWaveShaper","_curve","curve","isFinite","Float32Array","setMap","len","normalized","oversample","oversampling","RangeError","freqToMidi","f","mathlog2","m","round","midiToFreq","noteToFreq","note","wholeNotes","A","B","C","D","E","F","G","toUpperCase","octave","slice","soundFormats","toLowerCase","disposeSound","registerMethod","_checkFileFormats","paths","path","extTest","pop","isFileSupported","pathSplit","pathCore","extension","supported","p","_mathChain","o","math","thisChain","nextChain","type","mathOps","convertToWav","audioBuffer","leftChannel","rightChannel","getChannelData","numberOfChannels","interleaved","interleave","buffer","ArrayBuffer","view","DataView","writeUTFBytes","setUint32","setUint16","lng","volume","setInt16","result","inputIndex","offset","string","setUint8","charCodeAt","Add","_sum","Time","Frequency","TransportTime","Ticks","NormalRange","AudioRange","Decibels","Interval","BPM","Positive","Cents","Degrees","MIDI","BarsBeatsSixteenths","Samples","Hertz","Note","Milliseconds","Seconds","Notation","toSeconds","time","TimeBase","toFrequency","freq","valueOf","toTicks","Transport","ticks","GainNode","AudioContext","createGainNode","_gainNode","CustomError","name","errorTrace","failedPath","err","Error","tempStack","splitStack","originalStack","stack","filter","ln","toneConnect","outNum","inNum","nativeConnect","e","nativeDisconnect","webkitAudioContext","prop","Emitter","_context","_defineProperty","_latencyHint","_lookAhead","_updateInterval","_computedUpdateInterval","_worker","_createWorker","_constants","mixin","bind","URL","webkitURL","blob","Blob","toFixed","blobUrl","createObjectURL","worker","Worker","addEventListener","_lastUpdate","diff","max","createBuffer","arr","constant","createBufferSource","channelCount","channelCountMode","loop","start","lA","blockTime","postMessage","hint","lookAhead","latencyHint","updateInterval","warn","Scale","outputMin","outputMax","_outputMin","_outputMax","_scale","_add","_setRange","min","TimelineSignal","_events","Timeline","_initial","_fromUnits","Linear","Exponential","Target","Curve","Set","getValueAtTime","_toUnits","convertedVal","setValueAtTime","startTime","add","endTime","exponentialRampToValueAtTime","beforeEvent","_searchBefore","_minOutput","setValue","sampleTime","setTargetAtTime","timeConstant","setValueCurveAtTime","duration","scaling","floats","segmentTime","after","cancel","setRampPoint","before","_searchAfter","linearRampToValueBetween","finish","exponentialRampToValueBetween","getAfter","previouVal","previous","getBefore","_exponentialApproach","_curveInterpolate","_linearInterpolate","_exponentialInterpolate","t0","v0","v1","t","exp","t1","progress","lowerIndex","floor","upperIndex","ceil","lowerVal","upperVal","Filter","biquad","createBiquadFilter","setType","_on","_untoggledType","create","process","src","res","frequency","Q","toggle","LowPass","HighPass","BandPass","Subtract","_neg","Negate","global","StartAudioContext","getAudioContext","userStartAudio","elements","callback","elt","Element","map","on","event","events","eventName","off","ev","eventList","args","object","functions","func","emitterFunc","module","exports","recorderProcessor","soundFileProcessor","amplitudeProcessor","node","outputNumber","inputNumber","overridden","_plusNow","_unaryExpressions","quantize","regexp","method","rh","nextSubdivision","lh","subdiv","_expr","expr","subdivision","addNow","_defaultExpr","_noOp","copy","toNotation","retNotation","_toNotationHelper","retTripletNotation","testNotations","_notationToUnits","notationTime","multiple","notation","primaryExprs","_primaryExpressions","notationExprs","n","toBarsBeatsSixteenths","quarterTime","_beatsToUnits","quarters","measures","_timeSignature","sixteenths","parseFloat","PPQ","toSamples","toMilliseconds","_defaultUnits","exprString","_parseExprString","clone","instance","parseInt","_ticksToUnits","hz","_frequencyToUnits","tr","q","s","total","_secondsToUnits","samples","default","_binaryExpressions","+","precedence","-","*","/","neg","_syntaxGlue","(",")","_tokenize","position","tokens","token","getNextToken","trim","substr","expressions","group","opName","op","reg","SyntaxError","next","peek","_matchGroup","prec","test","_parseBinary","lexer","_parseUnary","_parsePrimary","matching","beats","bpm","seconds","timeSignature","_pushExpr","sub","mult","div","_lfo","lfo","LFO","currentVal","exponentialRampToValue","linearRampToValue","Mult","Oscillator","started","phaseAmount","oscillator","createOscillator","_freqMods","panPosition","connection","panner","Panner","stop","abs","freqNode","self","getAmp","isNaN","phase","getFreq","getType","oscMods","pan","pval","getPan","osc2","delayAmt","dNode","createDelay","delayTime","sigChain","mathObj","chainSource","num","scale","inMin","inMax","outMin","outMax","mapOutMin","mapOutMax","SinOsc","TriOsc","SawOsc","SqrOsc","_timeline","_toRemove","_iterating","memory","Infinity","_search","remove","shift","cancelBefore","beginning","end","midPoint","nextEvent","_iterate","lowerBound","upperBound","forEach","forEachBefore","forEachAfter","forEachFrom","forEachAtTime","_multiply","GreaterThanZero","_thresh","Clock","_nextTick","_lastState","_state","TimelineState","_boundLoop","_loop","state","setStateAtTime","pause","loopInterval","lag","currentState","tickTime","getStateAtTime","AudioVoice","DEFAULT_SUSTAIN","MonoSynth","env","Envelope","setRange","setExp","setADSR","setInput","play","velocity","secondsFromNow","susTime","triggerAttack","triggerRelease","vel","ramp","attack","decay","sustain","release","defineProperties","aTime","dTime","sPercent","rTime","sustime","PolySynth","audioVoice","maxVoices","audiovoices","notes","_newest","_oldest","_voicesInUse","_allocateVoices","noteAttack","noteRelease","noteADSR","d","r","timeFromNow","voice","_note","_velocity","acTime","currentVoice","oldestNote","previousVal","_updateAfter","maxRange","nextTime","p5SOUND","fixSetTarget","setTargetValueAtTime","createDelayNode","createScriptProcessor","createJavaScriptNode","createPeriodicWave","createWaveTable","internal_createGain","internal_createDelay","maxDelayTime","internal_createBufferSource","when","noteGrainOn","noteOn","internal_start","noteOff","internal_stop","playbackRate","internal_createDynamicsCompressor","reduction","internal_createBiquadFilter","detune","internal_createOscillator","setPeriodicWave","setWaveTable","OfflineAudioContext","webkitOfflineAudioContext","navigator","getUserMedia","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","el","document","createElement","isSupported","canPlayType","isOGGSupported","isMP3Supported","isWAVSupported","isAACSupported","isAIFSupported","moduleSources","loadAudioWorkletModules","Promise","all","moduleSrc","objectURL","audioWorklet","addModule","preload","_preloadCount","onWorkletModulesLoad","_decrementPreload","then","createStereoPanner","stereoPanner","inputChannels","obj","numInputChannels","left","right","channelInterpretation","splitter","createChannelSplitter","createChannelMerger","v","rightVal","cos","leftVal","numChannels","processorNames","SoundFile","onload","onerror","whileLoading","url","File","FileReader","FileList","file","_onended","_looping","_playing","_paused","_pauseTime","_cues","_cueIDCounter","_lastPos","_counterNode","_workletNode","bufferSourceNodes","bufferSourceNode","reversed","pauseTime","mode","startMillis","load","_whileLoading","_onAudioProcess","_clearOnEnd","registerPreloadMethod","loadSound","location","origin","cordova","alert","errorCallback","request","XMLHttpRequest","evt","_updateProgress","open","responseType","status","decodeAudioData","response","buff","msg","error","statusText","message","send","reader","readAsArrayBuffer","lengthComputable","percentComplete","loaded","isLoaded","rate","_cueStart","cueStart","cueEnd","setVolume","isPlaying","_initSourceNode","_initCounterNode","_arrayIndex","loopStart","loopEnd","playMode","str","pTime","setLoop","bool","isLooping","isPaused","stopAll","_time","_rampTime","_tFromNow","getVolume","reverse","reverseBuffer","setPitch","newPlaybackRate","getPlaybackRate","jump","cueTime","cTime","dur","channels","frames","getPeaks","width","sampleSize","sampleStep","peaks","c","chan","currentPos","curVol","onended","warning","getLevel","setPath","setBuffer","buf","size","newBuffer","channelNum","channel","_createCounterBuffer","audioBuf","arrayBuffer","cNode","AudioWorkletNode","port","onmessage","data","_onTimeUpdate","processPeaks","_initThreshold","_minThreshold","_minPeaks","bufLen","allPeaks","initialThreshold","minThreshold","minPeaks","offlineContext","source","startRendering","oncomplete","filteredBuffer","renderedBuffer","bufferData","getPeaksAtThreshold","intervalCounts","countIntervalsBetweenNearbyPeaks","groups","groupNeighborsByTempo","topTempos","sort","intA","intB","count","tempo","bpmVariance","tempoPeaks","getPeaksAtTopTempo","Peak","sampleIndex","amplitude","tempos","intervals","peaksObj","peak","peaksArray","startPeak","endPeak","startPos","endPos","foundInterval","some","intervalCount","tempoCounts","theoreticalTempo","mapTempo","foundTempo","tempoCount","peaksAtTopTempo","key","intervalBPM","peakTime","dif","Cue","id","addCue","cue","removeCue","cueLength","clearCues","playbackTime","callbackTime","_prevTime","save","fileName","dataView","saveSound","getBlob","processEvent","inputBuffer","thisBufferSourceNode","target","soundFile","removeEventListener","Amplitude","smoothing","bufferSize","outputChannelCount","parameterData","processorOptions","normalize","volNorm","stereoVol","stereoVolNorm","parameters","toggleNormalize","smooth","FFT","bins","analyser","createAnalyser","fftSize","configurable","smoothingTimeConstant","freqDomain","Uint8Array","frequencyBinCount","timeDomain","bass","lowMid","mid","highMid","treble","waveform","normalArray","_isSafari","timeToFloat","getFloatTimeDomainData","timeToInt","getByteTimeDomainData","scaled","analyze","freqToFloat","getFloatFrequencyData","freqToInt","getByteFrequencyData","getEnergy","frequency1","frequency2","nyquist","swap","lowIndex","highIndex","numFrequencies","toReturn","freq1","freq2","x","getCentroid","cumulative_sum","centroid_normalization","mean_freq_index","spec_centroid_freq","linAverages","N","spectrum","spectrumLength","spectrumStep","linearAverages","groupIndex","specIndex","logAverages","octaveBands","octaveIndex","specIndexFrequency","hi","getOctaveBands","fCtr0","lastFrequencyBand","lo","ctr","newFrequencyBand","fft","_input","midi","midiToFrequency","pitch","noteNumber","noteToScaleIndex","transpose","harmonize","toMidi","frequencyToMidi","toNote","A4","LN2","scaleIndexToNote","cbb","cb","c#","cx","dbb","d#","dx","ebb","eb","e#","ex","fbb","fb","f#","fx","gbb","gb","g","g#","gx","abb","ab","a#","ax","bbb","bb","b#","bx","_secondsToTicks","l1","t2","l2","t3","l3","aLevel","dLevel","rLevel","_rampHighPercentage","_rampLowPercentage","control","_init","isExponential","sourceToClear","wasTriggered","_setRampAD","_rampAttackTime","checkExpInput","_rampDecayTime","TCDenominator","_rampAttackTC","_rampDecayTC","setRampPercentages","p1","p2","isExp","lastAttack","valToSet","v2","destination1","destination2","AudioIn","Reverb","Noise","Delay","Env","Pulse","w","dcOffset","createDCOffset","dcGain","mW","sig","SignalAdd","mods","currentFreq","freqMod","bufferSource","assignType","_brownNoise","_pinkNoise","_whiteNoise","whiteBuffer","noiseData","random","pinkBuffer","b0","b1","b2","b3","b4","b5","b6","white","brownBuffer","lastOut","noise","inputSources","stream","mediaStream","currentSource","enabled","MediaStreamTrack","mediaDevices","successCallback","audioSource","constraints","audio","echoCancellation","deviceId","createMediaStreamSource","getTracks","track","getSources","onSuccess","onError","resolve","reject","enumerateDevices","devices","device","kind","setSource","active","initialFade","_equalPowerA","EqualPowerGain","_equalPowerB","_invert","Expr","applyBinary","Constructor","_eval","applyUnary","getNumber","literalNumber","_replacements","inputCount","_parseInputs","_nodes","tree","_parseTree","_disposeNodes","_Expressions","signal","glue",",","Abs","mod","modulus","Modulo","Pow","a2g","AudioToGain","binary","unary","!","NOT","inputArray","inputMax","replace","matchSyntax","syn","matchGroup","groupName","parseExpression","parseUnary","operator","parsePrimary","parseArgumentList","parseFunctionCall","GreaterThan","_gtz","_abs","_subtract","_modSignal","_setWaveShaper","_exp","_expScaler","_expFunc","_norm","_eqPower","EQFilter","EQ","_eqsize","factor","bands","_newBand","Panner3D","createPanner","panningModel","distanceModel","xVal","yVal","zVal","positionX","positionY","positionZ","orient","orientX","orientY","orientZ","orientationX","orientationY","orientationZ","setFalloff","maxDistance","rolloffFactor","maxDist","rolloff","Listener3D","listener","xValF","yValF","zValF","xValU","yValU","zValU","orientForward","orientUp","forwardX","forwardY","forwardZ","upX","upY","upZ","_split","_merge","_leftGain","_rightGain","leftDelay","rightDelay","_leftFilter","_rightFilter","_maxDelay","maxValue","feedback","_delayTime","_feedback","_filter","_initConvolverNode","_seconds","_decay","_reverse","_buildImpulse","convolverNode","createConvolver","_teardownConvolverNode","_setBuffer","decayRate","rebuild","impulse","impulseL","impulseR","Convolver","impulses","_loadBuffer","cReverb","chunks","addImpulse","resetImpulse","toggleImpulse","Metro","clock","ontick","syncedParts","prevTick","tatumTime","tickCallback","elapsedTime","thisPart","incrementStep","phrases","thisPhrase","phraseArray","sequence","bNum","metroTicks","looping","setBPM","beatTime","tatums","getBPM","getRate","resetSync","part","pushSync","beatLength","initial","Phrase","phraseStep","Part","steps","bLength","partStep","noLoop","metro","addPhrase","array","removePhrase","getPhrase","replaceSequence","onStep","Score","currentPart","thisScore","nextPart","resetPart","playNextPart","resetParts","scoreStep","aScore","SoundLoop","musicalTimeMode","_interval","_bpm","maxIterations","iterations","_calcFreq","syncedStart","otherLoop","_update","_convertNotation","Number","_measure","timeSig","Compressor","compressor","number","SoundRecorder","_inputChannels","_outputChannels","buffers","leftBuffer","rightBuffer","_callback","record","sFile","writeFile","PeakDetect","_framesPerPeak","framesPerPeak","framesSinceLastPeak","cutoff","cutoffMult","energy","penergy","currentValue","isDetected","f1","f2","_onPeak","update","fftObject","nrg","onPeak","makeDistortionCurve","amount","k","numSamples","deg","Distortion","curveAmount","waveShaperNode","getAmount","getOversample"],"mappings":"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;;AAED;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;;AAEA;AACA;AACA,4CAA4C;;AAE5C;;;;;;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,IAA0C;AAC/C,EAAE,iCAAO,EAAE,oCAAE,OAAO;AAAA;AAAA;AAAA,oGAAC;AACrB,GAAG,MAAM,EAIN;AACH,CAAC;;AAED;;AAEA;AACA;AACA,YAAY,QAAQ;AACpB;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,YAAY,aAAa;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,SAAS;AACtB;AACA;;AAEA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;AACA;;AAEA;AACA;AACA,aAAa,4BAA4B;AACzC,YAAY,MAAM;AAClB;AACA;AACA;AACA,kBAAkB,oBAAoB;AACtC;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;AACA;AACA,G;AACA;;AAEA;AACA,YAAY,aAAa;AACzB,YAAY,6BAA6B;AACzC;AACA;AACA;AACA;AACA,YAAY,UAAU;AACtB,aAAa,QAAQ;AACrB;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kBAAkB,yBAAyB;AAC3C;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA,CAAC,E;;;;;;A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","file":"p5.sound.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 31);\n","/**\n * Tone.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2014-2017 Yotam Mann\n */\ndefine(function(){\n\n\t\"use strict\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTONE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * @class Tone is the base class of all other classes. It provides \n\t * a lot of methods and functionality to all classes that extend\n\t * it. \n\t * \n\t * @constructor\n\t * @alias Tone\n\t * @param {number} [inputs=1] the number of input nodes\n\t * @param {number} [outputs=1] the number of output nodes\n\t */\n\tvar Tone = function(inputs, outputs){\n\n\t\t/**\n\t\t * the input node(s)\n\t\t * @type {GainNode|Array}\n\t\t */\n\t\tif (this.isUndef(inputs) || inputs === 1){\n\t\t\tthis.input = this.context.createGain();\n\t\t} else if (inputs > 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\t/**\n\t\t * the output node(s)\n\t\t * @type {GainNode|Array}\n\t\t */\n\t\tif (this.isUndef(outputs) || outputs === 1){\n\t\t\tthis.output = this.context.createGain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t/**\n\t * Set the parameters at once. Either pass in an\n\t * object mapping parameters to values, or to set a\n\t * single parameter, by passing in a string and value.\n\t * The last argument is an optional ramp time which \n\t * will ramp any signal values to their destination value\n\t * over the duration of the rampTime.\n\t * @param {Object|string} params\n\t * @param {number=} value\n\t * @param {Time=} rampTime\n\t * @returns {Tone} this\n\t * @example\n\t * //set values using an object\n\t * filter.set({\n\t * \t\"frequency\" : 300,\n\t * \t\"type\" : highpass\n\t * });\n\t * @example\n\t * filter.set(\"type\", \"highpass\");\n\t * @example\n\t * //ramp to the value 220 over 3 seconds. \n\t * oscillator.set({\n\t * \t\"frequency\" : 220\n\t * }, 3);\n\t */\n\tTone.prototype.set = function(params, value, rampTime){\n\t\tif (this.isObject(params)){\n\t\t\trampTime = value;\n\t\t} else if (this.isString(params)){\n\t\t\tvar tmpObj = {};\n\t\t\ttmpObj[params] = value;\n\t\t\tparams = tmpObj;\n\t\t}\n\n\t\tparamLoop:\n\t\tfor (var attr in params){\n\t\t\tvalue = params[attr];\n\t\t\tvar parent = this;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var i = 0; i < attrSplit.length - 1; i++){\n\t\t\t\t\tparent = parent[attrSplit[i]];\n\t\t\t\t\tif (parent instanceof Tone) {\n\t\t\t\t\t\tattrSplit.splice(0,i+1);\n\t\t\t\t\t\tvar innerParam = attrSplit.join(\".\");\n\t\t\t\t\t\tparent.set(innerParam, value);\n\t\t\t\t\t\tcontinue paramLoop;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isUndef(param)){\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((Tone.Signal && param instanceof Tone.Signal) || \n\t\t\t\t\t(Tone.Param && param instanceof Tone.Param)){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tif (this.isUndef(rampTime)){\n\t\t\t\t\t\tparam.value = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparam.rampTo(value, rampTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tparam.value = value;\n\t\t\t\t}\t\t\t\t\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tparam.set(value);\n\t\t\t} else if (param !== value){\n\t\t\t\tparent[attr] = value;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the object's attributes. Given no arguments get\n\t * will return all available object properties and their corresponding\n\t * values. Pass in a single attribute to retrieve or an array\n\t * of attributes. The attribute strings can also include a \".\"\n\t * to access deeper properties.\n\t * @example\n\t * osc.get();\n\t * //returns {\"type\" : \"sine\", \"frequency\" : 440, ...etc}\n\t * @example\n\t * osc.get(\"type\");\n\t * //returns { \"type\" : \"sine\"}\n\t * @example\n\t * //use dot notation to access deep properties\n\t * synth.get([\"envelope.attack\", \"envelope.release\"]);\n\t * //returns {\"envelope\" : {\"attack\" : 0.2, \"release\" : 0.4}}\n\t * @param {Array=|string|undefined} params the parameters to get, otherwise will return \n\t * \t\t\t\t\t all available.\n\t * @returns {Object}\n\t */\n\tTone.prototype.get = function(params){\n\t\tif (this.isUndef(params)){\n\t\t\tparams = this._collectDefaults(this.constructor);\n\t\t} else if (this.isString(params)){\n\t\t\tparams = [params];\n\t\t} \n\t\tvar ret = {};\n\t\tfor (var i = 0; i < params.length; i++){\n\t\t\tvar attr = params[i];\n\t\t\tvar parent = this;\n\t\t\tvar subRet = ret;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var j = 0; j < attrSplit.length - 1; j++){\n\t\t\t\t\tvar subAttr = attrSplit[j];\n\t\t\t\t\tsubRet[subAttr] = subRet[subAttr] || {};\n\t\t\t\t\tsubRet = subRet[subAttr];\n\t\t\t\t\tparent = parent[subAttr];\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isObject(params[attr])){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (Tone.Signal && param instanceof Tone.Signal){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (Tone.Param && param instanceof Tone.Param){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (!this.isFunction(param) && !this.isUndef(param)){\n\t\t\t\tsubRet[attr] = param;\n\t\t\t} \n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * collect all of the default attributes in one\n\t * @private\n\t * @param {function} constr the constructor to find the defaults from\n\t * @return {Array} all of the attributes which belong to the class\n\t */\n\tTone.prototype._collectDefaults = function(constr){\n\t\tvar ret = [];\n\t\tif (!this.isUndef(constr.defaults)){\n\t\t\tret = Object.keys(constr.defaults);\n\t\t}\n\t\tif (!this.isUndef(constr._super)){\n\t\t\tvar superDefs = this._collectDefaults(constr._super);\n\t\t\t//filter out repeats\n\t\t\tfor (var i = 0; i < superDefs.length; i++){\n\t\t\t\tif (ret.indexOf(superDefs[i]) === -1){\n\t\t\t\t\tret.push(superDefs[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * @returns {string} returns the name of the class as a string\n\t */\n\tTone.prototype.toString = function(){\n\t\tfor (var className in Tone){\n\t\t\tvar isLetter = className[0].match(/^[A-Z]$/);\n\t\t\tvar sameConstructor = Tone[className] === this.constructor;\n\t\t\tif (this.isFunction(Tone[className]) && isLetter && sameConstructor){\n\t\t\t\treturn className;\n\t\t\t}\n\t\t}\n\t\treturn \"Tone\";\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCLASS VARS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The number of inputs feeding into the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfInputs\", {\n\t\tget : function(){\n\t\t\tif (this.input){\n\t\t\t\tif (this.isArray(this.input)){\n\t\t\t\t\treturn this.input.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The number of outputs coming out of the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfOutputs\", {\n\t\tget : function(){\n\t\t\tif (this.output){\n\t\t\t\tif (this.isArray(this.output)){\n\t\t\t\t\treturn this.output.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\t\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONNECTIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * disconnect and dispose\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.dispose = function(){\n\t\tif (!this.isUndef(this.input)){\n\t\t\tif (this.input instanceof AudioNode){\n\t\t\t\tthis.input.disconnect();\n\t\t\t} \n\t\t\tthis.input = null;\n\t\t}\n\t\tif (!this.isUndef(this.output)){\n\t\t\tif (this.output instanceof AudioNode){\n\t\t\t\tthis.output.disconnect();\n\t\t\t} \n\t\t\tthis.output = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode\n\t * @param {Tone | AudioParam | AudioNode} unit \n\t * @param {number} [outputNum=0] optionally which output to connect from\n\t * @param {number} [inputNum=0] optionally which input to connect to\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connect = function(unit, outputNum, inputNum){\n\t\tif (Array.isArray(this.output)){\n\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\tthis.output[outputNum].connect(unit, 0, inputNum);\n\t\t} else {\n\t\t\tthis.output.connect(unit, outputNum, inputNum);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * disconnect the output\n\t * @param {Number|AudioNode} output Either the output index to disconnect\n\t * if the output is an array, or the\n\t * node to disconnect from.\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.disconnect = function(destination, outputNum, inputNum){\n\t\tif (this.isArray(this.output)){\n\t\t\tif (this.isNumber(destination)){\n\t\t\t\tthis.output[destination].disconnect();\n\t\t\t} else {\n\t\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\t\tthis.output[outputNum].disconnect(destination, 0, inputNum);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.output.disconnect.apply(this.output, arguments);\n\t\t}\n\t};\n\n\t/**\n\t * connect together all of the arguments in series\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connectSeries = function(){\n\t\tif (arguments.length > 1){\n\t\t\tvar currentUnit = arguments[0];\n\t\t\tfor (var i = 1; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Connect the output of this node to the rest of the nodes in series.\n\t * @example\n\t * //connect a node to an effect, panVol and then to the master output\n\t * node.chain(effect, panVol, Tone.Master);\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.chain = function(){\n\t\tif (arguments.length > 0){\n\t\t\tvar currentUnit = this;\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of this node to the rest of the nodes in parallel.\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.fan = function(){\n\t\tif (arguments.length > 0){\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tthis.connect(arguments[i]);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t//give native nodes chain and fan methods\n\tAudioNode.prototype.chain = Tone.prototype.chain;\n\tAudioNode.prototype.fan = Tone.prototype.fan;\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUTILITIES / HELPERS / MATHS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * If the `given` parameter is undefined, use the `fallback`. \n\t * If both `given` and `fallback` are object literals, it will\n\t * return a deep copy which includes all of the parameters from both \n\t * objects. If a parameter is undefined in given, it will return\n\t * the fallback property. \n\t *
\n\t * WARNING: if object is self referential, it will go into an an \n\t * infinite recursive loop.\n\t * \n\t * @param {*} given \n\t * @param {*} fallback \n\t * @return {*} \n\t */\n\tTone.prototype.defaultArg = function(given, fallback){\n\t\tif (this.isObject(given) && this.isObject(fallback)){\n\t\t\tvar ret = {};\n\t\t\t//make a deep copy of the given object\n\t\t\tfor (var givenProp in given) {\n\t\t\t\tret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);\n\t\t\t}\n\t\t\tfor (var fallbackProp in fallback) {\n\t\t\t\tret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn this.isUndef(given) ? fallback : given;\n\t\t}\n\t};\n\n\t/**\n\t * returns the args as an options object with given arguments\n\t * mapped to the names provided. \n\t *\n\t * if the args given is an array containing only one object, it is assumed\n\t * that that's already the options object and will just return it. \n\t * \n\t * @param {Array} values the 'arguments' object of the function\n\t * @param {Array} keys the names of the arguments as they\n\t * should appear in the options object\n\t * @param {Object=} defaults optional defaults to mixin to the returned \n\t * options object \n\t * @return {Object} the options object with the names mapped to the arguments\n\t */\n\tTone.prototype.optionsObject = function(values, keys, defaults){\n\t\tvar options = {};\n\t\tif (values.length === 1 && this.isObject(values[0])){\n\t\t\toptions = values[0];\n\t\t} else {\n\t\t\tfor (var i = 0; i < keys.length; i++){\n\t\t\t\toptions[keys[i]] = values[i];\n\t\t\t}\n\t\t}\n\t\tif (!this.isUndef(defaults)){\n\t\t\treturn this.defaultArg(options, defaults);\n\t\t} else {\n\t\t\treturn options;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// TYPE CHECKING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * test if the arg is undefined\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is undefined\n\t * @function\n\t */\n\tTone.prototype.isUndef = function(val){\n\t\treturn typeof val === \"undefined\";\n\t};\n\n\t/**\n\t * test if the arg is a function\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a function\n\t * @function\n\t */\n\tTone.prototype.isFunction = function(val){\n\t\treturn typeof val === \"function\";\n\t};\n\n\t/**\n\t * Test if the argument is a number.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a number\n\t */\n\tTone.prototype.isNumber = function(arg){\n\t\treturn (typeof arg === \"number\");\n\t};\n\n\t/**\n\t * Test if the given argument is an object literal (i.e. `{}`);\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an object literal.\n\t */\n\tTone.prototype.isObject = function(arg){\n\t\treturn (Object.prototype.toString.call(arg) === \"[object Object]\" && arg.constructor === Object);\n\t};\n\n\t/**\n\t * Test if the argument is a boolean.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a boolean\n\t */\n\tTone.prototype.isBoolean = function(arg){\n\t\treturn (typeof arg === \"boolean\");\n\t};\n\n\t/**\n\t * Test if the argument is an Array\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an array\n\t */\n\tTone.prototype.isArray = function(arg){\n\t\treturn (Array.isArray(arg));\n\t};\n\n\t/**\n\t * Test if the argument is a string.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a string\n\t */\n\tTone.prototype.isString = function(arg){\n\t\treturn (typeof arg === \"string\");\n\t};\n\n \t/**\n\t * An empty function.\n\t * @static\n\t */\n\tTone.noOp = function(){};\n\n\t/**\n\t * Make the property not writable. Internal use only. \n\t * @private\n\t * @param {string} property the property to make not writable\n\t */\n\tTone.prototype._readOnly = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._readOnly(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: false,\n\t\t\t\tenumerable : true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Make an attribute writeable. Interal use only. \n\t * @private\n\t * @param {string} property the property to make writable\n\t */\n\tTone.prototype._writable = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._writable(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Possible play states. \n\t * @enum {string}\n\t */\n\tTone.State = {\n\t\tStarted : \"started\",\n\t\tStopped : \"stopped\",\n\t\tPaused : \"paused\",\n \t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Equal power gain scale. Good for cross-fading.\n\t * @param {NormalRange} percent (0-1)\n\t * @return {Number} output gain (0-1)\n\t */\n\tTone.prototype.equalPowerScale = function(percent){\n\t\tvar piFactor = 0.5 * Math.PI;\n\t\treturn Math.sin(percent * piFactor);\n\t};\n\n\t/**\n\t * Convert decibels into gain.\n\t * @param {Decibels} db\n\t * @return {Number} \n\t */\n\tTone.prototype.dbToGain = function(db) {\n\t\treturn Math.pow(2, db / 6);\n\t};\n\n\t/**\n\t * Convert gain to decibels.\n\t * @param {Number} gain (0-1)\n\t * @return {Decibels} \n\t */\n\tTone.prototype.gainToDb = function(gain) {\n\t\treturn 20 * (Math.log(gain) / Math.LN10);\n\t};\n\n\t/**\n\t * Convert an interval (in semitones) to a frequency ratio.\n\t * @param {Interval} interval the number of semitones above the base note\n\t * @return {number} the frequency ratio\n\t * @example\n\t * tone.intervalToFrequencyRatio(0); // 1\n\t * tone.intervalToFrequencyRatio(12); // 2\n\t * tone.intervalToFrequencyRatio(-12); // 0.5\n\t */\n\tTone.prototype.intervalToFrequencyRatio = function(interval){\n\t\treturn Math.pow(2,(interval/12));\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTIMING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t */\n\tTone.prototype.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t * @static\n\t */\n\tTone.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tINHERITANCE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * have a child inherit all of Tone's (or a parent's) prototype\n\t * to inherit the parent's properties, make sure to call \n\t * Parent.call(this) in the child's constructor\n\t *\n\t * based on closure library's inherit function\n\t *\n\t * @static\n\t * @param {function} \tchild \n\t * @param {function=} parent (optional) parent to inherit from\n\t * if no parent is supplied, the child\n\t * will inherit from Tone\n\t */\n\tTone.extend = function(child, parent){\n\t\tif (Tone.prototype.isUndef(parent)){\n\t\t\tparent = Tone;\n\t\t}\n\t\tfunction TempConstructor(){}\n\t\tTempConstructor.prototype = parent.prototype;\n\t\tchild.prototype = new TempConstructor();\n\t\t/** @override */\n\t\tchild.prototype.constructor = child;\n\t\tchild._super = parent;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONTEXT\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The private audio context shared by all Tone Nodes. \n\t * @private\n\t * @type {Tone.Context|undefined}\n\t */\n\tvar audioContext;\n\n\t/**\n\t * A static pointer to the audio context accessible as Tone.context. \n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone\n\t */\n\tObject.defineProperty(Tone, \"context\", {\n\t\tget : function(){\n\t\t\treturn audioContext;\n\t\t},\n\t\tset : function(context){\n\t\t\tif (Tone.Context && context instanceof Tone.Context){\n\t\t\t\taudioContext = context;\n\t\t\t} else {\n\t\t\t\taudioContext = new Tone.Context(context);\n\t\t\t}\n\t\t\t//initialize the new audio context\n\t\t\tif (Tone.Context){\n\t\t\t\tTone.Context.emit(\"init\", audioContext);\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The AudioContext\n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"context\", {\n\t\tget : function(){\n\t\t\treturn Tone.context;\n\t\t}\n\t});\n\n\t/**\n\t * Tone automatically creates a context on init, but if you are working\n\t * with other libraries which also create an AudioContext, it can be\n\t * useful to set your own. If you are going to set your own context, \n\t * be sure to do it at the start of your code, before creating any objects.\n\t * @static\n\t * @param {AudioContext} ctx The new audio context to set\n\t */\n\tTone.setContext = function(ctx){\n\t\tTone.context = ctx;\n\t};\n\n\t/**\n\t * The number of seconds of 1 processing block (128 samples)\n\t * @type {Number}\n\t * @name blockTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"blockTime\", {\n\t\tget : function(){\n\t\t\treturn 128 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * The duration in seconds of one sample.\n\t * @type {Number}\n\t * @name sampleTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"sampleTime\", {\n\t\tget : function(){\n\t\t\treturn 1 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * Whether or not all the technologies that Tone.js relies on are supported by the current browser. \n\t * @type {Boolean}\n\t * @name supported\n\t * @memberOf Tone\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone, \"supported\", {\n\t\tget : function(){\n\t\t\tvar hasAudioContext = window.hasOwnProperty(\"AudioContext\") || window.hasOwnProperty(\"webkitAudioContext\");\n\t\t\tvar hasPromises = window.hasOwnProperty(\"Promise\");\n\t\t\tvar hasWorkers = window.hasOwnProperty(\"Worker\");\n\t\t\treturn hasAudioContext && hasPromises && hasWorkers;\n\t\t}\n\t});\n\n\tTone.version = \"r10\";\n\n\t// allow optional silencing of this log\n\tif (!window.TONE_SILENCE_VERSION_LOGGING) {\n\t\tconsole.log(\"%c * Tone.js \" + Tone.version + \" * \", \"background: #000; color: #fff\");\n\t}\n\n\treturn Tone;\n});\n","'use strict';\r\n\r\n\r\ndefine(['audiocontext'], function (audiocontext) {\r\n /**\r\n * Master contains AudioContext and the master sound output.\r\n * @for p5\r\n */\r\n var Master = function() {\r\n this.input = audiocontext.createGain();\r\n this.output = audiocontext.createGain();\r\n\r\n //put a hard limiter on the output\r\n this.limiter = audiocontext.createDynamicsCompressor();\r\n this.limiter.threshold.value = -3;\r\n this.limiter.ratio.value = 20;\r\n this.limiter.knee.value = 1;\r\n\r\n this.audiocontext = audiocontext;\r\n\r\n this.output.disconnect();\r\n\r\n // connect input to limiter\r\n this.input.connect(this.limiter);\r\n\r\n // connect limiter to output\r\n this.limiter.connect(this.output);\r\n\r\n // meter is just for global Amplitude / FFT analysis\r\n this.meter = audiocontext.createGain();\r\n this.fftMeter = audiocontext.createGain();\r\n this.output.connect(this.meter);\r\n this.output.connect(this.fftMeter);\r\n\r\n // connect output to destination\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // an array of all sounds in the sketch\r\n this.soundArray = [];\r\n // an array of all musical parts in the sketch\r\n this.parts = [];\r\n\r\n // file extensions to search for\r\n this.extensions = [];\r\n };\r\n\r\n // create a single instance of the p5Sound / master output for use within this sketch\r\n var p5sound = new Master();\r\n\r\n /**\r\n * Returns a number representing the master amplitude (volume) for sound\r\n * in this sketch.\r\n *\r\n * @method getMasterVolume\r\n * @return {Number} Master amplitude (volume) for sound in this sketch.\r\n * Should be between 0.0 (silence) and 1.0.\r\n */\r\n p5.prototype.getMasterVolume = function() {\r\n return p5sound.output.gain.value;\r\n };\r\n\r\n /**\r\n *
Scale the output of all sound in this sketch
\r\n * Scaled between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n *
How This Works: When you load the p5.sound module, it\r\n * creates a single instance of p5sound. All sound objects in this\r\n * module output to p5sound before reaching your computer's output.\r\n * So if you change the amplitude of p5sound, it impacts all of the\r\n * sound in this module.
\r\n *\r\n *
If no value is provided, returns a Web Audio API Gain Node
\r\n *\r\n * @method masterVolume\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.prototype.masterVolume = function(vol, rampTime, tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = p5sound.output.gain.value;\r\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(p5sound.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return p5sound.output.gain;\r\n }\r\n };\r\n\r\n /**\r\n * `p5.soundOut` is the p5.sound master output. It sends output to\r\n * the destination of this window's web audio context. It contains\r\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\r\n * and Gain Nodes for .input and .output.\r\n *\r\n * @property {Object} soundOut\r\n */\r\n p5.prototype.soundOut = p5.soundOut = p5sound;\r\n\r\n /**\r\n * a silent connection to the DesinationNode\r\n * which will ensure that anything connected to it\r\n * will not be garbage collected\r\n *\r\n * @private\r\n */\r\n p5.soundOut._silentNode = p5sound.audiocontext.createGain();\r\n p5.soundOut._silentNode.gain.value = 0;\r\n p5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\r\n\r\n\r\n return p5sound;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/type/Type\", \"Tone/core/Param\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal is an audio-rate value. Tone.Signal is a core component of the library.\n\t * Unlike a number, Signals can be scheduled with sample-level accuracy. Tone.Signal\n\t * has all of the methods available to native Web Audio \n\t * [AudioParam](http://webaudio.github.io/web-audio-api/#the-audioparam-interface)\n\t * as well as additional conveniences. Read more about working with signals \n\t * [here](https://github.com/Tonejs/Tone.js/wiki/Signals).\n\t *\n\t * @constructor\n\t * @extends {Tone.Param}\n\t * @param {Number|AudioParam} [value] Initial value of the signal. If an AudioParam\n\t * is passed in, that parameter will be wrapped\n\t * and controlled by the Signal. \n\t * @param {string} [units=Number] unit The units the signal is in. \n\t * @example\n\t * var signal = new Tone.Signal(10);\n\t */\n\tTone.Signal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\n\t\t/**\n\t\t * The node where the constant signal value is scaled.\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.output = this._gain = this.context.createGain();\n\n\t\toptions.param = this._gain.gain;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The node where the value is set.\n\t\t * @type {Tone.Param}\n\t\t * @private\n\t\t */\n\t\tthis.input = this._param = this._gain.gain;\n\n\t\t//connect the const output to the node output\n\t\tthis.context.getConstant(1).chain(this._gain);\n\t};\n\n\tTone.extend(Tone.Signal, Tone.Param);\n\n\t/**\n\t * The default values\n\t * @type {Object}\n\t * @static\n\t * @const\n\t */\n\tTone.Signal.defaults = {\n\t\t\"value\" : 0,\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t * @method\n\t */\n\tTone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\t/**\n\t * dispose and disconnect\n\t * @returns {Tone.Signal} this\n\t */\n\tTone.Signal.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tthis._gain.disconnect();\n\t\tthis._gain = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Signal;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Multiply two incoming signals. Or, if a number is given in the constructor, \n\t * multiplies the incoming signal by that value. \n\t *\n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value Constant value to multiple. If no value is provided,\n\t * it will return the product of the first and second inputs\n\t * @example\n\t * var mult = new Tone.Multiply();\n\t * var sigA = new Tone.Signal(3);\n\t * var sigB = new Tone.Signal(4);\n\t * sigA.connect(mult, 0, 0);\n\t * sigB.connect(mult, 0, 1);\n\t * //output of mult is 12.\n\t * @example\n\t * var mult = new Tone.Multiply(10);\n\t * var sig = new Tone.Signal(2).connect(mult);\n\t * //the output of mult is 20. \n\t */\n\tTone.Multiply = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the input node is the same as the output node\n\t\t * it is also the GainNode which handles the scaling of incoming signal\n\t\t * \n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._mult = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * the scaling parameter\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[1] = this.output.gain;\n\t\t\n\t\tthis._param.value = this.defaultArg(value, 0);\n\t};\n\n\tTone.extend(Tone.Multiply, Tone.Signal);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Multiply} this\n\t */\n\tTone.Multiply.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._mult.dispose();\n\t\tthis._mult = null;\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Multiply;\n});\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var CrossFade = require('Tone/component/CrossFade');\r\n\r\n /**\r\n * Effect is a base class for audio effects in p5. \r\n * This module handles the nodes and methods that are\r\n * common and useful for current and future effects.\r\n *\r\n *\r\n * This class is extended by p5.Distortion,\r\n * p5.Compressor,\r\n * p5.Delay,\r\n * p5.Filter,\r\n * p5.Reverb.\r\n *\r\n * @class p5.Effect\r\n * @constructor\r\n *\r\n * @param {Object} [ac] Reference to the audio context of the p5 object\r\n * @param {AudioNode} [input] Gain Node effect wrapper\r\n * @param {AudioNode} [output] Gain Node effect wrapper\r\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\r\n * @param {AudioNode} [wet] Effects that extend this class should connect\r\n * to the wet signal to this gain node, so that dry and wet\r\n * signals are mixed properly.\r\n */\r\n p5.Effect = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n /**\r\n *\tThe p5.Effect class is built\r\n * \tusing Tone.js CrossFade\r\n * \t@private\r\n */\r\n\r\n this._drywet = new CrossFade(1);\r\n\r\n /**\r\n *\tIn classes that extend\r\n *\tp5.Effect, connect effect nodes\r\n *\tto the wet parameter\r\n */\r\n this.wet = this.ac.createGain();\r\n\r\n this.input.connect(this._drywet.a);\r\n this.wet.connect(this._drywet.b);\r\n this._drywet.connect(this.output);\r\n\r\n this.connect();\r\n\r\n //Add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the output volume of the filter.\r\n *\r\n * @method amp\r\n * @for p5.Effect\r\n * @param {Number} [vol] amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts until rampTime\r\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\r\n */\r\n p5.Effect.prototype.amp = function(vol, rampTime, tFromNow){\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + .001);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + .001);\r\n };\r\n\r\n /**\r\n * Link effects together in a chain\r\n * Example usage: filter.chain(reverb, delay, panner);\r\n * May be used with an open-ended number of arguments\r\n *\r\n * @method chain\r\n * @for p5.Effect\r\n * @param {Object} [arguments] Chain together multiple sound objects\r\n */\r\n p5.Effect.prototype.chain = function(){\r\n if (arguments.length>0){\r\n this.connect(arguments[0]);\r\n for(var i=1;i\r\n * var notes = [60, 64, 67, 72];\r\n * var i = 0;\r\n *\r\n * function setup() {\r\n * osc = new p5.Oscillator('Triangle');\r\n * osc.start();\r\n * frameRate(1);\r\n * }\r\n *\r\n * function draw() {\r\n * var freq = midiToFreq(notes[i]);\r\n * osc.freq(freq);\r\n * i++;\r\n * if (i >= notes.length){\r\n * i = 0;\r\n * }\r\n * }\r\n * \r\n */\r\n var midiToFreq = p5.prototype.midiToFreq = function(m) {\r\n return 440 * Math.pow(2, (m-69)/12.0);\r\n };\r\n\r\n // This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\r\n var noteToFreq = function(note) {\r\n if (typeof note !== 'string') {\r\n return note;\r\n }\r\n var wholeNotes = {A:21, B:23, C:24, D:26, E:28, F:29, G:31};\r\n var value = wholeNotes[ note[0].toUpperCase() ];\r\n var octave = ~~note.slice(-1);\r\n value += 12 * (octave -1);\r\n\r\n switch(note[1]) {\r\n case '#':\r\n value += 1;\r\n break;\r\n case 'b':\r\n value -= 1;\r\n break;\r\n default:\r\n break;\r\n }\r\n return midiToFreq(value);\r\n };\r\n\r\n /**\r\n * List the SoundFile formats that you will include. LoadSound\r\n * will search your directory for these extensions, and will pick\r\n * a format that is compatable with the client's web browser.\r\n * Here is a free online file\r\n * converter.\r\n *\r\n * @method soundFormats\r\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\r\n * @example\r\n *
\r\n * function preload() {\r\n * // set the global sound formats\r\n * soundFormats('mp3', 'ogg');\r\n *\r\n * // load either beatbox.mp3, or .ogg, depending on browser\r\n * mySound = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * mySound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.soundFormats = function() {\r\n // reset extensions array\r\n p5sound.extensions = [];\r\n // add extensions\r\n for (var i = 0; i < arguments.length; i++) {\r\n arguments[i] = arguments[i].toLowerCase();\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\r\n p5sound.extensions.push(arguments[i]);\r\n } else {\r\n throw arguments[i] + ' is not a valid sound format!';\r\n }\r\n }\r\n };\r\n\r\n p5.prototype.disposeSound = function() {\r\n for (var i = 0; i < p5sound.soundArray.length; i++) {\r\n p5sound.soundArray[i].dispose();\r\n }\r\n };\r\n\r\n // register removeSound to dispose of p5sound SoundFiles, Convolvers,\r\n // Oscillators etc when sketch ends\r\n p5.prototype.registerMethod('remove', p5.prototype.disposeSound);\r\n\r\n p5.prototype._checkFileFormats = function(paths) {\r\n var path;\r\n // if path is a single string, check to see if extension is provided\r\n if (typeof paths === 'string') {\r\n path = paths;\r\n // see if extension is provided\r\n var extTest = path.split('.').pop();\r\n // if an extension is provided...\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\r\n if (p5.prototype.isFileSupported(extTest)) {\r\n path = path;\r\n }\r\n else {\r\n var pathSplit = path.split('.');\r\n var pathCore = pathSplit[pathSplit.length - 1];\r\n for (var i = 0; i 1) {\r\n rightChannel = audioBuffer.getChannelData(1);\r\n } else {\r\n rightChannel = leftChannel;\r\n }\r\n\r\n var interleaved = interleave(leftChannel, rightChannel);\r\n\r\n // create the buffer and view to create the .WAV file\r\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\r\n var view = new window.DataView(buffer);\r\n\r\n // write the WAV container,\r\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\r\n\r\n // RIFF chunk descriptor\r\n writeUTFBytes(view, 0, 'RIFF');\r\n view.setUint32(4, 36 + interleaved.length * 2, true);\r\n writeUTFBytes(view, 8, 'WAVE');\r\n // FMT sub-chunk\r\n writeUTFBytes(view, 12, 'fmt ');\r\n view.setUint32(16, 16, true);\r\n view.setUint16(20, 1, true);\r\n // stereo (2 channels)\r\n view.setUint16(22, 2, true);\r\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\r\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\r\n view.setUint16(32, 4, true);\r\n view.setUint16(34, 16, true);\r\n // data sub-chunk\r\n writeUTFBytes(view, 36, 'data');\r\n view.setUint32(40, interleaved.length * 2, true);\r\n\r\n // write the PCM samples\r\n var lng = interleaved.length;\r\n var index = 44;\r\n var volume = 1;\r\n for (var i = 0; i < lng; i++) {\r\n view.setInt16(index, interleaved[i] * (0x7FFF * volume), true);\r\n index += 2;\r\n }\r\n\r\n return view;\r\n }\r\n\r\n // helper methods to save waves\r\n function interleave(leftChannel, rightChannel) {\r\n var length = leftChannel.length + rightChannel.length;\r\n var result = new Float32Array(length);\r\n\r\n var inputIndex = 0;\r\n\r\n for (var index = 0; index < length;) {\r\n result[index++] = leftChannel[inputIndex];\r\n result[index++] = rightChannel[inputIndex];\r\n inputIndex++;\r\n }\r\n return result;\r\n }\r\n\r\n function writeUTFBytes(view, offset, string) {\r\n var lng = string.length;\r\n for (var i = 0; i < lng; i++) {\r\n view.setUint8(offset + i, string.charCodeAt(i));\r\n }\r\n }\r\n\r\n return {\r\n convertToWav: convertToWav,\r\n midiToFreq: midiToFreq,\r\n noteToFreq: noteToFreq\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Add a signal and a number or two signals. When no value is\n\t * passed into the constructor, Tone.Add will sum input[0]\n\t * and input[1]. If a value is passed into the constructor, \n\t * the it will be added to the input.\n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value If no value is provided, Tone.Add will sum the first\n\t * and second inputs. \n\t * @example\n\t * var signal = new Tone.Signal(2);\n\t * var add = new Tone.Add(2);\n\t * signal.connect(add);\n\t * //the output of add equals 4\n\t * @example\n\t * //if constructed with no arguments\n\t * //it will add the first and second inputs\n\t * var add = new Tone.Add();\n\t * var sig0 = new Tone.Signal(3).connect(add, 0, 0);\n\t * var sig1 = new Tone.Signal(4).connect(add, 0, 1);\n\t * //the output of add equals 7. \n\t */\n\tTone.Add = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.connect(this._sum);\n\t};\n\n\tTone.extend(Tone.Add, Tone.Signal);\n\t\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Add} this\n\t */\n\tTone.Add.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._sum.dispose();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Add;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\", \"Tone/type/Frequency\", \"Tone/type/TransportTime\", \"Tone/core/Context\"],\nfunction (Tone) {\t\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTYPES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Units which a value can take on.\n\t * @enum {String}\n\t */\n\tTone.Type = {\n\t\t/** \n\t\t * Default units\n\t\t * @typedef {Default}\n\t\t */\n\t\tDefault : \"number\",\n\t\t/**\n\t\t * Time can be described in a number of ways. Read more [Time](https://github.com/Tonejs/Tone.js/wiki/Time).\n\t\t *\n\t\t *
\n\t\t *
Numbers, which will be taken literally as the time (in seconds).
\n\t\t *
Notation, (\"4n\", \"8t\") describes time in BPM and time signature relative values.
\n\t\t *
TransportTime, (\"4:3:2\") will also provide tempo and time signature relative times \n\t\t * in the form BARS:QUARTERS:SIXTEENTHS.
\n\t\t *
Frequency, (\"8hz\") is converted to the length of the cycle in seconds.
\n\t\t *
Now-Relative, (\"+1\") prefix any of the above with \"+\" and it will be interpreted as \n\t\t * \"the current time plus whatever expression follows\".
\n\t\t *
Expressions, (\"3:0 + 2 - (1m / 7)\") any of the above can also be combined \n\t\t * into a mathematical expression which will be evaluated to compute the desired time.
\n\t\t *
No Argument, for methods which accept time, no argument will be interpreted as \n\t\t * \"now\" (i.e. the currentTime).
\n\t\t *
\n\t\t * \n\t\t * @typedef {Time}\n\t\t */\n\t\tTime : \"time\",\n\t\t/**\n\t\t * Frequency can be described similar to time, except ultimately the\n\t\t * values are converted to frequency instead of seconds. A number\n\t\t * is taken literally as the value in hertz. Additionally any of the \n\t\t * Time encodings can be used. Note names in the form\n\t\t * of NOTE OCTAVE (i.e. C4) are also accepted and converted to their\n\t\t * frequency value. \n\t\t * @typedef {Frequency}\n\t\t */\n\t\tFrequency : \"frequency\",\n\t\t/**\n\t\t * TransportTime describes a position along the Transport's timeline. It is\n\t\t * similar to Time in that it uses all the same encodings, but TransportTime specifically\n\t\t * pertains to the Transport's timeline, which is startable, stoppable, loopable, and seekable. \n\t\t * [Read more](https://github.com/Tonejs/Tone.js/wiki/TransportTime)\n\t\t * @typedef {TransportTime}\n\t\t */\n\t\tTransportTime : \"transportTime\",\n\t\t/** \n\t\t * Ticks are the basic subunit of the Transport. They are\n\t\t * the smallest unit of time that the Transport supports.\n\t\t * @typedef {Ticks}\n\t\t */\n\t\tTicks : \"ticks\",\n\t\t/** \n\t\t * Normal values are within the range [0, 1].\n\t\t * @typedef {NormalRange}\n\t\t */\n\t\tNormalRange : \"normalRange\",\n\t\t/** \n\t\t * AudioRange values are between [-1, 1].\n\t\t * @typedef {AudioRange}\n\t\t */\n\t\tAudioRange : \"audioRange\",\n\t\t/** \n\t\t * Decibels are a logarithmic unit of measurement which is useful for volume\n\t\t * because of the logarithmic way that we perceive loudness. 0 decibels \n\t\t * means no change in volume. -10db is approximately half as loud and 10db \n\t\t * is twice is loud. \n\t\t * @typedef {Decibels}\n\t\t */\n\t\tDecibels : \"db\",\n\t\t/** \n\t\t * Half-step note increments, i.e. 12 is an octave above the root. and 1 is a half-step up.\n\t\t * @typedef {Interval}\n\t\t */\n\t\tInterval : \"interval\",\n\t\t/** \n\t\t * Beats per minute. \n\t\t * @typedef {BPM}\n\t\t */\n\t\tBPM : \"bpm\",\n\t\t/** \n\t\t * The value must be greater than or equal to 0.\n\t\t * @typedef {Positive}\n\t\t */\n\t\tPositive : \"positive\",\n\t\t/** \n\t\t * A cent is a hundredth of a semitone. \n\t\t * @typedef {Cents}\n\t\t */\n\t\tCents : \"cents\",\n\t\t/** \n\t\t * Angle between 0 and 360. \n\t\t * @typedef {Degrees}\n\t\t */\n\t\tDegrees : \"degrees\",\n\t\t/** \n\t\t * A number representing a midi note.\n\t\t * @typedef {MIDI}\n\t\t */\n\t\tMIDI : \"midi\",\n\t\t/** \n\t\t * A colon-separated representation of time in the form of\n\t\t * Bars:Beats:Sixteenths. \n\t\t * @typedef {BarsBeatsSixteenths}\n\t\t */\n\t\tBarsBeatsSixteenths : \"barsBeatsSixteenths\",\n\t\t/** \n\t\t * Sampling is the reduction of a continuous signal to a discrete signal.\n\t\t * Audio is typically sampled 44100 times per second. \n\t\t * @typedef {Samples}\n\t\t */\n\t\tSamples : \"samples\",\n\t\t/** \n\t\t * Hertz are a frequency representation defined as one cycle per second.\n\t\t * @typedef {Hertz}\n\t\t */\n\t\tHertz : \"hertz\",\n\t\t/** \n\t\t * A frequency represented by a letter name, \n\t\t * accidental and octave. This system is known as\n\t\t * [Scientific Pitch Notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation).\n\t\t * @typedef {Note}\n\t\t */\n\t\tNote : \"note\",\n\t\t/** \n\t\t * One millisecond is a thousandth of a second. \n\t\t * @typedef {Milliseconds}\n\t\t */\n\t\tMilliseconds : \"milliseconds\",\n\t\t/** \n\t\t * Seconds are the time unit of the AudioContext. In the end, \n\t\t * all values need to be evaluated to seconds. \n\t\t * @typedef {Seconds}\n\t\t */\n\t\tSeconds : \"seconds\",\n\t\t/** \n\t\t * A string representing a duration relative to a measure. \n\t\t *
\n\t\t * \t
\"4n\" = quarter note
\n\t\t * \t
\"2m\" = two measures
\n\t\t * \t
\"8t\" = eighth-note triplet
\n\t\t *
\n\t\t * @typedef {Notation}\n\t\t */\n\t\tNotation : \"notation\",\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// AUGMENT TONE's PROTOTYPE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert Time into seconds.\n\t * \n\t * Unlike the method which it overrides, this takes into account \n\t * transporttime and musical notation.\n\t *\n\t * Time : 1.40\n\t * Notation: 4n|1m|2t\n\t * Now Relative: +3n\n\t * Math: 3n+16n or even complicated expressions ((3n*2)/6 + 1)\n\t *\n\t * @param {Time} time \n\t * @return {Seconds} \n\t */\n\tTone.prototype.toSeconds = function(time){\n\t\tif (this.isNumber(time)){\n\t\t\treturn time;\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn this.now();\t\t\t\n\t\t} else if (this.isString(time)){\n\t\t\treturn (new Tone.Time(time)).toSeconds();\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toSeconds();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a frequency representation into a number.\n\t * @param {Frequency} freq \n\t * @return {Hertz} the frequency in hertz\n\t */\n\tTone.prototype.toFrequency = function(freq){\n\t\tif (this.isNumber(freq)){\n\t\t\treturn freq;\n\t\t} else if (this.isString(freq) || this.isUndef(freq)){\n\t\t\treturn (new Tone.Frequency(freq)).valueOf();\n\t\t} else if (freq instanceof Tone.TimeBase){\n\t\t\treturn freq.toFrequency();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a time representation into ticks.\n\t * @param {Time} time\n\t * @return {Ticks} the time in ticks\n\t */\n\tTone.prototype.toTicks = function(time){\n\t\tif (this.isNumber(time) || this.isString(time)){\n\t\t\treturn (new Tone.TransportTime(time)).toTicks();\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn Tone.Transport.ticks;\t\t\t\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toTicks();\n\t\t}\n\t};\n\n\treturn Tone;\n});","define([\"Tone/core/Tone\", \"Tone/core/Param\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * createGain shim\n\t * @private\n\t */\n\tif (window.GainNode && !AudioContext.prototype.createGain){\n\t\tAudioContext.prototype.createGain = AudioContext.prototype.createGainNode;\n\t}\n\n\t/**\n\t * @class A thin wrapper around the Native Web Audio GainNode.\n\t * The GainNode is a basic building block of the Web Audio\n\t * API and is useful for routing audio and adjusting gains. \n\t * @extends {Tone}\n\t * @param {Number=} gain The initial gain of the GainNode\n\t * @param {Tone.Type=} units The units of the gain parameter. \n\t */\n\tTone.Gain = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"gain\", \"units\"], Tone.Gain.defaults);\n\n\t\t/**\n\t\t * The GainNode\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.input = this.output = this._gainNode = this.context.createGain();\n\n\t\t/**\n\t\t * The gain parameter of the gain node.\n\t\t * @type {Tone.Param}\n\t\t * @signal\n\t\t */\n\t\tthis.gain = new Tone.Param({\n\t\t\t\"param\" : this._gainNode.gain, \n\t\t\t\"units\" : options.units,\n\t\t\t\"value\" : options.gain,\n\t\t\t\"convert\" : options.convert\n\t\t});\n\t\tthis._readOnly(\"gain\");\n\t};\n\n\tTone.extend(Tone.Gain);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Gain.defaults = {\n\t\t\"gain\" : 1,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Gain} this\n\t */\n\tTone.Gain.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._gainNode.disconnect();\n\t\tthis._gainNode = null;\n\t\tthis._writable(\"gain\");\n\t\tthis.gain.dispose();\n\t\tthis.gain = null;\n\t};\n\n\t//STATIC///////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Create input and outputs for this object.\n\t * @param {Number} input The number of inputs\n\t * @param {Number=} outputs The number of outputs\n\t * @return {Tone} this\n\t * @internal\n\t */\n\tTone.prototype.createInsOuts = function(inputs, outputs){\n\n\t\tif (inputs === 1){\n\t\t\tthis.input = new Tone.Gain();\n\t\t} else if (inputs > 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\tif (outputs === 1){\n\t\t\tthis.output = new Tone.Gain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\n\treturn Tone.Gain;\n});","'use strict';\r\n\r\ndefine(function () {\r\n /*\r\n Helper function to generate an error\r\n with a custom stack trace that points to the sketch\r\n and removes other parts of the stack trace.\r\n\r\n @private\r\n @class customError\r\n @constructor\r\n @param {String} name custom error name\r\n @param {String} errorTrace custom error trace\r\n @param {String} failedPath path to the file that failed to load\r\n @property {String} name custom error name\r\n @property {String} message custom error message\r\n @property {String} stack trace the error back to a line in the user's sketch.\r\n Note: this edits out stack trace within p5.js and p5.sound.\r\n @property {String} originalStack unedited, original stack trace\r\n @property {String} failedPath path to the file that failed to load\r\n @return {Error} returns a custom Error object\r\n */\r\n var CustomError = function(name, errorTrace, failedPath) {\r\n var err = new Error();\r\n var tempStack, splitStack;\r\n\r\n err.name = name;\r\n err.originalStack = err.stack + errorTrace;\r\n tempStack = err.stack + errorTrace;\r\n err.failedPath = failedPath;\r\n\r\n // only print the part of the stack trace that refers to the user code:\r\n var splitStack = tempStack.split('\\n');\r\n splitStack = splitStack.filter(function(ln) {\r\n return !ln.match(/(p5.|native code|globalInit)/g);\r\n });\r\n err.stack = splitStack.join('\\n');\r\n\r\n return err; // TODO: is this really a constructor?\r\n };\r\n\r\n return CustomError;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Emitter\"], function (Tone) {\n\n\t/**\n\t * shim\n\t * @private\n\t */\n\tif (!window.hasOwnProperty(\"AudioContext\") && window.hasOwnProperty(\"webkitAudioContext\")){\n\t\twindow.AudioContext = window.webkitAudioContext;\n\t}\n\n\t/**\n\t * @class Wrapper around the native AudioContext.\n\t * @extends {Tone.Emitter}\n\t * @param {AudioContext=} context optionally pass in a context\n\t */\n\tTone.Context = function(context){\n\n\t\tTone.Emitter.call(this);\n\n\t\tif (!context){\n\t\t\tcontext = new window.AudioContext();\n\t\t}\n\t\tthis._context = context;\n\t\t// extend all of the methods\n\t\tfor (var prop in this._context){\n\t\t\tthis._defineProperty(this._context, prop);\n\t\t}\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// WORKER\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\t/**\n\t\t * The default latency hint\n\t\t * @type {String}\n\t\t * @private\n\t\t */\n\t\tthis._latencyHint = \"interactive\";\n\n\t\t/**\n\t\t * The amount of time events are scheduled\n\t\t * into the future\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._lookAhead = 0.1;\n\n\t\t/**\n\t\t * How often the update look runs\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._updateInterval = this._lookAhead/3;\n\n\t\t/**\n\t\t * A reference to the actual computed update interval\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._computedUpdateInterval = 0;\n\n\t\t/**\n\t\t * The web worker which is used to update Tone.Clock\n\t\t * @private\n\t\t * @type {WebWorker}\n\t\t */\n\t\tthis._worker = this._createWorker();\n\n\t\t/**\n\t\t * An object containing all of the constants AudioBufferSourceNodes\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t\tthis._constants = {};\n\n\t};\n\n\tTone.extend(Tone.Context, Tone.Emitter);\n\tTone.Emitter.mixin(Tone.Context);\n\n\t/**\n\t * Define a property on this Tone.Context. \n\t * This is used to extend the native AudioContext\n\t * @param {AudioContext} context\n\t * @param {String} prop \n\t * @private\n\t */\n\tTone.Context.prototype._defineProperty = function(context, prop){\n\t\tif (this.isUndef(this[prop])){\n\t\t\tObject.defineProperty(this, prop, {\n\t\t\t\tget : function(){\n\t\t\t\t\tif (typeof context[prop] === \"function\"){\n\t\t\t\t\t\treturn context[prop].bind(context);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn context[prop];\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tset : function(val){\n\t\t\t\t\tcontext[prop] = val;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * The current audio context time\n\t * @return {Number}\n\t */\n\tTone.Context.prototype.now = function(){\n\t\treturn this._context.currentTime;\n\t};\n\n\t/**\n\t * Generate a web worker\n\t * @return {WebWorker}\n\t * @private\n\t */\n\tTone.Context.prototype._createWorker = function(){\n\t\t\n\t\t//URL Shim\n\t\twindow.URL = window.URL || window.webkitURL;\n\n\t\tvar blob = new Blob([\n\t\t\t//the initial timeout time\n\t\t\t\"var timeoutTime = \"+(this._updateInterval * 1000).toFixed(1)+\";\" +\n\t\t\t//onmessage callback\n\t\t\t\"self.onmessage = function(msg){\" +\n\t\t\t\"\ttimeoutTime = parseInt(msg.data);\" + \n\t\t\t\"};\" + \n\t\t\t//the tick function which posts a message\n\t\t\t//and schedules a new tick\n\t\t\t\"function tick(){\" +\n\t\t\t\"\tsetTimeout(tick, timeoutTime);\" +\n\t\t\t\"\tself.postMessage('tick');\" +\n\t\t\t\"}\" +\n\t\t\t//call tick initially\n\t\t\t\"tick();\"\n\t\t]);\n\t\tvar blobUrl = URL.createObjectURL(blob);\n\t\tvar worker = new Worker(blobUrl);\n\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\t// tick the clock\n\t\t\tthis.emit(\"tick\");\n\t\t}.bind(this));\n\n\t\t//lag compensation\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\tvar now = this.now();\n\t\t\tif (this.isNumber(this._lastUpdate)){\n\t\t\t\tvar diff = now - this._lastUpdate;\n\t\t\t\tthis._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);\n\t\t\t}\n\t\t\tthis._lastUpdate = now;\n\t\t}.bind(this));\n\n\t\treturn worker;\n\t};\n\n\t/**\n\t * Generate a looped buffer at some constant value.\n\t * @param {Number} val\n\t * @return {BufferSourceNode}\n\t */\n\tTone.Context.prototype.getConstant = function(val){\n\t\tif (this._constants[val]){\n\t\t\treturn this._constants[val];\n\t\t} else {\n\t\t\tvar buffer = this._context.createBuffer(1, 128, this._context.sampleRate);\n\t\t\tvar arr = buffer.getChannelData(0);\n\t\t\tfor (var i = 0; i < arr.length; i++){\n\t\t\t\tarr[i] = val;\n\t\t\t}\n\t\t\tvar constant = this._context.createBufferSource();\n\t\t\tconstant.channelCount = 1;\n\t\t\tconstant.channelCountMode = \"explicit\";\n\t\t\tconstant.buffer = buffer;\n\t\t\tconstant.loop = true;\n\t\t\tconstant.start(0);\n\t\t\tthis._constants[val] = constant;\n\t\t\treturn constant;\n\t\t}\n\t};\n\n\t/**\n\t * This is the time that the clock is falling behind\n\t * the scheduled update interval. The Context automatically\n\t * adjusts for the lag and schedules further in advance.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lag\n\t * @static\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lag\", {\n\t\tget : function(){\n\t\t\tvar diff = this._computedUpdateInterval - this._updateInterval;\n\t\t\tdiff = Math.max(diff, 0);\n\t\t\treturn diff;\n\t\t}\n\t});\n\n\t/**\n\t * The amount of time in advance that events are scheduled.\n\t * The lookAhead will adjust slightly in response to the \n\t * measured update time to try to avoid clicks.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lookAhead\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lookAhead\", {\n\t\tget : function(){\n\t\t\treturn this._lookAhead;\n\t\t},\n\t\tset : function(lA){\n\t\t\tthis._lookAhead = lA;\n\t\t}\n\t});\n\n\t/**\n\t * How often the Web Worker callback is invoked.\n\t * This number corresponds to how responsive the scheduling\n\t * can be. Context.updateInterval + Context.lookAhead gives you the\n\t * total latency between scheduling an event and hearing it.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name updateInterval\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"updateInterval\", {\n\t\tget : function(){\n\t\t\treturn this._updateInterval;\n\t\t},\n\t\tset : function(interval){\n\t\t\tthis._updateInterval = Math.max(interval, Tone.prototype.blockTime);\n\t\t\tthis._worker.postMessage(Math.max(interval * 1000, 1));\n\t\t}\n\t});\n\n\t/**\n\t * The type of playback, which affects tradeoffs between audio \n\t * output latency and responsiveness. \n\t * \n\t * In addition to setting the value in seconds, the latencyHint also\n\t * accepts the strings \"interactive\" (prioritizes low latency), \n\t * \"playback\" (prioritizes sustained playback), \"balanced\" (balances\n\t * latency and performance), and \"fastest\" (lowest latency, might glitch more often). \n\t * @type {String|Seconds}\n\t * @memberOf Tone.Context#\n\t * @name latencyHint\n\t * @static\n\t * @example\n\t * //set the lookAhead to 0.3 seconds\n\t * Tone.context.latencyHint = 0.3;\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"latencyHint\", {\n\t\tget : function(){\n\t\t\treturn this._latencyHint;\n\t\t},\n\t\tset : function(hint){\n\t\t\tvar lookAhead = hint;\n\t\t\tthis._latencyHint = hint;\n\t\t\tif (this.isString(hint)){\n\t\t\t\tswitch(hint){\n\t\t\t\t\tcase \"interactive\" :\n\t\t\t\t\t\tlookAhead = 0.1;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"playback\" :\n\t\t\t\t\t\tlookAhead = 0.8;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"balanced\" :\n\t\t\t\t\t\tlookAhead = 0.25;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"fastest\" :\n\t\t\t\t\t\tlookAhead = 0.01;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.lookAhead = lookAhead;\n\t\t\tthis.updateInterval = lookAhead/3;\n\t\t}\n\t});\n\n\t/**\n\t * Shim all connect/disconnect and some deprecated methods which are still in\n\t * some older implementations.\n\t * @private\n\t */\n\tfunction shimConnect(){\n\n\t\tvar nativeConnect = AudioNode.prototype.connect;\n\t\tvar nativeDisconnect = AudioNode.prototype.disconnect;\n\n\t\t//replace the old connect method\n\t\tfunction toneConnect(B, outNum, inNum){\n\t\t\tif (B.input){\n\t\t\t\tif (Array.isArray(B.input)){\n\t\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\t\tinNum = 0;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connect(B.input[inNum]);\n\t\t\t\t} else {\n\t\t\t\t\tthis.connect(B.input, outNum, inNum);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (B instanceof AudioNode){\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum, inNum);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error connecting to node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//replace the old disconnect method\n\t\tfunction toneDisconnect(B, outNum, inNum){\n\t\t\tif (B && B.input && Array.isArray(B.input)){\n\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\tinNum = 0;\n\t\t\t\t}\n\t\t\t\tthis.disconnect(B.input[inNum], outNum, inNum);\n\t\t\t} else if (B && B.input){\n\t\t\t\tthis.disconnect(B.input, outNum, inNum);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tnativeDisconnect.apply(this, arguments);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error disconnecting node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (AudioNode.prototype.connect !== toneConnect){\n\t\t\tAudioNode.prototype.connect = toneConnect;\n\t\t\tAudioNode.prototype.disconnect = toneDisconnect;\n\t\t}\n\t}\n\n\t// set the audio context initially\n\tif (Tone.supported){\n\t\tshimConnect();\n\t\tTone.context = new Tone.Context();\n\t} else {\n\t\tconsole.warn(\"This browser does not support Tone.js\");\n\t}\n\n\treturn Tone.Context;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\t\n\t/**\n\t * @class Performs a linear scaling on an input signal.\n\t * Scales a NormalRange input to between\n\t * outputMin and outputMax.\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {number} [outputMin=0] The output value when the input is 0. \n\t * @param {number} [outputMax=1]\tThe output value when the input is 1. \n\t * @example\n\t * var scale = new Tone.Scale(50, 100);\n\t * var signal = new Tone.Signal(0.5).connect(scale);\n\t * //the output of scale equals 75\n\t */\n\tTone.Scale = function(outputMin, outputMax){\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMin = this.defaultArg(outputMin, 0);\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMax = this.defaultArg(outputMax, 1);\n\n\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(1);\n\t\t\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Add}\n\t\t * @private\n\t\t */\n\t\tthis._add = this.output = new Tone.Add(0);\n\n\t\tthis._scale.connect(this._add);\n\t\tthis._setRange();\n\t};\n\n\tTone.extend(Tone.Scale, Tone.SignalBase);\n\n\t/**\n\t * The minimum output value. This number is output when \n\t * the value input value is 0. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name min\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"min\", {\n\t\tget : function(){\n\t\t\treturn this._outputMin;\n\t\t},\n\t\tset : function(min){\n\t\t\tthis._outputMin = min;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * The maximum output value. This number is output when \n\t * the value input value is 1. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name max\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"max\", {\n\t\tget : function(){\n\t\t\treturn this._outputMax;\n\t\t},\n\t\tset : function(max){\n\t\t\tthis._outputMax = max;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * set the values\n\t * @private\n\t */\n\tTone.Scale.prototype._setRange = function() {\n\t\tthis._add.value = this._outputMin;\n\t\tthis._scale.value = this._outputMax - this._outputMin;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Scale} this\n\t */\n\tTone.Scale.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._add.dispose();\n\t\tthis._add = null;\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Scale;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Timeline\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal which adds the method getValueAtTime. \n\t * Code and inspiration from https://github.com/jsantell/web-audio-automation-timeline\n\t * @extends {Tone.Param}\n\t * @param {Number=} value The initial value of the signal\n\t * @param {String=} units The conversion units of the signal.\n\t */\n\tTone.TimelineSignal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\t\t\n\t\t/**\n\t\t * The scheduled events\n\t\t * @type {Tone.Timeline}\n\t\t * @private\n\t\t */\n\t\tthis._events = new Tone.Timeline(10);\n\n\t\t//constructors\n\t\tTone.Signal.apply(this, options);\n\t\toptions.param = this._param;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The initial scheduled value\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._initial = this._fromUnits(this._param.value);\n\t};\n\n\tTone.extend(Tone.TimelineSignal, Tone.Param);\n\n\t/**\n\t * The event types of a schedulable signal.\n\t * @enum {String}\n\t * @private\n\t */\n\tTone.TimelineSignal.Type = {\n\t\tLinear : \"linear\",\n\t\tExponential : \"exponential\",\n\t\tTarget : \"target\",\n\t\tCurve : \"curve\",\n\t\tSet : \"set\"\n\t};\n\n\t/**\n\t * The current value of the signal. \n\t * @memberOf Tone.TimelineSignal#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.TimelineSignal.prototype, \"value\", {\n\t\tget : function(){\n\t\t\tvar now = this.now();\n\t\t\tvar val = this.getValueAtTime(now);\n\t\t\treturn this._toUnits(val);\n\t\t},\n\t\tset : function(value){\n\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\tthis._initial = convertedVal;\n\t\t\tthis.cancelScheduledValues();\n\t\t\tthis._param.value = convertedVal;\n\t\t}\n\t});\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tSCHEDULING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.TimelineSignal} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Set,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime\n\t\t});\n\t\t//invoke the original event\n\t\tthis._param.setValueAtTime(value, startTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tendTime = this.toSeconds(endTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Linear,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\tthis._param.linearRampToValueAtTime(value, endTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {\n\t\t//get the previous event and make sure it's not starting from 0\n\t\tendTime = this.toSeconds(endTime);\n\t\tvar beforeEvent = this._searchBefore(endTime);\n\t\tif (beforeEvent && beforeEvent.value === 0){\n\t\t\t//reschedule that event\n\t\t\tthis.setValueAtTime(this._minOutput, beforeEvent.time);\n\t\t}\n\t\tvalue = this._fromUnits(value);\n\t\tvar setValue = Math.max(value, this._minOutput);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Exponential,\n\t\t\t\"value\" : setValue,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\t//if the ramped to value is 0, make it go to the min output, and then set to 0.\n\t\tif (value < this._minOutput){\n\t\t\tthis._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);\n\t\t\tthis.setValueAtTime(0, endTime);\n\t\t} else {\n\t\t\tthis._param.exponentialRampToValueAtTime(value, endTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Target,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime,\n\t\t\t\"constant\" : timeConstant\n\t\t});\n\t\tthis._param.setTargetAtTime(value, startTime, timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Set an array of arbitrary values starting at the given time for the given duration.\n\t * @param {Float32Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration\n\t * @param {NormalRange} [scaling=1] If the values in the curve should be scaled by some value\n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {\n\t\tscaling = this.defaultArg(scaling, 1);\n\t\t//copy the array\n\t\tvar floats = new Array(values.length);\n\t\tfor (var i = 0; i < floats.length; i++){\n\t\t\tfloats[i] = this._fromUnits(values[i]) * scaling;\n\t\t}\n\t\tstartTime = this.toSeconds(startTime);\n\t\tduration = this.toSeconds(duration);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Curve,\n\t\t\t\"value\" : floats,\n\t\t\t\"time\" : startTime,\n\t\t\t\"duration\" : duration\n\t\t});\n\t\t//set the first value\n\t\tthis._param.setValueAtTime(floats[0], startTime);\n\t\t//schedule a lienar ramp for each of the segments\n\t\tfor (var j = 1; j < floats.length; j++){\n\t\t\tvar segmentTime = startTime + (j / (floats.length - 1) * duration);\n\t\t\tthis._param.linearRampToValueAtTime(floats[j], segmentTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.cancelScheduledValues = function (after) {\n\t\tafter = this.toSeconds(after);\n\t\tthis._events.cancel(after);\n\t\tthis._param.cancelScheduledValues(after);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets the computed value at the given time. This provides\n\t * a point from which a linear or exponential curve\n\t * can be scheduled after. Will cancel events after \n\t * the given time and shorten the currently scheduled\n\t * linear or exponential ramp so that it ends at `time` .\n\t * This is to avoid discontinuities and clicks in envelopes. \n\t * @param {Time} time When to set the ramp point\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.setRampPoint = function (time) {\n\t\ttime = this.toSeconds(time);\n\t\t//get the value at the given time\n\t\tvar val = this._toUnits(this.getValueAtTime(time));\n\t\t//if there is an event at the given time\n\t\t//and that even is not a \"set\"\n\t\tvar before = this._searchBefore(time);\n\t\tif (before && before.time === time){\n\t\t\t//remove everything after\n\t\t\tthis.cancelScheduledValues(time + this.sampleTime);\n\t\t} else if (before && \n\t\t\t\t before.type === Tone.TimelineSignal.Type.Curve &&\n\t\t\t\t before.time + before.duration > time){\n\t\t\t//if the curve is still playing\n\t\t\t//cancel the curve\n\t\t\tthis.cancelScheduledValues(time);\n\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t} else {\n\t\t\t//reschedule the next event to end at the given time\n\t\t\tvar after = this._searchAfter(time);\n\t\t\tif (after){\n\t\t\t\t//cancel the next event(s)\n\t\t\t\tthis.cancelScheduledValues(time);\n\t\t\t\tif (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\t\t\tthis.exponentialRampToValueAtTime(val, time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.setValueAtTime(val, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a linear ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the linear ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.linearRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a exponential ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the exponential ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.exponentialRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tGETTING SCHEDULED VALUES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value before or equal to the given time\n\t * @param {Number} time The time to query\n\t * @return {Object} The event at or before the given time.\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchBefore = function(time){\n\t\treturn this._events.get(time);\n\t};\n\n\t/**\n\t * The event after the given time\n\t * @param {Number} time The time to query.\n\t * @return {Object} The next event after the given time\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchAfter = function(time){\n\t\treturn this._events.getAfter(time);\n\t};\n\n\t/**\n\t * Get the scheduled value at the given time. This will\n\t * return the unconverted (raw) value.\n\t * @param {Number} time The time in seconds.\n\t * @return {Number} The scheduled value at the given time.\n\t */\n\tTone.TimelineSignal.prototype.getValueAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tvar after = this._searchAfter(time);\n\t\tvar before = this._searchBefore(time);\n\t\tvar value = this._initial;\n\t\t//if it was set by\n\t\tif (before === null){\n\t\t\tvalue = this._initial;\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Target){\n\t\t\tvar previous = this._events.getBefore(before.time);\n\t\t\tvar previouVal;\n\t\t\tif (previous === null){\n\t\t\t\tpreviouVal = this._initial;\n\t\t\t} else {\n\t\t\t\tpreviouVal = previous.value;\n\t\t\t}\n\t\t\tvalue = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Curve){\n\t\t\tvalue = this._curveInterpolate(before.time, before.value, before.duration, time);\n\t\t} else if (after === null){\n\t\t\tvalue = before.value;\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\tvalue = this._linearInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\tvalue = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else {\n\t\t\tvalue = before.value;\n\t\t}\n\t\treturn value;\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.TimelineSignal} this\n\t * @method\n\t */\n\tTone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUTOMATION CURVE CALCULATIONS\n\t//\tMIT License, copyright (c) 2014 Jordan Santell\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Calculates the the value along the curve produced by setTargetAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {\n\t\treturn v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by linearRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {\n\t\treturn v0 + (v1 - v0) * ((t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by exponentialRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {\n\t\tv0 = Math.max(this._minOutput, v0);\n\t\treturn v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by setValueCurveAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {\n\t\tvar len = curve.length;\n\t\t// If time is after duration, return the last curve value\n\t\tif (time >= start + duration) {\n\t\t\treturn curve[len - 1];\n\t\t} else if (time <= start){\n\t\t\treturn curve[0];\n\t\t} else {\n\t\t\tvar progress = (time - start) / duration;\n\t\t\tvar lowerIndex = Math.floor((len - 1) * progress);\n\t\t\tvar upperIndex = Math.ceil((len - 1) * progress);\n\t\t\tvar lowerVal = curve[lowerIndex];\n\t\t\tvar upperVal = curve[upperIndex];\n\t\t\tif (upperIndex === lowerIndex){\n\t\t\t\treturn lowerVal;\n\t\t\t} else {\n\t\t\t\treturn this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.dispose = function(){\n\t\tTone.Signal.prototype.dispose.call(this);\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._events.dispose();\n\t\tthis._events = null;\n\t};\n\n\treturn Tone.TimelineSignal;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Effect = require('effect');\r\n\r\n /**\r\n *
A p5.Filter uses a Web Audio Biquad Filter to filter\r\n * the frequency response of an input source. Subclasses\r\n * include:
\r\n * p5.LowPass:\r\n * Allows frequencies below the cutoff frequency to pass through,\r\n * and attenuates frequencies above the cutoff. \r\n * p5.HighPass:\r\n * The opposite of a lowpass filter. \r\n * p5.BandPass:\r\n * Allows a range of frequencies to pass through and attenuates\r\n * the frequencies below and above this frequency range. \r\n *\r\n * The .res() method controls either width of the\r\n * bandpass, or resonance of the low/highpass cutoff frequency.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Filter\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\r\n * @example\r\n *
\r\n * var fft, noise, filter;\r\n *\r\n * function setup() {\r\n * fill(255, 40, 255);\r\n *\r\n * filter = new p5.BandPass();\r\n *\r\n * noise = new p5.Noise();\r\n * // disconnect unfiltered noise,\r\n * // and connect to filter\r\n * noise.disconnect();\r\n * noise.connect(filter);\r\n * noise.start();\r\n *\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n *\r\n * // set the BandPass frequency based on mouseX\r\n * var freq = map(mouseX, 0, width, 20, 10000);\r\n * filter.freq(freq);\r\n * // give the filter a narrow band (lower res = wider bandpass)\r\n * filter.res(50);\r\n *\r\n * // draw filtered spectrum\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * for (var i = 0; i < spectrum.length; i++) {\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width/spectrum.length, h);\r\n * }\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * noise.amp(0.5, 0.2);\r\n * } else {\r\n * noise.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Filter = function (type) {\r\n\r\n Effect.call(this);\r\n //add extend Effect by adding a Biquad Filter\r\n\r\n /**\r\n * The p5.Filter is built with a\r\n * \r\n * Web Audio BiquadFilter Node.\r\n *\r\n * @property {DelayNode} biquadFilter\r\n\t */\r\n\r\n this.biquad = this.ac.createBiquadFilter();\r\n\r\n this.input.connect(this.biquad);\r\n\r\n this.biquad.connect(this.wet);\r\n\r\n if (type) {\r\n this.setType(type);\r\n }\r\n\r\n //Properties useful for the toggle method.\r\n this._on = true;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n p5.Filter.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Filter an audio signal according to a set\r\n * of filter parameters.\r\n *\r\n * @method process\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance/Width of the filter frequency\r\n * from 0.001 to 1000\r\n */\r\n p5.Filter.prototype.process = function(src, freq, res, time) {\r\n src.connect(this.input);\r\n this.set(freq, res, time);\r\n };\r\n\r\n\r\n /**\r\n * Set the frequency and the resonance of the filter.\r\n *\r\n * @method set\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Filter.prototype.set = function(freq, res, time) {\r\n if (freq) {\r\n this.freq(freq, time);\r\n }\r\n if (res) {\r\n this.res(res, time);\r\n }\r\n };\r\n\r\n /**\r\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\r\n * human hearing, although in reality most people hear in a narrower\r\n * range).\r\n *\r\n * @method freq\r\n * @param {Number} freq Filter Frequency\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current frequency value\r\n */\r\n p5.Filter.prototype.freq = function(freq, time) {\r\n var t = time || 0;\r\n if (freq <= 0) {\r\n freq = 1;\r\n }\r\n if (typeof freq === 'number') {\r\n this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t);\r\n } else if (freq) {\r\n freq.connect(this.biquad.frequency);\r\n }\r\n return this.biquad.frequency.value;\r\n };\r\n\r\n /**\r\n * Controls either width of a bandpass frequency,\r\n * or the resonance of a low/highpass cutoff frequency.\r\n *\r\n * @method res\r\n * @param {Number} res Resonance/Width of filter freq\r\n * from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current res value\r\n */\r\n p5.Filter.prototype.res = function(res, time) {\r\n var t = time || 0;\r\n if (typeof res === 'number') {\r\n this.biquad.Q.value = res;\r\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);\r\n } else if (res) {\r\n res.connect(this.biquad.Q);\r\n }\r\n return this.biquad.Q.value;\r\n };\r\n\r\n /**\r\n * Controls the gain attribute of a Biquad Filter.\r\n * This is distinctly different from .amp() which is inherited from p5.Effect\r\n * .amp() controls the volume via the output gain node\r\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\r\n *\r\n * @method gain\r\n * @param {Number} gain\r\n * @return {Number} Returns the current or updated gain value\r\n */\r\n p5.Filter.prototype.gain = function(gain, time) {\r\n var t = time || 0;\r\n if (typeof gain === 'number') {\r\n this.biquad.gain.value = gain;\r\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t);\r\n } else if (gain) {\r\n gain.connect(this.biquad.gain);\r\n }\r\n return this.biquad.gain.value;\r\n };\r\n\r\n\r\n /**\r\n * Toggle function. Switches between the specified type and allpass\r\n *\r\n * @method toggle\r\n * @return {boolean} [Toggle value]\r\n */\r\n p5.Filter.prototype.toggle = function() {\r\n this._on = !this._on;\r\n\r\n if (this._on === true) {\r\n this.biquad.type = this._untoggledType;\r\n } else if (this._on === false) {\r\n this.biquad.type = 'allpass';\r\n }\r\n\r\n return this._on;\r\n };\r\n\r\n /**\r\n * Set the type of a p5.Filter. Possible types include:\r\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\r\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\r\n * \"allpass\".\r\n *\r\n * @method setType\r\n * @param {String} t\r\n */\r\n p5.Filter.prototype.setType = function(t) {\r\n this.biquad.type = t;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n\r\n p5.Filter.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n Effect.prototype.dispose.apply(this);\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n delete this.biquad;\r\n }\r\n };\r\n\r\n /**\r\n * Constructor: new p5.LowPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('lowpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.LowPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.LowPass = function() {\r\n p5.Filter.call(this, 'lowpass');\r\n };\r\n p5.LowPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.HighPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('highpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.HighPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.HighPass = function() {\r\n p5.Filter.call(this, 'highpass');\r\n };\r\n p5.HighPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.BandPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('bandpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.BandPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.BandPass = function() {\r\n p5.Filter.call(this, 'bandpass');\r\n };\r\n p5.BandPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n return p5.Filter;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Negate\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Subtract the signal connected to input[1] from the signal connected \n\t * to input[0]. If an argument is provided in the constructor, the \n\t * signals .value will be subtracted from the incoming signal.\n\t *\n\t * @extends {Tone.Signal}\n\t * @constructor\n\t * @param {number=} value The value to subtract from the incoming signal. If the value\n\t * is omitted, it will subtract the second signal from the first.\n\t * @example\n\t * var sub = new Tone.Subtract(1);\n\t * var sig = new Tone.Signal(4).connect(sub);\n\t * //the output of sub is 3. \n\t * @example\n\t * var sub = new Tone.Subtract();\n\t * var sigA = new Tone.Signal(10);\n\t * var sigB = new Tone.Signal(2.5);\n\t * sigA.connect(sub, 0, 0);\n\t * sigB.connect(sub, 0, 1);\n\t * //output of sub is 7.5\n\t */\n\tTone.Subtract = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * negate the input of the second input before connecting it\n\t\t * to the summing node.\n\t\t * @type {Tone.Negate}\n\t\t * @private\n\t\t */\n\t\tthis._neg = new Tone.Negate();\n\n\t\t/**\n\t\t * the node where the value is set\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.chain(this._neg, this._sum);\n\t};\n\n\tTone.extend(Tone.Subtract, Tone.Signal);\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.Subtract.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._neg.dispose();\n\t\tthis._neg = null;\n\t\tthis._sum.disconnect();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Subtract;\n});","'use strict';\r\n\r\nglobal.TONE_SILENCE_VERSION_LOGGING = true;\r\n\r\ndefine(['startaudiocontext', 'Tone/core/Context', 'Tone/core/Tone'], function (StartAudioContext, Context, Tone) {\r\n // Create the Audio Context\r\n const audiocontext = new window.AudioContext();\r\n\r\n // Tone and p5.sound share the same audio context\r\n Tone.context.dispose();\r\n Tone.setContext(audiocontext);\r\n\r\n /**\r\n *
Returns the Audio Context for this sketch. Useful for users\r\n * who would like to dig deeper into the Web Audio API\r\n * .
\r\n *\r\n *
Some browsers require users to startAudioContext\r\n * with a user gesture, such as touchStarted in the example below.
\r\n *\r\n * @method getAudioContext\r\n * @return {Object} AudioContext for this sketch\r\n * @example\r\n *
\r\n * function draw() {\r\n * background(255);\r\n * textAlign(CENTER);\r\n *\r\n * if (getAudioContext().state !== 'running') {\r\n * text('click to start audio', width/2, height/2);\r\n * } else {\r\n * text('audio is enabled', width/2, height/2);\r\n * }\r\n * }\r\n *\r\n * function touchStarted() {\r\n * if (getAudioContext().state !== 'running') {\r\n * getAudioContext().resume();\r\n * }\r\n * var synth = new p5.MonoSynth();\r\n * synth.play('A4', 0.5, 0, 0.2);\r\n * }\r\n *\r\n *
It is a good practice to give users control over starting audio playback.\r\n * This practice is enforced by Google Chrome's autoplay policy as of r70\r\n * (info), iOS Safari, and other browsers.\r\n *
\r\n *\r\n *
\r\n * userStartAudio() starts the Audio Context on a user gesture. It utilizes\r\n * the StartAudioContext library by\r\n * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext.\r\n *
\r\n *\r\n *
Starting the audio context on a user gesture can be as simple as userStartAudio().\r\n * Optional parameters let you decide on a specific element that will start the audio context,\r\n * and/or call a function once the audio context is started.
\r\n * @param {Element|Array} [element(s)] This argument can be an Element,\r\n * Selector String, NodeList, p5.Element,\r\n * jQuery Element, or an Array of any of those.\r\n * @param {Function} [callback] Callback to invoke when the AudioContext has started\r\n * @return {Promise} Returns a Promise which is resolved when\r\n * the AudioContext state is 'running'\r\n * @method userStartAudio\r\n * @for p5\r\n * @example\r\n *
\r\n * function setup() {\r\n * var myDiv = createDiv('click to start audio');\r\n * myDiv.position(0, 0);\r\n *\r\n * var mySynth = new p5.MonoSynth();\r\n *\r\n * // This won't play until the context has started\r\n * mySynth.play('A6');\r\n *\r\n * // Start the audio context on a click/touch event\r\n * userStartAudio().then(function() {\r\n * myDiv.remove();\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.prototype.userStartAudio = function(elements, callback) {\r\n var elt = elements;\r\n if (elements instanceof p5.Element) {\r\n elt = elements.elt;\r\n } else if (elements instanceof Array && elements[0] instanceof p5.Element ) {\r\n elt = elements.map(function(e) { return e.elt});\r\n }\r\n return StartAudioContext(audiocontext, elt, callback);\r\n };\r\n\r\n return audiocontext;\r\n});\r\n","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Emitter gives classes which extend it\n\t * the ability to listen for and emit events. \n\t * Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).\n\t * MIT (c) 2011 Jerome Etienne.\n\t * \n\t * @extends {Tone}\n\t */\n\tTone.Emitter = function(){\n\t\t/**\n\t\t * Contains all of the events.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t\tthis._events = {};\n\t};\n\n\tTone.extend(Tone.Emitter);\n\n\t/**\n\t * Bind a callback to a specific event.\n\t * @param {String} event The name of the event to listen for.\n\t * @param {Function} callback The callback to invoke when the\n\t * event is emitted\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.on = function(event, callback){\n\t\t//split the event\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var i = 0; i < events.length; i++){\n\t\t\tvar eventName = events[i];\n\t\t\tif (!this._events.hasOwnProperty(eventName)){\n\t\t\t\tthis._events[eventName] = [];\n\t\t\t}\n\t\t\tthis._events[eventName].push(callback);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove the event listener.\n\t * @param {String} event The event to stop listening to.\n\t * @param {Function=} callback The callback which was bound to \n\t * the event with Tone.Emitter.on.\n\t * If no callback is given, all callbacks\n\t * events are removed.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.off = function(event, callback){\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var ev = 0; ev < events.length; ev++){\n\t\t\tevent = events[ev];\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tif (Tone.prototype.isUndef(callback)){\n\t\t\t\t\tthis._events[event] = [];\n\t\t\t\t} else {\n\t\t\t\t\tvar eventList = this._events[event];\n\t\t\t\t\tfor (var i = 0; i < eventList.length; i++){\n\t\t\t\t\t\tif (eventList[i] === callback){\n\t\t\t\t\t\t\teventList.splice(i, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Invoke all of the callbacks bound to the event\n\t * with any arguments passed in. \n\t * @param {String} event The name of the event.\n\t * @param {*...} args The arguments to pass to the functions listening.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.emit = function(event){\n\t\tif (this._events){\n\t\t\tvar args = Array.apply(null, arguments).slice(1);\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tvar eventList = this._events[event];\n\t\t\t\tfor (var i = 0, len = eventList.length; i < len; i++){\n\t\t\t\t\teventList[i].apply(this, args);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add Emitter functions (on/off/emit) to the object\n\t * @param {Object|Function} object The object or class to extend.\n\t */\n\tTone.Emitter.mixin = function(object){\n\t\tvar functions = [\"on\", \"off\", \"emit\"];\n\t\tobject._events = {};\n\t\tfor (var i = 0; i < functions.length; i++){\n\t\t\tvar func = functions[i];\n\t\t\tvar emitterFunc = Tone.Emitter.prototype[func];\n\t\t\tobject[func] = emitterFunc;\n\t\t}\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._events = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Emitter;\n});","module.exports = {\r\n recorderProcessor: 'recorder-processor',\r\n soundFileProcessor: 'sound-file-processor',\r\n amplitudeProcessor: 'amplitude-processor'\r\n};\r\n","define([\"Tone/core/Tone\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Base class for all Signals. Used Internally. \n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t */\n\tTone.SignalBase = function(){};\n\n\tTone.extend(Tone.SignalBase);\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.SignalBase.prototype.connect = function(node, outputNumber, inputNumber){\n\t\t//zero it out so that the signal can have full control\n\t\tif ((Tone.Signal && Tone.Signal === node.constructor) || \n\t\t\t\t(Tone.Param && Tone.Param === node.constructor) || \n\t\t\t\t(Tone.TimelineSignal && Tone.TimelineSignal === node.constructor)){\n\t\t\t//cancel changes\n\t\t\tnode._param.cancelScheduledValues(0);\n\t\t\t//reset the value\n\t\t\tnode._param.value = 0;\n\t\t\t//mark the value as overridden\n\t\t\tnode.overridden = true;\n\t\t} else if (node instanceof AudioParam){\n\t\t\tnode.cancelScheduledValues(0);\n\t\t\tnode.value = 0;\n\t\t} \n\t\tTone.prototype.connect.call(this, node, outputNumber, inputNumber);\n\t\treturn this;\n\t};\n\n\treturn Tone.SignalBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Time is a primitive type for encoding Time values. \n\t * Eventually all time values are evaluated to seconds\n\t * using the `eval` method. Tone.Time can be constructed\n\t * with or without the `new` keyword. Tone.Time can be passed\n\t * into the parameter of any method which takes time as an argument. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * var t = Tone.Time(\"4n\");//encodes a quarter note\n\t * t.mult(4); // multiply that value by 4\n\t * t.toNotation(); //returns \"1m\"\n\t */\n\tTone.Time = function(val, units){\n\t\tif (this instanceof Tone.Time){\n\n\t\t\t/**\n\t\t\t * If the current clock time should\n\t\t\t * be added to the output\n\t\t\t * @type {Boolean}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._plusNow = false;\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Time(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Time, Tone.TimeBase);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);\n\n\t/*\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\treturn Tone.Transport.nextSubdivision(rh());\n\t\t}\n\t};\n\n\t/*\n\t * Adds an additional unary expression\n\t * which adds the current clock time.\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.now = {\n\t\tregexp : /^\\+/,\n\t\tmethod : function(lh){\n\t\t\tthis._plusNow = true;\n\t\t\treturn lh();\n\t\t}\n\t};\n\n\t/**\n\t * Quantize the time by the given subdivision. Optionally add a\n\t * percentage which will move the time value towards the ideal\n\t * quantized value by that percentage. \n\t * @param {Number|Time} val The subdivision to quantize to\n\t * @param {NormalRange} [percent=1] Move the time value\n\t * towards the quantized value by\n\t * a percentage.\n\t * @return {Tone.Time} this\n\t * @example\n\t * Tone.Time(21).quantize(2) //returns 22\n\t * Tone.Time(0.6).quantize(\"4n\", 0.5) //returns 0.55\n\t */\n\tTone.Time.prototype.quantize = function(subdiv, percent){\n\t\tpercent = this.defaultArg(percent, 1);\n\t\tthis._expr = function(expr, subdivision, percent){\n\t\t\texpr = expr();\n\t\t\tsubdivision = subdivision.toSeconds();\n\t\t\tvar multiple = Math.round(expr / subdivision);\n\t\t\tvar ideal = multiple * subdivision;\n\t\t\tvar diff = ideal - expr;\n\t\t\treturn expr + diff * percent;\n\t\t}.bind(this, this._expr, new this.constructor(subdiv), percent);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Adds the clock time to the time expression at the \n\t * moment of evaluation. \n\t * @return {Tone.Time} this\n\t */\n\tTone.Time.prototype.addNow = function(){\n\t\tthis._plusNow = true;\n\t\treturn this;\n\t};\n\n\t/**\n\t * @override\n\t * Override the default value return when no arguments are passed in.\n\t * The default value is 'now'\n\t * @private\n\t */\n\tTone.Time.prototype._defaultExpr = function(){\n\t\tthis._plusNow = true;\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.Time} time\n\t * @return {Time}\n\t */\n\tTone.Time.prototype.copy = function(time){\n\t\tTone.TimeBase.prototype.copy.call(this, time);\n\t\tthis._plusNow = time._plusNow;\n\t\treturn this;\n\t};\n\n\t//CONVERSIONS//////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert a Time to Notation. Values will be thresholded to the nearest 128th note. \n\t * @return {Notation} \n\t * @example\n\t * //if the Transport is at 120bpm:\n\t * Tone.Time(2).toNotation();//returns \"1m\"\n\t */\n\tTone.Time.prototype.toNotation = function(){\n\t\tvar time = this.toSeconds();\n\t\tvar testNotations = [\"1m\", \"2n\", \"4n\", \"8n\", \"16n\", \"32n\", \"64n\", \"128n\"];\n\t\tvar retNotation = this._toNotationHelper(time, testNotations);\n\t\t//try the same thing but with tripelets\n\t\tvar testTripletNotations = [\"1m\", \"2n\", \"2t\", \"4n\", \"4t\", \"8n\", \"8t\", \"16n\", \"16t\", \"32n\", \"32t\", \"64n\", \"64t\", \"128n\"];\n\t\tvar retTripletNotation = this._toNotationHelper(time, testTripletNotations);\n\t\t//choose the simpler expression of the two\n\t\tif (retTripletNotation.split(\"+\").length < retNotation.split(\"+\").length){\n\t\t\treturn retTripletNotation;\n\t\t} else {\n\t\t\treturn retNotation;\n\t\t}\n\t};\n\n\t/**\n\t * Helper method for Tone.toNotation\n\t * @param {Number} units \n\t * @param {Array} testNotations\n\t * @return {String}\n\t * @private\n\t */\n\tTone.Time.prototype._toNotationHelper = function(units, testNotations){\n\t\t//the threshold is the last value in the array\n\t\tvar threshold = this._notationToUnits(testNotations[testNotations.length - 1]);\n\t\tvar retNotation = \"\";\n\t\tfor (var i = 0; i < testNotations.length; i++){\n\t\t\tvar notationTime = this._notationToUnits(testNotations[i]);\n\t\t\t//account for floating point errors (i.e. round up if the value is 0.999999)\n\t\t\tvar multiple = units / notationTime;\n\t\t\tvar floatingPointError = 0.000001;\n\t\t\tif (1 - multiple % 1 < floatingPointError){\n\t\t\t\tmultiple += floatingPointError;\n\t\t\t}\n\t\t\tmultiple = Math.floor(multiple);\n\t\t\tif (multiple > 0){\n\t\t\t\tif (multiple === 1){\n\t\t\t\t\tretNotation += testNotations[i];\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += multiple.toString() + \"*\" + testNotations[i];\n\t\t\t\t}\n\t\t\t\tunits -= multiple * notationTime;\n\t\t\t\tif (units < threshold){\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += \" + \";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (retNotation === \"\"){\n\t\t\tretNotation = \"0\";\n\t\t}\n\t\treturn retNotation;\n\t};\n\n\t/**\n\t * Convert a notation value to the current units\n\t * @param {Notation} notation \n\t * @return {Number} \n\t * @private\n\t */\n\tTone.Time.prototype._notationToUnits = function(notation){\n\t\tvar primaryExprs = this._primaryExpressions;\n\t\tvar notationExprs = [primaryExprs.n, primaryExprs.t, primaryExprs.m];\n\t\tfor (var i = 0; i < notationExprs.length; i++){\n\t\t\tvar expr = notationExprs[i];\n\t\t\tvar match = notation.match(expr.regexp);\n\t\t\tif (match){\n\t\t\t\treturn expr.method.call(this, match[1]);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Return the time encoded as Bars:Beats:Sixteenths.\n\t * @return {BarsBeatsSixteenths}\n\t */\n\tTone.Time.prototype.toBarsBeatsSixteenths = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.toSeconds() / quarterTime;\n\t\tvar measures = Math.floor(quarters / this._timeSignature());\n\t\tvar sixteenths = (quarters % 1) * 4;\n\t\tquarters = Math.floor(quarters) % this._timeSignature();\n\t\tsixteenths = sixteenths.toString();\n\t\tif (sixteenths.length > 3){\n\t\t\tsixteenths = parseFloat(sixteenths).toFixed(3);\n\t\t}\n\t\tvar progress = [measures, quarters, sixteenths];\n\t\treturn progress.join(\":\");\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.Time.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time in samples\n\t * @return {Samples} \n\t */\n\tTone.Time.prototype.toSamples = function(){\n\t\treturn this.toSeconds() * this.context.sampleRate;\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t * @example\n\t * Tone.Time(2).toFrequency(); //0.5\n\t */\n\tTone.Time.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.toSeconds = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in milliseconds.\n\t * @return {Milliseconds} \n\t */\n\tTone.Time.prototype.toMilliseconds = function(){\n\t\treturn this.toSeconds() * 1000;\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.valueOf = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow?this.now():0);\n\t};\n\n\treturn Tone.Time;\n});","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TimeBase is a flexible encoding of time\n\t * which can be evaluated to and from a string.\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t * @extends {Tone}\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @example\n\t * Tone.TimeBase(4, \"n\")\n\t * Tone.TimeBase(2, \"t\")\n\t * Tone.TimeBase(\"2t\").add(\"1m\")\n\t * Tone.TimeBase(\"2t + 1m\");\n\t */\n\tTone.TimeBase = function(val, units){\n\n\t\t//allows it to be constructed with or without 'new'\n\t\tif (this instanceof Tone.TimeBase) {\n\n\t\t\t/**\n\t\t\t * Any expressions parsed from the Time\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._expr = this._noOp;\n\n\t\t\tif (val instanceof Tone.TimeBase){\n\t\t\t\tthis.copy(val);\n\t\t\t} else if (!this.isUndef(units) || this.isNumber(val)){\n\t\t\t\t//default units\n\t\t\t\tunits = this.defaultArg(units, this._defaultUnits);\n\t\t\t\tvar method = this._primaryExpressions[units].method;\n\t\t\t\tthis._expr = method.bind(this, val);\n\t\t\t} else if (this.isString(val)){\n\t\t\t\tthis.set(val);\n\t\t\t} else if (this.isUndef(val)){\n\t\t\t\t//default expression\n\t\t\t\tthis._expr = this._defaultExpr();\n\t\t\t}\n\t\t} else {\n\n\t\t\treturn new Tone.TimeBase(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TimeBase);\n\n\t/**\n\t * Repalce the current time value with the value\n\t * given by the expression string.\n\t * @param {String} exprString\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.set = function(exprString){\n\t\tthis._expr = this._parseExprString(exprString);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Return a clone of the TimeBase object.\n\t * @return {Tone.TimeBase} The new cloned Tone.TimeBase\n\t */\n\tTone.TimeBase.prototype.clone = function(){\n\t\tvar instance = new this.constructor();\n\t\tinstance.copy(this);\n\t\treturn instance;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.TimeBase} time\n\t * @return {TimeBase}\n\t */\n\tTone.TimeBase.prototype.copy = function(time){\n\t\tvar val = time._expr();\n\t\treturn this.set(val);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tABSTRACT SYNTAX TREE PARSER\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * All the primary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._primaryExpressions = {\n\t\t\"n\" : {\n\t\t\tregexp : /^(\\d+)n/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\tif (value === 1){\n\t\t\t\t\treturn this._beatsToUnits(this._timeSignature());\n\t\t\t\t} else {\n\t\t\t\t\treturn this._beatsToUnits(4 / value);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"t\" : {\n\t\t\tregexp : /^(\\d+)t/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\treturn this._beatsToUnits(8 / (parseInt(value) * 3));\n\t\t\t}\n\t\t},\n\t\t\"m\" : {\n\t\t\tregexp : /^(\\d+)m/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._beatsToUnits(parseInt(value) * this._timeSignature());\n\t\t\t}\n\t\t},\n\t\t\"i\" : {\n\t\t\tregexp : /^(\\d+)i/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._ticksToUnits(parseInt(value));\n\t\t\t}\n\t\t},\n\t\t\"hz\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)hz/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._frequencyToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"tr\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\t\tvar total = 0;\n\t\t\t\tif (m && m !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t\t}\n\t\t\t\tif (q && q !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(q));\n\t\t\t\t}\n\t\t\t\tif (s && s !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t\t}\n\t\t\t\treturn total;\n\t\t\t}\n\t\t},\n\t\t\"s\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?s)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._secondsToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"samples\" : {\n\t\t\tregexp : /^(\\d+)samples/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn parseInt(value) / this.context.sampleRate;\n\t\t\t}\n\t\t},\n\t\t\"default\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._primaryExpressions[this._defaultUnits].method.call(this, value);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the binary expressions that TimeBase can accept.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._binaryExpressions = {\n\t\t\"+\" : {\n\t\t\tregexp : /^\\+/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() + rh();\n\t\t\t}\n\t\t},\n\t\t\"-\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() - rh();\n\t\t\t}\n\t\t},\n\t\t\"*\" : {\n\t\t\tregexp : /^\\*/,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() * rh();\n\t\t\t}\n\t\t},\n\t\t\"/\" : {\n\t\t\tregexp : /^\\//,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() / rh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the unary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._unaryExpressions = {\n\t\t\"neg\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tmethod : function(lh){\n\t\t\t\treturn -lh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Syntactic glue which holds expressions together\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._syntaxGlue = {\n\t\t\"(\" : {\n\t\t\tregexp : /^\\(/\n\t\t},\n\t\t\")\" : {\n\t\t\tregexp : /^\\)/\n\t\t}\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.TimeBase.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr, this);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr, context){\n\t\t\tvar expressions = [\"_binaryExpressions\", \"_unaryExpressions\", \"_primaryExpressions\", \"_syntaxGlue\"];\n\t\t\tfor (var i = 0; i < expressions.length; i++){\n\t\t\t\tvar group = context[expressions[i]];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tmethod : op.method,\n\t\t\t\t\t\t\tprecedence : op.precedence,\n\t\t\t\t\t\t\tregexp : op.regexp,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * Given a token, find the value within the groupName\n\t * @param {Object} token\n\t * @param {String} groupName\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._matchGroup = function(token, group, prec) {\n\t\tvar ret = false;\n\t\tif (!this.isUndef(token)){\n\t\t\tfor (var opName in group){\n\t\t\t\tvar op = group[opName];\n\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\tif (!this.isUndef(prec)){\n\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\treturn op;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn op;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * Match a binary expression given the token and the precedence\n\t * @param {Lexer} lexer\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseBinary = function(lexer, precedence){\n\t\tif (this.isUndef(precedence)){\n\t\t\tprecedence = 2;\n\t\t}\n\t\tvar expr;\n\t\tif (precedence < 0){\n\t\t\texpr = this._parseUnary(lexer);\n\t\t} else {\n\t\t\texpr = this._parseBinary(lexer, precedence - 1);\n\t\t}\n\t\tvar token = lexer.peek();\n\t\twhile (token && this._matchGroup(token, this._binaryExpressions, precedence)){\n\t\t\ttoken = lexer.next();\n\t\t\texpr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));\n\t\t\ttoken = lexer.peek();\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * Match a unary expression.\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseUnary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tvar op = this._matchGroup(token, this._unaryExpressions);\n\t\tif (op) {\n\t\t\ttoken = lexer.next();\n\t\t\texpr = this._parseUnary(lexer);\n\t\t\treturn op.method.bind(this, expr);\n\t\t}\n\t\treturn this._parsePrimary(lexer);\n\t};\n\n\t/**\n\t * Match a primary expression (a value).\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parsePrimary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tif (this.isUndef(token)) {\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected end of expression\");\n\t\t}\n\t\tif (this._matchGroup(token, this._primaryExpressions)) {\n\t\t\ttoken = lexer.next();\n\t\t\tvar matching = token.value.match(token.regexp);\n\t\t\treturn token.method.bind(this, matching[1], matching[2], matching[3]);\n\t\t}\n\t\tif (token && token.value === \"(\"){\n\t\t\tlexer.next();\n\t\t\texpr = this._parseBinary(lexer);\n\t\t\ttoken = lexer.next();\n\t\t\tif (!(token && token.value === \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\t\tthrow new SyntaxError(\"Tone.TimeBase: Cannot process token \" + token.value);\n\t};\n\n\t/**\n\t * Recursively parse the string expression into a syntax tree.\n\t * @param {string} expr \n\t * @return {Function} the bound method to be evaluated later\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseExprString = function(exprString){\n\t\tif (!this.isString(exprString)){\n\t\t\texprString = exprString.toString();\n\t\t}\n\t\tvar lexer = this._tokenize(exprString);\n\t\tvar tree = this._parseBinary(lexer);\n\t\treturn tree;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tDEFAULTS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The initial expression value\n\t * @return {Number} The initial value 0\n\t * @private\n\t */\n\tTone.TimeBase.prototype._noOp = function(){\n\t\treturn 0;\n\t};\n\n\t/**\n\t * The default expression value if no arguments are given\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultExpr = function(){\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultUnits = \"s\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._frequencyToUnits = function(freq){\n\t\treturn 1/freq;\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._beatsToUnits = function(beats){\n\t\treturn (60 / Tone.Transport.bpm.value) * beats;\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._secondsToUnits = function(seconds){\n\t\treturn seconds;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._ticksToUnits = function(ticks){\n\t\treturn ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time signature.\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._timeSignature = function(){\n\t\treturn Tone.Transport.timeSignature;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Push an expression onto the expression list\n\t * @param {Time} val\n\t * @param {String} type\n\t * @param {String} units\n\t * @return {Tone.TimeBase} \n\t * @private\n\t */\n\tTone.TimeBase.prototype._pushExpr = function(val, name, units){\n\t\t//create the expression\n\t\tif (!(val instanceof Tone.TimeBase)){\n\t\t\tval = new this.constructor(val, units);\n\t\t}\n\t\tthis._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add to the current value.\n\t * @param {Time} val The value to add\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").add(\"1m\"); //\"3m\"\n\t */\n\tTone.TimeBase.prototype.add = function(val, units){\n\t\treturn this._pushExpr(val, \"+\", units);\n\t};\n\n\t/**\n\t * Subtract the value from the current time.\n\t * @param {Time} val The value to subtract\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").sub(\"1m\"); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.sub = function(val, units){\n\t\treturn this._pushExpr(val, \"-\", units);\n\t};\n\n\t/**\n\t * Multiply the current value by the given time.\n\t * @param {Time} val The value to multiply\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").mult(\"2\"); //\"4m\"\n\t */\n\tTone.TimeBase.prototype.mult = function(val, units){\n\t\treturn this._pushExpr(val, \"*\", units);\n\t};\n\n\t/**\n\t * Divide the current value by the given time.\n\t * @param {Time} val The value to divide by\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").div(2); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.div = function(val, units){\n\t\treturn this._pushExpr(val, \"/\", units);\n\t};\n\n\t/**\n\t * Evaluate the time value. Returns the time\n\t * in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.TimeBase.prototype.valueOf = function(){\n\t\treturn this._expr();\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.dispose = function(){\n\t\tthis._expr = null;\n\t};\n\n\treturn Tone.TimeBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Param wraps the native Web Audio's AudioParam to provide\n\t * additional unit conversion functionality. It also\n\t * serves as a base-class for classes which have a single,\n\t * automatable parameter. \n\t * @extends {Tone}\n\t * @param {AudioParam} param The parameter to wrap.\n\t * @param {Tone.Type} units The units of the audio param.\n\t * @param {Boolean} convert If the param should be converted.\n\t */\n\tTone.Param = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"param\", \"units\", \"convert\"], Tone.Param.defaults);\n\n\t\t/**\n\t\t * The native parameter to control\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input = options.param;\n\n\t\t/**\n\t\t * The units of the parameter\n\t\t * @type {Tone.Type}\n\t\t */\n\t\tthis.units = options.units;\n\n\t\t/**\n\t\t * If the value should be converted or not\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis.convert = options.convert;\n\n\t\t/**\n\t\t * True if the signal value is being overridden by \n\t\t * a connected signal.\n\t\t * @readOnly\n\t\t * @type {boolean}\n\t\t * @private\n\t\t */\n\t\tthis.overridden = false;\n\n\t\t/**\n\t\t * If there is an LFO, this is where it is held.\n\t\t * @type {Tone.LFO}\n\t\t * @private\n\t\t */\n\t\tthis._lfo = null;\n\n\t\tif (this.isObject(options.lfo)){\n\t\t\tthis.value = options.lfo;\n\t\t} else if (!this.isUndef(options.value)){\n\t\t\tthis.value = options.value;\n\t\t}\n\t};\n\n\tTone.extend(Tone.Param);\n\t\n\t/**\n\t * Defaults\n\t * @type {Object}\n\t * @const\n\t */\n\tTone.Param.defaults = {\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t\t\"param\" : undefined\n\t};\n\n\t/**\n\t * The current value of the parameter. \n\t * @memberOf Tone.Param#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._toUnits(this._param.value);\n\t\t},\n\t\tset : function(value){\n\t\t\tif (this.isObject(value)){\n\t\t\t\t//throw an error if the LFO needs to be included\n\t\t\t\tif (this.isUndef(Tone.LFO)){\n\t\t\t\t\tthrow new Error(\"Include 'Tone.LFO' to use an LFO as a Param value.\");\n\t\t\t\t}\n\t\t\t\t//remove the old one\n\t\t\t\tif (this._lfo){\n\t\t\t\t\tthis._lfo.dispose();\n\t\t\t\t}\n\t\t\t\tthis._lfo = new Tone.LFO(value).start();\n\t\t\t\tthis._lfo.connect(this.input);\n\t\t\t} else {\n\t\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\t\tthis._param.cancelScheduledValues(0);\n\t\t\t\tthis._param.value = convertedVal;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Convert the given value from the type specified by Tone.Param.units\n\t * into the destination value (such as Gain or Frequency).\n\t * @private\n\t * @param {*} val the value to convert\n\t * @return {number} the number which the value should be set to\n\t */\n\tTone.Param.prototype._fromUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Time: \n\t\t\t\t\treturn this.toSeconds(val);\n\t\t\t\tcase Tone.Type.Frequency: \n\t\t\t\t\treturn this.toFrequency(val);\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.dbToGain(val);\n\t\t\t\tcase Tone.Type.NormalRange: \n\t\t\t\t\treturn Math.min(Math.max(val, 0), 1);\n\t\t\t\tcase Tone.Type.AudioRange: \n\t\t\t\t\treturn Math.min(Math.max(val, -1), 1);\n\t\t\t\tcase Tone.Type.Positive: \n\t\t\t\t\treturn Math.max(val, 0);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * Convert the parameters value into the units specified by Tone.Param.units.\n\t * @private\n\t * @param {number} val the value to convert\n\t * @return {number}\n\t */\n\tTone.Param.prototype._toUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.gainToDb(val);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * the minimum output value\n\t * @type {Number}\n\t * @private\n\t */\n\tTone.Param.prototype._minOutput = 0.00001;\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.Param} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.Param.prototype.setValueAtTime = function(value, time){\n\t\tvalue = this._fromUnits(value);\n\t\ttime = this.toSeconds(time);\n\t\tif (time <= this.now() + this.blockTime){\n\t\t\tthis._param.value = value;\n\t\t} else {\n\t\t\tthis._param.setValueAtTime(value, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Creates a schedule point with the current value at the current time.\n\t * This is useful for creating an automation anchor point in order to \n\t * schedule changes from the current value. \n\t *\n\t * @param {number=} now (Optionally) pass the now value in. \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setRampPoint = function(now){\n\t\tnow = this.defaultArg(now, this.now());\n\t\tvar currentVal = this._param.value;\n\t\t// exponentialRampToValueAt cannot ever ramp from or to 0\n\t\t// More info: https://bugzilla.mozilla.org/show_bug.cgi?id=1125600#c2\n\t\tif (currentVal === 0){\n\t\t\tcurrentVal = this._minOutput;\n\t\t}\n\t\tthis._param.setValueAtTime(currentVal, now);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.linearRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tthis._param.linearRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.exponentialRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\tthis._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //exponentially ramp to the value 2 over 4 seconds. \n\t * signal.exponentialRampToValue(2, 4);\n\t */\n\tTone.Param.prototype.exponentialRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an linear continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //linearly ramp to the value 4 over 3 seconds. \n\t * signal.linearRampToValue(4, 3);\n\t */\n\tTone.Param.prototype.linearRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.Param} this \n\t */\n\tTone.Param.prototype.setTargetAtTime = function(value, startTime, timeConstant){\n\t\tvalue = this._fromUnits(value);\n\t\t// The value will never be able to approach without timeConstant > 0.\n\t\t// http://www.w3.org/TR/webaudio/#dfn-setTargetAtTime, where the equation\n\t\t// is described. 0 results in a division by 0.\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tthis._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets an array of arbitrary parameter values starting at the given time\n\t * for the given duration.\n\t * \t\n\t * @param {Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setValueCurveAtTime = function(values, startTime, duration){\n\t\tfor (var i = 0; i < values.length; i++){\n\t\t\tvalues[i] = this._fromUnits(values[i]);\n\t\t}\n\t\tthis._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.cancelScheduledValues = function(startTime){\n\t\tthis._param.cancelScheduledValues(this.toSeconds(startTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Ramps to the given value over the duration of the rampTime. \n\t * Automatically selects the best ramp type (exponential or linear)\n\t * depending on the `units` of the signal\n\t * \n\t * @param {number} value \n\t * @param {Time} rampTime \tThe time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //ramp to the value either linearly or exponentially \n\t * //depending on the \"units\" value of the signal\n\t * signal.rampTo(0, 10);\n\t * @example\n\t * //schedule it to ramp starting at a specific time\n\t * signal.rampTo(0, 10, 5)\n\t */\n\tTone.Param.prototype.rampTo = function(value, rampTime, startTime){\n\t\trampTime = this.defaultArg(rampTime, 0);\n\t\tif (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels){\n\t\t\tthis.exponentialRampToValue(value, rampTime, startTime);\n\t\t} else {\n\t\t\tthis.linearRampToValue(value, rampTime, startTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * The LFO created by the signal instance. If none\n\t * was created, this is null.\n\t * @type {Tone.LFO}\n\t * @readOnly\n\t * @memberOf Tone.Param#\n\t * @name lfo\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"lfo\", {\n\t\tget : function(){\n\t\t\treturn this._lfo;\n\t\t}\n\t});\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tif (this._lfo){\n\t\t\tthis._lfo.dispose();\n\t\t\tthis._lfo = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\treturn Tone.Param;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
Creates a signal that oscillates between -1.0 and 1.0.\r\n * By default, the oscillation takes the form of a sinusoidal\r\n * shape ('sine'). Additional types include 'triangle',\r\n * 'sawtooth' and 'square'. The frequency defaults to\r\n * 440 oscillations per second (440Hz, equal to the pitch of an\r\n * 'A' note).
\r\n *\r\n *
Set the type of oscillation with setType(), or by instantiating a\r\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\r\n *
\r\n *\r\n * @class p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] frequency defaults to 440Hz\r\n * @param {String} [type] type of oscillator. Options:\r\n * 'sine' (default), 'triangle',\r\n * 'sawtooth', 'square'\r\n * @example\r\n *
\r\n * var osc;\r\n * var playing = false;\r\n *\r\n * function setup() {\r\n * backgroundColor = color(255,0,255);\r\n * textAlign(CENTER);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.setType('sine');\r\n * osc.freq(240);\r\n * osc.amp(0);\r\n * osc.start();\r\n * }\r\n *\r\n * function draw() {\r\n * background(backgroundColor)\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * if (!playing) {\r\n * // ramp amplitude to 0.5 over 0.05 seconds\r\n * osc.amp(0.5, 0.05);\r\n * playing = true;\r\n * backgroundColor = color(0,255,255);\r\n * } else {\r\n * // ramp amplitude to 0 over 0.5 seconds\r\n * osc.amp(0, 0.5);\r\n * playing = false;\r\n * backgroundColor = color(255,0,255);\r\n * }\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Oscillator = function(freq, type) {\r\n if (typeof freq === 'string') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n } if (typeof type === 'number') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n }\r\n this.started = false;\r\n\r\n // components\r\n this.phaseAmount = undefined;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.f = freq || 440.0; // frequency\r\n this.oscillator.type = type || 'sine';\r\n this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime);\r\n\r\n // connections\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this._freqMods = []; // modulators connected to this oscillator's frequency\r\n\r\n // set default output gain to 0.5\r\n this.output.gain.value = 0.5;\r\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\r\n\r\n this.oscillator.connect(this.output);\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.connection = p5sound.input; // connect to p5sound by default\r\n this.panner = new p5.Panner(this.output, this.connection, 1);\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.output];\r\n\r\n // add to the soundArray so we can dispose of the osc later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start an oscillator. Accepts an optional parameter to\r\n * determine how long (in seconds from now) until the\r\n * oscillator starts.\r\n *\r\n * @method start\r\n * @for p5.Oscillator\r\n * @param {Number} [time] startTime in seconds from now.\r\n * @param {Number} [frequency] frequency in Hz.\r\n */\r\n p5.Oscillator.prototype.start = function(time, f) {\r\n if (this.started) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n }\r\n if (!this.started) {\r\n var freq = f || this.f;\r\n var type = this.oscillator.type;\r\n\r\n // set old osc free to be garbage collected (memory)\r\n if (this.oscillator) {\r\n this.oscillator.disconnect();\r\n delete this.oscillator;\r\n }\r\n\r\n // var detune = this.oscillator.frequency.value;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.oscillator.frequency.value = Math.abs(freq);\r\n this.oscillator.type = type;\r\n // this.oscillator.detune.value = detune;\r\n this.oscillator.connect(this.output);\r\n time = time || 0;\r\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\r\n this.freqNode = this.oscillator.frequency;\r\n\r\n // if other oscillators are already connected to this osc's freq\r\n for (var i in this._freqMods) {\r\n if (typeof this._freqMods[i].connect !== 'undefined') {\r\n this._freqMods[i].connect(this.oscillator.frequency);\r\n }\r\n }\r\n\r\n this.started = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop an oscillator. Accepts an optional parameter\r\n * to determine how long (in seconds from now) until the\r\n * oscillator stops.\r\n *\r\n * @method stop\r\n * @for p5.Oscillator\r\n * @param {Number} secondsFromNow Time, in seconds from now.\r\n */\r\n p5.Oscillator.prototype.stop = function(time) {\r\n if (this.started) {\r\n var t = time || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.oscillator.stop(t + now);\r\n this.started = false;\r\n }\r\n };\r\n\r\n /**\r\n * Set the amplitude between 0 and 1.0. Or, pass in an object\r\n * such as an oscillator to modulate amplitude with an audio signal.\r\n *\r\n * @method amp\r\n * @for p5.Oscillator\r\n * @param {Number|Object} vol between 0 and 1.0\r\n * or a modulating signal/oscillator\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {AudioParam} gain If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's\r\n * gain/amplitude/volume)\r\n */\r\n p5.Oscillator.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var self = this;\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n\r\n else if (vol) {\r\n vol.connect(self.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // these are now the same thing\r\n p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;\r\n\r\n p5.Oscillator.prototype.getAmp = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set frequency of an oscillator to a value. Or, pass in an object\r\n * such as an oscillator to modulate the frequency with an audio signal.\r\n *\r\n * @method freq\r\n * @for p5.Oscillator\r\n * @param {Number|Object} Frequency Frequency in Hz\r\n * or modulating signal/oscillator\r\n * @param {Number} [rampTime] Ramp time (in seconds)\r\n * @param {Number} [timeFromNow] Schedule this event to happen\r\n * at x seconds from now\r\n * @return {AudioParam} Frequency If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's frequency\r\n * @example\r\n *
\r\n * var osc = new p5.Oscillator(300);\r\n * osc.start();\r\n * osc.freq(40, 10);\r\n *
\r\n */\r\n p5.Oscillator.prototype.freq = function(val, rampTime, tFromNow) {\r\n if (typeof val === 'number' && !isNaN(val)) {\r\n this.f = val;\r\n var now = p5sound.audiocontext.currentTime;\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var t = now + tFromNow + rampTime;\r\n // var currentFreq = this.oscillator.frequency.value;\r\n // this.oscillator.frequency.cancelScheduledValues(now);\r\n\r\n if (rampTime === 0) {\r\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\r\n } else {\r\n if (val > 0 ) {\r\n this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);\r\n } else {\r\n this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now);\r\n }\r\n }\r\n\r\n // reset phase if oscillator has a phase\r\n if (this.phaseAmount) {\r\n this.phase(this.phaseAmount);\r\n }\r\n\r\n } else if (val) {\r\n if (val.output) {\r\n val = val.output;\r\n }\r\n val.connect(this.oscillator.frequency);\r\n\r\n // keep track of what is modulating this param\r\n // so it can be re-connected if\r\n this._freqMods.push( val );\r\n } else {\r\n // return the Frequency Node\r\n return this.oscillator.frequency;\r\n }\r\n };\r\n\r\n p5.Oscillator.prototype.getFreq = function() {\r\n return this.oscillator.frequency.value;\r\n };\r\n\r\n /**\r\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\r\n *\r\n * @method setType\r\n * @for p5.Oscillator\r\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\r\n */\r\n p5.Oscillator.prototype.setType = function(type) {\r\n this.oscillator.type = type;\r\n };\r\n\r\n p5.Oscillator.prototype.getType = function() {\r\n return this.oscillator.type;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.Oscillator\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.Oscillator.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n this.connection = unit.input;\r\n }\r\n else {\r\n this.panner.connect(unit);\r\n this.connection = unit;\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.Oscillator\r\n */\r\n p5.Oscillator.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n if (this.output) {\r\n this.output.connect(this.panner);\r\n }\r\n }\r\n this.oscMods = [];\r\n };\r\n\r\n /**\r\n * Pan between Left (-1) and Right (1)\r\n *\r\n * @method pan\r\n * @for p5.Oscillator\r\n * @param {Number} panning Number between -1 and 1\r\n * @param {Number} timeFromNow schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Oscillator.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n p5.Oscillator.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n // get rid of the oscillator\r\n p5.Oscillator.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.oscillator) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n this.disconnect();\r\n this.panner = null;\r\n this.oscillator = null;\r\n }\r\n // if it is a Pulse\r\n if (this.osc2) {\r\n this.osc2.dispose();\r\n }\r\n };\r\n\r\n /**\r\n * Set the phase of an oscillator between 0.0 and 1.0.\r\n * In this implementation, phase is a delay time\r\n * based on the oscillator's current frequency.\r\n *\r\n * @method phase\r\n * @for p5.Oscillator\r\n * @param {Number} phase float between 0.0 and 1.0\r\n */\r\n p5.Oscillator.prototype.phase = function(p) {\r\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1/this.f);\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n this.phaseAmount = p;\r\n\r\n if (!this.dNode) {\r\n // create a delay node\r\n this.dNode = p5sound.audiocontext.createDelay();\r\n // put the delay node in between output and panner\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.dNode);\r\n this.dNode.connect(this.output);\r\n }\r\n\r\n // set delay time to match phase:\r\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\r\n };\r\n\r\n // ========================== //\r\n // SIGNAL MATH FOR MODULATION //\r\n // ========================== //\r\n\r\n // return sigChain(this, scale, thisChain, nextChain, Scale);\r\n var sigChain = function(o, mathObj, thisChain, nextChain, type) {\r\n var chainSource = o.oscillator;\r\n // if this type of math already exists in the chain, replace it\r\n for (var i in o.mathOps) {\r\n if (o.mathOps[i] instanceof type) {\r\n chainSource.disconnect();\r\n o.mathOps[i].dispose();\r\n thisChain = i;\r\n // assume nextChain is output gain node unless...\r\n if (thisChain < o.mathOps.length - 2) {\r\n nextChain = o.mathOps[i+1];\r\n }\r\n }\r\n }\r\n if (thisChain === o.mathOps.length - 1) {\r\n o.mathOps.push(nextChain);\r\n }\r\n // assume source is the oscillator unless i > 0\r\n if (i > 0) {\r\n chainSource = o.mathOps[i-1];\r\n }\r\n chainSource.disconnect();\r\n chainSource.connect(mathObj);\r\n mathObj.connect(nextChain);\r\n o.mathOps[thisChain] = mathObj;\r\n return o;\r\n };\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method again\r\n * will override the initial add() with a new value.\r\n *\r\n * @method add\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n *\r\n */\r\n p5.Oscillator.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Oscillator's output amplitude\r\n * by a fixed value (i.e. turn it up!). Calling this method\r\n * again will override the initial mult() with a new value.\r\n *\r\n * @method mult\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with multiplied output\r\n */\r\n p5.Oscillator.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this oscillator's amplitude values to a given\r\n * range, and return the oscillator. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Oscillator\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n */\r\n p5.Oscillator.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, scale, thisChain, nextChain, Scale);\r\n\r\n // this.output.disconnect();\r\n // this.output.connect(scale)\r\n };\r\n\r\n // ============================== //\r\n // SinOsc, TriOsc, SqrOsc, SawOsc //\r\n // ============================== //\r\n\r\n /**\r\n * Constructor: new p5.SinOsc().\r\n * This creates a Sine Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sine')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sine').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SinOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SinOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sine');\r\n };\r\n\r\n p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.TriOsc().\r\n * This creates a Triangle Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('triangle')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('triangle').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.TriOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.TriOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'triangle');\r\n };\r\n\r\n p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SawOsc().\r\n * This creates a SawTooth Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sawtooth')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sawtooth').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SawOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SawOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sawtooth');\r\n };\r\n\r\n p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SqrOsc().\r\n * This creates a Square Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('square')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('square').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SqrOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SqrOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'square');\r\n };\r\n\r\n p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline class for scheduling and maintaining state\n\t * along a timeline. All events must have a \"time\" property. \n\t * Internally, events are stored in time order for fast \n\t * retrieval.\n\t * @extends {Tone}\n\t * @param {Positive} [memory=Infinity] The number of previous events that are retained.\n\t */\n\tTone.Timeline = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"memory\"], Tone.Timeline.defaults);\n\n\t\t/**\n\t\t * The array of scheduled timeline events\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._timeline = [];\n\n\t\t/**\n\t\t * An array of items to remove from the list. \n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._toRemove = [];\n\n\t\t/**\n\t\t * Flag if the tieline is mid iteration\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._iterating = false;\n\n\t\t/**\n\t\t * The memory of the timeline, i.e.\n\t\t * how many events in the past it will retain\n\t\t * @type {Positive}\n\t\t */\n\t\tthis.memory = options.memory;\n\t};\n\n\tTone.extend(Tone.Timeline);\n\n\t/**\n\t * the default parameters\n\t * @static\n\t * @const\n\t */\n\tTone.Timeline.defaults = {\n\t\t\"memory\" : Infinity\n\t};\n\n\t/**\n\t * The number of items in the timeline.\n\t * @type {Number}\n\t * @memberOf Tone.Timeline#\n\t * @name length\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Timeline.prototype, \"length\", {\n\t\tget : function(){\n\t\t\treturn this._timeline.length;\n\t\t}\n\t});\n\n\t/**\n\t * Insert an event object onto the timeline. Events must have a \"time\" attribute.\n\t * @param {Object} event The event object to insert into the \n\t * timeline. \n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.add = function(event){\n\t\t//the event needs to have a time attribute\n\t\tif (this.isUndef(event.time)){\n\t\t\tthrow new Error(\"Tone.Timeline: events must have a time attribute\");\n\t\t}\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(event.time);\n\t\t\tthis._timeline.splice(index + 1, 0, event);\n\t\t} else {\n\t\t\tthis._timeline.push(event);\t\t\t\n\t\t}\n\t\t//if the length is more than the memory, remove the previous ones\n\t\tif (this.length > this.memory){\n\t\t\tvar diff = this.length - this.memory;\n\t\t\tthis._timeline.splice(0, diff);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove an event from the timeline.\n\t * @param {Object} event The event object to remove from the list.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.remove = function(event){\n\t\tif (this._iterating){\n\t\t\tthis._toRemove.push(event);\n\t\t} else {\n\t\t\tvar index = this._timeline.indexOf(event);\n\t\t\tif (index !== -1){\n\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the nearest event whose time is less than or equal to the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object set after that time.\n\t */\n\tTone.Timeline.prototype.get = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index !== -1){\n\t\t\treturn this._timeline[index];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Return the first event in the timeline without removing it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.peek = function(){\n\t\treturn this._timeline[0];\n\t};\n\n\t/**\n\t * Return the first event in the timeline and remove it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.shift = function(){\n\t\treturn this._timeline.shift();\n\t};\n\n\t/**\n\t * Get the event which is scheduled after the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object after the given time\n\t */\n\tTone.Timeline.prototype.getAfter = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index + 1 < this._timeline.length){\n\t\t\treturn this._timeline[index + 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Get the event before the event at the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object before the given time\n\t */\n\tTone.Timeline.prototype.getBefore = function(time){\n\t\tvar len = this._timeline.length;\n\t\t//if it's after the last item, return the last item\n\t\tif (len > 0 && this._timeline[len - 1].time < time){\n\t\t\treturn this._timeline[len - 1];\n\t\t}\n\t\tvar index = this._search(time);\n\t\tif (index - 1 >= 0){\n\t\t\treturn this._timeline[index - 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Cancel events after the given time\n\t * @param {Number} time The time to query.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancel = function(after){\n\t\tif (this._timeline.length > 1){\n\t\t\tvar index = this._search(after);\n\t\t\tif (index >= 0){\n\t\t\t\tif (this._timeline[index].time === after){\n\t\t\t\t\t//get the first item with that time\n\t\t\t\t\tfor (var i = index; i >= 0; i--){\n\t\t\t\t\t\tif (this._timeline[i].time === after){\n\t\t\t\t\t\t\tindex = i;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index);\n\t\t\t\t} else {\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t} else if (this._timeline.length === 1){\n\t\t\t//the first item's time\n\t\t\tif (this._timeline[0].time >= after){\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancel events before or equal to the given time.\n\t * @param {Number} time The time to cancel before.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancelBefore = function(time){\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(time);\n\t\t\tif (index >= 0){\n\t\t\t\tthis._timeline = this._timeline.slice(index + 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Does a binary serach on the timeline array and returns the \n\t * nearest event index whose time is after or equal to the given time.\n\t * If a time is searched before the first index in the timeline, -1 is returned.\n\t * If the time is after the end, the index of the last item is returned.\n\t * @param {Number} time \n\t * @return {Number} the index in the timeline array \n\t * @private\n\t */\n\tTone.Timeline.prototype._search = function(time){\n\t\tvar beginning = 0;\n\t\tvar len = this._timeline.length;\n\t\tvar end = len;\n\t\tif (len > 0 && this._timeline[len - 1].time <= time){\n\t\t\treturn len - 1;\n\t\t}\n\t\twhile (beginning < end){\n\t\t\t// calculate the midpoint for roughly equal partition\n\t\t\tvar midPoint = Math.floor(beginning + (end - beginning) / 2);\n\t\t\tvar event = this._timeline[midPoint];\n\t\t\tvar nextEvent = this._timeline[midPoint + 1];\n\t\t\tif (event.time === time){\n\t\t\t\t//choose the last one that has the same time\n\t\t\t\tfor (var i = midPoint; i < this._timeline.length; i++){\n\t\t\t\t\tvar testEvent = this._timeline[i];\n\t\t\t\t\tif (testEvent.time === time){\n\t\t\t\t\t\tmidPoint = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time < time && nextEvent.time > time){\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time > time){\n\t\t\t\t//search lower\n\t\t\t\tend = midPoint;\n\t\t\t} else if (event.time < time){\n\t\t\t\t//search upper\n\t\t\t\tbeginning = midPoint + 1;\n\t\t\t} \n\t\t}\n\t\treturn -1;\n\t};\n\n\t/**\n\t * Internal iterator. Applies extra safety checks for \n\t * removing items from the array. \n\t * @param {Function} callback \n\t * @param {Number=} lowerBound \n\t * @param {Number=} upperBound \n\t * @private\n\t */\n\tTone.Timeline.prototype._iterate = function(callback, lowerBound, upperBound){\n\t\tthis._iterating = true;\n\t\tlowerBound = this.defaultArg(lowerBound, 0);\n\t\tupperBound = this.defaultArg(upperBound, this._timeline.length - 1);\n\t\tfor (var i = lowerBound; i <= upperBound; i++){\n\t\t\tcallback(this._timeline[i]);\n\t\t}\n\t\tthis._iterating = false;\n\t\tif (this._toRemove.length > 0){\n\t\t\tfor (var j = 0; j < this._toRemove.length; j++){\n\t\t\t\tvar index = this._timeline.indexOf(this._toRemove[j]);\n\t\t\t\tif (index !== -1){\n\t\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._toRemove = [];\n\t\t}\n\t};\n\n\t/**\n\t * Iterate over everything in the array\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEach = function(callback){\n\t\tthis._iterate(callback);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or before the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachBefore = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(callback, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array after the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAfter = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or after the given time. Similar to \n\t * forEachAfter, but includes the item(s) at the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachFrom = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\t//work backwards until the event time is less than time\n\t\twhile (lowerBound >= 0 && this._timeline[lowerBound].time >= time){\n\t\t\tlowerBound--;\n\t\t}\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at the given time\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAtTime = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(function(event){\n\t\t\t\tif (event.time === time){\n\t\t\t\t\tcallback(event);\n\t\t\t\t} \n\t\t\t}, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._timeline = null;\n\t\tthis._toRemove = null;\n\t};\n\n\treturn Tone.Timeline;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Negate the incoming signal. i.e. an input signal of 10 will output -10\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var neg = new Tone.Negate();\n\t * var sig = new Tone.Signal(-2).connect(neg);\n\t * //output of neg is positive 2. \n\t */\n\tTone.Negate = function(){\n\t\t/**\n\t\t * negation is done by multiplying by -1\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = this.input = this.output = new Tone.Multiply(-1);\n\t};\n\n\tTone.extend(Tone.Negate, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Negate} this\n\t */\n\tTone.Negate.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Negate;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Multiply\", \"Tone/signal/WaveShaper\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class GreaterThanZero outputs 1 when the input is strictly greater than zero\n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var gt0 = new Tone.GreaterThanZero();\n\t * var sig = new Tone.Signal(0.01).connect(gt0);\n\t * //the output of gt0 is 1. \n\t * sig.value = 0;\n\t * //the output of gt0 is 0. \n\t */\n\tTone.GreaterThanZero = function(){\n\t\t\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._thresh = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val <= 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}, 127);\n\n\t\t/**\n\t\t * scale the first thresholded signal by a large value.\n\t\t * this will help with values which are very close to 0\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(10000);\n\n\t\t//connections\n\t\tthis._scale.connect(this._thresh);\n\t};\n\n\tTone.extend(Tone.GreaterThanZero, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThanZero} this\n\t */\n\tTone.GreaterThanZero.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\tthis._thresh.dispose();\n\t\tthis._thresh = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThanZero;\n});","define([\"Tone/core/Tone\", \"Tone/signal/TimelineSignal\", \"Tone/core/TimelineState\", \n\t\"Tone/core/Emitter\", \"Tone/core/Context\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A sample accurate clock which provides a callback at the given rate. \n\t * While the callback is not sample-accurate (it is still susceptible to\n\t * loose JS timing), the time passed in as the argument to the callback\n\t * is precise. For most applications, it is better to use Tone.Transport\n\t * instead of the Clock by itself since you can synchronize multiple callbacks.\n\t *\n\t * \t@constructor\n\t * @extends {Tone.Emitter}\n\t * \t@param {function} callback The callback to be invoked with the time of the audio event\n\t * \t@param {Frequency} frequency The rate of the callback\n\t * \t@example\n\t * //the callback will be invoked approximately once a second\n\t * //and will print the time exactly once a second apart.\n\t * var clock = new Tone.Clock(function(time){\n\t * \tconsole.log(time);\n\t * }, 1);\n\t */\n\tTone.Clock = function(){\n\n\t\tTone.Emitter.call(this);\n\n\t\tvar options = this.optionsObject(arguments, [\"callback\", \"frequency\"], Tone.Clock.defaults);\n\n\t\t/**\n\t\t * The callback function to invoke at the scheduled tick.\n\t\t * @type {Function}\n\t\t */\n\t\tthis.callback = options.callback;\n\n\t\t/**\n\t\t * The next time the callback is scheduled.\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._nextTick = 0;\n\n\t\t/**\n\t\t * The last state of the clock.\n\t\t * @type {State}\n\t\t * @private\n\t\t */\n\t\tthis._lastState = Tone.State.Stopped;\n\n\t\t/**\n\t\t * The rate the callback function should be invoked. \n\t\t * @type {BPM}\n\t\t * @signal\n\t\t */\n\t\tthis.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);\n\t\tthis._readOnly(\"frequency\");\n\n\t\t/**\n\t\t * The number of times the callback was invoked. Starts counting at 0\n\t\t * and increments after the callback was invoked. \n\t\t * @type {Ticks}\n\t\t * @readOnly\n\t\t */\n\t\tthis.ticks = 0;\n\n\t\t/**\n\t\t * The state timeline\n\t\t * @type {Tone.TimelineState}\n\t\t * @private\n\t\t */\n\t\tthis._state = new Tone.TimelineState(Tone.State.Stopped);\n\n\t\t/**\n\t\t * The loop function bound to its context. \n\t\t * This is necessary to remove the event in the end.\n\t\t * @type {Function}\n\t\t * @private\n\t\t */\n\t\tthis._boundLoop = this._loop.bind(this);\n\n\t\t//bind a callback to the worker thread\n \tthis.context.on(\"tick\", this._boundLoop);\n\t};\n\n\tTone.extend(Tone.Clock, Tone.Emitter);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Clock.defaults = {\n\t\t\"callback\" : Tone.noOp,\n\t\t\"frequency\" : 1,\n\t\t\"lookAhead\" : \"auto\",\n\t};\n\n\t/**\n\t * Returns the playback state of the source, either \"started\", \"stopped\" or \"paused\".\n\t * @type {Tone.State}\n\t * @readOnly\n\t * @memberOf Tone.Clock#\n\t * @name state\n\t */\n\tObject.defineProperty(Tone.Clock.prototype, \"state\", {\n\t\tget : function(){\n\t\t\treturn this._state.getValueAtTime(this.now());\n\t\t}\n\t});\n\n\t/**\n\t * Start the clock at the given time. Optionally pass in an offset\n\t * of where to start the tick counter from.\n\t * @param {Time} time The time the clock should start\n\t * @param {Ticks=} offset Where the tick counter starts counting from.\n\t * @return {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.start = function(time, offset){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) !== Tone.State.Started){\n\t\t\tthis._state.add({\n\t\t\t\t\"state\" : Tone.State.Started, \n\t\t\t\t\"time\" : time,\n\t\t\t\t\"offset\" : offset\n\t\t\t});\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * Stop the clock. Stopping the clock resets the tick counter to 0.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t * @example\n\t * clock.stop();\n\t */\n\tTone.Clock.prototype.stop = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tthis._state.cancel(time);\n\t\tthis._state.setStateAtTime(Tone.State.Stopped, time);\n\t\treturn this;\t\n\t};\n\n\n\t/**\n\t * Pause the clock. Pausing does not reset the tick counter.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.pause = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) === Tone.State.Started){\n\t\t\tthis._state.setStateAtTime(Tone.State.Paused, time);\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * The scheduling loop.\n\t * @param {Number} time The current page time starting from 0\n\t * when the page was loaded.\n\t * @private\n\t */\n\tTone.Clock.prototype._loop = function(){\n\t\t//get the frequency value to compute the value of the next loop\n\t\tvar now = this.now();\n\t\t//if it's started\n\t\tvar lookAhead = this.context.lookAhead;\n\t\tvar updateInterval = this.context.updateInterval;\n\t\tvar lagCompensation = this.context.lag * 2;\n\t\tvar loopInterval = now + lookAhead + updateInterval + lagCompensation;\n\t\twhile (loopInterval > this._nextTick && this._state){\n\t\t\tvar currentState = this._state.getValueAtTime(this._nextTick);\n\t\t\tif (currentState !== this._lastState){\n\t\t\t\tthis._lastState = currentState;\n\t\t\t\tvar event = this._state.get(this._nextTick);\n\t\t\t\t// emit an event\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\t//correct the time\n\t\t\t\t\tthis._nextTick = event.time;\n\t\t\t\t\tif (!this.isUndef(event.offset)){\n\t\t\t\t\t\tthis.ticks = event.offset;\n\t\t\t\t\t}\n\t\t\t\t\tthis.emit(\"start\", event.time, this.ticks);\n\t\t\t\t} else if (currentState === Tone.State.Stopped){\n\t\t\t\t\tthis.ticks = 0;\n\n\t\t\t\t\tthis.emit(\"stop\", event.time);\n\t\t\t\t} else if (currentState === Tone.State.Paused){\n\t\t\t\t\tthis.emit(\"pause\", event.time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar tickTime = this._nextTick;\n\t\t\tif (this.frequency){\n\t\t\t\tthis._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\tthis.callback(tickTime);\n\t\t\t\t\tthis.ticks++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state at the given time.\n\t * @param {Time} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t * @example\n\t * clock.start(\"+0.1\");\n\t * clock.getStateAtTime(\"+0.1\"); //returns \"started\"\n\t */\n\tTone.Clock.prototype.getStateAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\treturn this._state.getValueAtTime(time);\n\t};\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.dispose = function(){\n\t\tTone.Emitter.prototype.dispose.call(this);\n\t\tthis.context.off(\"tick\", this._boundLoop);\n\t\tthis._writable(\"frequency\");\n\t\tthis.frequency.dispose();\n\t\tthis.frequency = null;\n\t\tthis._boundLoop = null;\n\t\tthis._nextTick = Infinity;\n\t\tthis.callback = null;\n\t\tthis._state.dispose();\n\t\tthis._state = null;\n\t};\n\n\treturn Tone.Clock;\n});","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var AudioVoice = require('audioVoice');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n var DEFAULT_SUSTAIN = 0.15;\r\n\r\n /**\r\n * A MonoSynth is used as a single voice for sound synthesis.\r\n * This is a class to be used in conjunction with the PolySynth\r\n * class. Custom synthetisers should be built inheriting from\r\n * this class.\r\n *\r\n * @class p5.MonoSynth\r\n * @constructor\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 0.25;\r\n * // velocity (volume, from 0 to 1)\r\n * var v = 0.2;\r\n *\r\n * monoSynth.play(\"G3\", v, time, dur);\r\n * monoSynth.play(\"C4\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n\r\n p5.MonoSynth = function () {\r\n AudioVoice.call(this);\r\n\r\n this.oscillator = new p5.Oscillator();\r\n\r\n this.env = new p5.Envelope();\r\n this.env.setRange(1, 0);\r\n this.env.setExp(true);\r\n\r\n //set params\r\n this.setADSR(0.02, 0.25, 0.05, 0.35);\r\n\r\n // oscillator --> env --> this.output (gain) --> p5.soundOut\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.output);\r\n\r\n this.env.disconnect();\r\n this.env.setInput(this.output.gain);\r\n\r\n // reset oscillator gain to 1.0\r\n this.oscillator.output.gain.value = 1.0;\r\n\r\n this.oscillator.start();\r\n this.connect();\r\n\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);\r\n\r\n /**\r\n * Play tells the MonoSynth to start playing a note. This method schedules\r\n * the calling of .triggerAttack and .triggerRelease.\r\n *\r\n * @method play\r\n * @for p5.MonoSynth\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 1/6;\r\n * // note velocity (volume, from 0 to 1)\r\n * var v = random();\r\n *\r\n * monoSynth.play(\"Fb3\", v, 0, dur);\r\n * monoSynth.play(\"Gb3\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n *\r\n */\r\n p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) {\r\n this.triggerAttack(note, velocity, ~~secondsFromNow);\r\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @method triggerAttack\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n var secondsFromNow = ~~secondsFromNow;\r\n var freq = noteToFreq(note);\r\n var vel = velocity || 0.1;\r\n this.oscillator.freq(freq, 0, secondsFromNow);\r\n this.env.ramp(this.output.gain, secondsFromNow, vel);\r\n };\r\n\r\n /**\r\n * Trigger the release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @method triggerRelease\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) {\r\n var secondsFromNow = secondsFromNow || 0;\r\n this.env.ramp(this.output.gain, secondsFromNow, 0);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.MonoSynth\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n */\r\n p5.MonoSynth.prototype.setADSR = function (attack,decay,sustain,release) {\r\n this.env.setADSR(attack, decay, sustain, release);\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters\r\n * @property {Number} attack\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} decay\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} sustain\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} release\r\n * @for p5.MonoSynth\r\n */\r\n Object.defineProperties(p5.MonoSynth.prototype, {\r\n 'attack': {\r\n get : function() {\r\n return this.env.aTime;\r\n },\r\n set : function(attack) {\r\n this.env.setADSR(attack, this.env.dTime,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'decay': {\r\n get : function() {\r\n return this.env.dTime;\r\n },\r\n set : function(decay) {\r\n this.env.setADSR(this.env.aTime, decay,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'sustain': {\r\n get : function() {\r\n return this.env.sPercent;\r\n },\r\n set : function(sustain) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n sustain, this.env.rTime);\r\n }\r\n },\r\n 'release': {\r\n get : function() {\r\n return this.env.rTime;\r\n },\r\n set : function(release) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n this.env.sPercent, release);\r\n }\r\n },\r\n });\r\n\r\n\r\n /**\r\n * MonoSynth amp\r\n * @method amp\r\n * @for p5.MonoSynth\r\n * @param {Number} vol desired volume\r\n * @param {Number} [rampTime] Time to reach new volume\r\n * @return {Number} new volume value\r\n */\r\n p5.MonoSynth.prototype.amp = function(vol, rampTime) {\r\n var t = rampTime || 0;\r\n if (typeof vol !== 'undefined') {\r\n this.oscillator.amp(vol, t);\r\n }\r\n return this.oscillator.amp().value;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.MonoSynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n\r\n p5.MonoSynth.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.dispose = function() {\r\n AudioVoice.prototype.dispose.apply(this);\r\n\r\n if (this.env) {\r\n this.env.dispose();\r\n }\r\n if (this.oscillator) {\r\n this.oscillator.dispose();\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\ndefine(function() {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * Base class for monophonic synthesizers. Any extensions of this class\r\n * should follow the API and implement the methods below in order to\r\n * remain compatible with p5.PolySynth();\r\n *\r\n * @class p5.AudioVoice\r\n * @constructor\r\n */\r\n p5.AudioVoice = function () {\r\n\t this.ac = p5sound.audiocontext;\r\n\t this.output = this.ac.createGain();\r\n\t this.connect();\r\n\t p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.amp = function(vol, rampTime) {\r\n };\r\n\r\n /**\r\n * Connect to p5 objects or Web Audio Nodes\r\n * @method connect\r\n * @for p5.AudioVoice\r\n * @param {Object} unit\r\n */\r\n p5.AudioVoice.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect from soundOut\r\n * @method disconnect\r\n * @for p5.AudioVoice\r\n */\r\n p5.AudioVoice.prototype.disconnect = function() {\r\n this.output.disconnect();\r\n };\r\n\r\n p5.AudioVoice.prototype.dispose = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n return p5.AudioVoice;\r\n});\r\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n /**\r\n * An AudioVoice is used as a single voice for sound synthesis.\r\n * The PolySynth class holds an array of AudioVoice, and deals\r\n * with voices allocations, with setting notes to be played, and\r\n * parameters to be set.\r\n *\r\n * @class p5.PolySynth\r\n * @constructor\r\n *\r\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\r\n * the AudioVoice class. Defaults to p5.MonoSynth\r\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 1.5;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * // notes can overlap with each other\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, time += 1/3, dur);\r\n * polySynth.play(\"G3\", vel, time += 1/3, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n p5.PolySynth = function(audioVoice, maxVoices) {\r\n //audiovoices will contain maxVoices many monophonic synths\r\n this.audiovoices = [];\r\n\r\n /**\r\n * An object that holds information about which notes have been played and\r\n * which notes are currently being played. New notes are added as keys\r\n * on the fly. While a note has been attacked, but not released, the value of the\r\n * key is the audiovoice which is generating that note. When notes are released,\r\n * the value of the key becomes undefined.\r\n * @property notes\r\n */\r\n this.notes = {};\r\n\r\n //indices of the most recently used, and least recently used audiovoice\r\n this._newest = 0;\r\n this._oldest = 0;\r\n\r\n /**\r\n * A PolySynth must have at least 1 voice, defaults to 8\r\n * @property polyvalue\r\n */\r\n this.maxVoices = maxVoices || 8;\r\n\r\n /**\r\n * Monosynth that generates the sound for each note that is triggered. The\r\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\r\n * @property AudioVoice\r\n */\r\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\r\n\r\n /**\r\n * This value must only change as a note is attacked or released. Due to delay\r\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\r\n\t * @private\r\n * @property {Tone.TimelineSignal} _voicesInUse\r\n */\r\n this._voicesInUse = new TimelineSignal(0);\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n this.connect();\r\n\r\n //Construct the appropriate number of audiovoices\r\n this._allocateVoices();\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Construct the appropriate number of audiovoices\r\n * @private\r\n * @for p5.PolySynth\r\n * @method _allocateVoices\r\n */\r\n p5.PolySynth.prototype._allocateVoices = function() {\r\n for(var i = 0; i< this.maxVoices; i++) {\r\n this.audiovoices.push(new this.AudioVoice());\r\n this.audiovoices[i].disconnect();\r\n this.audiovoices[i].connect(this.output);\r\n }\r\n };\r\n\r\n /**\r\n * Play a note by triggering noteAttack and noteRelease with sustain time\r\n *\r\n * @method play\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 0.1;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, 0, dur);\r\n * polySynth.play(\"G3\", vel, 0, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.play = function (note,velocity, secondsFromNow, susTime) {\r\n var susTime = susTime || 1;\r\n this.noteAttack(note, velocity, secondsFromNow);\r\n this.noteRelease(note, secondsFromNow + susTime);\r\n };\r\n\r\n\r\n /**\r\n * noteADSR sets the envelope for a specific note that has just been triggered.\r\n * Using this method modifies the envelope of whichever audiovoice is being used\r\n * to play the desired note. The envelope should be reset before noteRelease is called\r\n * in order to prevent the modified envelope from being used on other notes.\r\n *\r\n * @method noteADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [note] Midi note on which ADSR should be set.\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n\r\n p5.PolySynth.prototype.noteADSR = function (note,a,d,s,r,timeFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var timeFromNow = timeFromNow || 0;\r\n var t = now + timeFromNow\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].setADSR(a,d,s,r);\r\n };\r\n\r\n\r\n /**\r\n * Set the PolySynths global envelope. This method modifies the envelopes of each\r\n * monosynth so that all notes are played with this envelope.\r\n *\r\n * @method setADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n p5.PolySynth.prototype.setADSR = function(a,d,s,r) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.setADSR(a,d,s,r);\r\n });\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of a MonoSynth.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @method noteAttack\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\r\n * @param {Number} [secondsFromNow] time from now (in seconds)\r\n * @example\r\n *
\r\n * var polySynth = new p5.PolySynth();\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) {\r\n //this value goes to the audiovoices which handle their own scheduling\r\n var secondsFromNow = ~~secondsFromNow;\r\n\r\n //this value is used by this._voicesInUse\r\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\r\n\r\n //Convert note to frequency if necessary. This is because entries into this.notes\r\n //should be based on frequency for the sake of consistency.\r\n var note = noteToFreq(_note);\r\n var velocity = _velocity || 0.1;\r\n\r\n var currentVoice;\r\n\r\n //Release the note if it is already playing\r\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\r\n this.noteRelease(note, 0);\r\n }\r\n\r\n //Check to see how many voices are in use at the time the note will start\r\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\r\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\r\n }\r\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\r\n //with a new note\r\n else {\r\n currentVoice = this._oldest;\r\n\r\n var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value);\r\n this.noteRelease(oldestNote);\r\n this._oldest = ( this._oldest + 1 ) % (this.maxVoices - 1);\r\n }\r\n\r\n //Overrite the entry in the notes object. A note (frequency value)\r\n //corresponds to the index of the audiovoice that is playing it\r\n this.notes[note] = new TimelineSignal();\r\n this.notes[note].setValueAtTime(currentVoice, acTime);\r\n\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //Add 1 and schedule this value at time 't', when this note will start playing\r\n var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value;\r\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\r\n\r\n //Then update all scheduled values that follow to increase by 1\r\n this._updateAfter(acTime, 1);\r\n\r\n this._newest = currentVoice;\r\n //The audiovoice handles the actual scheduling of the note\r\n if (typeof velocity === 'number') {\r\n var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2;\r\n velocity = velocity > maxRange ? maxRange : velocity;\r\n }\r\n this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);\r\n };\r\n\r\n /**\r\n * Private method to ensure accurate values of this._voicesInUse\r\n * Any time a new value is scheduled, it is necessary to increment all subsequent\r\n * scheduledValues after attack, and decrement all subsequent\r\n * scheduledValues after release\r\n *\r\n * @private\r\n * @for p5.PolySynth\r\n * @param {[type]} time [description]\r\n * @param {[type]} value [description]\r\n * @return {[type]} [description]\r\n */\r\n p5.PolySynth.prototype._updateAfter = function(time, value) {\r\n if(this._voicesInUse._searchAfter(time) === null) {\r\n return;\r\n } else{\r\n this._voicesInUse._searchAfter(time).value += value;\r\n var nextTime = this._voicesInUse._searchAfter(time).time;\r\n this._updateAfter(nextTime, value);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Trigger the Release of an AudioVoice note. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method noteRelease\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * If no value is provided, all notes will be released.\r\n * @param {Number} [secondsFromNow] time to trigger the release\r\n * @example\r\n *
\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n * var polySynth = new p5.PolySynth();\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n *\r\n */\r\n p5.PolySynth.prototype.noteRelease = function (_note,secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n // if a note value is not provided, release all voices\r\n if (!_note) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.triggerRelease(tFromNow)\r\n });\r\n this._voicesInUse.setValueAtTime(0, t);\r\n for (var n in this.notes) {\r\n this.notes[n].dispose();\r\n delete this.notes[n];\r\n }\r\n return;\r\n }\r\n\r\n //Make sure note is in frequency inorder to query the this.notes object\r\n var note = noteToFreq(_note);\r\n\r\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\r\n console.warn('Cannot release a note that is not already playing');\r\n } else {\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //subtract 1 and schedule this value at time 't', when this note will stop playing\r\n var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);\r\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\r\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\r\n if (previousVal > 0) {\r\n this._updateAfter(t, -1);\r\n }\r\n\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].triggerRelease(tFromNow);\r\n this.notes[note].dispose();\r\n delete this.notes[note];\r\n\r\n this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\r\n }\r\n\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.PolySynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.PolySynth.prototype.connect = function (unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.dispose = function() {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.dispose();\r\n });\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n require('audioworklet-polyfill');\r\n require('shims');\r\n require('audiocontext');\r\n var p5SOUND = require('master');\r\n require('helpers');\r\n require('errorHandler');\r\n require('audioWorklet');\r\n require('panner');\r\n require('soundfile');\r\n require('amplitude');\r\n require('fft');\r\n require('signal');\r\n require('oscillator');\r\n require('envelope');\r\n require('pulse');\r\n require('noise');\r\n require('audioin');\r\n require('filter');\r\n require('eq');\r\n require('panner3d');\r\n require('listener3d');\r\n require('delay');\r\n require('reverb');\r\n require('metro');\r\n require('looper');\r\n require('soundLoop');\r\n require('compressor');\r\n require('soundRecorder');\r\n require('peakDetect');\r\n require('gain');\r\n require('monosynth');\r\n require('polysynth');\r\n require('distortion');\r\n require('audioVoice');\r\n require('monosynth');\r\n require('polysynth');\r\n\r\n return p5SOUND;\r\n\r\n});\r\n","!function(){var e,t=[];function r(e){var r=this,n={},i=-1;this.parameters.forEach(function(e,o){var s=t[++i]||(t[i]=new Float32Array(r.bufferSize));s.fill(e.value),n[o]=s}),this.processor.realm.exec(\"self.sampleRate=sampleRate=\"+this.context.sampleRate+\";self.currentTime=currentTime=\"+this.context.currentTime);var s=o(e.inputBuffer),a=o(e.outputBuffer);this.instance.process([s],[a],n)}function o(e){for(var t=[],r=0;r= this.sampleLimit) {\\n this.stop();\\n return true;\\n }\\n\\n var input = inputs[0];\\n var output = outputs[0];\\n\\n for (var channel = 0; channel < output.length; ++channel) {\\n var inputChannel = input[channel];\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannel);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n }\\n\\n this.recordedSamples += output[0].length;\\n return true;\\n }\\n }, {\\n key: \\\"record\\\",\\n value: function record(duration) {\\n if (duration) {\\n this.sampleLimit = Math.round(duration * sampleRate);\\n }\\n\\n this.recording = true;\\n }\\n }, {\\n key: \\\"stop\\\",\\n value: function stop() {\\n this.recording = false;\\n var buffers = this.getBuffers();\\n var leftBuffer = buffers[0].buffer;\\n var rightBuffer = buffers[1].buffer;\\n this.port.postMessage({\\n name: 'buffers',\\n leftBuffer: leftBuffer,\\n rightBuffer: rightBuffer\\n }, [leftBuffer, rightBuffer]);\\n this.clear();\\n }\\n }, {\\n key: \\\"getBuffers\\\",\\n value: function getBuffers() {\\n var buffers = [];\\n buffers.push(this.mergeBuffers(this.leftBuffers));\\n buffers.push(this.mergeBuffers(this.rightBuffers));\\n return buffers;\\n }\\n }, {\\n key: \\\"mergeBuffers\\\",\\n value: function mergeBuffers(channelBuffer) {\\n var result = new Float32Array(this.recordedSamples);\\n var offset = 0;\\n var lng = channelBuffer.length;\\n\\n for (var i = 0; i < lng; i++) {\\n var buffer = channelBuffer[i];\\n result.set(buffer, offset);\\n offset += buffer.length;\\n }\\n\\n return result;\\n }\\n }, {\\n key: \\\"clear\\\",\\n value: function clear() {\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.recordedSamples = 0;\\n this.sampleLimit = null;\\n }\\n }]);\\n\\n return RecorderProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);\"","export default \"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \\\"function\\\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \\\"function\\\") { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } if (typeof _cache !== \\\"undefined\\\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\\n\\nfunction isNativeReflectConstruct() { if (typeof Reflect === \\\"undefined\\\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \\\"function\\\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\\n\\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\\n\\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\\\"[native code]\\\") !== -1; }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\n// import processor name via preval.require so that it's available as a value at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\n\\nvar SoundFileProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\\n\\n function SoundFileProcessor() {\\n _classCallCheck(this, SoundFileProcessor);\\n\\n return _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).apply(this, arguments));\\n }\\n\\n _createClass(SoundFileProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs) {\\n var input = inputs[0];\\n var inputChannel = input[0];\\n var position = inputChannel[inputChannel.length - 1] || 0;\\n this.port.postMessage({\\n name: 'position',\\n position: position\\n });\\n return true;\\n }\\n }]);\\n\\n return SoundFileProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);\"","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n\r\n // Stereo panner\r\n // if there is a stereo panner node use it\r\n if(typeof ac.createStereoPanner !== 'undefined') {\r\n p5.Panner = function (input, output) {\r\n this.stereoPanner = this.input = ac.createStereoPanner();\r\n input.connect(this.stereoPanner);\r\n this.stereoPanner.connect(output);\r\n };\r\n\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n\r\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\r\n };\r\n\r\n //not implemented because stereopanner\r\n //node does not require this and will automatically\r\n //convert single channel or multichannel to stereo.\r\n //tested with single and stereo, not with (>2) multichannel\r\n p5.Panner.prototype.inputChannels = function() {};\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.stereoPanner.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.stereoPanner) {\r\n this.stereoPanner.disconnect();\r\n }\r\n };\r\n\r\n } else {\r\n // if there is no createStereoPanner object\r\n // such as in safari 7.1.7 at the time of writing this\r\n // use this method to create the effect\r\n p5.Panner = function(input, output, numInputChannels) {\r\n this.input = ac.createGain();\r\n input.connect(this.input);\r\n\r\n this.left = ac.createGain();\r\n this.right = ac.createGain();\r\n this.left.channelInterpretation = 'discrete';\r\n this.right.channelInterpretation = 'discrete';\r\n\r\n // if input is stereo\r\n if (numInputChannels > 1) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n this.input.connect(this.splitter);\r\n\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n else {\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n }\r\n\r\n this.output = ac.createChannelMerger(2);\r\n this.left.connect(this.output, 0, 1);\r\n this.right.connect(this.output, 0, 0);\r\n this.output.connect(output);\r\n };\r\n\r\n // -1 is left, +1 is right\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n var v = (val + 1) / 2;\r\n var rightVal = Math.cos(v*Math.PI/2);\r\n var leftVal = Math.sin(v * Math.PI/2);\r\n this.left.gain.linearRampToValueAtTime(leftVal, t);\r\n this.right.gain.linearRampToValueAtTime(rightVal, t);\r\n };\r\n\r\n p5.Panner.prototype.inputChannels = function(numChannels) {\r\n if (numChannels === 1) {\r\n this.input.disconnect();\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n } else if (numChannels === 2) {\r\n if (typeof(this.splitter === 'undefined')) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n }\r\n this.input.disconnect();\r\n this.input.connect(this.splitter);\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n };\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.output.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var CustomError = require('errorHandler');\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n var midiToFreq = require('helpers').midiToFreq;\r\n var convertToWav = require('helpers').convertToWav;\r\n var processorNames = require('./audioWorklet/processorNames');\r\n\r\n /**\r\n *
SoundFile object with a path to a file.
\r\n *\r\n *
The p5.SoundFile may not be available immediately because\r\n * it loads the file information asynchronously.
\r\n *\r\n *
To do something with the sound as soon as it loads\r\n * pass the name of a function as the second parameter.
\r\n *\r\n *
Only one file path is required. However, audio file formats\r\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\r\n * web browsers. If you want to ensure compatability, instead of a single\r\n * file path, you may include an Array of filepaths, and the browser will\r\n * choose a format that works.
\r\n *\r\n * @class p5.SoundFile\r\n * @constructor\r\n * @param {String|Array} path path to a sound file (String). Optionally,\r\n * you may include multiple file formats in\r\n * an array. Alternately, accepts an object\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if file fails to\r\n * load. This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\r\n * is loading. That function will\r\n * receive progress of the request to\r\n * load the sound file\r\n * (between 0 and 1) as its first\r\n * parameter. This progress\r\n * does not account for the additional\r\n * time needed to decode the audio data.\r\n *\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile = function(paths, onload, onerror, whileLoading) {\r\n if (typeof paths !== 'undefined') {\r\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\r\n var path = p5.prototype._checkFileFormats(paths);\r\n this.url = path;\r\n }\r\n else if(typeof paths === 'object') {\r\n if (!(window.File && window.FileReader && window.FileList && window.Blob)) {\r\n // The File API isn't supported in this browser\r\n throw 'Unable to load file because the File API is not supported';\r\n }\r\n }\r\n\r\n // if type is a p5.File...get the actual file\r\n if (paths.file) {\r\n paths = paths.file;\r\n }\r\n\r\n this.file = paths;\r\n }\r\n\r\n // private _onended callback, set by the method: onended(callback)\r\n this._onended = function() {};\r\n\r\n this._looping = false;\r\n this._playing = false;\r\n this._paused = false;\r\n this._pauseTime = 0;\r\n\r\n // cues for scheduling events with addCue() removeCue()\r\n this._cues = [];\r\n this._cueIDCounter = 0;\r\n\r\n // position of the most recently played sample\r\n this._lastPos = 0;\r\n this._counterNode = null;\r\n this._workletNode = null;\r\n\r\n // array of sources so that they can all be stopped!\r\n this.bufferSourceNodes = [];\r\n\r\n // current source\r\n this.bufferSourceNode = null;\r\n\r\n this.buffer = null;\r\n this.playbackRate = 1;\r\n\r\n this.input = p5sound.audiocontext.createGain();\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.reversed = false;\r\n\r\n // start and end of playback / loop\r\n this.startTime = 0;\r\n this.endTime = null;\r\n this.pauseTime = 0;\r\n\r\n // \"restart\" would stop playback before retriggering\r\n this.mode = 'sustain';\r\n\r\n // time that playback was started, in millis\r\n this.startMillis = null;\r\n\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.panner = new p5.Panner(this.output, p5sound.input, 2);\r\n\r\n // it is possible to instantiate a soundfile with no path\r\n if (this.url || this.file) {\r\n this.load(onload, onerror);\r\n }\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n\r\n if (typeof whileLoading === 'function') {\r\n this._whileLoading = whileLoading;\r\n } else {\r\n this._whileLoading = function() {};\r\n }\r\n\r\n this._onAudioProcess = _onAudioProcess.bind(this);\r\n this._clearOnEnd = _clearOnEnd.bind(this);\r\n };\r\n\r\n // register preload handling of loadSound\r\n p5.prototype.registerPreloadMethod('loadSound', p5.prototype);\r\n\r\n /**\r\n * loadSound() returns a new p5.SoundFile from a specified\r\n * path. If called during preload(), the p5.SoundFile will be ready\r\n * to play in time for setup() and draw(). If called outside of\r\n * preload, the p5.SoundFile will not be ready immediately, so\r\n * loadSound accepts a callback as the second parameter. Using a\r\n * \r\n * local server is recommended when loading external files.\r\n *\r\n * @method loadSound\r\n * @for p5\r\n * @param {String|Array} path Path to the sound file, or an array with\r\n * paths to soundfiles in multiple formats\r\n * i.e. ['sound.ogg', 'sound.mp3'].\r\n * Alternately, accepts an object: either\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is\r\n * an error loading the file.\r\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\r\n * This function will receive the percentage loaded\r\n * so far, from 0.0 to 1.0.\r\n * @return {SoundFile} Returns a p5.SoundFile\r\n * @example\r\n *
\r\n */\r\n p5.prototype.loadSound = function(path, callback, onerror, whileLoading) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined' ) {\r\n window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n\r\n var self = this;\r\n var s = new p5.SoundFile(path, function() {\r\n if(typeof callback === 'function') {\r\n callback.apply(self, arguments);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, onerror, whileLoading);\r\n\r\n return s;\r\n };\r\n\r\n /**\r\n * This is a helper function that the p5.SoundFile calls to load\r\n * itself. Accepts a callback (the name of another function)\r\n * as an optional parameter.\r\n *\r\n * @private\r\n * @for p5.SoundFile\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is an error\r\n */\r\n p5.SoundFile.prototype.load = function(callback, errorCallback) {\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n\r\n if (this.url !== undefined && this.url !== '') {\r\n var request = new XMLHttpRequest();\r\n request.addEventListener('progress', function(evt) {\r\n self._updateProgress(evt);\r\n }, false);\r\n request.open('GET', this.url, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on sucess loading file:\r\n if (!self.panner) return;\r\n ac.decodeAudioData(request.response,\r\n // success decoding buffer:\r\n function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n if (!self.panner) return;\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n if (!self.panner) return;\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url + '. The request status was: ' +\r\n request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n\r\n request.send();\r\n }\r\n else if (this.file !== undefined) {\r\n var reader = new FileReader();\r\n reader.onload = function() {\r\n if (!self.panner) return;\r\n ac.decodeAudioData(reader.result, function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n });\r\n };\r\n reader.onerror = function(e) {\r\n if (!self.panner) return;\r\n if (onerror) {\r\n onerror(e);\r\n }\r\n };\r\n reader.readAsArrayBuffer(this.file);\r\n }\r\n };\r\n\r\n // TO DO: use this method to create a loading bar that shows progress during file upload/decode.\r\n p5.SoundFile.prototype._updateProgress = function(evt) {\r\n if (evt.lengthComputable) {\r\n var percentComplete = evt.loaded / evt.total * 0.99;\r\n this._whileLoading(percentComplete, evt);\r\n // ...\r\n } else {\r\n // Unable to compute progress information since the total size is unknown\r\n this._whileLoading('size unknown');\r\n }\r\n };\r\n\r\n /**\r\n * Returns true if the sound file finished loading successfully.\r\n *\r\n * @method isLoaded\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLoaded = function() {\r\n if (this.buffer) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n };\r\n\r\n /**\r\n * Play the p5.SoundFile\r\n *\r\n * @method play\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) amplitude (volume)\r\n * of playback\r\n * @param {Number} [cueStart] (optional) cue start time in seconds\r\n * @param {Number} [duration] (optional) duration of playback in seconds\r\n */\r\n p5.SoundFile.prototype.play = function(startTime, rate, amp, _cueStart, duration) {\r\n if (!this.output) {\r\n console.warn('SoundFile.play() called after dispose');\r\n return;\r\n }\r\n\r\n var self = this;\r\n var now = p5sound.audiocontext.currentTime;\r\n var cueStart, cueEnd;\r\n var time = startTime || 0;\r\n if (time < 0) {\r\n time = 0;\r\n }\r\n\r\n time = time + now;\r\n\r\n if (typeof rate !== 'undefined') {\r\n this.rate(rate);\r\n }\r\n\r\n if (typeof amp !== 'undefined') {\r\n this.setVolume(amp);\r\n }\r\n\r\n // TO DO: if already playing, create array of buffers for easy stop()\r\n if (this.buffer) {\r\n\r\n // reset the pause time (if it was paused)\r\n this._pauseTime = 0;\r\n\r\n // handle restart playmode\r\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\r\n this.bufferSourceNode.stop(time);\r\n this._counterNode.stop(time);\r\n }\r\n\r\n //dont create another instance if already playing\r\n if (this.mode === 'untildone' && this.isPlaying()) {\r\n return;\r\n }\r\n // make a new source and counter. They are automatically assigned playbackRate and buffer\r\n this.bufferSourceNode = this._initSourceNode();\r\n\r\n // garbage collect counterNode and create a new one\r\n delete this._counterNode;\r\n this._counterNode = this._initCounterNode();\r\n\r\n if (_cueStart) {\r\n if (_cueStart >=0 && _cueStart < this.buffer.duration) {\r\n // this.startTime = cueStart;\r\n cueStart = _cueStart;\r\n } else { throw 'start time out of range'; }\r\n } else {\r\n cueStart = 0;\r\n }\r\n\r\n if (duration) {\r\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\r\n duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration;\r\n }\r\n\r\n // if it was paused, play at the pause position\r\n if (this._paused) {\r\n this.bufferSourceNode.start(time, this.pauseTime, duration);\r\n this._counterNode.start(time, this.pauseTime, duration);\r\n } else {\r\n this.bufferSourceNode.start(time, cueStart, duration);\r\n this._counterNode.start(time, cueStart, duration);\r\n }\r\n\r\n this._playing = true;\r\n this._paused = false;\r\n\r\n // add source to sources array, which is used in stopAll()\r\n this.bufferSourceNodes.push(this.bufferSourceNode);\r\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\r\n\r\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\r\n }\r\n // If soundFile hasn't loaded the buffer yet, throw an error\r\n else {\r\n throw 'not ready to play file, buffer has yet to load. Try preload()';\r\n }\r\n\r\n // if looping, will restart at original time\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n\r\n if (this._looping === true) {\r\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\r\n this.bufferSourceNode.loopStart = cueStart;\r\n this.bufferSourceNode.loopEnd = cueEnd;\r\n this._counterNode.loopStart = cueStart;\r\n this._counterNode.loopEnd = cueEnd;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * p5.SoundFile has two play modes: restart and\r\n * sustain. Play Mode determines what happens to a\r\n * p5.SoundFile if it is triggered while in the middle of playback.\r\n * In sustain mode, playback will continue simultaneous to the\r\n * new playback. In restart mode, play() will stop playback\r\n * and start over. With untilDone, a sound will play only if it's\r\n * not already playing. Sustain is the default mode.\r\n *\r\n * @method playMode\r\n * @for p5.SoundFile\r\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\r\n * @example\r\n *
\r\n * var mySound;\r\n * function preload(){\r\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n * function mouseClicked() {\r\n * mySound.playMode('sustain');\r\n * mySound.play();\r\n * }\r\n * function keyPressed() {\r\n * mySound.playMode('restart');\r\n * mySound.play();\r\n * }\r\n *\r\n *
\r\n */\r\n p5.SoundFile.prototype.playMode = function(str) {\r\n var s = str.toLowerCase();\r\n\r\n // if restart, stop all other sounds from playing\r\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNodes[i].stop(now);\r\n }\r\n }\r\n\r\n // set play mode to effect future playback\r\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\r\n this.mode = s;\r\n } else {\r\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\r\n }\r\n };\r\n\r\n /**\r\n * Pauses a file that is currently playing. If the file is not\r\n * playing, then nothing will happen.\r\n *\r\n * After pausing, .play() will resume from the paused\r\n * position.\r\n * If p5.SoundFile had been set to loop before it was paused,\r\n * it will continue to loop after it is unpaused with .play().\r\n *\r\n * @method pause\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.pause = function(startTime) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = startTime || 0;\r\n var pTime = time + now;\r\n\r\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\r\n this.pauseTime = this.currentTime();\r\n this.bufferSourceNode.stop(pTime);\r\n this._counterNode.stop(pTime);\r\n this._paused = true;\r\n this._playing = false;\r\n\r\n this._pauseTime = this.currentTime();\r\n // TO DO: make sure play() still starts from orig start position\r\n } else {\r\n this._pauseTime = 0;\r\n }\r\n };\r\n\r\n /**\r\n * Loop the p5.SoundFile. Accepts optional parameters to set the\r\n * playback rate, playback volume, loopStart, loopEnd.\r\n *\r\n * @method loop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) playback volume\r\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\r\n * @param {Number} [duration] (optional) loop duration in seconds\r\n */\r\n p5.SoundFile.prototype.loop = function(startTime, rate, amp, loopStart, duration) {\r\n this._looping = true;\r\n this.play(startTime, rate, amp, loopStart, duration);\r\n };\r\n\r\n /**\r\n * Set a p5.SoundFile's looping flag to true or false. If the sound\r\n * is currently playing, this change will take effect when it\r\n * reaches the end of the current playback.\r\n *\r\n * @method setLoop\r\n * @for p5.SoundFile\r\n * @param {Boolean} Boolean set looping to true or false\r\n */\r\n p5.SoundFile.prototype.setLoop = function(bool) {\r\n if (bool === true) {\r\n this._looping = true;\r\n }\r\n else if (bool === false) {\r\n this._looping = false;\r\n }\r\n else {\r\n throw 'Error: setLoop accepts either true or false';\r\n }\r\n if (this.bufferSourceNode) {\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n }\r\n };\r\n\r\n /**\r\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\r\n *\r\n * @method isLooping\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLooping = function() {\r\n if (!this.bufferSourceNode) {\r\n return false;\r\n }\r\n if (this._looping === true && this.isPlaying() === true) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\r\n * paused or stopped).\r\n *\r\n * @method isPlaying\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPlaying = function() {\r\n return this._playing;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\r\n * playing or stopped).\r\n *\r\n * @method isPaused\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPaused = function() {\r\n return this._paused;\r\n };\r\n\r\n /**\r\n * Stop soundfile playback.\r\n *\r\n * @method stop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * in seconds from now\r\n */\r\n p5.SoundFile.prototype.stop = function(timeFromNow) {\r\n var time = timeFromNow || 0;\r\n\r\n if (this.mode === 'sustain' || this.mode === 'untildone') {\r\n this.stopAll(time);\r\n this._playing = false;\r\n this.pauseTime = 0;\r\n this._paused = false;\r\n }\r\n else if (this.buffer && this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = time || 0;\r\n this.pauseTime = 0;\r\n this.bufferSourceNode.stop(now + t);\r\n this._counterNode.stop(now + t);\r\n this._playing = false;\r\n this._paused = false;\r\n }\r\n };\r\n\r\n /**\r\n * Stop playback on all of this soundfile's sources.\r\n * @private\r\n */\r\n p5.SoundFile.prototype.stopAll = function(_time) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = _time || 0;\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i in this.bufferSourceNodes) {\r\n const bufferSourceNode = this.bufferSourceNodes[i];\r\n if (!!bufferSourceNode) {\r\n try {\r\n bufferSourceNode.stop(now + time);\r\n } catch(e) {\r\n // this was throwing errors only on Safari\r\n }\r\n }\r\n }\r\n this._counterNode.stop(now + time);\r\n this._onended(this);\r\n }\r\n };\r\n\r\n /**\r\n * Multiply the output volume (amplitude) of a sound file\r\n * between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n * @method setVolume\r\n * @for p5.SoundFile\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.SoundFile.prototype.setVolume = function(vol, _rampTime, _tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = _rampTime || 0;\r\n var tFromNow = _tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(this.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // same as setVolume, to match Processing Sound\r\n p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;\r\n\r\n // these are the same thing\r\n p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;\r\n\r\n p5.SoundFile.prototype.getVolume = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set the stereo panning of a p5.sound object to\r\n * a floating point number between -1.0 (left) and 1.0 (right).\r\n * Default is 0.0 (center).\r\n *\r\n * @method pan\r\n * @for p5.SoundFile\r\n * @param {Number} [panValue] Set the stereo panner\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @example\r\n *
\r\n *\r\n * var ball = {};\r\n * var soundFile;\r\n *\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n * soundFile = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * ball.x = constrain(mouseX, 0, width);\r\n * ellipse(ball.x, height/2, 20, 20)\r\n * }\r\n *\r\n * function mousePressed(){\r\n * // map the ball's x location to a panning degree\r\n * // between -1.0 (left) and 1.0 (right)\r\n * var panning = map(ball.x, 0., width,-1.0, 1.0);\r\n * soundFile.pan(panning);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n /**\r\n * Returns the current stereo pan position (-1.0 to 1.0)\r\n *\r\n * @method getPan\r\n * @for p5.SoundFile\r\n * @return {Number} Returns the stereo pan setting of the Oscillator\r\n * as a number between -1.0 (left) and 1.0 (right).\r\n * 0.0 is center and default.\r\n */\r\n p5.SoundFile.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n /**\r\n * Set the playback rate of a sound file. Will change the speed and the pitch.\r\n * Values less than zero will reverse the audio buffer.\r\n *\r\n * @method rate\r\n * @for p5.SoundFile\r\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\r\n * .5 is half-speed, 2.0 is twice as fast.\r\n * Values less than zero play backwards.\r\n * @example\r\n *
\r\n * var song;\r\n *\r\n * function preload() {\r\n * song = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * song.loop();\r\n * }\r\n *\r\n * function draw() {\r\n * background(200);\r\n *\r\n * // Set the rate to a range between 0.1 and 4\r\n * // Changing the rate also alters the pitch\r\n * var speed = map(mouseY, 0.1, height, 0, 2);\r\n * speed = constrain(speed, 0.01, 4);\r\n * song.rate(speed);\r\n *\r\n * // Draw a circle to show what is going on\r\n * stroke(0);\r\n * fill(51, 100);\r\n * ellipse(mouseX, 100, 48, 48);\r\n * }\r\n *\r\n * \r\n *
\r\n *\r\n */\r\n p5.SoundFile.prototype.rate = function(playbackRate) {\r\n var reverse = false;\r\n if (typeof playbackRate === 'undefined') {\r\n return this.playbackRate;\r\n }\r\n\r\n this.playbackRate = playbackRate;\r\n\r\n if (playbackRate === 0) {\r\n playbackRate = 0.0000000000001;\r\n }\r\n\r\n else if (playbackRate < 0 && !this.reversed) {\r\n playbackRate = Math.abs(playbackRate);\r\n reverse = true;\r\n }\r\n\r\n else if (playbackRate > 0 && this.reversed) {\r\n reverse = true;\r\n }\r\n\r\n if (this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\r\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n this._counterNode.playbackRate.cancelScheduledValues(now);\r\n this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n }\r\n\r\n if (reverse) {\r\n this.reverseBuffer();\r\n }\r\n return this.playbackRate;\r\n };\r\n\r\n // TO DO: document this\r\n p5.SoundFile.prototype.setPitch = function(num) {\r\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\r\n this.rate(newPlaybackRate);\r\n };\r\n\r\n p5.SoundFile.prototype.getPlaybackRate = function() {\r\n return this.playbackRate;\r\n };\r\n\r\n /**\r\n * Returns the duration of a sound file in seconds.\r\n *\r\n * @method duration\r\n * @for p5.SoundFile\r\n * @return {Number} The duration of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.duration = function() {\r\n // Return Duration\r\n if (this.buffer) {\r\n return this.buffer.duration;\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n /**\r\n * Return the current position of the p5.SoundFile playhead, in seconds.\r\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\r\n * has been called, currentTime will count backwards.\r\n *\r\n * @method currentTime\r\n * @for p5.SoundFile\r\n * @return {Number} currentTime of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.currentTime = function() {\r\n return this.reversed\r\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\r\n : this._lastPos / ac.sampleRate;\r\n };\r\n\r\n /**\r\n * Move the playhead of the song to a position, in seconds. Start timing\r\n * and playback duration. If none are given, will reset the file to play\r\n * entire duration from start to finish.\r\n *\r\n * @method jump\r\n * @for p5.SoundFile\r\n * @param {Number} cueTime cueTime of the soundFile in seconds.\r\n * @param {Number} duration duration in seconds.\r\n */\r\n p5.SoundFile.prototype.jump = function(cueTime, duration) {\r\n if (cueTime < 0 || cueTime > this.buffer.duration) {\r\n throw 'jump time out of range';\r\n }\r\n if (duration > this.buffer.duration - cueTime) {\r\n throw 'end time out of range';\r\n }\r\n\r\n var cTime = cueTime || 0;\r\n var dur = duration || undefined;\r\n if (this.isPlaying()) {\r\n this.stop(0);\r\n }\r\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\r\n };\r\n\r\n /**\r\n * Return the number of channels in a sound file.\r\n * For example, Mono = 1, Stereo = 2.\r\n *\r\n * @method channels\r\n * @for p5.SoundFile\r\n * @return {Number} [channels]\r\n */\r\n p5.SoundFile.prototype.channels = function() {\r\n return this.buffer.numberOfChannels;\r\n };\r\n\r\n /**\r\n * Return the sample rate of the sound file.\r\n *\r\n * @method sampleRate\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleRate]\r\n */\r\n p5.SoundFile.prototype.sampleRate = function() {\r\n return this.buffer.sampleRate;\r\n };\r\n\r\n /**\r\n * Return the number of samples in a sound file.\r\n * Equal to sampleRate * duration.\r\n *\r\n * @method frames\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleCount]\r\n */\r\n p5.SoundFile.prototype.frames = function() {\r\n return this.buffer.length;\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\r\n * used to draw a static waveform. Scans through the p5.SoundFile's\r\n * audio buffer to find the greatest amplitudes. Accepts one\r\n * parameter, 'length', which determines size of the array.\r\n * Larger arrays result in more precise waveform visualizations.\r\n *\r\n * Inspired by Wavesurfer.js.\r\n *\r\n * @method getPeaks\r\n * @for p5.SoundFile\r\n * @params {Number} [length] length is the size of the returned array.\r\n * Larger length results in more precision.\r\n * Defaults to 5*width of the browser window.\r\n * @returns {Float32Array} Array of peaks.\r\n */\r\n p5.SoundFile.prototype.getPeaks = function(length) {\r\n\r\n if (this.buffer) {\r\n // set length to window's width if no length is provided\r\n if (!length) {\r\n length = window.width*5;\r\n }\r\n if (this.buffer) {\r\n var buffer = this.buffer;\r\n var sampleSize = buffer.length / length;\r\n var sampleStep = ~~(sampleSize / 10) || 1;\r\n var channels = buffer.numberOfChannels;\r\n var peaks = new Float32Array(Math.round(length));\r\n\r\n for (var c = 0; c < channels; c++) {\r\n var chan = buffer.getChannelData(c);\r\n for (var i = 0; i < length; i++) {\r\n var start = ~~(i*sampleSize);\r\n var end = ~~(start + sampleSize);\r\n var max = 0;\r\n for (var j = start; j < end; j+= sampleStep) {\r\n var value = chan[j];\r\n if (value > max) {\r\n max = value;\r\n // faster than Math.abs\r\n } else if (-value > max) {\r\n max = value;\r\n }\r\n }\r\n if (c === 0 || Math.abs(max) > peaks[i]) {\r\n peaks[i] = max;\r\n }\r\n }\r\n }\r\n\r\n return peaks;\r\n }\r\n }\r\n\r\n else {\r\n throw 'Cannot load peaks yet, buffer is not loaded';\r\n }\r\n };\r\n\r\n /**\r\n * Reverses the p5.SoundFile's buffer source.\r\n * Playback must be handled separately (see example).\r\n *\r\n * @method reverseBuffer\r\n * @for p5.SoundFile\r\n * @example\r\n *
\r\n * var drum;\r\n *\r\n * function preload() {\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * drum.reverseBuffer();\r\n * drum.play();\r\n * }\r\n *\r\n * \r\n *
\r\n */\r\n p5.SoundFile.prototype.reverseBuffer = function() {\r\n if (this.buffer) {\r\n var currentPos = this._lastPos / ac.sampleRate;\r\n var curVol = this.getVolume();\r\n this.setVolume(0, 0.001);\r\n\r\n const numChannels = this.buffer.numberOfChannels;\r\n for (var i = 0; i < numChannels; i++) {\r\n this.buffer.getChannelData(i).reverse();\r\n }\r\n // set reversed flag\r\n this.reversed = !this.reversed;\r\n\r\n if (currentPos) {\r\n this.jump(this.duration() - currentPos);\r\n }\r\n this.setVolume(curVol, 0.001);\r\n } else {\r\n throw 'SoundFile is not done loading';\r\n }\r\n };\r\n\r\n /**\r\n * Schedule an event to be called when the soundfile\r\n * reaches the end of a buffer. If the soundfile is\r\n * playing through once, this will be called when it\r\n * ends. If it is looping, it will be called when\r\n * stop is called.\r\n *\r\n * @method onended\r\n * @for p5.SoundFile\r\n * @param {Function} callback function to call when the\r\n * soundfile has ended.\r\n */\r\n p5.SoundFile.prototype.onended = function(callback) {\r\n this._onended = callback;\r\n return this;\r\n };\r\n\r\n p5.SoundFile.prototype.add = function() {\r\n // TO DO\r\n };\r\n\r\n p5.SoundFile.prototype.dispose = function() {\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n // remove reference to soundfile\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop(now);\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n if (this.bufferSourceNodes[i] !== null) {\r\n this.bufferSourceNodes[i].disconnect();\r\n try {\r\n this.bufferSourceNodes[i].stop(now);\r\n } catch(e) {\r\n console.warning('no buffer source node to dispose');\r\n }\r\n this.bufferSourceNodes[i] = null;\r\n }\r\n }\r\n if ( this.isPlaying() ) {\r\n try {\r\n this._counterNode.stop(now);\r\n } catch(e) {\r\n console.log(e);\r\n }\r\n this._counterNode = null;\r\n }\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n this.output = null;\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n this.panner = null;\r\n }\r\n };\r\n\r\n /**\r\n * Connects the output of a p5sound object to input of another\r\n * p5.sound object. For example, you may connect a p5.SoundFile to an\r\n * FFT or an Effect. If no parameter is given, it will connect to\r\n * the master output. Most p5sound objects connect to the master\r\n * output when they are created.\r\n *\r\n * @method connect\r\n * @for p5.SoundFile\r\n * @param {Object} [object] Audio object that accepts an input\r\n */\r\n p5.SoundFile.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else {\r\n if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n } else {\r\n this.panner.connect(unit);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Disconnects the output of this p5sound object.\r\n *\r\n * @method disconnect\r\n * @for p5.SoundFile\r\n */\r\n p5.SoundFile.prototype.disconnect = function() {\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n */\r\n p5.SoundFile.prototype.getLevel = function() {\r\n console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead');\r\n };\r\n\r\n /**\r\n * Reset the source for this SoundFile to a\r\n * new path (URL).\r\n *\r\n * @method setPath\r\n * @for p5.SoundFile\r\n * @param {String} path path to audio file\r\n * @param {Function} callback Callback\r\n */\r\n p5.SoundFile.prototype.setPath = function(p, callback) {\r\n var path = p5.prototype._checkFileFormats(p);\r\n this.url = path;\r\n this.load(callback);\r\n };\r\n\r\n /**\r\n * Replace the current Audio Buffer with a new Buffer.\r\n *\r\n * @method setBuffer\r\n * @for p5.SoundFile\r\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\r\n * will create a stereo source. 1 will create\r\n * a mono source.\r\n */\r\n p5.SoundFile.prototype.setBuffer = function(buf) {\r\n var numChannels = buf.length;\r\n var size = buf[0].length;\r\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\r\n\r\n if (!(buf[0] instanceof Float32Array)) {\r\n buf[0] = new Float32Array(buf[0]);\r\n }\r\n\r\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\r\n var channel = newBuffer.getChannelData( channelNum );\r\n channel.set(buf[channelNum]);\r\n }\r\n\r\n this.buffer = newBuffer;\r\n\r\n // set numbers of channels on input to the panner\r\n this.panner.inputChannels(numChannels);\r\n };\r\n\r\n //////////////////////////////////////////////////\r\n // script processor node with an empty buffer to help\r\n // keep a sample-accurate position in playback buffer.\r\n // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV\r\n // Copyright [2015] [Sonoport (Asia) Pte. Ltd.],\r\n // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0\r\n ////////////////////////////////////////////////////////////////////////////////////\r\n\r\n var _createCounterBuffer = function(buffer) {\r\n const len = buffer.length;\r\n const audioBuf = ac.createBuffer( 1, buffer.length, ac.sampleRate );\r\n const arrayBuffer = audioBuf.getChannelData(0);\r\n for (var index = 0; index < len; index++) {\r\n arrayBuffer[index] = index;\r\n }\r\n return audioBuf;\r\n };\r\n\r\n // initialize counterNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initCounterNode = function() {\r\n var self = this;\r\n var now = ac.currentTime;\r\n var cNode = ac.createBufferSource();\r\n\r\n // dispose of worklet node if it already exists\r\n if (self._workletNode) {\r\n self._workletNode.disconnect();\r\n delete self._workletNode;\r\n }\r\n self._workletNode = new AudioWorkletNode(ac, processorNames.soundFileProcessor);\r\n self._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'position') {\r\n this._lastPos = event.data.position;\r\n\r\n // do any callbacks that have been scheduled\r\n this._onTimeUpdate(self._lastPos);\r\n }\r\n }.bind(self);\r\n\r\n // create counter buffer of the same length as self.buffer\r\n cNode.buffer = _createCounterBuffer( self.buffer );\r\n\r\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\r\n\r\n cNode.connect(self._workletNode);\r\n self._workletNode.connect(p5.soundOut._silentNode);\r\n\r\n return cNode;\r\n };\r\n\r\n // initialize sourceNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initSourceNode = function() {\r\n var bufferSourceNode = ac.createBufferSource();\r\n bufferSourceNode.buffer = this.buffer;\r\n bufferSourceNode.playbackRate.value = this.playbackRate;\r\n bufferSourceNode.connect(this.output);\r\n return bufferSourceNode;\r\n };\r\n\r\n /**\r\n * processPeaks returns an array of timestamps where it thinks there is a beat.\r\n *\r\n * This is an asynchronous function that processes the soundfile in an offline audio context,\r\n * and sends the results to your callback function.\r\n *\r\n * The process involves running the soundfile through a lowpass filter, and finding all of the\r\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\r\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\r\n *\r\n * @method processPeaks\r\n * @for p5.SoundFile\r\n * @param {Function} callback a function to call once this data is returned\r\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\r\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\r\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\r\n * @return {Array} Array of timestamped peaks\r\n */\r\n p5.SoundFile.prototype.processPeaks = function(callback, _initThreshold, _minThreshold, _minPeaks) {\r\n var bufLen = this.buffer.length;\r\n var sampleRate = this.buffer.sampleRate;\r\n var buffer = this.buffer;\r\n var allPeaks = [];\r\n\r\n var initialThreshold = _initThreshold || 0.9,\r\n threshold = initialThreshold,\r\n minThreshold = _minThreshold || 0.22,\r\n minPeaks = _minPeaks || 200;\r\n\r\n // Create offline context\r\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\r\n\r\n // create buffer source\r\n var source = offlineContext.createBufferSource();\r\n source.buffer = buffer;\r\n\r\n // Create filter. TO DO: allow custom setting of filter\r\n var filter = offlineContext.createBiquadFilter();\r\n filter.type = 'lowpass';\r\n source.connect(filter);\r\n filter.connect(offlineContext.destination);\r\n\r\n // start playing at time:0\r\n source.start(0);\r\n offlineContext.startRendering(); // Render the song\r\n\r\n // act on the result\r\n offlineContext.oncomplete = function(e) {\r\n if (!self.panner) return;\r\n var filteredBuffer = e.renderedBuffer;\r\n var bufferData = filteredBuffer.getChannelData(0);\r\n\r\n\r\n // step 1:\r\n // create Peak instances, add them to array, with strength and sampleIndex\r\n do {\r\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\r\n threshold -= 0.005;\r\n } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold);\r\n\r\n\r\n // step 2:\r\n // find intervals for each peak in the sampleIndex, add tempos array\r\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\r\n\r\n // step 3: find top tempos\r\n var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate);\r\n\r\n // sort top intervals\r\n var topTempos = groups.sort(function(intA, intB) {\r\n return intB.count - intA.count;\r\n\r\n }).splice(0,5);\r\n\r\n // set this SoundFile's tempo to the top tempo ??\r\n this.tempo = topTempos[0].tempo;\r\n\r\n // step 4:\r\n // new array of peaks at top tempo within a bpmVariance\r\n var bpmVariance = 5;\r\n var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance);\r\n\r\n callback(tempoPeaks);\r\n };\r\n };\r\n\r\n // process peaks\r\n var Peak = function(amp, i) {\r\n this.sampleIndex = i;\r\n this.amplitude = amp;\r\n this.tempos = [];\r\n this.intervals = [];\r\n };\r\n\r\n // 1. for processPeaks() Function to identify peaks above a threshold\r\n // returns an array of peak indexes as frames (samples) of the original soundfile\r\n function getPeaksAtThreshold(data, threshold) {\r\n var peaksObj = {};\r\n var length = data.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (data[i] > threshold) {\r\n var amp = data[i];\r\n var peak = new Peak(amp, i);\r\n peaksObj[i] = peak;\r\n // Skip forward ~ 1/8s to get past this peak.\r\n i += 6000;\r\n }\r\n i++;\r\n }\r\n return peaksObj;\r\n }\r\n\r\n // 2. for processPeaks()\r\n function countIntervalsBetweenNearbyPeaks(peaksObj) {\r\n var intervalCounts = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n for (var index = 0; index < peaksArray.length; index++) {\r\n\r\n // find intervals in comparison to nearby peaks\r\n for (var i = 0; i < 10; i++) {\r\n var startPeak = peaksObj[peaksArray[index]];\r\n var endPeak = peaksObj[peaksArray[index + i]];\r\n\r\n if (startPeak && endPeak) {\r\n var startPos = startPeak.sampleIndex;\r\n var endPos = endPeak.sampleIndex;\r\n var interval = endPos - startPos;\r\n\r\n // add a sample interval to the startPeak in the allPeaks array\r\n if (interval > 0) {\r\n startPeak.intervals.push(interval);\r\n }\r\n\r\n // tally the intervals and return interval counts\r\n var foundInterval = intervalCounts.some(function(intervalCount) {\r\n if (intervalCount.interval === interval) {\r\n intervalCount.count++;\r\n return intervalCount;\r\n }\r\n });\r\n\r\n // store with JSON like formatting\r\n if (!foundInterval) {\r\n intervalCounts.push({\r\n interval: interval,\r\n count: 1,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return intervalCounts;\r\n }\r\n\r\n\r\n // 3. for processPeaks --> find tempo\r\n function groupNeighborsByTempo(intervalCounts, sampleRate) {\r\n var tempoCounts = [];\r\n\r\n intervalCounts.forEach(function(intervalCount) {\r\n\r\n try {\r\n // Convert an interval to tempo\r\n var theoreticalTempo = Math.abs( 60 / (intervalCount.interval / sampleRate ) );\r\n\r\n theoreticalTempo = mapTempo(theoreticalTempo);\r\n\r\n var foundTempo = tempoCounts.some(function(tempoCount) {\r\n if (tempoCount.tempo === theoreticalTempo)\r\n return tempoCount.count += intervalCount.count;\r\n });\r\n if (!foundTempo) {\r\n if (isNaN(theoreticalTempo)) {\r\n return;\r\n }\r\n tempoCounts.push({\r\n tempo: Math.round(theoreticalTempo),\r\n count: intervalCount.count\r\n });\r\n }\r\n } catch(e) {\r\n throw e;\r\n }\r\n\r\n });\r\n\r\n return tempoCounts;\r\n }\r\n\r\n // 4. for processPeaks - get peaks at top tempo\r\n function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\r\n var peaksAtTopTempo = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n // TO DO: filter out peaks that have the tempo and return\r\n for (var i = 0; i < peaksArray.length; i++) {\r\n var key = peaksArray[i];\r\n var peak = peaksObj[key];\r\n\r\n for (var j = 0; j < peak.intervals.length; j++) {\r\n var intervalBPM = Math.round(Math.abs( 60 / (peak.intervals[j] / sampleRate) ) );\r\n\r\n intervalBPM = mapTempo(intervalBPM);\r\n\r\n if ( Math.abs(intervalBPM - tempo) < bpmVariance ) {\r\n // convert sampleIndex to seconds\r\n peaksAtTopTempo.push(peak.sampleIndex/sampleRate);\r\n }\r\n }\r\n }\r\n\r\n // filter out peaks that are very close to each other\r\n peaksAtTopTempo = peaksAtTopTempo.filter(function(peakTime, index, arr) {\r\n var dif = arr[index + 1] - peakTime;\r\n if (dif > 0.01) {\r\n return true;\r\n }\r\n });\r\n\r\n return peaksAtTopTempo;\r\n }\r\n\r\n // helper function for processPeaks\r\n function mapTempo(theoreticalTempo) {\r\n // these scenarios create infinite while loop\r\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0 ) {\r\n return;\r\n }\r\n\r\n // Adjust the tempo to fit within the 90-180 BPM range\r\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\r\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\r\n\r\n return theoreticalTempo;\r\n }\r\n\r\n\r\n /*** SCHEDULE EVENTS ***/\r\n\r\n // Cue inspired by JavaScript setTimeout, and the\r\n // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\r\n var Cue = function(callback, time, id, val) {\r\n this.callback = callback;\r\n this.time = time;\r\n this.id = id;\r\n this.val = val;\r\n };\r\n\r\n /**\r\n * Schedule events to trigger every time a MediaElement\r\n * (audio/video) reaches a playback cue point.\r\n *\r\n * Accepts a callback function, a time (in seconds) at which to trigger\r\n * the callback, and an optional parameter for the callback.\r\n *\r\n * Time will be passed as the first parameter to the callback function,\r\n * and param will be the second parameter.\r\n *\r\n *\r\n * @method addCue\r\n * @for p5.SoundFile\r\n * @param {Number} time Time in seconds, relative to this media\r\n * element's playback. For example, to trigger\r\n * an event every time playback reaches two\r\n * seconds, pass in the number 2. This will be\r\n * passed as the first parameter to\r\n * the callback function.\r\n * @param {Function} callback Name of a function that will be\r\n * called at the given time. The callback will\r\n * receive time and (optionally) param as its\r\n * two parameters.\r\n * @param {Object} [value] An object to be passed as the\r\n * second parameter to the\r\n * callback function.\r\n * @return {Number} id ID of this cue,\r\n * useful for removeCue(id)\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.addCue = function(time, callback, val) {\r\n var id = this._cueIDCounter++;\r\n\r\n var cue = new Cue(callback, time, id, val);\r\n this._cues.push(cue);\r\n\r\n // if (!this.elt.ontimeupdate) {\r\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\r\n // }\r\n\r\n return id;\r\n };\r\n\r\n /**\r\n * Remove a callback based on its ID. The ID is returned by the\r\n * addCue method.\r\n *\r\n * @method removeCue\r\n * @for p5.SoundFile\r\n * @param {Number} id ID of the cue, as returned by addCue\r\n */\r\n p5.SoundFile.prototype.removeCue = function(id) {\r\n var cueLength = this._cues.length;\r\n for (var i = 0; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n if (cue.id === id) {\r\n this._cues.splice(i, 1);\r\n break;\r\n }\r\n }\r\n\r\n if (this._cues.length === 0) {\r\n // TO DO: remove callback\r\n // this.elt.ontimeupdate = null\r\n }\r\n };\r\n\r\n /**\r\n * Remove all of the callbacks that had originally been scheduled\r\n * via the addCue method.\r\n *\r\n * @method clearCues\r\n */\r\n p5.SoundFile.prototype.clearCues = function() {\r\n this._cues = [];\r\n // this.elt.ontimeupdate = null;\r\n };\r\n\r\n // private method that checks for cues to be fired if events\r\n // have been scheduled using addCue(callback, time).\r\n p5.SoundFile.prototype._onTimeUpdate = function(position) {\r\n var playbackTime = position/this.buffer.sampleRate;\r\n var cueLength = this._cues.length;\r\n\r\n for (var i = 0 ; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n var callbackTime = cue.time;\r\n var val = cue.val;\r\n\r\n if (this._prevTime < callbackTime && callbackTime <= playbackTime) {\r\n\r\n // pass the scheduled callbackTime as parameter to the callback\r\n cue.callback(val);\r\n }\r\n\r\n }\r\n\r\n this._prevTime = playbackTime;\r\n };\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device. To upload a file to a server, see\r\n * getBlob\r\n *\r\n * @method save\r\n * @for p5.SoundFile\r\n * @param {String} [fileName] name of the resulting .wav file.\r\n * @example\r\n *
\r\n * var inp, button, mySound;\r\n * var fileName = 'cool';\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n * function setup() {\r\n * btn = createButton('click to save file');\r\n * btn.position(0, 0);\r\n * btn.mouseClicked(handleMouseClick);\r\n * }\r\n *\r\n * function handleMouseClick() {\r\n * mySound.save(fileName);\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.save = function(fileName) {\r\n const dataView = convertToWav(this.buffer);\r\n p5.prototype.saveSound([dataView], fileName, 'wav');\r\n };\r\n\r\n /**\r\n * This method is useful for sending a SoundFile to a server. It returns the\r\n * .wav-encoded audio data as a \"Blob\".\r\n * A Blob is a file-like data object that can be uploaded to a server\r\n * with an http request. We'll\r\n * use the `httpDo` options object to send a POST request with some\r\n * specific options: we encode the request as `multipart/form-data`,\r\n * and attach the blob as one of the form values using `FormData`.\r\n *\r\n *\r\n * @method getBlob\r\n * @for p5.SoundFile\r\n * @returns {Blob} A file-like data object\r\n * @example\r\n *
\r\n *\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noCanvas();\r\n * var soundBlob = mySound.getBlob();\r\n *\r\n * // Now we can send the blob to a server...\r\n * var serverUrl = 'https://jsonplaceholder.typicode.com/posts';\r\n * var httpRequestOptions = {\r\n * method: 'POST',\r\n * body: new FormData().append('soundBlob', soundBlob),\r\n * headers: new Headers({\r\n * 'Content-Type': 'multipart/form-data'\r\n * })\r\n * };\r\n * httpDo(serverUrl, httpRequestOptions);\r\n *\r\n * // We can also create an `ObjectURL` pointing to the Blob\r\n * var blobUrl = URL.createObjectURL(soundBlob);\r\n *\r\n * // The `
\r\n */\r\n p5.SoundFile.prototype.getBlob = function() {\r\n const dataView = convertToWav(this.buffer);\r\n return new Blob([dataView], { type: 'audio/wav' });\r\n };\r\n\r\n // event handler to keep track of current position\r\n function _onAudioProcess(processEvent) {\r\n var inputBuffer = processEvent.inputBuffer.getChannelData(0);\r\n\r\n this._lastPos = inputBuffer[inputBuffer.length - 1] || 0;\r\n\r\n // do any callbacks that have been scheduled\r\n this._onTimeUpdate(self._lastPos);\r\n }\r\n\r\n // event handler to remove references to the bufferSourceNode when it is done playing\r\n function _clearOnEnd(e) {\r\n const thisBufferSourceNode = e.target;\r\n const soundFile = this;\r\n\r\n // delete this.bufferSourceNode from the sources array when it is done playing:\r\n thisBufferSourceNode._playing = false;\r\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\r\n\r\n // call the onended callback\r\n soundFile._onended(soundFile);\r\n\r\n soundFile.bufferSourceNodes.forEach(function (n, i) {\r\n if (n._playing === false) {\r\n soundFile.bufferSourceNodes.splice(i);\r\n }\r\n });\r\n\r\n if (soundFile.bufferSourceNodes.length === 0) {\r\n soundFile._playing = false;\r\n }\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var processorNames = require('./audioWorklet/processorNames');\r\n\r\n /**\r\n * Amplitude measures volume between 0.0 and 1.0.\r\n * Listens to all p5sound by default, or use setInput()\r\n * to listen to a specific sound source. Accepts an optional\r\n * smoothing value, which defaults to 0.\r\n *\r\n * @class p5.Amplitude\r\n * @constructor\r\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\r\n * amplitude readings (defaults to 0)\r\n * @example\r\n *
\r\n * var sound, amplitude, cnv;\r\n *\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * amplitude = new p5.Amplitude();\r\n *\r\n * // start / stop the sound when canvas is clicked\r\n * cnv.mouseClicked(function() {\r\n * if (sound.isPlaying() ){\r\n * sound.stop();\r\n * } else {\r\n * sound.play();\r\n * }\r\n * });\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n *\r\n *
\r\n */\r\n p5.Amplitude = function(smoothing) {\r\n\r\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\r\n this.bufferSize = 2048;\r\n\r\n // set audio context\r\n this.audiocontext = p5sound.audiocontext;\r\n this._workletNode = new AudioWorkletNode(this.audiocontext, processorNames.amplitudeProcessor, {\r\n outputChannelCount: [1],\r\n parameterData: { smoothing: smoothing || 0 },\r\n processorOptions: { normalize: false }\r\n });\r\n\r\n this._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'amplitude') {\r\n this.volume = event.data.volume;\r\n this.volNorm = event.data.volNorm;\r\n this.stereoVol = event.data.stereoVol;\r\n this.stereoVolNorm = event.data.stereoVolNorm;\r\n }\r\n }.bind(this);\r\n\r\n // for connections\r\n this.input = this._workletNode;\r\n\r\n this.output = this.audiocontext.createGain();\r\n\r\n // the variables to return\r\n this.volume = 0;\r\n this.volNorm = 0;\r\n this.stereoVol = [0, 0];\r\n this.stereoVolNorm = [0, 0];\r\n\r\n this.normalize = false;\r\n\r\n this._workletNode.connect(this.output);\r\n this.output.gain.value = 0;\r\n\r\n // this may only be necessary because of a Chrome bug\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // connect to p5sound master output by default, unless set by input()\r\n p5sound.meter.connect(this._workletNode);\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connects to the p5sound instance (master output) by default.\r\n * Optionally, you can pass in a specific source (i.e. a soundfile).\r\n *\r\n * @method setInput\r\n * @for p5.Amplitude\r\n * @param {soundObject|undefined} [snd] set the sound source\r\n * (optional, defaults to\r\n * master output)\r\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\r\n * to smooth amplitude readings\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound1 = loadSound('assets/beat.mp3');\r\n * sound2 = loadSound('assets/drum.mp3');\r\n * }\r\n * function setup(){\r\n * amplitude = new p5.Amplitude();\r\n * sound1.play();\r\n * sound2.play();\r\n * amplitude.setInput(sound2);\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound1.stop();\r\n * sound2.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.setInput = function(source, smoothing) {\r\n\r\n p5sound.meter.disconnect();\r\n\r\n if (smoothing) {\r\n this._workletNode.parameters.get('smoothing').value = smoothing;\r\n }\r\n\r\n // connect to the master out of p5s instance if no snd is provided\r\n if (source == null) {\r\n console.log('Amplitude input source is not ready! Connecting to master output instead');\r\n p5sound.meter.connect(this._workletNode);\r\n }\r\n\r\n // if it is a p5.Signal\r\n else if (source instanceof p5.Signal) {\r\n source.output.connect(this._workletNode);\r\n }\r\n // connect to the sound if it is available\r\n else if (source) {\r\n source.connect(this._workletNode);\r\n this._workletNode.disconnect();\r\n this._workletNode.connect(this.output);\r\n }\r\n\r\n // otherwise, connect to the master out of p5s instance (default)\r\n else {\r\n p5sound.meter.connect(this._workletNode);\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n } else {\r\n this.output.connect(unit);\r\n }\r\n } else {\r\n this.output.connect(this.panner.connect(p5sound.input));\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Returns a single Amplitude reading at the moment it is called.\r\n * For continuous readings, run in the draw loop.\r\n *\r\n * @method getLevel\r\n * @for p5.Amplitude\r\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\r\n * @return {Number} Amplitude as a number between 0.0 and 1.0\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * amplitude = new p5.Amplitude();\r\n * sound.play();\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.getLevel = function(channel) {\r\n if (typeof channel !== 'undefined') {\r\n if (this.normalize) {\r\n return this.stereoVolNorm[channel];\r\n } else {\r\n return this.stereoVol[channel];\r\n }\r\n }\r\n else if (this.normalize) {\r\n return this.volNorm;\r\n }\r\n else {\r\n return this.volume;\r\n }\r\n };\r\n\r\n /**\r\n * Determines whether the results of Amplitude.process() will be\r\n * Normalized. To normalize, Amplitude finds the difference the\r\n * loudest reading it has processed and the maximum amplitude of\r\n * 1.0. Amplitude adds this difference to all values to produce\r\n * results that will reliably map between 0.0 and 1.0. However,\r\n * if a louder moment occurs, the amount that Normalize adds to\r\n * all the values will change. Accepts an optional boolean parameter\r\n * (true or false). Normalizing is off by default.\r\n *\r\n * @method toggleNormalize\r\n * @for p5.Amplitude\r\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\r\n */\r\n p5.Amplitude.prototype.toggleNormalize = function(bool) {\r\n if (typeof bool === 'boolean') {\r\n this.normalize = bool;\r\n }\r\n else {\r\n this.normalize = !this.normalize;\r\n }\r\n this._workletNode.port.postMessage({ name: 'toggleNormalize', normalize: this.normalize });\r\n };\r\n\r\n /**\r\n * Smooth Amplitude analysis by averaging with the last analysis\r\n * frame. Off by default.\r\n *\r\n * @method smooth\r\n * @for p5.Amplitude\r\n * @param {Number} set smoothing from 0.0 <= 1\r\n */\r\n p5.Amplitude.prototype.smooth = function(s) {\r\n if (s >= 0 && s < 1) {\r\n this._workletNode.parameters.get('smoothing').value = s;\r\n } else {\r\n console.log('Error: smoothing must be between 0 and 1');\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n\r\n this._workletNode.disconnect();\r\n delete this._workletNode;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n *
FFT (Fast Fourier Transform) is an analysis algorithm that\r\n * isolates individual\r\n * \r\n * audio frequencies within a waveform.
\r\n *\r\n *
Once instantiated, a p5.FFT object can return an array based on\r\n * two types of analyses: • FFT.waveform() computes\r\n * amplitude values along the time domain. The array indices correspond\r\n * to samples across a brief moment in time. Each value represents\r\n * amplitude of the waveform at that sample of time. \r\n * • FFT.analyze() computes amplitude values along the\r\n * frequency domain. The array indices correspond to frequencies (i.e.\r\n * pitches), from the lowest to the highest that humans can hear. Each\r\n * value represents amplitude at that slice of the frequency spectrum.\r\n * Use with getEnergy() to measure amplitude at specific\r\n * frequencies, or within a range of frequencies.
\r\n *\r\n *
FFT analyzes a very short snapshot of sound called a sample\r\n * buffer. It returns an array of amplitude measurements, referred\r\n * to as bins. The array is 1024 bins long by default.\r\n * You can change the bin array length, but it must be a power of 2\r\n * between 16 and 1024 in order for the FFT algorithm to function\r\n * correctly. The actual size of the FFT buffer is twice the\r\n * number of bins, so given a standard sample rate, the buffer is\r\n * 2048/44100 seconds long.
\r\n *\r\n *\r\n * @class p5.FFT\r\n * @constructor\r\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\r\n * 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n * @param {Number} [bins] Length of resulting array.\r\n * Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup(){\r\n * var cnv = createCanvas(100,100);\r\n * cnv.mouseClicked(togglePlay);\r\n * fft = new p5.FFT();\r\n * sound.amp(0.2);\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h )\r\n * }\r\n *\r\n * var waveform = fft.waveform();\r\n * noFill();\r\n * beginShape();\r\n * stroke(255,0,0); // waveform is red\r\n * strokeWeight(1);\r\n * for (var i = 0; i< waveform.length; i++){\r\n * var x = map(i, 0, waveform.length, 0, width);\r\n * var y = map( waveform[i], -1, 1, 0, height);\r\n * vertex(x,y);\r\n * }\r\n * endShape();\r\n *\r\n * text('click to play/pause', 4, 10);\r\n * }\r\n *\r\n * // fade sound if mouse is over canvas\r\n * function togglePlay() {\r\n * if (sound.isPlaying()) {\r\n * sound.pause();\r\n * } else {\r\n * sound.loop();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.FFT = function(smoothing, bins) {\r\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\r\n\r\n Object.defineProperties(this, {\r\n bins: {\r\n get: function() {\r\n return this.analyser.fftSize / 2;\r\n },\r\n set: function(b) {\r\n this.analyser.fftSize = b * 2;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n },\r\n smoothing: {\r\n get: function() {\r\n return this.analyser.smoothingTimeConstant;\r\n },\r\n set: function(s) {\r\n this.analyser.smoothingTimeConstant = s;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n }\r\n });\r\n\r\n // set default smoothing and bins\r\n this.smooth(smoothing);\r\n this.bins = bins || 1024;\r\n\r\n // default connections to p5sound fftMeter\r\n p5sound.fftMeter.connect(this.analyser);\r\n\r\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n\r\n // predefined frequency ranges, these will be tweakable\r\n this.bass = [20, 140];\r\n this.lowMid = [140, 400];\r\n this.mid = [400, 2600];\r\n this.highMid = [2600, 5200];\r\n this.treble = [5200, 14000];\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the input source for the FFT analysis. If no source is\r\n * provided, FFT will analyze all sound in the sketch.\r\n *\r\n * @method setInput\r\n * @for p5.FFT\r\n * @param {Object} [source] p5.sound object (or web audio API source node)\r\n */\r\n p5.FFT.prototype.setInput = function(source) {\r\n if (!source) {\r\n p5sound.fftMeter.connect(this.analyser);\r\n } else {\r\n if (source.output) {\r\n source.output.connect(this.analyser);\r\n } else if (source.connect) {\r\n source.connect(this.analyser);\r\n }\r\n p5sound.fftMeter.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\r\n * a snapshot of amplitude readings in a single buffer. Length will be\r\n * equal to bins (defaults to 1024). Can be used to draw the waveform\r\n * of a sound.\r\n *\r\n * @method waveform\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {String} [precision] If any value is provided, will return results\r\n * in a Float32 Array which is more precise\r\n * than a regular array.\r\n * @return {Array} Array Array of amplitude values (-1 to 1)\r\n * over time. Array length = bins.\r\n *\r\n */\r\n p5.FFT.prototype.waveform = function() {\r\n var bins, mode, normalArray;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n bins = arguments[i];\r\n this.analyser.fftSize = bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\r\n if (mode && !p5.prototype._isSafari()) {\r\n timeToFloat(this, this.timeDomain);\r\n this.analyser.getFloatTimeDomainData(this.timeDomain);\r\n return this.timeDomain;\r\n } else {\r\n timeToInt(this, this.timeDomain);\r\n this.analyser.getByteTimeDomainData(this.timeDomain);\r\n var normalArray = new Array();\r\n for (var j = 0; j < this.timeDomain.length; j++) {\r\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\r\n normalArray.push(scaled);\r\n }\r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between 0 and 255)\r\n * across the frequency spectrum. Length is equal to FFT bins\r\n * (1024 by default). The array indices correspond to frequencies\r\n * (i.e. pitches), from the lowest to the highest that humans can\r\n * hear. Each value represents amplitude at that slice of the\r\n * frequency spectrum. Must be called prior to using\r\n * getEnergy().\r\n *\r\n * @method analyze\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {Number} [scale] If \"dB,\" returns decibel\r\n * float measurements between\r\n * -140 and 0 (max).\r\n * Otherwise returns integers from 0-255.\r\n * @return {Array} spectrum Array of energy (amplitude/volume)\r\n * values across the frequency spectrum.\r\n * Lowest energy (silence) = 0, highest\r\n * possible is 255.\r\n * @example\r\n *
\r\n * var osc;\r\n * var fft;\r\n *\r\n * function setup(){\r\n * createCanvas(100,100);\r\n * osc = new p5.Oscillator();\r\n * osc.amp(0);\r\n * osc.start();\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var freq = map(mouseX, 0, 800, 20, 15000);\r\n * freq = constrain(freq, 1, 20000);\r\n * osc.freq(freq);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h );\r\n * }\r\n *\r\n * stroke(255);\r\n * text('Freq: ' + round(freq)+'Hz', 10, 10);\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * // only play sound when mouse is over canvas\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * osc.amp(0.5, 0.2);\r\n * } else {\r\n * osc.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n *\r\n *\r\n */\r\n p5.FFT.prototype.analyze = function() {\r\n var mode;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n this.bins = arguments[i];\r\n this.analyser.fftSize = this.bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n if (mode && mode.toLowerCase() === 'db') {\r\n freqToFloat(this);\r\n this.analyser.getFloatFrequencyData(this.freqDomain);\r\n return this.freqDomain;\r\n } else {\r\n freqToInt(this, this.freqDomain);\r\n this.analyser.getByteFrequencyData(this.freqDomain);\r\n var normalArray = Array.apply([], this.freqDomain);\r\n \r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns the amount of energy (volume) at a specific\r\n * \r\n * frequency, or the average amount of energy between two\r\n * frequencies. Accepts Number(s) corresponding\r\n * to frequency (in Hz), or a String corresponding to predefined\r\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\r\n * Returns a range between 0 (no energy/volume at that frequency) and\r\n * 255 (maximum energy).\r\n * NOTE: analyze() must be called prior to getEnergy(). Analyze()\r\n * tells the FFT to analyze frequency data, and getEnergy() uses\r\n * the results determine the value at a specific frequency or\r\n * range of frequencies.\r\n *\r\n * @method getEnergy\r\n * @for p5.FFT\r\n * @param {Number|String} frequency1 Will return a value representing\r\n * energy at this frequency. Alternately,\r\n * the strings \"bass\", \"lowMid\" \"mid\",\r\n * \"highMid\", and \"treble\" will return\r\n * predefined frequency ranges.\r\n * @param {Number} [frequency2] If a second frequency is given,\r\n * will return average amount of\r\n * energy that exists between the\r\n * two frequencies.\r\n * @return {Number} Energy Energy (volume/amplitude) from\r\n * 0 and 255.\r\n *\r\n */\r\n p5.FFT.prototype.getEnergy = function(frequency1, frequency2) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n\r\n if (frequency1 === 'bass') {\r\n frequency1 = this.bass[0];\r\n frequency2 = this.bass[1];\r\n } else if (frequency1 === 'lowMid') {\r\n frequency1 = this.lowMid[0];\r\n frequency2 = this.lowMid[1];\r\n } else if (frequency1 === 'mid') {\r\n frequency1 = this.mid[0];\r\n frequency2 = this.mid[1];\r\n } else if (frequency1 === 'highMid') {\r\n frequency1 = this.highMid[0];\r\n frequency2 = this.highMid[1];\r\n } else if (frequency1 === 'treble') {\r\n frequency1 = this.treble[0];\r\n frequency2 = this.treble[1];\r\n }\r\n\r\n if (typeof frequency1 !== 'number') {\r\n throw 'invalid input for getEnergy()';\r\n } else if (!frequency2) {\r\n // if only one parameter:\r\n var index = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n return this.freqDomain[index];\r\n } else if (frequency1 && frequency2) {\r\n // if two parameters:\r\n // if second is higher than first\r\n if (frequency1 > frequency2) {\r\n var swap = frequency2;\r\n frequency2 = frequency1;\r\n frequency1 = swap;\r\n }\r\n var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length);\r\n\r\n var total = 0;\r\n var numFrequencies = 0;\r\n // add up all of the values for the frequencies\r\n for (var i = lowIndex; i <= highIndex; i++) {\r\n total += this.freqDomain[i];\r\n numFrequencies += 1;\r\n }\r\n // divide by total number of frequencies\r\n var toReturn = total / numFrequencies;\r\n return toReturn;\r\n } else {\r\n throw 'invalid input for getEnergy()';\r\n }\r\n };\r\n\r\n // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\r\n p5.FFT.prototype.getFreq = function(freq1, freq2) {\r\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\r\n var x = this.getEnergy(freq1, freq2);\r\n return x;\r\n };\r\n\r\n /**\r\n * Returns the\r\n * \r\n * spectral centroid of the input signal.\r\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\r\n * tells the FFT to analyze frequency data, and getCentroid() uses\r\n * the results determine the spectral centroid.\r\n *\r\n * @method getCentroid\r\n * @for p5.FFT\r\n * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz.\r\n *\r\n *\r\n * @example\r\n *
\r\n *\r\n *\r\n *function setup(){\r\n * cnv = createCanvas(100,100);\r\n * sound = new p5.AudioIn();\r\n * sound.start();\r\n * fft = new p5.FFT();\r\n * sound.connect(fft);\r\n *}\r\n *\r\n *\r\n *function draw(){\r\n *\r\n * var centroidplot = 0.0;\r\n * var spectralCentroid = 0;\r\n *\r\n *\r\n * background(0);\r\n * stroke(0,255,0);\r\n * var spectrum = fft.analyze();\r\n * fill(0,255,0); // spectrum is green\r\n *\r\n * //draw the spectrum\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(log(i), 0, log(spectrum.length), 0, width);\r\n * var h = map(spectrum[i], 0, 255, 0, height);\r\n * var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\r\n * rect(x, height, rectangle_width, -h )\r\n * }\r\n\r\n * var nyquist = 22050;\r\n *\r\n * // get the centroid\r\n * spectralCentroid = fft.getCentroid();\r\n *\r\n * // the mean_freq_index calculation is for the display.\r\n * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\r\n *\r\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\r\n *\r\n *\r\n * stroke(255,0,0); // the line showing where the centroid is will be red\r\n *\r\n * rect(centroidplot, 0, width / spectrum.length, height)\r\n * noStroke();\r\n * fill(255,255,255); // text is white\r\n * text(\"centroid: \", 10, 20);\r\n * text(round(spectralCentroid)+\" Hz\", 10, 40);\r\n *}\r\n *
\r\n */\r\n p5.FFT.prototype.getCentroid = function() {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var cumulative_sum = 0;\r\n var centroid_normalization = 0;\r\n\r\n for (var i = 0; i < this.freqDomain.length; i++) {\r\n cumulative_sum += i * this.freqDomain[i];\r\n centroid_normalization += this.freqDomain[i];\r\n }\r\n\r\n var mean_freq_index = 0;\r\n\r\n if (centroid_normalization !== 0) {\r\n mean_freq_index = cumulative_sum / centroid_normalization;\r\n }\r\n\r\n var spec_centroid_freq =\r\n mean_freq_index * (nyquist / this.freqDomain.length);\r\n return spec_centroid_freq;\r\n };\r\n\r\n /**\r\n * Smooth FFT analysis by averaging with the last analysis frame.\r\n *\r\n * @method smooth\r\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n */\r\n p5.FFT.prototype.smooth = function(s) {\r\n if (typeof s !== 'undefined') {\r\n this.smoothing = s;\r\n }\r\n return this.smoothing;\r\n };\r\n\r\n p5.FFT.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.analyser) {\r\n this.analyser.disconnect();\r\n delete this.analyser;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values for a given number\r\n * of frequency bands split equally. N defaults to 16.\r\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and linAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method linAverages\r\n * @for p5.FFT\r\n * @param {Number} N Number of returned frequency groups\r\n * @return {Array} linearAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.linAverages = function(N) {\r\n var N = N || 16; // This prevents undefined, null or 0 values of N\r\n\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n var spectrumStep = Math.floor(spectrumLength / N);\r\n\r\n var linearAverages = new Array(N);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // with only one loop in the spectrum data\r\n var groupIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n linearAverages[groupIndex] =\r\n linearAverages[groupIndex] !== undefined\r\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n\r\n // Increase the group index when the last element of the group is processed\r\n if (specIndex % spectrumStep === spectrumStep - 1) {\r\n groupIndex++;\r\n }\r\n }\r\n\r\n return linearAverages;\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values of the spectrum, for a given\r\n * set of \r\n * Octave Bands\r\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and logAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method logAverages\r\n * @for p5.FFT\r\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\r\n * @return {Array} logAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.logAverages = function(octaveBands) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n\r\n var logAverages = new Array(octaveBands.length);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // With only one loop in the spectrum data\r\n var octaveIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n var specIndexFrequency = Math.round(\r\n specIndex * nyquist / this.freqDomain.length\r\n );\r\n\r\n // Increase the group index if the current frequency exceeds the limits of the band\r\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\r\n octaveIndex++;\r\n }\r\n\r\n logAverages[octaveIndex] =\r\n logAverages[octaveIndex] !== undefined\r\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n }\r\n\r\n return logAverages;\r\n };\r\n\r\n /**\r\n * Calculates and Returns the 1/N\r\n * Octave Bands\r\n * N defaults to 3 and minimum central frequency to 15.625Hz.\r\n * (1/3 Octave Bands ~= 31 Frequency Bands)\r\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\r\n * and produce less frequency groups.\r\n *\r\n * @method getOctaveBands\r\n * @for p5.FFT\r\n * @param {Number} N Specifies the 1/N type of generated octave bands\r\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\r\n * @return {Array} octaveBands Array of octave band objects with their bounds\r\n */\r\n p5.FFT.prototype.getOctaveBands = function(N, fCtr0) {\r\n var N = N || 3; // Default to 1/3 Octave Bands\r\n var fCtr0 = fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\r\n\r\n var octaveBands = [];\r\n var lastFrequencyBand = {\r\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\r\n ctr: fCtr0,\r\n hi: fCtr0 * Math.pow(2, 1 / (2 * N))\r\n };\r\n octaveBands.push(lastFrequencyBand);\r\n\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n while (lastFrequencyBand.hi < nyquist) {\r\n var newFrequencyBand = {};\r\n newFrequencyBand.lo = lastFrequencyBand.hi;\r\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\r\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\r\n\r\n octaveBands.push(newFrequencyBand);\r\n lastFrequencyBand = newFrequencyBand;\r\n }\r\n\r\n return octaveBands;\r\n };\r\n\r\n // helper methods to convert type from float (dB) to int (0-255)\r\n var freqToFloat = function(fft) {\r\n if (fft.freqDomain instanceof Float32Array === false) {\r\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var freqToInt = function(fft) {\r\n if (fft.freqDomain instanceof Uint8Array === false) {\r\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToFloat = function(fft) {\r\n if (fft.timeDomain instanceof Float32Array === false) {\r\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToInt = function(fft) {\r\n if (fft.timeDomain instanceof Uint8Array === false) {\r\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // Signal is built with the Tone.js signal by Yotam Mann\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Signal = require('Tone/signal/Signal');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
p5.Signal is a constant audio-rate signal used by p5.Oscillator\r\n * and p5.Envelope for modulation math.
\r\n *\r\n *
This is necessary because Web Audio is processed on a seprate clock.\r\n * For example, the p5 draw loop runs about 60 times per second. But\r\n * the audio clock must process samples 44100 times per second. If we\r\n * want to add a value to each of those samples, we can't do it in the\r\n * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns\r\n * a Tone.Signal from the Tone.js library by Yotam Mann.\r\n * If you want to work directly with audio signals for modular\r\n * synthesis, check out\r\n * tone.js.
\r\n *\r\n * @class p5.Signal\r\n * @constructor\r\n * @return {Tone.Signal} A Signal object from the Tone.js library\r\n * @example\r\n *
\r\n * function setup() {\r\n * carrier = new p5.Oscillator('sine');\r\n * carrier.amp(1); // set amplitude\r\n * carrier.freq(220); // set frequency\r\n * carrier.start(); // start oscillating\r\n *\r\n * modulator = new p5.Oscillator('sawtooth');\r\n * modulator.disconnect();\r\n * modulator.amp(1);\r\n * modulator.freq(4);\r\n * modulator.start();\r\n *\r\n * // Modulator's default amplitude range is -1 to 1.\r\n * // Multiply it by -200, so the range is -200 to 200\r\n * // then add 220 so the range is 20 to 420\r\n * carrier.freq( modulator.mult(-200).add(220) );\r\n * }\r\n *
\r\n */\r\n p5.Signal = function(value) {\r\n var s = new Signal(value);\r\n // p5sound.soundArray.push(s);\r\n return s; // TODO: is this really a constructor?\r\n };\r\n\r\n /**\r\n * Fade to value, for smooth transitions\r\n *\r\n * @method fade\r\n * @for p5.Signal\r\n * @param {Number} value Value to set this signal\r\n * @param {Number} [secondsFromNow] Length of fade, in seconds from now\r\n */\r\n Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime;\r\n Mult.prototype.fade = Signal.prototype.fade;\r\n Add.prototype.fade = Signal.prototype.fade;\r\n Scale.prototype.fade = Signal.prototype.fade;\r\n\r\n\r\n /**\r\n * Connect a p5.sound object or Web Audio node to this\r\n * p5.Signal so that its amplitude values can be scaled.\r\n *\r\n * @method setInput\r\n * @for p5.Signal\r\n * @param {Object} input\r\n */\r\n Signal.prototype.setInput = function(_input) {\r\n _input.connect(this);\r\n };\r\n Mult.prototype.setInput = Signal.prototype.setInput;\r\n Add.prototype.setInput = Signal.prototype.setInput;\r\n Scale.prototype.setInput = Signal.prototype.setInput;\r\n\r\n\r\n // signals can add / mult / scale themselves\r\n\r\n /**\r\n * Add a constant value to this audio signal,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalAdd.\r\n *\r\n * @method add\r\n * @for p5.Signal\r\n * @param {Number} number\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.add = function(num) {\r\n var add = new Add(num);\r\n // add.setInput(this);\r\n this.connect(add);\r\n return add;\r\n };\r\n Mult.prototype.add = Signal.prototype.add;\r\n Add.prototype.add = Signal.prototype.add;\r\n Scale.prototype.add = Signal.prototype.add;\r\n\r\n /**\r\n * Multiply this signal by a constant value,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalMult.\r\n *\r\n * @method mult\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n // mult.setInput(this);\r\n this.connect(mult);\r\n return mult;\r\n };\r\n Mult.prototype.mult = Signal.prototype.mult;\r\n Add.prototype.mult = Signal.prototype.mult;\r\n Scale.prototype.mult = Signal.prototype.mult;\r\n\r\n /**\r\n * Scale this signal value to a given range,\r\n * and return the result as an audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalScale.\r\n *\r\n * @method scale\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n this.connect(scale);\r\n return scale;\r\n };\r\n Mult.prototype.scale = Signal.prototype.scale;\r\n Add.prototype.scale = Signal.prototype.scale;\r\n Scale.prototype.scale = Signal.prototype.scale;\r\n\r\n});\r\n\r\n\r\n","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Frequency is a primitive type for encoding Frequency values. \n\t * Eventually all time values are evaluated to hertz\n\t * using the `eval` method. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * Tone.Frequency(\"C3\") // 261\n\t * Tone.Frequency(38, \"midi\") //\n\t * Tone.Frequency(\"C3\").transpose(4);\n\t */\n\tTone.Frequency = function(val, units){\n\t\tif (this instanceof Tone.Frequency){\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Frequency(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Frequency, Tone.TimeBase);\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUGMENT BASE EXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);\n\n\t/*\n\t * midi type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.midi = {\n\t\tregexp : /^(\\d+(?:\\.\\d+)?midi)/,\n\t\tmethod : function(value){\n\t\t\treturn this.midiToFrequency(value);\n\t\t}\t\n\t};\n\n\t/*\n\t * note type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.note = {\n\t\tregexp : /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,\n\t\tmethod : function(pitch, octave){\n\t\t\tvar index = noteToScaleIndex[pitch.toLowerCase()];\n\t\t\tvar noteNumber = index + (parseInt(octave) + 1) * 12;\n\t\t\treturn this.midiToFrequency(noteNumber);\n\t\t}\t\n\t};\n\n\t/*\n\t * BeatsBarsSixteenths type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.tr = {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\tvar total = 1;\n\t\t\tif (m && m !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t}\n\t\t\tif (q && q !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(q));\n\t\t\t}\n\t\t\tif (s && s !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t}\n\t\t\treturn total;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Transposes the frequency by the given number of semitones.\n\t * @param {Interval} interval\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").transpose(3); //\"C5\"\n\t */\n\tTone.Frequency.prototype.transpose = function(interval){\n\t\tthis._expr = function(expr, interval){\n\t\t\tvar val = expr();\n\t\t\treturn val * this.intervalToFrequencyRatio(interval);\n\t\t}.bind(this, this._expr, interval);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Takes an array of semitone intervals and returns\n\t * an array of frequencies transposed by those intervals.\n\t * @param {Array} intervals\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").harmonize([0, 3, 7]); //[\"A4\", \"C5\", \"E5\"]\n\t */\n\tTone.Frequency.prototype.harmonize = function(intervals){\n\t\tthis._expr = function(expr, intervals){\n\t\t\tvar val = expr();\n\t\t\tvar ret = [];\n\t\t\tfor (var i = 0; i < intervals.length; i++){\n\t\t\t\tret[i] = val * this.intervalToFrequencyRatio(intervals[i]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t}.bind(this, this._expr, intervals);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the value of the frequency as a MIDI note\n\t * @return {MIDI}\n\t * @example\n\t * Tone.Frequency(\"C4\").toMidi(); //60\n\t */\n\tTone.Frequency.prototype.toMidi = function(){\n\t\treturn this.frequencyToMidi(this.valueOf());\n\t};\n\n\t/**\n\t * Return the value of the frequency in Scientific Pitch Notation\n\t * @return {Note}\n\t * @example\n\t * Tone.Frequency(69, \"midi\").toNote(); //\"A4\"\n\t */\n\tTone.Frequency.prototype.toNote = function(){\n\t\tvar freq = this.valueOf();\n\t\tvar log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;\n\t\tvar noteNumber = Math.round(12 * log) + 57;\n\t\tvar octave = Math.floor(noteNumber/12);\n\t\tif(octave < 0){\n\t\t\tnoteNumber += -12 * octave;\n\t\t}\n\t\tvar noteName = scaleIndexToNote[noteNumber % 12];\n\t\treturn noteName + octave.toString();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.Frequency.prototype.toSeconds = function(){\n\t\treturn 1 / this.valueOf();\n\t};\n\n\t/**\n\t * Return the value in Hertz\n\t * @return {Frequency}\n\t */\n\tTone.Frequency.prototype.toFrequency = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in ticks\n\t * @return {Ticks}\n\t */\n\tTone.Frequency.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS HELPERS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._frequencyToUnits = function(freq){\n\t\treturn freq;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._ticksToUnits = function(ticks){\n\t\treturn 1 / ((ticks * 60) / (Tone.Transport.bpm.value * Tone.Transport.PPQ));\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._beatsToUnits = function(beats){\n\t\treturn 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._secondsToUnits = function(seconds){\n\t\treturn 1 / seconds;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.Frequency.prototype._defaultUnits = \"hz\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tFREQUENCY CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Note to scale index\n\t * @type {Object}\n\t */\n\tvar noteToScaleIndex = {\n\t\t\"cbb\" : -2, \"cb\" : -1, \"c\" : 0, \"c#\" : 1, \"cx\" : 2, \n\t\t\"dbb\" : 0, \"db\" : 1, \"d\" : 2, \"d#\" : 3, \"dx\" : 4,\n\t\t\"ebb\" : 2, \"eb\" : 3, \"e\" : 4, \"e#\" : 5, \"ex\" : 6, \n\t\t\"fbb\" : 3, \"fb\" : 4, \"f\" : 5, \"f#\" : 6, \"fx\" : 7,\n\t\t\"gbb\" : 5, \"gb\" : 6, \"g\" : 7, \"g#\" : 8, \"gx\" : 9,\n\t\t\"abb\" : 7, \"ab\" : 8, \"a\" : 9, \"a#\" : 10, \"ax\" : 11,\n\t\t\"bbb\" : 9, \"bb\" : 10, \"b\" : 11, \"b#\" : 12, \"bx\" : 13,\n\t};\n\n\t/**\n\t * scale index to note (sharps)\n\t * @type {Array}\n\t */\n\tvar scaleIndexToNote = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"];\n\n\t/**\n\t * The [concert pitch](https://en.wikipedia.org/wiki/Concert_pitch)\n\t * A4's values in Hertz. \n\t * @type {Frequency}\n\t * @static\n\t */\n\tTone.Frequency.A4 = 440;\n\n\t/**\n\t * Convert a MIDI note to frequency value. \n\t * @param {MIDI} midi The midi number to convert.\n\t * @return {Frequency} the corresponding frequency value\n\t * @example\n\t * tone.midiToFrequency(69); // returns 440\n\t */\n\tTone.Frequency.prototype.midiToFrequency = function(midi){\n\t\treturn Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);\n\t};\n\n\t/**\n\t * Convert a frequency value to a MIDI note.\n\t * @param {Frequency} frequency The value to frequency value to convert.\n\t * @returns {MIDI}\n\t * @example\n\t * tone.midiToFrequency(440); // returns 69\n\t */\n\tTone.Frequency.prototype.frequencyToMidi = function(frequency){\n\t\treturn 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;\n\t};\n\n\treturn Tone.Frequency;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TransportTime is a the time along the Transport's\n\t * timeline. It is similar to Tone.Time, but instead of evaluating\n\t * against the AudioContext's clock, it is evaluated against\n\t * the Transport's position. See [TransportTime wiki](https://github.com/Tonejs/Tone.js/wiki/TransportTime).\n\t * @constructor\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @extends {Tone.Time}\n\t */\n\tTone.TransportTime = function(val, units){\n\t\tif (this instanceof Tone.TransportTime){\n\t\t\t\n\t\t\tTone.Time.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.TransportTime(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TransportTime, Tone.Time);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);\n\n\t/**\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\tvar subdivision = this._secondsToTicks(rh());\n\t\t\tvar multiple = Math.ceil(Tone.Transport.ticks / subdivision);\n\t\t\treturn this._ticksToUnits(multiple * subdivision);\n\t\t}\n\t};\n\n\t/**\n\t * Convert seconds into ticks\n\t * @param {Seconds} seconds\n\t * @return {Ticks}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._secondsToTicks = function(seconds){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = seconds / quarterTime;\n\t\treturn Math.round(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Evaluate the time expression. Returns values in ticks\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.valueOf = function(){\n\t\tvar val = this._secondsToTicks(this._expr());\n\t\treturn val + (this._plusNow ? Tone.Transport.ticks : 0);\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.toTicks = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.TransportTime.prototype.toSeconds = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow ? Tone.Transport.seconds : 0);\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t */\n\tTone.TransportTime.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\treturn Tone.TransportTime;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n\r\n /**\r\n *
Envelopes are pre-defined amplitude distribution over time.\r\n * Typically, envelopes are used to control the output volume\r\n * of an object, a series of fades referred to as Attack, Decay,\r\n * Sustain and Release (\r\n * ADSR\r\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\r\n * control an Oscillator's frequency like this: osc.freq(env).
\r\n *
Use setRange to change the attack/release level.\r\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.
\r\n *
Use the play method to play the entire envelope,\r\n * the ramp method for a pingable trigger,\r\n * or triggerAttack/\r\n * triggerRelease to trigger noteOn/noteOff.
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope = function(t1, l1, t2, l2, t3, l3) {\r\n /**\r\n * Time until envelope reaches attackLevel\r\n * @property attackTime\r\n */\r\n this.aTime = t1 || 0.1;\r\n /**\r\n * Level once attack is complete.\r\n * @property attackLevel\r\n */\r\n this.aLevel = l1 || 1;\r\n /**\r\n * Time until envelope reaches decayLevel.\r\n * @property decayTime\r\n */\r\n this.dTime = t2 || 0.5;\r\n /**\r\n * Level after decay. The envelope will sustain here until it is released.\r\n * @property decayLevel\r\n */\r\n this.dLevel = l2 || 0;\r\n /**\r\n * Duration of the release portion of the envelope.\r\n * @property releaseTime\r\n */\r\n this.rTime = t3 || 0;\r\n /**\r\n * Level at the end of the release.\r\n * @property releaseLevel\r\n */\r\n this.rLevel = l3 || 0;\r\n\r\n this._rampHighPercentage = 0.98;\r\n\r\n this._rampLowPercentage = 0.02;\r\n\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.control = new TimelineSignal();\r\n\r\n this._init(); // this makes sure the envelope starts at zero\r\n\r\n this.control.connect(this.output); // connect to the output\r\n\r\n this.connection = null; // store connection\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.control];\r\n\r\n //whether envelope should be linear or exponential curve\r\n this.isExponential = false;\r\n\r\n // oscillator or buffer source to clear on env complete\r\n // to save resources if/when it is retriggered\r\n this.sourceToClear = null;\r\n\r\n // set to true if attack is set, then false on release\r\n this.wasTriggered = false;\r\n\r\n\r\n // add to the soundArray so we can dispose of the env later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n // this init function just smooths the starting value to zero and gives a start point for the timeline\r\n // - it was necessary to remove glitches at the beginning.\r\n p5.Envelope.prototype._init = function () {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = now;\r\n this.control.setTargetAtTime(0.00001, t, .001);\r\n //also, compute the correct time constants\r\n this._setRampAD(this.aTime, this.dTime);\r\n };\r\n\r\n /**\r\n * Reset the envelope with a series of time/value pairs.\r\n *\r\n * @method set\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds) before level\r\n * reaches attackLevel\r\n * @param {Number} attackLevel Typically an amplitude between\r\n * 0.0 and 1.0\r\n * @param {Number} decayTime Time\r\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\r\n * decayLevel = sustainLevel)\r\n * @param {Number} releaseTime Release Time (in seconds)\r\n * @param {Number} releaseLevel Amplitude\r\n * @example\r\n *
\r\n * var t1 = 0.1; // attack time in seconds\r\n * var l1 = 0.7; // attack level 0.0 to 1.0\r\n * var t2 = 0.3; // decay time in seconds\r\n * var l2 = 0.1; // decay level 0.0 to 1.0\r\n * var t3 = 0.2; // sustain time in seconds\r\n * var l3 = 0.5; // sustain level 0.0 to 1.0\r\n * // release level defaults to zero\r\n *\r\n * var env;\r\n * var triOsc;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope(t1, l1, t2, l2, t3, l3);\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env); // give the env control of the triOsc's amp\r\n * triOsc.start();\r\n * }\r\n *\r\n * // mouseClick triggers envelope if over canvas\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(triOsc);\r\n * }\r\n * }\r\n *
\r\n *\r\n */\r\n p5.Envelope.prototype.set = function(t1, l1, t2, l2, t3, l3) {\r\n this.aTime = t1;\r\n this.aLevel = l1;\r\n this.dTime = t2 || 0;\r\n this.dLevel = l2 || 0;\r\n this.rTime = t3 || 0;\r\n this.rLevel = l3 || 0;\r\n\r\n // set time constants for ramp\r\n this._setRampAD(t1, t2);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setADSR = function(aTime, dTime, sPercent, rTime) {\r\n this.aTime = aTime;\r\n this.dTime = dTime || 0;\r\n\r\n // lerp\r\n this.sPercent = sPercent || 0;\r\n this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n\r\n this.rTime = rTime || 0;\r\n\r\n // also set time constants for ramp\r\n this._setRampAD(aTime, dTime);\r\n };\r\n\r\n /**\r\n * Set max (attackLevel) and min (releaseLevel) of envelope.\r\n *\r\n * @method setRange\r\n * @for p5.Envelope\r\n * @param {Number} aLevel attack level (defaults to 1)\r\n * @param {Number} rLevel release level (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setRange = function(aLevel, rLevel) {\r\n this.aLevel = aLevel || 1;\r\n this.rLevel = rLevel || 0;\r\n\r\n // not sure if this belongs here:\r\n\r\n // {Number} [dLevel] decay/sustain level (optional)\r\n // if (typeof(dLevel) !== 'undefined') {\r\n // this.dLevel = dLevel\r\n // } else if (this.sPercent) {\r\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n // }\r\n };\r\n\r\n // private (undocumented) method called when ADSR is set to set time constants for ramp\r\n //\r\n // Set the \r\n // time constants for simple exponential ramps.\r\n // The larger the time constant value, the slower the\r\n // transition will be.\r\n //\r\n // method _setRampAD\r\n // param {Number} attackTimeConstant attack time constant\r\n // param {Number} decayTimeConstant decay time constant\r\n //\r\n p5.Envelope.prototype._setRampAD = function(t1, t2) {\r\n this._rampAttackTime = this.checkExpInput(t1);\r\n this._rampDecayTime = this.checkExpInput(t2);\r\n\r\n var TCDenominator = 1.0;\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n // private method\r\n p5.Envelope.prototype.setRampPercentages = function(p1, p2) {\r\n //set the percentages that the simple exponential ramps go to\r\n this._rampHighPercentage = this.checkExpInput(p1);\r\n this._rampLowPercentage = this.checkExpInput(p2);\r\n var TCDenominator = 1.0;\r\n //now re-compute the time constants based on those percentages\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n\r\n /**\r\n * Assign a parameter to be controlled by this envelope.\r\n * If a p5.Sound object is given, then the p5.Envelope will control its\r\n * output gain. If multiple inputs are provided, the env will\r\n * control all of them.\r\n *\r\n * @method setInput\r\n * @for p5.Envelope\r\n * @param {Object} [...inputs] A p5.sound object or\r\n * Web Audio Param.\r\n */\r\n p5.Envelope.prototype.setInput = function() {\r\n for (var i = 0; i\r\n * Web Audio Audio Param.\r\n *\r\n * @method play\r\n * @for p5.Envelope\r\n * @param {Object} unit A p5.sound object or\r\n * Web Audio Param.\r\n * @param {Number} [startTime] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * // trigger env on triOsc, 0 seconds from now\r\n * // After decay, sustain for 0.2 seconds before release\r\n * env.play(triOsc, 0, 0.2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.play = function(unit, secondsFromNow, susTime) {\r\n var tFromNow = secondsFromNow || 0;\r\n var susTime = susTime || 0;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n this.triggerAttack(unit, tFromNow);\r\n\r\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime);\r\n\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go. Input can be\r\n * any p5.sound object, or a \r\n * Web Audio Param.\r\n *\r\n * @method triggerAttack\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time from now (in seconds)\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerAttack = function(unit, secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n this.lastAttack = t;\r\n this.wasTriggered = true;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // after each ramp completes, cancel scheduled values\r\n // (so they can be overridden in case env has been re-triggered)\r\n // then, set current value (with linearRamp to avoid click)\r\n // then, schedule the next automation...\r\n\r\n // attack\r\n t += this.aTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.aLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n\r\n }\r\n\r\n // decay to decay level (if using ADSR, then decay level == sustain level)\r\n t += this.dTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.dLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n };\r\n\r\n /**\r\n * Trigger the Release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method triggerRelease\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerRelease = function(unit, secondsFromNow) {\r\n\r\n // only trigger a release if an attack was triggered\r\n if (!this.wasTriggered) {\r\n // this currently causes a bit of trouble:\r\n // if a later release has been scheduled (via the play function)\r\n // a new earlier release won't interrupt it, because\r\n // this.wasTriggered has already been set to false.\r\n // If we want new earlier releases to override, then we need to\r\n // keep track of the last release time, and if the new release time is\r\n // earlier, then use it.\r\n return;\r\n }\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear or exponential ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // release\r\n t += this.rTime;\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.rLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n this.wasTriggered = false;\r\n };\r\n\r\n /**\r\n * Exponentially ramp to a value using the first two\r\n * values from setADSR(attackTime, decayTime)\r\n * as \r\n * time constants for simple exponential ramps.\r\n * If the value is higher than current value, it uses attackTime,\r\n * while a decrease uses decayTime.\r\n *\r\n * @method ramp\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow When to trigger the ramp\r\n * @param {Number} v Target value\r\n * @param {Number} [v2] Second target value (optional)\r\n * @example\r\n *
\r\n * var env, osc, amp, cnv;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var attackLevel = 1;\r\n * var decayLevel = 0;\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100, 100);\r\n * fill(0,255,0);\r\n * noStroke();\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.amp(env);\r\n * osc.start();\r\n *\r\n * amp = new p5.Amplitude();\r\n *\r\n * cnv.mousePressed(triggerRamp);\r\n * }\r\n *\r\n * function triggerRamp() {\r\n * env.ramp(osc, 0, attackLevel, decayLevel);\r\n * }\r\n *\r\n * function draw() {\r\n * background(20,20,20);\r\n * text('click me', 10, 20);\r\n * var h = map(amp.getLevel(), 0, 0.4, 0, height);;\r\n *\r\n * rect(0, height, width, -h);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.ramp = function(unit, secondsFromNow, v1, v2) {\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n var destination1 = this.checkExpInput(v1);\r\n var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\r\n\r\n // connect env to unit if not already connected\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n //get current value\r\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\r\n // this.control.cancelScheduledValues(t);\r\n\r\n //if it's going up\r\n if (destination1 > currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\r\n t += this._rampAttackTime;\r\n }\r\n\r\n //if it's going down\r\n else if (destination1 < currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\r\n t += this._rampDecayTime;\r\n }\r\n\r\n // Now the second part of envelope begins\r\n if (destination2 === undefined) return;\r\n\r\n //if it's going up\r\n if (destination2 > destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\r\n }\r\n\r\n //if it's going down\r\n else if (destination2 < destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\r\n }\r\n };\r\n\r\n\r\n p5.Envelope.prototype.connect = function(unit) {\r\n this.connection = unit;\r\n\r\n // assume we're talking about output gain\r\n // unless given a different audio param\r\n if (unit instanceof p5.Oscillator ||\r\n unit instanceof p5.SoundFile ||\r\n unit instanceof p5.AudioIn ||\r\n unit instanceof p5.Reverb ||\r\n unit instanceof p5.Noise ||\r\n unit instanceof p5.Filter ||\r\n unit instanceof p5.Delay\r\n ) {\r\n unit = unit.output.gain;\r\n }\r\n if (unit instanceof AudioParam) {\r\n //set the initial value\r\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\r\n }\r\n if (unit instanceof p5.Signal) {\r\n unit.setValue(0);\r\n }\r\n this.output.connect(unit);\r\n };\r\n\r\n p5.Envelope.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n // Signal Math\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method\r\n * again will override the initial add() with new values.\r\n *\r\n * @method add\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Envelope's output amplitude\r\n * by a fixed value. Calling this method\r\n * again will override the initial mult() with new values.\r\n *\r\n * @method mult\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this envelope's amplitude values to a given\r\n * range, and return the envelope. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Envelope\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var scale = new Scale(inMin, inMax, outMin, outMax);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\r\n };\r\n\r\n\r\n // get rid of the oscillator\r\n p5.Envelope.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.disconnect();\r\n if (this.control) {\r\n this.control.dispose();\r\n this.control = null;\r\n }\r\n for (var i = 1; i < this.mathOps.length; i++) {\r\n this.mathOps[i].dispose();\r\n }\r\n };\r\n\r\n // Different name for backwards compatibility, replicates p5.Envelope class\r\n p5.Env = function(t1, l1, t2, l2, t3, l3) {\r\n console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\r\n 'Please use the new p5.Envelope instead.');\r\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\r\n };\r\n p5.Env.prototype = Object.create(p5.Envelope.prototype);\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n require('oscillator');\r\n\r\n /**\r\n * Creates a Pulse object, an oscillator that implements\r\n * Pulse Width Modulation.\r\n * The pulse is created with two oscillators.\r\n * Accepts a parameter for frequency, and to set the\r\n * width between the pulses. See \r\n * p5.Oscillator for a full list of methods.\r\n *\r\n * @class p5.Pulse\r\n * @extends p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\r\n * @param {Number} [w] Width between the pulses (0 to 1.0,\r\n * defaults to 0)\r\n * @example\r\n *
Note: This uses the getUserMedia/\r\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\r\n * is limited to localhost and https, but access over http may be limited.
\r\n *\r\n * @class p5.AudioIn\r\n * @constructor\r\n * @param {Function} [errorCallback] A function to call if there is an error\r\n * accessing the AudioIn. For example,\r\n * Safari and iOS devices do not\r\n * currently allow microphone access.\r\n * @example\r\n *
\r\n * var mic;\r\n * function setup(){\r\n * mic = new p5.AudioIn()\r\n * mic.start();\r\n * }\r\n * function draw(){\r\n * background(0);\r\n * micLevel = mic.getLevel();\r\n * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);\r\n * }\r\n *
\r\n */\r\n p5.AudioIn = function(errorCallback) {\r\n // set up audio input\r\n /**\r\n * @property {GainNode} input\r\n */\r\n this.input = p5sound.audiocontext.createGain();\r\n /**\r\n * @property {GainNode} output\r\n */\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n /**\r\n * @property {MediaStream|null} stream\r\n */\r\n this.stream = null;\r\n /**\r\n * @property {MediaStreamAudioSourceNode|null} mediaStream\r\n */\r\n this.mediaStream = null;\r\n /**\r\n * @property {Number|null} currentSource\r\n */\r\n this.currentSource = null;\r\n\r\n /**\r\n * Client must allow browser to access their microphone / audioin source.\r\n * Default: false. Will become true when the client enables acces.\r\n *\r\n * @property {Boolean} enabled\r\n */\r\n this.enabled = false;\r\n\r\n /**\r\n * Input amplitude, connect to it by default but not to master out\r\n *\r\n * @property {p5.Amplitude} amplitude\r\n */\r\n this.amplitude = new p5.Amplitude();\r\n this.output.connect(this.amplitude.input);\r\n\r\n if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) {\r\n errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices');\r\n }\r\n\r\n // add to soundArray so we can dispose on close\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start processing audio input. This enables the use of other\r\n * AudioIn methods like getLevel(). Note that by default, AudioIn\r\n * is not connected to p5.sound's output. So you won't hear\r\n * anything unless you use the connect() method. \r\n *\r\n * Certain browsers limit access to the user's microphone. For example,\r\n * Chrome only allows access from localhost and over https. For this reason,\r\n * you may want to include an errorCallback—a function that is called in case\r\n * the browser won't provide mic access.\r\n *\r\n * @method start\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] Name of a function to call on\r\n * success.\r\n * @param {Function} [errorCallback] Name of a function to call if\r\n * there was an error. For example,\r\n * some browsers do not support\r\n * getUserMedia.\r\n */\r\n p5.AudioIn.prototype.start = function(successCallback, errorCallback) {\r\n var self = this;\r\n\r\n if (this.stream) {\r\n this.stop();\r\n }\r\n\r\n // set the audio source\r\n var audioSource = p5sound.inputSources[self.currentSource];\r\n var constraints = {\r\n audio: {\r\n sampleRate: p5sound.audiocontext.sampleRate,\r\n echoCancellation: false\r\n }\r\n };\r\n\r\n // if developers determine which source to use\r\n if (p5sound.inputSources[this.currentSource]) {\r\n constraints.audio.deviceId = audioSource.deviceId;\r\n }\r\n\r\n window.navigator.mediaDevices.getUserMedia( constraints )\r\n .then( function(stream) {\r\n self.stream = stream;\r\n self.enabled = true;\r\n // Wrap a MediaStreamSourceNode around the live input\r\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\r\n self.mediaStream.connect(self.output);\r\n // only send to the Amplitude reader, so we can see it but not hear it.\r\n self.amplitude.setInput(self.output);\r\n if (successCallback) successCallback();\r\n })\r\n .catch( function(err) {\r\n if (errorCallback) errorCallback(err);\r\n else console.error(err);\r\n });\r\n };\r\n\r\n /**\r\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\r\n * If re-starting, the user may be prompted for permission access.\r\n *\r\n * @method stop\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.stop = function() {\r\n if (this.stream) {\r\n this.stream.getTracks().forEach(function(track) {\r\n track.stop();\r\n });\r\n\r\n this.mediaStream.disconnect();\r\n\r\n delete this.mediaStream;\r\n delete this.stream;\r\n }\r\n };\r\n\r\n /**\r\n * Connect to an audio unit. If no parameter is provided, will\r\n * connect to the master output (i.e. your speakers). \r\n *\r\n * @method connect\r\n * @for p5.AudioIn\r\n * @param {Object} [unit] An object that accepts audio input,\r\n * such as an FFT\r\n */\r\n p5.AudioIn.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n }\r\n else if (unit.hasOwnProperty('analyser')) {\r\n this.output.connect(unit.analyser);\r\n }\r\n else {\r\n this.output.connect(unit);\r\n }\r\n }\r\n else {\r\n this.output.connect(p5sound.input);\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect the AudioIn from all audio units. For example, if\r\n * connect() had been called, disconnect() will stop sending\r\n * signal to your speakers. \r\n *\r\n * @method disconnect\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n // stay connected to amplitude even if not outputting to p5\r\n this.output.connect(this.amplitude.input);\r\n }\r\n };\r\n\r\n /**\r\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\r\n * class contains its own instance of the Amplitude class to help\r\n * make it easy to get a microphone's volume level. Accepts an\r\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\r\n * .start() before using .getLevel(). \r\n *\r\n * @method getLevel\r\n * @for p5.AudioIn\r\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\r\n * Smooths values based on previous values.\r\n * @return {Number} Volume level (between 0.0 and 1.0)\r\n */\r\n p5.AudioIn.prototype.getLevel = function(smoothing) {\r\n if (smoothing) {\r\n this.amplitude.smoothing = smoothing;\r\n }\r\n return this.amplitude.getLevel();\r\n };\r\n\r\n /**\r\n * Set amplitude (volume) of a mic input between 0 and 1.0. \r\n *\r\n * @method amp\r\n * @for p5.AudioIn\r\n * @param {Number} vol between 0 and 1.0\r\n * @param {Number} [time] ramp time (optional)\r\n */\r\n p5.AudioIn.prototype.amp = function(vol, t) {\r\n if (t) {\r\n var rampTime = t || 0;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime);\r\n this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime);\r\n } else {\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Returns a list of available input sources. This is a wrapper\r\n * for and it returns a Promise.\r\n *\r\n * @method getSources\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] This callback function handles the sources when they\r\n * have been enumerated. The callback function\r\n * receives the deviceList array as its only argument\r\n * @param {Function} [errorCallback] This optional callback receives the error\r\n * message as its argument.\r\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\r\n * to the enumerateDevices() method\r\n * @example\r\n *
\r\n */\r\n p5.AudioIn.prototype.getSources = function (onSuccess, onError) {\r\n return new Promise( function(resolve, reject) {\r\n window.navigator.mediaDevices.enumerateDevices()\r\n .then( function(devices) {\r\n p5sound.inputSources = devices.filter(function(device) {\r\n return device.kind === 'audioinput';\r\n });\r\n resolve(p5sound.inputSources);\r\n if (onSuccess) {\r\n onSuccess(p5sound.inputSources);\r\n }\r\n })\r\n .catch( function(error) {\r\n reject(error);\r\n if (onError) {\r\n onError(error);\r\n } else {\r\n console.error('This browser does not support MediaStreamTrack.getSources()');\r\n }\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Set the input source. Accepts a number representing a\r\n * position in the array returned by getSources().\r\n * This is only available in browsers that support\r\n * navigator.mediaDevices.enumerateDevices(). \r\n *\r\n * @method setSource\r\n * @for p5.AudioIn\r\n * @param {number} num position of input source in the array\r\n */\r\n p5.AudioIn.prototype.setSource = function(num) {\r\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\r\n // set the current source\r\n this.currentSource = num;\r\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\r\n } else {\r\n console.log('unable to set input source');\r\n }\r\n\r\n // restart stream if currently active\r\n if (this.stream && this.stream.active) {\r\n this.start();\r\n }\r\n };\r\n\r\n // private method\r\n p5.AudioIn.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop();\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.amplitude) {\r\n this.amplitude.disconnect();\r\n }\r\n delete this.amplitude;\r\n delete this.output;\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Expr\", \n\t\"Tone/signal/EqualPowerGain\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Crossfade provides equal power fading between two inputs. \n\t * More on crossfading technique [here](https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Crossfading).\n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t * @param {NormalRange} [initialFade=0.5]\n\t * @example\n\t * var crossFade = new Tone.CrossFade(0.5);\n\t * //connect effect A to crossfade from\n\t * //effect output 0 to crossfade input 0\n\t * effectA.connect(crossFade, 0, 0);\n\t * //connect effect B to crossfade from\n\t * //effect output 0 to crossfade input 1\n\t * effectB.connect(crossFade, 0, 1);\n\t * crossFade.fade.value = 0;\n\t * // ^ only effectA is output\n\t * crossFade.fade.value = 1;\n\t * // ^ only effectB is output\n\t * crossFade.fade.value = 0.5;\n\t * // ^ the two signals are mixed equally. \n\t */\t\t\n\tTone.CrossFade = function(initialFade){\n\n\t\tthis.createInsOuts(2, 1);\n\n\t\t/**\n\t\t * Alias for input[0]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.a = this.input[0] = new Tone.Gain();\n\n\t\t/**\n\t\t * Alias for input[1]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.b = this.input[1] = new Tone.Gain();\n\n\t\t/**\n\t\t * \tThe mix between the two inputs. A fade value of 0\n\t\t * \twill output 100% input[0] and \n\t\t * \ta value of 1 will output 100% input[1]. \n\t\t * @type {NormalRange}\n\t\t * @signal\n\t\t */\n\t\tthis.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerA = new Tone.EqualPowerGain();\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerB = new Tone.EqualPowerGain();\n\t\t\n\t\t/**\n\t\t * invert the incoming signal\n\t\t * @private\n\t\t * @type {Tone}\n\t\t */\n\t\tthis._invert = new Tone.Expr(\"1 - $0\");\n\n\t\t//connections\n\t\tthis.a.connect(this.output);\n\t\tthis.b.connect(this.output);\n\t\tthis.fade.chain(this._equalPowerB, this.b.gain);\n\t\tthis.fade.chain(this._invert, this._equalPowerA, this.a.gain);\n\t\tthis._readOnly(\"fade\");\n\t};\n\n\tTone.extend(Tone.CrossFade);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.CrossFade} this\n\t */\n\tTone.CrossFade.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._writable(\"fade\");\n\t\tthis._equalPowerA.dispose();\n\t\tthis._equalPowerA = null;\n\t\tthis._equalPowerB.dispose();\n\t\tthis._equalPowerB = null;\n\t\tthis.fade.dispose();\n\t\tthis.fade = null;\n\t\tthis._invert.dispose();\n\t\tthis._invert = null;\n\t\tthis.a.dispose();\n\t\tthis.a = null;\n\t\tthis.b.dispose();\n\t\tthis.b = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.CrossFade;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Subtract\", \"Tone/signal/Multiply\", \n\t\"Tone/signal/GreaterThan\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Abs\", \"Tone/signal/Negate\", \n\t\"Tone/signal/Modulo\", \"Tone/signal/Pow\", \"Tone/signal/AudioToGain\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Evaluate an expression at audio rate.
\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {string} expr the expression to generate\n\t * @example\n\t * //adds the signals from input[0] and input[1].\n\t * var expr = new Tone.Expr(\"$0 + $1\");\n\t */\n\tTone.Expr = function(){\n\n\t\tvar expr = this._replacements(Array.prototype.slice.call(arguments));\n\t\tvar inputCount = this._parseInputs(expr);\n\n\t\t/**\n\t\t * hold onto all of the nodes for disposal\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._nodes = [];\n\n\t\t/**\n\t\t * The inputs. The length is determined by the expression. \n\t\t * @type {Array}\n\t\t */\n\t\tthis.input = new Array(inputCount);\n\n\t\t//create a gain for each input\n\t\tfor (var i = 0; i < inputCount; i++){\n\t\t\tthis.input[i] = this.context.createGain();\n\t\t}\n\n\t\t//parse the syntax tree\n\t\tvar tree = this._parseTree(expr);\n\t\t//evaluate the results\n\t\tvar result;\n\t\ttry {\n\t\t\tresult = this._eval(tree);\n\t\t} catch (e){\n\t\t\tthis._disposeNodes();\n\t\t\tthrow new Error(\"Tone.Expr: Could evaluate expression: \"+expr);\n\t\t}\n\n\t\t/**\n\t\t * The output node is the result of the expression\n\t\t * @type {Tone}\n\t\t */\n\t\tthis.output = result;\n\t};\n\n\tTone.extend(Tone.Expr, Tone.SignalBase);\n\n\t//some helpers to cut down the amount of code\n\tfunction applyBinary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\tself._eval(args[1]).connect(op, 0, 1);\n\t\treturn op;\n\t}\n\tfunction applyUnary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\treturn op;\n\t}\n\tfunction getNumber(arg){\n\t\treturn arg ? parseFloat(arg) : undefined;\n\t}\n\tfunction literalNumber(arg){\n\t\treturn arg && arg.args ? parseFloat(arg.args) : undefined;\n\t}\n\n\t/*\n\t * the Expressions that Tone.Expr can parse.\n\t *\n\t * each expression belongs to a group and contains a regexp \n\t * for selecting the operator as well as that operators method\n\t * \n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Expr._Expressions = {\n\t\t//values\n\t\t\"value\" : {\n\t\t\t\"signal\" : {\n\t\t\t\tregexp : /^\\d+\\.\\d+|^\\d+/,\n\t\t\t\tmethod : function(arg){\n\t\t\t\t\tvar sig = new Tone.Signal(getNumber(arg));\n\t\t\t\t\treturn sig;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"input\" : {\n\t\t\t\tregexp : /^\\$\\d/,\n\t\t\t\tmethod : function(arg, self){\n\t\t\t\t\treturn self.input[getNumber(arg.substr(1))];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t//syntactic glue\n\t\t\"glue\" : {\n\t\t\t\"(\" : {\n\t\t\t\tregexp : /^\\(/,\n\t\t\t},\n\t\t\t\")\" : {\n\t\t\t\tregexp : /^\\)/,\n\t\t\t},\n\t\t\t\",\" : {\n\t\t\t\tregexp : /^,/,\n\t\t\t}\n\t\t},\n\t\t//functions\n\t\t\"func\" : {\n\t\t\t\"abs\" : {\n\t\t\t\tregexp : /^abs/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Abs)\n\t\t\t},\n\t\t\t\"mod\" : {\n\t\t\t\tregexp : /^mod/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar modulus = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Modulo(modulus);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"pow\" : {\n\t\t\t\tregexp : /^pow/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar exp = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Pow(exp);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"a2g\" : {\n\t\t\t\tregexp : /^a2g/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar op = new Tone.AudioToGain();\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t//binary expressions\n\t\t\"binary\" : {\n\t\t\t\"+\" : {\n\t\t\t\tregexp : /^\\+/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Add)\n\t\t\t},\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\t//both unary and binary op\n\t\t\t\t\tif (args.length === 1){\n\t\t\t\t\t\treturn applyUnary(Tone.Negate, args, self);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn applyBinary(Tone.Subtract, args, self);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"*\" : {\n\t\t\t\tregexp : /^\\*/,\n\t\t\t\tprecedence : 0,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Multiply)\n\t\t\t}\n\t\t},\n\t\t//unary expressions\n\t\t\"unary\" : {\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Negate)\n\t\t\t},\n\t\t\t\"!\" : {\n\t\t\t\tregexp : /^\\!/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.NOT)\n\t\t\t},\n\t\t},\n\t};\n\t\t\n\t/**\n\t * @param {string} expr the expression string\n\t * @return {number} the input count\n\t * @private\n\t */\n\tTone.Expr.prototype._parseInputs = function(expr){\n\t\tvar inputArray = expr.match(/\\$\\d/g);\n\t\tvar inputMax = 0;\n\t\tif (inputArray !== null){\n\t\t\tfor (var i = 0; i < inputArray.length; i++){\n\t\t\t\tvar inputNum = parseInt(inputArray[i].substr(1)) + 1;\n\t\t\t\tinputMax = Math.max(inputMax, inputNum);\n\t\t\t}\n\t\t}\n\t\treturn inputMax;\n\t};\n\n\t/**\n\t * @param {Array} args \tan array of arguments\n\t * @return {string} the results of the replacements being replaced\n\t * @private\n\t */\n\tTone.Expr.prototype._replacements = function(args){\n\t\tvar expr = args.shift();\n\t\tfor (var i = 0; i < args.length; i++){\n\t\t\texpr = expr.replace(/\\%/i, args[i]);\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.Expr.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr){\n\t\t\tfor (var type in Tone.Expr._Expressions){\n\t\t\t\tvar group = Tone.Expr._Expressions[type];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype : type,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t\tmethod : op.method\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * recursively parse the string expression into a syntax tree\n\t * \n\t * @param {string} expr \n\t * @return {Object}\n\t * @private\n\t */\n\tTone.Expr.prototype._parseTree = function(expr){\n\t\tvar lexer = this._tokenize(expr);\n\t\tvar isUndef = this.isUndef.bind(this);\n\n\t\tfunction matchSyntax(token, syn) {\n\t\t\treturn !isUndef(token) && \n\t\t\t\ttoken.type === \"glue\" &&\n\t\t\t\ttoken.value === syn;\n\t\t}\n\n\t\tfunction matchGroup(token, groupName, prec) {\n\t\t\tvar ret = false;\n\t\t\tvar group = Tone.Expr._Expressions[groupName];\n\t\t\tif (!isUndef(token)){\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\t\tif (!isUndef(prec)){\n\t\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\n\t\tfunction parseExpression(precedence) {\n\t\t\tif (isUndef(precedence)){\n\t\t\t\tprecedence = 5;\n\t\t\t}\n\t\t\tvar expr;\n\t\t\tif (precedence < 0){\n\t\t\t\texpr = parseUnary();\n\t\t\t} else {\n\t\t\t\texpr = parseExpression(precedence-1);\n\t\t\t}\n\t\t\tvar token = lexer.peek();\n\t\t\twhile (matchGroup(token, \"binary\", precedence)) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [\n\t\t\t\t\t\texpr,\n\t\t\t\t\t\tparseExpression(precedence-1)\n\t\t\t\t\t]\n\t\t\t\t};\n\t\t\t\ttoken = lexer.peek();\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\n\t\tfunction parseUnary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (matchGroup(token, \"unary\")) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = parseUnary();\n\t\t\t\treturn {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [expr]\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn parsePrimary();\n\t\t}\n\n\t\tfunction parsePrimary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (isUndef(token)) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected termination of expression\");\n\t\t\t}\n\t\t\tif (token.type === \"func\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn parseFunctionCall(token);\n\t\t\t}\n\t\t\tif (token.type === \"value\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn {\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : token.value\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (matchSyntax(token, \"(\")) {\n\t\t\t\tlexer.next();\n\t\t\t\texpr = parseExpression();\n\t\t\t\ttoken = lexer.next();\n\t\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t\t}\n\t\t\t\treturn expr;\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Parse error, cannot process token \" + token.value);\n\t\t}\n\n\t\tfunction parseFunctionCall(func) {\n\t\t\tvar token, args = [];\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \"(\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ( in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\ttoken = lexer.peek();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\targs = parseArgumentList();\n\t\t\t}\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ) in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod : func.method,\n\t\t\t\targs : args,\n\t\t\t\tname : name\n\t\t\t};\n\t\t}\n\n\t\tfunction parseArgumentList() {\n\t\t\tvar token, expr, args = [];\n\t\t\twhile (true) {\n\t\t\t\texpr = parseExpression();\n\t\t\t\tif (isUndef(expr)) {\n\t\t\t\t\t// TODO maybe throw exception?\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\targs.push(expr);\n\t\t\t\ttoken = lexer.peek();\n\t\t\t\tif (!matchSyntax(token, \",\")) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlexer.next();\n\t\t\t}\n\t\t\treturn args;\n\t\t}\n\n\t\treturn parseExpression();\n\t};\n\n\t/**\n\t * recursively evaluate the expression tree\n\t * @param {Object} tree \n\t * @return {AudioNode} the resulting audio node from the expression\n\t * @private\n\t */\n\tTone.Expr.prototype._eval = function(tree){\n\t\tif (!this.isUndef(tree)){\n\t\t\tvar node = tree.method(tree.args, this);\n\t\t\tthis._nodes.push(node);\n\t\t\treturn node;\n\t\t} \n\t};\n\n\t/**\n\t * dispose all the nodes\n\t * @private\n\t */\n\tTone.Expr.prototype._disposeNodes = function(){\n\t\tfor (var i = 0; i < this._nodes.length; i++){\n\t\t\tvar node = this._nodes[i];\n\t\t\tif (this.isFunction(node.dispose)) {\n\t\t\t\tnode.dispose();\n\t\t\t} else if (this.isFunction(node.disconnect)) {\n\t\t\t\tnode.disconnect();\n\t\t\t}\n\t\t\tnode = null;\n\t\t\tthis._nodes[i] = null;\n\t\t}\n\t\tthis._nodes = null;\n\t};\n\n\t/**\n\t * clean up\n\t */\n\tTone.Expr.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._disposeNodes();\n\t};\n\n\treturn Tone.Expr;\n});","define([\"Tone/core/Tone\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Subtract\", \"Tone/signal/Signal\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Output 1 if the signal is greater than the value, otherwise outputs 0.\n\t * can compare two signals or a signal and a number. \n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number} [value=0] the value to compare to the incoming signal\n\t * @example\n\t * var gt = new Tone.GreaterThan(2);\n\t * var sig = new Tone.Signal(4).connect(gt);\n\t * //output of gt is equal 1. \n\t */\n\tTone.GreaterThan = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\t\t\n\t\t/**\n\t\t * subtract the amount from the incoming signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[0] = new Tone.Subtract(value);\n\t\tthis.input[1] = this._param.input[1];\n\n\t\t/**\n\t\t * compare that amount to zero\n\t\t * @type {Tone.GreaterThanZero}\n\t\t * @private\n\t\t */\n\t\tthis._gtz = this.output = new Tone.GreaterThanZero();\n\n\t\t//connect\n\t\tthis._param.connect(this._gtz);\n\t};\n\n\tTone.extend(Tone.GreaterThan, Tone.Signal);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThan} this\n\t */\n\tTone.GreaterThan.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\tthis._gtz.dispose();\n\t\tthis._gtz = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThan;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/SignalBase\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Return the absolute value of an incoming signal. \n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var signal = new Tone.Signal(-1);\n\t * var abs = new Tone.Abs();\n\t * signal.connect(abs);\n\t * //the output of abs is 1. \n\t */\n\tTone.Abs = function(){\n\t\t/**\n\t\t * @type {Tone.LessThan}\n\t\t * @private\n\t\t */\n\t\tthis._abs = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val === 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn Math.abs(val);\n\t\t\t}\n\t\t}, 127);\n\t};\n\n\tTone.extend(Tone.Abs, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.Abs} this\n\t */\n\tTone.Abs.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._abs.dispose();\n\t\tthis._abs = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Abs;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Multiply\", \"Tone/signal/Subtract\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Signal-rate modulo operator. Only works in AudioRange [-1, 1] and for modulus\n\t * values in the NormalRange. \n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {NormalRange} modulus The modulus to apply.\n\t * @example\n\t * var mod = new Tone.Modulo(0.2)\n\t * var sig = new Tone.Signal(0.5).connect(mod);\n\t * //mod outputs 0.1\n\t */\n\tTone.Modulo = function(modulus){\n\n\t\tthis.createInsOuts(1, 0);\n\n\t\t/**\n\t\t * A waveshaper gets the integer multiple of \n\t\t * the input signal and the modulus.\n\t\t * @private\n\t\t * @type {Tone.WaveShaper}\n\t\t */\n\t\tthis._shaper = new Tone.WaveShaper(Math.pow(2, 16));\n\n\t\t/**\n\t\t * the integer multiple is multiplied by the modulus\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = new Tone.Multiply();\n\n\t\t/**\n\t\t * and subtracted from the input signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._subtract = this.output = new Tone.Subtract();\n\n\t\t/**\n\t\t * the modulus signal\n\t\t * @type {Tone.Signal}\n\t\t * @private\n\t\t */\n\t\tthis._modSignal = new Tone.Signal(modulus);\n\n\t\t//connections\n\t\tthis.input.fan(this._shaper, this._subtract);\n\t\tthis._modSignal.connect(this._multiply, 0, 0);\n\t\tthis._shaper.connect(this._multiply, 0, 1);\n\t\tthis._multiply.connect(this._subtract, 0, 1);\n\t\tthis._setWaveShaper(modulus);\n\t};\n\n\tTone.extend(Tone.Modulo, Tone.SignalBase);\n\n\t/**\n\t * @param {number} mod the modulus to apply\n\t * @private\n\t */\n\tTone.Modulo.prototype._setWaveShaper = function(mod){\n\t\tthis._shaper.setMap(function(val){\n\t\t\tvar multiple = Math.floor((val + 0.0001) / mod);\n\t\t\treturn multiple;\n\t\t});\n\t};\n\n\t/**\n\t * The modulus value.\n\t * @memberOf Tone.Modulo#\n\t * @type {NormalRange}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Modulo.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._modSignal.value;\n\t\t},\n\t\tset : function(mod){\n\t\t\tthis._modSignal.value = mod;\n\t\t\tthis._setWaveShaper(mod);\n\t\t}\n\t});\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Modulo} this\n\t */\n\tTone.Modulo.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.dispose();\n\t\tthis._shaper = null;\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\tthis._subtract.dispose();\n\t\tthis._subtract = null;\n\t\tthis._modSignal.dispose();\n\t\tthis._modSignal = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Modulo;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Pow applies an exponent to the incoming signal. The incoming signal\n\t * must be AudioRange.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {Positive} exp The exponent to apply to the incoming signal, must be at least 2. \n\t * @example\n\t * var pow = new Tone.Pow(2);\n\t * var sig = new Tone.Signal(0.5).connect(pow);\n\t * //output of pow is 0.25. \n\t */\n\tTone.Pow = function(exp){\n\n\t\t/**\n\t\t * the exponent\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._exp = this.defaultArg(exp, 1);\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);\n\t};\n\n\tTone.extend(Tone.Pow, Tone.SignalBase);\n\n\t/**\n\t * The value of the exponent.\n\t * @memberOf Tone.Pow#\n\t * @type {number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Pow.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._exp;\n\t\t},\n\t\tset : function(exp){\n\t\t\tthis._exp = exp;\n\t\t\tthis._expScaler.setMap(this._expFunc(this._exp));\n\t\t}\n\t});\n\n\n\t/**\n\t * the function which maps the waveshaper\n\t * @param {number} exp\n\t * @return {function}\n\t * @private\n\t */\n\tTone.Pow.prototype._expFunc = function(exp){\n\t\treturn function(val){\n\t\t\treturn Math.pow(Math.abs(val), exp);\n\t\t};\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Pow} this\n\t */\n\tTone.Pow.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._expScaler.dispose();\n\t\tthis._expScaler = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Pow;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class AudioToGain converts an input in AudioRange [-1,1] to NormalRange [0,1]. \n\t * See Tone.GainToAudio.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var a2g = new Tone.AudioToGain();\n\t */\n\tTone.AudioToGain = function(){\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._norm = this.input = this.output = new Tone.WaveShaper(function(x){\n\t\t\treturn (x + 1) / 2;\n\t\t});\n\t};\n\n\tTone.extend(Tone.AudioToGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.AudioToGain} this\n\t */\n\tTone.AudioToGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._norm.dispose();\n\t\tthis._norm = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.AudioToGain;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Convert an incoming signal between 0, 1 to an equal power gain scale.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var eqPowGain = new Tone.EqualPowerGain();\n\t */\n\tTone.EqualPowerGain = function(){\n\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._eqPower = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (Math.abs(val) < 0.001){\n\t\t\t\t//should output 0 when input is 0\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn this.equalPowerScale(val);\n\t\t\t}\n\t\t}.bind(this), 4096);\n\t};\n\n\tTone.extend(Tone.EqualPowerGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.EqualPowerGain} this\n\t */\n\tTone.EqualPowerGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._eqPower.dispose();\n\t\tthis._eqPower = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.EqualPowerGain;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n var EQFilter = require('eqFilter');\r\n\r\n /**\r\n * p5.EQ is an audio effect that performs the function of a multiband\r\n * audio equalizer. Equalization is used to adjust the balance of\r\n * frequency compoenents of an audio signal. This process is commonly used\r\n * in sound production and recording to change the waveform before it reaches\r\n * a sound output device. EQ can also be used as an audio effect to create\r\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\r\n * built using a chain of Web Audio Biquad Filter Nodes and can be\r\n * instantiated with 3 or 8 bands. Bands can be added or removed from\r\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.EQ\r\n * @constructor\r\n * @extends p5.Effect\r\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\r\n * @return {Object} p5.EQ object\r\n *\r\n * @example\r\n *
\r\n * var eq;\r\n * var band_names;\r\n * var band_index;\r\n *\r\n * var soundFile, play;\r\n *\r\n * function preload() {\r\n * soundFormats('mp3', 'ogg');\r\n * soundFile = loadSound('assets/beat');\r\n * }\r\n *\r\n * function setup() {\r\n * eq = new p5.EQ(3);\r\n * soundFile.disconnect();\r\n * eq.process(soundFile);\r\n *\r\n * band_names = ['lows','mids','highs'];\r\n * band_index = 0;\r\n * play = false;\r\n * textAlign(CENTER);\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n * noStroke();\r\n * fill(255);\r\n * text('click to kill',50,25);\r\n *\r\n * fill(255, 40, 255);\r\n * textSize(26);\r\n * text(band_names[band_index],50,55);\r\n *\r\n * fill(255);\r\n * textSize(9);\r\n * text('space = play/pause',50,80);\r\n * }\r\n *\r\n * //If mouse is over canvas, cycle to the next band and kill the frequency\r\n * function mouseClicked() {\r\n * for (var i = 0; i < eq.bands.length; i++) {\r\n * eq.bands[i].gain(0);\r\n * }\r\n * eq.bands[band_index].gain(-40);\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * band_index === 2 ? band_index = 0 : band_index++;\r\n * }\r\n * }\r\n *\r\n * //use space bar to trigger play / pause\r\n * function keyPressed() {\r\n * if (key===' ') {\r\n * play = !play\r\n * play ? soundFile.loop() : soundFile.pause();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.EQ = function(_eqsize) {\r\n Effect.call(this);\r\n\r\n //p5.EQ can be of size (3) or (8), defaults to 3\r\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\r\n\r\n var factor;\r\n _eqsize === 3 ? factor = Math.pow(2,3) : factor = 2;\r\n\r\n /**\r\n * The p5.EQ is built with abstracted p5.Filter objects.\r\n * To modify any bands, use methods of the \r\n * p5.Filter API, especially `gain` and `freq`.\r\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\r\n * @property {Array} bands\r\n *\r\n */\r\n this.bands = [];\r\n\r\n\r\n var freq, res;\r\n for (var i = 0; i < _eqsize; i++) {\r\n if (i === _eqsize - 1) {\r\n freq = 21000;\r\n res = .01;\r\n } else if (i === 0) {\r\n freq = 100;\r\n res = .1;\r\n }\r\n else if (i===1) {\r\n freq = _eqsize === 3 ? 360 * factor : 360;\r\n res = 1;\r\n }else {\r\n freq = this.bands[i-1].freq() * factor;\r\n res = 1;\r\n }\r\n this.bands[i] = this._newBand(freq, res);\r\n\r\n if (i>0) {\r\n this.bands[i-1].connect(this.bands[i].biquad);\r\n } else {\r\n this.input.connect(this.bands[i].biquad);\r\n }\r\n }\r\n this.bands[_eqsize-1].connect(this.output);\r\n };\r\n p5.EQ.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Process an input by connecting it to the EQ\r\n * @method process\r\n * @param {Object} src Audio source\r\n */\r\n p5.EQ.prototype.process = function (src) {\r\n src.connect(this.input);\r\n };\r\n\r\n // /**\r\n // * Set the frequency and gain of each band in the EQ. This method should be\r\n // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\r\n // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\r\n // *\r\n // * @method set\r\n // * @for p5.EQ\r\n // * @param {Number} [freq0] Frequency value for band with index 0\r\n // * @param {Number} [gain0] Gain value for band with index 0\r\n // * @param {Number} [freq1] Frequency value for band with index 1\r\n // * @param {Number} [gain1] Gain value for band with index 1\r\n // * @param {Number} [freq2] Frequency value for band with index 2\r\n // * @param {Number} [gain2] Gain value for band with index 2\r\n // * @param {Number} [freq3] Frequency value for band with index 3\r\n // * @param {Number} [gain3] Gain value for band with index 3\r\n // * @param {Number} [freq4] Frequency value for band with index 4\r\n // * @param {Number} [gain4] Gain value for band with index 4\r\n // * @param {Number} [freq5] Frequency value for band with index 5\r\n // * @param {Number} [gain5] Gain value for band with index 5\r\n // * @param {Number} [freq6] Frequency value for band with index 6\r\n // * @param {Number} [gain6] Gain value for band with index 6\r\n // * @param {Number} [freq7] Frequency value for band with index 7\r\n // * @param {Number} [gain7] Gain value for band with index 7\r\n // */\r\n p5.EQ.prototype.set = function() {\r\n if (arguments.length === this.bands.length * 2) {\r\n for (var i = 0; i < arguments.length; i+=2) {\r\n this.bands[i/2].freq(arguments[i]);\r\n this.bands[i/2].gain(arguments[i+1]);\r\n }\r\n }\r\n else {\r\n console.error('Argument mismatch. .set() should be called with ' + this.bands.length*2 +\r\n ' arguments. (one frequency and gain value pair for each band of the eq)');\r\n }\r\n };\r\n\r\n /**\r\n * Add a new band. Creates a p5.Filter and strips away everything but\r\n * the raw biquad filter. This method returns an abstracted p5.Filter,\r\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\r\n * @private\r\n * @for p5.EQ\r\n * @method _newBand\r\n * @param {Number} freq\r\n * @param {Number} res\r\n * @return {Object} Abstracted Filter\r\n */\r\n p5.EQ.prototype._newBand = function(freq, res) {\r\n return new EQFilter(freq, res);\r\n };\r\n\r\n p5.EQ.prototype.dispose = function () {\r\n Effect.prototype.dispose.apply(this);\r\n\r\n if (this.bands) {\r\n while (this.bands.length > 0) {\r\n delete this.bands.pop().dispose();\r\n }\r\n delete this.bands;\r\n }\r\n };\r\n\r\n return p5.EQ;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var p5sound = require('master');\r\n\r\n /**\r\n * EQFilter extends p5.Filter with constraints\r\n * necessary for the p5.EQ\r\n *\r\n * @private\r\n */\r\n var EQFilter = function(freq, res) {\r\n Filter.call(this, 'peaking');\r\n this.disconnect();\r\n this.set(freq, res);\r\n this.biquad.gain.value = 0;\r\n delete this.input;\r\n delete this.output;\r\n delete this._drywet;\r\n delete this.wet;\r\n\r\n };\r\n EQFilter.prototype = Object.create(Filter.prototype);\r\n\r\n EQFilter.prototype.amp = function() {\r\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\r\n };\r\n EQFilter.prototype.drywet = function() {\r\n console.warn('`drywet()` is not available for p5.EQ bands.');\r\n };\r\n EQFilter.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n if (this.biquad) {\r\n this.biquad.connect(u.input ? u.input : u);\r\n } else {\r\n this.output.connect(u.input ? u.input : u);\r\n }\r\n };\r\n\r\n EQFilter.prototype.disconnect = function() {\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n }\r\n };\r\n EQFilter.prototype.dispose = function() {\r\n // remove reference form soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n this.disconnect();\r\n delete this.biquad;\r\n };\r\n\r\n return EQFilter;\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Panner3D is based on the \r\n * Web Audio Spatial Panner Node.\r\n * This panner is a spatial processing node that allows audio to be positioned\r\n * and oriented in 3D space.\r\n *\r\n * The position is relative to an \r\n * Audio Context Listener, which can be accessed\r\n * by p5.soundOut.audiocontext.listener\r\n *\r\n *\r\n * @class p5.Panner3D\r\n * @constructor\r\n */\r\n\tp5.Panner3D = function() {\r\n Effect.call(this);\r\n\r\n /**\r\n * \r\n * Web Audio Spatial Panner Node\r\n *\r\n * Properties include\r\n * - panningModel: \"equal power\" or \"HRTF\"\r\n * - distanceModel: \"linear\", \"inverse\", or \"exponential\"\r\n *\r\n * @property {AudioNode} panner\r\n *\r\n */\r\n this.panner = this.ac.createPanner();\r\n this.panner.panningModel = 'HRTF';\r\n this.panner.distanceModel = 'linear';\r\n this.panner.connect(this.output);\r\n this.input.connect(this.panner);\r\n\t};\r\n\r\n p5.Panner3D.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Connect an audio sorce\r\n *\r\n * @method process\r\n * @for p5.Panner3D\r\n * @param {Object} src Input source\r\n */\r\n p5.Panner3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method set\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.set = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.panner.positionX.value,\r\n this.panner.positionY.value,\r\n this.panner.positionZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.positionX.value = xVal;\r\n this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.positionX);\r\n }\r\n return this.panner.positionX.value;\r\n };\r\n p5.Panner3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.positionY.value = yVal;\r\n this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.positionY);\r\n }\r\n return this.panner.positionY.value;\r\n };\r\n p5.Panner3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.positionZ.value = zVal;\r\n this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.positionZ);\r\n }\r\n return this.panner.positionZ.value;\r\n };\r\n\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method orient\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.orient = function(xVal, yVal, zVal, time) {\r\n this.orientX(xVal,time);\r\n this.orientY(yVal,time);\r\n this.orientZ(zVal,time);\r\n return [this.panner.orientationX.value,\r\n this.panner.orientationY.value,\r\n this.panner.orientationZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.orientX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.orientationX.value = xVal;\r\n this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.orientationX);\r\n }\r\n return this.panner.orientationX.value;\r\n };\r\n p5.Panner3D.prototype.orientY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.orientationY.value = yVal;\r\n this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.orientationY);\r\n }\r\n return this.panner.orientationY.value;\r\n };\r\n p5.Panner3D.prototype.orientZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.orientationZ.value = zVal;\r\n this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.orientationZ);\r\n }\r\n return this.panner.orientationZ.value;\r\n };\r\n\r\n /**\r\n * Set the rolloff factor and max distance\r\n * @method setFalloff\r\n * @for p5.Panner3D\r\n * @param {Number} [maxDistance]\r\n * @param {Number} [rolloffFactor]\r\n */\r\n p5.Panner3D.prototype.setFalloff = function(maxDistance, rolloffFactor) {\r\n this.maxDist(maxDistance);\r\n this.rolloff(rolloffFactor);\r\n };\r\n /**\r\n * Maxium distance between the source and the listener\r\n * @method maxDist\r\n * @for p5.Panner3D\r\n * @param {Number} maxDistance\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.maxDist = function(maxDistance){\r\n if (typeof maxDistance === 'number') {\r\n this.panner.maxDistance = maxDistance;\r\n }\r\n return this.panner.maxDistance;\r\n };\r\n\r\n /**\r\n * How quickly the volume is reduced as the source moves away from the listener\r\n * @method rollof\r\n * @for p5.Panner3D\r\n * @param {Number} rolloffFactor\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.rolloff = function(rolloffFactor){\r\n if (typeof rolloffFactor === 'number') {\r\n this.panner.rolloffFactor = rolloffFactor;\r\n }\r\n return this.panner.rolloffFactor;\r\n };\r\n\r\n p5.Panner3D.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n delete this.panner;\r\n }\r\n };\r\n\r\n return p5.Panner3D;\r\n\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n// /**\r\n// * listener is a class that can construct both a Spatial Panner\r\n// * and a Spatial Listener. The panner is based on the \r\n// * Web Audio Spatial Panner Node\r\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\r\n// * This panner is a spatial processing node that allows audio to be positioned\r\n// * and oriented in 3D space. \r\n// *\r\n// * The Listener modifies the properties of the Audio Context Listener. \r\n// * Both objects types use the same methods. The default is a spatial panner.\r\n// *\r\n// * p5.Panner3D - Constructs a Spatial Panner \r\n// * p5.Listener3D - Constructs a Spatial Listener \r\n// *\r\n// * @class listener\r\n// * @constructor\r\n// * @return {Object} p5.Listener3D Object\r\n// *\r\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\r\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\r\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\r\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\r\n// */\r\n \r\n\tp5.Listener3D = function(type) {\r\n this.ac = p5sound.audiocontext;\r\n this.listener = this.ac.listener;\r\n\t}; \r\n\r\n// /**\r\n// * Connect an audio sorce\r\n// * @param {Object} src Input source\r\n// */\r\n p5.Listener3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n// /**\r\n// * Set the X,Y,Z position of the Panner\r\n// * @param {[Number]} xVal\r\n// * @param {[Number]} yVal\r\n// * @param {[Number]} zVal\r\n// * @param {[Number]} time\r\n// * @return {[Array]} [Updated x, y, z values as an array]\r\n// */\r\n p5.Listener3D.prototype.position = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.listener.positionX.value, \r\n this.listener.positionY.value,\r\n this.listener.positionZ.value];\r\n };\r\n\r\n// /**\r\n// * Getter and setter methods for position coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.positionX.value = xVal;\r\n this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.positionX);\r\n }\r\n return this.listener.positionX.value;\r\n };\r\n p5.Listener3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.positionY.value = yVal;\r\n this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.positionY);\r\n }\r\n return this.listener.positionY.value;\r\n };\r\n p5.Listener3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.positionZ.value = zVal;\r\n this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.positionZ);\r\n }\r\n return this.listener.positionZ.value;\r\n };\r\n\r\n// cannot define method when class definition is commented\r\n// /**\r\n// * Overrides the listener orient() method because Listener has slightly\r\n// * different params. In human terms, Forward vectors are the direction the \r\n// * nose is pointing. Up vectors are the direction of the top of the head.\r\n// *\r\n// * @method orient\r\n// * @param {Number} xValF Forward vector X direction\r\n// * @param {Number} yValF Forward vector Y direction\r\n// * @param {Number} zValF Forward vector Z direction\r\n// * @param {Number} xValU Up vector X direction\r\n// * @param {Number} yValU Up vector Y direction\r\n// * @param {Number} zValU Up vector Z direction\r\n// * @param {Number} time \r\n// * @return {Array} All orienation params\r\n// */\r\n p5.Listener3D.prototype.orient = function(xValF, yValF, zValF, \r\n xValU, yValU, zValU, time) {\r\n\r\n if (arguments.length === 3 || arguments.length === 4) {\r\n time = arguments[3];\r\n this.orientForward(xValF, yValF, zValF, time);\r\n } else if (arguments.length === 6 || arguments === 7) {\r\n this.orientForward(xValF, yValF, zValF);\r\n this.orientUp(xValU, yValU, zValU, time);\r\n }\r\n \r\n return [this.listener.forwardX.value, \r\n this.listener.forwardY.value,\r\n this.listener.forwardZ.value,\r\n this.listener.upX.value,\r\n this.listener.upY.value,\r\n this.listener.upZ.value];\r\n };\r\n\r\n\r\n p5.Listener3D.prototype.orientForward = function(xValF, yValF, zValF, time) {\r\n this.forwardX(xValF,time);\r\n this.forwardY(yValF,time);\r\n this.forwardZ(zValF,time);\r\n\r\n return [this.listener.forwardX, \r\n this.listener.forwardY,\r\n this.listener.forwardZ];\r\n };\r\n\r\n p5.Listener3D.prototype.orientUp = function(xValU, yValU, zValU, time) {\r\n this.upX(xValU,time);\r\n this.upY(yValU,time);\r\n this.upZ(zValU,time);\r\n\r\n return [this.listener.upX, \r\n this.listener.upY,\r\n this.listener.upZ];\r\n };\r\n// /**\r\n// * Getter and setter methods for orient coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.forwardX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.forwardX.value = xVal;\r\n this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.forwardX);\r\n }\r\n return this.listener.forwardX.value;\r\n };\r\n p5.Listener3D.prototype.forwardY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.forwardY.value = yVal;\r\n this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.forwardY);\r\n }\r\n return this.listener.forwardY.value;\r\n };\r\n p5.Listener3D.prototype.forwardZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.forwardZ.value = zVal;\r\n this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.forwardZ);\r\n }\r\n return this.listener.forwardZ.value;\r\n };\r\n p5.Listener3D.prototype.upX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.upX.value = xVal;\r\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.upX);\r\n }\r\n return this.listener.upX.value;\r\n };\r\n p5.Listener3D.prototype.upY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.upY.value = yVal;\r\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.upY);\r\n }\r\n return this.listener.upY.value;\r\n };\r\n p5.Listener3D.prototype.upZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.upZ.value = zVal;\r\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.upZ);\r\n }\r\n return this.listener.upZ.value;\r\n };\r\n \r\n return p5.Listener3D;\r\n\r\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Delay is an echo effect. It processes an existing sound source,\r\n * and outputs a delayed version of that sound. The p5.Delay can\r\n * produce different effects depending on the delayTime, feedback,\r\n * filter, and type. In the example below, a feedback of 0.5 (the\r\n * defaul value) will produce a looping delay that decreases in\r\n * volume by 50% each repeat. A filter will cut out the high\r\n * frequencies so that the delay does not sound as piercing as the\r\n * original source.\r\n *\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n * @class p5.Delay\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var noise, env, delay;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * noise = new p5.Noise('brown');\r\n * noise.amp(0);\r\n * noise.start();\r\n *\r\n * delay = new p5.Delay();\r\n *\r\n * // delay.process() accepts 4 parameters:\r\n * // source, delayTime, feedback, filter frequency\r\n * // play with these numbers!!\r\n * delay.process(noise, .12, .7, 2300);\r\n *\r\n * // play the noise with an envelope,\r\n * // a series of fades ( time / value pairs )\r\n * env = new p5.Envelope(.01, 0.2, .2, .1);\r\n * }\r\n *\r\n * // mouseClick triggers envelope\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(noise);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Delay = function() {\r\n \tEffect.call(this);\r\n\r\n this._split = this.ac.createChannelSplitter(2);\r\n this._merge = this.ac.createChannelMerger(2);\r\n\r\n this._leftGain = this.ac.createGain();\r\n this._rightGain = this.ac.createGain();\r\n\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} leftDelay\r\n */\r\n this.leftDelay = this.ac.createDelay();\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} rightDelay\r\n */\r\n this.rightDelay = this.ac.createDelay();\r\n\r\n this._leftFilter = new Filter();\r\n this._rightFilter = new Filter();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n\r\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n\r\n // graph routing\r\n this.input.connect(this._split);\r\n this.leftDelay.connect(this._leftGain);\r\n this.rightDelay.connect(this._rightGain);\r\n this._leftGain.connect(this._leftFilter.input);\r\n this._rightGain.connect(this._rightFilter.input);\r\n this._merge.connect(this.wet);\r\n\r\n\r\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n\r\n // default routing\r\n this.setType(0);\r\n\r\n this._maxDelay = this.leftDelay.delayTime.maxValue;\r\n\r\n // set initial feedback to 0.5\r\n this.feedback(0.5);\r\n\r\n\r\n };\r\n\r\n p5.Delay.prototype = Object.create(Effect.prototype);\r\n /**\r\n * Add delay to an audio signal according to a set\r\n * of delay parameters.\r\n *\r\n * @method process\r\n * @for p5.Delay\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\r\n * Some browsers limit delayTime to\r\n * 1 second.\r\n * @param {Number} [feedback] sends the delay back through itself\r\n * in a loop that decreases in volume\r\n * each time.\r\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\r\n * below the lowPass will be part of the\r\n * delay.\r\n */\r\n p5.Delay.prototype.process = function(src, _delayTime, _feedback, _filter) {\r\n var feedback = _feedback || 0;\r\n var delayTime = _delayTime || 0;\r\n if (feedback >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n if (delayTime >= this._maxDelay) {\r\n throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.');\r\n }\r\n\r\n src.connect(this.input);\r\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this._leftGain.gain.value = feedback;\r\n this._rightGain.gain.value = feedback;\r\n\r\n if (_filter) {\r\n this._leftFilter.freq(_filter);\r\n this._rightFilter.freq(_filter);\r\n }\r\n };\r\n\r\n /**\r\n * Set the delay (echo) time, in seconds. Usually this value will be\r\n * a floating point number between 0.0 and 1.0.\r\n *\r\n * @method delayTime\r\n * @for p5.Delay\r\n * @param {Number} delayTime Time (in seconds) of the delay\r\n */\r\n p5.Delay.prototype.delayTime = function(t) {\r\n // if t is an audio node...\r\n if (typeof t !== 'number') {\r\n t.connect(this.leftDelay.delayTime);\r\n t.connect(this.rightDelay.delayTime);\r\n }\r\n\r\n else {\r\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Feedback occurs when Delay sends its signal back through its input\r\n * in a loop. The feedback amount determines how much signal to send each\r\n * time through the loop. A feedback greater than 1.0 is not desirable because\r\n * it will increase the overall output each time through the loop,\r\n * creating an infinite feedback loop. The default value is 0.5\r\n *\r\n * @method feedback\r\n * @for p5.Delay\r\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\r\n * Oscillator that can be used to\r\n * modulate this param\r\n * @returns {Number} Feedback value\r\n *\r\n */\r\n p5.Delay.prototype.feedback = function(f) {\r\n // if f is an audio node...\r\n if (f && typeof f !== 'number') {\r\n f.connect(this._leftGain.gain);\r\n f.connect(this._rightGain.gain);\r\n }\r\n else if (f >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n else if (typeof f === 'number') {\r\n this._leftGain.gain.value = f;\r\n this._rightGain.gain.value = f;\r\n }\r\n\r\n // return value of feedback\r\n return this._leftGain.gain.value;\r\n };\r\n\r\n /**\r\n * Set a lowpass filter frequency for the delay. A lowpass filter\r\n * will cut off any frequencies higher than the filter frequency.\r\n *\r\n * @method filter\r\n * @for p5.Delay\r\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\r\n * frequencies higher than the filter frequency.\r\n * @param {Number|Object} res Resonance of the filter frequency\r\n * cutoff, or an object (i.e. a p5.Oscillator)\r\n * that can be used to modulate this parameter.\r\n * High numbers (i.e. 15) will produce a resonance,\r\n * low numbers (i.e. .2) will produce a slope.\r\n */\r\n p5.Delay.prototype.filter = function(freq, q) {\r\n this._leftFilter.set(freq, q);\r\n this._rightFilter.set(freq, q);\r\n };\r\n\r\n\r\n /**\r\n * Choose a preset type of delay. 'pingPong' bounces the signal\r\n * from the left to the right channel to produce a stereo effect.\r\n * Any other parameter will revert to the default delay setting.\r\n *\r\n * @method setType\r\n * @for p5.Delay\r\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\r\n */\r\n p5.Delay.prototype.setType = function(t) {\r\n if (t === 1) {\r\n t = 'pingPong';\r\n }\r\n this._split.disconnect();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n this._split.connect(this.leftDelay, 0);\r\n this._split.connect(this.rightDelay, 1);\r\n switch(t) {\r\n case 'pingPong':\r\n this._rightFilter.setType( this._leftFilter.biquad.type );\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.rightDelay);\r\n this._rightFilter.output.connect(this.leftDelay);\r\n break;\r\n default:\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.leftDelay);\r\n this._rightFilter.output.connect(this.rightDelay);\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the delay effect.\r\n *\r\n * @method amp\r\n * @for p5.Delay\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Delay\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Delay\r\n */\r\n\r\n p5.Delay.prototype.dispose = function() {\r\n\r\n Effect.prototype.dispose.apply(this);\r\n\r\n this._split.disconnect();\r\n this._leftFilter.dispose();\r\n this._rightFilter.dispose();\r\n this._merge.disconnect();\r\n this._leftGain.disconnect();\r\n this._rightGain.disconnect();\r\n this.leftDelay.disconnect();\r\n this.rightDelay.disconnect();\r\n\r\n this._split = undefined;\r\n this._leftFilter = undefined;\r\n this._rightFilter = undefined;\r\n this._merge = undefined;\r\n this._leftGain = undefined;\r\n this._rightGain = undefined;\r\n this.leftDelay = undefined;\r\n this.rightDelay = undefined;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var CustomError = require('errorHandler');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Reverb adds depth to a sound through a large number of decaying\r\n * echoes. It creates the perception that sound is occurring in a\r\n * physical space. The p5.Reverb has paramters for Time (how long does the\r\n * reverb last) and decayRate (how much the sound decays with each echo)\r\n * that can be set with the .set() or .process() methods. The p5.Convolver\r\n * extends p5.Reverb allowing you to recreate the sound of actual physical\r\n * spaces through convolution.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Reverb\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var soundFile, reverb;\r\n * function preload() {\r\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * reverb = new p5.Reverb();\r\n * soundFile.disconnect(); // so we'll only hear reverb...\r\n *\r\n * // connect soundFile to reverb, process w/\r\n * // 3 second reverbTime, decayRate of 2%\r\n * reverb.process(soundFile, 3, 2);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n\r\n\r\n p5.Reverb = function() {\r\n Effect.call(this);\r\n\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n // default params\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n\r\n };\r\n\r\n p5.Reverb.prototype = Object.create(Effect.prototype);\r\n\r\n p5.Reverb.prototype._initConvolverNode = function() {\r\n this.convolverNode = this.ac.createConvolver();\r\n this.input.connect(this.convolverNode);\r\n this.convolverNode.connect(this.wet);\r\n };\r\n\r\n p5.Reverb.prototype._teardownConvolverNode = function() {\r\n if (this.convolverNode) {\r\n this.convolverNode.disconnect();\r\n delete this.convolverNode;\r\n }\r\n };\r\n\r\n p5.Reverb.prototype._setBuffer = function(audioBuffer) {\r\n this._teardownConvolverNode();\r\n this._initConvolverNode();\r\n this.convolverNode.buffer = audioBuffer;\r\n };\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Reverb\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.process = function(src, seconds, decayRate, reverse) {\r\n src.connect(this.input);\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n /**\r\n * Set the reverb settings. Similar to .process(), but without\r\n * assigning a new input.\r\n *\r\n * @method set\r\n * @for p5.Reverb\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.set = function(seconds, decayRate, reverse) {\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the reverb effect.\r\n *\r\n * @method amp\r\n * @for p5.Reverb\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Reverb\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Reverb\r\n */\r\n\r\n /**\r\n * Inspired by Simple Reverb by Jordan Santell\r\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\r\n *\r\n * Utility function for building an impulse response\r\n * based on the module parameters.\r\n *\r\n * @private\r\n */\r\n p5.Reverb.prototype._buildImpulse = function() {\r\n var rate = this.ac.sampleRate;\r\n var length = rate*this._seconds;\r\n var decay = this._decay;\r\n var impulse = this.ac.createBuffer(2, length, rate);\r\n var impulseL = impulse.getChannelData(0);\r\n var impulseR = impulse.getChannelData(1);\r\n var n, i;\r\n for (i = 0; i < length; i++) {\r\n n = this._reverse ? length - i : i;\r\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n }\r\n this._setBuffer(impulse);\r\n };\r\n\r\n p5.Reverb.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n this._teardownConvolverNode();\r\n };\r\n\r\n // =======================================================================\r\n // *** p5.Convolver ***\r\n // =======================================================================\r\n\r\n /**\r\n *
p5.Convolver extends p5.Reverb. It can emulate the sound of real\r\n * physical spaces through a process called \r\n * convolution.
\r\n *\r\n *
Convolution multiplies any audio input by an \"impulse response\"\r\n * to simulate the dispersion of sound over time. The impulse response is\r\n * generated from an audio file that you provide. One way to\r\n * generate an impulse response is to pop a balloon in a reverberant space\r\n * and record the echo. Convolution can also be used to experiment with\r\n * sound.
\r\n *\r\n *
Use the method createConvolution(path) to instantiate a\r\n * p5.Convolver with a path to your impulse response audio file.
\r\n *\r\n * @class p5.Convolver\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call when loading succeeds\r\n * @param {Function} [errorCallback] function to call if loading fails.\r\n * This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver = function(path, callback, errorCallback) {\r\n \t p5.Reverb.call(this);\r\n\r\n /**\r\n * Internally, the p5.Convolver uses the a\r\n * \r\n * Web Audio Convolver Node.\r\n *\r\n * @property {ConvolverNode} convolverNode\r\n */\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n if (path) {\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n }\r\n else {\r\n // parameters\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n }\r\n\r\n };\r\n\r\n p5.Convolver.prototype = Object.create(p5.Reverb.prototype);\r\n\r\n p5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\r\n\r\n /**\r\n * Create a p5.Convolver. Accepts a path to a soundfile\r\n * that will be used to generate an impulse response.\r\n *\r\n * @method createConvolver\r\n * @for p5\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call if loading is successful.\r\n * The object will be passed in as the argument\r\n * to the callback function.\r\n * @param {Function} [errorCallback] function to call if loading is not successful.\r\n * A custom error will be passed in as the argument\r\n * to the callback function.\r\n * @return {p5.Convolver}\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.createConvolver = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n var self = this;\r\n var cReverb = new p5.Convolver(path, function(buffer) {\r\n if (typeof callback === 'function') {\r\n callback(buffer);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, errorCallback);\r\n cReverb.impulses = [];\r\n return cReverb;\r\n };\r\n\r\n /**\r\n * Private method to load a buffer as an Impulse Response,\r\n * assign it to the convolverNode, and add to the Array of .impulses.\r\n *\r\n * @param {String} path\r\n * @param {Function} callback\r\n * @param {Function} errorCallback\r\n * @private\r\n */\r\n p5.Convolver.prototype._loadBuffer = function(path, callback, errorCallback) {\r\n var path = p5.prototype._checkFileFormats(path);\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n var ac = p5.prototype.getAudioContext();\r\n\r\n var request = new XMLHttpRequest();\r\n request.open('GET', path, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on success loading file:\r\n ac.decodeAudioData(request.response,\r\n function(buff) {\r\n var buffer = {};\r\n var chunks = path.split('/');\r\n buffer.name = chunks[chunks.length - 1];\r\n buffer.audioBuffer = buff;\r\n self.impulses.push(buffer);\r\n self._setBuffer(buffer.audioBuffer);\r\n if (callback) {\r\n callback(buffer);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url +\r\n '. The request status was: ' + request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n request.send();\r\n };\r\n\r\n p5.Convolver.prototype.set = null;\r\n\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Convolver\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * cVerb = createConvolver('assets/concrete-tunnel.mp3');\r\n *\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with (i.e. connect to) cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver.prototype.process = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * If you load multiple impulse files using the .addImpulse method,\r\n * they will be stored as Objects in this Array. Toggle between them\r\n * with the toggleImpulse(id) method.\r\n *\r\n * @property {Array} impulses\r\n * @for p5.Convolver\r\n */\r\n p5.Convolver.prototype.impulses = [];\r\n\r\n /**\r\n * Load and assign a new Impulse Response to the p5.Convolver.\r\n * The impulse is added to the .impulses array. Previous\r\n * impulses can be accessed with the .toggleImpulse(id)\r\n * method.\r\n *\r\n * @method addImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.addImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * Similar to .addImpulse, except that the .impulses\r\n * Array is reset to save memory. A new .impulses\r\n * array is created with this impulse as the only item.\r\n *\r\n * @method resetImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.resetImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * If you have used .addImpulse() to add multiple impulses\r\n * to a p5.Convolver, then you can use this method to toggle between\r\n * the items in the .impulses Array. Accepts a parameter\r\n * to identify which impulse you wish to use, identified either by its\r\n * original filename (String) or by its position in the .impulses\r\n * Array (Number). \r\n * You can access the objects in the .impulses Array directly. Each\r\n * Object has two attributes: an .audioBuffer (type:\r\n * Web Audio \r\n * AudioBuffer) and a .name, a String that corresponds\r\n * with the original filename.\r\n *\r\n * @method toggleImpulse\r\n * @for p5.Convolver\r\n * @param {String|Number} id Identify the impulse by its original filename\r\n * (String), or by its position in the\r\n * .impulses Array (Number).\r\n */\r\n p5.Convolver.prototype.toggleImpulse = function(id) {\r\n if (typeof id === 'number' && id < this.impulses.length) {\r\n this._setBuffer(this.impulses[id].audioBuffer);\r\n }\r\n if (typeof id === 'string') {\r\n for (var i = 0; i < this.impulses.length; i++) {\r\n if (this.impulses[i].name === id) {\r\n this._setBuffer(this.impulses[i].audioBuffer);\r\n break;\r\n }\r\n }\r\n }\r\n };\r\n\r\n p5.Convolver.prototype.dispose = function() {\r\n p5.Reverb.prototype.dispose.apply(this);\r\n\r\n // remove all the Impulse Response buffers\r\n for (var i in this.impulses) {\r\n if (this.impulses[i]) {\r\n this.impulses[i] = null;\r\n }\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n // requires the Tone.js library's Clock (MIT license, Yotam Mann)\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Clock = require('Tone/core/Clock');\r\n\r\n p5.Metro = function() {\r\n this.clock = new Clock({\r\n 'callback': this.ontick.bind(this)\r\n });\r\n this.syncedParts = [];\r\n this.bpm = 120; // gets overridden by p5.Part\r\n this._init();\r\n\r\n this.prevTick = 0;\r\n this.tatumTime = 0;\r\n\r\n this.tickCallback = function() {};\r\n };\r\n\r\n p5.Metro.prototype.ontick = function(tickTime) {\r\n var elapsedTime = tickTime - this.prevTick;\r\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\r\n if (elapsedTime - this.tatumTime <= -0.02) {\r\n return;\r\n } else {\r\n // console.log('ok', this.syncedParts[0].phrases[0].name);\r\n this.prevTick = tickTime;\r\n\r\n // for all of the active things on the metro:\r\n var self = this;\r\n this.syncedParts.forEach(function(thisPart) {\r\n if (!thisPart.isPlaying) return;\r\n thisPart.incrementStep(secondsFromNow);\r\n // each synced source keeps track of its own beat number\r\n thisPart.phrases.forEach(function(thisPhrase) {\r\n var phraseArray = thisPhrase.sequence;\r\n var bNum = self.metroTicks % phraseArray.length;\r\n if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping) ) {\r\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\r\n }\r\n });\r\n });\r\n this.metroTicks += 1;\r\n this.tickCallback(secondsFromNow);\r\n }\r\n };\r\n\r\n p5.Metro.prototype.setBPM = function(bpm, rampTime) {\r\n var beatTime = 60 / (bpm*this.tatums);\r\n var now = p5sound.audiocontext.currentTime;\r\n this.tatumTime = beatTime;\r\n\r\n var rampTime = rampTime || 0;\r\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\r\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\r\n this.bpm = bpm;\r\n };\r\n\r\n p5.Metro.prototype.getBPM = function() {\r\n return this.clock.getRate() / this.tatums * 60;\r\n };\r\n\r\n p5.Metro.prototype._init = function() {\r\n this.metroTicks = 0;\r\n // this.setBPM(120);\r\n };\r\n\r\n // clear existing synced parts, add only this one\r\n p5.Metro.prototype.resetSync = function(part) {\r\n this.syncedParts = [part];\r\n };\r\n\r\n // push a new synced part to the array\r\n p5.Metro.prototype.pushSync = function(part) {\r\n this.syncedParts.push(part);\r\n };\r\n\r\n p5.Metro.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.start(now + t);\r\n this.setBPM(this.bpm);\r\n };\r\n\r\n p5.Metro.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.stop(now + t);\r\n };\r\n\r\n p5.Metro.prototype.beatLength = function(tatums) {\r\n this.tatums = 1/tatums / 4; // lowest possible division of a beat\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Timeline\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline State. Provides the methods: setStateAtTime(\"state\", time)\n\t * and getValueAtTime(time).\n\t *\n\t * @extends {Tone.Timeline}\n\t * @param {String} initial The initial state of the TimelineState. \n\t * Defaults to undefined\n\t */\n\tTone.TimelineState = function(initial){\n\n\t\tTone.Timeline.call(this);\n\n\t\t/**\n\t\t * The initial state\n\t\t * @private\n\t\t * @type {String}\n\t\t */\n\t\tthis._initial = initial;\n\t};\n\n\tTone.extend(Tone.TimelineState, Tone.Timeline);\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {Number} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t */\n\tTone.TimelineState.prototype.getValueAtTime = function(time){\n\t\tvar event = this.get(time);\n\t\tif (event !== null){\n\t\t\treturn event.state;\n\t\t} else {\n\t\t\treturn this._initial;\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {String} state The name of the state to set.\n\t * @param {Number} time The time to query.\n\t */\n\tTone.TimelineState.prototype.setStateAtTime = function(state, time){\n\t\tthis.add({\n\t\t\t\"state\" : state,\n\t\t\t\"time\" : time\n\t\t});\n\t};\n\n\treturn Tone.TimelineState;\n});","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n var BPM = 120;\r\n\r\n /**\r\n * Set the global tempo, in beats per minute, for all\r\n * p5.Parts. This method will impact all active p5.Parts.\r\n *\r\n * @method setBPM\r\n * @for p5\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.prototype.setBPM = function(bpm, rampTime) {\r\n BPM = bpm;\r\n for (var i in p5sound.parts) {\r\n if (p5sound.parts[i]) {\r\n p5sound.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n *
A phrase is a pattern of musical events over time, i.e.\r\n * a series of notes and rests.
\r\n *\r\n *
Phrases must be added to a p5.Part for playback, and\r\n * each part can play multiple phrases at the same time.\r\n * For example, one Phrase might be a kick drum, another\r\n * could be a snare, and another could be the bassline.
\r\n *\r\n *
The first parameter is a name so that the phrase can be\r\n * modified or deleted later. The callback is a a function that\r\n * this phrase will call at every step—for example it might be\r\n * called playNote(value){}. The array determines\r\n * which value is passed into the callback at each step of the\r\n * phrase. It can be numbers, an object with multiple numbers,\r\n * or a zero (0) indicates a rest so the callback won't be called).
\r\n *\r\n * @class p5.Phrase\r\n * @constructor\r\n * @param {String} name Name so that you can access the Phrase.\r\n * @param {Function} callback The name of a function that this phrase\r\n * will call. Typically it will play a sound,\r\n * and accept two parameters: a time at which\r\n * to play the sound (in seconds from now),\r\n * and a value from the sequence array. The\r\n * time should be passed into the play() or\r\n * start() method to ensure precision.\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n * @example\r\n *
\r\n */\r\n p5.Phrase = function(name, callback, sequence) {\r\n this.phraseStep = 0;\r\n this.name = name;\r\n this.callback = callback;\r\n /**\r\n * Array of values to pass into the callback\r\n * at each step of the phrase. Depending on the callback\r\n * function's requirements, these values may be numbers,\r\n * strings, or an object with multiple parameters.\r\n * Zero (0) indicates a rest.\r\n *\r\n * @property {Array} sequence\r\n */\r\n this.sequence = sequence;\r\n };\r\n\r\n /**\r\n *
A p5.Part plays back one or more p5.Phrases. Instantiate a part\r\n * with steps and tatums. By default, each step represents a 1/16th note.
\r\n *\r\n *
See p5.Phrase for more about musical timing.
\r\n *\r\n * @class p5.Part\r\n * @constructor\r\n * @param {Number} [steps] Steps in the part\r\n * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note)\r\n * @example\r\n *
\r\n * var box, drum, myPart;\r\n * var boxPat = [1,0,0,2,0,2,0,0];\r\n * var drumPat = [0,1,1,0,2,0,1,0];\r\n * var msg = 'click to play';\r\n *\r\n * function preload() {\r\n * box = loadSound('assets/beatbox.mp3');\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * masterVolume(0.1);\r\n *\r\n * var boxPhrase = new p5.Phrase('box', playBox, boxPat);\r\n * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\r\n * myPart = new p5.Part();\r\n * myPart.addPhrase(boxPhrase);\r\n * myPart.addPhrase(drumPhrase);\r\n * myPart.setBPM(60);\r\n * masterVolume(0.1);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * text(msg, width/2, height/2);\r\n * }\r\n *\r\n * function playBox(time, playbackRate) {\r\n * box.rate(playbackRate);\r\n * box.play(time);\r\n * }\r\n *\r\n * function playDrum(time, playbackRate) {\r\n * drum.rate(playbackRate);\r\n * drum.play(time);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * myPart.start();\r\n * msg = 'playing part';\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Part = function(steps, bLength) {\r\n this.length = steps || 0; // how many beats\r\n this.partStep = 0;\r\n this.phrases = [];\r\n this.isPlaying = false;\r\n this.noLoop();\r\n this.tatums = bLength || 0.0625; // defaults to quarter note\r\n\r\n this.metro = new p5.Metro();\r\n this.metro._init();\r\n this.metro.beatLength(this.tatums);\r\n this.metro.setBPM(BPM);\r\n p5sound.parts.push(this);\r\n this.callback = function() {};\r\n };\r\n\r\n /**\r\n * Set the tempo of this part, in Beats Per Minute.\r\n *\r\n * @method setBPM\r\n * @for p5.Part\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} [rampTime] Seconds from now\r\n */\r\n p5.Part.prototype.setBPM = function(tempo, rampTime) {\r\n this.metro.setBPM(tempo, rampTime);\r\n };\r\n\r\n /**\r\n * Returns the tempo, in Beats Per Minute, of this part.\r\n *\r\n * @method getBPM\r\n * @for p5.Part\r\n * @return {Number}\r\n */\r\n p5.Part.prototype.getBPM = function() {\r\n return this.metro.getBPM();\r\n };\r\n\r\n /**\r\n * Start playback of this part. It will play\r\n * through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method start\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.start = function(time) {\r\n if (!this.isPlaying) {\r\n this.isPlaying = true;\r\n this.metro.resetSync(this);\r\n var t = time || 0;\r\n this.metro.start(t);\r\n }\r\n };\r\n\r\n /**\r\n * Loop playback of this part. It will begin\r\n * looping through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method loop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.loop = function(time) {\r\n this.looping = true;\r\n // rest onended function\r\n this.onended = function() {\r\n this.partStep = 0;\r\n };\r\n var t = time || 0;\r\n this.start(t);\r\n };\r\n\r\n /**\r\n * Tell the part to stop looping.\r\n *\r\n * @method noLoop\r\n * @for p5.Part\r\n */\r\n p5.Part.prototype.noLoop = function() {\r\n this.looping = false;\r\n // rest onended function\r\n this.onended = function() {\r\n this.stop();\r\n };\r\n };\r\n\r\n /**\r\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\r\n *\r\n * @method stop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.stop = function(time) {\r\n this.partStep = 0;\r\n this.pause(time);\r\n };\r\n\r\n /**\r\n * Pause the part. Playback will resume\r\n * from the current step.\r\n *\r\n * @method pause\r\n * @for p5.Part\r\n * @param {Number} time seconds from now\r\n */\r\n p5.Part.prototype.pause = function(time) {\r\n this.isPlaying = false;\r\n var t = time || 0;\r\n this.metro.stop(t);\r\n };\r\n\r\n /**\r\n * Add a p5.Phrase to this Part.\r\n *\r\n * @method addPhrase\r\n * @for p5.Part\r\n * @param {p5.Phrase} phrase reference to a p5.Phrase\r\n */\r\n p5.Part.prototype.addPhrase = function(name, callback, array) {\r\n var p;\r\n if (arguments.length === 3) {\r\n p = new p5.Phrase(name, callback, array);\r\n } else if (arguments[0] instanceof p5.Phrase) {\r\n p = arguments[0];\r\n } else {\r\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\r\n }\r\n this.phrases.push(p);\r\n // reset the length if phrase is longer than part's existing length\r\n if (p.sequence.length > this.length) {\r\n this.length = p.sequence.length;\r\n }\r\n };\r\n\r\n /**\r\n * Remove a phrase from this part, based on the name it was\r\n * given when it was created.\r\n *\r\n * @method removePhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.removePhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases.splice(i, 1);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Get a phrase from this part, based on the name it was\r\n * given when it was created. Now you can modify its array.\r\n *\r\n * @method getPhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.getPhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n return this.phrases[i];\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Find all sequences with the specified name, and replace their patterns with the specified array.\r\n *\r\n * @method replaceSequence\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n */\r\n p5.Part.prototype.replaceSequence = function(name, array) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases[i].sequence = array;\r\n }\r\n }\r\n };\r\n\r\n p5.Part.prototype.incrementStep = function(time) {\r\n if (this.partStep < this.length - 1) {\r\n this.callback(time);\r\n this.partStep += 1;\r\n } else {\r\n if (!this.looping && this.partStep === this.length - 1) {\r\n console.log('done');\r\n // this.callback(time);\r\n this.onended();\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the function that will be called at every step. This will clear the previous function.\r\n *\r\n * @method onStep\r\n * @for p5.Part\r\n * @param {Function} callback The name of the callback\r\n * you want to fire\r\n * on every beat/tatum.\r\n */\r\n p5.Part.prototype.onStep = function(callback) {\r\n this.callback = callback;\r\n };\r\n\r\n\r\n // ===============\r\n // p5.Score\r\n // ===============\r\n\r\n /**\r\n * A Score consists of a series of Parts. The parts will\r\n * be played back in order. For example, you could have an\r\n * A part, a B part, and a C part, and play them back in this order\r\n * new p5.Score(a, a, b, a, c)\r\n *\r\n * @class p5.Score\r\n * @constructor\r\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\r\n */\r\n p5.Score = function() {\r\n // for all of the arguments\r\n this.parts = [];\r\n this.currentPart = 0;\r\n\r\n var thisScore = this;\r\n for (var i in arguments) {\r\n if (arguments[i] && this.parts[i]) {\r\n this.parts[i] = arguments[i];\r\n this.parts[i].nextPart = this.parts[i + 1];\r\n this.parts[i].onended = function() {\r\n thisScore.resetPart(i);\r\n playNextPart(thisScore);\r\n };\r\n }\r\n }\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.onended = function() {\r\n if (this.looping) {\r\n // this.resetParts();\r\n this.parts[0].start();\r\n } else {\r\n this.parts[this.parts.length - 1].onended = function() {\r\n this.stop();\r\n this.resetParts();\r\n };\r\n }\r\n this.currentPart = 0;\r\n };\r\n\r\n /**\r\n * Start playback of the score.\r\n *\r\n * @method start\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.start = function() {\r\n this.parts[this.currentPart].start();\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Stop playback of the score.\r\n *\r\n * @method stop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.stop = function() {\r\n this.parts[this.currentPart].stop();\r\n this.currentPart = 0;\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Pause playback of the score.\r\n *\r\n * @method pause\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.pause = function() {\r\n this.parts[this.currentPart].stop();\r\n };\r\n\r\n /**\r\n * Loop playback of the score.\r\n *\r\n * @method loop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.loop = function() {\r\n this.looping = true;\r\n this.start();\r\n };\r\n\r\n /**\r\n * Stop looping playback of the score. If it\r\n * is currently playing, this will go into effect\r\n * after the current round of playback completes.\r\n *\r\n * @method noLoop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.noLoop = function() {\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.resetParts = function() {\r\n var self = this;\r\n this.parts.forEach(function(part) {\r\n self.resetParts[part];\r\n });\r\n };\r\n\r\n p5.Score.prototype.resetPart = function(i) {\r\n this.parts[i].stop();\r\n this.parts[i].partStep = 0;\r\n for (var p in this.parts[i].phrases) {\r\n if (this.parts[i]) {\r\n this.parts[i].phrases[p].phraseStep = 0;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the tempo for all parts in the score\r\n *\r\n * @method setBPM\r\n * @for p5.Score\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.Score.prototype.setBPM = function(bpm, rampTime) {\r\n for (var i in this.parts) {\r\n if (this.parts[i]) {\r\n this.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n function playNextPart(aScore) {\r\n aScore.currentPart++;\r\n if (aScore.currentPart >= aScore.parts.length) {\r\n aScore.scoreStep = 0;\r\n aScore.onended();\r\n } else {\r\n aScore.scoreStep = 0;\r\n aScore.parts[aScore.currentPart - 1].stop();\r\n aScore.parts[aScore.currentPart].start();\r\n }\r\n }\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Clock = require('Tone/core/Clock');\r\n\r\n /**\r\n * SoundLoop\r\n *\r\n * @class p5.SoundLoop\r\n * @constructor\r\n *\r\n * @param {Function} callback this function will be called on each iteration of theloop\r\n * @param {Number|String} [interval] amount of time or beats for each iteration of the loop\r\n * defaults to 1\r\n *\r\n * @example\r\n *
\r\n * var click;\r\n * var looper1;\r\n *\r\n * function preload() {\r\n * click = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * //the looper's callback is passed the timeFromNow\r\n * //this value should be used as a reference point from\r\n * //which to schedule sounds\r\n * looper1 = new p5.SoundLoop(function(timeFromNow){\r\n * click.play(timeFromNow);\r\n * background(255 * (looper1.iterations % 2));\r\n * }, 2);\r\n *\r\n * //stop after 10 iteratios;\r\n * looper1.maxIterations = 10;\r\n * //start the loop\r\n * looper1.start();\r\n * }\r\n *
\r\n */\r\n p5.SoundLoop = function(callback, interval) {\r\n this.callback = callback;\r\n /**\r\n * musicalTimeMode uses Tone.Time convention\r\n\t * true if string, false if number\r\n * @property {Boolean} musicalTimeMode\r\n */\r\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\r\n\r\n this._interval = interval || 1;\r\n\r\n /**\r\n * musicalTimeMode variables\r\n * modify these only when the interval is specified in musicalTime format as a string\r\n */\r\n this._timeSignature = 4;\r\n this._bpm = 60;\r\n\r\n this.isPlaying = false;\r\n\r\n /**\r\n * Set a limit to the number of loops to play. defaults to Infinity\r\n * @property {Number} maxIterations\r\n */\r\n this.maxIterations = Infinity;\r\n var self = this;\r\n\r\n this.clock = new Clock({\r\n 'callback' : function(time) {\r\n var timeFromNow = time - p5sound.audiocontext.currentTime;\r\n /**\r\n * Do not initiate the callback if timeFromNow is < 0\r\n * This ususually occurs for a few milliseconds when the page\r\n * is not fully loaded\r\n *\r\n * The callback should only be called until maxIterations is reached\r\n */\r\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\r\n self.callback(timeFromNow);}\r\n },\r\n 'frequency' : this._calcFreq()\r\n });\r\n };\r\n\r\n /**\r\n * Start the loop\r\n * @method start\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a starting time\r\n */\r\n p5.SoundLoop.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (!this.isPlaying) {\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop the loop\r\n * @method stop\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a stopping time\r\n */\r\n p5.SoundLoop.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.stop(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n /**\r\n * Pause the loop\r\n * @method pause\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a pausing time\r\n */\r\n p5.SoundLoop.prototype.pause = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.pause(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Synchronize loops. Use this method to start two more more loops in synchronization\r\n * or to start a loop in synchronization with a loop that is already playing\r\n * This method will schedule the implicit loop in sync with the explicit master loop\r\n * i.e. loopToStart.syncedStart(loopToSyncWith)\r\n *\r\n * @method syncedStart\r\n * @for p5.SoundLoop\r\n * @param {Object} otherLoop a p5.SoundLoop to sync with\r\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\r\n */\r\n p5.SoundLoop.prototype.syncedStart = function(otherLoop, timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n if (!otherLoop.isPlaying) {\r\n otherLoop.clock.start(now + t);\r\n otherLoop.isPlaying = true;\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n } else if (otherLoop.isPlaying) {\r\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\r\n this.clock.start(now + time);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Updates frequency value, reflected in next callback\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _update\r\n */\r\n p5.SoundLoop.prototype._update = function() {\r\n this.clock.frequency.value = this._calcFreq();\r\n };\r\n\r\n /**\r\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _calcFreq\r\n * @return {Number} new clock frequency value\r\n */\r\n p5.SoundLoop.prototype._calcFreq = function() {\r\n //Seconds mode, bpm / timesignature has no effect\r\n if (typeof this._interval === 'number') {\r\n this.musicalTimeMode = false;\r\n return 1 / this._interval;\r\n }\r\n //Musical timing mode, calculate interval based bpm, interval,and time signature\r\n else if (typeof this._interval === 'string') {\r\n this.musicalTimeMode = true;\r\n return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4);\r\n }\r\n };\r\n\r\n /**\r\n * Convert notation from musical time format to seconds\r\n * Uses Tone.Time convention\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _convertNotation\r\n * @param {String} value value to be converted\r\n * @return {Number} converted value in seconds\r\n */\r\n p5.SoundLoop.prototype._convertNotation = function(value) {\r\n var type = value.slice(-1);\r\n value = Number(value.slice(0,-1));\r\n switch (type) {\r\n case 'm':\r\n return this._measure(value);\r\n case 'n':\r\n return this._note(value);\r\n default:\r\n console.warn('Specified interval is not formatted correctly. See Tone.js '+\r\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time');\r\n }\r\n };\r\n\r\n /**\r\n * Helper conversion methods of measure and note\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _measure\r\n */\r\n p5.SoundLoop.prototype._measure = function(value) {\r\n return value * this._timeSignature;\r\n };\r\n\r\n /**\r\n * @private\r\n * @method _note\r\n * @for p5.SoundLoop\r\n */\r\n p5.SoundLoop.prototype._note = function(value) {\r\n return this._timeSignature / value ;\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters, setting any paramter will result in a change in the clock's\r\n * frequency, that will be reflected after the next callback\r\n * beats per minute (defaults to 60)\r\n * @property {Number} bpm\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'bpm', {\r\n get : function() {\r\n return this._bpm;\r\n },\r\n set : function(bpm) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the BPM in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._bpm = bpm;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * number of quarter notes in a measure (defaults to 4)\r\n * @property {Number} timeSignature\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {\r\n get : function() {\r\n return this._timeSignature;\r\n },\r\n set : function(timeSig) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the timeSignature in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._timeSignature = timeSig;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * length of the loops interval\r\n * @property {Number|String} interval\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'interval', {\r\n get : function() {\r\n return this._interval;\r\n },\r\n set : function(interval) {\r\n this.musicalTimeMode = typeof interval === 'Number'? false : true;\r\n this._interval = interval;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * how many times the callback has been called so far\r\n * @property {Number} iterations\r\n * @for p5.SoundLoop\r\n * @readonly\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'iterations', {\r\n get : function() {\r\n return this.clock.ticks;\r\n }\r\n });\r\n\r\n return p5.SoundLoop;\r\n});\r\n","define(function (require) {\r\n\t'use strict';\r\n\r\n\tvar p5sound = require('master');\r\n\tvar Effect = require('effect');\r\n var CustomError = require('errorHandler');\r\n\r\n /**\r\n * Compressor is an audio effect class that performs dynamics compression\r\n * on an audio input source. This is a very commonly used technique in music\r\n * and sound production. Compression creates an overall louder, richer,\r\n * and fuller sound by lowering the volume of louds and raising that of softs.\r\n * Compression can be used to avoid clipping (sound distortion due to\r\n * peaks in volume) and is especially useful when many sounds are played\r\n * at once. Compression can be used on indivudal sound sources in addition\r\n * to the master output.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Compressor\r\n * @constructor\r\n * @extends p5.Effect\r\n *\r\n *\r\n */\r\n\tp5.Compressor = function() {\r\n\t\tEffect.call(this);\r\n\r\n /**\r\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\r\n * \r\n * @property {AudioNode} compressor\r\n */\r\n\r\n\r\n\t\tthis.compressor = this.ac.createDynamicsCompressor();\r\n\r\n this.input.connect(this.compressor);\r\n this.compressor.connect(this.wet);\r\n\t};\r\n\r\n\tp5.Compressor.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Performs the same function as .connect, but also accepts\r\n * optional parameters to set compressor's audioParams\r\n * @method process\r\n * @for p5.Compressor\r\n *\r\n * @param {Object} src Sound source to be connected\r\n *\r\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n\tp5.Compressor.prototype.process = function(src, attack, knee,\r\n ratio, threshold, release) {\r\n\t\tsrc.connect(this.input);\r\n\t\tthis.set(attack, knee, ratio, threshold, release);\r\n\t};\r\n\r\n /**\r\n * Set the paramters of a compressor.\r\n * @method set\r\n * @for p5.Compressor\r\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} knee A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n p5.Compressor.prototype.set = function (attack, knee,\r\n ratio, threshold, release) {\r\n\r\n if (typeof attack !== 'undefined') {this.attack(attack);}\r\n if (typeof knee !== 'undefined') {this.knee(knee);}\r\n if (typeof ratio !== 'undefined') {this.ratio(ratio);}\r\n if (typeof threshold !== 'undefined') {this.threshold(threshold);}\r\n if (typeof release !== 'undefined') {this.release(release);}\r\n };\r\n\r\n\r\n /**\r\n * Get current attack or set value w/ time ramp\r\n *\r\n *\r\n * @method attack\r\n * @for p5.Compressor\r\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.attack = function (attack, time){\r\n var t = time || 0;\r\n if (typeof attack == 'number'){\r\n this.compressor.attack.value = attack;\r\n this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof attack !== 'undefined') {\r\n attack.connect(this.compressor.attack);\r\n }\r\n return this.compressor.attack.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current knee or set value w/ time ramp\r\n *\r\n * @method knee\r\n * @for p5.Compressor\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.knee = function (knee, time){\r\n var t = time || 0;\r\n if (typeof knee == 'number'){\r\n this.compressor.knee.value = knee;\r\n this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof knee !== 'undefined') {\r\n knee.connect(this.compressor.knee);\r\n }\r\n return this.compressor.knee.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current ratio or set value w/ time ramp\r\n * @method ratio\r\n * @for p5.Compressor\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.ratio = function (ratio, time){\r\n var t = time || 0;\r\n if (typeof ratio == 'number'){\r\n this.compressor.ratio.value = ratio;\r\n this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof ratio !== 'undefined') {\r\n ratio.connect(this.compressor.ratio);\r\n }\r\n return this.compressor.ratio.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current threshold or set value w/ time ramp\r\n * @method threshold\r\n * @for p5.Compressor\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.threshold = function (threshold, time){\r\n var t = time || 0;\r\n if (typeof threshold == 'number'){\r\n this.compressor.threshold.value = threshold;\r\n this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof threshold !== 'undefined') {\r\n threshold.connect(this.compressor.threshold);\r\n }\r\n return this.compressor.threshold.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current release or set value w/ time ramp\r\n * @method release\r\n * @for p5.Compressor\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n *\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.release = function (release, time){\r\n var t = time || 0;\r\n if (typeof release == 'number'){\r\n this.compressor.release.value = release;\r\n this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof number !== 'undefined') {\r\n release.connect(this.compressor.release);\r\n }\r\n return this.compressor.release.value;\r\n };\r\n\r\n /**\r\n * Return the current reduction value\r\n *\r\n * @method reduction\r\n * @for p5.Compressor\r\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\r\n */\r\n p5.Compressor.prototype.reduction =function() {\r\n return this.compressor.reduction.value;\r\n };\r\n\r\n\r\n\tp5.Compressor.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.compressor) {\r\n this.compressor.disconnect();\r\n delete this.compressor;\r\n }\r\n\t};\r\n\r\n return p5.Compressor;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // inspiration: recorder.js, Tone.js & typedarray.org\r\n\r\n var p5sound = require('master');\r\n var convertToWav = require('helpers').convertToWav;\r\n var processorNames = require('./audioWorklet/processorNames');\r\n var ac = p5sound.audiocontext;\r\n\r\n /**\r\n *
Record sounds for playback and/or to save as a .wav file.\r\n * The p5.SoundRecorder records all sound output from your sketch,\r\n * or can be assigned a specific source with setInput().
\r\n *
The record() method accepts a p5.SoundFile as a parameter.\r\n * When playback is stopped (either after the given amount of time,\r\n * or with the stop() method), the p5.SoundRecorder will send its\r\n * recording to that p5.SoundFile for playback.
\r\n * var mic, recorder, soundFile;\r\n * var state = 0;\r\n *\r\n * function setup() {\r\n * background(200);\r\n * // create an audio in\r\n * mic = new p5.AudioIn();\r\n *\r\n * // prompts user to enable their browser mic\r\n * mic.start();\r\n *\r\n * // create a sound recorder\r\n * recorder = new p5.SoundRecorder();\r\n *\r\n * // connect the mic to the recorder\r\n * recorder.setInput(mic);\r\n *\r\n * // this sound file will be used to\r\n * // playback & save the recording\r\n * soundFile = new p5.SoundFile();\r\n *\r\n * text('keyPress to record', 20, 20);\r\n * }\r\n *\r\n * function keyPressed() {\r\n * // make sure user enabled the mic\r\n * if (state === 0 && mic.enabled) {\r\n *\r\n * // record to our p5.SoundFile\r\n * recorder.record(soundFile);\r\n *\r\n * background(255,0,0);\r\n * text('Recording!', 20, 20);\r\n * state++;\r\n * }\r\n * else if (state === 1) {\r\n * background(0,255,0);\r\n *\r\n * // stop recorder and\r\n * // send result to soundFile\r\n * recorder.stop();\r\n *\r\n * text('Stopped', 20, 20);\r\n * state++;\r\n * }\r\n *\r\n * else if (state === 2) {\r\n * soundFile.play(); // play the result!\r\n * save(soundFile, 'mySound.wav');\r\n * state++;\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.SoundRecorder = function() {\r\n this.input = ac.createGain();\r\n this.output = ac.createGain();\r\n\r\n this._inputChannels = 2;\r\n this._outputChannels = 2; // stereo output, even if input is mono\r\n\r\n this._workletNode = new AudioWorkletNode(ac, processorNames.recorderProcessor, {\r\n outputChannelCount: [this._outputChannels],\r\n processorOptions: { numInputChannels: this._inputChannels }\r\n });\r\n\r\n this._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'buffers') {\r\n const buffers = [\r\n new Float32Array(event.data.leftBuffer),\r\n new Float32Array(event.data.rightBuffer)\r\n ];\r\n this._callback(buffers);\r\n }\r\n }.bind(this);\r\n\r\n /**\r\n * callback invoked when the recording is over\r\n * @private\r\n * @type Function(Float32Array)\r\n */\r\n this._callback = function() {};\r\n\r\n // connections\r\n this._workletNode.connect(p5.soundOut._silentNode);\r\n this.setInput();\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a specific device to the p5.SoundRecorder.\r\n * If no parameter is given, p5.SoundRecorer will record\r\n * all audible p5.sound from your sketch.\r\n *\r\n * @method setInput\r\n * @for p5.SoundRecorder\r\n * @param {Object} [unit] p5.sound object or a web audio unit\r\n * that outputs sound\r\n */\r\n p5.SoundRecorder.prototype.setInput = function(unit) {\r\n this.input.disconnect();\r\n this.input = null;\r\n this.input = ac.createGain();\r\n this.input.connect(this._workletNode);\r\n this.input.connect(this.output);\r\n if (unit) {\r\n unit.connect(this.input);\r\n } else {\r\n p5.soundOut.output.connect(this.input);\r\n }\r\n };\r\n\r\n /**\r\n * Start recording. To access the recording, provide\r\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\r\n * will send its recording to that p5.SoundFile for playback once\r\n * recording is complete. Optional parameters include duration\r\n * (in seconds) of the recording, and a callback function that\r\n * will be called once the complete recording has been\r\n * transfered to the p5.SoundFile.\r\n *\r\n * @method record\r\n * @for p5.SoundRecorder\r\n * @param {p5.SoundFile} soundFile p5.SoundFile\r\n * @param {Number} [duration] Time (in seconds)\r\n * @param {Function} [callback] The name of a function that will be\r\n * called once the recording completes\r\n */\r\n p5.SoundRecorder.prototype.record = function(sFile, duration, callback) {\r\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\r\n\r\n if (sFile && callback) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n callback();\r\n };\r\n }\r\n else if (sFile) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Stop the recording. Once the recording is stopped,\r\n * the results will be sent to the p5.SoundFile that\r\n * was given on .record(), and if a callback function\r\n * was provided on record, that function will be called.\r\n *\r\n * @method stop\r\n * @for p5.SoundRecorder\r\n */\r\n p5.SoundRecorder.prototype.stop = function() {\r\n this._workletNode.port.postMessage({ name: 'stop' });\r\n };\r\n\r\n p5.SoundRecorder.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this._callback = function() {};\r\n if (this.input) {\r\n this.input.disconnect();\r\n }\r\n this.input = null;\r\n this._workletNode = null;\r\n };\r\n\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device.\r\n * For uploading audio to a server, use\r\n * `p5.SoundFile.saveBlob`.\r\n *\r\n * @for p5\r\n * @method saveSound\r\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\r\n * @param {String} fileName name of the resulting .wav file.\r\n */\r\n // add to p5.prototype as this is used by the p5 `save()` method.\r\n p5.prototype.saveSound = function (soundFile, fileName) {\r\n const dataView = convertToWav(soundFile.buffer);\r\n p5.prototype.writeFile([dataView], fileName, 'wav');\r\n };\r\n});\r\n","'use strict';\r\n\r\ndefine(function () {\r\n /**\r\n *
PeakDetect works in conjunction with p5.FFT to\r\n * look for onsets in some or all of the frequency spectrum.\r\n *
\r\n *
\r\n * To use p5.PeakDetect, call update in the draw loop\r\n * and pass in a p5.FFT object.\r\n *
\r\n *
\r\n * You can listen for a specific part of the frequency spectrum by\r\n * setting the range between freq1 and freq2.\r\n *
\r\n *\r\n *
threshold is the threshold for detecting a peak,\r\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\r\n * as 1.0.
\r\n *\r\n *
\r\n * The update method is meant to be run in the draw loop, and\r\n * frames determines how many loops must pass before\r\n * another peak can be detected.\r\n * For example, if the frameRate() = 60, you could detect the beat of a\r\n * 120 beat-per-minute song with this equation:\r\n * framesPerPeak = 60 / (estimatedBPM / 60 );\r\n *
\r\n *\r\n *
\r\n * Based on example contribtued by @b2renger, and a simple beat detection\r\n * explanation by Felix Turner.\r\n *
\r\n *\r\n * @class p5.PeakDetect\r\n * @constructor\r\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\r\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\r\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\r\n * scaled logarithmically where 0.1 is 1/2 the loudness\r\n * of 1.0. Defaults to 0.35.\r\n * @param {Number} [framesPerPeak] Defaults to 20.\r\n * @example\r\n *
\r\n */\r\n p5.PeakDetect = function(freq1, freq2, threshold, _framesPerPeak) {\r\n // framesPerPeak determines how often to look for a beat.\r\n // If a beat is provided, try to look for a beat based on bpm\r\n this.framesPerPeak = _framesPerPeak || 20;\r\n this.framesSinceLastPeak = 0;\r\n this.decayRate = 0.95;\r\n\r\n this.threshold = threshold || 0.35;\r\n this.cutoff = 0;\r\n\r\n // how much to increase the cutoff\r\n // TO DO: document this / figure out how to make it accessible\r\n this.cutoffMult = 1.5;\r\n\r\n this.energy = 0;\r\n this.penergy = 0;\r\n\r\n // TO DO: document this property / figure out how to make it accessible\r\n this.currentValue = 0;\r\n\r\n /**\r\n * isDetected is set to true when a peak is detected.\r\n *\r\n * @attribute isDetected {Boolean}\r\n * @default false\r\n */\r\n this.isDetected = false;\r\n\r\n this.f1 = freq1 || 40;\r\n this.f2 = freq2 || 20000;\r\n\r\n // function to call when a peak is detected\r\n this._onPeak = function() {};\r\n };\r\n\r\n\r\n /**\r\n * The update method is run in the draw loop.\r\n *\r\n * Accepts an FFT object. You must call .analyze()\r\n * on the FFT object prior to updating the peakDetect\r\n * because it relies on a completed FFT analysis.\r\n *\r\n * @method update\r\n * @param {p5.FFT} fftObject A p5.FFT object\r\n */\r\n p5.PeakDetect.prototype.update = function(fftObject) {\r\n var nrg = this.energy = fftObject.getEnergy(this.f1,this.f2)/255;\r\n if (nrg > this.cutoff && nrg > this.threshold && nrg-this.penergy > 0) {\r\n\r\n // trigger callback\r\n this._onPeak();\r\n this.isDetected = true;\r\n\r\n // debounce\r\n this.cutoff = nrg * this.cutoffMult;\r\n this.framesSinceLastPeak = 0;\r\n } else {\r\n this.isDetected = false;\r\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\r\n this.framesSinceLastPeak++;\r\n } else {\r\n this.cutoff *= this.decayRate;\r\n this.cutoff = Math.max(this.cutoff, this.threshold);\r\n }\r\n }\r\n\r\n this.currentValue = nrg;\r\n this.penergy = nrg;\r\n };\r\n\r\n /**\r\n * onPeak accepts two arguments: a function to call when\r\n * a peak is detected. The value of the peak,\r\n * between 0.0 and 1.0, is passed to the callback.\r\n *\r\n * @method onPeak\r\n * @param {Function} callback Name of a function that will\r\n * be called when a peak is\r\n * detected.\r\n * @param {Object} [val] Optional value to pass\r\n * into the function when\r\n * a peak is detected.\r\n * @example\r\n *
\r\n * var cnv, soundFile, fft, peakDetect;\r\n * var ellipseWidth = 0;\r\n *\r\n * function preload() {\r\n * soundFile = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * textAlign(CENTER);\r\n *\r\n * fft = new p5.FFT();\r\n * peakDetect = new p5.PeakDetect();\r\n *\r\n * setupSound();\r\n *\r\n * // when a beat is detected, call triggerBeat()\r\n * peakDetect.onPeak(triggerBeat);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * fft.analyze();\r\n * peakDetect.update(fft);\r\n *\r\n * ellipseWidth *= 0.95;\r\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\r\n * }\r\n *\r\n * // this function is called by peakDetect.onPeak\r\n * function triggerBeat() {\r\n * ellipseWidth = 50;\r\n * }\r\n *\r\n * // mouseclick starts/stops sound\r\n * function setupSound() {\r\n * cnv.mouseClicked( function() {\r\n * if (soundFile.isPlaying() ) {\r\n * soundFile.stop();\r\n * } else {\r\n * soundFile.play();\r\n * }\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.PeakDetect.prototype.onPeak = function(callback, val) {\r\n var self = this;\r\n\r\n self._onPeak = function() {\r\n callback(self.energy, val);\r\n };\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * A gain node is usefull to set the relative volume of sound.\r\n * It's typically used to build mixers.\r\n *\r\n * @class p5.Gain\r\n * @constructor\r\n * @example\r\n *
\r\n *\r\n * // load two soundfile and crossfade beetween them\r\n * var sound1,sound2;\r\n * var gain1, gain2, gain3;\r\n *\r\n * function preload(){\r\n * soundFormats('ogg', 'mp3');\r\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\r\n * sound2 = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * createCanvas(400,200);\r\n *\r\n * // create a 'master' gain to which we will connect both soundfiles\r\n * gain3 = new p5.Gain();\r\n * gain3.connect();\r\n *\r\n * // setup first sound for playing\r\n * sound1.rate(1);\r\n * sound1.loop();\r\n * sound1.disconnect(); // diconnect from p5 output\r\n *\r\n * gain1 = new p5.Gain(); // setup a gain node\r\n * gain1.setInput(sound1); // connect the first sound to its input\r\n * gain1.connect(gain3); // connect its output to the 'master'\r\n *\r\n * sound2.rate(1);\r\n * sound2.disconnect();\r\n * sound2.loop();\r\n *\r\n * gain2 = new p5.Gain();\r\n * gain2.setInput(sound2);\r\n * gain2.connect(gain3);\r\n *\r\n * }\r\n *\r\n * function draw(){\r\n * background(180);\r\n *\r\n * // calculate the horizontal distance beetween the mouse and the right of the screen\r\n * var d = dist(mouseX,0,width,0);\r\n *\r\n * // map the horizontal position of the mouse to values useable for volume control of sound1\r\n * var vol1 = map(mouseX,0,width,0,1);\r\n * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa\r\n *\r\n * gain1.amp(vol1,0.5,0);\r\n * gain2.amp(vol2,0.5,0);\r\n *\r\n * // map the vertical position of the mouse to values useable for 'master volume control'\r\n * var vol3 = map(mouseY,0,height,0,1);\r\n * gain3.amp(vol3,0.5,0);\r\n * }\r\n *
\r\n *\r\n */\r\n\r\n p5.Gain = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n this.input.connect(this.output);\r\n\r\n // add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a source to the gain node.\r\n *\r\n * @method setInput\r\n * @for p5.Gain\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n */\r\n\r\n\r\n p5.Gain.prototype.setInput = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Gain\r\n * @param {Object} unit\r\n */\r\n p5.Gain.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Gain\r\n */\r\n p5.Gain.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Set the output level of the gain node.\r\n *\r\n * @method amp\r\n * @for p5.Gain\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Gain.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n };\r\n\r\n p5.Gain.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n\r\n /*\r\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n */\r\n function makeDistortionCurve(amount) {\r\n var k = typeof amount === 'number' ? amount : 50;\r\n var numSamples = 44100;\r\n var curve = new Float32Array(numSamples);\r\n var deg = Math.PI / 180;\r\n var i = 0;\r\n var x;\r\n for ( ; i < numSamples; ++i ) {\r\n x = i * 2 / numSamples - 1;\r\n curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );\r\n }\r\n return curve;\r\n }\r\n\r\n /**\r\n * A Distortion effect created with a Waveshaper Node,\r\n * with an approach adapted from\r\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Distortion\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n *\r\n */\r\n p5.Distortion = function(amount, oversample) {\r\n Effect.call(this);\r\n\r\n if (typeof amount === 'undefined') {\r\n amount = 0.25;\r\n } if (typeof amount !== 'number') {\r\n throw new Error('amount must be a number');\r\n } if (typeof oversample === 'undefined') {\r\n oversample = '2x';\r\n } if (typeof oversample !== 'string') {\r\n throw new Error('oversample must be a String');\r\n }\r\n\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n\r\n /**\r\n * The p5.Distortion is built with a\r\n * \r\n * Web Audio WaveShaper Node.\r\n *\r\n * @property {AudioNode} WaveShaperNode\r\n */\r\n this.waveShaperNode = this.ac.createWaveShaper();\r\n\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n this.waveShaperNode.oversample = oversample;\r\n\r\n this.input.connect(this.waveShaperNode);\r\n\r\n this.waveShaperNode.connect(this.wet);\r\n };\r\n\r\n p5.Distortion.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Process a sound source, optionally specify amount and oversample values.\r\n *\r\n * @method process\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.process = function(src, amount, oversample) {\r\n src.connect(this.input);\r\n this.set(amount, oversample);\r\n };\r\n\r\n /**\r\n * Set the amount and oversample of the waveshaper distortion.\r\n *\r\n * @method set\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.set = function(amount, oversample) {\r\n if (amount) {\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n }\r\n if (oversample) {\r\n this.waveShaperNode.oversample = oversample;\r\n }\r\n };\r\n\r\n /**\r\n * Return the distortion amount, typically between 0-1.\r\n *\r\n * @method getAmount\r\n * @for p5.Distortion\r\n * @return {Number} Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n */\r\n p5.Distortion.prototype.getAmount = function() {\r\n return this.amount;\r\n };\r\n\r\n /**\r\n * Return the oversampling.\r\n *\r\n * @method getOversample\r\n * @for p5.Distortion\r\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.getOversample = function() {\r\n return this.waveShaperNode.oversample;\r\n };\r\n\r\n\r\n p5.Distortion.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.waveShaperNode) {\r\n this.waveShaperNode.disconnect();\r\n this.waveShaperNode = null;\r\n }\r\n };\r\n});\r\n","export default \"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \\\"function\\\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \\\"function\\\") { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } if (typeof _cache !== \\\"undefined\\\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\\n\\nfunction isNativeReflectConstruct() { if (typeof Reflect === \\\"undefined\\\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \\\"function\\\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\\n\\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\\n\\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\\\"[native code]\\\") !== -1; }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\n// import processor name via preval.require so that it's available as a value at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n}; // TO DO make this stereo / dependent on # of audio channels\\n\\nvar AmplitudeProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\\n\\n _createClass(AmplitudeProcessor, null, [{\\n key: \\\"parameterDescriptors\\\",\\n get: function get() {\\n return [{\\n name: 'smoothing',\\n defaultValue: 0,\\n minValue: 0,\\n maxValue: 1,\\n automationRate: 'k-rate'\\n }];\\n }\\n }]);\\n\\n function AmplitudeProcessor(options) {\\n var _this;\\n\\n _classCallCheck(this, AmplitudeProcessor);\\n\\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\\n var processorOptions = options.processorOptions || {};\\n _this.normalize = processorOptions.normalize || false;\\n _this.stereoVol = [0, 0];\\n _this.stereoVolNorm = [0, 0];\\n _this.volMax = 0.001;\\n\\n _this.port.onmessage = function (event) {\\n var data = event.data;\\n\\n if (data.name === 'toggleNormalize') {\\n _this.normalize = data.normalize;\\n }\\n };\\n\\n return _this;\\n }\\n\\n _createClass(AmplitudeProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs, outputs, parameters) {\\n var input = inputs[0];\\n var output = outputs[0];\\n var smoothing = parameters.smoothing;\\n\\n for (var channel = 0; channel < input.length; ++channel) {\\n var inputBuffer = input[channel];\\n var bufLength = inputBuffer.length;\\n var sum = 0;\\n\\n for (var i = 0; i < bufLength; i++) {\\n var x = inputBuffer[i];\\n\\n if (this.normalize) {\\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\\n } else {\\n sum += x * x;\\n }\\n } // ... then take the square root of the sum.\\n\\n\\n var rms = Math.sqrt(sum / bufLength);\\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\\n } // calculate stero normalized volume and add volume from all channels together\\n\\n\\n var volSum = 0;\\n\\n for (var index = 0; index < this.stereoVol.length; index++) {\\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\\n volSum += this.stereoVol[index];\\n } // volume is average of channels\\n\\n\\n var volume = volSum / this.stereoVol.length; // normalized value\\n\\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\\n this.port.postMessage({\\n name: 'amplitude',\\n volume: volume,\\n volNorm: volNorm,\\n stereoVol: this.stereoVol,\\n stereoVolNorm: this.stereoVolNorm\\n }); // pass input through to output\\n\\n for (var _channel = 0; _channel < output.length; ++_channel) {\\n output[_channel].set(input[_channel]);\\n }\\n\\n return true;\\n }\\n }]);\\n\\n return AmplitudeProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);\""],"sourceRoot":""}
\ No newline at end of file
diff --git a/lib/p5.sound.min.js b/lib/p5.sound.min.js
index bc92539b..0c0343fb 100644
--- a/lib/p5.sound.min.js
+++ b/lib/p5.sound.min.js
@@ -1,2 +1,2 @@
-!function(i){var n={};function o(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return i[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=i,o.c=n,o.d=function(t,e,i){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(i,n,function(t){return e[t]}.bind(null,n));return i},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=30)}([function(t,e,i){var n;void 0===(n=function(){"use strict";function c(t,e){this.isUndef(t)||1===t?this.input=this.context.createGain():1t)this.cancelScheduledValues(t),this.linearRampToValueAtTime(e,t);else{var n=this._searchAfter(t);n&&(this.cancelScheduledValues(t),n.type===p.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):n.type===p.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},p.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,i){return this.setRampPoint(e),this.linearRampToValueAtTime(t,i),this},p.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,i){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,i),this},p.TimelineSignal.prototype._searchBefore=function(t){return this._events.get(t)},p.TimelineSignal.prototype._searchAfter=function(t){return this._events.getAfter(t)},p.TimelineSignal.prototype.getValueAtTime=function(t){t=this.toSeconds(t);var e=this._searchAfter(t),i=this._searchBefore(t),n=this._initial;if(null===i)n=this._initial;else if(i.type===p.TimelineSignal.Type.Target){var o,r=this._events.getBefore(i.time);o=null===r?this._initial:r.value,n=this._exponentialApproach(i.time,o,i.value,i.constant,t)}else n=i.type===p.TimelineSignal.Type.Curve?this._curveInterpolate(i.time,i.value,i.duration,t):null===e?i.value:e.type===p.TimelineSignal.Type.Linear?this._linearInterpolate(i.time,i.value,e.time,e.value,t):e.type===p.TimelineSignal.Type.Exponential?this._exponentialInterpolate(i.time,i.value,e.time,e.value,t):i.value;return n},p.TimelineSignal.prototype.connect=p.SignalBase.prototype.connect,p.TimelineSignal.prototype._exponentialApproach=function(t,e,i,n,o){return i+(e-i)*Math.exp(-(o-t)/n)},p.TimelineSignal.prototype._linearInterpolate=function(t,e,i,n,o){return e+(o-t)/(i-t)*(n-e)},p.TimelineSignal.prototype._exponentialInterpolate=function(t,e,i,n,o){return(e=Math.max(this._minOutput,e))*Math.pow(n/e,(o-t)/(i-t))},p.TimelineSignal.prototype._curveInterpolate=function(t,e,i,n){var o=e.length;if(t+i<=n)return e[o-1];if(n<=t)return e[0];var r=(n-t)/i,s=Math.floor((o-1)*r),a=Math.ceil((o-1)*r),p=e[s],u=e[a];return a===s?p:this._linearInterpolate(s,p,a,u,r*(o-1))},p.TimelineSignal.prototype.dispose=function(){p.Signal.prototype.dispose.call(this),p.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},p.TimelineSignal}.apply(e,n))||(t.exports=o)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var e=i(4);return p5.Filter=function(t){e.call(this),this.biquad=this.ac.createBiquadFilter(),this.input.connect(this.biquad),this.biquad.connect(this.wet),t&&this.setType(t),this._on=!0,this._untoggledType=this.biquad.type},p5.Filter.prototype=Object.create(e.prototype),p5.Filter.prototype.process=function(t,e,i,n){t.connect(this.input),this.set(e,i,n)},p5.Filter.prototype.set=function(t,e,i){t&&this.freq(t,i),e&&this.res(e,i)},p5.Filter.prototype.freq=function(t,e){var i=e||0;return t<=0&&(t=1),"number"==typeof t?(this.biquad.frequency.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.frequency.exponentialRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.frequency),this.biquad.frequency.value},p5.Filter.prototype.res=function(t,e){var i=e||0;return"number"==typeof t?(this.biquad.Q.value=t,this.biquad.Q.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.Q.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.Q),this.biquad.Q.value},p5.Filter.prototype.gain=function(t,e){var i=e||0;return"number"==typeof t?(this.biquad.gain.value=t,this.biquad.gain.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.gain.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.gain),this.biquad.gain.value},p5.Filter.prototype.toggle=function(){return this._on=!this._on,!0===this._on?this.biquad.type=this._untoggledType:!1===this._on&&(this.biquad.type="allpass"),this._on},p5.Filter.prototype.setType=function(t){this.biquad.type=t,this._untoggledType=this.biquad.type},p5.Filter.prototype.dispose=function(){e.prototype.dispose.apply(this),this.biquad&&(this.biquad.disconnect(),delete this.biquad)},p5.LowPass=function(){p5.Filter.call(this,"lowpass")},p5.LowPass.prototype=Object.create(p5.Filter.prototype),p5.HighPass=function(){p5.Filter.call(this,"highpass")},p5.HighPass.prototype=Object.create(p5.Filter.prototype),p5.BandPass=function(){p5.Filter.call(this,"bandpass")},p5.BandPass.prototype=Object.create(p5.Filter.prototype),p5.Filter}.call(e,i,e,t))||(t.exports=n)},function(t,e,i){var n,o;n=[i(0),i(7),i(24),i(2),i(9)],void 0===(o=function(e){"use strict";return e.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new e.Gain,this._neg=new e.Negate,this._param=this.input[1]=new e.Signal(t),this._param.chain(this._neg,this._sum)},e.extend(e.Subtract,e.Signal),e.Subtract.prototype.dispose=function(){return e.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},e.Subtract}.apply(e,n))||(t.exports=o)},function(n,o,r){"use strict";(function(t){var e,i;t.TONE_SILENCE_VERSION_LOGGING=!0,e=[r(34),r(11),r(0)],void 0===(i=function(n,t,e){var o=new window.AudioContext;return e.context.dispose(),e.setContext(o),p5.prototype.getAudioContext=function(){return o},p5.prototype.userStartAudio=function(t,e){var i=t;return t instanceof p5.Element?i=t.elt:t instanceof Array&&t[0]instanceof p5.Element&&(i=t.map(function(t){return t.elt})),n(o,i,e)},o}.apply(o,e))||(n.exports=i)}).call(this,r(33))},function(t,e,i){var n,o;n=[i(0)],void 0===(o=function(s){"use strict";return s.Emitter=function(){this._events={}},s.extend(s.Emitter),s.Emitter.prototype.on=function(t,e){for(var i=t.split(/\W+/),n=0;nthis.memory){var i=this.length-this.memory;this._timeline.splice(0,i)}return this},e.Timeline.prototype.remove=function(t){if(this._iterating)this._toRemove.push(t);else{var e=this._timeline.indexOf(t);-1!==e&&this._timeline.splice(e,1)}return this},e.Timeline.prototype.get=function(t){var e=this._search(t);return-1!==e?this._timeline[e]:null},e.Timeline.prototype.peek=function(){return this._timeline[0]},e.Timeline.prototype.shift=function(){return this._timeline.shift()},e.Timeline.prototype.getAfter=function(t){var e=this._search(t);return e+1=t&&(this._timeline=[]);return this},e.Timeline.prototype.cancelBefore=function(t){if(this._timeline.length){var e=this._search(t);0<=e&&(this._timeline=this._timeline.slice(e+1))}return this},e.Timeline.prototype._search=function(t){var e=0,i=this._timeline.length,n=i;if(0t)return o;r.time>t?n=o:r.time=t;)i--;return this._iterate(e,i+1),this},e.Timeline.prototype.forEachAtTime=function(e,i){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&i(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,n))||(t.exports=o)},function(t,e,i){var n,o;n=[i(0),i(3),i(2)],void 0===(o=function(t){"use strict";return t.Negate=function(){this._multiply=this.input=this.output=new t.Multiply(-1)},t.extend(t.Negate,t.SignalBase),t.Negate.prototype.dispose=function(){return t.prototype.dispose.call(this),this._multiply.dispose(),this._multiply=null,this},t.Negate}.apply(e,n))||(t.exports=o)},function(t,e,i){var n,o;n=[i(0),i(2),i(3),i(5)],void 0===(o=function(t){"use strict";return t.GreaterThanZero=function(){this._thresh=this.output=new t.WaveShaper(function(t){return t<=0?0:1},127),this._scale=this.input=new t.Multiply(1e4),this._scale.connect(this._thresh)},t.extend(t.GreaterThanZero,t.SignalBase),t.GreaterThanZero.prototype.dispose=function(){return t.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},t.GreaterThanZero}.apply(e,n))||(t.exports=o)},function(t,e,i){var n,o;n=[i(0),i(13),i(63),i(17),i(11)],void 0===(o=function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var i=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=i.time,this.isUndef(i.offset)||(this.ticks=i.offset),this.emit("start",i.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",i.time)):e===o.State.Paused&&this.emit("pause",i.time)}var n=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(n),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}.apply(e,n))||(t.exports=o)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var i=n(1),e=n(28),r=n(6).noteToFreq;p5.MonoSynth=function(){e.call(this),this.oscillator=new p5.Oscillator,this.env=new p5.Envelope,this.env.setRange(1,0),this.env.setExp(!0),this.setADSR(.02,.25,.05,.35),this.oscillator.disconnect(),this.oscillator.connect(this.output),this.env.disconnect(),this.env.setInput(this.output.gain),this.oscillator.output.gain.value=1,this.oscillator.start(),this.connect(),i.soundArray.push(this)},p5.MonoSynth.prototype=Object.create(p5.AudioVoice.prototype),p5.MonoSynth.prototype.play=function(t,e,i,n){this.triggerAttack(t,e,~~i),this.triggerRelease(~~i+(n||.15))},p5.MonoSynth.prototype.triggerAttack=function(t,e,i){i=~~i;var n=r(t),o=e||.1;this.oscillator.freq(n,0,i),this.env.ramp(this.output.gain,i,o)},p5.MonoSynth.prototype.triggerRelease=function(t){t=t||0;this.env.ramp(this.output.gain,t,0)},p5.MonoSynth.prototype.setADSR=function(t,e,i,n){this.env.setADSR(t,e,i,n)},Object.defineProperties(p5.MonoSynth.prototype,{attack:{get:function(){return this.env.aTime},set:function(t){this.env.setADSR(t,this.env.dTime,this.env.sPercent,this.env.rTime)}},decay:{get:function(){return this.env.dTime},set:function(t){this.env.setADSR(this.env.aTime,t,this.env.sPercent,this.env.rTime)}},sustain:{get:function(){return this.env.sPercent},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,t,this.env.rTime)}},release:{get:function(){return this.env.rTime},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,this.env.sPercent,t)}}}),p5.MonoSynth.prototype.amp=function(t,e){var i=e||0;return void 0!==t&&this.oscillator.amp(t,i),this.oscillator.amp().value},p5.MonoSynth.prototype.connect=function(t){var e=t||i.input;this.output.connect(e.input?e.input:e)},p5.MonoSynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},p5.MonoSynth.prototype.dispose=function(){e.prototype.dispose.apply(this),this.env&&this.env.dispose(),this.oscillator&&this.oscillator.dispose()}}.call(e,n,e,t))||(t.exports=i)},function(t,e,n){"use strict";var i;void 0===(i=function(){var i=n(1);return p5.AudioVoice=function(){this.ac=i.audiocontext,this.output=this.ac.createGain(),this.connect(),i.soundArray.push(this)},p5.AudioVoice.prototype.play=function(t,e,i,n){},p5.AudioVoice.prototype.triggerAttack=function(t,e,i){},p5.AudioVoice.prototype.triggerRelease=function(t){},p5.AudioVoice.prototype.amp=function(t,e){},p5.AudioVoice.prototype.connect=function(t){var e=t||i.input;this.output.connect(e.input?e.input:e)},p5.AudioVoice.prototype.disconnect=function(){this.output.disconnect()},p5.AudioVoice.prototype.dispose=function(){this.output&&(this.output.disconnect(),delete this.output)},p5.AudioVoice}.call(e,n,e,t))||(t.exports=i)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var c=i(1),h=i(13),l=i(6).noteToFreq;p5.PolySynth=function(t,e){this.audiovoices=[],this.notes={},this._newest=0,this._oldest=0,this.maxVoices=e||8,this.AudioVoice=void 0===t?p5.MonoSynth:t,this._voicesInUse=new h(0),this.output=c.audiocontext.createGain(),this.connect(),this._allocateVoices(),c.soundArray.push(this)},p5.PolySynth.prototype._allocateVoices=function(){for(var t=0;t= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n var output = outputs[0];\n\n for (var channel = 0; channel < output.length; ++channel) {\n var inputChannel = input[channel];\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannel);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannel);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannel);\n }\n }\n\n this.recordedSamples += output[0].length;\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'},function(t,e,i){"use strict";var n;function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}void 0===(n=function(t){var a=i(1).audiocontext;void 0!==a.createStereoPanner?(p5.Panner=function(t,e){this.stereoPanner=this.input=a.createStereoPanner(),t.connect(this.stereoPanner),this.stereoPanner.connect(e)},p5.Panner.prototype.pan=function(t,e){var i=e||0,n=a.currentTime+i;this.stereoPanner.pan.linearRampToValueAtTime(t,n)},p5.Panner.prototype.inputChannels=function(){},p5.Panner.prototype.connect=function(t){this.stereoPanner.connect(t)},p5.Panner.prototype.disconnect=function(){this.stereoPanner&&this.stereoPanner.disconnect()}):(p5.Panner=function(t,e,i){this.input=a.createGain(),t.connect(this.input),this.left=a.createGain(),this.right=a.createGain(),this.left.channelInterpretation="discrete",this.right.channelInterpretation="discrete",1this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var i=t||0,n=e||void 0;this.isPlaying()&&this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,i,n)},p5.SoundFile.prototype.channels=function(){return this.buffer.numberOfChannels},p5.SoundFile.prototype.sampleRate=function(){return this.buffer.sampleRate},p5.SoundFile.prototype.frames=function(){return this.buffer.length},p5.SoundFile.prototype.getPeaks=function(t){if(!this.buffer)throw"Cannot load peaks yet, buffer is not loaded";if(t=t||5*window.width,this.buffer){for(var e=this.buffer,i=e.length/t,n=~~(i/10)||1,o=e.numberOfChannels,r=new Float32Array(Math.round(t)),s=0;sr[p])&&(r[p]=h)}return r}},p5.SoundFile.prototype.reverseBuffer=function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/u.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var i=this.buffer.numberOfChannels,n=0;ne){var r=t[o],s=new c(r,o);i[o]=s,o+=6e3}o++}return i}function m(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180t[r].hi&&r++,o[r]=void 0!==o[r]?(o[r]+i[s])/2:i[s]}return o},p5.FFT.prototype.getOctaveBands=function(t,e){t=t||3;var i=[],n={lo:(e=e||15.625)/Math.pow(2,1/(2*t)),ctr:e,hi:e*Math.pow(2,1/(2*t))};i.push(n);for(var o=c.audiocontext.sampleRate/2;n.hi=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this._leftGain.gain.value=o,this._rightGain.gain.value=o,n&&(this._leftFilter.freq(n),this._rightFilter.freq(n))},p5.Delay.prototype.delayTime=function(t){"number"!=typeof t?(t.connect(this.leftDelay.delayTime),t.connect(this.rightDelay.delayTime)):(this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.leftDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime),this.rightDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime))},p5.Delay.prototype.feedback=function(t){if(t&&"number"!=typeof t)t.connect(this._leftGain.gain),t.connect(this._rightGain.gain);else{if(1<=t)throw new Error("Feedback value will force a positive feedback loop.");"number"==typeof t&&(this._leftGain.gain.value=t,this._rightGain.gain.value=t)}return this._leftGain.gain.value},p5.Delay.prototype.filter=function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)},p5.Delay.prototype.setType=function(t){switch(1===t&&(t="pingPong"),this._split.disconnect(),this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._split.connect(this.leftDelay,0),this._split.connect(this.rightDelay,1),t){case"pingPong":this._rightFilter.setType(this._leftFilter.biquad.type),this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.rightDelay),this._rightFilter.output.connect(this.leftDelay);break;default:this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.leftDelay),this._rightFilter.output.connect(this.rightDelay)}},p5.Delay.prototype.dispose=function(){i.prototype.dispose.apply(this),this._split.disconnect(),this._leftFilter.dispose(),this._rightFilter.dispose(),this._merge.disconnect(),this._leftGain.disconnect(),this._rightGain.disconnect(),this.leftDelay.disconnect(),this.rightDelay.disconnect(),this._split=void 0,this._leftFilter=void 0,this._rightFilter=void 0,this._merge=void 0,this._leftGain=void 0,this._rightGain=void 0,this.leftDelay=void 0,this.rightDelay=void 0}}.call(e,n,e,t))||(t.exports=i)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var u=i(10),e=i(4);p5.Reverb=function(){e.call(this),this._initConvolverNode(),this.input.gain.value=.5,this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse()},p5.Reverb.prototype=Object.create(e.prototype),p5.Reverb.prototype._initConvolverNode=function(){this.convolverNode=this.ac.createConvolver(),this.input.connect(this.convolverNode),this.convolverNode.connect(this.wet)},p5.Reverb.prototype._teardownConvolverNode=function(){this.convolverNode&&(this.convolverNode.disconnect(),delete this.convolverNode)},p5.Reverb.prototype._setBuffer=function(t){this._teardownConvolverNode(),this._initConvolverNode(),this.convolverNode.buffer=t},p5.Reverb.prototype.process=function(t,e,i,n){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),i&&(this._decay=i),n&&(this._reverse=n),o&&this._buildImpulse()},p5.Reverb.prototype.set=function(t,e,i){var n=!1;t&&(this._seconds=t,n=!0),e&&(this._decay=e),i&&(this._reverse=i),n&&this._buildImpulse()},p5.Reverb.prototype._buildImpulse=function(){var t,e,i=this.ac.sampleRate,n=i*this._seconds,o=this._decay,r=this.ac.createBuffer(2,n,i),s=r.getChannelData(0),a=r.getChannelData(1);for(e=0;e=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}p5.prototype.setBPM=function(t,e){for(var i in o=t,n.parts)n.parts[i]&&n.parts[i].setBPM(t,e)},p5.Phrase=function(t,e,i){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=i},p5.Part=function(t,e){this.length=t||0,this.partStep=0,this.phrases=[],this.isPlaying=!1,this.noLoop(),this.tatums=e||.0625,this.metro=new p5.Metro,this.metro._init(),this.metro.beatLength(this.tatums),this.metro.setBPM(o),n.parts.push(this),this.callback=function(){}},p5.Part.prototype.setBPM=function(t,e){this.metro.setBPM(t,e)},p5.Part.prototype.getBPM=function(){return this.metro.getBPM()},p5.Part.prototype.start=function(t){if(!this.isPlaying){this.isPlaying=!0,this.metro.resetSync(this);var e=t||0;this.metro.start(e)}},p5.Part.prototype.loop=function(t){this.looping=!0,this.onended=function(){this.partStep=0};var e=t||0;this.start(e)},p5.Part.prototype.noLoop=function(){this.looping=!1,this.onended=function(){this.stop()}},p5.Part.prototype.stop=function(t){this.partStep=0,this.pause(t)},p5.Part.prototype.pause=function(t){this.isPlaying=!1;var e=t||0;this.metro.stop(e)},p5.Part.prototype.addPhrase=function(t,e,i){var n;if(3===arguments.length)n=new p5.Phrase(t,e,i);else{if(!(t instanceof p5.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";n=t}this.phrases.push(n),n.sequence.length>this.length&&(this.length=n.sequence.length)},p5.Part.prototype.removePhrase=function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)},p5.Part.prototype.getPhrase=function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]},p5.Part.prototype.replaceSequence=function(t,e){for(var i in this.phrases)this.phrases[i].name===t&&(this.phrases[i].sequence=e)},p5.Part.prototype.incrementStep=function(t){this.partStepthis.cutoff&&e>this.threshold&&0t)this.cancelScheduledValues(t),this.linearRampToValueAtTime(e,t);else{var n=this._searchAfter(t);n&&(this.cancelScheduledValues(t),n.type===u.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):n.type===u.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},u.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,i){return this.setRampPoint(e),this.linearRampToValueAtTime(t,i),this},u.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,i){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,i),this},u.TimelineSignal.prototype._searchBefore=function(t){return this._events.get(t)},u.TimelineSignal.prototype._searchAfter=function(t){return this._events.getAfter(t)},u.TimelineSignal.prototype.getValueAtTime=function(t){t=this.toSeconds(t);var e=this._searchAfter(t),i=this._searchBefore(t),n=this._initial;if(null===i)n=this._initial;else if(i.type===u.TimelineSignal.Type.Target){var o,r=this._events.getBefore(i.time);o=null===r?this._initial:r.value,n=this._exponentialApproach(i.time,o,i.value,i.constant,t)}else n=i.type===u.TimelineSignal.Type.Curve?this._curveInterpolate(i.time,i.value,i.duration,t):null===e?i.value:e.type===u.TimelineSignal.Type.Linear?this._linearInterpolate(i.time,i.value,e.time,e.value,t):e.type===u.TimelineSignal.Type.Exponential?this._exponentialInterpolate(i.time,i.value,e.time,e.value,t):i.value;return n},u.TimelineSignal.prototype.connect=u.SignalBase.prototype.connect,u.TimelineSignal.prototype._exponentialApproach=function(t,e,i,n,o){return i+(e-i)*Math.exp(-(o-t)/n)},u.TimelineSignal.prototype._linearInterpolate=function(t,e,i,n,o){return e+(o-t)/(i-t)*(n-e)},u.TimelineSignal.prototype._exponentialInterpolate=function(t,e,i,n,o){return(e=Math.max(this._minOutput,e))*Math.pow(n/e,(o-t)/(i-t))},u.TimelineSignal.prototype._curveInterpolate=function(t,e,i,n){var o=e.length;if(t+i<=n)return e[o-1];if(n<=t)return e[0];var r=(n-t)/i,s=Math.floor((o-1)*r),a=Math.ceil((o-1)*r),u=e[s],p=e[a];return a===s?u:this._linearInterpolate(s,u,a,p,r*(o-1))},u.TimelineSignal.prototype.dispose=function(){u.Signal.prototype.dispose.call(this),u.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},u.TimelineSignal}.apply(e,n))||(t.exports=o)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var e=i(4);return p5.Filter=function(t){e.call(this),this.biquad=this.ac.createBiquadFilter(),this.input.connect(this.biquad),this.biquad.connect(this.wet),t&&this.setType(t),this._on=!0,this._untoggledType=this.biquad.type},p5.Filter.prototype=Object.create(e.prototype),p5.Filter.prototype.process=function(t,e,i,n){t.connect(this.input),this.set(e,i,n)},p5.Filter.prototype.set=function(t,e,i){t&&this.freq(t,i),e&&this.res(e,i)},p5.Filter.prototype.freq=function(t,e){var i=e||0;return t<=0&&(t=1),"number"==typeof t?(this.biquad.frequency.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.frequency.exponentialRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.frequency),this.biquad.frequency.value},p5.Filter.prototype.res=function(t,e){var i=e||0;return"number"==typeof t?(this.biquad.Q.value=t,this.biquad.Q.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.Q.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.Q),this.biquad.Q.value},p5.Filter.prototype.gain=function(t,e){var i=e||0;return"number"==typeof t?(this.biquad.gain.value=t,this.biquad.gain.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.gain.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.gain),this.biquad.gain.value},p5.Filter.prototype.toggle=function(){return this._on=!this._on,!0===this._on?this.biquad.type=this._untoggledType:!1===this._on&&(this.biquad.type="allpass"),this._on},p5.Filter.prototype.setType=function(t){this.biquad.type=t,this._untoggledType=this.biquad.type},p5.Filter.prototype.dispose=function(){e.prototype.dispose.apply(this),this.biquad&&(this.biquad.disconnect(),delete this.biquad)},p5.LowPass=function(){p5.Filter.call(this,"lowpass")},p5.LowPass.prototype=Object.create(p5.Filter.prototype),p5.HighPass=function(){p5.Filter.call(this,"highpass")},p5.HighPass.prototype=Object.create(p5.Filter.prototype),p5.BandPass=function(){p5.Filter.call(this,"bandpass")},p5.BandPass.prototype=Object.create(p5.Filter.prototype),p5.Filter}.call(e,i,e,t))||(t.exports=n)},function(t,e,i){var n,o;n=[i(0),i(7),i(25),i(2),i(9)],void 0===(o=function(e){"use strict";return e.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new e.Gain,this._neg=new e.Negate,this._param=this.input[1]=new e.Signal(t),this._param.chain(this._neg,this._sum)},e.extend(e.Subtract,e.Signal),e.Subtract.prototype.dispose=function(){return e.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},e.Subtract}.apply(e,n))||(t.exports=o)},function(n,o,r){"use strict";(function(t){var e,i;t.TONE_SILENCE_VERSION_LOGGING=!0,e=[r(35),r(11),r(0)],void 0===(i=function(n,t,e){var o=new window.AudioContext;return e.context.dispose(),e.setContext(o),p5.prototype.getAudioContext=function(){return o},p5.prototype.userStartAudio=function(t,e){var i=t;return t instanceof p5.Element?i=t.elt:t instanceof Array&&t[0]instanceof p5.Element&&(i=t.map(function(t){return t.elt})),n(o,i,e)},o}.apply(o,e))||(n.exports=i)}).call(this,r(34))},function(t,e,i){var n,o;n=[i(0)],void 0===(o=function(s){"use strict";return s.Emitter=function(){this._events={}},s.extend(s.Emitter),s.Emitter.prototype.on=function(t,e){for(var i=t.split(/\W+/),n=0;nthis.memory){var i=this.length-this.memory;this._timeline.splice(0,i)}return this},e.Timeline.prototype.remove=function(t){if(this._iterating)this._toRemove.push(t);else{var e=this._timeline.indexOf(t);-1!==e&&this._timeline.splice(e,1)}return this},e.Timeline.prototype.get=function(t){var e=this._search(t);return-1!==e?this._timeline[e]:null},e.Timeline.prototype.peek=function(){return this._timeline[0]},e.Timeline.prototype.shift=function(){return this._timeline.shift()},e.Timeline.prototype.getAfter=function(t){var e=this._search(t);return e+1=t&&(this._timeline=[]);return this},e.Timeline.prototype.cancelBefore=function(t){if(this._timeline.length){var e=this._search(t);0<=e&&(this._timeline=this._timeline.slice(e+1))}return this},e.Timeline.prototype._search=function(t){var e=0,i=this._timeline.length,n=i;if(0t)return o;r.time>t?n=o:r.time=t;)i--;return this._iterate(e,i+1),this},e.Timeline.prototype.forEachAtTime=function(e,i){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&i(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,n))||(t.exports=o)},function(t,e,i){var n,o;n=[i(0),i(3),i(2)],void 0===(o=function(t){"use strict";return t.Negate=function(){this._multiply=this.input=this.output=new t.Multiply(-1)},t.extend(t.Negate,t.SignalBase),t.Negate.prototype.dispose=function(){return t.prototype.dispose.call(this),this._multiply.dispose(),this._multiply=null,this},t.Negate}.apply(e,n))||(t.exports=o)},function(t,e,i){var n,o;n=[i(0),i(2),i(3),i(5)],void 0===(o=function(t){"use strict";return t.GreaterThanZero=function(){this._thresh=this.output=new t.WaveShaper(function(t){return t<=0?0:1},127),this._scale=this.input=new t.Multiply(1e4),this._scale.connect(this._thresh)},t.extend(t.GreaterThanZero,t.SignalBase),t.GreaterThanZero.prototype.dispose=function(){return t.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},t.GreaterThanZero}.apply(e,n))||(t.exports=o)},function(t,e,i){var n,o;n=[i(0),i(13),i(65),i(17),i(11)],void 0===(o=function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var i=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=i.time,this.isUndef(i.offset)||(this.ticks=i.offset),this.emit("start",i.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",i.time)):e===o.State.Paused&&this.emit("pause",i.time)}var n=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(n),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}.apply(e,n))||(t.exports=o)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var i=n(1),e=n(29),r=n(6).noteToFreq;p5.MonoSynth=function(){e.call(this),this.oscillator=new p5.Oscillator,this.env=new p5.Envelope,this.env.setRange(1,0),this.env.setExp(!0),this.setADSR(.02,.25,.05,.35),this.oscillator.disconnect(),this.oscillator.connect(this.output),this.env.disconnect(),this.env.setInput(this.output.gain),this.oscillator.output.gain.value=1,this.oscillator.start(),this.connect(),i.soundArray.push(this)},p5.MonoSynth.prototype=Object.create(p5.AudioVoice.prototype),p5.MonoSynth.prototype.play=function(t,e,i,n){this.triggerAttack(t,e,~~i),this.triggerRelease(~~i+(n||.15))},p5.MonoSynth.prototype.triggerAttack=function(t,e,i){i=~~i;var n=r(t),o=e||.1;this.oscillator.freq(n,0,i),this.env.ramp(this.output.gain,i,o)},p5.MonoSynth.prototype.triggerRelease=function(t){t=t||0;this.env.ramp(this.output.gain,t,0)},p5.MonoSynth.prototype.setADSR=function(t,e,i,n){this.env.setADSR(t,e,i,n)},Object.defineProperties(p5.MonoSynth.prototype,{attack:{get:function(){return this.env.aTime},set:function(t){this.env.setADSR(t,this.env.dTime,this.env.sPercent,this.env.rTime)}},decay:{get:function(){return this.env.dTime},set:function(t){this.env.setADSR(this.env.aTime,t,this.env.sPercent,this.env.rTime)}},sustain:{get:function(){return this.env.sPercent},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,t,this.env.rTime)}},release:{get:function(){return this.env.rTime},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,this.env.sPercent,t)}}}),p5.MonoSynth.prototype.amp=function(t,e){var i=e||0;return void 0!==t&&this.oscillator.amp(t,i),this.oscillator.amp().value},p5.MonoSynth.prototype.connect=function(t){var e=t||i.input;this.output.connect(e.input?e.input:e)},p5.MonoSynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},p5.MonoSynth.prototype.dispose=function(){e.prototype.dispose.apply(this),this.env&&this.env.dispose(),this.oscillator&&this.oscillator.dispose()}}.call(e,n,e,t))||(t.exports=i)},function(t,e,n){"use strict";var i;void 0===(i=function(){var i=n(1);return p5.AudioVoice=function(){this.ac=i.audiocontext,this.output=this.ac.createGain(),this.connect(),i.soundArray.push(this)},p5.AudioVoice.prototype.play=function(t,e,i,n){},p5.AudioVoice.prototype.triggerAttack=function(t,e,i){},p5.AudioVoice.prototype.triggerRelease=function(t){},p5.AudioVoice.prototype.amp=function(t,e){},p5.AudioVoice.prototype.connect=function(t){var e=t||i.input;this.output.connect(e.input?e.input:e)},p5.AudioVoice.prototype.disconnect=function(){this.output.disconnect()},p5.AudioVoice.prototype.dispose=function(){this.output&&(this.output.disconnect(),delete this.output)},p5.AudioVoice}.call(e,n,e,t))||(t.exports=i)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var c=i(1),h=i(13),l=i(6).noteToFreq;p5.PolySynth=function(t,e){this.audiovoices=[],this.notes={},this._newest=0,this._oldest=0,this.maxVoices=e||8,this.AudioVoice=void 0===t?p5.MonoSynth:t,this._voicesInUse=new h(0),this.output=c.audiocontext.createGain(),this.connect(),this._allocateVoices(),c.soundArray.push(this)},p5.PolySynth.prototype._allocateVoices=function(){for(var t=0;t= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n var output = outputs[0];\n\n for (var channel = 0; channel < output.length; ++channel) {\n var inputChannel = input[channel];\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannel);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannel);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannel);\n }\n }\n\n this.recordedSamples += output[0].length;\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'},function(t,e,i){"use strict";i.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import processor name via preval.require so that it\'s available as a value at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor() {\n _classCallCheck(this, SoundFileProcessor);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).apply(this, arguments));\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0];\n var inputChannel = input[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'},function(t,e,i){"use strict";var n;function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}void 0===(n=function(t){var a=i(1).audiocontext;void 0!==a.createStereoPanner?(p5.Panner=function(t,e){this.stereoPanner=this.input=a.createStereoPanner(),t.connect(this.stereoPanner),this.stereoPanner.connect(e)},p5.Panner.prototype.pan=function(t,e){var i=e||0,n=a.currentTime+i;this.stereoPanner.pan.linearRampToValueAtTime(t,n)},p5.Panner.prototype.inputChannels=function(){},p5.Panner.prototype.connect=function(t){this.stereoPanner.connect(t)},p5.Panner.prototype.disconnect=function(){this.stereoPanner&&this.stereoPanner.disconnect()}):(p5.Panner=function(t,e,i){this.input=a.createGain(),t.connect(this.input),this.left=a.createGain(),this.right=a.createGain(),this.left.channelInterpretation="discrete",this.right.channelInterpretation="discrete",1this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var i=t||0,n=e||void 0;this.isPlaying()&&this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,i,n)},p5.SoundFile.prototype.channels=function(){return this.buffer.numberOfChannels},p5.SoundFile.prototype.sampleRate=function(){return this.buffer.sampleRate},p5.SoundFile.prototype.frames=function(){return this.buffer.length},p5.SoundFile.prototype.getPeaks=function(t){if(!this.buffer)throw"Cannot load peaks yet, buffer is not loaded";if(t=t||5*window.width,this.buffer){for(var e=this.buffer,i=e.length/t,n=~~(i/10)||1,o=e.numberOfChannels,r=new Float32Array(Math.round(t)),s=0;sr[u])&&(r[u]=h)}return r}},p5.SoundFile.prototype.reverseBuffer=function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/p.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var i=this.buffer.numberOfChannels,n=0;ne){var r=t[o],s=new c(r,o);i[o]=s,o+=6e3}o++}return i}function m(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180t[r].hi&&r++,o[r]=void 0!==o[r]?(o[r]+i[s])/2:i[s]}return o},p5.FFT.prototype.getOctaveBands=function(t,e){t=t||3;var i=[],n={lo:(e=e||15.625)/Math.pow(2,1/(2*t)),ctr:e,hi:e*Math.pow(2,1/(2*t))};i.push(n);for(var o=c.audiocontext.sampleRate/2;n.hi=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this._leftGain.gain.value=o,this._rightGain.gain.value=o,n&&(this._leftFilter.freq(n),this._rightFilter.freq(n))},p5.Delay.prototype.delayTime=function(t){"number"!=typeof t?(t.connect(this.leftDelay.delayTime),t.connect(this.rightDelay.delayTime)):(this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.leftDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime),this.rightDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime))},p5.Delay.prototype.feedback=function(t){if(t&&"number"!=typeof t)t.connect(this._leftGain.gain),t.connect(this._rightGain.gain);else{if(1<=t)throw new Error("Feedback value will force a positive feedback loop.");"number"==typeof t&&(this._leftGain.gain.value=t,this._rightGain.gain.value=t)}return this._leftGain.gain.value},p5.Delay.prototype.filter=function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)},p5.Delay.prototype.setType=function(t){switch(1===t&&(t="pingPong"),this._split.disconnect(),this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._split.connect(this.leftDelay,0),this._split.connect(this.rightDelay,1),t){case"pingPong":this._rightFilter.setType(this._leftFilter.biquad.type),this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.rightDelay),this._rightFilter.output.connect(this.leftDelay);break;default:this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.leftDelay),this._rightFilter.output.connect(this.rightDelay)}},p5.Delay.prototype.dispose=function(){i.prototype.dispose.apply(this),this._split.disconnect(),this._leftFilter.dispose(),this._rightFilter.dispose(),this._merge.disconnect(),this._leftGain.disconnect(),this._rightGain.disconnect(),this.leftDelay.disconnect(),this.rightDelay.disconnect(),this._split=void 0,this._leftFilter=void 0,this._rightFilter=void 0,this._merge=void 0,this._leftGain=void 0,this._rightGain=void 0,this.leftDelay=void 0,this.rightDelay=void 0}}.call(e,n,e,t))||(t.exports=i)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var p=i(10),e=i(4);p5.Reverb=function(){e.call(this),this._initConvolverNode(),this.input.gain.value=.5,this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse()},p5.Reverb.prototype=Object.create(e.prototype),p5.Reverb.prototype._initConvolverNode=function(){this.convolverNode=this.ac.createConvolver(),this.input.connect(this.convolverNode),this.convolverNode.connect(this.wet)},p5.Reverb.prototype._teardownConvolverNode=function(){this.convolverNode&&(this.convolverNode.disconnect(),delete this.convolverNode)},p5.Reverb.prototype._setBuffer=function(t){this._teardownConvolverNode(),this._initConvolverNode(),this.convolverNode.buffer=t},p5.Reverb.prototype.process=function(t,e,i,n){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),i&&(this._decay=i),n&&(this._reverse=n),o&&this._buildImpulse()},p5.Reverb.prototype.set=function(t,e,i){var n=!1;t&&(this._seconds=t,n=!0),e&&(this._decay=e),i&&(this._reverse=i),n&&this._buildImpulse()},p5.Reverb.prototype._buildImpulse=function(){var t,e,i=this.ac.sampleRate,n=i*this._seconds,o=this._decay,r=this.ac.createBuffer(2,n,i),s=r.getChannelData(0),a=r.getChannelData(1);for(e=0;e=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}p5.prototype.setBPM=function(t,e){for(var i in o=t,n.parts)n.parts[i]&&n.parts[i].setBPM(t,e)},p5.Phrase=function(t,e,i){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=i},p5.Part=function(t,e){this.length=t||0,this.partStep=0,this.phrases=[],this.isPlaying=!1,this.noLoop(),this.tatums=e||.0625,this.metro=new p5.Metro,this.metro._init(),this.metro.beatLength(this.tatums),this.metro.setBPM(o),n.parts.push(this),this.callback=function(){}},p5.Part.prototype.setBPM=function(t,e){this.metro.setBPM(t,e)},p5.Part.prototype.getBPM=function(){return this.metro.getBPM()},p5.Part.prototype.start=function(t){if(!this.isPlaying){this.isPlaying=!0,this.metro.resetSync(this);var e=t||0;this.metro.start(e)}},p5.Part.prototype.loop=function(t){this.looping=!0,this.onended=function(){this.partStep=0};var e=t||0;this.start(e)},p5.Part.prototype.noLoop=function(){this.looping=!1,this.onended=function(){this.stop()}},p5.Part.prototype.stop=function(t){this.partStep=0,this.pause(t)},p5.Part.prototype.pause=function(t){this.isPlaying=!1;var e=t||0;this.metro.stop(e)},p5.Part.prototype.addPhrase=function(t,e,i){var n;if(3===arguments.length)n=new p5.Phrase(t,e,i);else{if(!(t instanceof p5.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";n=t}this.phrases.push(n),n.sequence.length>this.length&&(this.length=n.sequence.length)},p5.Part.prototype.removePhrase=function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)},p5.Part.prototype.getPhrase=function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]},p5.Part.prototype.replaceSequence=function(t,e){for(var i in this.phrases)this.phrases[i].name===t&&(this.phrases[i].sequence=e)},p5.Part.prototype.incrementStep=function(t){this.partStepthis.cutoff&&e>this.threshold&&0 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\t/**\n\t\t * the output node(s)\n\t\t * @type {GainNode|Array}\n\t\t */\n\t\tif (this.isUndef(outputs) || outputs === 1){\n\t\t\tthis.output = this.context.createGain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t/**\n\t * Set the parameters at once. Either pass in an\n\t * object mapping parameters to values, or to set a\n\t * single parameter, by passing in a string and value.\n\t * The last argument is an optional ramp time which \n\t * will ramp any signal values to their destination value\n\t * over the duration of the rampTime.\n\t * @param {Object|string} params\n\t * @param {number=} value\n\t * @param {Time=} rampTime\n\t * @returns {Tone} this\n\t * @example\n\t * //set values using an object\n\t * filter.set({\n\t * \t\"frequency\" : 300,\n\t * \t\"type\" : highpass\n\t * });\n\t * @example\n\t * filter.set(\"type\", \"highpass\");\n\t * @example\n\t * //ramp to the value 220 over 3 seconds. \n\t * oscillator.set({\n\t * \t\"frequency\" : 220\n\t * }, 3);\n\t */\n\tTone.prototype.set = function(params, value, rampTime){\n\t\tif (this.isObject(params)){\n\t\t\trampTime = value;\n\t\t} else if (this.isString(params)){\n\t\t\tvar tmpObj = {};\n\t\t\ttmpObj[params] = value;\n\t\t\tparams = tmpObj;\n\t\t}\n\n\t\tparamLoop:\n\t\tfor (var attr in params){\n\t\t\tvalue = params[attr];\n\t\t\tvar parent = this;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var i = 0; i < attrSplit.length - 1; i++){\n\t\t\t\t\tparent = parent[attrSplit[i]];\n\t\t\t\t\tif (parent instanceof Tone) {\n\t\t\t\t\t\tattrSplit.splice(0,i+1);\n\t\t\t\t\t\tvar innerParam = attrSplit.join(\".\");\n\t\t\t\t\t\tparent.set(innerParam, value);\n\t\t\t\t\t\tcontinue paramLoop;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isUndef(param)){\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((Tone.Signal && param instanceof Tone.Signal) || \n\t\t\t\t\t(Tone.Param && param instanceof Tone.Param)){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tif (this.isUndef(rampTime)){\n\t\t\t\t\t\tparam.value = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparam.rampTo(value, rampTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tparam.value = value;\n\t\t\t\t}\t\t\t\t\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tparam.set(value);\n\t\t\t} else if (param !== value){\n\t\t\t\tparent[attr] = value;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the object's attributes. Given no arguments get\n\t * will return all available object properties and their corresponding\n\t * values. Pass in a single attribute to retrieve or an array\n\t * of attributes. The attribute strings can also include a \".\"\n\t * to access deeper properties.\n\t * @example\n\t * osc.get();\n\t * //returns {\"type\" : \"sine\", \"frequency\" : 440, ...etc}\n\t * @example\n\t * osc.get(\"type\");\n\t * //returns { \"type\" : \"sine\"}\n\t * @example\n\t * //use dot notation to access deep properties\n\t * synth.get([\"envelope.attack\", \"envelope.release\"]);\n\t * //returns {\"envelope\" : {\"attack\" : 0.2, \"release\" : 0.4}}\n\t * @param {Array=|string|undefined} params the parameters to get, otherwise will return \n\t * \t\t\t\t\t all available.\n\t * @returns {Object}\n\t */\n\tTone.prototype.get = function(params){\n\t\tif (this.isUndef(params)){\n\t\t\tparams = this._collectDefaults(this.constructor);\n\t\t} else if (this.isString(params)){\n\t\t\tparams = [params];\n\t\t} \n\t\tvar ret = {};\n\t\tfor (var i = 0; i < params.length; i++){\n\t\t\tvar attr = params[i];\n\t\t\tvar parent = this;\n\t\t\tvar subRet = ret;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var j = 0; j < attrSplit.length - 1; j++){\n\t\t\t\t\tvar subAttr = attrSplit[j];\n\t\t\t\t\tsubRet[subAttr] = subRet[subAttr] || {};\n\t\t\t\t\tsubRet = subRet[subAttr];\n\t\t\t\t\tparent = parent[subAttr];\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isObject(params[attr])){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (Tone.Signal && param instanceof Tone.Signal){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (Tone.Param && param instanceof Tone.Param){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (!this.isFunction(param) && !this.isUndef(param)){\n\t\t\t\tsubRet[attr] = param;\n\t\t\t} \n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * collect all of the default attributes in one\n\t * @private\n\t * @param {function} constr the constructor to find the defaults from\n\t * @return {Array} all of the attributes which belong to the class\n\t */\n\tTone.prototype._collectDefaults = function(constr){\n\t\tvar ret = [];\n\t\tif (!this.isUndef(constr.defaults)){\n\t\t\tret = Object.keys(constr.defaults);\n\t\t}\n\t\tif (!this.isUndef(constr._super)){\n\t\t\tvar superDefs = this._collectDefaults(constr._super);\n\t\t\t//filter out repeats\n\t\t\tfor (var i = 0; i < superDefs.length; i++){\n\t\t\t\tif (ret.indexOf(superDefs[i]) === -1){\n\t\t\t\t\tret.push(superDefs[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * @returns {string} returns the name of the class as a string\n\t */\n\tTone.prototype.toString = function(){\n\t\tfor (var className in Tone){\n\t\t\tvar isLetter = className[0].match(/^[A-Z]$/);\n\t\t\tvar sameConstructor = Tone[className] === this.constructor;\n\t\t\tif (this.isFunction(Tone[className]) && isLetter && sameConstructor){\n\t\t\t\treturn className;\n\t\t\t}\n\t\t}\n\t\treturn \"Tone\";\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCLASS VARS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The number of inputs feeding into the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfInputs\", {\n\t\tget : function(){\n\t\t\tif (this.input){\n\t\t\t\tif (this.isArray(this.input)){\n\t\t\t\t\treturn this.input.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The number of outputs coming out of the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfOutputs\", {\n\t\tget : function(){\n\t\t\tif (this.output){\n\t\t\t\tif (this.isArray(this.output)){\n\t\t\t\t\treturn this.output.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\t\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONNECTIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * disconnect and dispose\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.dispose = function(){\n\t\tif (!this.isUndef(this.input)){\n\t\t\tif (this.input instanceof AudioNode){\n\t\t\t\tthis.input.disconnect();\n\t\t\t} \n\t\t\tthis.input = null;\n\t\t}\n\t\tif (!this.isUndef(this.output)){\n\t\t\tif (this.output instanceof AudioNode){\n\t\t\t\tthis.output.disconnect();\n\t\t\t} \n\t\t\tthis.output = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode\n\t * @param {Tone | AudioParam | AudioNode} unit \n\t * @param {number} [outputNum=0] optionally which output to connect from\n\t * @param {number} [inputNum=0] optionally which input to connect to\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connect = function(unit, outputNum, inputNum){\n\t\tif (Array.isArray(this.output)){\n\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\tthis.output[outputNum].connect(unit, 0, inputNum);\n\t\t} else {\n\t\t\tthis.output.connect(unit, outputNum, inputNum);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * disconnect the output\n\t * @param {Number|AudioNode} output Either the output index to disconnect\n\t * if the output is an array, or the\n\t * node to disconnect from.\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.disconnect = function(destination, outputNum, inputNum){\n\t\tif (this.isArray(this.output)){\n\t\t\tif (this.isNumber(destination)){\n\t\t\t\tthis.output[destination].disconnect();\n\t\t\t} else {\n\t\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\t\tthis.output[outputNum].disconnect(destination, 0, inputNum);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.output.disconnect.apply(this.output, arguments);\n\t\t}\n\t};\n\n\t/**\n\t * connect together all of the arguments in series\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connectSeries = function(){\n\t\tif (arguments.length > 1){\n\t\t\tvar currentUnit = arguments[0];\n\t\t\tfor (var i = 1; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Connect the output of this node to the rest of the nodes in series.\n\t * @example\n\t * //connect a node to an effect, panVol and then to the master output\n\t * node.chain(effect, panVol, Tone.Master);\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.chain = function(){\n\t\tif (arguments.length > 0){\n\t\t\tvar currentUnit = this;\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of this node to the rest of the nodes in parallel.\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.fan = function(){\n\t\tif (arguments.length > 0){\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tthis.connect(arguments[i]);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t//give native nodes chain and fan methods\n\tAudioNode.prototype.chain = Tone.prototype.chain;\n\tAudioNode.prototype.fan = Tone.prototype.fan;\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUTILITIES / HELPERS / MATHS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * If the `given` parameter is undefined, use the `fallback`. \n\t * If both `given` and `fallback` are object literals, it will\n\t * return a deep copy which includes all of the parameters from both \n\t * objects. If a parameter is undefined in given, it will return\n\t * the fallback property. \n\t *
\n\t * WARNING: if object is self referential, it will go into an an \n\t * infinite recursive loop.\n\t * \n\t * @param {*} given \n\t * @param {*} fallback \n\t * @return {*} \n\t */\n\tTone.prototype.defaultArg = function(given, fallback){\n\t\tif (this.isObject(given) && this.isObject(fallback)){\n\t\t\tvar ret = {};\n\t\t\t//make a deep copy of the given object\n\t\t\tfor (var givenProp in given) {\n\t\t\t\tret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);\n\t\t\t}\n\t\t\tfor (var fallbackProp in fallback) {\n\t\t\t\tret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn this.isUndef(given) ? fallback : given;\n\t\t}\n\t};\n\n\t/**\n\t * returns the args as an options object with given arguments\n\t * mapped to the names provided. \n\t *\n\t * if the args given is an array containing only one object, it is assumed\n\t * that that's already the options object and will just return it. \n\t * \n\t * @param {Array} values the 'arguments' object of the function\n\t * @param {Array} keys the names of the arguments as they\n\t * should appear in the options object\n\t * @param {Object=} defaults optional defaults to mixin to the returned \n\t * options object \n\t * @return {Object} the options object with the names mapped to the arguments\n\t */\n\tTone.prototype.optionsObject = function(values, keys, defaults){\n\t\tvar options = {};\n\t\tif (values.length === 1 && this.isObject(values[0])){\n\t\t\toptions = values[0];\n\t\t} else {\n\t\t\tfor (var i = 0; i < keys.length; i++){\n\t\t\t\toptions[keys[i]] = values[i];\n\t\t\t}\n\t\t}\n\t\tif (!this.isUndef(defaults)){\n\t\t\treturn this.defaultArg(options, defaults);\n\t\t} else {\n\t\t\treturn options;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// TYPE CHECKING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * test if the arg is undefined\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is undefined\n\t * @function\n\t */\n\tTone.prototype.isUndef = function(val){\n\t\treturn typeof val === \"undefined\";\n\t};\n\n\t/**\n\t * test if the arg is a function\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a function\n\t * @function\n\t */\n\tTone.prototype.isFunction = function(val){\n\t\treturn typeof val === \"function\";\n\t};\n\n\t/**\n\t * Test if the argument is a number.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a number\n\t */\n\tTone.prototype.isNumber = function(arg){\n\t\treturn (typeof arg === \"number\");\n\t};\n\n\t/**\n\t * Test if the given argument is an object literal (i.e. `{}`);\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an object literal.\n\t */\n\tTone.prototype.isObject = function(arg){\n\t\treturn (Object.prototype.toString.call(arg) === \"[object Object]\" && arg.constructor === Object);\n\t};\n\n\t/**\n\t * Test if the argument is a boolean.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a boolean\n\t */\n\tTone.prototype.isBoolean = function(arg){\n\t\treturn (typeof arg === \"boolean\");\n\t};\n\n\t/**\n\t * Test if the argument is an Array\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an array\n\t */\n\tTone.prototype.isArray = function(arg){\n\t\treturn (Array.isArray(arg));\n\t};\n\n\t/**\n\t * Test if the argument is a string.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a string\n\t */\n\tTone.prototype.isString = function(arg){\n\t\treturn (typeof arg === \"string\");\n\t};\n\n \t/**\n\t * An empty function.\n\t * @static\n\t */\n\tTone.noOp = function(){};\n\n\t/**\n\t * Make the property not writable. Internal use only. \n\t * @private\n\t * @param {string} property the property to make not writable\n\t */\n\tTone.prototype._readOnly = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._readOnly(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: false,\n\t\t\t\tenumerable : true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Make an attribute writeable. Interal use only. \n\t * @private\n\t * @param {string} property the property to make writable\n\t */\n\tTone.prototype._writable = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._writable(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Possible play states. \n\t * @enum {string}\n\t */\n\tTone.State = {\n\t\tStarted : \"started\",\n\t\tStopped : \"stopped\",\n\t\tPaused : \"paused\",\n \t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Equal power gain scale. Good for cross-fading.\n\t * @param {NormalRange} percent (0-1)\n\t * @return {Number} output gain (0-1)\n\t */\n\tTone.prototype.equalPowerScale = function(percent){\n\t\tvar piFactor = 0.5 * Math.PI;\n\t\treturn Math.sin(percent * piFactor);\n\t};\n\n\t/**\n\t * Convert decibels into gain.\n\t * @param {Decibels} db\n\t * @return {Number} \n\t */\n\tTone.prototype.dbToGain = function(db) {\n\t\treturn Math.pow(2, db / 6);\n\t};\n\n\t/**\n\t * Convert gain to decibels.\n\t * @param {Number} gain (0-1)\n\t * @return {Decibels} \n\t */\n\tTone.prototype.gainToDb = function(gain) {\n\t\treturn 20 * (Math.log(gain) / Math.LN10);\n\t};\n\n\t/**\n\t * Convert an interval (in semitones) to a frequency ratio.\n\t * @param {Interval} interval the number of semitones above the base note\n\t * @return {number} the frequency ratio\n\t * @example\n\t * tone.intervalToFrequencyRatio(0); // 1\n\t * tone.intervalToFrequencyRatio(12); // 2\n\t * tone.intervalToFrequencyRatio(-12); // 0.5\n\t */\n\tTone.prototype.intervalToFrequencyRatio = function(interval){\n\t\treturn Math.pow(2,(interval/12));\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTIMING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t */\n\tTone.prototype.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t * @static\n\t */\n\tTone.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tINHERITANCE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * have a child inherit all of Tone's (or a parent's) prototype\n\t * to inherit the parent's properties, make sure to call \n\t * Parent.call(this) in the child's constructor\n\t *\n\t * based on closure library's inherit function\n\t *\n\t * @static\n\t * @param {function} \tchild \n\t * @param {function=} parent (optional) parent to inherit from\n\t * if no parent is supplied, the child\n\t * will inherit from Tone\n\t */\n\tTone.extend = function(child, parent){\n\t\tif (Tone.prototype.isUndef(parent)){\n\t\t\tparent = Tone;\n\t\t}\n\t\tfunction TempConstructor(){}\n\t\tTempConstructor.prototype = parent.prototype;\n\t\tchild.prototype = new TempConstructor();\n\t\t/** @override */\n\t\tchild.prototype.constructor = child;\n\t\tchild._super = parent;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONTEXT\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The private audio context shared by all Tone Nodes. \n\t * @private\n\t * @type {Tone.Context|undefined}\n\t */\n\tvar audioContext;\n\n\t/**\n\t * A static pointer to the audio context accessible as Tone.context. \n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone\n\t */\n\tObject.defineProperty(Tone, \"context\", {\n\t\tget : function(){\n\t\t\treturn audioContext;\n\t\t},\n\t\tset : function(context){\n\t\t\tif (Tone.Context && context instanceof Tone.Context){\n\t\t\t\taudioContext = context;\n\t\t\t} else {\n\t\t\t\taudioContext = new Tone.Context(context);\n\t\t\t}\n\t\t\t//initialize the new audio context\n\t\t\tif (Tone.Context){\n\t\t\t\tTone.Context.emit(\"init\", audioContext);\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The AudioContext\n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"context\", {\n\t\tget : function(){\n\t\t\treturn Tone.context;\n\t\t}\n\t});\n\n\t/**\n\t * Tone automatically creates a context on init, but if you are working\n\t * with other libraries which also create an AudioContext, it can be\n\t * useful to set your own. If you are going to set your own context, \n\t * be sure to do it at the start of your code, before creating any objects.\n\t * @static\n\t * @param {AudioContext} ctx The new audio context to set\n\t */\n\tTone.setContext = function(ctx){\n\t\tTone.context = ctx;\n\t};\n\n\t/**\n\t * The number of seconds of 1 processing block (128 samples)\n\t * @type {Number}\n\t * @name blockTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"blockTime\", {\n\t\tget : function(){\n\t\t\treturn 128 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * The duration in seconds of one sample.\n\t * @type {Number}\n\t * @name sampleTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"sampleTime\", {\n\t\tget : function(){\n\t\t\treturn 1 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * Whether or not all the technologies that Tone.js relies on are supported by the current browser. \n\t * @type {Boolean}\n\t * @name supported\n\t * @memberOf Tone\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone, \"supported\", {\n\t\tget : function(){\n\t\t\tvar hasAudioContext = window.hasOwnProperty(\"AudioContext\") || window.hasOwnProperty(\"webkitAudioContext\");\n\t\t\tvar hasPromises = window.hasOwnProperty(\"Promise\");\n\t\t\tvar hasWorkers = window.hasOwnProperty(\"Worker\");\n\t\t\treturn hasAudioContext && hasPromises && hasWorkers;\n\t\t}\n\t});\n\n\tTone.version = \"r10\";\n\n\t// allow optional silencing of this log\n\tif (!window.TONE_SILENCE_VERSION_LOGGING) {\n\t\tconsole.log(\"%c * Tone.js \" + Tone.version + \" * \", \"background: #000; color: #fff\");\n\t}\n\n\treturn Tone;\n});\n","'use strict';\r\n\r\n\r\ndefine(['audiocontext'], function (audiocontext) {\r\n /**\r\n * Master contains AudioContext and the master sound output.\r\n * @for p5\r\n */\r\n var Master = function() {\r\n this.input = audiocontext.createGain();\r\n this.output = audiocontext.createGain();\r\n\r\n //put a hard limiter on the output\r\n this.limiter = audiocontext.createDynamicsCompressor();\r\n this.limiter.threshold.value = -3;\r\n this.limiter.ratio.value = 20;\r\n this.limiter.knee.value = 1;\r\n\r\n this.audiocontext = audiocontext;\r\n\r\n this.output.disconnect();\r\n\r\n // connect input to limiter\r\n this.input.connect(this.limiter);\r\n\r\n // connect limiter to output\r\n this.limiter.connect(this.output);\r\n\r\n // meter is just for global Amplitude / FFT analysis\r\n this.meter = audiocontext.createGain();\r\n this.fftMeter = audiocontext.createGain();\r\n this.output.connect(this.meter);\r\n this.output.connect(this.fftMeter);\r\n\r\n // connect output to destination\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // an array of all sounds in the sketch\r\n this.soundArray = [];\r\n // an array of all musical parts in the sketch\r\n this.parts = [];\r\n\r\n // file extensions to search for\r\n this.extensions = [];\r\n };\r\n\r\n // create a single instance of the p5Sound / master output for use within this sketch\r\n var p5sound = new Master();\r\n\r\n /**\r\n * Returns a number representing the master amplitude (volume) for sound\r\n * in this sketch.\r\n *\r\n * @method getMasterVolume\r\n * @return {Number} Master amplitude (volume) for sound in this sketch.\r\n * Should be between 0.0 (silence) and 1.0.\r\n */\r\n p5.prototype.getMasterVolume = function() {\r\n return p5sound.output.gain.value;\r\n };\r\n\r\n /**\r\n *
Scale the output of all sound in this sketch
\r\n * Scaled between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n *
How This Works: When you load the p5.sound module, it\r\n * creates a single instance of p5sound. All sound objects in this\r\n * module output to p5sound before reaching your computer's output.\r\n * So if you change the amplitude of p5sound, it impacts all of the\r\n * sound in this module.
\r\n *\r\n *
If no value is provided, returns a Web Audio API Gain Node
\r\n *\r\n * @method masterVolume\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.prototype.masterVolume = function(vol, rampTime, tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = p5sound.output.gain.value;\r\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(p5sound.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return p5sound.output.gain;\r\n }\r\n };\r\n\r\n /**\r\n * `p5.soundOut` is the p5.sound master output. It sends output to\r\n * the destination of this window's web audio context. It contains\r\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\r\n * and Gain Nodes for .input and .output.\r\n *\r\n * @property {Object} soundOut\r\n */\r\n p5.prototype.soundOut = p5.soundOut = p5sound;\r\n\r\n /**\r\n * a silent connection to the DesinationNode\r\n * which will ensure that anything connected to it\r\n * will not be garbage collected\r\n *\r\n * @private\r\n */\r\n p5.soundOut._silentNode = p5sound.audiocontext.createGain();\r\n p5.soundOut._silentNode.gain.value = 0;\r\n p5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\r\n\r\n\r\n return p5sound;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/type/Type\", \"Tone/core/Param\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal is an audio-rate value. Tone.Signal is a core component of the library.\n\t * Unlike a number, Signals can be scheduled with sample-level accuracy. Tone.Signal\n\t * has all of the methods available to native Web Audio \n\t * [AudioParam](http://webaudio.github.io/web-audio-api/#the-audioparam-interface)\n\t * as well as additional conveniences. Read more about working with signals \n\t * [here](https://github.com/Tonejs/Tone.js/wiki/Signals).\n\t *\n\t * @constructor\n\t * @extends {Tone.Param}\n\t * @param {Number|AudioParam} [value] Initial value of the signal. If an AudioParam\n\t * is passed in, that parameter will be wrapped\n\t * and controlled by the Signal. \n\t * @param {string} [units=Number] unit The units the signal is in. \n\t * @example\n\t * var signal = new Tone.Signal(10);\n\t */\n\tTone.Signal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\n\t\t/**\n\t\t * The node where the constant signal value is scaled.\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.output = this._gain = this.context.createGain();\n\n\t\toptions.param = this._gain.gain;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The node where the value is set.\n\t\t * @type {Tone.Param}\n\t\t * @private\n\t\t */\n\t\tthis.input = this._param = this._gain.gain;\n\n\t\t//connect the const output to the node output\n\t\tthis.context.getConstant(1).chain(this._gain);\n\t};\n\n\tTone.extend(Tone.Signal, Tone.Param);\n\n\t/**\n\t * The default values\n\t * @type {Object}\n\t * @static\n\t * @const\n\t */\n\tTone.Signal.defaults = {\n\t\t\"value\" : 0,\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t * @method\n\t */\n\tTone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\t/**\n\t * dispose and disconnect\n\t * @returns {Tone.Signal} this\n\t */\n\tTone.Signal.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tthis._gain.disconnect();\n\t\tthis._gain = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Signal;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Multiply two incoming signals. Or, if a number is given in the constructor, \n\t * multiplies the incoming signal by that value. \n\t *\n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value Constant value to multiple. If no value is provided,\n\t * it will return the product of the first and second inputs\n\t * @example\n\t * var mult = new Tone.Multiply();\n\t * var sigA = new Tone.Signal(3);\n\t * var sigB = new Tone.Signal(4);\n\t * sigA.connect(mult, 0, 0);\n\t * sigB.connect(mult, 0, 1);\n\t * //output of mult is 12.\n\t * @example\n\t * var mult = new Tone.Multiply(10);\n\t * var sig = new Tone.Signal(2).connect(mult);\n\t * //the output of mult is 20. \n\t */\n\tTone.Multiply = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the input node is the same as the output node\n\t\t * it is also the GainNode which handles the scaling of incoming signal\n\t\t * \n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._mult = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * the scaling parameter\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[1] = this.output.gain;\n\t\t\n\t\tthis._param.value = this.defaultArg(value, 0);\n\t};\n\n\tTone.extend(Tone.Multiply, Tone.Signal);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Multiply} this\n\t */\n\tTone.Multiply.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._mult.dispose();\n\t\tthis._mult = null;\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Multiply;\n});\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var CrossFade = require('Tone/component/CrossFade');\r\n\r\n /**\r\n * Effect is a base class for audio effects in p5. \r\n * This module handles the nodes and methods that are\r\n * common and useful for current and future effects.\r\n *\r\n *\r\n * This class is extended by p5.Distortion,\r\n * p5.Compressor,\r\n * p5.Delay,\r\n * p5.Filter,\r\n * p5.Reverb.\r\n *\r\n * @class p5.Effect\r\n * @constructor\r\n *\r\n * @param {Object} [ac] Reference to the audio context of the p5 object\r\n * @param {AudioNode} [input] Gain Node effect wrapper\r\n * @param {AudioNode} [output] Gain Node effect wrapper\r\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\r\n * @param {AudioNode} [wet] Effects that extend this class should connect\r\n * to the wet signal to this gain node, so that dry and wet\r\n * signals are mixed properly.\r\n */\r\n p5.Effect = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n /**\r\n *\tThe p5.Effect class is built\r\n * \tusing Tone.js CrossFade\r\n * \t@private\r\n */\r\n\r\n this._drywet = new CrossFade(1);\r\n\r\n /**\r\n *\tIn classes that extend\r\n *\tp5.Effect, connect effect nodes\r\n *\tto the wet parameter\r\n */\r\n this.wet = this.ac.createGain();\r\n\r\n this.input.connect(this._drywet.a);\r\n this.wet.connect(this._drywet.b);\r\n this._drywet.connect(this.output);\r\n\r\n this.connect();\r\n\r\n //Add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the output volume of the filter.\r\n *\r\n * @method amp\r\n * @for p5.Effect\r\n * @param {Number} [vol] amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts until rampTime\r\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\r\n */\r\n p5.Effect.prototype.amp = function(vol, rampTime, tFromNow){\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + .001);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + .001);\r\n };\r\n\r\n /**\r\n * Link effects together in a chain\r\n * Example usage: filter.chain(reverb, delay, panner);\r\n * May be used with an open-ended number of arguments\r\n *\r\n * @method chain\r\n * @for p5.Effect\r\n * @param {Object} [arguments] Chain together multiple sound objects\r\n */\r\n p5.Effect.prototype.chain = function(){\r\n if (arguments.length>0){\r\n this.connect(arguments[0]);\r\n for(var i=1;i\r\n * var notes = [60, 64, 67, 72];\r\n * var i = 0;\r\n *\r\n * function setup() {\r\n * osc = new p5.Oscillator('Triangle');\r\n * osc.start();\r\n * frameRate(1);\r\n * }\r\n *\r\n * function draw() {\r\n * var freq = midiToFreq(notes[i]);\r\n * osc.freq(freq);\r\n * i++;\r\n * if (i >= notes.length){\r\n * i = 0;\r\n * }\r\n * }\r\n * \r\n */\r\n var midiToFreq = p5.prototype.midiToFreq = function(m) {\r\n return 440 * Math.pow(2, (m-69)/12.0);\r\n };\r\n\r\n // This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\r\n var noteToFreq = function(note) {\r\n if (typeof note !== 'string') {\r\n return note;\r\n }\r\n var wholeNotes = {A:21, B:23, C:24, D:26, E:28, F:29, G:31};\r\n var value = wholeNotes[ note[0].toUpperCase() ];\r\n var octave = ~~note.slice(-1);\r\n value += 12 * (octave -1);\r\n\r\n switch(note[1]) {\r\n case '#':\r\n value += 1;\r\n break;\r\n case 'b':\r\n value -= 1;\r\n break;\r\n default:\r\n break;\r\n }\r\n return midiToFreq(value);\r\n };\r\n\r\n /**\r\n * List the SoundFile formats that you will include. LoadSound\r\n * will search your directory for these extensions, and will pick\r\n * a format that is compatable with the client's web browser.\r\n * Here is a free online file\r\n * converter.\r\n *\r\n * @method soundFormats\r\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\r\n * @example\r\n *
\r\n * function preload() {\r\n * // set the global sound formats\r\n * soundFormats('mp3', 'ogg');\r\n *\r\n * // load either beatbox.mp3, or .ogg, depending on browser\r\n * mySound = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * mySound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.soundFormats = function() {\r\n // reset extensions array\r\n p5sound.extensions = [];\r\n // add extensions\r\n for (var i = 0; i < arguments.length; i++) {\r\n arguments[i] = arguments[i].toLowerCase();\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\r\n p5sound.extensions.push(arguments[i]);\r\n } else {\r\n throw arguments[i] + ' is not a valid sound format!';\r\n }\r\n }\r\n };\r\n\r\n p5.prototype.disposeSound = function() {\r\n for (var i = 0; i < p5sound.soundArray.length; i++) {\r\n p5sound.soundArray[i].dispose();\r\n }\r\n };\r\n\r\n // register removeSound to dispose of p5sound SoundFiles, Convolvers,\r\n // Oscillators etc when sketch ends\r\n p5.prototype.registerMethod('remove', p5.prototype.disposeSound);\r\n\r\n p5.prototype._checkFileFormats = function(paths) {\r\n var path;\r\n // if path is a single string, check to see if extension is provided\r\n if (typeof paths === 'string') {\r\n path = paths;\r\n // see if extension is provided\r\n var extTest = path.split('.').pop();\r\n // if an extension is provided...\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\r\n if (p5.prototype.isFileSupported(extTest)) {\r\n path = path;\r\n }\r\n else {\r\n var pathSplit = path.split('.');\r\n var pathCore = pathSplit[pathSplit.length - 1];\r\n for (var i = 0; i 1) {\r\n rightChannel = audioBuffer.getChannelData(1);\r\n } else {\r\n rightChannel = leftChannel;\r\n }\r\n\r\n var interleaved = interleave(leftChannel, rightChannel);\r\n\r\n // create the buffer and view to create the .WAV file\r\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\r\n var view = new window.DataView(buffer);\r\n\r\n // write the WAV container,\r\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\r\n\r\n // RIFF chunk descriptor\r\n writeUTFBytes(view, 0, 'RIFF');\r\n view.setUint32(4, 36 + interleaved.length * 2, true);\r\n writeUTFBytes(view, 8, 'WAVE');\r\n // FMT sub-chunk\r\n writeUTFBytes(view, 12, 'fmt ');\r\n view.setUint32(16, 16, true);\r\n view.setUint16(20, 1, true);\r\n // stereo (2 channels)\r\n view.setUint16(22, 2, true);\r\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\r\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\r\n view.setUint16(32, 4, true);\r\n view.setUint16(34, 16, true);\r\n // data sub-chunk\r\n writeUTFBytes(view, 36, 'data');\r\n view.setUint32(40, interleaved.length * 2, true);\r\n\r\n // write the PCM samples\r\n var lng = interleaved.length;\r\n var index = 44;\r\n var volume = 1;\r\n for (var i = 0; i < lng; i++) {\r\n view.setInt16(index, interleaved[i] * (0x7FFF * volume), true);\r\n index += 2;\r\n }\r\n\r\n return view;\r\n }\r\n\r\n // helper methods to save waves\r\n function interleave(leftChannel, rightChannel) {\r\n var length = leftChannel.length + rightChannel.length;\r\n var result = new Float32Array(length);\r\n\r\n var inputIndex = 0;\r\n\r\n for (var index = 0; index < length;) {\r\n result[index++] = leftChannel[inputIndex];\r\n result[index++] = rightChannel[inputIndex];\r\n inputIndex++;\r\n }\r\n return result;\r\n }\r\n\r\n function writeUTFBytes(view, offset, string) {\r\n var lng = string.length;\r\n for (var i = 0; i < lng; i++) {\r\n view.setUint8(offset + i, string.charCodeAt(i));\r\n }\r\n }\r\n\r\n return {\r\n convertToWav: convertToWav,\r\n midiToFreq: midiToFreq,\r\n noteToFreq: noteToFreq\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Add a signal and a number or two signals. When no value is\n\t * passed into the constructor, Tone.Add will sum input[0]\n\t * and input[1]. If a value is passed into the constructor, \n\t * the it will be added to the input.\n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value If no value is provided, Tone.Add will sum the first\n\t * and second inputs. \n\t * @example\n\t * var signal = new Tone.Signal(2);\n\t * var add = new Tone.Add(2);\n\t * signal.connect(add);\n\t * //the output of add equals 4\n\t * @example\n\t * //if constructed with no arguments\n\t * //it will add the first and second inputs\n\t * var add = new Tone.Add();\n\t * var sig0 = new Tone.Signal(3).connect(add, 0, 0);\n\t * var sig1 = new Tone.Signal(4).connect(add, 0, 1);\n\t * //the output of add equals 7. \n\t */\n\tTone.Add = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.connect(this._sum);\n\t};\n\n\tTone.extend(Tone.Add, Tone.Signal);\n\t\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Add} this\n\t */\n\tTone.Add.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._sum.dispose();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Add;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\", \"Tone/type/Frequency\", \"Tone/type/TransportTime\", \"Tone/core/Context\"],\nfunction (Tone) {\t\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTYPES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Units which a value can take on.\n\t * @enum {String}\n\t */\n\tTone.Type = {\n\t\t/** \n\t\t * Default units\n\t\t * @typedef {Default}\n\t\t */\n\t\tDefault : \"number\",\n\t\t/**\n\t\t * Time can be described in a number of ways. Read more [Time](https://github.com/Tonejs/Tone.js/wiki/Time).\n\t\t *\n\t\t *
\n\t\t *
Numbers, which will be taken literally as the time (in seconds).
\n\t\t *
Notation, (\"4n\", \"8t\") describes time in BPM and time signature relative values.
\n\t\t *
TransportTime, (\"4:3:2\") will also provide tempo and time signature relative times \n\t\t * in the form BARS:QUARTERS:SIXTEENTHS.
\n\t\t *
Frequency, (\"8hz\") is converted to the length of the cycle in seconds.
\n\t\t *
Now-Relative, (\"+1\") prefix any of the above with \"+\" and it will be interpreted as \n\t\t * \"the current time plus whatever expression follows\".
\n\t\t *
Expressions, (\"3:0 + 2 - (1m / 7)\") any of the above can also be combined \n\t\t * into a mathematical expression which will be evaluated to compute the desired time.
\n\t\t *
No Argument, for methods which accept time, no argument will be interpreted as \n\t\t * \"now\" (i.e. the currentTime).
\n\t\t *
\n\t\t * \n\t\t * @typedef {Time}\n\t\t */\n\t\tTime : \"time\",\n\t\t/**\n\t\t * Frequency can be described similar to time, except ultimately the\n\t\t * values are converted to frequency instead of seconds. A number\n\t\t * is taken literally as the value in hertz. Additionally any of the \n\t\t * Time encodings can be used. Note names in the form\n\t\t * of NOTE OCTAVE (i.e. C4) are also accepted and converted to their\n\t\t * frequency value. \n\t\t * @typedef {Frequency}\n\t\t */\n\t\tFrequency : \"frequency\",\n\t\t/**\n\t\t * TransportTime describes a position along the Transport's timeline. It is\n\t\t * similar to Time in that it uses all the same encodings, but TransportTime specifically\n\t\t * pertains to the Transport's timeline, which is startable, stoppable, loopable, and seekable. \n\t\t * [Read more](https://github.com/Tonejs/Tone.js/wiki/TransportTime)\n\t\t * @typedef {TransportTime}\n\t\t */\n\t\tTransportTime : \"transportTime\",\n\t\t/** \n\t\t * Ticks are the basic subunit of the Transport. They are\n\t\t * the smallest unit of time that the Transport supports.\n\t\t * @typedef {Ticks}\n\t\t */\n\t\tTicks : \"ticks\",\n\t\t/** \n\t\t * Normal values are within the range [0, 1].\n\t\t * @typedef {NormalRange}\n\t\t */\n\t\tNormalRange : \"normalRange\",\n\t\t/** \n\t\t * AudioRange values are between [-1, 1].\n\t\t * @typedef {AudioRange}\n\t\t */\n\t\tAudioRange : \"audioRange\",\n\t\t/** \n\t\t * Decibels are a logarithmic unit of measurement which is useful for volume\n\t\t * because of the logarithmic way that we perceive loudness. 0 decibels \n\t\t * means no change in volume. -10db is approximately half as loud and 10db \n\t\t * is twice is loud. \n\t\t * @typedef {Decibels}\n\t\t */\n\t\tDecibels : \"db\",\n\t\t/** \n\t\t * Half-step note increments, i.e. 12 is an octave above the root. and 1 is a half-step up.\n\t\t * @typedef {Interval}\n\t\t */\n\t\tInterval : \"interval\",\n\t\t/** \n\t\t * Beats per minute. \n\t\t * @typedef {BPM}\n\t\t */\n\t\tBPM : \"bpm\",\n\t\t/** \n\t\t * The value must be greater than or equal to 0.\n\t\t * @typedef {Positive}\n\t\t */\n\t\tPositive : \"positive\",\n\t\t/** \n\t\t * A cent is a hundredth of a semitone. \n\t\t * @typedef {Cents}\n\t\t */\n\t\tCents : \"cents\",\n\t\t/** \n\t\t * Angle between 0 and 360. \n\t\t * @typedef {Degrees}\n\t\t */\n\t\tDegrees : \"degrees\",\n\t\t/** \n\t\t * A number representing a midi note.\n\t\t * @typedef {MIDI}\n\t\t */\n\t\tMIDI : \"midi\",\n\t\t/** \n\t\t * A colon-separated representation of time in the form of\n\t\t * Bars:Beats:Sixteenths. \n\t\t * @typedef {BarsBeatsSixteenths}\n\t\t */\n\t\tBarsBeatsSixteenths : \"barsBeatsSixteenths\",\n\t\t/** \n\t\t * Sampling is the reduction of a continuous signal to a discrete signal.\n\t\t * Audio is typically sampled 44100 times per second. \n\t\t * @typedef {Samples}\n\t\t */\n\t\tSamples : \"samples\",\n\t\t/** \n\t\t * Hertz are a frequency representation defined as one cycle per second.\n\t\t * @typedef {Hertz}\n\t\t */\n\t\tHertz : \"hertz\",\n\t\t/** \n\t\t * A frequency represented by a letter name, \n\t\t * accidental and octave. This system is known as\n\t\t * [Scientific Pitch Notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation).\n\t\t * @typedef {Note}\n\t\t */\n\t\tNote : \"note\",\n\t\t/** \n\t\t * One millisecond is a thousandth of a second. \n\t\t * @typedef {Milliseconds}\n\t\t */\n\t\tMilliseconds : \"milliseconds\",\n\t\t/** \n\t\t * Seconds are the time unit of the AudioContext. In the end, \n\t\t * all values need to be evaluated to seconds. \n\t\t * @typedef {Seconds}\n\t\t */\n\t\tSeconds : \"seconds\",\n\t\t/** \n\t\t * A string representing a duration relative to a measure. \n\t\t *
\n\t\t * \t
\"4n\" = quarter note
\n\t\t * \t
\"2m\" = two measures
\n\t\t * \t
\"8t\" = eighth-note triplet
\n\t\t *
\n\t\t * @typedef {Notation}\n\t\t */\n\t\tNotation : \"notation\",\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// AUGMENT TONE's PROTOTYPE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert Time into seconds.\n\t * \n\t * Unlike the method which it overrides, this takes into account \n\t * transporttime and musical notation.\n\t *\n\t * Time : 1.40\n\t * Notation: 4n|1m|2t\n\t * Now Relative: +3n\n\t * Math: 3n+16n or even complicated expressions ((3n*2)/6 + 1)\n\t *\n\t * @param {Time} time \n\t * @return {Seconds} \n\t */\n\tTone.prototype.toSeconds = function(time){\n\t\tif (this.isNumber(time)){\n\t\t\treturn time;\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn this.now();\t\t\t\n\t\t} else if (this.isString(time)){\n\t\t\treturn (new Tone.Time(time)).toSeconds();\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toSeconds();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a frequency representation into a number.\n\t * @param {Frequency} freq \n\t * @return {Hertz} the frequency in hertz\n\t */\n\tTone.prototype.toFrequency = function(freq){\n\t\tif (this.isNumber(freq)){\n\t\t\treturn freq;\n\t\t} else if (this.isString(freq) || this.isUndef(freq)){\n\t\t\treturn (new Tone.Frequency(freq)).valueOf();\n\t\t} else if (freq instanceof Tone.TimeBase){\n\t\t\treturn freq.toFrequency();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a time representation into ticks.\n\t * @param {Time} time\n\t * @return {Ticks} the time in ticks\n\t */\n\tTone.prototype.toTicks = function(time){\n\t\tif (this.isNumber(time) || this.isString(time)){\n\t\t\treturn (new Tone.TransportTime(time)).toTicks();\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn Tone.Transport.ticks;\t\t\t\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toTicks();\n\t\t}\n\t};\n\n\treturn Tone;\n});","define([\"Tone/core/Tone\", \"Tone/core/Param\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * createGain shim\n\t * @private\n\t */\n\tif (window.GainNode && !AudioContext.prototype.createGain){\n\t\tAudioContext.prototype.createGain = AudioContext.prototype.createGainNode;\n\t}\n\n\t/**\n\t * @class A thin wrapper around the Native Web Audio GainNode.\n\t * The GainNode is a basic building block of the Web Audio\n\t * API and is useful for routing audio and adjusting gains. \n\t * @extends {Tone}\n\t * @param {Number=} gain The initial gain of the GainNode\n\t * @param {Tone.Type=} units The units of the gain parameter. \n\t */\n\tTone.Gain = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"gain\", \"units\"], Tone.Gain.defaults);\n\n\t\t/**\n\t\t * The GainNode\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.input = this.output = this._gainNode = this.context.createGain();\n\n\t\t/**\n\t\t * The gain parameter of the gain node.\n\t\t * @type {Tone.Param}\n\t\t * @signal\n\t\t */\n\t\tthis.gain = new Tone.Param({\n\t\t\t\"param\" : this._gainNode.gain, \n\t\t\t\"units\" : options.units,\n\t\t\t\"value\" : options.gain,\n\t\t\t\"convert\" : options.convert\n\t\t});\n\t\tthis._readOnly(\"gain\");\n\t};\n\n\tTone.extend(Tone.Gain);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Gain.defaults = {\n\t\t\"gain\" : 1,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Gain} this\n\t */\n\tTone.Gain.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._gainNode.disconnect();\n\t\tthis._gainNode = null;\n\t\tthis._writable(\"gain\");\n\t\tthis.gain.dispose();\n\t\tthis.gain = null;\n\t};\n\n\t//STATIC///////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Create input and outputs for this object.\n\t * @param {Number} input The number of inputs\n\t * @param {Number=} outputs The number of outputs\n\t * @return {Tone} this\n\t * @internal\n\t */\n\tTone.prototype.createInsOuts = function(inputs, outputs){\n\n\t\tif (inputs === 1){\n\t\t\tthis.input = new Tone.Gain();\n\t\t} else if (inputs > 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\tif (outputs === 1){\n\t\t\tthis.output = new Tone.Gain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\n\treturn Tone.Gain;\n});","'use strict';\r\n\r\ndefine(function () {\r\n /*\r\n Helper function to generate an error\r\n with a custom stack trace that points to the sketch\r\n and removes other parts of the stack trace.\r\n\r\n @private\r\n @class customError\r\n @constructor\r\n @param {String} name custom error name\r\n @param {String} errorTrace custom error trace\r\n @param {String} failedPath path to the file that failed to load\r\n @property {String} name custom error name\r\n @property {String} message custom error message\r\n @property {String} stack trace the error back to a line in the user's sketch.\r\n Note: this edits out stack trace within p5.js and p5.sound.\r\n @property {String} originalStack unedited, original stack trace\r\n @property {String} failedPath path to the file that failed to load\r\n @return {Error} returns a custom Error object\r\n */\r\n var CustomError = function(name, errorTrace, failedPath) {\r\n var err = new Error();\r\n var tempStack, splitStack;\r\n\r\n err.name = name;\r\n err.originalStack = err.stack + errorTrace;\r\n tempStack = err.stack + errorTrace;\r\n err.failedPath = failedPath;\r\n\r\n // only print the part of the stack trace that refers to the user code:\r\n var splitStack = tempStack.split('\\n');\r\n splitStack = splitStack.filter(function(ln) {\r\n return !ln.match(/(p5.|native code|globalInit)/g);\r\n });\r\n err.stack = splitStack.join('\\n');\r\n\r\n return err; // TODO: is this really a constructor?\r\n };\r\n\r\n return CustomError;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Emitter\"], function (Tone) {\n\n\t/**\n\t * shim\n\t * @private\n\t */\n\tif (!window.hasOwnProperty(\"AudioContext\") && window.hasOwnProperty(\"webkitAudioContext\")){\n\t\twindow.AudioContext = window.webkitAudioContext;\n\t}\n\n\t/**\n\t * @class Wrapper around the native AudioContext.\n\t * @extends {Tone.Emitter}\n\t * @param {AudioContext=} context optionally pass in a context\n\t */\n\tTone.Context = function(context){\n\n\t\tTone.Emitter.call(this);\n\n\t\tif (!context){\n\t\t\tcontext = new window.AudioContext();\n\t\t}\n\t\tthis._context = context;\n\t\t// extend all of the methods\n\t\tfor (var prop in this._context){\n\t\t\tthis._defineProperty(this._context, prop);\n\t\t}\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// WORKER\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\t/**\n\t\t * The default latency hint\n\t\t * @type {String}\n\t\t * @private\n\t\t */\n\t\tthis._latencyHint = \"interactive\";\n\n\t\t/**\n\t\t * The amount of time events are scheduled\n\t\t * into the future\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._lookAhead = 0.1;\n\n\t\t/**\n\t\t * How often the update look runs\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._updateInterval = this._lookAhead/3;\n\n\t\t/**\n\t\t * A reference to the actual computed update interval\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._computedUpdateInterval = 0;\n\n\t\t/**\n\t\t * The web worker which is used to update Tone.Clock\n\t\t * @private\n\t\t * @type {WebWorker}\n\t\t */\n\t\tthis._worker = this._createWorker();\n\n\t\t/**\n\t\t * An object containing all of the constants AudioBufferSourceNodes\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t\tthis._constants = {};\n\n\t};\n\n\tTone.extend(Tone.Context, Tone.Emitter);\n\tTone.Emitter.mixin(Tone.Context);\n\n\t/**\n\t * Define a property on this Tone.Context. \n\t * This is used to extend the native AudioContext\n\t * @param {AudioContext} context\n\t * @param {String} prop \n\t * @private\n\t */\n\tTone.Context.prototype._defineProperty = function(context, prop){\n\t\tif (this.isUndef(this[prop])){\n\t\t\tObject.defineProperty(this, prop, {\n\t\t\t\tget : function(){\n\t\t\t\t\tif (typeof context[prop] === \"function\"){\n\t\t\t\t\t\treturn context[prop].bind(context);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn context[prop];\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tset : function(val){\n\t\t\t\t\tcontext[prop] = val;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * The current audio context time\n\t * @return {Number}\n\t */\n\tTone.Context.prototype.now = function(){\n\t\treturn this._context.currentTime;\n\t};\n\n\t/**\n\t * Generate a web worker\n\t * @return {WebWorker}\n\t * @private\n\t */\n\tTone.Context.prototype._createWorker = function(){\n\t\t\n\t\t//URL Shim\n\t\twindow.URL = window.URL || window.webkitURL;\n\n\t\tvar blob = new Blob([\n\t\t\t//the initial timeout time\n\t\t\t\"var timeoutTime = \"+(this._updateInterval * 1000).toFixed(1)+\";\" +\n\t\t\t//onmessage callback\n\t\t\t\"self.onmessage = function(msg){\" +\n\t\t\t\"\ttimeoutTime = parseInt(msg.data);\" + \n\t\t\t\"};\" + \n\t\t\t//the tick function which posts a message\n\t\t\t//and schedules a new tick\n\t\t\t\"function tick(){\" +\n\t\t\t\"\tsetTimeout(tick, timeoutTime);\" +\n\t\t\t\"\tself.postMessage('tick');\" +\n\t\t\t\"}\" +\n\t\t\t//call tick initially\n\t\t\t\"tick();\"\n\t\t]);\n\t\tvar blobUrl = URL.createObjectURL(blob);\n\t\tvar worker = new Worker(blobUrl);\n\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\t// tick the clock\n\t\t\tthis.emit(\"tick\");\n\t\t}.bind(this));\n\n\t\t//lag compensation\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\tvar now = this.now();\n\t\t\tif (this.isNumber(this._lastUpdate)){\n\t\t\t\tvar diff = now - this._lastUpdate;\n\t\t\t\tthis._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);\n\t\t\t}\n\t\t\tthis._lastUpdate = now;\n\t\t}.bind(this));\n\n\t\treturn worker;\n\t};\n\n\t/**\n\t * Generate a looped buffer at some constant value.\n\t * @param {Number} val\n\t * @return {BufferSourceNode}\n\t */\n\tTone.Context.prototype.getConstant = function(val){\n\t\tif (this._constants[val]){\n\t\t\treturn this._constants[val];\n\t\t} else {\n\t\t\tvar buffer = this._context.createBuffer(1, 128, this._context.sampleRate);\n\t\t\tvar arr = buffer.getChannelData(0);\n\t\t\tfor (var i = 0; i < arr.length; i++){\n\t\t\t\tarr[i] = val;\n\t\t\t}\n\t\t\tvar constant = this._context.createBufferSource();\n\t\t\tconstant.channelCount = 1;\n\t\t\tconstant.channelCountMode = \"explicit\";\n\t\t\tconstant.buffer = buffer;\n\t\t\tconstant.loop = true;\n\t\t\tconstant.start(0);\n\t\t\tthis._constants[val] = constant;\n\t\t\treturn constant;\n\t\t}\n\t};\n\n\t/**\n\t * This is the time that the clock is falling behind\n\t * the scheduled update interval. The Context automatically\n\t * adjusts for the lag and schedules further in advance.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lag\n\t * @static\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lag\", {\n\t\tget : function(){\n\t\t\tvar diff = this._computedUpdateInterval - this._updateInterval;\n\t\t\tdiff = Math.max(diff, 0);\n\t\t\treturn diff;\n\t\t}\n\t});\n\n\t/**\n\t * The amount of time in advance that events are scheduled.\n\t * The lookAhead will adjust slightly in response to the \n\t * measured update time to try to avoid clicks.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lookAhead\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lookAhead\", {\n\t\tget : function(){\n\t\t\treturn this._lookAhead;\n\t\t},\n\t\tset : function(lA){\n\t\t\tthis._lookAhead = lA;\n\t\t}\n\t});\n\n\t/**\n\t * How often the Web Worker callback is invoked.\n\t * This number corresponds to how responsive the scheduling\n\t * can be. Context.updateInterval + Context.lookAhead gives you the\n\t * total latency between scheduling an event and hearing it.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name updateInterval\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"updateInterval\", {\n\t\tget : function(){\n\t\t\treturn this._updateInterval;\n\t\t},\n\t\tset : function(interval){\n\t\t\tthis._updateInterval = Math.max(interval, Tone.prototype.blockTime);\n\t\t\tthis._worker.postMessage(Math.max(interval * 1000, 1));\n\t\t}\n\t});\n\n\t/**\n\t * The type of playback, which affects tradeoffs between audio \n\t * output latency and responsiveness. \n\t * \n\t * In addition to setting the value in seconds, the latencyHint also\n\t * accepts the strings \"interactive\" (prioritizes low latency), \n\t * \"playback\" (prioritizes sustained playback), \"balanced\" (balances\n\t * latency and performance), and \"fastest\" (lowest latency, might glitch more often). \n\t * @type {String|Seconds}\n\t * @memberOf Tone.Context#\n\t * @name latencyHint\n\t * @static\n\t * @example\n\t * //set the lookAhead to 0.3 seconds\n\t * Tone.context.latencyHint = 0.3;\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"latencyHint\", {\n\t\tget : function(){\n\t\t\treturn this._latencyHint;\n\t\t},\n\t\tset : function(hint){\n\t\t\tvar lookAhead = hint;\n\t\t\tthis._latencyHint = hint;\n\t\t\tif (this.isString(hint)){\n\t\t\t\tswitch(hint){\n\t\t\t\t\tcase \"interactive\" :\n\t\t\t\t\t\tlookAhead = 0.1;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"playback\" :\n\t\t\t\t\t\tlookAhead = 0.8;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"balanced\" :\n\t\t\t\t\t\tlookAhead = 0.25;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"fastest\" :\n\t\t\t\t\t\tlookAhead = 0.01;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.lookAhead = lookAhead;\n\t\t\tthis.updateInterval = lookAhead/3;\n\t\t}\n\t});\n\n\t/**\n\t * Shim all connect/disconnect and some deprecated methods which are still in\n\t * some older implementations.\n\t * @private\n\t */\n\tfunction shimConnect(){\n\n\t\tvar nativeConnect = AudioNode.prototype.connect;\n\t\tvar nativeDisconnect = AudioNode.prototype.disconnect;\n\n\t\t//replace the old connect method\n\t\tfunction toneConnect(B, outNum, inNum){\n\t\t\tif (B.input){\n\t\t\t\tif (Array.isArray(B.input)){\n\t\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\t\tinNum = 0;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connect(B.input[inNum]);\n\t\t\t\t} else {\n\t\t\t\t\tthis.connect(B.input, outNum, inNum);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (B instanceof AudioNode){\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum, inNum);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error connecting to node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//replace the old disconnect method\n\t\tfunction toneDisconnect(B, outNum, inNum){\n\t\t\tif (B && B.input && Array.isArray(B.input)){\n\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\tinNum = 0;\n\t\t\t\t}\n\t\t\t\tthis.disconnect(B.input[inNum], outNum, inNum);\n\t\t\t} else if (B && B.input){\n\t\t\t\tthis.disconnect(B.input, outNum, inNum);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tnativeDisconnect.apply(this, arguments);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error disconnecting node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (AudioNode.prototype.connect !== toneConnect){\n\t\t\tAudioNode.prototype.connect = toneConnect;\n\t\t\tAudioNode.prototype.disconnect = toneDisconnect;\n\t\t}\n\t}\n\n\t// set the audio context initially\n\tif (Tone.supported){\n\t\tshimConnect();\n\t\tTone.context = new Tone.Context();\n\t} else {\n\t\tconsole.warn(\"This browser does not support Tone.js\");\n\t}\n\n\treturn Tone.Context;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\t\n\t/**\n\t * @class Performs a linear scaling on an input signal.\n\t * Scales a NormalRange input to between\n\t * outputMin and outputMax.\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {number} [outputMin=0] The output value when the input is 0. \n\t * @param {number} [outputMax=1]\tThe output value when the input is 1. \n\t * @example\n\t * var scale = new Tone.Scale(50, 100);\n\t * var signal = new Tone.Signal(0.5).connect(scale);\n\t * //the output of scale equals 75\n\t */\n\tTone.Scale = function(outputMin, outputMax){\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMin = this.defaultArg(outputMin, 0);\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMax = this.defaultArg(outputMax, 1);\n\n\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(1);\n\t\t\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Add}\n\t\t * @private\n\t\t */\n\t\tthis._add = this.output = new Tone.Add(0);\n\n\t\tthis._scale.connect(this._add);\n\t\tthis._setRange();\n\t};\n\n\tTone.extend(Tone.Scale, Tone.SignalBase);\n\n\t/**\n\t * The minimum output value. This number is output when \n\t * the value input value is 0. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name min\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"min\", {\n\t\tget : function(){\n\t\t\treturn this._outputMin;\n\t\t},\n\t\tset : function(min){\n\t\t\tthis._outputMin = min;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * The maximum output value. This number is output when \n\t * the value input value is 1. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name max\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"max\", {\n\t\tget : function(){\n\t\t\treturn this._outputMax;\n\t\t},\n\t\tset : function(max){\n\t\t\tthis._outputMax = max;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * set the values\n\t * @private\n\t */\n\tTone.Scale.prototype._setRange = function() {\n\t\tthis._add.value = this._outputMin;\n\t\tthis._scale.value = this._outputMax - this._outputMin;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Scale} this\n\t */\n\tTone.Scale.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._add.dispose();\n\t\tthis._add = null;\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Scale;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Timeline\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal which adds the method getValueAtTime. \n\t * Code and inspiration from https://github.com/jsantell/web-audio-automation-timeline\n\t * @extends {Tone.Param}\n\t * @param {Number=} value The initial value of the signal\n\t * @param {String=} units The conversion units of the signal.\n\t */\n\tTone.TimelineSignal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\t\t\n\t\t/**\n\t\t * The scheduled events\n\t\t * @type {Tone.Timeline}\n\t\t * @private\n\t\t */\n\t\tthis._events = new Tone.Timeline(10);\n\n\t\t//constructors\n\t\tTone.Signal.apply(this, options);\n\t\toptions.param = this._param;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The initial scheduled value\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._initial = this._fromUnits(this._param.value);\n\t};\n\n\tTone.extend(Tone.TimelineSignal, Tone.Param);\n\n\t/**\n\t * The event types of a schedulable signal.\n\t * @enum {String}\n\t * @private\n\t */\n\tTone.TimelineSignal.Type = {\n\t\tLinear : \"linear\",\n\t\tExponential : \"exponential\",\n\t\tTarget : \"target\",\n\t\tCurve : \"curve\",\n\t\tSet : \"set\"\n\t};\n\n\t/**\n\t * The current value of the signal. \n\t * @memberOf Tone.TimelineSignal#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.TimelineSignal.prototype, \"value\", {\n\t\tget : function(){\n\t\t\tvar now = this.now();\n\t\t\tvar val = this.getValueAtTime(now);\n\t\t\treturn this._toUnits(val);\n\t\t},\n\t\tset : function(value){\n\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\tthis._initial = convertedVal;\n\t\t\tthis.cancelScheduledValues();\n\t\t\tthis._param.value = convertedVal;\n\t\t}\n\t});\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tSCHEDULING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.TimelineSignal} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Set,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime\n\t\t});\n\t\t//invoke the original event\n\t\tthis._param.setValueAtTime(value, startTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tendTime = this.toSeconds(endTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Linear,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\tthis._param.linearRampToValueAtTime(value, endTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {\n\t\t//get the previous event and make sure it's not starting from 0\n\t\tendTime = this.toSeconds(endTime);\n\t\tvar beforeEvent = this._searchBefore(endTime);\n\t\tif (beforeEvent && beforeEvent.value === 0){\n\t\t\t//reschedule that event\n\t\t\tthis.setValueAtTime(this._minOutput, beforeEvent.time);\n\t\t}\n\t\tvalue = this._fromUnits(value);\n\t\tvar setValue = Math.max(value, this._minOutput);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Exponential,\n\t\t\t\"value\" : setValue,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\t//if the ramped to value is 0, make it go to the min output, and then set to 0.\n\t\tif (value < this._minOutput){\n\t\t\tthis._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);\n\t\t\tthis.setValueAtTime(0, endTime);\n\t\t} else {\n\t\t\tthis._param.exponentialRampToValueAtTime(value, endTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Target,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime,\n\t\t\t\"constant\" : timeConstant\n\t\t});\n\t\tthis._param.setTargetAtTime(value, startTime, timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Set an array of arbitrary values starting at the given time for the given duration.\n\t * @param {Float32Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration\n\t * @param {NormalRange} [scaling=1] If the values in the curve should be scaled by some value\n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {\n\t\tscaling = this.defaultArg(scaling, 1);\n\t\t//copy the array\n\t\tvar floats = new Array(values.length);\n\t\tfor (var i = 0; i < floats.length; i++){\n\t\t\tfloats[i] = this._fromUnits(values[i]) * scaling;\n\t\t}\n\t\tstartTime = this.toSeconds(startTime);\n\t\tduration = this.toSeconds(duration);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Curve,\n\t\t\t\"value\" : floats,\n\t\t\t\"time\" : startTime,\n\t\t\t\"duration\" : duration\n\t\t});\n\t\t//set the first value\n\t\tthis._param.setValueAtTime(floats[0], startTime);\n\t\t//schedule a lienar ramp for each of the segments\n\t\tfor (var j = 1; j < floats.length; j++){\n\t\t\tvar segmentTime = startTime + (j / (floats.length - 1) * duration);\n\t\t\tthis._param.linearRampToValueAtTime(floats[j], segmentTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.cancelScheduledValues = function (after) {\n\t\tafter = this.toSeconds(after);\n\t\tthis._events.cancel(after);\n\t\tthis._param.cancelScheduledValues(after);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets the computed value at the given time. This provides\n\t * a point from which a linear or exponential curve\n\t * can be scheduled after. Will cancel events after \n\t * the given time and shorten the currently scheduled\n\t * linear or exponential ramp so that it ends at `time` .\n\t * This is to avoid discontinuities and clicks in envelopes. \n\t * @param {Time} time When to set the ramp point\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.setRampPoint = function (time) {\n\t\ttime = this.toSeconds(time);\n\t\t//get the value at the given time\n\t\tvar val = this._toUnits(this.getValueAtTime(time));\n\t\t//if there is an event at the given time\n\t\t//and that even is not a \"set\"\n\t\tvar before = this._searchBefore(time);\n\t\tif (before && before.time === time){\n\t\t\t//remove everything after\n\t\t\tthis.cancelScheduledValues(time + this.sampleTime);\n\t\t} else if (before && \n\t\t\t\t before.type === Tone.TimelineSignal.Type.Curve &&\n\t\t\t\t before.time + before.duration > time){\n\t\t\t//if the curve is still playing\n\t\t\t//cancel the curve\n\t\t\tthis.cancelScheduledValues(time);\n\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t} else {\n\t\t\t//reschedule the next event to end at the given time\n\t\t\tvar after = this._searchAfter(time);\n\t\t\tif (after){\n\t\t\t\t//cancel the next event(s)\n\t\t\t\tthis.cancelScheduledValues(time);\n\t\t\t\tif (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\t\t\tthis.exponentialRampToValueAtTime(val, time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.setValueAtTime(val, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a linear ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the linear ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.linearRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a exponential ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the exponential ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.exponentialRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tGETTING SCHEDULED VALUES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value before or equal to the given time\n\t * @param {Number} time The time to query\n\t * @return {Object} The event at or before the given time.\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchBefore = function(time){\n\t\treturn this._events.get(time);\n\t};\n\n\t/**\n\t * The event after the given time\n\t * @param {Number} time The time to query.\n\t * @return {Object} The next event after the given time\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchAfter = function(time){\n\t\treturn this._events.getAfter(time);\n\t};\n\n\t/**\n\t * Get the scheduled value at the given time. This will\n\t * return the unconverted (raw) value.\n\t * @param {Number} time The time in seconds.\n\t * @return {Number} The scheduled value at the given time.\n\t */\n\tTone.TimelineSignal.prototype.getValueAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tvar after = this._searchAfter(time);\n\t\tvar before = this._searchBefore(time);\n\t\tvar value = this._initial;\n\t\t//if it was set by\n\t\tif (before === null){\n\t\t\tvalue = this._initial;\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Target){\n\t\t\tvar previous = this._events.getBefore(before.time);\n\t\t\tvar previouVal;\n\t\t\tif (previous === null){\n\t\t\t\tpreviouVal = this._initial;\n\t\t\t} else {\n\t\t\t\tpreviouVal = previous.value;\n\t\t\t}\n\t\t\tvalue = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Curve){\n\t\t\tvalue = this._curveInterpolate(before.time, before.value, before.duration, time);\n\t\t} else if (after === null){\n\t\t\tvalue = before.value;\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\tvalue = this._linearInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\tvalue = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else {\n\t\t\tvalue = before.value;\n\t\t}\n\t\treturn value;\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.TimelineSignal} this\n\t * @method\n\t */\n\tTone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUTOMATION CURVE CALCULATIONS\n\t//\tMIT License, copyright (c) 2014 Jordan Santell\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Calculates the the value along the curve produced by setTargetAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {\n\t\treturn v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by linearRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {\n\t\treturn v0 + (v1 - v0) * ((t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by exponentialRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {\n\t\tv0 = Math.max(this._minOutput, v0);\n\t\treturn v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by setValueCurveAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {\n\t\tvar len = curve.length;\n\t\t// If time is after duration, return the last curve value\n\t\tif (time >= start + duration) {\n\t\t\treturn curve[len - 1];\n\t\t} else if (time <= start){\n\t\t\treturn curve[0];\n\t\t} else {\n\t\t\tvar progress = (time - start) / duration;\n\t\t\tvar lowerIndex = Math.floor((len - 1) * progress);\n\t\t\tvar upperIndex = Math.ceil((len - 1) * progress);\n\t\t\tvar lowerVal = curve[lowerIndex];\n\t\t\tvar upperVal = curve[upperIndex];\n\t\t\tif (upperIndex === lowerIndex){\n\t\t\t\treturn lowerVal;\n\t\t\t} else {\n\t\t\t\treturn this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.dispose = function(){\n\t\tTone.Signal.prototype.dispose.call(this);\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._events.dispose();\n\t\tthis._events = null;\n\t};\n\n\treturn Tone.TimelineSignal;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Effect = require('effect');\r\n\r\n /**\r\n *
A p5.Filter uses a Web Audio Biquad Filter to filter\r\n * the frequency response of an input source. Subclasses\r\n * include:
\r\n * p5.LowPass:\r\n * Allows frequencies below the cutoff frequency to pass through,\r\n * and attenuates frequencies above the cutoff. \r\n * p5.HighPass:\r\n * The opposite of a lowpass filter. \r\n * p5.BandPass:\r\n * Allows a range of frequencies to pass through and attenuates\r\n * the frequencies below and above this frequency range. \r\n *\r\n * The .res() method controls either width of the\r\n * bandpass, or resonance of the low/highpass cutoff frequency.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Filter\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\r\n * @example\r\n *
\r\n * var fft, noise, filter;\r\n *\r\n * function setup() {\r\n * fill(255, 40, 255);\r\n *\r\n * filter = new p5.BandPass();\r\n *\r\n * noise = new p5.Noise();\r\n * // disconnect unfiltered noise,\r\n * // and connect to filter\r\n * noise.disconnect();\r\n * noise.connect(filter);\r\n * noise.start();\r\n *\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n *\r\n * // set the BandPass frequency based on mouseX\r\n * var freq = map(mouseX, 0, width, 20, 10000);\r\n * filter.freq(freq);\r\n * // give the filter a narrow band (lower res = wider bandpass)\r\n * filter.res(50);\r\n *\r\n * // draw filtered spectrum\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * for (var i = 0; i < spectrum.length; i++) {\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width/spectrum.length, h);\r\n * }\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * noise.amp(0.5, 0.2);\r\n * } else {\r\n * noise.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Filter = function (type) {\r\n\r\n Effect.call(this);\r\n //add extend Effect by adding a Biquad Filter\r\n\r\n /**\r\n * The p5.Filter is built with a\r\n * \r\n * Web Audio BiquadFilter Node.\r\n *\r\n * @property {DelayNode} biquadFilter\r\n\t */\r\n\r\n this.biquad = this.ac.createBiquadFilter();\r\n\r\n this.input.connect(this.biquad);\r\n\r\n this.biquad.connect(this.wet);\r\n\r\n if (type) {\r\n this.setType(type);\r\n }\r\n\r\n //Properties useful for the toggle method.\r\n this._on = true;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n p5.Filter.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Filter an audio signal according to a set\r\n * of filter parameters.\r\n *\r\n * @method process\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance/Width of the filter frequency\r\n * from 0.001 to 1000\r\n */\r\n p5.Filter.prototype.process = function(src, freq, res, time) {\r\n src.connect(this.input);\r\n this.set(freq, res, time);\r\n };\r\n\r\n\r\n /**\r\n * Set the frequency and the resonance of the filter.\r\n *\r\n * @method set\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Filter.prototype.set = function(freq, res, time) {\r\n if (freq) {\r\n this.freq(freq, time);\r\n }\r\n if (res) {\r\n this.res(res, time);\r\n }\r\n };\r\n\r\n /**\r\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\r\n * human hearing, although in reality most people hear in a narrower\r\n * range).\r\n *\r\n * @method freq\r\n * @param {Number} freq Filter Frequency\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current frequency value\r\n */\r\n p5.Filter.prototype.freq = function(freq, time) {\r\n var t = time || 0;\r\n if (freq <= 0) {\r\n freq = 1;\r\n }\r\n if (typeof freq === 'number') {\r\n this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t);\r\n } else if (freq) {\r\n freq.connect(this.biquad.frequency);\r\n }\r\n return this.biquad.frequency.value;\r\n };\r\n\r\n /**\r\n * Controls either width of a bandpass frequency,\r\n * or the resonance of a low/highpass cutoff frequency.\r\n *\r\n * @method res\r\n * @param {Number} res Resonance/Width of filter freq\r\n * from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current res value\r\n */\r\n p5.Filter.prototype.res = function(res, time) {\r\n var t = time || 0;\r\n if (typeof res === 'number') {\r\n this.biquad.Q.value = res;\r\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);\r\n } else if (res) {\r\n res.connect(this.biquad.Q);\r\n }\r\n return this.biquad.Q.value;\r\n };\r\n\r\n /**\r\n * Controls the gain attribute of a Biquad Filter.\r\n * This is distinctly different from .amp() which is inherited from p5.Effect\r\n * .amp() controls the volume via the output gain node\r\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\r\n *\r\n * @method gain\r\n * @param {Number} gain\r\n * @return {Number} Returns the current or updated gain value\r\n */\r\n p5.Filter.prototype.gain = function(gain, time) {\r\n var t = time || 0;\r\n if (typeof gain === 'number') {\r\n this.biquad.gain.value = gain;\r\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t);\r\n } else if (gain) {\r\n gain.connect(this.biquad.gain);\r\n }\r\n return this.biquad.gain.value;\r\n };\r\n\r\n\r\n /**\r\n * Toggle function. Switches between the specified type and allpass\r\n *\r\n * @method toggle\r\n * @return {boolean} [Toggle value]\r\n */\r\n p5.Filter.prototype.toggle = function() {\r\n this._on = !this._on;\r\n\r\n if (this._on === true) {\r\n this.biquad.type = this._untoggledType;\r\n } else if (this._on === false) {\r\n this.biquad.type = 'allpass';\r\n }\r\n\r\n return this._on;\r\n };\r\n\r\n /**\r\n * Set the type of a p5.Filter. Possible types include:\r\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\r\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\r\n * \"allpass\".\r\n *\r\n * @method setType\r\n * @param {String} t\r\n */\r\n p5.Filter.prototype.setType = function(t) {\r\n this.biquad.type = t;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n\r\n p5.Filter.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n Effect.prototype.dispose.apply(this);\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n delete this.biquad;\r\n }\r\n };\r\n\r\n /**\r\n * Constructor: new p5.LowPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('lowpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.LowPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.LowPass = function() {\r\n p5.Filter.call(this, 'lowpass');\r\n };\r\n p5.LowPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.HighPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('highpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.HighPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.HighPass = function() {\r\n p5.Filter.call(this, 'highpass');\r\n };\r\n p5.HighPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.BandPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('bandpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.BandPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.BandPass = function() {\r\n p5.Filter.call(this, 'bandpass');\r\n };\r\n p5.BandPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n return p5.Filter;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Negate\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Subtract the signal connected to input[1] from the signal connected \n\t * to input[0]. If an argument is provided in the constructor, the \n\t * signals .value will be subtracted from the incoming signal.\n\t *\n\t * @extends {Tone.Signal}\n\t * @constructor\n\t * @param {number=} value The value to subtract from the incoming signal. If the value\n\t * is omitted, it will subtract the second signal from the first.\n\t * @example\n\t * var sub = new Tone.Subtract(1);\n\t * var sig = new Tone.Signal(4).connect(sub);\n\t * //the output of sub is 3. \n\t * @example\n\t * var sub = new Tone.Subtract();\n\t * var sigA = new Tone.Signal(10);\n\t * var sigB = new Tone.Signal(2.5);\n\t * sigA.connect(sub, 0, 0);\n\t * sigB.connect(sub, 0, 1);\n\t * //output of sub is 7.5\n\t */\n\tTone.Subtract = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * negate the input of the second input before connecting it\n\t\t * to the summing node.\n\t\t * @type {Tone.Negate}\n\t\t * @private\n\t\t */\n\t\tthis._neg = new Tone.Negate();\n\n\t\t/**\n\t\t * the node where the value is set\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.chain(this._neg, this._sum);\n\t};\n\n\tTone.extend(Tone.Subtract, Tone.Signal);\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.Subtract.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._neg.dispose();\n\t\tthis._neg = null;\n\t\tthis._sum.disconnect();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Subtract;\n});","'use strict';\r\n\r\nglobal.TONE_SILENCE_VERSION_LOGGING = true;\r\n\r\ndefine(['startaudiocontext', 'Tone/core/Context', 'Tone/core/Tone'], function (StartAudioContext, Context, Tone) {\r\n // Create the Audio Context\r\n const audiocontext = new window.AudioContext();\r\n\r\n // Tone and p5.sound share the same audio context\r\n Tone.context.dispose();\r\n Tone.setContext(audiocontext);\r\n\r\n /**\r\n *
Returns the Audio Context for this sketch. Useful for users\r\n * who would like to dig deeper into the Web Audio API\r\n * .
\r\n *\r\n *
Some browsers require users to startAudioContext\r\n * with a user gesture, such as touchStarted in the example below.
\r\n *\r\n * @method getAudioContext\r\n * @return {Object} AudioContext for this sketch\r\n * @example\r\n *
\r\n * function draw() {\r\n * background(255);\r\n * textAlign(CENTER);\r\n *\r\n * if (getAudioContext().state !== 'running') {\r\n * text('click to start audio', width/2, height/2);\r\n * } else {\r\n * text('audio is enabled', width/2, height/2);\r\n * }\r\n * }\r\n *\r\n * function touchStarted() {\r\n * if (getAudioContext().state !== 'running') {\r\n * getAudioContext().resume();\r\n * }\r\n * var synth = new p5.MonoSynth();\r\n * synth.play('A4', 0.5, 0, 0.2);\r\n * }\r\n *\r\n *
It is a good practice to give users control over starting audio playback.\r\n * This practice is enforced by Google Chrome's autoplay policy as of r70\r\n * (info), iOS Safari, and other browsers.\r\n *
\r\n *\r\n *
\r\n * userStartAudio() starts the Audio Context on a user gesture. It utilizes\r\n * the StartAudioContext library by\r\n * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext.\r\n *
\r\n *\r\n *
Starting the audio context on a user gesture can be as simple as userStartAudio().\r\n * Optional parameters let you decide on a specific element that will start the audio context,\r\n * and/or call a function once the audio context is started.
\r\n * @param {Element|Array} [element(s)] This argument can be an Element,\r\n * Selector String, NodeList, p5.Element,\r\n * jQuery Element, or an Array of any of those.\r\n * @param {Function} [callback] Callback to invoke when the AudioContext has started\r\n * @return {Promise} Returns a Promise which is resolved when\r\n * the AudioContext state is 'running'\r\n * @method userStartAudio\r\n * @for p5\r\n * @example\r\n *
\r\n * function setup() {\r\n * var myDiv = createDiv('click to start audio');\r\n * myDiv.position(0, 0);\r\n *\r\n * var mySynth = new p5.MonoSynth();\r\n *\r\n * // This won't play until the context has started\r\n * mySynth.play('A6');\r\n *\r\n * // Start the audio context on a click/touch event\r\n * userStartAudio().then(function() {\r\n * myDiv.remove();\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.prototype.userStartAudio = function(elements, callback) {\r\n var elt = elements;\r\n if (elements instanceof p5.Element) {\r\n elt = elements.elt;\r\n } else if (elements instanceof Array && elements[0] instanceof p5.Element ) {\r\n elt = elements.map(function(e) { return e.elt});\r\n }\r\n return StartAudioContext(audiocontext, elt, callback);\r\n };\r\n\r\n return audiocontext;\r\n});\r\n","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Emitter gives classes which extend it\n\t * the ability to listen for and emit events. \n\t * Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).\n\t * MIT (c) 2011 Jerome Etienne.\n\t * \n\t * @extends {Tone}\n\t */\n\tTone.Emitter = function(){\n\t\t/**\n\t\t * Contains all of the events.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t\tthis._events = {};\n\t};\n\n\tTone.extend(Tone.Emitter);\n\n\t/**\n\t * Bind a callback to a specific event.\n\t * @param {String} event The name of the event to listen for.\n\t * @param {Function} callback The callback to invoke when the\n\t * event is emitted\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.on = function(event, callback){\n\t\t//split the event\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var i = 0; i < events.length; i++){\n\t\t\tvar eventName = events[i];\n\t\t\tif (!this._events.hasOwnProperty(eventName)){\n\t\t\t\tthis._events[eventName] = [];\n\t\t\t}\n\t\t\tthis._events[eventName].push(callback);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove the event listener.\n\t * @param {String} event The event to stop listening to.\n\t * @param {Function=} callback The callback which was bound to \n\t * the event with Tone.Emitter.on.\n\t * If no callback is given, all callbacks\n\t * events are removed.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.off = function(event, callback){\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var ev = 0; ev < events.length; ev++){\n\t\t\tevent = events[ev];\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tif (Tone.prototype.isUndef(callback)){\n\t\t\t\t\tthis._events[event] = [];\n\t\t\t\t} else {\n\t\t\t\t\tvar eventList = this._events[event];\n\t\t\t\t\tfor (var i = 0; i < eventList.length; i++){\n\t\t\t\t\t\tif (eventList[i] === callback){\n\t\t\t\t\t\t\teventList.splice(i, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Invoke all of the callbacks bound to the event\n\t * with any arguments passed in. \n\t * @param {String} event The name of the event.\n\t * @param {*...} args The arguments to pass to the functions listening.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.emit = function(event){\n\t\tif (this._events){\n\t\t\tvar args = Array.apply(null, arguments).slice(1);\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tvar eventList = this._events[event];\n\t\t\t\tfor (var i = 0, len = eventList.length; i < len; i++){\n\t\t\t\t\teventList[i].apply(this, args);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add Emitter functions (on/off/emit) to the object\n\t * @param {Object|Function} object The object or class to extend.\n\t */\n\tTone.Emitter.mixin = function(object){\n\t\tvar functions = [\"on\", \"off\", \"emit\"];\n\t\tobject._events = {};\n\t\tfor (var i = 0; i < functions.length; i++){\n\t\t\tvar func = functions[i];\n\t\t\tvar emitterFunc = Tone.Emitter.prototype[func];\n\t\t\tobject[func] = emitterFunc;\n\t\t}\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._events = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Emitter;\n});","define([\"Tone/core/Tone\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Base class for all Signals. Used Internally. \n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t */\n\tTone.SignalBase = function(){};\n\n\tTone.extend(Tone.SignalBase);\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.SignalBase.prototype.connect = function(node, outputNumber, inputNumber){\n\t\t//zero it out so that the signal can have full control\n\t\tif ((Tone.Signal && Tone.Signal === node.constructor) || \n\t\t\t\t(Tone.Param && Tone.Param === node.constructor) || \n\t\t\t\t(Tone.TimelineSignal && Tone.TimelineSignal === node.constructor)){\n\t\t\t//cancel changes\n\t\t\tnode._param.cancelScheduledValues(0);\n\t\t\t//reset the value\n\t\t\tnode._param.value = 0;\n\t\t\t//mark the value as overridden\n\t\t\tnode.overridden = true;\n\t\t} else if (node instanceof AudioParam){\n\t\t\tnode.cancelScheduledValues(0);\n\t\t\tnode.value = 0;\n\t\t} \n\t\tTone.prototype.connect.call(this, node, outputNumber, inputNumber);\n\t\treturn this;\n\t};\n\n\treturn Tone.SignalBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Time is a primitive type for encoding Time values. \n\t * Eventually all time values are evaluated to seconds\n\t * using the `eval` method. Tone.Time can be constructed\n\t * with or without the `new` keyword. Tone.Time can be passed\n\t * into the parameter of any method which takes time as an argument. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * var t = Tone.Time(\"4n\");//encodes a quarter note\n\t * t.mult(4); // multiply that value by 4\n\t * t.toNotation(); //returns \"1m\"\n\t */\n\tTone.Time = function(val, units){\n\t\tif (this instanceof Tone.Time){\n\n\t\t\t/**\n\t\t\t * If the current clock time should\n\t\t\t * be added to the output\n\t\t\t * @type {Boolean}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._plusNow = false;\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Time(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Time, Tone.TimeBase);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);\n\n\t/*\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\treturn Tone.Transport.nextSubdivision(rh());\n\t\t}\n\t};\n\n\t/*\n\t * Adds an additional unary expression\n\t * which adds the current clock time.\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.now = {\n\t\tregexp : /^\\+/,\n\t\tmethod : function(lh){\n\t\t\tthis._plusNow = true;\n\t\t\treturn lh();\n\t\t}\n\t};\n\n\t/**\n\t * Quantize the time by the given subdivision. Optionally add a\n\t * percentage which will move the time value towards the ideal\n\t * quantized value by that percentage. \n\t * @param {Number|Time} val The subdivision to quantize to\n\t * @param {NormalRange} [percent=1] Move the time value\n\t * towards the quantized value by\n\t * a percentage.\n\t * @return {Tone.Time} this\n\t * @example\n\t * Tone.Time(21).quantize(2) //returns 22\n\t * Tone.Time(0.6).quantize(\"4n\", 0.5) //returns 0.55\n\t */\n\tTone.Time.prototype.quantize = function(subdiv, percent){\n\t\tpercent = this.defaultArg(percent, 1);\n\t\tthis._expr = function(expr, subdivision, percent){\n\t\t\texpr = expr();\n\t\t\tsubdivision = subdivision.toSeconds();\n\t\t\tvar multiple = Math.round(expr / subdivision);\n\t\t\tvar ideal = multiple * subdivision;\n\t\t\tvar diff = ideal - expr;\n\t\t\treturn expr + diff * percent;\n\t\t}.bind(this, this._expr, new this.constructor(subdiv), percent);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Adds the clock time to the time expression at the \n\t * moment of evaluation. \n\t * @return {Tone.Time} this\n\t */\n\tTone.Time.prototype.addNow = function(){\n\t\tthis._plusNow = true;\n\t\treturn this;\n\t};\n\n\t/**\n\t * @override\n\t * Override the default value return when no arguments are passed in.\n\t * The default value is 'now'\n\t * @private\n\t */\n\tTone.Time.prototype._defaultExpr = function(){\n\t\tthis._plusNow = true;\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.Time} time\n\t * @return {Time}\n\t */\n\tTone.Time.prototype.copy = function(time){\n\t\tTone.TimeBase.prototype.copy.call(this, time);\n\t\tthis._plusNow = time._plusNow;\n\t\treturn this;\n\t};\n\n\t//CONVERSIONS//////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert a Time to Notation. Values will be thresholded to the nearest 128th note. \n\t * @return {Notation} \n\t * @example\n\t * //if the Transport is at 120bpm:\n\t * Tone.Time(2).toNotation();//returns \"1m\"\n\t */\n\tTone.Time.prototype.toNotation = function(){\n\t\tvar time = this.toSeconds();\n\t\tvar testNotations = [\"1m\", \"2n\", \"4n\", \"8n\", \"16n\", \"32n\", \"64n\", \"128n\"];\n\t\tvar retNotation = this._toNotationHelper(time, testNotations);\n\t\t//try the same thing but with tripelets\n\t\tvar testTripletNotations = [\"1m\", \"2n\", \"2t\", \"4n\", \"4t\", \"8n\", \"8t\", \"16n\", \"16t\", \"32n\", \"32t\", \"64n\", \"64t\", \"128n\"];\n\t\tvar retTripletNotation = this._toNotationHelper(time, testTripletNotations);\n\t\t//choose the simpler expression of the two\n\t\tif (retTripletNotation.split(\"+\").length < retNotation.split(\"+\").length){\n\t\t\treturn retTripletNotation;\n\t\t} else {\n\t\t\treturn retNotation;\n\t\t}\n\t};\n\n\t/**\n\t * Helper method for Tone.toNotation\n\t * @param {Number} units \n\t * @param {Array} testNotations\n\t * @return {String}\n\t * @private\n\t */\n\tTone.Time.prototype._toNotationHelper = function(units, testNotations){\n\t\t//the threshold is the last value in the array\n\t\tvar threshold = this._notationToUnits(testNotations[testNotations.length - 1]);\n\t\tvar retNotation = \"\";\n\t\tfor (var i = 0; i < testNotations.length; i++){\n\t\t\tvar notationTime = this._notationToUnits(testNotations[i]);\n\t\t\t//account for floating point errors (i.e. round up if the value is 0.999999)\n\t\t\tvar multiple = units / notationTime;\n\t\t\tvar floatingPointError = 0.000001;\n\t\t\tif (1 - multiple % 1 < floatingPointError){\n\t\t\t\tmultiple += floatingPointError;\n\t\t\t}\n\t\t\tmultiple = Math.floor(multiple);\n\t\t\tif (multiple > 0){\n\t\t\t\tif (multiple === 1){\n\t\t\t\t\tretNotation += testNotations[i];\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += multiple.toString() + \"*\" + testNotations[i];\n\t\t\t\t}\n\t\t\t\tunits -= multiple * notationTime;\n\t\t\t\tif (units < threshold){\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += \" + \";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (retNotation === \"\"){\n\t\t\tretNotation = \"0\";\n\t\t}\n\t\treturn retNotation;\n\t};\n\n\t/**\n\t * Convert a notation value to the current units\n\t * @param {Notation} notation \n\t * @return {Number} \n\t * @private\n\t */\n\tTone.Time.prototype._notationToUnits = function(notation){\n\t\tvar primaryExprs = this._primaryExpressions;\n\t\tvar notationExprs = [primaryExprs.n, primaryExprs.t, primaryExprs.m];\n\t\tfor (var i = 0; i < notationExprs.length; i++){\n\t\t\tvar expr = notationExprs[i];\n\t\t\tvar match = notation.match(expr.regexp);\n\t\t\tif (match){\n\t\t\t\treturn expr.method.call(this, match[1]);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Return the time encoded as Bars:Beats:Sixteenths.\n\t * @return {BarsBeatsSixteenths}\n\t */\n\tTone.Time.prototype.toBarsBeatsSixteenths = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.toSeconds() / quarterTime;\n\t\tvar measures = Math.floor(quarters / this._timeSignature());\n\t\tvar sixteenths = (quarters % 1) * 4;\n\t\tquarters = Math.floor(quarters) % this._timeSignature();\n\t\tsixteenths = sixteenths.toString();\n\t\tif (sixteenths.length > 3){\n\t\t\tsixteenths = parseFloat(sixteenths).toFixed(3);\n\t\t}\n\t\tvar progress = [measures, quarters, sixteenths];\n\t\treturn progress.join(\":\");\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.Time.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time in samples\n\t * @return {Samples} \n\t */\n\tTone.Time.prototype.toSamples = function(){\n\t\treturn this.toSeconds() * this.context.sampleRate;\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t * @example\n\t * Tone.Time(2).toFrequency(); //0.5\n\t */\n\tTone.Time.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.toSeconds = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in milliseconds.\n\t * @return {Milliseconds} \n\t */\n\tTone.Time.prototype.toMilliseconds = function(){\n\t\treturn this.toSeconds() * 1000;\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.valueOf = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow?this.now():0);\n\t};\n\n\treturn Tone.Time;\n});","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TimeBase is a flexible encoding of time\n\t * which can be evaluated to and from a string.\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t * @extends {Tone}\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @example\n\t * Tone.TimeBase(4, \"n\")\n\t * Tone.TimeBase(2, \"t\")\n\t * Tone.TimeBase(\"2t\").add(\"1m\")\n\t * Tone.TimeBase(\"2t + 1m\");\n\t */\n\tTone.TimeBase = function(val, units){\n\n\t\t//allows it to be constructed with or without 'new'\n\t\tif (this instanceof Tone.TimeBase) {\n\n\t\t\t/**\n\t\t\t * Any expressions parsed from the Time\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._expr = this._noOp;\n\n\t\t\tif (val instanceof Tone.TimeBase){\n\t\t\t\tthis.copy(val);\n\t\t\t} else if (!this.isUndef(units) || this.isNumber(val)){\n\t\t\t\t//default units\n\t\t\t\tunits = this.defaultArg(units, this._defaultUnits);\n\t\t\t\tvar method = this._primaryExpressions[units].method;\n\t\t\t\tthis._expr = method.bind(this, val);\n\t\t\t} else if (this.isString(val)){\n\t\t\t\tthis.set(val);\n\t\t\t} else if (this.isUndef(val)){\n\t\t\t\t//default expression\n\t\t\t\tthis._expr = this._defaultExpr();\n\t\t\t}\n\t\t} else {\n\n\t\t\treturn new Tone.TimeBase(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TimeBase);\n\n\t/**\n\t * Repalce the current time value with the value\n\t * given by the expression string.\n\t * @param {String} exprString\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.set = function(exprString){\n\t\tthis._expr = this._parseExprString(exprString);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Return a clone of the TimeBase object.\n\t * @return {Tone.TimeBase} The new cloned Tone.TimeBase\n\t */\n\tTone.TimeBase.prototype.clone = function(){\n\t\tvar instance = new this.constructor();\n\t\tinstance.copy(this);\n\t\treturn instance;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.TimeBase} time\n\t * @return {TimeBase}\n\t */\n\tTone.TimeBase.prototype.copy = function(time){\n\t\tvar val = time._expr();\n\t\treturn this.set(val);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tABSTRACT SYNTAX TREE PARSER\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * All the primary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._primaryExpressions = {\n\t\t\"n\" : {\n\t\t\tregexp : /^(\\d+)n/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\tif (value === 1){\n\t\t\t\t\treturn this._beatsToUnits(this._timeSignature());\n\t\t\t\t} else {\n\t\t\t\t\treturn this._beatsToUnits(4 / value);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"t\" : {\n\t\t\tregexp : /^(\\d+)t/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\treturn this._beatsToUnits(8 / (parseInt(value) * 3));\n\t\t\t}\n\t\t},\n\t\t\"m\" : {\n\t\t\tregexp : /^(\\d+)m/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._beatsToUnits(parseInt(value) * this._timeSignature());\n\t\t\t}\n\t\t},\n\t\t\"i\" : {\n\t\t\tregexp : /^(\\d+)i/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._ticksToUnits(parseInt(value));\n\t\t\t}\n\t\t},\n\t\t\"hz\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)hz/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._frequencyToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"tr\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\t\tvar total = 0;\n\t\t\t\tif (m && m !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t\t}\n\t\t\t\tif (q && q !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(q));\n\t\t\t\t}\n\t\t\t\tif (s && s !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t\t}\n\t\t\t\treturn total;\n\t\t\t}\n\t\t},\n\t\t\"s\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?s)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._secondsToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"samples\" : {\n\t\t\tregexp : /^(\\d+)samples/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn parseInt(value) / this.context.sampleRate;\n\t\t\t}\n\t\t},\n\t\t\"default\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._primaryExpressions[this._defaultUnits].method.call(this, value);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the binary expressions that TimeBase can accept.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._binaryExpressions = {\n\t\t\"+\" : {\n\t\t\tregexp : /^\\+/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() + rh();\n\t\t\t}\n\t\t},\n\t\t\"-\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() - rh();\n\t\t\t}\n\t\t},\n\t\t\"*\" : {\n\t\t\tregexp : /^\\*/,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() * rh();\n\t\t\t}\n\t\t},\n\t\t\"/\" : {\n\t\t\tregexp : /^\\//,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() / rh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the unary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._unaryExpressions = {\n\t\t\"neg\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tmethod : function(lh){\n\t\t\t\treturn -lh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Syntactic glue which holds expressions together\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._syntaxGlue = {\n\t\t\"(\" : {\n\t\t\tregexp : /^\\(/\n\t\t},\n\t\t\")\" : {\n\t\t\tregexp : /^\\)/\n\t\t}\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.TimeBase.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr, this);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr, context){\n\t\t\tvar expressions = [\"_binaryExpressions\", \"_unaryExpressions\", \"_primaryExpressions\", \"_syntaxGlue\"];\n\t\t\tfor (var i = 0; i < expressions.length; i++){\n\t\t\t\tvar group = context[expressions[i]];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tmethod : op.method,\n\t\t\t\t\t\t\tprecedence : op.precedence,\n\t\t\t\t\t\t\tregexp : op.regexp,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * Given a token, find the value within the groupName\n\t * @param {Object} token\n\t * @param {String} groupName\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._matchGroup = function(token, group, prec) {\n\t\tvar ret = false;\n\t\tif (!this.isUndef(token)){\n\t\t\tfor (var opName in group){\n\t\t\t\tvar op = group[opName];\n\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\tif (!this.isUndef(prec)){\n\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\treturn op;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn op;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * Match a binary expression given the token and the precedence\n\t * @param {Lexer} lexer\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseBinary = function(lexer, precedence){\n\t\tif (this.isUndef(precedence)){\n\t\t\tprecedence = 2;\n\t\t}\n\t\tvar expr;\n\t\tif (precedence < 0){\n\t\t\texpr = this._parseUnary(lexer);\n\t\t} else {\n\t\t\texpr = this._parseBinary(lexer, precedence - 1);\n\t\t}\n\t\tvar token = lexer.peek();\n\t\twhile (token && this._matchGroup(token, this._binaryExpressions, precedence)){\n\t\t\ttoken = lexer.next();\n\t\t\texpr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));\n\t\t\ttoken = lexer.peek();\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * Match a unary expression.\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseUnary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tvar op = this._matchGroup(token, this._unaryExpressions);\n\t\tif (op) {\n\t\t\ttoken = lexer.next();\n\t\t\texpr = this._parseUnary(lexer);\n\t\t\treturn op.method.bind(this, expr);\n\t\t}\n\t\treturn this._parsePrimary(lexer);\n\t};\n\n\t/**\n\t * Match a primary expression (a value).\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parsePrimary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tif (this.isUndef(token)) {\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected end of expression\");\n\t\t}\n\t\tif (this._matchGroup(token, this._primaryExpressions)) {\n\t\t\ttoken = lexer.next();\n\t\t\tvar matching = token.value.match(token.regexp);\n\t\t\treturn token.method.bind(this, matching[1], matching[2], matching[3]);\n\t\t}\n\t\tif (token && token.value === \"(\"){\n\t\t\tlexer.next();\n\t\t\texpr = this._parseBinary(lexer);\n\t\t\ttoken = lexer.next();\n\t\t\tif (!(token && token.value === \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\t\tthrow new SyntaxError(\"Tone.TimeBase: Cannot process token \" + token.value);\n\t};\n\n\t/**\n\t * Recursively parse the string expression into a syntax tree.\n\t * @param {string} expr \n\t * @return {Function} the bound method to be evaluated later\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseExprString = function(exprString){\n\t\tif (!this.isString(exprString)){\n\t\t\texprString = exprString.toString();\n\t\t}\n\t\tvar lexer = this._tokenize(exprString);\n\t\tvar tree = this._parseBinary(lexer);\n\t\treturn tree;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tDEFAULTS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The initial expression value\n\t * @return {Number} The initial value 0\n\t * @private\n\t */\n\tTone.TimeBase.prototype._noOp = function(){\n\t\treturn 0;\n\t};\n\n\t/**\n\t * The default expression value if no arguments are given\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultExpr = function(){\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultUnits = \"s\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._frequencyToUnits = function(freq){\n\t\treturn 1/freq;\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._beatsToUnits = function(beats){\n\t\treturn (60 / Tone.Transport.bpm.value) * beats;\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._secondsToUnits = function(seconds){\n\t\treturn seconds;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._ticksToUnits = function(ticks){\n\t\treturn ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time signature.\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._timeSignature = function(){\n\t\treturn Tone.Transport.timeSignature;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Push an expression onto the expression list\n\t * @param {Time} val\n\t * @param {String} type\n\t * @param {String} units\n\t * @return {Tone.TimeBase} \n\t * @private\n\t */\n\tTone.TimeBase.prototype._pushExpr = function(val, name, units){\n\t\t//create the expression\n\t\tif (!(val instanceof Tone.TimeBase)){\n\t\t\tval = new this.constructor(val, units);\n\t\t}\n\t\tthis._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add to the current value.\n\t * @param {Time} val The value to add\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").add(\"1m\"); //\"3m\"\n\t */\n\tTone.TimeBase.prototype.add = function(val, units){\n\t\treturn this._pushExpr(val, \"+\", units);\n\t};\n\n\t/**\n\t * Subtract the value from the current time.\n\t * @param {Time} val The value to subtract\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").sub(\"1m\"); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.sub = function(val, units){\n\t\treturn this._pushExpr(val, \"-\", units);\n\t};\n\n\t/**\n\t * Multiply the current value by the given time.\n\t * @param {Time} val The value to multiply\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").mult(\"2\"); //\"4m\"\n\t */\n\tTone.TimeBase.prototype.mult = function(val, units){\n\t\treturn this._pushExpr(val, \"*\", units);\n\t};\n\n\t/**\n\t * Divide the current value by the given time.\n\t * @param {Time} val The value to divide by\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").div(2); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.div = function(val, units){\n\t\treturn this._pushExpr(val, \"/\", units);\n\t};\n\n\t/**\n\t * Evaluate the time value. Returns the time\n\t * in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.TimeBase.prototype.valueOf = function(){\n\t\treturn this._expr();\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.dispose = function(){\n\t\tthis._expr = null;\n\t};\n\n\treturn Tone.TimeBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Param wraps the native Web Audio's AudioParam to provide\n\t * additional unit conversion functionality. It also\n\t * serves as a base-class for classes which have a single,\n\t * automatable parameter. \n\t * @extends {Tone}\n\t * @param {AudioParam} param The parameter to wrap.\n\t * @param {Tone.Type} units The units of the audio param.\n\t * @param {Boolean} convert If the param should be converted.\n\t */\n\tTone.Param = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"param\", \"units\", \"convert\"], Tone.Param.defaults);\n\n\t\t/**\n\t\t * The native parameter to control\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input = options.param;\n\n\t\t/**\n\t\t * The units of the parameter\n\t\t * @type {Tone.Type}\n\t\t */\n\t\tthis.units = options.units;\n\n\t\t/**\n\t\t * If the value should be converted or not\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis.convert = options.convert;\n\n\t\t/**\n\t\t * True if the signal value is being overridden by \n\t\t * a connected signal.\n\t\t * @readOnly\n\t\t * @type {boolean}\n\t\t * @private\n\t\t */\n\t\tthis.overridden = false;\n\n\t\t/**\n\t\t * If there is an LFO, this is where it is held.\n\t\t * @type {Tone.LFO}\n\t\t * @private\n\t\t */\n\t\tthis._lfo = null;\n\n\t\tif (this.isObject(options.lfo)){\n\t\t\tthis.value = options.lfo;\n\t\t} else if (!this.isUndef(options.value)){\n\t\t\tthis.value = options.value;\n\t\t}\n\t};\n\n\tTone.extend(Tone.Param);\n\t\n\t/**\n\t * Defaults\n\t * @type {Object}\n\t * @const\n\t */\n\tTone.Param.defaults = {\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t\t\"param\" : undefined\n\t};\n\n\t/**\n\t * The current value of the parameter. \n\t * @memberOf Tone.Param#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._toUnits(this._param.value);\n\t\t},\n\t\tset : function(value){\n\t\t\tif (this.isObject(value)){\n\t\t\t\t//throw an error if the LFO needs to be included\n\t\t\t\tif (this.isUndef(Tone.LFO)){\n\t\t\t\t\tthrow new Error(\"Include 'Tone.LFO' to use an LFO as a Param value.\");\n\t\t\t\t}\n\t\t\t\t//remove the old one\n\t\t\t\tif (this._lfo){\n\t\t\t\t\tthis._lfo.dispose();\n\t\t\t\t}\n\t\t\t\tthis._lfo = new Tone.LFO(value).start();\n\t\t\t\tthis._lfo.connect(this.input);\n\t\t\t} else {\n\t\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\t\tthis._param.cancelScheduledValues(0);\n\t\t\t\tthis._param.value = convertedVal;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Convert the given value from the type specified by Tone.Param.units\n\t * into the destination value (such as Gain or Frequency).\n\t * @private\n\t * @param {*} val the value to convert\n\t * @return {number} the number which the value should be set to\n\t */\n\tTone.Param.prototype._fromUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Time: \n\t\t\t\t\treturn this.toSeconds(val);\n\t\t\t\tcase Tone.Type.Frequency: \n\t\t\t\t\treturn this.toFrequency(val);\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.dbToGain(val);\n\t\t\t\tcase Tone.Type.NormalRange: \n\t\t\t\t\treturn Math.min(Math.max(val, 0), 1);\n\t\t\t\tcase Tone.Type.AudioRange: \n\t\t\t\t\treturn Math.min(Math.max(val, -1), 1);\n\t\t\t\tcase Tone.Type.Positive: \n\t\t\t\t\treturn Math.max(val, 0);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * Convert the parameters value into the units specified by Tone.Param.units.\n\t * @private\n\t * @param {number} val the value to convert\n\t * @return {number}\n\t */\n\tTone.Param.prototype._toUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.gainToDb(val);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * the minimum output value\n\t * @type {Number}\n\t * @private\n\t */\n\tTone.Param.prototype._minOutput = 0.00001;\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.Param} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.Param.prototype.setValueAtTime = function(value, time){\n\t\tvalue = this._fromUnits(value);\n\t\ttime = this.toSeconds(time);\n\t\tif (time <= this.now() + this.blockTime){\n\t\t\tthis._param.value = value;\n\t\t} else {\n\t\t\tthis._param.setValueAtTime(value, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Creates a schedule point with the current value at the current time.\n\t * This is useful for creating an automation anchor point in order to \n\t * schedule changes from the current value. \n\t *\n\t * @param {number=} now (Optionally) pass the now value in. \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setRampPoint = function(now){\n\t\tnow = this.defaultArg(now, this.now());\n\t\tvar currentVal = this._param.value;\n\t\t// exponentialRampToValueAt cannot ever ramp from or to 0\n\t\t// More info: https://bugzilla.mozilla.org/show_bug.cgi?id=1125600#c2\n\t\tif (currentVal === 0){\n\t\t\tcurrentVal = this._minOutput;\n\t\t}\n\t\tthis._param.setValueAtTime(currentVal, now);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.linearRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tthis._param.linearRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.exponentialRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\tthis._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //exponentially ramp to the value 2 over 4 seconds. \n\t * signal.exponentialRampToValue(2, 4);\n\t */\n\tTone.Param.prototype.exponentialRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an linear continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //linearly ramp to the value 4 over 3 seconds. \n\t * signal.linearRampToValue(4, 3);\n\t */\n\tTone.Param.prototype.linearRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.Param} this \n\t */\n\tTone.Param.prototype.setTargetAtTime = function(value, startTime, timeConstant){\n\t\tvalue = this._fromUnits(value);\n\t\t// The value will never be able to approach without timeConstant > 0.\n\t\t// http://www.w3.org/TR/webaudio/#dfn-setTargetAtTime, where the equation\n\t\t// is described. 0 results in a division by 0.\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tthis._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets an array of arbitrary parameter values starting at the given time\n\t * for the given duration.\n\t * \t\n\t * @param {Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setValueCurveAtTime = function(values, startTime, duration){\n\t\tfor (var i = 0; i < values.length; i++){\n\t\t\tvalues[i] = this._fromUnits(values[i]);\n\t\t}\n\t\tthis._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.cancelScheduledValues = function(startTime){\n\t\tthis._param.cancelScheduledValues(this.toSeconds(startTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Ramps to the given value over the duration of the rampTime. \n\t * Automatically selects the best ramp type (exponential or linear)\n\t * depending on the `units` of the signal\n\t * \n\t * @param {number} value \n\t * @param {Time} rampTime \tThe time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //ramp to the value either linearly or exponentially \n\t * //depending on the \"units\" value of the signal\n\t * signal.rampTo(0, 10);\n\t * @example\n\t * //schedule it to ramp starting at a specific time\n\t * signal.rampTo(0, 10, 5)\n\t */\n\tTone.Param.prototype.rampTo = function(value, rampTime, startTime){\n\t\trampTime = this.defaultArg(rampTime, 0);\n\t\tif (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels){\n\t\t\tthis.exponentialRampToValue(value, rampTime, startTime);\n\t\t} else {\n\t\t\tthis.linearRampToValue(value, rampTime, startTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * The LFO created by the signal instance. If none\n\t * was created, this is null.\n\t * @type {Tone.LFO}\n\t * @readOnly\n\t * @memberOf Tone.Param#\n\t * @name lfo\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"lfo\", {\n\t\tget : function(){\n\t\t\treturn this._lfo;\n\t\t}\n\t});\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tif (this._lfo){\n\t\t\tthis._lfo.dispose();\n\t\t\tthis._lfo = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\treturn Tone.Param;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
Creates a signal that oscillates between -1.0 and 1.0.\r\n * By default, the oscillation takes the form of a sinusoidal\r\n * shape ('sine'). Additional types include 'triangle',\r\n * 'sawtooth' and 'square'. The frequency defaults to\r\n * 440 oscillations per second (440Hz, equal to the pitch of an\r\n * 'A' note).
\r\n *\r\n *
Set the type of oscillation with setType(), or by instantiating a\r\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\r\n *
\r\n *\r\n * @class p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] frequency defaults to 440Hz\r\n * @param {String} [type] type of oscillator. Options:\r\n * 'sine' (default), 'triangle',\r\n * 'sawtooth', 'square'\r\n * @example\r\n *
\r\n * var osc;\r\n * var playing = false;\r\n *\r\n * function setup() {\r\n * backgroundColor = color(255,0,255);\r\n * textAlign(CENTER);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.setType('sine');\r\n * osc.freq(240);\r\n * osc.amp(0);\r\n * osc.start();\r\n * }\r\n *\r\n * function draw() {\r\n * background(backgroundColor)\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * if (!playing) {\r\n * // ramp amplitude to 0.5 over 0.05 seconds\r\n * osc.amp(0.5, 0.05);\r\n * playing = true;\r\n * backgroundColor = color(0,255,255);\r\n * } else {\r\n * // ramp amplitude to 0 over 0.5 seconds\r\n * osc.amp(0, 0.5);\r\n * playing = false;\r\n * backgroundColor = color(255,0,255);\r\n * }\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Oscillator = function(freq, type) {\r\n if (typeof freq === 'string') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n } if (typeof type === 'number') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n }\r\n this.started = false;\r\n\r\n // components\r\n this.phaseAmount = undefined;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.f = freq || 440.0; // frequency\r\n this.oscillator.type = type || 'sine';\r\n this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime);\r\n\r\n // connections\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this._freqMods = []; // modulators connected to this oscillator's frequency\r\n\r\n // set default output gain to 0.5\r\n this.output.gain.value = 0.5;\r\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\r\n\r\n this.oscillator.connect(this.output);\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.connection = p5sound.input; // connect to p5sound by default\r\n this.panner = new p5.Panner(this.output, this.connection, 1);\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.output];\r\n\r\n // add to the soundArray so we can dispose of the osc later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start an oscillator. Accepts an optional parameter to\r\n * determine how long (in seconds from now) until the\r\n * oscillator starts.\r\n *\r\n * @method start\r\n * @for p5.Oscillator\r\n * @param {Number} [time] startTime in seconds from now.\r\n * @param {Number} [frequency] frequency in Hz.\r\n */\r\n p5.Oscillator.prototype.start = function(time, f) {\r\n if (this.started) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n }\r\n if (!this.started) {\r\n var freq = f || this.f;\r\n var type = this.oscillator.type;\r\n\r\n // set old osc free to be garbage collected (memory)\r\n if (this.oscillator) {\r\n this.oscillator.disconnect();\r\n delete this.oscillator;\r\n }\r\n\r\n // var detune = this.oscillator.frequency.value;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.oscillator.frequency.value = Math.abs(freq);\r\n this.oscillator.type = type;\r\n // this.oscillator.detune.value = detune;\r\n this.oscillator.connect(this.output);\r\n time = time || 0;\r\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\r\n this.freqNode = this.oscillator.frequency;\r\n\r\n // if other oscillators are already connected to this osc's freq\r\n for (var i in this._freqMods) {\r\n if (typeof this._freqMods[i].connect !== 'undefined') {\r\n this._freqMods[i].connect(this.oscillator.frequency);\r\n }\r\n }\r\n\r\n this.started = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop an oscillator. Accepts an optional parameter\r\n * to determine how long (in seconds from now) until the\r\n * oscillator stops.\r\n *\r\n * @method stop\r\n * @for p5.Oscillator\r\n * @param {Number} secondsFromNow Time, in seconds from now.\r\n */\r\n p5.Oscillator.prototype.stop = function(time) {\r\n if (this.started) {\r\n var t = time || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.oscillator.stop(t + now);\r\n this.started = false;\r\n }\r\n };\r\n\r\n /**\r\n * Set the amplitude between 0 and 1.0. Or, pass in an object\r\n * such as an oscillator to modulate amplitude with an audio signal.\r\n *\r\n * @method amp\r\n * @for p5.Oscillator\r\n * @param {Number|Object} vol between 0 and 1.0\r\n * or a modulating signal/oscillator\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {AudioParam} gain If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's\r\n * gain/amplitude/volume)\r\n */\r\n p5.Oscillator.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var self = this;\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n\r\n else if (vol) {\r\n vol.connect(self.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // these are now the same thing\r\n p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;\r\n\r\n p5.Oscillator.prototype.getAmp = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set frequency of an oscillator to a value. Or, pass in an object\r\n * such as an oscillator to modulate the frequency with an audio signal.\r\n *\r\n * @method freq\r\n * @for p5.Oscillator\r\n * @param {Number|Object} Frequency Frequency in Hz\r\n * or modulating signal/oscillator\r\n * @param {Number} [rampTime] Ramp time (in seconds)\r\n * @param {Number} [timeFromNow] Schedule this event to happen\r\n * at x seconds from now\r\n * @return {AudioParam} Frequency If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's frequency\r\n * @example\r\n *
\r\n * var osc = new p5.Oscillator(300);\r\n * osc.start();\r\n * osc.freq(40, 10);\r\n *
\r\n */\r\n p5.Oscillator.prototype.freq = function(val, rampTime, tFromNow) {\r\n if (typeof val === 'number' && !isNaN(val)) {\r\n this.f = val;\r\n var now = p5sound.audiocontext.currentTime;\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var t = now + tFromNow + rampTime;\r\n // var currentFreq = this.oscillator.frequency.value;\r\n // this.oscillator.frequency.cancelScheduledValues(now);\r\n\r\n if (rampTime === 0) {\r\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\r\n } else {\r\n if (val > 0 ) {\r\n this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);\r\n } else {\r\n this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now);\r\n }\r\n }\r\n\r\n // reset phase if oscillator has a phase\r\n if (this.phaseAmount) {\r\n this.phase(this.phaseAmount);\r\n }\r\n\r\n } else if (val) {\r\n if (val.output) {\r\n val = val.output;\r\n }\r\n val.connect(this.oscillator.frequency);\r\n\r\n // keep track of what is modulating this param\r\n // so it can be re-connected if\r\n this._freqMods.push( val );\r\n } else {\r\n // return the Frequency Node\r\n return this.oscillator.frequency;\r\n }\r\n };\r\n\r\n p5.Oscillator.prototype.getFreq = function() {\r\n return this.oscillator.frequency.value;\r\n };\r\n\r\n /**\r\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\r\n *\r\n * @method setType\r\n * @for p5.Oscillator\r\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\r\n */\r\n p5.Oscillator.prototype.setType = function(type) {\r\n this.oscillator.type = type;\r\n };\r\n\r\n p5.Oscillator.prototype.getType = function() {\r\n return this.oscillator.type;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.Oscillator\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.Oscillator.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n this.connection = unit.input;\r\n }\r\n else {\r\n this.panner.connect(unit);\r\n this.connection = unit;\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.Oscillator\r\n */\r\n p5.Oscillator.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n if (this.output) {\r\n this.output.connect(this.panner);\r\n }\r\n }\r\n this.oscMods = [];\r\n };\r\n\r\n /**\r\n * Pan between Left (-1) and Right (1)\r\n *\r\n * @method pan\r\n * @for p5.Oscillator\r\n * @param {Number} panning Number between -1 and 1\r\n * @param {Number} timeFromNow schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Oscillator.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n p5.Oscillator.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n // get rid of the oscillator\r\n p5.Oscillator.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.oscillator) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n this.disconnect();\r\n this.panner = null;\r\n this.oscillator = null;\r\n }\r\n // if it is a Pulse\r\n if (this.osc2) {\r\n this.osc2.dispose();\r\n }\r\n };\r\n\r\n /**\r\n * Set the phase of an oscillator between 0.0 and 1.0.\r\n * In this implementation, phase is a delay time\r\n * based on the oscillator's current frequency.\r\n *\r\n * @method phase\r\n * @for p5.Oscillator\r\n * @param {Number} phase float between 0.0 and 1.0\r\n */\r\n p5.Oscillator.prototype.phase = function(p) {\r\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1/this.f);\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n this.phaseAmount = p;\r\n\r\n if (!this.dNode) {\r\n // create a delay node\r\n this.dNode = p5sound.audiocontext.createDelay();\r\n // put the delay node in between output and panner\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.dNode);\r\n this.dNode.connect(this.output);\r\n }\r\n\r\n // set delay time to match phase:\r\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\r\n };\r\n\r\n // ========================== //\r\n // SIGNAL MATH FOR MODULATION //\r\n // ========================== //\r\n\r\n // return sigChain(this, scale, thisChain, nextChain, Scale);\r\n var sigChain = function(o, mathObj, thisChain, nextChain, type) {\r\n var chainSource = o.oscillator;\r\n // if this type of math already exists in the chain, replace it\r\n for (var i in o.mathOps) {\r\n if (o.mathOps[i] instanceof type) {\r\n chainSource.disconnect();\r\n o.mathOps[i].dispose();\r\n thisChain = i;\r\n // assume nextChain is output gain node unless...\r\n if (thisChain < o.mathOps.length - 2) {\r\n nextChain = o.mathOps[i+1];\r\n }\r\n }\r\n }\r\n if (thisChain === o.mathOps.length - 1) {\r\n o.mathOps.push(nextChain);\r\n }\r\n // assume source is the oscillator unless i > 0\r\n if (i > 0) {\r\n chainSource = o.mathOps[i-1];\r\n }\r\n chainSource.disconnect();\r\n chainSource.connect(mathObj);\r\n mathObj.connect(nextChain);\r\n o.mathOps[thisChain] = mathObj;\r\n return o;\r\n };\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method again\r\n * will override the initial add() with a new value.\r\n *\r\n * @method add\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n *\r\n */\r\n p5.Oscillator.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Oscillator's output amplitude\r\n * by a fixed value (i.e. turn it up!). Calling this method\r\n * again will override the initial mult() with a new value.\r\n *\r\n * @method mult\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with multiplied output\r\n */\r\n p5.Oscillator.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this oscillator's amplitude values to a given\r\n * range, and return the oscillator. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Oscillator\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n */\r\n p5.Oscillator.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, scale, thisChain, nextChain, Scale);\r\n\r\n // this.output.disconnect();\r\n // this.output.connect(scale)\r\n };\r\n\r\n // ============================== //\r\n // SinOsc, TriOsc, SqrOsc, SawOsc //\r\n // ============================== //\r\n\r\n /**\r\n * Constructor: new p5.SinOsc().\r\n * This creates a Sine Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sine')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sine').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SinOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SinOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sine');\r\n };\r\n\r\n p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.TriOsc().\r\n * This creates a Triangle Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('triangle')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('triangle').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.TriOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.TriOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'triangle');\r\n };\r\n\r\n p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SawOsc().\r\n * This creates a SawTooth Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sawtooth')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sawtooth').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SawOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SawOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sawtooth');\r\n };\r\n\r\n p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SqrOsc().\r\n * This creates a Square Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('square')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('square').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SqrOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SqrOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'square');\r\n };\r\n\r\n p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline class for scheduling and maintaining state\n\t * along a timeline. All events must have a \"time\" property. \n\t * Internally, events are stored in time order for fast \n\t * retrieval.\n\t * @extends {Tone}\n\t * @param {Positive} [memory=Infinity] The number of previous events that are retained.\n\t */\n\tTone.Timeline = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"memory\"], Tone.Timeline.defaults);\n\n\t\t/**\n\t\t * The array of scheduled timeline events\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._timeline = [];\n\n\t\t/**\n\t\t * An array of items to remove from the list. \n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._toRemove = [];\n\n\t\t/**\n\t\t * Flag if the tieline is mid iteration\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._iterating = false;\n\n\t\t/**\n\t\t * The memory of the timeline, i.e.\n\t\t * how many events in the past it will retain\n\t\t * @type {Positive}\n\t\t */\n\t\tthis.memory = options.memory;\n\t};\n\n\tTone.extend(Tone.Timeline);\n\n\t/**\n\t * the default parameters\n\t * @static\n\t * @const\n\t */\n\tTone.Timeline.defaults = {\n\t\t\"memory\" : Infinity\n\t};\n\n\t/**\n\t * The number of items in the timeline.\n\t * @type {Number}\n\t * @memberOf Tone.Timeline#\n\t * @name length\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Timeline.prototype, \"length\", {\n\t\tget : function(){\n\t\t\treturn this._timeline.length;\n\t\t}\n\t});\n\n\t/**\n\t * Insert an event object onto the timeline. Events must have a \"time\" attribute.\n\t * @param {Object} event The event object to insert into the \n\t * timeline. \n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.add = function(event){\n\t\t//the event needs to have a time attribute\n\t\tif (this.isUndef(event.time)){\n\t\t\tthrow new Error(\"Tone.Timeline: events must have a time attribute\");\n\t\t}\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(event.time);\n\t\t\tthis._timeline.splice(index + 1, 0, event);\n\t\t} else {\n\t\t\tthis._timeline.push(event);\t\t\t\n\t\t}\n\t\t//if the length is more than the memory, remove the previous ones\n\t\tif (this.length > this.memory){\n\t\t\tvar diff = this.length - this.memory;\n\t\t\tthis._timeline.splice(0, diff);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove an event from the timeline.\n\t * @param {Object} event The event object to remove from the list.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.remove = function(event){\n\t\tif (this._iterating){\n\t\t\tthis._toRemove.push(event);\n\t\t} else {\n\t\t\tvar index = this._timeline.indexOf(event);\n\t\t\tif (index !== -1){\n\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the nearest event whose time is less than or equal to the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object set after that time.\n\t */\n\tTone.Timeline.prototype.get = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index !== -1){\n\t\t\treturn this._timeline[index];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Return the first event in the timeline without removing it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.peek = function(){\n\t\treturn this._timeline[0];\n\t};\n\n\t/**\n\t * Return the first event in the timeline and remove it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.shift = function(){\n\t\treturn this._timeline.shift();\n\t};\n\n\t/**\n\t * Get the event which is scheduled after the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object after the given time\n\t */\n\tTone.Timeline.prototype.getAfter = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index + 1 < this._timeline.length){\n\t\t\treturn this._timeline[index + 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Get the event before the event at the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object before the given time\n\t */\n\tTone.Timeline.prototype.getBefore = function(time){\n\t\tvar len = this._timeline.length;\n\t\t//if it's after the last item, return the last item\n\t\tif (len > 0 && this._timeline[len - 1].time < time){\n\t\t\treturn this._timeline[len - 1];\n\t\t}\n\t\tvar index = this._search(time);\n\t\tif (index - 1 >= 0){\n\t\t\treturn this._timeline[index - 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Cancel events after the given time\n\t * @param {Number} time The time to query.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancel = function(after){\n\t\tif (this._timeline.length > 1){\n\t\t\tvar index = this._search(after);\n\t\t\tif (index >= 0){\n\t\t\t\tif (this._timeline[index].time === after){\n\t\t\t\t\t//get the first item with that time\n\t\t\t\t\tfor (var i = index; i >= 0; i--){\n\t\t\t\t\t\tif (this._timeline[i].time === after){\n\t\t\t\t\t\t\tindex = i;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index);\n\t\t\t\t} else {\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t} else if (this._timeline.length === 1){\n\t\t\t//the first item's time\n\t\t\tif (this._timeline[0].time >= after){\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancel events before or equal to the given time.\n\t * @param {Number} time The time to cancel before.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancelBefore = function(time){\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(time);\n\t\t\tif (index >= 0){\n\t\t\t\tthis._timeline = this._timeline.slice(index + 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Does a binary serach on the timeline array and returns the \n\t * nearest event index whose time is after or equal to the given time.\n\t * If a time is searched before the first index in the timeline, -1 is returned.\n\t * If the time is after the end, the index of the last item is returned.\n\t * @param {Number} time \n\t * @return {Number} the index in the timeline array \n\t * @private\n\t */\n\tTone.Timeline.prototype._search = function(time){\n\t\tvar beginning = 0;\n\t\tvar len = this._timeline.length;\n\t\tvar end = len;\n\t\tif (len > 0 && this._timeline[len - 1].time <= time){\n\t\t\treturn len - 1;\n\t\t}\n\t\twhile (beginning < end){\n\t\t\t// calculate the midpoint for roughly equal partition\n\t\t\tvar midPoint = Math.floor(beginning + (end - beginning) / 2);\n\t\t\tvar event = this._timeline[midPoint];\n\t\t\tvar nextEvent = this._timeline[midPoint + 1];\n\t\t\tif (event.time === time){\n\t\t\t\t//choose the last one that has the same time\n\t\t\t\tfor (var i = midPoint; i < this._timeline.length; i++){\n\t\t\t\t\tvar testEvent = this._timeline[i];\n\t\t\t\t\tif (testEvent.time === time){\n\t\t\t\t\t\tmidPoint = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time < time && nextEvent.time > time){\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time > time){\n\t\t\t\t//search lower\n\t\t\t\tend = midPoint;\n\t\t\t} else if (event.time < time){\n\t\t\t\t//search upper\n\t\t\t\tbeginning = midPoint + 1;\n\t\t\t} \n\t\t}\n\t\treturn -1;\n\t};\n\n\t/**\n\t * Internal iterator. Applies extra safety checks for \n\t * removing items from the array. \n\t * @param {Function} callback \n\t * @param {Number=} lowerBound \n\t * @param {Number=} upperBound \n\t * @private\n\t */\n\tTone.Timeline.prototype._iterate = function(callback, lowerBound, upperBound){\n\t\tthis._iterating = true;\n\t\tlowerBound = this.defaultArg(lowerBound, 0);\n\t\tupperBound = this.defaultArg(upperBound, this._timeline.length - 1);\n\t\tfor (var i = lowerBound; i <= upperBound; i++){\n\t\t\tcallback(this._timeline[i]);\n\t\t}\n\t\tthis._iterating = false;\n\t\tif (this._toRemove.length > 0){\n\t\t\tfor (var j = 0; j < this._toRemove.length; j++){\n\t\t\t\tvar index = this._timeline.indexOf(this._toRemove[j]);\n\t\t\t\tif (index !== -1){\n\t\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._toRemove = [];\n\t\t}\n\t};\n\n\t/**\n\t * Iterate over everything in the array\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEach = function(callback){\n\t\tthis._iterate(callback);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or before the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachBefore = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(callback, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array after the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAfter = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or after the given time. Similar to \n\t * forEachAfter, but includes the item(s) at the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachFrom = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\t//work backwards until the event time is less than time\n\t\twhile (lowerBound >= 0 && this._timeline[lowerBound].time >= time){\n\t\t\tlowerBound--;\n\t\t}\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at the given time\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAtTime = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(function(event){\n\t\t\t\tif (event.time === time){\n\t\t\t\t\tcallback(event);\n\t\t\t\t} \n\t\t\t}, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._timeline = null;\n\t\tthis._toRemove = null;\n\t};\n\n\treturn Tone.Timeline;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Negate the incoming signal. i.e. an input signal of 10 will output -10\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var neg = new Tone.Negate();\n\t * var sig = new Tone.Signal(-2).connect(neg);\n\t * //output of neg is positive 2. \n\t */\n\tTone.Negate = function(){\n\t\t/**\n\t\t * negation is done by multiplying by -1\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = this.input = this.output = new Tone.Multiply(-1);\n\t};\n\n\tTone.extend(Tone.Negate, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Negate} this\n\t */\n\tTone.Negate.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Negate;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Multiply\", \"Tone/signal/WaveShaper\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class GreaterThanZero outputs 1 when the input is strictly greater than zero\n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var gt0 = new Tone.GreaterThanZero();\n\t * var sig = new Tone.Signal(0.01).connect(gt0);\n\t * //the output of gt0 is 1. \n\t * sig.value = 0;\n\t * //the output of gt0 is 0. \n\t */\n\tTone.GreaterThanZero = function(){\n\t\t\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._thresh = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val <= 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}, 127);\n\n\t\t/**\n\t\t * scale the first thresholded signal by a large value.\n\t\t * this will help with values which are very close to 0\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(10000);\n\n\t\t//connections\n\t\tthis._scale.connect(this._thresh);\n\t};\n\n\tTone.extend(Tone.GreaterThanZero, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThanZero} this\n\t */\n\tTone.GreaterThanZero.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\tthis._thresh.dispose();\n\t\tthis._thresh = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThanZero;\n});","define([\"Tone/core/Tone\", \"Tone/signal/TimelineSignal\", \"Tone/core/TimelineState\", \n\t\"Tone/core/Emitter\", \"Tone/core/Context\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A sample accurate clock which provides a callback at the given rate. \n\t * While the callback is not sample-accurate (it is still susceptible to\n\t * loose JS timing), the time passed in as the argument to the callback\n\t * is precise. For most applications, it is better to use Tone.Transport\n\t * instead of the Clock by itself since you can synchronize multiple callbacks.\n\t *\n\t * \t@constructor\n\t * @extends {Tone.Emitter}\n\t * \t@param {function} callback The callback to be invoked with the time of the audio event\n\t * \t@param {Frequency} frequency The rate of the callback\n\t * \t@example\n\t * //the callback will be invoked approximately once a second\n\t * //and will print the time exactly once a second apart.\n\t * var clock = new Tone.Clock(function(time){\n\t * \tconsole.log(time);\n\t * }, 1);\n\t */\n\tTone.Clock = function(){\n\n\t\tTone.Emitter.call(this);\n\n\t\tvar options = this.optionsObject(arguments, [\"callback\", \"frequency\"], Tone.Clock.defaults);\n\n\t\t/**\n\t\t * The callback function to invoke at the scheduled tick.\n\t\t * @type {Function}\n\t\t */\n\t\tthis.callback = options.callback;\n\n\t\t/**\n\t\t * The next time the callback is scheduled.\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._nextTick = 0;\n\n\t\t/**\n\t\t * The last state of the clock.\n\t\t * @type {State}\n\t\t * @private\n\t\t */\n\t\tthis._lastState = Tone.State.Stopped;\n\n\t\t/**\n\t\t * The rate the callback function should be invoked. \n\t\t * @type {BPM}\n\t\t * @signal\n\t\t */\n\t\tthis.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);\n\t\tthis._readOnly(\"frequency\");\n\n\t\t/**\n\t\t * The number of times the callback was invoked. Starts counting at 0\n\t\t * and increments after the callback was invoked. \n\t\t * @type {Ticks}\n\t\t * @readOnly\n\t\t */\n\t\tthis.ticks = 0;\n\n\t\t/**\n\t\t * The state timeline\n\t\t * @type {Tone.TimelineState}\n\t\t * @private\n\t\t */\n\t\tthis._state = new Tone.TimelineState(Tone.State.Stopped);\n\n\t\t/**\n\t\t * The loop function bound to its context. \n\t\t * This is necessary to remove the event in the end.\n\t\t * @type {Function}\n\t\t * @private\n\t\t */\n\t\tthis._boundLoop = this._loop.bind(this);\n\n\t\t//bind a callback to the worker thread\n \tthis.context.on(\"tick\", this._boundLoop);\n\t};\n\n\tTone.extend(Tone.Clock, Tone.Emitter);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Clock.defaults = {\n\t\t\"callback\" : Tone.noOp,\n\t\t\"frequency\" : 1,\n\t\t\"lookAhead\" : \"auto\",\n\t};\n\n\t/**\n\t * Returns the playback state of the source, either \"started\", \"stopped\" or \"paused\".\n\t * @type {Tone.State}\n\t * @readOnly\n\t * @memberOf Tone.Clock#\n\t * @name state\n\t */\n\tObject.defineProperty(Tone.Clock.prototype, \"state\", {\n\t\tget : function(){\n\t\t\treturn this._state.getValueAtTime(this.now());\n\t\t}\n\t});\n\n\t/**\n\t * Start the clock at the given time. Optionally pass in an offset\n\t * of where to start the tick counter from.\n\t * @param {Time} time The time the clock should start\n\t * @param {Ticks=} offset Where the tick counter starts counting from.\n\t * @return {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.start = function(time, offset){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) !== Tone.State.Started){\n\t\t\tthis._state.add({\n\t\t\t\t\"state\" : Tone.State.Started, \n\t\t\t\t\"time\" : time,\n\t\t\t\t\"offset\" : offset\n\t\t\t});\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * Stop the clock. Stopping the clock resets the tick counter to 0.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t * @example\n\t * clock.stop();\n\t */\n\tTone.Clock.prototype.stop = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tthis._state.cancel(time);\n\t\tthis._state.setStateAtTime(Tone.State.Stopped, time);\n\t\treturn this;\t\n\t};\n\n\n\t/**\n\t * Pause the clock. Pausing does not reset the tick counter.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.pause = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) === Tone.State.Started){\n\t\t\tthis._state.setStateAtTime(Tone.State.Paused, time);\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * The scheduling loop.\n\t * @param {Number} time The current page time starting from 0\n\t * when the page was loaded.\n\t * @private\n\t */\n\tTone.Clock.prototype._loop = function(){\n\t\t//get the frequency value to compute the value of the next loop\n\t\tvar now = this.now();\n\t\t//if it's started\n\t\tvar lookAhead = this.context.lookAhead;\n\t\tvar updateInterval = this.context.updateInterval;\n\t\tvar lagCompensation = this.context.lag * 2;\n\t\tvar loopInterval = now + lookAhead + updateInterval + lagCompensation;\n\t\twhile (loopInterval > this._nextTick && this._state){\n\t\t\tvar currentState = this._state.getValueAtTime(this._nextTick);\n\t\t\tif (currentState !== this._lastState){\n\t\t\t\tthis._lastState = currentState;\n\t\t\t\tvar event = this._state.get(this._nextTick);\n\t\t\t\t// emit an event\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\t//correct the time\n\t\t\t\t\tthis._nextTick = event.time;\n\t\t\t\t\tif (!this.isUndef(event.offset)){\n\t\t\t\t\t\tthis.ticks = event.offset;\n\t\t\t\t\t}\n\t\t\t\t\tthis.emit(\"start\", event.time, this.ticks);\n\t\t\t\t} else if (currentState === Tone.State.Stopped){\n\t\t\t\t\tthis.ticks = 0;\n\n\t\t\t\t\tthis.emit(\"stop\", event.time);\n\t\t\t\t} else if (currentState === Tone.State.Paused){\n\t\t\t\t\tthis.emit(\"pause\", event.time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar tickTime = this._nextTick;\n\t\t\tif (this.frequency){\n\t\t\t\tthis._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\tthis.callback(tickTime);\n\t\t\t\t\tthis.ticks++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state at the given time.\n\t * @param {Time} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t * @example\n\t * clock.start(\"+0.1\");\n\t * clock.getStateAtTime(\"+0.1\"); //returns \"started\"\n\t */\n\tTone.Clock.prototype.getStateAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\treturn this._state.getValueAtTime(time);\n\t};\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.dispose = function(){\n\t\tTone.Emitter.prototype.dispose.call(this);\n\t\tthis.context.off(\"tick\", this._boundLoop);\n\t\tthis._writable(\"frequency\");\n\t\tthis.frequency.dispose();\n\t\tthis.frequency = null;\n\t\tthis._boundLoop = null;\n\t\tthis._nextTick = Infinity;\n\t\tthis.callback = null;\n\t\tthis._state.dispose();\n\t\tthis._state = null;\n\t};\n\n\treturn Tone.Clock;\n});","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var AudioVoice = require('audioVoice');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n var DEFAULT_SUSTAIN = 0.15;\r\n\r\n /**\r\n * A MonoSynth is used as a single voice for sound synthesis.\r\n * This is a class to be used in conjunction with the PolySynth\r\n * class. Custom synthetisers should be built inheriting from\r\n * this class.\r\n *\r\n * @class p5.MonoSynth\r\n * @constructor\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 0.25;\r\n * // velocity (volume, from 0 to 1)\r\n * var v = 0.2;\r\n *\r\n * monoSynth.play(\"G3\", v, time, dur);\r\n * monoSynth.play(\"C4\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n\r\n p5.MonoSynth = function () {\r\n AudioVoice.call(this);\r\n\r\n this.oscillator = new p5.Oscillator();\r\n\r\n this.env = new p5.Envelope();\r\n this.env.setRange(1, 0);\r\n this.env.setExp(true);\r\n\r\n //set params\r\n this.setADSR(0.02, 0.25, 0.05, 0.35);\r\n\r\n // oscillator --> env --> this.output (gain) --> p5.soundOut\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.output);\r\n\r\n this.env.disconnect();\r\n this.env.setInput(this.output.gain);\r\n\r\n // reset oscillator gain to 1.0\r\n this.oscillator.output.gain.value = 1.0;\r\n\r\n this.oscillator.start();\r\n this.connect();\r\n\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);\r\n\r\n /**\r\n * Play tells the MonoSynth to start playing a note. This method schedules\r\n * the calling of .triggerAttack and .triggerRelease.\r\n *\r\n * @method play\r\n * @for p5.MonoSynth\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 1/6;\r\n * // note velocity (volume, from 0 to 1)\r\n * var v = random();\r\n *\r\n * monoSynth.play(\"Fb3\", v, 0, dur);\r\n * monoSynth.play(\"Gb3\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n *\r\n */\r\n p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) {\r\n this.triggerAttack(note, velocity, ~~secondsFromNow);\r\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @method triggerAttack\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n var secondsFromNow = ~~secondsFromNow;\r\n var freq = noteToFreq(note);\r\n var vel = velocity || 0.1;\r\n this.oscillator.freq(freq, 0, secondsFromNow);\r\n this.env.ramp(this.output.gain, secondsFromNow, vel);\r\n };\r\n\r\n /**\r\n * Trigger the release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @method triggerRelease\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) {\r\n var secondsFromNow = secondsFromNow || 0;\r\n this.env.ramp(this.output.gain, secondsFromNow, 0);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.MonoSynth\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n */\r\n p5.MonoSynth.prototype.setADSR = function (attack,decay,sustain,release) {\r\n this.env.setADSR(attack, decay, sustain, release);\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters\r\n * @property {Number} attack\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} decay\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} sustain\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} release\r\n * @for p5.MonoSynth\r\n */\r\n Object.defineProperties(p5.MonoSynth.prototype, {\r\n 'attack': {\r\n get : function() {\r\n return this.env.aTime;\r\n },\r\n set : function(attack) {\r\n this.env.setADSR(attack, this.env.dTime,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'decay': {\r\n get : function() {\r\n return this.env.dTime;\r\n },\r\n set : function(decay) {\r\n this.env.setADSR(this.env.aTime, decay,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'sustain': {\r\n get : function() {\r\n return this.env.sPercent;\r\n },\r\n set : function(sustain) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n sustain, this.env.rTime);\r\n }\r\n },\r\n 'release': {\r\n get : function() {\r\n return this.env.rTime;\r\n },\r\n set : function(release) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n this.env.sPercent, release);\r\n }\r\n },\r\n });\r\n\r\n\r\n /**\r\n * MonoSynth amp\r\n * @method amp\r\n * @for p5.MonoSynth\r\n * @param {Number} vol desired volume\r\n * @param {Number} [rampTime] Time to reach new volume\r\n * @return {Number} new volume value\r\n */\r\n p5.MonoSynth.prototype.amp = function(vol, rampTime) {\r\n var t = rampTime || 0;\r\n if (typeof vol !== 'undefined') {\r\n this.oscillator.amp(vol, t);\r\n }\r\n return this.oscillator.amp().value;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.MonoSynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n\r\n p5.MonoSynth.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.dispose = function() {\r\n AudioVoice.prototype.dispose.apply(this);\r\n\r\n if (this.env) {\r\n this.env.dispose();\r\n }\r\n if (this.oscillator) {\r\n this.oscillator.dispose();\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\ndefine(function() {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * Base class for monophonic synthesizers. Any extensions of this class\r\n * should follow the API and implement the methods below in order to\r\n * remain compatible with p5.PolySynth();\r\n *\r\n * @class p5.AudioVoice\r\n * @constructor\r\n */\r\n p5.AudioVoice = function () {\r\n\t this.ac = p5sound.audiocontext;\r\n\t this.output = this.ac.createGain();\r\n\t this.connect();\r\n\t p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.amp = function(vol, rampTime) {\r\n };\r\n\r\n /**\r\n * Connect to p5 objects or Web Audio Nodes\r\n * @method connect\r\n * @for p5.AudioVoice\r\n * @param {Object} unit\r\n */\r\n p5.AudioVoice.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect from soundOut\r\n * @method disconnect\r\n * @for p5.AudioVoice\r\n */\r\n p5.AudioVoice.prototype.disconnect = function() {\r\n this.output.disconnect();\r\n };\r\n\r\n p5.AudioVoice.prototype.dispose = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n return p5.AudioVoice;\r\n});\r\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n /**\r\n * An AudioVoice is used as a single voice for sound synthesis.\r\n * The PolySynth class holds an array of AudioVoice, and deals\r\n * with voices allocations, with setting notes to be played, and\r\n * parameters to be set.\r\n *\r\n * @class p5.PolySynth\r\n * @constructor\r\n *\r\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\r\n * the AudioVoice class. Defaults to p5.MonoSynth\r\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 1.5;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * // notes can overlap with each other\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, time += 1/3, dur);\r\n * polySynth.play(\"G3\", vel, time += 1/3, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n p5.PolySynth = function(audioVoice, maxVoices) {\r\n //audiovoices will contain maxVoices many monophonic synths\r\n this.audiovoices = [];\r\n\r\n /**\r\n * An object that holds information about which notes have been played and\r\n * which notes are currently being played. New notes are added as keys\r\n * on the fly. While a note has been attacked, but not released, the value of the\r\n * key is the audiovoice which is generating that note. When notes are released,\r\n * the value of the key becomes undefined.\r\n * @property notes\r\n */\r\n this.notes = {};\r\n\r\n //indices of the most recently used, and least recently used audiovoice\r\n this._newest = 0;\r\n this._oldest = 0;\r\n\r\n /**\r\n * A PolySynth must have at least 1 voice, defaults to 8\r\n * @property polyvalue\r\n */\r\n this.maxVoices = maxVoices || 8;\r\n\r\n /**\r\n * Monosynth that generates the sound for each note that is triggered. The\r\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\r\n * @property AudioVoice\r\n */\r\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\r\n\r\n /**\r\n * This value must only change as a note is attacked or released. Due to delay\r\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\r\n\t * @private\r\n * @property {Tone.TimelineSignal} _voicesInUse\r\n */\r\n this._voicesInUse = new TimelineSignal(0);\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n this.connect();\r\n\r\n //Construct the appropriate number of audiovoices\r\n this._allocateVoices();\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Construct the appropriate number of audiovoices\r\n * @private\r\n * @for p5.PolySynth\r\n * @method _allocateVoices\r\n */\r\n p5.PolySynth.prototype._allocateVoices = function() {\r\n for(var i = 0; i< this.maxVoices; i++) {\r\n this.audiovoices.push(new this.AudioVoice());\r\n this.audiovoices[i].disconnect();\r\n this.audiovoices[i].connect(this.output);\r\n }\r\n };\r\n\r\n /**\r\n * Play a note by triggering noteAttack and noteRelease with sustain time\r\n *\r\n * @method play\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 0.1;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, 0, dur);\r\n * polySynth.play(\"G3\", vel, 0, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.play = function (note,velocity, secondsFromNow, susTime) {\r\n var susTime = susTime || 1;\r\n this.noteAttack(note, velocity, secondsFromNow);\r\n this.noteRelease(note, secondsFromNow + susTime);\r\n };\r\n\r\n\r\n /**\r\n * noteADSR sets the envelope for a specific note that has just been triggered.\r\n * Using this method modifies the envelope of whichever audiovoice is being used\r\n * to play the desired note. The envelope should be reset before noteRelease is called\r\n * in order to prevent the modified envelope from being used on other notes.\r\n *\r\n * @method noteADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [note] Midi note on which ADSR should be set.\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n\r\n p5.PolySynth.prototype.noteADSR = function (note,a,d,s,r,timeFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var timeFromNow = timeFromNow || 0;\r\n var t = now + timeFromNow\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].setADSR(a,d,s,r);\r\n };\r\n\r\n\r\n /**\r\n * Set the PolySynths global envelope. This method modifies the envelopes of each\r\n * monosynth so that all notes are played with this envelope.\r\n *\r\n * @method setADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n p5.PolySynth.prototype.setADSR = function(a,d,s,r) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.setADSR(a,d,s,r);\r\n });\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of a MonoSynth.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @method noteAttack\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\r\n * @param {Number} [secondsFromNow] time from now (in seconds)\r\n * @example\r\n *
\r\n * var polySynth = new p5.PolySynth();\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) {\r\n //this value goes to the audiovoices which handle their own scheduling\r\n var secondsFromNow = ~~secondsFromNow;\r\n\r\n //this value is used by this._voicesInUse\r\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\r\n\r\n //Convert note to frequency if necessary. This is because entries into this.notes\r\n //should be based on frequency for the sake of consistency.\r\n var note = noteToFreq(_note);\r\n var velocity = _velocity || 0.1;\r\n\r\n var currentVoice;\r\n\r\n //Release the note if it is already playing\r\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\r\n this.noteRelease(note, 0);\r\n }\r\n\r\n //Check to see how many voices are in use at the time the note will start\r\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\r\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\r\n }\r\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\r\n //with a new note\r\n else {\r\n currentVoice = this._oldest;\r\n\r\n var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value);\r\n this.noteRelease(oldestNote);\r\n this._oldest = ( this._oldest + 1 ) % (this.maxVoices - 1);\r\n }\r\n\r\n //Overrite the entry in the notes object. A note (frequency value)\r\n //corresponds to the index of the audiovoice that is playing it\r\n this.notes[note] = new TimelineSignal();\r\n this.notes[note].setValueAtTime(currentVoice, acTime);\r\n\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //Add 1 and schedule this value at time 't', when this note will start playing\r\n var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value;\r\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\r\n\r\n //Then update all scheduled values that follow to increase by 1\r\n this._updateAfter(acTime, 1);\r\n\r\n this._newest = currentVoice;\r\n //The audiovoice handles the actual scheduling of the note\r\n if (typeof velocity === 'number') {\r\n var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2;\r\n velocity = velocity > maxRange ? maxRange : velocity;\r\n }\r\n this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);\r\n };\r\n\r\n /**\r\n * Private method to ensure accurate values of this._voicesInUse\r\n * Any time a new value is scheduled, it is necessary to increment all subsequent\r\n * scheduledValues after attack, and decrement all subsequent\r\n * scheduledValues after release\r\n *\r\n * @private\r\n * @for p5.PolySynth\r\n * @param {[type]} time [description]\r\n * @param {[type]} value [description]\r\n * @return {[type]} [description]\r\n */\r\n p5.PolySynth.prototype._updateAfter = function(time, value) {\r\n if(this._voicesInUse._searchAfter(time) === null) {\r\n return;\r\n } else{\r\n this._voicesInUse._searchAfter(time).value += value;\r\n var nextTime = this._voicesInUse._searchAfter(time).time;\r\n this._updateAfter(nextTime, value);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Trigger the Release of an AudioVoice note. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method noteRelease\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * If no value is provided, all notes will be released.\r\n * @param {Number} [secondsFromNow] time to trigger the release\r\n * @example\r\n *
\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n * var polySynth = new p5.PolySynth();\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n *\r\n */\r\n p5.PolySynth.prototype.noteRelease = function (_note,secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n // if a note value is not provided, release all voices\r\n if (!_note) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.triggerRelease(tFromNow)\r\n });\r\n this._voicesInUse.setValueAtTime(0, t);\r\n for (var n in this.notes) {\r\n this.notes[n].dispose();\r\n delete this.notes[n];\r\n }\r\n return;\r\n }\r\n\r\n //Make sure note is in frequency inorder to query the this.notes object\r\n var note = noteToFreq(_note);\r\n\r\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\r\n console.warn('Cannot release a note that is not already playing');\r\n } else {\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //subtract 1 and schedule this value at time 't', when this note will stop playing\r\n var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);\r\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\r\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\r\n if (previousVal > 0) {\r\n this._updateAfter(t, -1);\r\n }\r\n\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].triggerRelease(tFromNow);\r\n this.notes[note].dispose();\r\n delete this.notes[note];\r\n\r\n this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\r\n }\r\n\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.PolySynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.PolySynth.prototype.connect = function (unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.dispose = function() {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.dispose();\r\n });\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n require('audioworklet-polyfill');\r\n require('shims');\r\n require('audiocontext');\r\n var p5SOUND = require('master');\r\n require('helpers');\r\n require('errorHandler');\r\n require('audioWorklet');\r\n require('panner');\r\n require('soundfile');\r\n require('amplitude');\r\n require('fft');\r\n require('signal');\r\n require('oscillator');\r\n require('envelope');\r\n require('pulse');\r\n require('noise');\r\n require('audioin');\r\n require('filter');\r\n require('eq');\r\n require('panner3d');\r\n require('listener3d');\r\n require('delay');\r\n require('reverb');\r\n require('metro');\r\n require('looper');\r\n require('soundLoop');\r\n require('compressor');\r\n require('soundRecorder');\r\n require('peakDetect');\r\n require('gain');\r\n require('monosynth');\r\n require('polysynth');\r\n require('distortion');\r\n require('audioVoice');\r\n require('monosynth');\r\n require('polysynth');\r\n\r\n return p5SOUND;\r\n\r\n});\r\n","!function(){var e,t=[];function r(e){var r=this,n={},i=-1;this.parameters.forEach(function(e,o){var s=t[++i]||(t[i]=new Float32Array(r.bufferSize));s.fill(e.value),n[o]=s}),this.processor.realm.exec(\"self.sampleRate=sampleRate=\"+this.context.sampleRate+\";self.currentTime=currentTime=\"+this.context.currentTime);var s=o(e.inputBuffer),a=o(e.outputBuffer);this.instance.process([s],[a],n)}function o(e){for(var t=[],r=0;r= this.sampleLimit) {\\n this.stop();\\n return true;\\n }\\n\\n var input = inputs[0];\\n var output = outputs[0];\\n\\n for (var channel = 0; channel < output.length; ++channel) {\\n var inputChannel = input[channel];\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannel);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n }\\n\\n this.recordedSamples += output[0].length;\\n return true;\\n }\\n }, {\\n key: \\\"record\\\",\\n value: function record(duration) {\\n if (duration) {\\n this.sampleLimit = Math.round(duration * sampleRate);\\n }\\n\\n this.recording = true;\\n }\\n }, {\\n key: \\\"stop\\\",\\n value: function stop() {\\n this.recording = false;\\n var buffers = this.getBuffers();\\n var leftBuffer = buffers[0].buffer;\\n var rightBuffer = buffers[1].buffer;\\n this.port.postMessage({\\n name: 'buffers',\\n leftBuffer: leftBuffer,\\n rightBuffer: rightBuffer\\n }, [leftBuffer, rightBuffer]);\\n this.clear();\\n }\\n }, {\\n key: \\\"getBuffers\\\",\\n value: function getBuffers() {\\n var buffers = [];\\n buffers.push(this.mergeBuffers(this.leftBuffers));\\n buffers.push(this.mergeBuffers(this.rightBuffers));\\n return buffers;\\n }\\n }, {\\n key: \\\"mergeBuffers\\\",\\n value: function mergeBuffers(channelBuffer) {\\n var result = new Float32Array(this.recordedSamples);\\n var offset = 0;\\n var lng = channelBuffer.length;\\n\\n for (var i = 0; i < lng; i++) {\\n var buffer = channelBuffer[i];\\n result.set(buffer, offset);\\n offset += buffer.length;\\n }\\n\\n return result;\\n }\\n }, {\\n key: \\\"clear\\\",\\n value: function clear() {\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.recordedSamples = 0;\\n this.sampleLimit = null;\\n }\\n }]);\\n\\n return RecorderProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);\"","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n\r\n // Stereo panner\r\n // if there is a stereo panner node use it\r\n if(typeof ac.createStereoPanner !== 'undefined') {\r\n p5.Panner = function (input, output) {\r\n this.stereoPanner = this.input = ac.createStereoPanner();\r\n input.connect(this.stereoPanner);\r\n this.stereoPanner.connect(output);\r\n };\r\n\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n\r\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\r\n };\r\n\r\n //not implemented because stereopanner\r\n //node does not require this and will automatically\r\n //convert single channel or multichannel to stereo.\r\n //tested with single and stereo, not with (>2) multichannel\r\n p5.Panner.prototype.inputChannels = function() {};\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.stereoPanner.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.stereoPanner) {\r\n this.stereoPanner.disconnect();\r\n }\r\n };\r\n\r\n } else {\r\n // if there is no createStereoPanner object\r\n // such as in safari 7.1.7 at the time of writing this\r\n // use this method to create the effect\r\n p5.Panner = function(input, output, numInputChannels) {\r\n this.input = ac.createGain();\r\n input.connect(this.input);\r\n\r\n this.left = ac.createGain();\r\n this.right = ac.createGain();\r\n this.left.channelInterpretation = 'discrete';\r\n this.right.channelInterpretation = 'discrete';\r\n\r\n // if input is stereo\r\n if (numInputChannels > 1) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n this.input.connect(this.splitter);\r\n\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n else {\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n }\r\n\r\n this.output = ac.createChannelMerger(2);\r\n this.left.connect(this.output, 0, 1);\r\n this.right.connect(this.output, 0, 0);\r\n this.output.connect(output);\r\n };\r\n\r\n // -1 is left, +1 is right\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n var v = (val + 1) / 2;\r\n var rightVal = Math.cos(v*Math.PI/2);\r\n var leftVal = Math.sin(v * Math.PI/2);\r\n this.left.gain.linearRampToValueAtTime(leftVal, t);\r\n this.right.gain.linearRampToValueAtTime(rightVal, t);\r\n };\r\n\r\n p5.Panner.prototype.inputChannels = function(numChannels) {\r\n if (numChannels === 1) {\r\n this.input.disconnect();\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n } else if (numChannels === 2) {\r\n if (typeof(this.splitter === 'undefined')) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n }\r\n this.input.disconnect();\r\n this.input.connect(this.splitter);\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n };\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.output.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var CustomError = require('errorHandler');\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n var midiToFreq = require('helpers').midiToFreq;\r\n var convertToWav = require('helpers').convertToWav;\r\n\r\n /**\r\n *
SoundFile object with a path to a file.
\r\n *\r\n *
The p5.SoundFile may not be available immediately because\r\n * it loads the file information asynchronously.
\r\n *\r\n *
To do something with the sound as soon as it loads\r\n * pass the name of a function as the second parameter.
\r\n *\r\n *
Only one file path is required. However, audio file formats\r\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\r\n * web browsers. If you want to ensure compatability, instead of a single\r\n * file path, you may include an Array of filepaths, and the browser will\r\n * choose a format that works.
\r\n *\r\n * @class p5.SoundFile\r\n * @constructor\r\n * @param {String|Array} path path to a sound file (String). Optionally,\r\n * you may include multiple file formats in\r\n * an array. Alternately, accepts an object\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if file fails to\r\n * load. This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\r\n * is loading. That function will\r\n * receive progress of the request to\r\n * load the sound file\r\n * (between 0 and 1) as its first\r\n * parameter. This progress\r\n * does not account for the additional\r\n * time needed to decode the audio data.\r\n *\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile = function(paths, onload, onerror, whileLoading) {\r\n if (typeof paths !== 'undefined') {\r\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\r\n var path = p5.prototype._checkFileFormats(paths);\r\n this.url = path;\r\n }\r\n else if(typeof paths === 'object') {\r\n if (!(window.File && window.FileReader && window.FileList && window.Blob)) {\r\n // The File API isn't supported in this browser\r\n throw 'Unable to load file because the File API is not supported';\r\n }\r\n }\r\n\r\n // if type is a p5.File...get the actual file\r\n if (paths.file) {\r\n paths = paths.file;\r\n }\r\n\r\n this.file = paths;\r\n }\r\n\r\n // private _onended callback, set by the method: onended(callback)\r\n this._onended = function() {};\r\n\r\n this._looping = false;\r\n this._playing = false;\r\n this._paused = false;\r\n this._pauseTime = 0;\r\n\r\n // cues for scheduling events with addCue() removeCue()\r\n this._cues = [];\r\n this._cueIDCounter = 0;\r\n\r\n // position of the most recently played sample\r\n this._lastPos = 0;\r\n this._counterNode = null;\r\n this._scopeNode = null;\r\n\r\n // array of sources so that they can all be stopped!\r\n this.bufferSourceNodes = [];\r\n\r\n // current source\r\n this.bufferSourceNode = null;\r\n\r\n this.buffer = null;\r\n this.playbackRate = 1;\r\n\r\n this.input = p5sound.audiocontext.createGain();\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.reversed = false;\r\n\r\n // start and end of playback / loop\r\n this.startTime = 0;\r\n this.endTime = null;\r\n this.pauseTime = 0;\r\n\r\n // \"restart\" would stop playback before retriggering\r\n this.mode = 'sustain';\r\n\r\n // time that playback was started, in millis\r\n this.startMillis = null;\r\n\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.panner = new p5.Panner(this.output, p5sound.input, 2);\r\n\r\n // it is possible to instantiate a soundfile with no path\r\n if (this.url || this.file) {\r\n this.load(onload, onerror);\r\n }\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n\r\n if (typeof whileLoading === 'function') {\r\n this._whileLoading = whileLoading;\r\n } else {\r\n this._whileLoading = function() {};\r\n }\r\n\r\n this._onAudioProcess = _onAudioProcess.bind(this);\r\n this._clearOnEnd = _clearOnEnd.bind(this);\r\n };\r\n\r\n // register preload handling of loadSound\r\n p5.prototype.registerPreloadMethod('loadSound', p5.prototype);\r\n\r\n /**\r\n * loadSound() returns a new p5.SoundFile from a specified\r\n * path. If called during preload(), the p5.SoundFile will be ready\r\n * to play in time for setup() and draw(). If called outside of\r\n * preload, the p5.SoundFile will not be ready immediately, so\r\n * loadSound accepts a callback as the second parameter. Using a\r\n * \r\n * local server is recommended when loading external files.\r\n *\r\n * @method loadSound\r\n * @for p5\r\n * @param {String|Array} path Path to the sound file, or an array with\r\n * paths to soundfiles in multiple formats\r\n * i.e. ['sound.ogg', 'sound.mp3'].\r\n * Alternately, accepts an object: either\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is\r\n * an error loading the file.\r\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\r\n * This function will receive the percentage loaded\r\n * so far, from 0.0 to 1.0.\r\n * @return {SoundFile} Returns a p5.SoundFile\r\n * @example\r\n *
\r\n */\r\n p5.prototype.loadSound = function(path, callback, onerror, whileLoading) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined' ) {\r\n window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n\r\n var self = this;\r\n var s = new p5.SoundFile(path, function() {\r\n if(typeof callback === 'function') {\r\n callback.apply(self, arguments);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, onerror, whileLoading);\r\n\r\n return s;\r\n };\r\n\r\n /**\r\n * This is a helper function that the p5.SoundFile calls to load\r\n * itself. Accepts a callback (the name of another function)\r\n * as an optional parameter.\r\n *\r\n * @private\r\n * @for p5.SoundFile\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is an error\r\n */\r\n p5.SoundFile.prototype.load = function(callback, errorCallback) {\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n\r\n if (this.url !== undefined && this.url !== '') {\r\n var request = new XMLHttpRequest();\r\n request.addEventListener('progress', function(evt) {\r\n self._updateProgress(evt);\r\n }, false);\r\n request.open('GET', this.url, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on sucess loading file:\r\n if (!self.panner) return;\r\n ac.decodeAudioData(request.response,\r\n // success decoding buffer:\r\n function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n if (!self.panner) return;\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n if (!self.panner) return;\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url + '. The request status was: ' +\r\n request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n\r\n request.send();\r\n }\r\n else if (this.file !== undefined) {\r\n var reader = new FileReader();\r\n reader.onload = function() {\r\n if (!self.panner) return;\r\n ac.decodeAudioData(reader.result, function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n });\r\n };\r\n reader.onerror = function(e) {\r\n if (!self.panner) return;\r\n if (onerror) {\r\n onerror(e);\r\n }\r\n };\r\n reader.readAsArrayBuffer(this.file);\r\n }\r\n };\r\n\r\n // TO DO: use this method to create a loading bar that shows progress during file upload/decode.\r\n p5.SoundFile.prototype._updateProgress = function(evt) {\r\n if (evt.lengthComputable) {\r\n var percentComplete = evt.loaded / evt.total * 0.99;\r\n this._whileLoading(percentComplete, evt);\r\n // ...\r\n } else {\r\n // Unable to compute progress information since the total size is unknown\r\n this._whileLoading('size unknown');\r\n }\r\n };\r\n\r\n /**\r\n * Returns true if the sound file finished loading successfully.\r\n *\r\n * @method isLoaded\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLoaded = function() {\r\n if (this.buffer) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n };\r\n\r\n /**\r\n * Play the p5.SoundFile\r\n *\r\n * @method play\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) amplitude (volume)\r\n * of playback\r\n * @param {Number} [cueStart] (optional) cue start time in seconds\r\n * @param {Number} [duration] (optional) duration of playback in seconds\r\n */\r\n p5.SoundFile.prototype.play = function(startTime, rate, amp, _cueStart, duration) {\r\n if (!this.output) {\r\n console.warn('SoundFile.play() called after dispose');\r\n return;\r\n }\r\n\r\n var self = this;\r\n var now = p5sound.audiocontext.currentTime;\r\n var cueStart, cueEnd;\r\n var time = startTime || 0;\r\n if (time < 0) {\r\n time = 0;\r\n }\r\n\r\n time = time + now;\r\n\r\n if (typeof rate !== 'undefined') {\r\n this.rate(rate);\r\n }\r\n\r\n if (typeof amp !== 'undefined') {\r\n this.setVolume(amp);\r\n }\r\n\r\n // TO DO: if already playing, create array of buffers for easy stop()\r\n if (this.buffer) {\r\n\r\n // reset the pause time (if it was paused)\r\n this._pauseTime = 0;\r\n\r\n // handle restart playmode\r\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\r\n this.bufferSourceNode.stop(time);\r\n this._counterNode.stop(time);\r\n }\r\n\r\n //dont create another instance if already playing\r\n if (this.mode === 'untildone' && this.isPlaying()) {\r\n return;\r\n }\r\n // make a new source and counter. They are automatically assigned playbackRate and buffer\r\n this.bufferSourceNode = this._initSourceNode();\r\n\r\n // garbage collect counterNode and create a new one\r\n delete this._counterNode;\r\n this._counterNode = this._initCounterNode();\r\n\r\n if (_cueStart) {\r\n if (_cueStart >=0 && _cueStart < this.buffer.duration) {\r\n // this.startTime = cueStart;\r\n cueStart = _cueStart;\r\n } else { throw 'start time out of range'; }\r\n } else {\r\n cueStart = 0;\r\n }\r\n\r\n if (duration) {\r\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\r\n duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration;\r\n }\r\n\r\n // if it was paused, play at the pause position\r\n if (this._paused) {\r\n this.bufferSourceNode.start(time, this.pauseTime, duration);\r\n this._counterNode.start(time, this.pauseTime, duration);\r\n } else {\r\n this.bufferSourceNode.start(time, cueStart, duration);\r\n this._counterNode.start(time, cueStart, duration);\r\n }\r\n\r\n this._playing = true;\r\n this._paused = false;\r\n\r\n // add source to sources array, which is used in stopAll()\r\n this.bufferSourceNodes.push(this.bufferSourceNode);\r\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\r\n\r\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\r\n }\r\n // If soundFile hasn't loaded the buffer yet, throw an error\r\n else {\r\n throw 'not ready to play file, buffer has yet to load. Try preload()';\r\n }\r\n\r\n // if looping, will restart at original time\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n\r\n if (this._looping === true) {\r\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\r\n this.bufferSourceNode.loopStart = cueStart;\r\n this.bufferSourceNode.loopEnd = cueEnd;\r\n this._counterNode.loopStart = cueStart;\r\n this._counterNode.loopEnd = cueEnd;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * p5.SoundFile has two play modes: restart and\r\n * sustain. Play Mode determines what happens to a\r\n * p5.SoundFile if it is triggered while in the middle of playback.\r\n * In sustain mode, playback will continue simultaneous to the\r\n * new playback. In restart mode, play() will stop playback\r\n * and start over. With untilDone, a sound will play only if it's\r\n * not already playing. Sustain is the default mode.\r\n *\r\n * @method playMode\r\n * @for p5.SoundFile\r\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\r\n * @example\r\n *
\r\n * var mySound;\r\n * function preload(){\r\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n * function mouseClicked() {\r\n * mySound.playMode('sustain');\r\n * mySound.play();\r\n * }\r\n * function keyPressed() {\r\n * mySound.playMode('restart');\r\n * mySound.play();\r\n * }\r\n *\r\n *
\r\n */\r\n p5.SoundFile.prototype.playMode = function(str) {\r\n var s = str.toLowerCase();\r\n\r\n // if restart, stop all other sounds from playing\r\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNodes[i].stop(now);\r\n }\r\n }\r\n\r\n // set play mode to effect future playback\r\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\r\n this.mode = s;\r\n } else {\r\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\r\n }\r\n };\r\n\r\n /**\r\n * Pauses a file that is currently playing. If the file is not\r\n * playing, then nothing will happen.\r\n *\r\n * After pausing, .play() will resume from the paused\r\n * position.\r\n * If p5.SoundFile had been set to loop before it was paused,\r\n * it will continue to loop after it is unpaused with .play().\r\n *\r\n * @method pause\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.pause = function(startTime) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = startTime || 0;\r\n var pTime = time + now;\r\n\r\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\r\n this.pauseTime = this.currentTime();\r\n this.bufferSourceNode.stop(pTime);\r\n this._counterNode.stop(pTime);\r\n this._paused = true;\r\n this._playing = false;\r\n\r\n this._pauseTime = this.currentTime();\r\n // TO DO: make sure play() still starts from orig start position\r\n } else {\r\n this._pauseTime = 0;\r\n }\r\n };\r\n\r\n /**\r\n * Loop the p5.SoundFile. Accepts optional parameters to set the\r\n * playback rate, playback volume, loopStart, loopEnd.\r\n *\r\n * @method loop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) playback volume\r\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\r\n * @param {Number} [duration] (optional) loop duration in seconds\r\n */\r\n p5.SoundFile.prototype.loop = function(startTime, rate, amp, loopStart, duration) {\r\n this._looping = true;\r\n this.play(startTime, rate, amp, loopStart, duration);\r\n };\r\n\r\n /**\r\n * Set a p5.SoundFile's looping flag to true or false. If the sound\r\n * is currently playing, this change will take effect when it\r\n * reaches the end of the current playback.\r\n *\r\n * @method setLoop\r\n * @for p5.SoundFile\r\n * @param {Boolean} Boolean set looping to true or false\r\n */\r\n p5.SoundFile.prototype.setLoop = function(bool) {\r\n if (bool === true) {\r\n this._looping = true;\r\n }\r\n else if (bool === false) {\r\n this._looping = false;\r\n }\r\n else {\r\n throw 'Error: setLoop accepts either true or false';\r\n }\r\n if (this.bufferSourceNode) {\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n }\r\n };\r\n\r\n /**\r\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\r\n *\r\n * @method isLooping\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLooping = function() {\r\n if (!this.bufferSourceNode) {\r\n return false;\r\n }\r\n if (this._looping === true && this.isPlaying() === true) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\r\n * paused or stopped).\r\n *\r\n * @method isPlaying\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPlaying = function() {\r\n return this._playing;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\r\n * playing or stopped).\r\n *\r\n * @method isPaused\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPaused = function() {\r\n return this._paused;\r\n };\r\n\r\n /**\r\n * Stop soundfile playback.\r\n *\r\n * @method stop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * in seconds from now\r\n */\r\n p5.SoundFile.prototype.stop = function(timeFromNow) {\r\n var time = timeFromNow || 0;\r\n\r\n if (this.mode === 'sustain' || this.mode === 'untildone') {\r\n this.stopAll(time);\r\n this._playing = false;\r\n this.pauseTime = 0;\r\n this._paused = false;\r\n }\r\n else if (this.buffer && this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = time || 0;\r\n this.pauseTime = 0;\r\n this.bufferSourceNode.stop(now + t);\r\n this._counterNode.stop(now + t);\r\n this._playing = false;\r\n this._paused = false;\r\n }\r\n };\r\n\r\n /**\r\n * Stop playback on all of this soundfile's sources.\r\n * @private\r\n */\r\n p5.SoundFile.prototype.stopAll = function(_time) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = _time || 0;\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i in this.bufferSourceNodes) {\r\n const bufferSourceNode = this.bufferSourceNodes[i];\r\n if (!!bufferSourceNode) {\r\n try {\r\n bufferSourceNode.stop(now + time);\r\n } catch(e) {\r\n // this was throwing errors only on Safari\r\n }\r\n }\r\n }\r\n this._counterNode.stop(now + time);\r\n this._onended(this);\r\n }\r\n };\r\n\r\n /**\r\n * Multiply the output volume (amplitude) of a sound file\r\n * between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n * @method setVolume\r\n * @for p5.SoundFile\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.SoundFile.prototype.setVolume = function(vol, _rampTime, _tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = _rampTime || 0;\r\n var tFromNow = _tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(this.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // same as setVolume, to match Processing Sound\r\n p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;\r\n\r\n // these are the same thing\r\n p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;\r\n\r\n p5.SoundFile.prototype.getVolume = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set the stereo panning of a p5.sound object to\r\n * a floating point number between -1.0 (left) and 1.0 (right).\r\n * Default is 0.0 (center).\r\n *\r\n * @method pan\r\n * @for p5.SoundFile\r\n * @param {Number} [panValue] Set the stereo panner\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @example\r\n *
\r\n *\r\n * var ball = {};\r\n * var soundFile;\r\n *\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n * soundFile = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * ball.x = constrain(mouseX, 0, width);\r\n * ellipse(ball.x, height/2, 20, 20)\r\n * }\r\n *\r\n * function mousePressed(){\r\n * // map the ball's x location to a panning degree\r\n * // between -1.0 (left) and 1.0 (right)\r\n * var panning = map(ball.x, 0., width,-1.0, 1.0);\r\n * soundFile.pan(panning);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n /**\r\n * Returns the current stereo pan position (-1.0 to 1.0)\r\n *\r\n * @method getPan\r\n * @for p5.SoundFile\r\n * @return {Number} Returns the stereo pan setting of the Oscillator\r\n * as a number between -1.0 (left) and 1.0 (right).\r\n * 0.0 is center and default.\r\n */\r\n p5.SoundFile.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n /**\r\n * Set the playback rate of a sound file. Will change the speed and the pitch.\r\n * Values less than zero will reverse the audio buffer.\r\n *\r\n * @method rate\r\n * @for p5.SoundFile\r\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\r\n * .5 is half-speed, 2.0 is twice as fast.\r\n * Values less than zero play backwards.\r\n * @example\r\n *
\r\n * var song;\r\n *\r\n * function preload() {\r\n * song = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * song.loop();\r\n * }\r\n *\r\n * function draw() {\r\n * background(200);\r\n *\r\n * // Set the rate to a range between 0.1 and 4\r\n * // Changing the rate also alters the pitch\r\n * var speed = map(mouseY, 0.1, height, 0, 2);\r\n * speed = constrain(speed, 0.01, 4);\r\n * song.rate(speed);\r\n *\r\n * // Draw a circle to show what is going on\r\n * stroke(0);\r\n * fill(51, 100);\r\n * ellipse(mouseX, 100, 48, 48);\r\n * }\r\n *\r\n * \r\n *
\r\n *\r\n */\r\n p5.SoundFile.prototype.rate = function(playbackRate) {\r\n var reverse = false;\r\n if (typeof playbackRate === 'undefined') {\r\n return this.playbackRate;\r\n }\r\n\r\n this.playbackRate = playbackRate;\r\n\r\n if (playbackRate === 0) {\r\n playbackRate = 0.0000000000001;\r\n }\r\n\r\n else if (playbackRate < 0 && !this.reversed) {\r\n playbackRate = Math.abs(playbackRate);\r\n reverse = true;\r\n }\r\n\r\n else if (playbackRate > 0 && this.reversed) {\r\n reverse = true;\r\n }\r\n\r\n if (this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\r\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n this._counterNode.playbackRate.cancelScheduledValues(now);\r\n this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n }\r\n\r\n if (reverse) {\r\n this.reverseBuffer();\r\n }\r\n return this.playbackRate;\r\n };\r\n\r\n // TO DO: document this\r\n p5.SoundFile.prototype.setPitch = function(num) {\r\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\r\n this.rate(newPlaybackRate);\r\n };\r\n\r\n p5.SoundFile.prototype.getPlaybackRate = function() {\r\n return this.playbackRate;\r\n };\r\n\r\n /**\r\n * Returns the duration of a sound file in seconds.\r\n *\r\n * @method duration\r\n * @for p5.SoundFile\r\n * @return {Number} The duration of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.duration = function() {\r\n // Return Duration\r\n if (this.buffer) {\r\n return this.buffer.duration;\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n /**\r\n * Return the current position of the p5.SoundFile playhead, in seconds.\r\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\r\n * has been called, currentTime will count backwards.\r\n *\r\n * @method currentTime\r\n * @for p5.SoundFile\r\n * @return {Number} currentTime of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.currentTime = function() {\r\n return this.reversed\r\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\r\n : this._lastPos / ac.sampleRate;\r\n };\r\n\r\n /**\r\n * Move the playhead of the song to a position, in seconds. Start timing\r\n * and playback duration. If none are given, will reset the file to play\r\n * entire duration from start to finish.\r\n *\r\n * @method jump\r\n * @for p5.SoundFile\r\n * @param {Number} cueTime cueTime of the soundFile in seconds.\r\n * @param {Number} duration duration in seconds.\r\n */\r\n p5.SoundFile.prototype.jump = function(cueTime, duration) {\r\n if (cueTime < 0 || cueTime > this.buffer.duration) {\r\n throw 'jump time out of range';\r\n }\r\n if (duration > this.buffer.duration - cueTime) {\r\n throw 'end time out of range';\r\n }\r\n\r\n var cTime = cueTime || 0;\r\n var dur = duration || undefined;\r\n if (this.isPlaying()) {\r\n this.stop(0);\r\n }\r\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\r\n };\r\n\r\n /**\r\n * Return the number of channels in a sound file.\r\n * For example, Mono = 1, Stereo = 2.\r\n *\r\n * @method channels\r\n * @for p5.SoundFile\r\n * @return {Number} [channels]\r\n */\r\n p5.SoundFile.prototype.channels = function() {\r\n return this.buffer.numberOfChannels;\r\n };\r\n\r\n /**\r\n * Return the sample rate of the sound file.\r\n *\r\n * @method sampleRate\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleRate]\r\n */\r\n p5.SoundFile.prototype.sampleRate = function() {\r\n return this.buffer.sampleRate;\r\n };\r\n\r\n /**\r\n * Return the number of samples in a sound file.\r\n * Equal to sampleRate * duration.\r\n *\r\n * @method frames\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleCount]\r\n */\r\n p5.SoundFile.prototype.frames = function() {\r\n return this.buffer.length;\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\r\n * used to draw a static waveform. Scans through the p5.SoundFile's\r\n * audio buffer to find the greatest amplitudes. Accepts one\r\n * parameter, 'length', which determines size of the array.\r\n * Larger arrays result in more precise waveform visualizations.\r\n *\r\n * Inspired by Wavesurfer.js.\r\n *\r\n * @method getPeaks\r\n * @for p5.SoundFile\r\n * @params {Number} [length] length is the size of the returned array.\r\n * Larger length results in more precision.\r\n * Defaults to 5*width of the browser window.\r\n * @returns {Float32Array} Array of peaks.\r\n */\r\n p5.SoundFile.prototype.getPeaks = function(length) {\r\n\r\n if (this.buffer) {\r\n // set length to window's width if no length is provided\r\n if (!length) {\r\n length = window.width*5;\r\n }\r\n if (this.buffer) {\r\n var buffer = this.buffer;\r\n var sampleSize = buffer.length / length;\r\n var sampleStep = ~~(sampleSize / 10) || 1;\r\n var channels = buffer.numberOfChannels;\r\n var peaks = new Float32Array(Math.round(length));\r\n\r\n for (var c = 0; c < channels; c++) {\r\n var chan = buffer.getChannelData(c);\r\n for (var i = 0; i < length; i++) {\r\n var start = ~~(i*sampleSize);\r\n var end = ~~(start + sampleSize);\r\n var max = 0;\r\n for (var j = start; j < end; j+= sampleStep) {\r\n var value = chan[j];\r\n if (value > max) {\r\n max = value;\r\n // faster than Math.abs\r\n } else if (-value > max) {\r\n max = value;\r\n }\r\n }\r\n if (c === 0 || Math.abs(max) > peaks[i]) {\r\n peaks[i] = max;\r\n }\r\n }\r\n }\r\n\r\n return peaks;\r\n }\r\n }\r\n\r\n else {\r\n throw 'Cannot load peaks yet, buffer is not loaded';\r\n }\r\n };\r\n\r\n /**\r\n * Reverses the p5.SoundFile's buffer source.\r\n * Playback must be handled separately (see example).\r\n *\r\n * @method reverseBuffer\r\n * @for p5.SoundFile\r\n * @example\r\n *
\r\n * var drum;\r\n *\r\n * function preload() {\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * drum.reverseBuffer();\r\n * drum.play();\r\n * }\r\n *\r\n * \r\n *
\r\n */\r\n p5.SoundFile.prototype.reverseBuffer = function() {\r\n if (this.buffer) {\r\n var currentPos = this._lastPos / ac.sampleRate;\r\n var curVol = this.getVolume();\r\n this.setVolume(0, 0.001);\r\n\r\n const numChannels = this.buffer.numberOfChannels;\r\n for (var i = 0; i < numChannels; i++) {\r\n this.buffer.getChannelData(i).reverse();\r\n }\r\n // set reversed flag\r\n this.reversed = !this.reversed;\r\n\r\n if (currentPos) {\r\n this.jump(this.duration() - currentPos);\r\n }\r\n this.setVolume(curVol, 0.001);\r\n } else {\r\n throw 'SoundFile is not done loading';\r\n }\r\n };\r\n\r\n /**\r\n * Schedule an event to be called when the soundfile\r\n * reaches the end of a buffer. If the soundfile is\r\n * playing through once, this will be called when it\r\n * ends. If it is looping, it will be called when\r\n * stop is called.\r\n *\r\n * @method onended\r\n * @for p5.SoundFile\r\n * @param {Function} callback function to call when the\r\n * soundfile has ended.\r\n */\r\n p5.SoundFile.prototype.onended = function(callback) {\r\n this._onended = callback;\r\n return this;\r\n };\r\n\r\n p5.SoundFile.prototype.add = function() {\r\n // TO DO\r\n };\r\n\r\n p5.SoundFile.prototype.dispose = function() {\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n // remove reference to soundfile\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop(now);\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n if (this.bufferSourceNodes[i] !== null) {\r\n this.bufferSourceNodes[i].disconnect();\r\n try {\r\n this.bufferSourceNodes[i].stop(now);\r\n } catch(e) {\r\n console.warning('no buffer source node to dispose');\r\n }\r\n this.bufferSourceNodes[i] = null;\r\n }\r\n }\r\n if ( this.isPlaying() ) {\r\n try {\r\n this._counterNode.stop(now);\r\n } catch(e) {\r\n console.log(e);\r\n }\r\n this._counterNode = null;\r\n }\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n this.output = null;\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n this.panner = null;\r\n }\r\n };\r\n\r\n /**\r\n * Connects the output of a p5sound object to input of another\r\n * p5.sound object. For example, you may connect a p5.SoundFile to an\r\n * FFT or an Effect. If no parameter is given, it will connect to\r\n * the master output. Most p5sound objects connect to the master\r\n * output when they are created.\r\n *\r\n * @method connect\r\n * @for p5.SoundFile\r\n * @param {Object} [object] Audio object that accepts an input\r\n */\r\n p5.SoundFile.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else {\r\n if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n } else {\r\n this.panner.connect(unit);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Disconnects the output of this p5sound object.\r\n *\r\n * @method disconnect\r\n * @for p5.SoundFile\r\n */\r\n p5.SoundFile.prototype.disconnect = function() {\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n */\r\n p5.SoundFile.prototype.getLevel = function() {\r\n console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead');\r\n };\r\n\r\n /**\r\n * Reset the source for this SoundFile to a\r\n * new path (URL).\r\n *\r\n * @method setPath\r\n * @for p5.SoundFile\r\n * @param {String} path path to audio file\r\n * @param {Function} callback Callback\r\n */\r\n p5.SoundFile.prototype.setPath = function(p, callback) {\r\n var path = p5.prototype._checkFileFormats(p);\r\n this.url = path;\r\n this.load(callback);\r\n };\r\n\r\n /**\r\n * Replace the current Audio Buffer with a new Buffer.\r\n *\r\n * @method setBuffer\r\n * @for p5.SoundFile\r\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\r\n * will create a stereo source. 1 will create\r\n * a mono source.\r\n */\r\n p5.SoundFile.prototype.setBuffer = function(buf) {\r\n var numChannels = buf.length;\r\n var size = buf[0].length;\r\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\r\n\r\n if (!(buf[0] instanceof Float32Array)) {\r\n buf[0] = new Float32Array(buf[0]);\r\n }\r\n\r\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\r\n var channel = newBuffer.getChannelData( channelNum );\r\n channel.set(buf[channelNum]);\r\n }\r\n\r\n this.buffer = newBuffer;\r\n\r\n // set numbers of channels on input to the panner\r\n this.panner.inputChannels(numChannels);\r\n };\r\n\r\n //////////////////////////////////////////////////\r\n // script processor node with an empty buffer to help\r\n // keep a sample-accurate position in playback buffer.\r\n // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV\r\n // Copyright [2015] [Sonoport (Asia) Pte. Ltd.],\r\n // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0\r\n ////////////////////////////////////////////////////////////////////////////////////\r\n\r\n var _createCounterBuffer = function(buffer) {\r\n const len = buffer.length;\r\n const audioBuf = ac.createBuffer( 1, buffer.length, ac.sampleRate );\r\n const arrayBuffer = audioBuf.getChannelData(0);\r\n for (var index = 0; index < len; index++) {\r\n arrayBuffer[index] = index;\r\n }\r\n return audioBuf;\r\n };\r\n\r\n // initialize counterNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initCounterNode = function() {\r\n var self = this;\r\n var now = ac.currentTime;\r\n var cNode = ac.createBufferSource();\r\n\r\n // dispose of scope node if it already exists\r\n if (self._scopeNode) {\r\n self._scopeNode.disconnect();\r\n self._scopeNode.removeEventListener('audioprocess', self._onAudioProcess);\r\n delete self._scopeNode;\r\n }\r\n self._scopeNode = ac.createScriptProcessor( 256, 1, 1 );\r\n\r\n // create counter buffer of the same length as self.buffer\r\n cNode.buffer = _createCounterBuffer( self.buffer );\r\n\r\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\r\n\r\n cNode.connect( self._scopeNode );\r\n self._scopeNode.connect( p5.soundOut._silentNode );\r\n\r\n self._scopeNode.addEventListener('audioprocess', self._onAudioProcess);\r\n\r\n return cNode;\r\n };\r\n\r\n // initialize sourceNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initSourceNode = function() {\r\n var bufferSourceNode = ac.createBufferSource();\r\n bufferSourceNode.buffer = this.buffer;\r\n bufferSourceNode.playbackRate.value = this.playbackRate;\r\n bufferSourceNode.connect(this.output);\r\n return bufferSourceNode;\r\n };\r\n\r\n /**\r\n * processPeaks returns an array of timestamps where it thinks there is a beat.\r\n *\r\n * This is an asynchronous function that processes the soundfile in an offline audio context,\r\n * and sends the results to your callback function.\r\n *\r\n * The process involves running the soundfile through a lowpass filter, and finding all of the\r\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\r\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\r\n *\r\n * @method processPeaks\r\n * @for p5.SoundFile\r\n * @param {Function} callback a function to call once this data is returned\r\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\r\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\r\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\r\n * @return {Array} Array of timestamped peaks\r\n */\r\n p5.SoundFile.prototype.processPeaks = function(callback, _initThreshold, _minThreshold, _minPeaks) {\r\n var bufLen = this.buffer.length;\r\n var sampleRate = this.buffer.sampleRate;\r\n var buffer = this.buffer;\r\n var allPeaks = [];\r\n\r\n var initialThreshold = _initThreshold || 0.9,\r\n threshold = initialThreshold,\r\n minThreshold = _minThreshold || 0.22,\r\n minPeaks = _minPeaks || 200;\r\n\r\n // Create offline context\r\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\r\n\r\n // create buffer source\r\n var source = offlineContext.createBufferSource();\r\n source.buffer = buffer;\r\n\r\n // Create filter. TO DO: allow custom setting of filter\r\n var filter = offlineContext.createBiquadFilter();\r\n filter.type = 'lowpass';\r\n source.connect(filter);\r\n filter.connect(offlineContext.destination);\r\n\r\n // start playing at time:0\r\n source.start(0);\r\n offlineContext.startRendering(); // Render the song\r\n\r\n // act on the result\r\n offlineContext.oncomplete = function(e) {\r\n if (!self.panner) return;\r\n var filteredBuffer = e.renderedBuffer;\r\n var bufferData = filteredBuffer.getChannelData(0);\r\n\r\n\r\n // step 1:\r\n // create Peak instances, add them to array, with strength and sampleIndex\r\n do {\r\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\r\n threshold -= 0.005;\r\n } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold);\r\n\r\n\r\n // step 2:\r\n // find intervals for each peak in the sampleIndex, add tempos array\r\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\r\n\r\n // step 3: find top tempos\r\n var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate);\r\n\r\n // sort top intervals\r\n var topTempos = groups.sort(function(intA, intB) {\r\n return intB.count - intA.count;\r\n\r\n }).splice(0,5);\r\n\r\n // set this SoundFile's tempo to the top tempo ??\r\n this.tempo = topTempos[0].tempo;\r\n\r\n // step 4:\r\n // new array of peaks at top tempo within a bpmVariance\r\n var bpmVariance = 5;\r\n var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance);\r\n\r\n callback(tempoPeaks);\r\n };\r\n };\r\n\r\n // process peaks\r\n var Peak = function(amp, i) {\r\n this.sampleIndex = i;\r\n this.amplitude = amp;\r\n this.tempos = [];\r\n this.intervals = [];\r\n };\r\n\r\n // 1. for processPeaks() Function to identify peaks above a threshold\r\n // returns an array of peak indexes as frames (samples) of the original soundfile\r\n function getPeaksAtThreshold(data, threshold) {\r\n var peaksObj = {};\r\n var length = data.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (data[i] > threshold) {\r\n var amp = data[i];\r\n var peak = new Peak(amp, i);\r\n peaksObj[i] = peak;\r\n // Skip forward ~ 1/8s to get past this peak.\r\n i += 6000;\r\n }\r\n i++;\r\n }\r\n return peaksObj;\r\n }\r\n\r\n // 2. for processPeaks()\r\n function countIntervalsBetweenNearbyPeaks(peaksObj) {\r\n var intervalCounts = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n for (var index = 0; index < peaksArray.length; index++) {\r\n\r\n // find intervals in comparison to nearby peaks\r\n for (var i = 0; i < 10; i++) {\r\n var startPeak = peaksObj[peaksArray[index]];\r\n var endPeak = peaksObj[peaksArray[index + i]];\r\n\r\n if (startPeak && endPeak) {\r\n var startPos = startPeak.sampleIndex;\r\n var endPos = endPeak.sampleIndex;\r\n var interval = endPos - startPos;\r\n\r\n // add a sample interval to the startPeak in the allPeaks array\r\n if (interval > 0) {\r\n startPeak.intervals.push(interval);\r\n }\r\n\r\n // tally the intervals and return interval counts\r\n var foundInterval = intervalCounts.some(function(intervalCount) {\r\n if (intervalCount.interval === interval) {\r\n intervalCount.count++;\r\n return intervalCount;\r\n }\r\n });\r\n\r\n // store with JSON like formatting\r\n if (!foundInterval) {\r\n intervalCounts.push({\r\n interval: interval,\r\n count: 1,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return intervalCounts;\r\n }\r\n\r\n\r\n // 3. for processPeaks --> find tempo\r\n function groupNeighborsByTempo(intervalCounts, sampleRate) {\r\n var tempoCounts = [];\r\n\r\n intervalCounts.forEach(function(intervalCount) {\r\n\r\n try {\r\n // Convert an interval to tempo\r\n var theoreticalTempo = Math.abs( 60 / (intervalCount.interval / sampleRate ) );\r\n\r\n theoreticalTempo = mapTempo(theoreticalTempo);\r\n\r\n var foundTempo = tempoCounts.some(function(tempoCount) {\r\n if (tempoCount.tempo === theoreticalTempo)\r\n return tempoCount.count += intervalCount.count;\r\n });\r\n if (!foundTempo) {\r\n if (isNaN(theoreticalTempo)) {\r\n return;\r\n }\r\n tempoCounts.push({\r\n tempo: Math.round(theoreticalTempo),\r\n count: intervalCount.count\r\n });\r\n }\r\n } catch(e) {\r\n throw e;\r\n }\r\n\r\n });\r\n\r\n return tempoCounts;\r\n }\r\n\r\n // 4. for processPeaks - get peaks at top tempo\r\n function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\r\n var peaksAtTopTempo = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n // TO DO: filter out peaks that have the tempo and return\r\n for (var i = 0; i < peaksArray.length; i++) {\r\n var key = peaksArray[i];\r\n var peak = peaksObj[key];\r\n\r\n for (var j = 0; j < peak.intervals.length; j++) {\r\n var intervalBPM = Math.round(Math.abs( 60 / (peak.intervals[j] / sampleRate) ) );\r\n\r\n intervalBPM = mapTempo(intervalBPM);\r\n\r\n if ( Math.abs(intervalBPM - tempo) < bpmVariance ) {\r\n // convert sampleIndex to seconds\r\n peaksAtTopTempo.push(peak.sampleIndex/sampleRate);\r\n }\r\n }\r\n }\r\n\r\n // filter out peaks that are very close to each other\r\n peaksAtTopTempo = peaksAtTopTempo.filter(function(peakTime, index, arr) {\r\n var dif = arr[index + 1] - peakTime;\r\n if (dif > 0.01) {\r\n return true;\r\n }\r\n });\r\n\r\n return peaksAtTopTempo;\r\n }\r\n\r\n // helper function for processPeaks\r\n function mapTempo(theoreticalTempo) {\r\n // these scenarios create infinite while loop\r\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0 ) {\r\n return;\r\n }\r\n\r\n // Adjust the tempo to fit within the 90-180 BPM range\r\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\r\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\r\n\r\n return theoreticalTempo;\r\n }\r\n\r\n\r\n /*** SCHEDULE EVENTS ***/\r\n\r\n // Cue inspired by JavaScript setTimeout, and the\r\n // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\r\n var Cue = function(callback, time, id, val) {\r\n this.callback = callback;\r\n this.time = time;\r\n this.id = id;\r\n this.val = val;\r\n };\r\n\r\n /**\r\n * Schedule events to trigger every time a MediaElement\r\n * (audio/video) reaches a playback cue point.\r\n *\r\n * Accepts a callback function, a time (in seconds) at which to trigger\r\n * the callback, and an optional parameter for the callback.\r\n *\r\n * Time will be passed as the first parameter to the callback function,\r\n * and param will be the second parameter.\r\n *\r\n *\r\n * @method addCue\r\n * @for p5.SoundFile\r\n * @param {Number} time Time in seconds, relative to this media\r\n * element's playback. For example, to trigger\r\n * an event every time playback reaches two\r\n * seconds, pass in the number 2. This will be\r\n * passed as the first parameter to\r\n * the callback function.\r\n * @param {Function} callback Name of a function that will be\r\n * called at the given time. The callback will\r\n * receive time and (optionally) param as its\r\n * two parameters.\r\n * @param {Object} [value] An object to be passed as the\r\n * second parameter to the\r\n * callback function.\r\n * @return {Number} id ID of this cue,\r\n * useful for removeCue(id)\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.addCue = function(time, callback, val) {\r\n var id = this._cueIDCounter++;\r\n\r\n var cue = new Cue(callback, time, id, val);\r\n this._cues.push(cue);\r\n\r\n // if (!this.elt.ontimeupdate) {\r\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\r\n // }\r\n\r\n return id;\r\n };\r\n\r\n /**\r\n * Remove a callback based on its ID. The ID is returned by the\r\n * addCue method.\r\n *\r\n * @method removeCue\r\n * @for p5.SoundFile\r\n * @param {Number} id ID of the cue, as returned by addCue\r\n */\r\n p5.SoundFile.prototype.removeCue = function(id) {\r\n var cueLength = this._cues.length;\r\n for (var i = 0; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n if (cue.id === id) {\r\n this._cues.splice(i, 1);\r\n break;\r\n }\r\n }\r\n\r\n if (this._cues.length === 0) {\r\n // TO DO: remove callback\r\n // this.elt.ontimeupdate = null\r\n }\r\n };\r\n\r\n /**\r\n * Remove all of the callbacks that had originally been scheduled\r\n * via the addCue method.\r\n *\r\n * @method clearCues\r\n */\r\n p5.SoundFile.prototype.clearCues = function() {\r\n this._cues = [];\r\n // this.elt.ontimeupdate = null;\r\n };\r\n\r\n // private method that checks for cues to be fired if events\r\n // have been scheduled using addCue(callback, time).\r\n p5.SoundFile.prototype._onTimeUpdate = function(position) {\r\n var playbackTime = position/this.buffer.sampleRate;\r\n var cueLength = this._cues.length;\r\n\r\n for (var i = 0 ; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n var callbackTime = cue.time;\r\n var val = cue.val;\r\n\r\n if (this._prevTime < callbackTime && callbackTime <= playbackTime) {\r\n\r\n // pass the scheduled callbackTime as parameter to the callback\r\n cue.callback(val);\r\n }\r\n\r\n }\r\n\r\n this._prevTime = playbackTime;\r\n };\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device. To upload a file to a server, see\r\n * getBlob\r\n *\r\n * @method save\r\n * @for p5.SoundFile\r\n * @param {String} [fileName] name of the resulting .wav file.\r\n * @example\r\n *
\r\n * var inp, button, mySound;\r\n * var fileName = 'cool';\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n * function setup() {\r\n * btn = createButton('click to save file');\r\n * btn.position(0, 0);\r\n * btn.mouseClicked(handleMouseClick);\r\n * }\r\n *\r\n * function handleMouseClick() {\r\n * mySound.save(fileName);\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.save = function(fileName) {\r\n const dataView = convertToWav(this.buffer);\r\n p5.prototype.saveSound([dataView], fileName, 'wav');\r\n };\r\n\r\n /**\r\n * This method is useful for sending a SoundFile to a server. It returns the\r\n * .wav-encoded audio data as a \"Blob\".\r\n * A Blob is a file-like data object that can be uploaded to a server\r\n * with an http request. We'll\r\n * use the `httpDo` options object to send a POST request with some\r\n * specific options: we encode the request as `multipart/form-data`,\r\n * and attach the blob as one of the form values using `FormData`.\r\n *\r\n *\r\n * @method getBlob\r\n * @for p5.SoundFile\r\n * @returns {Blob} A file-like data object\r\n * @example\r\n *
\r\n *\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noCanvas();\r\n * var soundBlob = mySound.getBlob();\r\n *\r\n * // Now we can send the blob to a server...\r\n * var serverUrl = 'https://jsonplaceholder.typicode.com/posts';\r\n * var httpRequestOptions = {\r\n * method: 'POST',\r\n * body: new FormData().append('soundBlob', soundBlob),\r\n * headers: new Headers({\r\n * 'Content-Type': 'multipart/form-data'\r\n * })\r\n * };\r\n * httpDo(serverUrl, httpRequestOptions);\r\n *\r\n * // We can also create an `ObjectURL` pointing to the Blob\r\n * var blobUrl = URL.createObjectURL(soundBlob);\r\n *\r\n * // The `
\r\n */\r\n p5.SoundFile.prototype.getBlob = function() {\r\n const dataView = convertToWav(this.buffer);\r\n return new Blob([dataView], { type: 'audio/wav' });\r\n };\r\n\r\n // event handler to keep track of current position\r\n function _onAudioProcess(processEvent) {\r\n var inputBuffer = processEvent.inputBuffer.getChannelData(0);\r\n\r\n this._lastPos = inputBuffer[inputBuffer.length - 1] || 0;\r\n\r\n // do any callbacks that have been scheduled\r\n this._onTimeUpdate(self._lastPos);\r\n }\r\n\r\n // event handler to remove references to the bufferSourceNode when it is done playing\r\n function _clearOnEnd(e) {\r\n const thisBufferSourceNode = e.target;\r\n const soundFile = this;\r\n\r\n // delete this.bufferSourceNode from the sources array when it is done playing:\r\n thisBufferSourceNode._playing = false;\r\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\r\n\r\n // call the onended callback\r\n soundFile._onended(soundFile);\r\n\r\n soundFile.bufferSourceNodes.forEach(function (n, i) {\r\n if (n._playing === false) {\r\n soundFile.bufferSourceNodes.splice(i);\r\n }\r\n });\r\n\r\n if (soundFile.bufferSourceNodes.length === 0) {\r\n soundFile._playing = false;\r\n }\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * Amplitude measures volume between 0.0 and 1.0.\r\n * Listens to all p5sound by default, or use setInput()\r\n * to listen to a specific sound source. Accepts an optional\r\n * smoothing value, which defaults to 0.\r\n *\r\n * @class p5.Amplitude\r\n * @constructor\r\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\r\n * amplitude readings (defaults to 0)\r\n * @example\r\n *
\r\n * var sound, amplitude, cnv;\r\n *\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * amplitude = new p5.Amplitude();\r\n *\r\n * // start / stop the sound when canvas is clicked\r\n * cnv.mouseClicked(function() {\r\n * if (sound.isPlaying() ){\r\n * sound.stop();\r\n * } else {\r\n * sound.play();\r\n * }\r\n * });\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n *\r\n *
\r\n */\r\n p5.Amplitude = function(smoothing) {\r\n\r\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\r\n this.bufferSize = 2048;\r\n\r\n // set audio context\r\n this.audiocontext = p5sound.audiocontext;\r\n this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1);\r\n\r\n // for connections\r\n this.input = this.processor;\r\n\r\n this.output = this.audiocontext.createGain();\r\n // smoothing defaults to 0\r\n this.smoothing = smoothing || 0;\r\n\r\n\r\n // the variables to return\r\n this.volume = 0;\r\n this.average = 0;\r\n\r\n this.stereoVol = [0, 0];\r\n this.stereoAvg = [0, 0];\r\n this.stereoVolNorm = [0, 0];\r\n\r\n this.volMax = 0.001;\r\n this.normalize = false;\r\n\r\n this.processor.onaudioprocess = this._audioProcess.bind(this);\r\n\r\n\r\n this.processor.connect(this.output);\r\n this.output.gain.value = 0;\r\n\r\n // this may only be necessary because of a Chrome bug\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // connect to p5sound master output by default, unless set by input()\r\n p5sound.meter.connect(this.processor);\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connects to the p5sound instance (master output) by default.\r\n * Optionally, you can pass in a specific source (i.e. a soundfile).\r\n *\r\n * @method setInput\r\n * @for p5.Amplitude\r\n * @param {soundObject|undefined} [snd] set the sound source\r\n * (optional, defaults to\r\n * master output)\r\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\r\n * to smooth amplitude readings\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound1 = loadSound('assets/beat.mp3');\r\n * sound2 = loadSound('assets/drum.mp3');\r\n * }\r\n * function setup(){\r\n * amplitude = new p5.Amplitude();\r\n * sound1.play();\r\n * sound2.play();\r\n * amplitude.setInput(sound2);\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound1.stop();\r\n * sound2.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.setInput = function(source, smoothing) {\r\n\r\n p5sound.meter.disconnect();\r\n\r\n if (smoothing) {\r\n this.smoothing = smoothing;\r\n }\r\n\r\n // connect to the master out of p5s instance if no snd is provided\r\n if (source == null) {\r\n console.log('Amplitude input source is not ready! Connecting to master output instead');\r\n p5sound.meter.connect(this.processor);\r\n }\r\n\r\n // if it is a p5.Signal\r\n else if (source instanceof p5.Signal) {\r\n source.output.connect(this.processor);\r\n }\r\n // connect to the sound if it is available\r\n else if (source) {\r\n source.connect(this.processor);\r\n this.processor.disconnect();\r\n this.processor.connect(this.output);\r\n }\r\n\r\n // otherwise, connect to the master out of p5s instance (default)\r\n else {\r\n p5sound.meter.connect(this.processor);\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n } else {\r\n this.output.connect(unit);\r\n }\r\n } else {\r\n this.output.connect(this.panner.connect(p5sound.input));\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n // TO DO make this stereo / dependent on # of audio channels\r\n p5.Amplitude.prototype._audioProcess = function(event) {\r\n\r\n for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) {\r\n var inputBuffer = event.inputBuffer.getChannelData(channel);\r\n var bufLength = inputBuffer.length;\r\n\r\n var total = 0;\r\n var sum = 0;\r\n var x;\r\n\r\n for (var i = 0; i < bufLength; i++) {\r\n x = inputBuffer[i];\r\n if (this.normalize) {\r\n total += Math.max(Math.min(x/this.volMax, 1), -1);\r\n sum += Math.max(Math.min(x/this.volMax, 1), -1) * Math.max(Math.min(x/this.volMax, 1), -1);\r\n }\r\n else {\r\n total += x;\r\n sum += x * x;\r\n }\r\n }\r\n var average = total/ bufLength;\r\n\r\n // ... then take the square root of the sum.\r\n var rms = Math.sqrt(sum / bufLength);\r\n\r\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing);\r\n this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing);\r\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\r\n }\r\n\r\n // add volume from all channels together\r\n var self = this;\r\n var volSum = this.stereoVol.reduce(function(previousValue, currentValue, index) {\r\n self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1]/self.volMax, 1), 0);\r\n self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index]/self.volMax, 1), 0);\r\n\r\n return previousValue + currentValue;\r\n });\r\n\r\n // volume is average of channels\r\n this.volume = volSum / this.stereoVol.length;\r\n\r\n // normalized value\r\n this.volNorm = Math.max(Math.min(this.volume/this.volMax, 1), 0);\r\n\r\n\r\n };\r\n\r\n /**\r\n * Returns a single Amplitude reading at the moment it is called.\r\n * For continuous readings, run in the draw loop.\r\n *\r\n * @method getLevel\r\n * @for p5.Amplitude\r\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\r\n * @return {Number} Amplitude as a number between 0.0 and 1.0\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * amplitude = new p5.Amplitude();\r\n * sound.play();\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.getLevel = function(channel) {\r\n if (typeof channel !== 'undefined') {\r\n if (this.normalize) {\r\n return this.stereoVolNorm[channel];\r\n } else {\r\n return this.stereoVol[channel];\r\n }\r\n }\r\n else if (this.normalize) {\r\n return this.volNorm;\r\n }\r\n else {\r\n return this.volume;\r\n }\r\n };\r\n\r\n /**\r\n * Determines whether the results of Amplitude.process() will be\r\n * Normalized. To normalize, Amplitude finds the difference the\r\n * loudest reading it has processed and the maximum amplitude of\r\n * 1.0. Amplitude adds this difference to all values to produce\r\n * results that will reliably map between 0.0 and 1.0. However,\r\n * if a louder moment occurs, the amount that Normalize adds to\r\n * all the values will change. Accepts an optional boolean parameter\r\n * (true or false). Normalizing is off by default.\r\n *\r\n * @method toggleNormalize\r\n * @for p5.Amplitude\r\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\r\n */\r\n p5.Amplitude.prototype.toggleNormalize = function(bool) {\r\n if (typeof bool === 'boolean') {\r\n this.normalize = bool;\r\n }\r\n else {\r\n this.normalize = !this.normalize;\r\n }\r\n };\r\n\r\n /**\r\n * Smooth Amplitude analysis by averaging with the last analysis\r\n * frame. Off by default.\r\n *\r\n * @method smooth\r\n * @for p5.Amplitude\r\n * @param {Number} set smoothing from 0.0 <= 1\r\n */\r\n p5.Amplitude.prototype.smooth = function(s) {\r\n if (s >= 0 && s < 1) {\r\n this.smoothing = s;\r\n } else {\r\n console.log('Error: smoothing must be between 0 and 1');\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n\r\n delete this.processor;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n *
FFT (Fast Fourier Transform) is an analysis algorithm that\r\n * isolates individual\r\n * \r\n * audio frequencies within a waveform.
\r\n *\r\n *
Once instantiated, a p5.FFT object can return an array based on\r\n * two types of analyses: • FFT.waveform() computes\r\n * amplitude values along the time domain. The array indices correspond\r\n * to samples across a brief moment in time. Each value represents\r\n * amplitude of the waveform at that sample of time. \r\n * • FFT.analyze() computes amplitude values along the\r\n * frequency domain. The array indices correspond to frequencies (i.e.\r\n * pitches), from the lowest to the highest that humans can hear. Each\r\n * value represents amplitude at that slice of the frequency spectrum.\r\n * Use with getEnergy() to measure amplitude at specific\r\n * frequencies, or within a range of frequencies.
\r\n *\r\n *
FFT analyzes a very short snapshot of sound called a sample\r\n * buffer. It returns an array of amplitude measurements, referred\r\n * to as bins. The array is 1024 bins long by default.\r\n * You can change the bin array length, but it must be a power of 2\r\n * between 16 and 1024 in order for the FFT algorithm to function\r\n * correctly. The actual size of the FFT buffer is twice the\r\n * number of bins, so given a standard sample rate, the buffer is\r\n * 2048/44100 seconds long.
\r\n *\r\n *\r\n * @class p5.FFT\r\n * @constructor\r\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\r\n * 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n * @param {Number} [bins] Length of resulting array.\r\n * Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup(){\r\n * var cnv = createCanvas(100,100);\r\n * cnv.mouseClicked(togglePlay);\r\n * fft = new p5.FFT();\r\n * sound.amp(0.2);\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h )\r\n * }\r\n *\r\n * var waveform = fft.waveform();\r\n * noFill();\r\n * beginShape();\r\n * stroke(255,0,0); // waveform is red\r\n * strokeWeight(1);\r\n * for (var i = 0; i< waveform.length; i++){\r\n * var x = map(i, 0, waveform.length, 0, width);\r\n * var y = map( waveform[i], -1, 1, 0, height);\r\n * vertex(x,y);\r\n * }\r\n * endShape();\r\n *\r\n * text('click to play/pause', 4, 10);\r\n * }\r\n *\r\n * // fade sound if mouse is over canvas\r\n * function togglePlay() {\r\n * if (sound.isPlaying()) {\r\n * sound.pause();\r\n * } else {\r\n * sound.loop();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.FFT = function(smoothing, bins) {\r\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\r\n\r\n Object.defineProperties(this, {\r\n bins: {\r\n get: function() {\r\n return this.analyser.fftSize / 2;\r\n },\r\n set: function(b) {\r\n this.analyser.fftSize = b * 2;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n },\r\n smoothing: {\r\n get: function() {\r\n return this.analyser.smoothingTimeConstant;\r\n },\r\n set: function(s) {\r\n this.analyser.smoothingTimeConstant = s;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n }\r\n });\r\n\r\n // set default smoothing and bins\r\n this.smooth(smoothing);\r\n this.bins = bins || 1024;\r\n\r\n // default connections to p5sound fftMeter\r\n p5sound.fftMeter.connect(this.analyser);\r\n\r\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n\r\n // predefined frequency ranges, these will be tweakable\r\n this.bass = [20, 140];\r\n this.lowMid = [140, 400];\r\n this.mid = [400, 2600];\r\n this.highMid = [2600, 5200];\r\n this.treble = [5200, 14000];\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the input source for the FFT analysis. If no source is\r\n * provided, FFT will analyze all sound in the sketch.\r\n *\r\n * @method setInput\r\n * @for p5.FFT\r\n * @param {Object} [source] p5.sound object (or web audio API source node)\r\n */\r\n p5.FFT.prototype.setInput = function(source) {\r\n if (!source) {\r\n p5sound.fftMeter.connect(this.analyser);\r\n } else {\r\n if (source.output) {\r\n source.output.connect(this.analyser);\r\n } else if (source.connect) {\r\n source.connect(this.analyser);\r\n }\r\n p5sound.fftMeter.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\r\n * a snapshot of amplitude readings in a single buffer. Length will be\r\n * equal to bins (defaults to 1024). Can be used to draw the waveform\r\n * of a sound.\r\n *\r\n * @method waveform\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {String} [precision] If any value is provided, will return results\r\n * in a Float32 Array which is more precise\r\n * than a regular array.\r\n * @return {Array} Array Array of amplitude values (-1 to 1)\r\n * over time. Array length = bins.\r\n *\r\n */\r\n p5.FFT.prototype.waveform = function() {\r\n var bins, mode, normalArray;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n bins = arguments[i];\r\n this.analyser.fftSize = bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\r\n if (mode && !p5.prototype._isSafari()) {\r\n timeToFloat(this, this.timeDomain);\r\n this.analyser.getFloatTimeDomainData(this.timeDomain);\r\n return this.timeDomain;\r\n } else {\r\n timeToInt(this, this.timeDomain);\r\n this.analyser.getByteTimeDomainData(this.timeDomain);\r\n var normalArray = new Array();\r\n for (var j = 0; j < this.timeDomain.length; j++) {\r\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\r\n normalArray.push(scaled);\r\n }\r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between 0 and 255)\r\n * across the frequency spectrum. Length is equal to FFT bins\r\n * (1024 by default). The array indices correspond to frequencies\r\n * (i.e. pitches), from the lowest to the highest that humans can\r\n * hear. Each value represents amplitude at that slice of the\r\n * frequency spectrum. Must be called prior to using\r\n * getEnergy().\r\n *\r\n * @method analyze\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {Number} [scale] If \"dB,\" returns decibel\r\n * float measurements between\r\n * -140 and 0 (max).\r\n * Otherwise returns integers from 0-255.\r\n * @return {Array} spectrum Array of energy (amplitude/volume)\r\n * values across the frequency spectrum.\r\n * Lowest energy (silence) = 0, highest\r\n * possible is 255.\r\n * @example\r\n *
\r\n * var osc;\r\n * var fft;\r\n *\r\n * function setup(){\r\n * createCanvas(100,100);\r\n * osc = new p5.Oscillator();\r\n * osc.amp(0);\r\n * osc.start();\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var freq = map(mouseX, 0, 800, 20, 15000);\r\n * freq = constrain(freq, 1, 20000);\r\n * osc.freq(freq);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h );\r\n * }\r\n *\r\n * stroke(255);\r\n * text('Freq: ' + round(freq)+'Hz', 10, 10);\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * // only play sound when mouse is over canvas\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * osc.amp(0.5, 0.2);\r\n * } else {\r\n * osc.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n *\r\n *\r\n */\r\n p5.FFT.prototype.analyze = function() {\r\n var mode;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n this.bins = arguments[i];\r\n this.analyser.fftSize = this.bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n if (mode && mode.toLowerCase() === 'db') {\r\n freqToFloat(this);\r\n this.analyser.getFloatFrequencyData(this.freqDomain);\r\n return this.freqDomain;\r\n } else {\r\n freqToInt(this, this.freqDomain);\r\n this.analyser.getByteFrequencyData(this.freqDomain);\r\n var normalArray = Array.apply([], this.freqDomain);\r\n \r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns the amount of energy (volume) at a specific\r\n * \r\n * frequency, or the average amount of energy between two\r\n * frequencies. Accepts Number(s) corresponding\r\n * to frequency (in Hz), or a String corresponding to predefined\r\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\r\n * Returns a range between 0 (no energy/volume at that frequency) and\r\n * 255 (maximum energy).\r\n * NOTE: analyze() must be called prior to getEnergy(). Analyze()\r\n * tells the FFT to analyze frequency data, and getEnergy() uses\r\n * the results determine the value at a specific frequency or\r\n * range of frequencies.\r\n *\r\n * @method getEnergy\r\n * @for p5.FFT\r\n * @param {Number|String} frequency1 Will return a value representing\r\n * energy at this frequency. Alternately,\r\n * the strings \"bass\", \"lowMid\" \"mid\",\r\n * \"highMid\", and \"treble\" will return\r\n * predefined frequency ranges.\r\n * @param {Number} [frequency2] If a second frequency is given,\r\n * will return average amount of\r\n * energy that exists between the\r\n * two frequencies.\r\n * @return {Number} Energy Energy (volume/amplitude) from\r\n * 0 and 255.\r\n *\r\n */\r\n p5.FFT.prototype.getEnergy = function(frequency1, frequency2) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n\r\n if (frequency1 === 'bass') {\r\n frequency1 = this.bass[0];\r\n frequency2 = this.bass[1];\r\n } else if (frequency1 === 'lowMid') {\r\n frequency1 = this.lowMid[0];\r\n frequency2 = this.lowMid[1];\r\n } else if (frequency1 === 'mid') {\r\n frequency1 = this.mid[0];\r\n frequency2 = this.mid[1];\r\n } else if (frequency1 === 'highMid') {\r\n frequency1 = this.highMid[0];\r\n frequency2 = this.highMid[1];\r\n } else if (frequency1 === 'treble') {\r\n frequency1 = this.treble[0];\r\n frequency2 = this.treble[1];\r\n }\r\n\r\n if (typeof frequency1 !== 'number') {\r\n throw 'invalid input for getEnergy()';\r\n } else if (!frequency2) {\r\n // if only one parameter:\r\n var index = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n return this.freqDomain[index];\r\n } else if (frequency1 && frequency2) {\r\n // if two parameters:\r\n // if second is higher than first\r\n if (frequency1 > frequency2) {\r\n var swap = frequency2;\r\n frequency2 = frequency1;\r\n frequency1 = swap;\r\n }\r\n var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length);\r\n\r\n var total = 0;\r\n var numFrequencies = 0;\r\n // add up all of the values for the frequencies\r\n for (var i = lowIndex; i <= highIndex; i++) {\r\n total += this.freqDomain[i];\r\n numFrequencies += 1;\r\n }\r\n // divide by total number of frequencies\r\n var toReturn = total / numFrequencies;\r\n return toReturn;\r\n } else {\r\n throw 'invalid input for getEnergy()';\r\n }\r\n };\r\n\r\n // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\r\n p5.FFT.prototype.getFreq = function(freq1, freq2) {\r\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\r\n var x = this.getEnergy(freq1, freq2);\r\n return x;\r\n };\r\n\r\n /**\r\n * Returns the\r\n * \r\n * spectral centroid of the input signal.\r\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\r\n * tells the FFT to analyze frequency data, and getCentroid() uses\r\n * the results determine the spectral centroid.\r\n *\r\n * @method getCentroid\r\n * @for p5.FFT\r\n * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz.\r\n *\r\n *\r\n * @example\r\n *
\r\n *\r\n *\r\n *function setup(){\r\n * cnv = createCanvas(100,100);\r\n * sound = new p5.AudioIn();\r\n * sound.start();\r\n * fft = new p5.FFT();\r\n * sound.connect(fft);\r\n *}\r\n *\r\n *\r\n *function draw(){\r\n *\r\n * var centroidplot = 0.0;\r\n * var spectralCentroid = 0;\r\n *\r\n *\r\n * background(0);\r\n * stroke(0,255,0);\r\n * var spectrum = fft.analyze();\r\n * fill(0,255,0); // spectrum is green\r\n *\r\n * //draw the spectrum\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(log(i), 0, log(spectrum.length), 0, width);\r\n * var h = map(spectrum[i], 0, 255, 0, height);\r\n * var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\r\n * rect(x, height, rectangle_width, -h )\r\n * }\r\n\r\n * var nyquist = 22050;\r\n *\r\n * // get the centroid\r\n * spectralCentroid = fft.getCentroid();\r\n *\r\n * // the mean_freq_index calculation is for the display.\r\n * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\r\n *\r\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\r\n *\r\n *\r\n * stroke(255,0,0); // the line showing where the centroid is will be red\r\n *\r\n * rect(centroidplot, 0, width / spectrum.length, height)\r\n * noStroke();\r\n * fill(255,255,255); // text is white\r\n * text(\"centroid: \", 10, 20);\r\n * text(round(spectralCentroid)+\" Hz\", 10, 40);\r\n *}\r\n *
\r\n */\r\n p5.FFT.prototype.getCentroid = function() {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var cumulative_sum = 0;\r\n var centroid_normalization = 0;\r\n\r\n for (var i = 0; i < this.freqDomain.length; i++) {\r\n cumulative_sum += i * this.freqDomain[i];\r\n centroid_normalization += this.freqDomain[i];\r\n }\r\n\r\n var mean_freq_index = 0;\r\n\r\n if (centroid_normalization !== 0) {\r\n mean_freq_index = cumulative_sum / centroid_normalization;\r\n }\r\n\r\n var spec_centroid_freq =\r\n mean_freq_index * (nyquist / this.freqDomain.length);\r\n return spec_centroid_freq;\r\n };\r\n\r\n /**\r\n * Smooth FFT analysis by averaging with the last analysis frame.\r\n *\r\n * @method smooth\r\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n */\r\n p5.FFT.prototype.smooth = function(s) {\r\n if (typeof s !== 'undefined') {\r\n this.smoothing = s;\r\n }\r\n return this.smoothing;\r\n };\r\n\r\n p5.FFT.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.analyser) {\r\n this.analyser.disconnect();\r\n delete this.analyser;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values for a given number\r\n * of frequency bands split equally. N defaults to 16.\r\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and linAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method linAverages\r\n * @for p5.FFT\r\n * @param {Number} N Number of returned frequency groups\r\n * @return {Array} linearAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.linAverages = function(N) {\r\n var N = N || 16; // This prevents undefined, null or 0 values of N\r\n\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n var spectrumStep = Math.floor(spectrumLength / N);\r\n\r\n var linearAverages = new Array(N);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // with only one loop in the spectrum data\r\n var groupIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n linearAverages[groupIndex] =\r\n linearAverages[groupIndex] !== undefined\r\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n\r\n // Increase the group index when the last element of the group is processed\r\n if (specIndex % spectrumStep === spectrumStep - 1) {\r\n groupIndex++;\r\n }\r\n }\r\n\r\n return linearAverages;\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values of the spectrum, for a given\r\n * set of \r\n * Octave Bands\r\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and logAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method logAverages\r\n * @for p5.FFT\r\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\r\n * @return {Array} logAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.logAverages = function(octaveBands) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n\r\n var logAverages = new Array(octaveBands.length);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // With only one loop in the spectrum data\r\n var octaveIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n var specIndexFrequency = Math.round(\r\n specIndex * nyquist / this.freqDomain.length\r\n );\r\n\r\n // Increase the group index if the current frequency exceeds the limits of the band\r\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\r\n octaveIndex++;\r\n }\r\n\r\n logAverages[octaveIndex] =\r\n logAverages[octaveIndex] !== undefined\r\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n }\r\n\r\n return logAverages;\r\n };\r\n\r\n /**\r\n * Calculates and Returns the 1/N\r\n * Octave Bands\r\n * N defaults to 3 and minimum central frequency to 15.625Hz.\r\n * (1/3 Octave Bands ~= 31 Frequency Bands)\r\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\r\n * and produce less frequency groups.\r\n *\r\n * @method getOctaveBands\r\n * @for p5.FFT\r\n * @param {Number} N Specifies the 1/N type of generated octave bands\r\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\r\n * @return {Array} octaveBands Array of octave band objects with their bounds\r\n */\r\n p5.FFT.prototype.getOctaveBands = function(N, fCtr0) {\r\n var N = N || 3; // Default to 1/3 Octave Bands\r\n var fCtr0 = fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\r\n\r\n var octaveBands = [];\r\n var lastFrequencyBand = {\r\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\r\n ctr: fCtr0,\r\n hi: fCtr0 * Math.pow(2, 1 / (2 * N))\r\n };\r\n octaveBands.push(lastFrequencyBand);\r\n\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n while (lastFrequencyBand.hi < nyquist) {\r\n var newFrequencyBand = {};\r\n newFrequencyBand.lo = lastFrequencyBand.hi;\r\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\r\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\r\n\r\n octaveBands.push(newFrequencyBand);\r\n lastFrequencyBand = newFrequencyBand;\r\n }\r\n\r\n return octaveBands;\r\n };\r\n\r\n // helper methods to convert type from float (dB) to int (0-255)\r\n var freqToFloat = function(fft) {\r\n if (fft.freqDomain instanceof Float32Array === false) {\r\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var freqToInt = function(fft) {\r\n if (fft.freqDomain instanceof Uint8Array === false) {\r\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToFloat = function(fft) {\r\n if (fft.timeDomain instanceof Float32Array === false) {\r\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToInt = function(fft) {\r\n if (fft.timeDomain instanceof Uint8Array === false) {\r\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // Signal is built with the Tone.js signal by Yotam Mann\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Signal = require('Tone/signal/Signal');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
p5.Signal is a constant audio-rate signal used by p5.Oscillator\r\n * and p5.Envelope for modulation math.
\r\n *\r\n *
This is necessary because Web Audio is processed on a seprate clock.\r\n * For example, the p5 draw loop runs about 60 times per second. But\r\n * the audio clock must process samples 44100 times per second. If we\r\n * want to add a value to each of those samples, we can't do it in the\r\n * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns\r\n * a Tone.Signal from the Tone.js library by Yotam Mann.\r\n * If you want to work directly with audio signals for modular\r\n * synthesis, check out\r\n * tone.js.
\r\n *\r\n * @class p5.Signal\r\n * @constructor\r\n * @return {Tone.Signal} A Signal object from the Tone.js library\r\n * @example\r\n *
\r\n * function setup() {\r\n * carrier = new p5.Oscillator('sine');\r\n * carrier.amp(1); // set amplitude\r\n * carrier.freq(220); // set frequency\r\n * carrier.start(); // start oscillating\r\n *\r\n * modulator = new p5.Oscillator('sawtooth');\r\n * modulator.disconnect();\r\n * modulator.amp(1);\r\n * modulator.freq(4);\r\n * modulator.start();\r\n *\r\n * // Modulator's default amplitude range is -1 to 1.\r\n * // Multiply it by -200, so the range is -200 to 200\r\n * // then add 220 so the range is 20 to 420\r\n * carrier.freq( modulator.mult(-200).add(220) );\r\n * }\r\n *
\r\n */\r\n p5.Signal = function(value) {\r\n var s = new Signal(value);\r\n // p5sound.soundArray.push(s);\r\n return s; // TODO: is this really a constructor?\r\n };\r\n\r\n /**\r\n * Fade to value, for smooth transitions\r\n *\r\n * @method fade\r\n * @for p5.Signal\r\n * @param {Number} value Value to set this signal\r\n * @param {Number} [secondsFromNow] Length of fade, in seconds from now\r\n */\r\n Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime;\r\n Mult.prototype.fade = Signal.prototype.fade;\r\n Add.prototype.fade = Signal.prototype.fade;\r\n Scale.prototype.fade = Signal.prototype.fade;\r\n\r\n\r\n /**\r\n * Connect a p5.sound object or Web Audio node to this\r\n * p5.Signal so that its amplitude values can be scaled.\r\n *\r\n * @method setInput\r\n * @for p5.Signal\r\n * @param {Object} input\r\n */\r\n Signal.prototype.setInput = function(_input) {\r\n _input.connect(this);\r\n };\r\n Mult.prototype.setInput = Signal.prototype.setInput;\r\n Add.prototype.setInput = Signal.prototype.setInput;\r\n Scale.prototype.setInput = Signal.prototype.setInput;\r\n\r\n\r\n // signals can add / mult / scale themselves\r\n\r\n /**\r\n * Add a constant value to this audio signal,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalAdd.\r\n *\r\n * @method add\r\n * @for p5.Signal\r\n * @param {Number} number\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.add = function(num) {\r\n var add = new Add(num);\r\n // add.setInput(this);\r\n this.connect(add);\r\n return add;\r\n };\r\n Mult.prototype.add = Signal.prototype.add;\r\n Add.prototype.add = Signal.prototype.add;\r\n Scale.prototype.add = Signal.prototype.add;\r\n\r\n /**\r\n * Multiply this signal by a constant value,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalMult.\r\n *\r\n * @method mult\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n // mult.setInput(this);\r\n this.connect(mult);\r\n return mult;\r\n };\r\n Mult.prototype.mult = Signal.prototype.mult;\r\n Add.prototype.mult = Signal.prototype.mult;\r\n Scale.prototype.mult = Signal.prototype.mult;\r\n\r\n /**\r\n * Scale this signal value to a given range,\r\n * and return the result as an audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalScale.\r\n *\r\n * @method scale\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n this.connect(scale);\r\n return scale;\r\n };\r\n Mult.prototype.scale = Signal.prototype.scale;\r\n Add.prototype.scale = Signal.prototype.scale;\r\n Scale.prototype.scale = Signal.prototype.scale;\r\n\r\n});\r\n\r\n\r\n","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Frequency is a primitive type for encoding Frequency values. \n\t * Eventually all time values are evaluated to hertz\n\t * using the `eval` method. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * Tone.Frequency(\"C3\") // 261\n\t * Tone.Frequency(38, \"midi\") //\n\t * Tone.Frequency(\"C3\").transpose(4);\n\t */\n\tTone.Frequency = function(val, units){\n\t\tif (this instanceof Tone.Frequency){\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Frequency(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Frequency, Tone.TimeBase);\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUGMENT BASE EXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);\n\n\t/*\n\t * midi type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.midi = {\n\t\tregexp : /^(\\d+(?:\\.\\d+)?midi)/,\n\t\tmethod : function(value){\n\t\t\treturn this.midiToFrequency(value);\n\t\t}\t\n\t};\n\n\t/*\n\t * note type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.note = {\n\t\tregexp : /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,\n\t\tmethod : function(pitch, octave){\n\t\t\tvar index = noteToScaleIndex[pitch.toLowerCase()];\n\t\t\tvar noteNumber = index + (parseInt(octave) + 1) * 12;\n\t\t\treturn this.midiToFrequency(noteNumber);\n\t\t}\t\n\t};\n\n\t/*\n\t * BeatsBarsSixteenths type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.tr = {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\tvar total = 1;\n\t\t\tif (m && m !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t}\n\t\t\tif (q && q !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(q));\n\t\t\t}\n\t\t\tif (s && s !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t}\n\t\t\treturn total;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Transposes the frequency by the given number of semitones.\n\t * @param {Interval} interval\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").transpose(3); //\"C5\"\n\t */\n\tTone.Frequency.prototype.transpose = function(interval){\n\t\tthis._expr = function(expr, interval){\n\t\t\tvar val = expr();\n\t\t\treturn val * this.intervalToFrequencyRatio(interval);\n\t\t}.bind(this, this._expr, interval);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Takes an array of semitone intervals and returns\n\t * an array of frequencies transposed by those intervals.\n\t * @param {Array} intervals\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").harmonize([0, 3, 7]); //[\"A4\", \"C5\", \"E5\"]\n\t */\n\tTone.Frequency.prototype.harmonize = function(intervals){\n\t\tthis._expr = function(expr, intervals){\n\t\t\tvar val = expr();\n\t\t\tvar ret = [];\n\t\t\tfor (var i = 0; i < intervals.length; i++){\n\t\t\t\tret[i] = val * this.intervalToFrequencyRatio(intervals[i]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t}.bind(this, this._expr, intervals);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the value of the frequency as a MIDI note\n\t * @return {MIDI}\n\t * @example\n\t * Tone.Frequency(\"C4\").toMidi(); //60\n\t */\n\tTone.Frequency.prototype.toMidi = function(){\n\t\treturn this.frequencyToMidi(this.valueOf());\n\t};\n\n\t/**\n\t * Return the value of the frequency in Scientific Pitch Notation\n\t * @return {Note}\n\t * @example\n\t * Tone.Frequency(69, \"midi\").toNote(); //\"A4\"\n\t */\n\tTone.Frequency.prototype.toNote = function(){\n\t\tvar freq = this.valueOf();\n\t\tvar log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;\n\t\tvar noteNumber = Math.round(12 * log) + 57;\n\t\tvar octave = Math.floor(noteNumber/12);\n\t\tif(octave < 0){\n\t\t\tnoteNumber += -12 * octave;\n\t\t}\n\t\tvar noteName = scaleIndexToNote[noteNumber % 12];\n\t\treturn noteName + octave.toString();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.Frequency.prototype.toSeconds = function(){\n\t\treturn 1 / this.valueOf();\n\t};\n\n\t/**\n\t * Return the value in Hertz\n\t * @return {Frequency}\n\t */\n\tTone.Frequency.prototype.toFrequency = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in ticks\n\t * @return {Ticks}\n\t */\n\tTone.Frequency.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS HELPERS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._frequencyToUnits = function(freq){\n\t\treturn freq;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._ticksToUnits = function(ticks){\n\t\treturn 1 / ((ticks * 60) / (Tone.Transport.bpm.value * Tone.Transport.PPQ));\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._beatsToUnits = function(beats){\n\t\treturn 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._secondsToUnits = function(seconds){\n\t\treturn 1 / seconds;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.Frequency.prototype._defaultUnits = \"hz\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tFREQUENCY CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Note to scale index\n\t * @type {Object}\n\t */\n\tvar noteToScaleIndex = {\n\t\t\"cbb\" : -2, \"cb\" : -1, \"c\" : 0, \"c#\" : 1, \"cx\" : 2, \n\t\t\"dbb\" : 0, \"db\" : 1, \"d\" : 2, \"d#\" : 3, \"dx\" : 4,\n\t\t\"ebb\" : 2, \"eb\" : 3, \"e\" : 4, \"e#\" : 5, \"ex\" : 6, \n\t\t\"fbb\" : 3, \"fb\" : 4, \"f\" : 5, \"f#\" : 6, \"fx\" : 7,\n\t\t\"gbb\" : 5, \"gb\" : 6, \"g\" : 7, \"g#\" : 8, \"gx\" : 9,\n\t\t\"abb\" : 7, \"ab\" : 8, \"a\" : 9, \"a#\" : 10, \"ax\" : 11,\n\t\t\"bbb\" : 9, \"bb\" : 10, \"b\" : 11, \"b#\" : 12, \"bx\" : 13,\n\t};\n\n\t/**\n\t * scale index to note (sharps)\n\t * @type {Array}\n\t */\n\tvar scaleIndexToNote = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"];\n\n\t/**\n\t * The [concert pitch](https://en.wikipedia.org/wiki/Concert_pitch)\n\t * A4's values in Hertz. \n\t * @type {Frequency}\n\t * @static\n\t */\n\tTone.Frequency.A4 = 440;\n\n\t/**\n\t * Convert a MIDI note to frequency value. \n\t * @param {MIDI} midi The midi number to convert.\n\t * @return {Frequency} the corresponding frequency value\n\t * @example\n\t * tone.midiToFrequency(69); // returns 440\n\t */\n\tTone.Frequency.prototype.midiToFrequency = function(midi){\n\t\treturn Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);\n\t};\n\n\t/**\n\t * Convert a frequency value to a MIDI note.\n\t * @param {Frequency} frequency The value to frequency value to convert.\n\t * @returns {MIDI}\n\t * @example\n\t * tone.midiToFrequency(440); // returns 69\n\t */\n\tTone.Frequency.prototype.frequencyToMidi = function(frequency){\n\t\treturn 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;\n\t};\n\n\treturn Tone.Frequency;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TransportTime is a the time along the Transport's\n\t * timeline. It is similar to Tone.Time, but instead of evaluating\n\t * against the AudioContext's clock, it is evaluated against\n\t * the Transport's position. See [TransportTime wiki](https://github.com/Tonejs/Tone.js/wiki/TransportTime).\n\t * @constructor\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @extends {Tone.Time}\n\t */\n\tTone.TransportTime = function(val, units){\n\t\tif (this instanceof Tone.TransportTime){\n\t\t\t\n\t\t\tTone.Time.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.TransportTime(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TransportTime, Tone.Time);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);\n\n\t/**\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\tvar subdivision = this._secondsToTicks(rh());\n\t\t\tvar multiple = Math.ceil(Tone.Transport.ticks / subdivision);\n\t\t\treturn this._ticksToUnits(multiple * subdivision);\n\t\t}\n\t};\n\n\t/**\n\t * Convert seconds into ticks\n\t * @param {Seconds} seconds\n\t * @return {Ticks}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._secondsToTicks = function(seconds){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = seconds / quarterTime;\n\t\treturn Math.round(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Evaluate the time expression. Returns values in ticks\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.valueOf = function(){\n\t\tvar val = this._secondsToTicks(this._expr());\n\t\treturn val + (this._plusNow ? Tone.Transport.ticks : 0);\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.toTicks = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.TransportTime.prototype.toSeconds = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow ? Tone.Transport.seconds : 0);\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t */\n\tTone.TransportTime.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\treturn Tone.TransportTime;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n\r\n /**\r\n *
Envelopes are pre-defined amplitude distribution over time.\r\n * Typically, envelopes are used to control the output volume\r\n * of an object, a series of fades referred to as Attack, Decay,\r\n * Sustain and Release (\r\n * ADSR\r\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\r\n * control an Oscillator's frequency like this: osc.freq(env).
\r\n *
Use setRange to change the attack/release level.\r\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.
\r\n *
Use the play method to play the entire envelope,\r\n * the ramp method for a pingable trigger,\r\n * or triggerAttack/\r\n * triggerRelease to trigger noteOn/noteOff.
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope = function(t1, l1, t2, l2, t3, l3) {\r\n /**\r\n * Time until envelope reaches attackLevel\r\n * @property attackTime\r\n */\r\n this.aTime = t1 || 0.1;\r\n /**\r\n * Level once attack is complete.\r\n * @property attackLevel\r\n */\r\n this.aLevel = l1 || 1;\r\n /**\r\n * Time until envelope reaches decayLevel.\r\n * @property decayTime\r\n */\r\n this.dTime = t2 || 0.5;\r\n /**\r\n * Level after decay. The envelope will sustain here until it is released.\r\n * @property decayLevel\r\n */\r\n this.dLevel = l2 || 0;\r\n /**\r\n * Duration of the release portion of the envelope.\r\n * @property releaseTime\r\n */\r\n this.rTime = t3 || 0;\r\n /**\r\n * Level at the end of the release.\r\n * @property releaseLevel\r\n */\r\n this.rLevel = l3 || 0;\r\n\r\n this._rampHighPercentage = 0.98;\r\n\r\n this._rampLowPercentage = 0.02;\r\n\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.control = new TimelineSignal();\r\n\r\n this._init(); // this makes sure the envelope starts at zero\r\n\r\n this.control.connect(this.output); // connect to the output\r\n\r\n this.connection = null; // store connection\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.control];\r\n\r\n //whether envelope should be linear or exponential curve\r\n this.isExponential = false;\r\n\r\n // oscillator or buffer source to clear on env complete\r\n // to save resources if/when it is retriggered\r\n this.sourceToClear = null;\r\n\r\n // set to true if attack is set, then false on release\r\n this.wasTriggered = false;\r\n\r\n\r\n // add to the soundArray so we can dispose of the env later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n // this init function just smooths the starting value to zero and gives a start point for the timeline\r\n // - it was necessary to remove glitches at the beginning.\r\n p5.Envelope.prototype._init = function () {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = now;\r\n this.control.setTargetAtTime(0.00001, t, .001);\r\n //also, compute the correct time constants\r\n this._setRampAD(this.aTime, this.dTime);\r\n };\r\n\r\n /**\r\n * Reset the envelope with a series of time/value pairs.\r\n *\r\n * @method set\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds) before level\r\n * reaches attackLevel\r\n * @param {Number} attackLevel Typically an amplitude between\r\n * 0.0 and 1.0\r\n * @param {Number} decayTime Time\r\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\r\n * decayLevel = sustainLevel)\r\n * @param {Number} releaseTime Release Time (in seconds)\r\n * @param {Number} releaseLevel Amplitude\r\n * @example\r\n *
\r\n * var t1 = 0.1; // attack time in seconds\r\n * var l1 = 0.7; // attack level 0.0 to 1.0\r\n * var t2 = 0.3; // decay time in seconds\r\n * var l2 = 0.1; // decay level 0.0 to 1.0\r\n * var t3 = 0.2; // sustain time in seconds\r\n * var l3 = 0.5; // sustain level 0.0 to 1.0\r\n * // release level defaults to zero\r\n *\r\n * var env;\r\n * var triOsc;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope(t1, l1, t2, l2, t3, l3);\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env); // give the env control of the triOsc's amp\r\n * triOsc.start();\r\n * }\r\n *\r\n * // mouseClick triggers envelope if over canvas\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(triOsc);\r\n * }\r\n * }\r\n *
\r\n *\r\n */\r\n p5.Envelope.prototype.set = function(t1, l1, t2, l2, t3, l3) {\r\n this.aTime = t1;\r\n this.aLevel = l1;\r\n this.dTime = t2 || 0;\r\n this.dLevel = l2 || 0;\r\n this.rTime = t3 || 0;\r\n this.rLevel = l3 || 0;\r\n\r\n // set time constants for ramp\r\n this._setRampAD(t1, t2);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setADSR = function(aTime, dTime, sPercent, rTime) {\r\n this.aTime = aTime;\r\n this.dTime = dTime || 0;\r\n\r\n // lerp\r\n this.sPercent = sPercent || 0;\r\n this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n\r\n this.rTime = rTime || 0;\r\n\r\n // also set time constants for ramp\r\n this._setRampAD(aTime, dTime);\r\n };\r\n\r\n /**\r\n * Set max (attackLevel) and min (releaseLevel) of envelope.\r\n *\r\n * @method setRange\r\n * @for p5.Envelope\r\n * @param {Number} aLevel attack level (defaults to 1)\r\n * @param {Number} rLevel release level (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setRange = function(aLevel, rLevel) {\r\n this.aLevel = aLevel || 1;\r\n this.rLevel = rLevel || 0;\r\n\r\n // not sure if this belongs here:\r\n\r\n // {Number} [dLevel] decay/sustain level (optional)\r\n // if (typeof(dLevel) !== 'undefined') {\r\n // this.dLevel = dLevel\r\n // } else if (this.sPercent) {\r\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n // }\r\n };\r\n\r\n // private (undocumented) method called when ADSR is set to set time constants for ramp\r\n //\r\n // Set the \r\n // time constants for simple exponential ramps.\r\n // The larger the time constant value, the slower the\r\n // transition will be.\r\n //\r\n // method _setRampAD\r\n // param {Number} attackTimeConstant attack time constant\r\n // param {Number} decayTimeConstant decay time constant\r\n //\r\n p5.Envelope.prototype._setRampAD = function(t1, t2) {\r\n this._rampAttackTime = this.checkExpInput(t1);\r\n this._rampDecayTime = this.checkExpInput(t2);\r\n\r\n var TCDenominator = 1.0;\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n // private method\r\n p5.Envelope.prototype.setRampPercentages = function(p1, p2) {\r\n //set the percentages that the simple exponential ramps go to\r\n this._rampHighPercentage = this.checkExpInput(p1);\r\n this._rampLowPercentage = this.checkExpInput(p2);\r\n var TCDenominator = 1.0;\r\n //now re-compute the time constants based on those percentages\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n\r\n /**\r\n * Assign a parameter to be controlled by this envelope.\r\n * If a p5.Sound object is given, then the p5.Envelope will control its\r\n * output gain. If multiple inputs are provided, the env will\r\n * control all of them.\r\n *\r\n * @method setInput\r\n * @for p5.Envelope\r\n * @param {Object} [...inputs] A p5.sound object or\r\n * Web Audio Param.\r\n */\r\n p5.Envelope.prototype.setInput = function() {\r\n for (var i = 0; i\r\n * Web Audio Audio Param.\r\n *\r\n * @method play\r\n * @for p5.Envelope\r\n * @param {Object} unit A p5.sound object or\r\n * Web Audio Param.\r\n * @param {Number} [startTime] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * // trigger env on triOsc, 0 seconds from now\r\n * // After decay, sustain for 0.2 seconds before release\r\n * env.play(triOsc, 0, 0.2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.play = function(unit, secondsFromNow, susTime) {\r\n var tFromNow = secondsFromNow || 0;\r\n var susTime = susTime || 0;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n this.triggerAttack(unit, tFromNow);\r\n\r\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime);\r\n\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go. Input can be\r\n * any p5.sound object, or a \r\n * Web Audio Param.\r\n *\r\n * @method triggerAttack\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time from now (in seconds)\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerAttack = function(unit, secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n this.lastAttack = t;\r\n this.wasTriggered = true;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // after each ramp completes, cancel scheduled values\r\n // (so they can be overridden in case env has been re-triggered)\r\n // then, set current value (with linearRamp to avoid click)\r\n // then, schedule the next automation...\r\n\r\n // attack\r\n t += this.aTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.aLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n\r\n }\r\n\r\n // decay to decay level (if using ADSR, then decay level == sustain level)\r\n t += this.dTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.dLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n };\r\n\r\n /**\r\n * Trigger the Release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method triggerRelease\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerRelease = function(unit, secondsFromNow) {\r\n\r\n // only trigger a release if an attack was triggered\r\n if (!this.wasTriggered) {\r\n // this currently causes a bit of trouble:\r\n // if a later release has been scheduled (via the play function)\r\n // a new earlier release won't interrupt it, because\r\n // this.wasTriggered has already been set to false.\r\n // If we want new earlier releases to override, then we need to\r\n // keep track of the last release time, and if the new release time is\r\n // earlier, then use it.\r\n return;\r\n }\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear or exponential ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // release\r\n t += this.rTime;\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.rLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n this.wasTriggered = false;\r\n };\r\n\r\n /**\r\n * Exponentially ramp to a value using the first two\r\n * values from setADSR(attackTime, decayTime)\r\n * as \r\n * time constants for simple exponential ramps.\r\n * If the value is higher than current value, it uses attackTime,\r\n * while a decrease uses decayTime.\r\n *\r\n * @method ramp\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow When to trigger the ramp\r\n * @param {Number} v Target value\r\n * @param {Number} [v2] Second target value (optional)\r\n * @example\r\n *
\r\n * var env, osc, amp, cnv;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var attackLevel = 1;\r\n * var decayLevel = 0;\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100, 100);\r\n * fill(0,255,0);\r\n * noStroke();\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.amp(env);\r\n * osc.start();\r\n *\r\n * amp = new p5.Amplitude();\r\n *\r\n * cnv.mousePressed(triggerRamp);\r\n * }\r\n *\r\n * function triggerRamp() {\r\n * env.ramp(osc, 0, attackLevel, decayLevel);\r\n * }\r\n *\r\n * function draw() {\r\n * background(20,20,20);\r\n * text('click me', 10, 20);\r\n * var h = map(amp.getLevel(), 0, 0.4, 0, height);;\r\n *\r\n * rect(0, height, width, -h);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.ramp = function(unit, secondsFromNow, v1, v2) {\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n var destination1 = this.checkExpInput(v1);\r\n var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\r\n\r\n // connect env to unit if not already connected\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n //get current value\r\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\r\n // this.control.cancelScheduledValues(t);\r\n\r\n //if it's going up\r\n if (destination1 > currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\r\n t += this._rampAttackTime;\r\n }\r\n\r\n //if it's going down\r\n else if (destination1 < currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\r\n t += this._rampDecayTime;\r\n }\r\n\r\n // Now the second part of envelope begins\r\n if (destination2 === undefined) return;\r\n\r\n //if it's going up\r\n if (destination2 > destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\r\n }\r\n\r\n //if it's going down\r\n else if (destination2 < destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\r\n }\r\n };\r\n\r\n\r\n p5.Envelope.prototype.connect = function(unit) {\r\n this.connection = unit;\r\n\r\n // assume we're talking about output gain\r\n // unless given a different audio param\r\n if (unit instanceof p5.Oscillator ||\r\n unit instanceof p5.SoundFile ||\r\n unit instanceof p5.AudioIn ||\r\n unit instanceof p5.Reverb ||\r\n unit instanceof p5.Noise ||\r\n unit instanceof p5.Filter ||\r\n unit instanceof p5.Delay\r\n ) {\r\n unit = unit.output.gain;\r\n }\r\n if (unit instanceof AudioParam) {\r\n //set the initial value\r\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\r\n }\r\n if (unit instanceof p5.Signal) {\r\n unit.setValue(0);\r\n }\r\n this.output.connect(unit);\r\n };\r\n\r\n p5.Envelope.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n // Signal Math\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method\r\n * again will override the initial add() with new values.\r\n *\r\n * @method add\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Envelope's output amplitude\r\n * by a fixed value. Calling this method\r\n * again will override the initial mult() with new values.\r\n *\r\n * @method mult\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this envelope's amplitude values to a given\r\n * range, and return the envelope. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Envelope\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var scale = new Scale(inMin, inMax, outMin, outMax);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\r\n };\r\n\r\n\r\n // get rid of the oscillator\r\n p5.Envelope.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.disconnect();\r\n if (this.control) {\r\n this.control.dispose();\r\n this.control = null;\r\n }\r\n for (var i = 1; i < this.mathOps.length; i++) {\r\n this.mathOps[i].dispose();\r\n }\r\n };\r\n\r\n // Different name for backwards compatibility, replicates p5.Envelope class\r\n p5.Env = function(t1, l1, t2, l2, t3, l3) {\r\n console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\r\n 'Please use the new p5.Envelope instead.');\r\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\r\n };\r\n p5.Env.prototype = Object.create(p5.Envelope.prototype);\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n require('oscillator');\r\n\r\n /**\r\n * Creates a Pulse object, an oscillator that implements\r\n * Pulse Width Modulation.\r\n * The pulse is created with two oscillators.\r\n * Accepts a parameter for frequency, and to set the\r\n * width between the pulses. See \r\n * p5.Oscillator for a full list of methods.\r\n *\r\n * @class p5.Pulse\r\n * @extends p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\r\n * @param {Number} [w] Width between the pulses (0 to 1.0,\r\n * defaults to 0)\r\n * @example\r\n *
Note: This uses the getUserMedia/\r\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\r\n * is limited to localhost and https, but access over http may be limited.
\r\n *\r\n * @class p5.AudioIn\r\n * @constructor\r\n * @param {Function} [errorCallback] A function to call if there is an error\r\n * accessing the AudioIn. For example,\r\n * Safari and iOS devices do not\r\n * currently allow microphone access.\r\n * @example\r\n *
\r\n * var mic;\r\n * function setup(){\r\n * mic = new p5.AudioIn()\r\n * mic.start();\r\n * }\r\n * function draw(){\r\n * background(0);\r\n * micLevel = mic.getLevel();\r\n * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);\r\n * }\r\n *
\r\n */\r\n p5.AudioIn = function(errorCallback) {\r\n // set up audio input\r\n /**\r\n * @property {GainNode} input\r\n */\r\n this.input = p5sound.audiocontext.createGain();\r\n /**\r\n * @property {GainNode} output\r\n */\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n /**\r\n * @property {MediaStream|null} stream\r\n */\r\n this.stream = null;\r\n /**\r\n * @property {MediaStreamAudioSourceNode|null} mediaStream\r\n */\r\n this.mediaStream = null;\r\n /**\r\n * @property {Number|null} currentSource\r\n */\r\n this.currentSource = null;\r\n\r\n /**\r\n * Client must allow browser to access their microphone / audioin source.\r\n * Default: false. Will become true when the client enables acces.\r\n *\r\n * @property {Boolean} enabled\r\n */\r\n this.enabled = false;\r\n\r\n /**\r\n * Input amplitude, connect to it by default but not to master out\r\n *\r\n * @property {p5.Amplitude} amplitude\r\n */\r\n this.amplitude = new p5.Amplitude();\r\n this.output.connect(this.amplitude.input);\r\n\r\n if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) {\r\n errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices');\r\n }\r\n\r\n // add to soundArray so we can dispose on close\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start processing audio input. This enables the use of other\r\n * AudioIn methods like getLevel(). Note that by default, AudioIn\r\n * is not connected to p5.sound's output. So you won't hear\r\n * anything unless you use the connect() method. \r\n *\r\n * Certain browsers limit access to the user's microphone. For example,\r\n * Chrome only allows access from localhost and over https. For this reason,\r\n * you may want to include an errorCallback—a function that is called in case\r\n * the browser won't provide mic access.\r\n *\r\n * @method start\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] Name of a function to call on\r\n * success.\r\n * @param {Function} [errorCallback] Name of a function to call if\r\n * there was an error. For example,\r\n * some browsers do not support\r\n * getUserMedia.\r\n */\r\n p5.AudioIn.prototype.start = function(successCallback, errorCallback) {\r\n var self = this;\r\n\r\n if (this.stream) {\r\n this.stop();\r\n }\r\n\r\n // set the audio source\r\n var audioSource = p5sound.inputSources[self.currentSource];\r\n var constraints = {\r\n audio: {\r\n sampleRate: p5sound.audiocontext.sampleRate,\r\n echoCancellation: false\r\n }\r\n };\r\n\r\n // if developers determine which source to use\r\n if (p5sound.inputSources[this.currentSource]) {\r\n constraints.audio.deviceId = audioSource.deviceId;\r\n }\r\n\r\n window.navigator.mediaDevices.getUserMedia( constraints )\r\n .then( function(stream) {\r\n self.stream = stream;\r\n self.enabled = true;\r\n // Wrap a MediaStreamSourceNode around the live input\r\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\r\n self.mediaStream.connect(self.output);\r\n // only send to the Amplitude reader, so we can see it but not hear it.\r\n self.amplitude.setInput(self.output);\r\n if (successCallback) successCallback();\r\n })\r\n .catch( function(err) {\r\n if (errorCallback) errorCallback(err);\r\n else console.error(err);\r\n });\r\n };\r\n\r\n /**\r\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\r\n * If re-starting, the user may be prompted for permission access.\r\n *\r\n * @method stop\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.stop = function() {\r\n if (this.stream) {\r\n this.stream.getTracks().forEach(function(track) {\r\n track.stop();\r\n });\r\n\r\n this.mediaStream.disconnect();\r\n\r\n delete this.mediaStream;\r\n delete this.stream;\r\n }\r\n };\r\n\r\n /**\r\n * Connect to an audio unit. If no parameter is provided, will\r\n * connect to the master output (i.e. your speakers). \r\n *\r\n * @method connect\r\n * @for p5.AudioIn\r\n * @param {Object} [unit] An object that accepts audio input,\r\n * such as an FFT\r\n */\r\n p5.AudioIn.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n }\r\n else if (unit.hasOwnProperty('analyser')) {\r\n this.output.connect(unit.analyser);\r\n }\r\n else {\r\n this.output.connect(unit);\r\n }\r\n }\r\n else {\r\n this.output.connect(p5sound.input);\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect the AudioIn from all audio units. For example, if\r\n * connect() had been called, disconnect() will stop sending\r\n * signal to your speakers. \r\n *\r\n * @method disconnect\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n // stay connected to amplitude even if not outputting to p5\r\n this.output.connect(this.amplitude.input);\r\n }\r\n };\r\n\r\n /**\r\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\r\n * class contains its own instance of the Amplitude class to help\r\n * make it easy to get a microphone's volume level. Accepts an\r\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\r\n * .start() before using .getLevel(). \r\n *\r\n * @method getLevel\r\n * @for p5.AudioIn\r\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\r\n * Smooths values based on previous values.\r\n * @return {Number} Volume level (between 0.0 and 1.0)\r\n */\r\n p5.AudioIn.prototype.getLevel = function(smoothing) {\r\n if (smoothing) {\r\n this.amplitude.smoothing = smoothing;\r\n }\r\n return this.amplitude.getLevel();\r\n };\r\n\r\n /**\r\n * Set amplitude (volume) of a mic input between 0 and 1.0. \r\n *\r\n * @method amp\r\n * @for p5.AudioIn\r\n * @param {Number} vol between 0 and 1.0\r\n * @param {Number} [time] ramp time (optional)\r\n */\r\n p5.AudioIn.prototype.amp = function(vol, t) {\r\n if (t) {\r\n var rampTime = t || 0;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime);\r\n this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime);\r\n } else {\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Returns a list of available input sources. This is a wrapper\r\n * for and it returns a Promise.\r\n *\r\n * @method getSources\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] This callback function handles the sources when they\r\n * have been enumerated. The callback function\r\n * receives the deviceList array as its only argument\r\n * @param {Function} [errorCallback] This optional callback receives the error\r\n * message as its argument.\r\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\r\n * to the enumerateDevices() method\r\n * @example\r\n *
\r\n */\r\n p5.AudioIn.prototype.getSources = function (onSuccess, onError) {\r\n return new Promise( function(resolve, reject) {\r\n window.navigator.mediaDevices.enumerateDevices()\r\n .then( function(devices) {\r\n p5sound.inputSources = devices.filter(function(device) {\r\n return device.kind === 'audioinput';\r\n });\r\n resolve(p5sound.inputSources);\r\n if (onSuccess) {\r\n onSuccess(p5sound.inputSources);\r\n }\r\n })\r\n .catch( function(error) {\r\n reject(error);\r\n if (onError) {\r\n onError(error);\r\n } else {\r\n console.error('This browser does not support MediaStreamTrack.getSources()');\r\n }\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Set the input source. Accepts a number representing a\r\n * position in the array returned by getSources().\r\n * This is only available in browsers that support\r\n * navigator.mediaDevices.enumerateDevices(). \r\n *\r\n * @method setSource\r\n * @for p5.AudioIn\r\n * @param {number} num position of input source in the array\r\n */\r\n p5.AudioIn.prototype.setSource = function(num) {\r\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\r\n // set the current source\r\n this.currentSource = num;\r\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\r\n } else {\r\n console.log('unable to set input source');\r\n }\r\n\r\n // restart stream if currently active\r\n if (this.stream && this.stream.active) {\r\n this.start();\r\n }\r\n };\r\n\r\n // private method\r\n p5.AudioIn.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop();\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.amplitude) {\r\n this.amplitude.disconnect();\r\n }\r\n delete this.amplitude;\r\n delete this.output;\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Expr\", \n\t\"Tone/signal/EqualPowerGain\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Crossfade provides equal power fading between two inputs. \n\t * More on crossfading technique [here](https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Crossfading).\n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t * @param {NormalRange} [initialFade=0.5]\n\t * @example\n\t * var crossFade = new Tone.CrossFade(0.5);\n\t * //connect effect A to crossfade from\n\t * //effect output 0 to crossfade input 0\n\t * effectA.connect(crossFade, 0, 0);\n\t * //connect effect B to crossfade from\n\t * //effect output 0 to crossfade input 1\n\t * effectB.connect(crossFade, 0, 1);\n\t * crossFade.fade.value = 0;\n\t * // ^ only effectA is output\n\t * crossFade.fade.value = 1;\n\t * // ^ only effectB is output\n\t * crossFade.fade.value = 0.5;\n\t * // ^ the two signals are mixed equally. \n\t */\t\t\n\tTone.CrossFade = function(initialFade){\n\n\t\tthis.createInsOuts(2, 1);\n\n\t\t/**\n\t\t * Alias for input[0]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.a = this.input[0] = new Tone.Gain();\n\n\t\t/**\n\t\t * Alias for input[1]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.b = this.input[1] = new Tone.Gain();\n\n\t\t/**\n\t\t * \tThe mix between the two inputs. A fade value of 0\n\t\t * \twill output 100% input[0] and \n\t\t * \ta value of 1 will output 100% input[1]. \n\t\t * @type {NormalRange}\n\t\t * @signal\n\t\t */\n\t\tthis.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerA = new Tone.EqualPowerGain();\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerB = new Tone.EqualPowerGain();\n\t\t\n\t\t/**\n\t\t * invert the incoming signal\n\t\t * @private\n\t\t * @type {Tone}\n\t\t */\n\t\tthis._invert = new Tone.Expr(\"1 - $0\");\n\n\t\t//connections\n\t\tthis.a.connect(this.output);\n\t\tthis.b.connect(this.output);\n\t\tthis.fade.chain(this._equalPowerB, this.b.gain);\n\t\tthis.fade.chain(this._invert, this._equalPowerA, this.a.gain);\n\t\tthis._readOnly(\"fade\");\n\t};\n\n\tTone.extend(Tone.CrossFade);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.CrossFade} this\n\t */\n\tTone.CrossFade.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._writable(\"fade\");\n\t\tthis._equalPowerA.dispose();\n\t\tthis._equalPowerA = null;\n\t\tthis._equalPowerB.dispose();\n\t\tthis._equalPowerB = null;\n\t\tthis.fade.dispose();\n\t\tthis.fade = null;\n\t\tthis._invert.dispose();\n\t\tthis._invert = null;\n\t\tthis.a.dispose();\n\t\tthis.a = null;\n\t\tthis.b.dispose();\n\t\tthis.b = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.CrossFade;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Subtract\", \"Tone/signal/Multiply\", \n\t\"Tone/signal/GreaterThan\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Abs\", \"Tone/signal/Negate\", \n\t\"Tone/signal/Modulo\", \"Tone/signal/Pow\", \"Tone/signal/AudioToGain\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Evaluate an expression at audio rate.
\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {string} expr the expression to generate\n\t * @example\n\t * //adds the signals from input[0] and input[1].\n\t * var expr = new Tone.Expr(\"$0 + $1\");\n\t */\n\tTone.Expr = function(){\n\n\t\tvar expr = this._replacements(Array.prototype.slice.call(arguments));\n\t\tvar inputCount = this._parseInputs(expr);\n\n\t\t/**\n\t\t * hold onto all of the nodes for disposal\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._nodes = [];\n\n\t\t/**\n\t\t * The inputs. The length is determined by the expression. \n\t\t * @type {Array}\n\t\t */\n\t\tthis.input = new Array(inputCount);\n\n\t\t//create a gain for each input\n\t\tfor (var i = 0; i < inputCount; i++){\n\t\t\tthis.input[i] = this.context.createGain();\n\t\t}\n\n\t\t//parse the syntax tree\n\t\tvar tree = this._parseTree(expr);\n\t\t//evaluate the results\n\t\tvar result;\n\t\ttry {\n\t\t\tresult = this._eval(tree);\n\t\t} catch (e){\n\t\t\tthis._disposeNodes();\n\t\t\tthrow new Error(\"Tone.Expr: Could evaluate expression: \"+expr);\n\t\t}\n\n\t\t/**\n\t\t * The output node is the result of the expression\n\t\t * @type {Tone}\n\t\t */\n\t\tthis.output = result;\n\t};\n\n\tTone.extend(Tone.Expr, Tone.SignalBase);\n\n\t//some helpers to cut down the amount of code\n\tfunction applyBinary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\tself._eval(args[1]).connect(op, 0, 1);\n\t\treturn op;\n\t}\n\tfunction applyUnary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\treturn op;\n\t}\n\tfunction getNumber(arg){\n\t\treturn arg ? parseFloat(arg) : undefined;\n\t}\n\tfunction literalNumber(arg){\n\t\treturn arg && arg.args ? parseFloat(arg.args) : undefined;\n\t}\n\n\t/*\n\t * the Expressions that Tone.Expr can parse.\n\t *\n\t * each expression belongs to a group and contains a regexp \n\t * for selecting the operator as well as that operators method\n\t * \n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Expr._Expressions = {\n\t\t//values\n\t\t\"value\" : {\n\t\t\t\"signal\" : {\n\t\t\t\tregexp : /^\\d+\\.\\d+|^\\d+/,\n\t\t\t\tmethod : function(arg){\n\t\t\t\t\tvar sig = new Tone.Signal(getNumber(arg));\n\t\t\t\t\treturn sig;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"input\" : {\n\t\t\t\tregexp : /^\\$\\d/,\n\t\t\t\tmethod : function(arg, self){\n\t\t\t\t\treturn self.input[getNumber(arg.substr(1))];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t//syntactic glue\n\t\t\"glue\" : {\n\t\t\t\"(\" : {\n\t\t\t\tregexp : /^\\(/,\n\t\t\t},\n\t\t\t\")\" : {\n\t\t\t\tregexp : /^\\)/,\n\t\t\t},\n\t\t\t\",\" : {\n\t\t\t\tregexp : /^,/,\n\t\t\t}\n\t\t},\n\t\t//functions\n\t\t\"func\" : {\n\t\t\t\"abs\" : {\n\t\t\t\tregexp : /^abs/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Abs)\n\t\t\t},\n\t\t\t\"mod\" : {\n\t\t\t\tregexp : /^mod/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar modulus = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Modulo(modulus);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"pow\" : {\n\t\t\t\tregexp : /^pow/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar exp = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Pow(exp);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"a2g\" : {\n\t\t\t\tregexp : /^a2g/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar op = new Tone.AudioToGain();\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t//binary expressions\n\t\t\"binary\" : {\n\t\t\t\"+\" : {\n\t\t\t\tregexp : /^\\+/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Add)\n\t\t\t},\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\t//both unary and binary op\n\t\t\t\t\tif (args.length === 1){\n\t\t\t\t\t\treturn applyUnary(Tone.Negate, args, self);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn applyBinary(Tone.Subtract, args, self);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"*\" : {\n\t\t\t\tregexp : /^\\*/,\n\t\t\t\tprecedence : 0,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Multiply)\n\t\t\t}\n\t\t},\n\t\t//unary expressions\n\t\t\"unary\" : {\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Negate)\n\t\t\t},\n\t\t\t\"!\" : {\n\t\t\t\tregexp : /^\\!/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.NOT)\n\t\t\t},\n\t\t},\n\t};\n\t\t\n\t/**\n\t * @param {string} expr the expression string\n\t * @return {number} the input count\n\t * @private\n\t */\n\tTone.Expr.prototype._parseInputs = function(expr){\n\t\tvar inputArray = expr.match(/\\$\\d/g);\n\t\tvar inputMax = 0;\n\t\tif (inputArray !== null){\n\t\t\tfor (var i = 0; i < inputArray.length; i++){\n\t\t\t\tvar inputNum = parseInt(inputArray[i].substr(1)) + 1;\n\t\t\t\tinputMax = Math.max(inputMax, inputNum);\n\t\t\t}\n\t\t}\n\t\treturn inputMax;\n\t};\n\n\t/**\n\t * @param {Array} args \tan array of arguments\n\t * @return {string} the results of the replacements being replaced\n\t * @private\n\t */\n\tTone.Expr.prototype._replacements = function(args){\n\t\tvar expr = args.shift();\n\t\tfor (var i = 0; i < args.length; i++){\n\t\t\texpr = expr.replace(/\\%/i, args[i]);\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.Expr.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr){\n\t\t\tfor (var type in Tone.Expr._Expressions){\n\t\t\t\tvar group = Tone.Expr._Expressions[type];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype : type,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t\tmethod : op.method\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * recursively parse the string expression into a syntax tree\n\t * \n\t * @param {string} expr \n\t * @return {Object}\n\t * @private\n\t */\n\tTone.Expr.prototype._parseTree = function(expr){\n\t\tvar lexer = this._tokenize(expr);\n\t\tvar isUndef = this.isUndef.bind(this);\n\n\t\tfunction matchSyntax(token, syn) {\n\t\t\treturn !isUndef(token) && \n\t\t\t\ttoken.type === \"glue\" &&\n\t\t\t\ttoken.value === syn;\n\t\t}\n\n\t\tfunction matchGroup(token, groupName, prec) {\n\t\t\tvar ret = false;\n\t\t\tvar group = Tone.Expr._Expressions[groupName];\n\t\t\tif (!isUndef(token)){\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\t\tif (!isUndef(prec)){\n\t\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\n\t\tfunction parseExpression(precedence) {\n\t\t\tif (isUndef(precedence)){\n\t\t\t\tprecedence = 5;\n\t\t\t}\n\t\t\tvar expr;\n\t\t\tif (precedence < 0){\n\t\t\t\texpr = parseUnary();\n\t\t\t} else {\n\t\t\t\texpr = parseExpression(precedence-1);\n\t\t\t}\n\t\t\tvar token = lexer.peek();\n\t\t\twhile (matchGroup(token, \"binary\", precedence)) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [\n\t\t\t\t\t\texpr,\n\t\t\t\t\t\tparseExpression(precedence-1)\n\t\t\t\t\t]\n\t\t\t\t};\n\t\t\t\ttoken = lexer.peek();\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\n\t\tfunction parseUnary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (matchGroup(token, \"unary\")) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = parseUnary();\n\t\t\t\treturn {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [expr]\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn parsePrimary();\n\t\t}\n\n\t\tfunction parsePrimary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (isUndef(token)) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected termination of expression\");\n\t\t\t}\n\t\t\tif (token.type === \"func\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn parseFunctionCall(token);\n\t\t\t}\n\t\t\tif (token.type === \"value\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn {\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : token.value\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (matchSyntax(token, \"(\")) {\n\t\t\t\tlexer.next();\n\t\t\t\texpr = parseExpression();\n\t\t\t\ttoken = lexer.next();\n\t\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t\t}\n\t\t\t\treturn expr;\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Parse error, cannot process token \" + token.value);\n\t\t}\n\n\t\tfunction parseFunctionCall(func) {\n\t\t\tvar token, args = [];\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \"(\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ( in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\ttoken = lexer.peek();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\targs = parseArgumentList();\n\t\t\t}\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ) in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod : func.method,\n\t\t\t\targs : args,\n\t\t\t\tname : name\n\t\t\t};\n\t\t}\n\n\t\tfunction parseArgumentList() {\n\t\t\tvar token, expr, args = [];\n\t\t\twhile (true) {\n\t\t\t\texpr = parseExpression();\n\t\t\t\tif (isUndef(expr)) {\n\t\t\t\t\t// TODO maybe throw exception?\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\targs.push(expr);\n\t\t\t\ttoken = lexer.peek();\n\t\t\t\tif (!matchSyntax(token, \",\")) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlexer.next();\n\t\t\t}\n\t\t\treturn args;\n\t\t}\n\n\t\treturn parseExpression();\n\t};\n\n\t/**\n\t * recursively evaluate the expression tree\n\t * @param {Object} tree \n\t * @return {AudioNode} the resulting audio node from the expression\n\t * @private\n\t */\n\tTone.Expr.prototype._eval = function(tree){\n\t\tif (!this.isUndef(tree)){\n\t\t\tvar node = tree.method(tree.args, this);\n\t\t\tthis._nodes.push(node);\n\t\t\treturn node;\n\t\t} \n\t};\n\n\t/**\n\t * dispose all the nodes\n\t * @private\n\t */\n\tTone.Expr.prototype._disposeNodes = function(){\n\t\tfor (var i = 0; i < this._nodes.length; i++){\n\t\t\tvar node = this._nodes[i];\n\t\t\tif (this.isFunction(node.dispose)) {\n\t\t\t\tnode.dispose();\n\t\t\t} else if (this.isFunction(node.disconnect)) {\n\t\t\t\tnode.disconnect();\n\t\t\t}\n\t\t\tnode = null;\n\t\t\tthis._nodes[i] = null;\n\t\t}\n\t\tthis._nodes = null;\n\t};\n\n\t/**\n\t * clean up\n\t */\n\tTone.Expr.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._disposeNodes();\n\t};\n\n\treturn Tone.Expr;\n});","define([\"Tone/core/Tone\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Subtract\", \"Tone/signal/Signal\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Output 1 if the signal is greater than the value, otherwise outputs 0.\n\t * can compare two signals or a signal and a number. \n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number} [value=0] the value to compare to the incoming signal\n\t * @example\n\t * var gt = new Tone.GreaterThan(2);\n\t * var sig = new Tone.Signal(4).connect(gt);\n\t * //output of gt is equal 1. \n\t */\n\tTone.GreaterThan = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\t\t\n\t\t/**\n\t\t * subtract the amount from the incoming signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[0] = new Tone.Subtract(value);\n\t\tthis.input[1] = this._param.input[1];\n\n\t\t/**\n\t\t * compare that amount to zero\n\t\t * @type {Tone.GreaterThanZero}\n\t\t * @private\n\t\t */\n\t\tthis._gtz = this.output = new Tone.GreaterThanZero();\n\n\t\t//connect\n\t\tthis._param.connect(this._gtz);\n\t};\n\n\tTone.extend(Tone.GreaterThan, Tone.Signal);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThan} this\n\t */\n\tTone.GreaterThan.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\tthis._gtz.dispose();\n\t\tthis._gtz = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThan;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/SignalBase\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Return the absolute value of an incoming signal. \n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var signal = new Tone.Signal(-1);\n\t * var abs = new Tone.Abs();\n\t * signal.connect(abs);\n\t * //the output of abs is 1. \n\t */\n\tTone.Abs = function(){\n\t\t/**\n\t\t * @type {Tone.LessThan}\n\t\t * @private\n\t\t */\n\t\tthis._abs = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val === 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn Math.abs(val);\n\t\t\t}\n\t\t}, 127);\n\t};\n\n\tTone.extend(Tone.Abs, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.Abs} this\n\t */\n\tTone.Abs.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._abs.dispose();\n\t\tthis._abs = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Abs;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Multiply\", \"Tone/signal/Subtract\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Signal-rate modulo operator. Only works in AudioRange [-1, 1] and for modulus\n\t * values in the NormalRange. \n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {NormalRange} modulus The modulus to apply.\n\t * @example\n\t * var mod = new Tone.Modulo(0.2)\n\t * var sig = new Tone.Signal(0.5).connect(mod);\n\t * //mod outputs 0.1\n\t */\n\tTone.Modulo = function(modulus){\n\n\t\tthis.createInsOuts(1, 0);\n\n\t\t/**\n\t\t * A waveshaper gets the integer multiple of \n\t\t * the input signal and the modulus.\n\t\t * @private\n\t\t * @type {Tone.WaveShaper}\n\t\t */\n\t\tthis._shaper = new Tone.WaveShaper(Math.pow(2, 16));\n\n\t\t/**\n\t\t * the integer multiple is multiplied by the modulus\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = new Tone.Multiply();\n\n\t\t/**\n\t\t * and subtracted from the input signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._subtract = this.output = new Tone.Subtract();\n\n\t\t/**\n\t\t * the modulus signal\n\t\t * @type {Tone.Signal}\n\t\t * @private\n\t\t */\n\t\tthis._modSignal = new Tone.Signal(modulus);\n\n\t\t//connections\n\t\tthis.input.fan(this._shaper, this._subtract);\n\t\tthis._modSignal.connect(this._multiply, 0, 0);\n\t\tthis._shaper.connect(this._multiply, 0, 1);\n\t\tthis._multiply.connect(this._subtract, 0, 1);\n\t\tthis._setWaveShaper(modulus);\n\t};\n\n\tTone.extend(Tone.Modulo, Tone.SignalBase);\n\n\t/**\n\t * @param {number} mod the modulus to apply\n\t * @private\n\t */\n\tTone.Modulo.prototype._setWaveShaper = function(mod){\n\t\tthis._shaper.setMap(function(val){\n\t\t\tvar multiple = Math.floor((val + 0.0001) / mod);\n\t\t\treturn multiple;\n\t\t});\n\t};\n\n\t/**\n\t * The modulus value.\n\t * @memberOf Tone.Modulo#\n\t * @type {NormalRange}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Modulo.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._modSignal.value;\n\t\t},\n\t\tset : function(mod){\n\t\t\tthis._modSignal.value = mod;\n\t\t\tthis._setWaveShaper(mod);\n\t\t}\n\t});\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Modulo} this\n\t */\n\tTone.Modulo.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.dispose();\n\t\tthis._shaper = null;\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\tthis._subtract.dispose();\n\t\tthis._subtract = null;\n\t\tthis._modSignal.dispose();\n\t\tthis._modSignal = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Modulo;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Pow applies an exponent to the incoming signal. The incoming signal\n\t * must be AudioRange.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {Positive} exp The exponent to apply to the incoming signal, must be at least 2. \n\t * @example\n\t * var pow = new Tone.Pow(2);\n\t * var sig = new Tone.Signal(0.5).connect(pow);\n\t * //output of pow is 0.25. \n\t */\n\tTone.Pow = function(exp){\n\n\t\t/**\n\t\t * the exponent\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._exp = this.defaultArg(exp, 1);\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);\n\t};\n\n\tTone.extend(Tone.Pow, Tone.SignalBase);\n\n\t/**\n\t * The value of the exponent.\n\t * @memberOf Tone.Pow#\n\t * @type {number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Pow.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._exp;\n\t\t},\n\t\tset : function(exp){\n\t\t\tthis._exp = exp;\n\t\t\tthis._expScaler.setMap(this._expFunc(this._exp));\n\t\t}\n\t});\n\n\n\t/**\n\t * the function which maps the waveshaper\n\t * @param {number} exp\n\t * @return {function}\n\t * @private\n\t */\n\tTone.Pow.prototype._expFunc = function(exp){\n\t\treturn function(val){\n\t\t\treturn Math.pow(Math.abs(val), exp);\n\t\t};\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Pow} this\n\t */\n\tTone.Pow.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._expScaler.dispose();\n\t\tthis._expScaler = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Pow;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class AudioToGain converts an input in AudioRange [-1,1] to NormalRange [0,1]. \n\t * See Tone.GainToAudio.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var a2g = new Tone.AudioToGain();\n\t */\n\tTone.AudioToGain = function(){\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._norm = this.input = this.output = new Tone.WaveShaper(function(x){\n\t\t\treturn (x + 1) / 2;\n\t\t});\n\t};\n\n\tTone.extend(Tone.AudioToGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.AudioToGain} this\n\t */\n\tTone.AudioToGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._norm.dispose();\n\t\tthis._norm = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.AudioToGain;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Convert an incoming signal between 0, 1 to an equal power gain scale.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var eqPowGain = new Tone.EqualPowerGain();\n\t */\n\tTone.EqualPowerGain = function(){\n\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._eqPower = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (Math.abs(val) < 0.001){\n\t\t\t\t//should output 0 when input is 0\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn this.equalPowerScale(val);\n\t\t\t}\n\t\t}.bind(this), 4096);\n\t};\n\n\tTone.extend(Tone.EqualPowerGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.EqualPowerGain} this\n\t */\n\tTone.EqualPowerGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._eqPower.dispose();\n\t\tthis._eqPower = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.EqualPowerGain;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n var EQFilter = require('eqFilter');\r\n\r\n /**\r\n * p5.EQ is an audio effect that performs the function of a multiband\r\n * audio equalizer. Equalization is used to adjust the balance of\r\n * frequency compoenents of an audio signal. This process is commonly used\r\n * in sound production and recording to change the waveform before it reaches\r\n * a sound output device. EQ can also be used as an audio effect to create\r\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\r\n * built using a chain of Web Audio Biquad Filter Nodes and can be\r\n * instantiated with 3 or 8 bands. Bands can be added or removed from\r\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.EQ\r\n * @constructor\r\n * @extends p5.Effect\r\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\r\n * @return {Object} p5.EQ object\r\n *\r\n * @example\r\n *
\r\n * var eq;\r\n * var band_names;\r\n * var band_index;\r\n *\r\n * var soundFile, play;\r\n *\r\n * function preload() {\r\n * soundFormats('mp3', 'ogg');\r\n * soundFile = loadSound('assets/beat');\r\n * }\r\n *\r\n * function setup() {\r\n * eq = new p5.EQ(3);\r\n * soundFile.disconnect();\r\n * eq.process(soundFile);\r\n *\r\n * band_names = ['lows','mids','highs'];\r\n * band_index = 0;\r\n * play = false;\r\n * textAlign(CENTER);\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n * noStroke();\r\n * fill(255);\r\n * text('click to kill',50,25);\r\n *\r\n * fill(255, 40, 255);\r\n * textSize(26);\r\n * text(band_names[band_index],50,55);\r\n *\r\n * fill(255);\r\n * textSize(9);\r\n * text('space = play/pause',50,80);\r\n * }\r\n *\r\n * //If mouse is over canvas, cycle to the next band and kill the frequency\r\n * function mouseClicked() {\r\n * for (var i = 0; i < eq.bands.length; i++) {\r\n * eq.bands[i].gain(0);\r\n * }\r\n * eq.bands[band_index].gain(-40);\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * band_index === 2 ? band_index = 0 : band_index++;\r\n * }\r\n * }\r\n *\r\n * //use space bar to trigger play / pause\r\n * function keyPressed() {\r\n * if (key===' ') {\r\n * play = !play\r\n * play ? soundFile.loop() : soundFile.pause();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.EQ = function(_eqsize) {\r\n Effect.call(this);\r\n\r\n //p5.EQ can be of size (3) or (8), defaults to 3\r\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\r\n\r\n var factor;\r\n _eqsize === 3 ? factor = Math.pow(2,3) : factor = 2;\r\n\r\n /**\r\n * The p5.EQ is built with abstracted p5.Filter objects.\r\n * To modify any bands, use methods of the \r\n * p5.Filter API, especially `gain` and `freq`.\r\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\r\n * @property {Array} bands\r\n *\r\n */\r\n this.bands = [];\r\n\r\n\r\n var freq, res;\r\n for (var i = 0; i < _eqsize; i++) {\r\n if (i === _eqsize - 1) {\r\n freq = 21000;\r\n res = .01;\r\n } else if (i === 0) {\r\n freq = 100;\r\n res = .1;\r\n }\r\n else if (i===1) {\r\n freq = _eqsize === 3 ? 360 * factor : 360;\r\n res = 1;\r\n }else {\r\n freq = this.bands[i-1].freq() * factor;\r\n res = 1;\r\n }\r\n this.bands[i] = this._newBand(freq, res);\r\n\r\n if (i>0) {\r\n this.bands[i-1].connect(this.bands[i].biquad);\r\n } else {\r\n this.input.connect(this.bands[i].biquad);\r\n }\r\n }\r\n this.bands[_eqsize-1].connect(this.output);\r\n };\r\n p5.EQ.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Process an input by connecting it to the EQ\r\n * @method process\r\n * @param {Object} src Audio source\r\n */\r\n p5.EQ.prototype.process = function (src) {\r\n src.connect(this.input);\r\n };\r\n\r\n // /**\r\n // * Set the frequency and gain of each band in the EQ. This method should be\r\n // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\r\n // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\r\n // *\r\n // * @method set\r\n // * @for p5.EQ\r\n // * @param {Number} [freq0] Frequency value for band with index 0\r\n // * @param {Number} [gain0] Gain value for band with index 0\r\n // * @param {Number} [freq1] Frequency value for band with index 1\r\n // * @param {Number} [gain1] Gain value for band with index 1\r\n // * @param {Number} [freq2] Frequency value for band with index 2\r\n // * @param {Number} [gain2] Gain value for band with index 2\r\n // * @param {Number} [freq3] Frequency value for band with index 3\r\n // * @param {Number} [gain3] Gain value for band with index 3\r\n // * @param {Number} [freq4] Frequency value for band with index 4\r\n // * @param {Number} [gain4] Gain value for band with index 4\r\n // * @param {Number} [freq5] Frequency value for band with index 5\r\n // * @param {Number} [gain5] Gain value for band with index 5\r\n // * @param {Number} [freq6] Frequency value for band with index 6\r\n // * @param {Number} [gain6] Gain value for band with index 6\r\n // * @param {Number} [freq7] Frequency value for band with index 7\r\n // * @param {Number} [gain7] Gain value for band with index 7\r\n // */\r\n p5.EQ.prototype.set = function() {\r\n if (arguments.length === this.bands.length * 2) {\r\n for (var i = 0; i < arguments.length; i+=2) {\r\n this.bands[i/2].freq(arguments[i]);\r\n this.bands[i/2].gain(arguments[i+1]);\r\n }\r\n }\r\n else {\r\n console.error('Argument mismatch. .set() should be called with ' + this.bands.length*2 +\r\n ' arguments. (one frequency and gain value pair for each band of the eq)');\r\n }\r\n };\r\n\r\n /**\r\n * Add a new band. Creates a p5.Filter and strips away everything but\r\n * the raw biquad filter. This method returns an abstracted p5.Filter,\r\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\r\n * @private\r\n * @for p5.EQ\r\n * @method _newBand\r\n * @param {Number} freq\r\n * @param {Number} res\r\n * @return {Object} Abstracted Filter\r\n */\r\n p5.EQ.prototype._newBand = function(freq, res) {\r\n return new EQFilter(freq, res);\r\n };\r\n\r\n p5.EQ.prototype.dispose = function () {\r\n Effect.prototype.dispose.apply(this);\r\n\r\n if (this.bands) {\r\n while (this.bands.length > 0) {\r\n delete this.bands.pop().dispose();\r\n }\r\n delete this.bands;\r\n }\r\n };\r\n\r\n return p5.EQ;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var p5sound = require('master');\r\n\r\n /**\r\n * EQFilter extends p5.Filter with constraints\r\n * necessary for the p5.EQ\r\n *\r\n * @private\r\n */\r\n var EQFilter = function(freq, res) {\r\n Filter.call(this, 'peaking');\r\n this.disconnect();\r\n this.set(freq, res);\r\n this.biquad.gain.value = 0;\r\n delete this.input;\r\n delete this.output;\r\n delete this._drywet;\r\n delete this.wet;\r\n\r\n };\r\n EQFilter.prototype = Object.create(Filter.prototype);\r\n\r\n EQFilter.prototype.amp = function() {\r\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\r\n };\r\n EQFilter.prototype.drywet = function() {\r\n console.warn('`drywet()` is not available for p5.EQ bands.');\r\n };\r\n EQFilter.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n if (this.biquad) {\r\n this.biquad.connect(u.input ? u.input : u);\r\n } else {\r\n this.output.connect(u.input ? u.input : u);\r\n }\r\n };\r\n\r\n EQFilter.prototype.disconnect = function() {\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n }\r\n };\r\n EQFilter.prototype.dispose = function() {\r\n // remove reference form soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n this.disconnect();\r\n delete this.biquad;\r\n };\r\n\r\n return EQFilter;\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Panner3D is based on the \r\n * Web Audio Spatial Panner Node.\r\n * This panner is a spatial processing node that allows audio to be positioned\r\n * and oriented in 3D space.\r\n *\r\n * The position is relative to an \r\n * Audio Context Listener, which can be accessed\r\n * by p5.soundOut.audiocontext.listener\r\n *\r\n *\r\n * @class p5.Panner3D\r\n * @constructor\r\n */\r\n\tp5.Panner3D = function() {\r\n Effect.call(this);\r\n\r\n /**\r\n * \r\n * Web Audio Spatial Panner Node\r\n *\r\n * Properties include\r\n * - panningModel: \"equal power\" or \"HRTF\"\r\n * - distanceModel: \"linear\", \"inverse\", or \"exponential\"\r\n *\r\n * @property {AudioNode} panner\r\n *\r\n */\r\n this.panner = this.ac.createPanner();\r\n this.panner.panningModel = 'HRTF';\r\n this.panner.distanceModel = 'linear';\r\n this.panner.connect(this.output);\r\n this.input.connect(this.panner);\r\n\t};\r\n\r\n p5.Panner3D.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Connect an audio sorce\r\n *\r\n * @method process\r\n * @for p5.Panner3D\r\n * @param {Object} src Input source\r\n */\r\n p5.Panner3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method set\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.set = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.panner.positionX.value,\r\n this.panner.positionY.value,\r\n this.panner.positionZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.positionX.value = xVal;\r\n this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.positionX);\r\n }\r\n return this.panner.positionX.value;\r\n };\r\n p5.Panner3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.positionY.value = yVal;\r\n this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.positionY);\r\n }\r\n return this.panner.positionY.value;\r\n };\r\n p5.Panner3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.positionZ.value = zVal;\r\n this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.positionZ);\r\n }\r\n return this.panner.positionZ.value;\r\n };\r\n\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method orient\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.orient = function(xVal, yVal, zVal, time) {\r\n this.orientX(xVal,time);\r\n this.orientY(yVal,time);\r\n this.orientZ(zVal,time);\r\n return [this.panner.orientationX.value,\r\n this.panner.orientationY.value,\r\n this.panner.orientationZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.orientX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.orientationX.value = xVal;\r\n this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.orientationX);\r\n }\r\n return this.panner.orientationX.value;\r\n };\r\n p5.Panner3D.prototype.orientY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.orientationY.value = yVal;\r\n this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.orientationY);\r\n }\r\n return this.panner.orientationY.value;\r\n };\r\n p5.Panner3D.prototype.orientZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.orientationZ.value = zVal;\r\n this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.orientationZ);\r\n }\r\n return this.panner.orientationZ.value;\r\n };\r\n\r\n /**\r\n * Set the rolloff factor and max distance\r\n * @method setFalloff\r\n * @for p5.Panner3D\r\n * @param {Number} [maxDistance]\r\n * @param {Number} [rolloffFactor]\r\n */\r\n p5.Panner3D.prototype.setFalloff = function(maxDistance, rolloffFactor) {\r\n this.maxDist(maxDistance);\r\n this.rolloff(rolloffFactor);\r\n };\r\n /**\r\n * Maxium distance between the source and the listener\r\n * @method maxDist\r\n * @for p5.Panner3D\r\n * @param {Number} maxDistance\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.maxDist = function(maxDistance){\r\n if (typeof maxDistance === 'number') {\r\n this.panner.maxDistance = maxDistance;\r\n }\r\n return this.panner.maxDistance;\r\n };\r\n\r\n /**\r\n * How quickly the volume is reduced as the source moves away from the listener\r\n * @method rollof\r\n * @for p5.Panner3D\r\n * @param {Number} rolloffFactor\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.rolloff = function(rolloffFactor){\r\n if (typeof rolloffFactor === 'number') {\r\n this.panner.rolloffFactor = rolloffFactor;\r\n }\r\n return this.panner.rolloffFactor;\r\n };\r\n\r\n p5.Panner3D.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n delete this.panner;\r\n }\r\n };\r\n\r\n return p5.Panner3D;\r\n\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n// /**\r\n// * listener is a class that can construct both a Spatial Panner\r\n// * and a Spatial Listener. The panner is based on the \r\n// * Web Audio Spatial Panner Node\r\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\r\n// * This panner is a spatial processing node that allows audio to be positioned\r\n// * and oriented in 3D space. \r\n// *\r\n// * The Listener modifies the properties of the Audio Context Listener. \r\n// * Both objects types use the same methods. The default is a spatial panner.\r\n// *\r\n// * p5.Panner3D - Constructs a Spatial Panner \r\n// * p5.Listener3D - Constructs a Spatial Listener \r\n// *\r\n// * @class listener\r\n// * @constructor\r\n// * @return {Object} p5.Listener3D Object\r\n// *\r\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\r\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\r\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\r\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\r\n// */\r\n \r\n\tp5.Listener3D = function(type) {\r\n this.ac = p5sound.audiocontext;\r\n this.listener = this.ac.listener;\r\n\t}; \r\n\r\n// /**\r\n// * Connect an audio sorce\r\n// * @param {Object} src Input source\r\n// */\r\n p5.Listener3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n// /**\r\n// * Set the X,Y,Z position of the Panner\r\n// * @param {[Number]} xVal\r\n// * @param {[Number]} yVal\r\n// * @param {[Number]} zVal\r\n// * @param {[Number]} time\r\n// * @return {[Array]} [Updated x, y, z values as an array]\r\n// */\r\n p5.Listener3D.prototype.position = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.listener.positionX.value, \r\n this.listener.positionY.value,\r\n this.listener.positionZ.value];\r\n };\r\n\r\n// /**\r\n// * Getter and setter methods for position coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.positionX.value = xVal;\r\n this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.positionX);\r\n }\r\n return this.listener.positionX.value;\r\n };\r\n p5.Listener3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.positionY.value = yVal;\r\n this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.positionY);\r\n }\r\n return this.listener.positionY.value;\r\n };\r\n p5.Listener3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.positionZ.value = zVal;\r\n this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.positionZ);\r\n }\r\n return this.listener.positionZ.value;\r\n };\r\n\r\n// cannot define method when class definition is commented\r\n// /**\r\n// * Overrides the listener orient() method because Listener has slightly\r\n// * different params. In human terms, Forward vectors are the direction the \r\n// * nose is pointing. Up vectors are the direction of the top of the head.\r\n// *\r\n// * @method orient\r\n// * @param {Number} xValF Forward vector X direction\r\n// * @param {Number} yValF Forward vector Y direction\r\n// * @param {Number} zValF Forward vector Z direction\r\n// * @param {Number} xValU Up vector X direction\r\n// * @param {Number} yValU Up vector Y direction\r\n// * @param {Number} zValU Up vector Z direction\r\n// * @param {Number} time \r\n// * @return {Array} All orienation params\r\n// */\r\n p5.Listener3D.prototype.orient = function(xValF, yValF, zValF, \r\n xValU, yValU, zValU, time) {\r\n\r\n if (arguments.length === 3 || arguments.length === 4) {\r\n time = arguments[3];\r\n this.orientForward(xValF, yValF, zValF, time);\r\n } else if (arguments.length === 6 || arguments === 7) {\r\n this.orientForward(xValF, yValF, zValF);\r\n this.orientUp(xValU, yValU, zValU, time);\r\n }\r\n \r\n return [this.listener.forwardX.value, \r\n this.listener.forwardY.value,\r\n this.listener.forwardZ.value,\r\n this.listener.upX.value,\r\n this.listener.upY.value,\r\n this.listener.upZ.value];\r\n };\r\n\r\n\r\n p5.Listener3D.prototype.orientForward = function(xValF, yValF, zValF, time) {\r\n this.forwardX(xValF,time);\r\n this.forwardY(yValF,time);\r\n this.forwardZ(zValF,time);\r\n\r\n return [this.listener.forwardX, \r\n this.listener.forwardY,\r\n this.listener.forwardZ];\r\n };\r\n\r\n p5.Listener3D.prototype.orientUp = function(xValU, yValU, zValU, time) {\r\n this.upX(xValU,time);\r\n this.upY(yValU,time);\r\n this.upZ(zValU,time);\r\n\r\n return [this.listener.upX, \r\n this.listener.upY,\r\n this.listener.upZ];\r\n };\r\n// /**\r\n// * Getter and setter methods for orient coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.forwardX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.forwardX.value = xVal;\r\n this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.forwardX);\r\n }\r\n return this.listener.forwardX.value;\r\n };\r\n p5.Listener3D.prototype.forwardY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.forwardY.value = yVal;\r\n this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.forwardY);\r\n }\r\n return this.listener.forwardY.value;\r\n };\r\n p5.Listener3D.prototype.forwardZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.forwardZ.value = zVal;\r\n this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.forwardZ);\r\n }\r\n return this.listener.forwardZ.value;\r\n };\r\n p5.Listener3D.prototype.upX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.upX.value = xVal;\r\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.upX);\r\n }\r\n return this.listener.upX.value;\r\n };\r\n p5.Listener3D.prototype.upY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.upY.value = yVal;\r\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.upY);\r\n }\r\n return this.listener.upY.value;\r\n };\r\n p5.Listener3D.prototype.upZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.upZ.value = zVal;\r\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.upZ);\r\n }\r\n return this.listener.upZ.value;\r\n };\r\n \r\n return p5.Listener3D;\r\n\r\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Delay is an echo effect. It processes an existing sound source,\r\n * and outputs a delayed version of that sound. The p5.Delay can\r\n * produce different effects depending on the delayTime, feedback,\r\n * filter, and type. In the example below, a feedback of 0.5 (the\r\n * defaul value) will produce a looping delay that decreases in\r\n * volume by 50% each repeat. A filter will cut out the high\r\n * frequencies so that the delay does not sound as piercing as the\r\n * original source.\r\n *\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n * @class p5.Delay\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var noise, env, delay;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * noise = new p5.Noise('brown');\r\n * noise.amp(0);\r\n * noise.start();\r\n *\r\n * delay = new p5.Delay();\r\n *\r\n * // delay.process() accepts 4 parameters:\r\n * // source, delayTime, feedback, filter frequency\r\n * // play with these numbers!!\r\n * delay.process(noise, .12, .7, 2300);\r\n *\r\n * // play the noise with an envelope,\r\n * // a series of fades ( time / value pairs )\r\n * env = new p5.Envelope(.01, 0.2, .2, .1);\r\n * }\r\n *\r\n * // mouseClick triggers envelope\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(noise);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Delay = function() {\r\n \tEffect.call(this);\r\n\r\n this._split = this.ac.createChannelSplitter(2);\r\n this._merge = this.ac.createChannelMerger(2);\r\n\r\n this._leftGain = this.ac.createGain();\r\n this._rightGain = this.ac.createGain();\r\n\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} leftDelay\r\n */\r\n this.leftDelay = this.ac.createDelay();\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} rightDelay\r\n */\r\n this.rightDelay = this.ac.createDelay();\r\n\r\n this._leftFilter = new Filter();\r\n this._rightFilter = new Filter();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n\r\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n\r\n // graph routing\r\n this.input.connect(this._split);\r\n this.leftDelay.connect(this._leftGain);\r\n this.rightDelay.connect(this._rightGain);\r\n this._leftGain.connect(this._leftFilter.input);\r\n this._rightGain.connect(this._rightFilter.input);\r\n this._merge.connect(this.wet);\r\n\r\n\r\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n\r\n // default routing\r\n this.setType(0);\r\n\r\n this._maxDelay = this.leftDelay.delayTime.maxValue;\r\n\r\n // set initial feedback to 0.5\r\n this.feedback(0.5);\r\n\r\n\r\n };\r\n\r\n p5.Delay.prototype = Object.create(Effect.prototype);\r\n /**\r\n * Add delay to an audio signal according to a set\r\n * of delay parameters.\r\n *\r\n * @method process\r\n * @for p5.Delay\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\r\n * Some browsers limit delayTime to\r\n * 1 second.\r\n * @param {Number} [feedback] sends the delay back through itself\r\n * in a loop that decreases in volume\r\n * each time.\r\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\r\n * below the lowPass will be part of the\r\n * delay.\r\n */\r\n p5.Delay.prototype.process = function(src, _delayTime, _feedback, _filter) {\r\n var feedback = _feedback || 0;\r\n var delayTime = _delayTime || 0;\r\n if (feedback >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n if (delayTime >= this._maxDelay) {\r\n throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.');\r\n }\r\n\r\n src.connect(this.input);\r\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this._leftGain.gain.value = feedback;\r\n this._rightGain.gain.value = feedback;\r\n\r\n if (_filter) {\r\n this._leftFilter.freq(_filter);\r\n this._rightFilter.freq(_filter);\r\n }\r\n };\r\n\r\n /**\r\n * Set the delay (echo) time, in seconds. Usually this value will be\r\n * a floating point number between 0.0 and 1.0.\r\n *\r\n * @method delayTime\r\n * @for p5.Delay\r\n * @param {Number} delayTime Time (in seconds) of the delay\r\n */\r\n p5.Delay.prototype.delayTime = function(t) {\r\n // if t is an audio node...\r\n if (typeof t !== 'number') {\r\n t.connect(this.leftDelay.delayTime);\r\n t.connect(this.rightDelay.delayTime);\r\n }\r\n\r\n else {\r\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Feedback occurs when Delay sends its signal back through its input\r\n * in a loop. The feedback amount determines how much signal to send each\r\n * time through the loop. A feedback greater than 1.0 is not desirable because\r\n * it will increase the overall output each time through the loop,\r\n * creating an infinite feedback loop. The default value is 0.5\r\n *\r\n * @method feedback\r\n * @for p5.Delay\r\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\r\n * Oscillator that can be used to\r\n * modulate this param\r\n * @returns {Number} Feedback value\r\n *\r\n */\r\n p5.Delay.prototype.feedback = function(f) {\r\n // if f is an audio node...\r\n if (f && typeof f !== 'number') {\r\n f.connect(this._leftGain.gain);\r\n f.connect(this._rightGain.gain);\r\n }\r\n else if (f >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n else if (typeof f === 'number') {\r\n this._leftGain.gain.value = f;\r\n this._rightGain.gain.value = f;\r\n }\r\n\r\n // return value of feedback\r\n return this._leftGain.gain.value;\r\n };\r\n\r\n /**\r\n * Set a lowpass filter frequency for the delay. A lowpass filter\r\n * will cut off any frequencies higher than the filter frequency.\r\n *\r\n * @method filter\r\n * @for p5.Delay\r\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\r\n * frequencies higher than the filter frequency.\r\n * @param {Number|Object} res Resonance of the filter frequency\r\n * cutoff, or an object (i.e. a p5.Oscillator)\r\n * that can be used to modulate this parameter.\r\n * High numbers (i.e. 15) will produce a resonance,\r\n * low numbers (i.e. .2) will produce a slope.\r\n */\r\n p5.Delay.prototype.filter = function(freq, q) {\r\n this._leftFilter.set(freq, q);\r\n this._rightFilter.set(freq, q);\r\n };\r\n\r\n\r\n /**\r\n * Choose a preset type of delay. 'pingPong' bounces the signal\r\n * from the left to the right channel to produce a stereo effect.\r\n * Any other parameter will revert to the default delay setting.\r\n *\r\n * @method setType\r\n * @for p5.Delay\r\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\r\n */\r\n p5.Delay.prototype.setType = function(t) {\r\n if (t === 1) {\r\n t = 'pingPong';\r\n }\r\n this._split.disconnect();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n this._split.connect(this.leftDelay, 0);\r\n this._split.connect(this.rightDelay, 1);\r\n switch(t) {\r\n case 'pingPong':\r\n this._rightFilter.setType( this._leftFilter.biquad.type );\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.rightDelay);\r\n this._rightFilter.output.connect(this.leftDelay);\r\n break;\r\n default:\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.leftDelay);\r\n this._rightFilter.output.connect(this.rightDelay);\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the delay effect.\r\n *\r\n * @method amp\r\n * @for p5.Delay\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Delay\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Delay\r\n */\r\n\r\n p5.Delay.prototype.dispose = function() {\r\n\r\n Effect.prototype.dispose.apply(this);\r\n\r\n this._split.disconnect();\r\n this._leftFilter.dispose();\r\n this._rightFilter.dispose();\r\n this._merge.disconnect();\r\n this._leftGain.disconnect();\r\n this._rightGain.disconnect();\r\n this.leftDelay.disconnect();\r\n this.rightDelay.disconnect();\r\n\r\n this._split = undefined;\r\n this._leftFilter = undefined;\r\n this._rightFilter = undefined;\r\n this._merge = undefined;\r\n this._leftGain = undefined;\r\n this._rightGain = undefined;\r\n this.leftDelay = undefined;\r\n this.rightDelay = undefined;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var CustomError = require('errorHandler');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Reverb adds depth to a sound through a large number of decaying\r\n * echoes. It creates the perception that sound is occurring in a\r\n * physical space. The p5.Reverb has paramters for Time (how long does the\r\n * reverb last) and decayRate (how much the sound decays with each echo)\r\n * that can be set with the .set() or .process() methods. The p5.Convolver\r\n * extends p5.Reverb allowing you to recreate the sound of actual physical\r\n * spaces through convolution.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Reverb\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var soundFile, reverb;\r\n * function preload() {\r\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * reverb = new p5.Reverb();\r\n * soundFile.disconnect(); // so we'll only hear reverb...\r\n *\r\n * // connect soundFile to reverb, process w/\r\n * // 3 second reverbTime, decayRate of 2%\r\n * reverb.process(soundFile, 3, 2);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n\r\n\r\n p5.Reverb = function() {\r\n Effect.call(this);\r\n\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n // default params\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n\r\n };\r\n\r\n p5.Reverb.prototype = Object.create(Effect.prototype);\r\n\r\n p5.Reverb.prototype._initConvolverNode = function() {\r\n this.convolverNode = this.ac.createConvolver();\r\n this.input.connect(this.convolverNode);\r\n this.convolverNode.connect(this.wet);\r\n };\r\n\r\n p5.Reverb.prototype._teardownConvolverNode = function() {\r\n if (this.convolverNode) {\r\n this.convolverNode.disconnect();\r\n delete this.convolverNode;\r\n }\r\n };\r\n\r\n p5.Reverb.prototype._setBuffer = function(audioBuffer) {\r\n this._teardownConvolverNode();\r\n this._initConvolverNode();\r\n this.convolverNode.buffer = audioBuffer;\r\n };\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Reverb\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.process = function(src, seconds, decayRate, reverse) {\r\n src.connect(this.input);\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n /**\r\n * Set the reverb settings. Similar to .process(), but without\r\n * assigning a new input.\r\n *\r\n * @method set\r\n * @for p5.Reverb\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.set = function(seconds, decayRate, reverse) {\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the reverb effect.\r\n *\r\n * @method amp\r\n * @for p5.Reverb\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Reverb\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Reverb\r\n */\r\n\r\n /**\r\n * Inspired by Simple Reverb by Jordan Santell\r\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\r\n *\r\n * Utility function for building an impulse response\r\n * based on the module parameters.\r\n *\r\n * @private\r\n */\r\n p5.Reverb.prototype._buildImpulse = function() {\r\n var rate = this.ac.sampleRate;\r\n var length = rate*this._seconds;\r\n var decay = this._decay;\r\n var impulse = this.ac.createBuffer(2, length, rate);\r\n var impulseL = impulse.getChannelData(0);\r\n var impulseR = impulse.getChannelData(1);\r\n var n, i;\r\n for (i = 0; i < length; i++) {\r\n n = this._reverse ? length - i : i;\r\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n }\r\n this._setBuffer(impulse);\r\n };\r\n\r\n p5.Reverb.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n this._teardownConvolverNode();\r\n };\r\n\r\n // =======================================================================\r\n // *** p5.Convolver ***\r\n // =======================================================================\r\n\r\n /**\r\n *
p5.Convolver extends p5.Reverb. It can emulate the sound of real\r\n * physical spaces through a process called \r\n * convolution.
\r\n *\r\n *
Convolution multiplies any audio input by an \"impulse response\"\r\n * to simulate the dispersion of sound over time. The impulse response is\r\n * generated from an audio file that you provide. One way to\r\n * generate an impulse response is to pop a balloon in a reverberant space\r\n * and record the echo. Convolution can also be used to experiment with\r\n * sound.
\r\n *\r\n *
Use the method createConvolution(path) to instantiate a\r\n * p5.Convolver with a path to your impulse response audio file.
\r\n *\r\n * @class p5.Convolver\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call when loading succeeds\r\n * @param {Function} [errorCallback] function to call if loading fails.\r\n * This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver = function(path, callback, errorCallback) {\r\n \t p5.Reverb.call(this);\r\n\r\n /**\r\n * Internally, the p5.Convolver uses the a\r\n * \r\n * Web Audio Convolver Node.\r\n *\r\n * @property {ConvolverNode} convolverNode\r\n */\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n if (path) {\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n }\r\n else {\r\n // parameters\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n }\r\n\r\n };\r\n\r\n p5.Convolver.prototype = Object.create(p5.Reverb.prototype);\r\n\r\n p5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\r\n\r\n /**\r\n * Create a p5.Convolver. Accepts a path to a soundfile\r\n * that will be used to generate an impulse response.\r\n *\r\n * @method createConvolver\r\n * @for p5\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call if loading is successful.\r\n * The object will be passed in as the argument\r\n * to the callback function.\r\n * @param {Function} [errorCallback] function to call if loading is not successful.\r\n * A custom error will be passed in as the argument\r\n * to the callback function.\r\n * @return {p5.Convolver}\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.createConvolver = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n var self = this;\r\n var cReverb = new p5.Convolver(path, function(buffer) {\r\n if (typeof callback === 'function') {\r\n callback(buffer);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, errorCallback);\r\n cReverb.impulses = [];\r\n return cReverb;\r\n };\r\n\r\n /**\r\n * Private method to load a buffer as an Impulse Response,\r\n * assign it to the convolverNode, and add to the Array of .impulses.\r\n *\r\n * @param {String} path\r\n * @param {Function} callback\r\n * @param {Function} errorCallback\r\n * @private\r\n */\r\n p5.Convolver.prototype._loadBuffer = function(path, callback, errorCallback) {\r\n var path = p5.prototype._checkFileFormats(path);\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n var ac = p5.prototype.getAudioContext();\r\n\r\n var request = new XMLHttpRequest();\r\n request.open('GET', path, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on success loading file:\r\n ac.decodeAudioData(request.response,\r\n function(buff) {\r\n var buffer = {};\r\n var chunks = path.split('/');\r\n buffer.name = chunks[chunks.length - 1];\r\n buffer.audioBuffer = buff;\r\n self.impulses.push(buffer);\r\n self._setBuffer(buffer.audioBuffer);\r\n if (callback) {\r\n callback(buffer);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url +\r\n '. The request status was: ' + request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n request.send();\r\n };\r\n\r\n p5.Convolver.prototype.set = null;\r\n\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Convolver\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * cVerb = createConvolver('assets/concrete-tunnel.mp3');\r\n *\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with (i.e. connect to) cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver.prototype.process = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * If you load multiple impulse files using the .addImpulse method,\r\n * they will be stored as Objects in this Array. Toggle between them\r\n * with the toggleImpulse(id) method.\r\n *\r\n * @property {Array} impulses\r\n * @for p5.Convolver\r\n */\r\n p5.Convolver.prototype.impulses = [];\r\n\r\n /**\r\n * Load and assign a new Impulse Response to the p5.Convolver.\r\n * The impulse is added to the .impulses array. Previous\r\n * impulses can be accessed with the .toggleImpulse(id)\r\n * method.\r\n *\r\n * @method addImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.addImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * Similar to .addImpulse, except that the .impulses\r\n * Array is reset to save memory. A new .impulses\r\n * array is created with this impulse as the only item.\r\n *\r\n * @method resetImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.resetImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * If you have used .addImpulse() to add multiple impulses\r\n * to a p5.Convolver, then you can use this method to toggle between\r\n * the items in the .impulses Array. Accepts a parameter\r\n * to identify which impulse you wish to use, identified either by its\r\n * original filename (String) or by its position in the .impulses\r\n * Array (Number). \r\n * You can access the objects in the .impulses Array directly. Each\r\n * Object has two attributes: an .audioBuffer (type:\r\n * Web Audio \r\n * AudioBuffer) and a .name, a String that corresponds\r\n * with the original filename.\r\n *\r\n * @method toggleImpulse\r\n * @for p5.Convolver\r\n * @param {String|Number} id Identify the impulse by its original filename\r\n * (String), or by its position in the\r\n * .impulses Array (Number).\r\n */\r\n p5.Convolver.prototype.toggleImpulse = function(id) {\r\n if (typeof id === 'number' && id < this.impulses.length) {\r\n this._setBuffer(this.impulses[id].audioBuffer);\r\n }\r\n if (typeof id === 'string') {\r\n for (var i = 0; i < this.impulses.length; i++) {\r\n if (this.impulses[i].name === id) {\r\n this._setBuffer(this.impulses[i].audioBuffer);\r\n break;\r\n }\r\n }\r\n }\r\n };\r\n\r\n p5.Convolver.prototype.dispose = function() {\r\n p5.Reverb.prototype.dispose.apply(this);\r\n\r\n // remove all the Impulse Response buffers\r\n for (var i in this.impulses) {\r\n if (this.impulses[i]) {\r\n this.impulses[i] = null;\r\n }\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n // requires the Tone.js library's Clock (MIT license, Yotam Mann)\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Clock = require('Tone/core/Clock');\r\n\r\n p5.Metro = function() {\r\n this.clock = new Clock({\r\n 'callback': this.ontick.bind(this)\r\n });\r\n this.syncedParts = [];\r\n this.bpm = 120; // gets overridden by p5.Part\r\n this._init();\r\n\r\n this.prevTick = 0;\r\n this.tatumTime = 0;\r\n\r\n this.tickCallback = function() {};\r\n };\r\n\r\n p5.Metro.prototype.ontick = function(tickTime) {\r\n var elapsedTime = tickTime - this.prevTick;\r\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\r\n if (elapsedTime - this.tatumTime <= -0.02) {\r\n return;\r\n } else {\r\n // console.log('ok', this.syncedParts[0].phrases[0].name);\r\n this.prevTick = tickTime;\r\n\r\n // for all of the active things on the metro:\r\n var self = this;\r\n this.syncedParts.forEach(function(thisPart) {\r\n if (!thisPart.isPlaying) return;\r\n thisPart.incrementStep(secondsFromNow);\r\n // each synced source keeps track of its own beat number\r\n thisPart.phrases.forEach(function(thisPhrase) {\r\n var phraseArray = thisPhrase.sequence;\r\n var bNum = self.metroTicks % phraseArray.length;\r\n if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping) ) {\r\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\r\n }\r\n });\r\n });\r\n this.metroTicks += 1;\r\n this.tickCallback(secondsFromNow);\r\n }\r\n };\r\n\r\n p5.Metro.prototype.setBPM = function(bpm, rampTime) {\r\n var beatTime = 60 / (bpm*this.tatums);\r\n var now = p5sound.audiocontext.currentTime;\r\n this.tatumTime = beatTime;\r\n\r\n var rampTime = rampTime || 0;\r\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\r\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\r\n this.bpm = bpm;\r\n };\r\n\r\n p5.Metro.prototype.getBPM = function() {\r\n return this.clock.getRate() / this.tatums * 60;\r\n };\r\n\r\n p5.Metro.prototype._init = function() {\r\n this.metroTicks = 0;\r\n // this.setBPM(120);\r\n };\r\n\r\n // clear existing synced parts, add only this one\r\n p5.Metro.prototype.resetSync = function(part) {\r\n this.syncedParts = [part];\r\n };\r\n\r\n // push a new synced part to the array\r\n p5.Metro.prototype.pushSync = function(part) {\r\n this.syncedParts.push(part);\r\n };\r\n\r\n p5.Metro.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.start(now + t);\r\n this.setBPM(this.bpm);\r\n };\r\n\r\n p5.Metro.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.stop(now + t);\r\n };\r\n\r\n p5.Metro.prototype.beatLength = function(tatums) {\r\n this.tatums = 1/tatums / 4; // lowest possible division of a beat\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Timeline\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline State. Provides the methods: setStateAtTime(\"state\", time)\n\t * and getValueAtTime(time).\n\t *\n\t * @extends {Tone.Timeline}\n\t * @param {String} initial The initial state of the TimelineState. \n\t * Defaults to undefined\n\t */\n\tTone.TimelineState = function(initial){\n\n\t\tTone.Timeline.call(this);\n\n\t\t/**\n\t\t * The initial state\n\t\t * @private\n\t\t * @type {String}\n\t\t */\n\t\tthis._initial = initial;\n\t};\n\n\tTone.extend(Tone.TimelineState, Tone.Timeline);\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {Number} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t */\n\tTone.TimelineState.prototype.getValueAtTime = function(time){\n\t\tvar event = this.get(time);\n\t\tif (event !== null){\n\t\t\treturn event.state;\n\t\t} else {\n\t\t\treturn this._initial;\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {String} state The name of the state to set.\n\t * @param {Number} time The time to query.\n\t */\n\tTone.TimelineState.prototype.setStateAtTime = function(state, time){\n\t\tthis.add({\n\t\t\t\"state\" : state,\n\t\t\t\"time\" : time\n\t\t});\n\t};\n\n\treturn Tone.TimelineState;\n});","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n var BPM = 120;\r\n\r\n /**\r\n * Set the global tempo, in beats per minute, for all\r\n * p5.Parts. This method will impact all active p5.Parts.\r\n *\r\n * @method setBPM\r\n * @for p5\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.prototype.setBPM = function(bpm, rampTime) {\r\n BPM = bpm;\r\n for (var i in p5sound.parts) {\r\n if (p5sound.parts[i]) {\r\n p5sound.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n *
A phrase is a pattern of musical events over time, i.e.\r\n * a series of notes and rests.
\r\n *\r\n *
Phrases must be added to a p5.Part for playback, and\r\n * each part can play multiple phrases at the same time.\r\n * For example, one Phrase might be a kick drum, another\r\n * could be a snare, and another could be the bassline.
\r\n *\r\n *
The first parameter is a name so that the phrase can be\r\n * modified or deleted later. The callback is a a function that\r\n * this phrase will call at every step—for example it might be\r\n * called playNote(value){}. The array determines\r\n * which value is passed into the callback at each step of the\r\n * phrase. It can be numbers, an object with multiple numbers,\r\n * or a zero (0) indicates a rest so the callback won't be called).
\r\n *\r\n * @class p5.Phrase\r\n * @constructor\r\n * @param {String} name Name so that you can access the Phrase.\r\n * @param {Function} callback The name of a function that this phrase\r\n * will call. Typically it will play a sound,\r\n * and accept two parameters: a time at which\r\n * to play the sound (in seconds from now),\r\n * and a value from the sequence array. The\r\n * time should be passed into the play() or\r\n * start() method to ensure precision.\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n * @example\r\n *
\r\n */\r\n p5.Phrase = function(name, callback, sequence) {\r\n this.phraseStep = 0;\r\n this.name = name;\r\n this.callback = callback;\r\n /**\r\n * Array of values to pass into the callback\r\n * at each step of the phrase. Depending on the callback\r\n * function's requirements, these values may be numbers,\r\n * strings, or an object with multiple parameters.\r\n * Zero (0) indicates a rest.\r\n *\r\n * @property {Array} sequence\r\n */\r\n this.sequence = sequence;\r\n };\r\n\r\n /**\r\n *
A p5.Part plays back one or more p5.Phrases. Instantiate a part\r\n * with steps and tatums. By default, each step represents a 1/16th note.
\r\n *\r\n *
See p5.Phrase for more about musical timing.
\r\n *\r\n * @class p5.Part\r\n * @constructor\r\n * @param {Number} [steps] Steps in the part\r\n * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note)\r\n * @example\r\n *
\r\n * var box, drum, myPart;\r\n * var boxPat = [1,0,0,2,0,2,0,0];\r\n * var drumPat = [0,1,1,0,2,0,1,0];\r\n * var msg = 'click to play';\r\n *\r\n * function preload() {\r\n * box = loadSound('assets/beatbox.mp3');\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * masterVolume(0.1);\r\n *\r\n * var boxPhrase = new p5.Phrase('box', playBox, boxPat);\r\n * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\r\n * myPart = new p5.Part();\r\n * myPart.addPhrase(boxPhrase);\r\n * myPart.addPhrase(drumPhrase);\r\n * myPart.setBPM(60);\r\n * masterVolume(0.1);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * text(msg, width/2, height/2);\r\n * }\r\n *\r\n * function playBox(time, playbackRate) {\r\n * box.rate(playbackRate);\r\n * box.play(time);\r\n * }\r\n *\r\n * function playDrum(time, playbackRate) {\r\n * drum.rate(playbackRate);\r\n * drum.play(time);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * myPart.start();\r\n * msg = 'playing part';\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Part = function(steps, bLength) {\r\n this.length = steps || 0; // how many beats\r\n this.partStep = 0;\r\n this.phrases = [];\r\n this.isPlaying = false;\r\n this.noLoop();\r\n this.tatums = bLength || 0.0625; // defaults to quarter note\r\n\r\n this.metro = new p5.Metro();\r\n this.metro._init();\r\n this.metro.beatLength(this.tatums);\r\n this.metro.setBPM(BPM);\r\n p5sound.parts.push(this);\r\n this.callback = function() {};\r\n };\r\n\r\n /**\r\n * Set the tempo of this part, in Beats Per Minute.\r\n *\r\n * @method setBPM\r\n * @for p5.Part\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} [rampTime] Seconds from now\r\n */\r\n p5.Part.prototype.setBPM = function(tempo, rampTime) {\r\n this.metro.setBPM(tempo, rampTime);\r\n };\r\n\r\n /**\r\n * Returns the tempo, in Beats Per Minute, of this part.\r\n *\r\n * @method getBPM\r\n * @for p5.Part\r\n * @return {Number}\r\n */\r\n p5.Part.prototype.getBPM = function() {\r\n return this.metro.getBPM();\r\n };\r\n\r\n /**\r\n * Start playback of this part. It will play\r\n * through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method start\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.start = function(time) {\r\n if (!this.isPlaying) {\r\n this.isPlaying = true;\r\n this.metro.resetSync(this);\r\n var t = time || 0;\r\n this.metro.start(t);\r\n }\r\n };\r\n\r\n /**\r\n * Loop playback of this part. It will begin\r\n * looping through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method loop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.loop = function(time) {\r\n this.looping = true;\r\n // rest onended function\r\n this.onended = function() {\r\n this.partStep = 0;\r\n };\r\n var t = time || 0;\r\n this.start(t);\r\n };\r\n\r\n /**\r\n * Tell the part to stop looping.\r\n *\r\n * @method noLoop\r\n * @for p5.Part\r\n */\r\n p5.Part.prototype.noLoop = function() {\r\n this.looping = false;\r\n // rest onended function\r\n this.onended = function() {\r\n this.stop();\r\n };\r\n };\r\n\r\n /**\r\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\r\n *\r\n * @method stop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.stop = function(time) {\r\n this.partStep = 0;\r\n this.pause(time);\r\n };\r\n\r\n /**\r\n * Pause the part. Playback will resume\r\n * from the current step.\r\n *\r\n * @method pause\r\n * @for p5.Part\r\n * @param {Number} time seconds from now\r\n */\r\n p5.Part.prototype.pause = function(time) {\r\n this.isPlaying = false;\r\n var t = time || 0;\r\n this.metro.stop(t);\r\n };\r\n\r\n /**\r\n * Add a p5.Phrase to this Part.\r\n *\r\n * @method addPhrase\r\n * @for p5.Part\r\n * @param {p5.Phrase} phrase reference to a p5.Phrase\r\n */\r\n p5.Part.prototype.addPhrase = function(name, callback, array) {\r\n var p;\r\n if (arguments.length === 3) {\r\n p = new p5.Phrase(name, callback, array);\r\n } else if (arguments[0] instanceof p5.Phrase) {\r\n p = arguments[0];\r\n } else {\r\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\r\n }\r\n this.phrases.push(p);\r\n // reset the length if phrase is longer than part's existing length\r\n if (p.sequence.length > this.length) {\r\n this.length = p.sequence.length;\r\n }\r\n };\r\n\r\n /**\r\n * Remove a phrase from this part, based on the name it was\r\n * given when it was created.\r\n *\r\n * @method removePhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.removePhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases.splice(i, 1);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Get a phrase from this part, based on the name it was\r\n * given when it was created. Now you can modify its array.\r\n *\r\n * @method getPhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.getPhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n return this.phrases[i];\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Find all sequences with the specified name, and replace their patterns with the specified array.\r\n *\r\n * @method replaceSequence\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n */\r\n p5.Part.prototype.replaceSequence = function(name, array) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases[i].sequence = array;\r\n }\r\n }\r\n };\r\n\r\n p5.Part.prototype.incrementStep = function(time) {\r\n if (this.partStep < this.length - 1) {\r\n this.callback(time);\r\n this.partStep += 1;\r\n } else {\r\n if (!this.looping && this.partStep === this.length - 1) {\r\n console.log('done');\r\n // this.callback(time);\r\n this.onended();\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the function that will be called at every step. This will clear the previous function.\r\n *\r\n * @method onStep\r\n * @for p5.Part\r\n * @param {Function} callback The name of the callback\r\n * you want to fire\r\n * on every beat/tatum.\r\n */\r\n p5.Part.prototype.onStep = function(callback) {\r\n this.callback = callback;\r\n };\r\n\r\n\r\n // ===============\r\n // p5.Score\r\n // ===============\r\n\r\n /**\r\n * A Score consists of a series of Parts. The parts will\r\n * be played back in order. For example, you could have an\r\n * A part, a B part, and a C part, and play them back in this order\r\n * new p5.Score(a, a, b, a, c)\r\n *\r\n * @class p5.Score\r\n * @constructor\r\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\r\n */\r\n p5.Score = function() {\r\n // for all of the arguments\r\n this.parts = [];\r\n this.currentPart = 0;\r\n\r\n var thisScore = this;\r\n for (var i in arguments) {\r\n if (arguments[i] && this.parts[i]) {\r\n this.parts[i] = arguments[i];\r\n this.parts[i].nextPart = this.parts[i + 1];\r\n this.parts[i].onended = function() {\r\n thisScore.resetPart(i);\r\n playNextPart(thisScore);\r\n };\r\n }\r\n }\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.onended = function() {\r\n if (this.looping) {\r\n // this.resetParts();\r\n this.parts[0].start();\r\n } else {\r\n this.parts[this.parts.length - 1].onended = function() {\r\n this.stop();\r\n this.resetParts();\r\n };\r\n }\r\n this.currentPart = 0;\r\n };\r\n\r\n /**\r\n * Start playback of the score.\r\n *\r\n * @method start\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.start = function() {\r\n this.parts[this.currentPart].start();\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Stop playback of the score.\r\n *\r\n * @method stop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.stop = function() {\r\n this.parts[this.currentPart].stop();\r\n this.currentPart = 0;\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Pause playback of the score.\r\n *\r\n * @method pause\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.pause = function() {\r\n this.parts[this.currentPart].stop();\r\n };\r\n\r\n /**\r\n * Loop playback of the score.\r\n *\r\n * @method loop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.loop = function() {\r\n this.looping = true;\r\n this.start();\r\n };\r\n\r\n /**\r\n * Stop looping playback of the score. If it\r\n * is currently playing, this will go into effect\r\n * after the current round of playback completes.\r\n *\r\n * @method noLoop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.noLoop = function() {\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.resetParts = function() {\r\n var self = this;\r\n this.parts.forEach(function(part) {\r\n self.resetParts[part];\r\n });\r\n };\r\n\r\n p5.Score.prototype.resetPart = function(i) {\r\n this.parts[i].stop();\r\n this.parts[i].partStep = 0;\r\n for (var p in this.parts[i].phrases) {\r\n if (this.parts[i]) {\r\n this.parts[i].phrases[p].phraseStep = 0;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the tempo for all parts in the score\r\n *\r\n * @method setBPM\r\n * @for p5.Score\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.Score.prototype.setBPM = function(bpm, rampTime) {\r\n for (var i in this.parts) {\r\n if (this.parts[i]) {\r\n this.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n function playNextPart(aScore) {\r\n aScore.currentPart++;\r\n if (aScore.currentPart >= aScore.parts.length) {\r\n aScore.scoreStep = 0;\r\n aScore.onended();\r\n } else {\r\n aScore.scoreStep = 0;\r\n aScore.parts[aScore.currentPart - 1].stop();\r\n aScore.parts[aScore.currentPart].start();\r\n }\r\n }\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Clock = require('Tone/core/Clock');\r\n\r\n /**\r\n * SoundLoop\r\n *\r\n * @class p5.SoundLoop\r\n * @constructor\r\n *\r\n * @param {Function} callback this function will be called on each iteration of theloop\r\n * @param {Number|String} [interval] amount of time or beats for each iteration of the loop\r\n * defaults to 1\r\n *\r\n * @example\r\n *
\r\n * var click;\r\n * var looper1;\r\n *\r\n * function preload() {\r\n * click = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * //the looper's callback is passed the timeFromNow\r\n * //this value should be used as a reference point from\r\n * //which to schedule sounds\r\n * looper1 = new p5.SoundLoop(function(timeFromNow){\r\n * click.play(timeFromNow);\r\n * background(255 * (looper1.iterations % 2));\r\n * }, 2);\r\n *\r\n * //stop after 10 iteratios;\r\n * looper1.maxIterations = 10;\r\n * //start the loop\r\n * looper1.start();\r\n * }\r\n *
\r\n */\r\n p5.SoundLoop = function(callback, interval) {\r\n this.callback = callback;\r\n /**\r\n * musicalTimeMode uses Tone.Time convention\r\n\t * true if string, false if number\r\n * @property {Boolean} musicalTimeMode\r\n */\r\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\r\n\r\n this._interval = interval || 1;\r\n\r\n /**\r\n * musicalTimeMode variables\r\n * modify these only when the interval is specified in musicalTime format as a string\r\n */\r\n this._timeSignature = 4;\r\n this._bpm = 60;\r\n\r\n this.isPlaying = false;\r\n\r\n /**\r\n * Set a limit to the number of loops to play. defaults to Infinity\r\n * @property {Number} maxIterations\r\n */\r\n this.maxIterations = Infinity;\r\n var self = this;\r\n\r\n this.clock = new Clock({\r\n 'callback' : function(time) {\r\n var timeFromNow = time - p5sound.audiocontext.currentTime;\r\n /**\r\n * Do not initiate the callback if timeFromNow is < 0\r\n * This ususually occurs for a few milliseconds when the page\r\n * is not fully loaded\r\n *\r\n * The callback should only be called until maxIterations is reached\r\n */\r\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\r\n self.callback(timeFromNow);}\r\n },\r\n 'frequency' : this._calcFreq()\r\n });\r\n };\r\n\r\n /**\r\n * Start the loop\r\n * @method start\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a starting time\r\n */\r\n p5.SoundLoop.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (!this.isPlaying) {\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop the loop\r\n * @method stop\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a stopping time\r\n */\r\n p5.SoundLoop.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.stop(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n /**\r\n * Pause the loop\r\n * @method pause\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a pausing time\r\n */\r\n p5.SoundLoop.prototype.pause = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.pause(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Synchronize loops. Use this method to start two more more loops in synchronization\r\n * or to start a loop in synchronization with a loop that is already playing\r\n * This method will schedule the implicit loop in sync with the explicit master loop\r\n * i.e. loopToStart.syncedStart(loopToSyncWith)\r\n *\r\n * @method syncedStart\r\n * @for p5.SoundLoop\r\n * @param {Object} otherLoop a p5.SoundLoop to sync with\r\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\r\n */\r\n p5.SoundLoop.prototype.syncedStart = function(otherLoop, timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n if (!otherLoop.isPlaying) {\r\n otherLoop.clock.start(now + t);\r\n otherLoop.isPlaying = true;\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n } else if (otherLoop.isPlaying) {\r\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\r\n this.clock.start(now + time);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Updates frequency value, reflected in next callback\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _update\r\n */\r\n p5.SoundLoop.prototype._update = function() {\r\n this.clock.frequency.value = this._calcFreq();\r\n };\r\n\r\n /**\r\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _calcFreq\r\n * @return {Number} new clock frequency value\r\n */\r\n p5.SoundLoop.prototype._calcFreq = function() {\r\n //Seconds mode, bpm / timesignature has no effect\r\n if (typeof this._interval === 'number') {\r\n this.musicalTimeMode = false;\r\n return 1 / this._interval;\r\n }\r\n //Musical timing mode, calculate interval based bpm, interval,and time signature\r\n else if (typeof this._interval === 'string') {\r\n this.musicalTimeMode = true;\r\n return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4);\r\n }\r\n };\r\n\r\n /**\r\n * Convert notation from musical time format to seconds\r\n * Uses Tone.Time convention\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _convertNotation\r\n * @param {String} value value to be converted\r\n * @return {Number} converted value in seconds\r\n */\r\n p5.SoundLoop.prototype._convertNotation = function(value) {\r\n var type = value.slice(-1);\r\n value = Number(value.slice(0,-1));\r\n switch (type) {\r\n case 'm':\r\n return this._measure(value);\r\n case 'n':\r\n return this._note(value);\r\n default:\r\n console.warn('Specified interval is not formatted correctly. See Tone.js '+\r\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time');\r\n }\r\n };\r\n\r\n /**\r\n * Helper conversion methods of measure and note\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _measure\r\n */\r\n p5.SoundLoop.prototype._measure = function(value) {\r\n return value * this._timeSignature;\r\n };\r\n\r\n /**\r\n * @private\r\n * @method _note\r\n * @for p5.SoundLoop\r\n */\r\n p5.SoundLoop.prototype._note = function(value) {\r\n return this._timeSignature / value ;\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters, setting any paramter will result in a change in the clock's\r\n * frequency, that will be reflected after the next callback\r\n * beats per minute (defaults to 60)\r\n * @property {Number} bpm\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'bpm', {\r\n get : function() {\r\n return this._bpm;\r\n },\r\n set : function(bpm) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the BPM in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._bpm = bpm;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * number of quarter notes in a measure (defaults to 4)\r\n * @property {Number} timeSignature\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {\r\n get : function() {\r\n return this._timeSignature;\r\n },\r\n set : function(timeSig) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the timeSignature in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._timeSignature = timeSig;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * length of the loops interval\r\n * @property {Number|String} interval\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'interval', {\r\n get : function() {\r\n return this._interval;\r\n },\r\n set : function(interval) {\r\n this.musicalTimeMode = typeof interval === 'Number'? false : true;\r\n this._interval = interval;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * how many times the callback has been called so far\r\n * @property {Number} iterations\r\n * @for p5.SoundLoop\r\n * @readonly\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'iterations', {\r\n get : function() {\r\n return this.clock.ticks;\r\n }\r\n });\r\n\r\n return p5.SoundLoop;\r\n});\r\n","define(function (require) {\r\n\t'use strict';\r\n\r\n\tvar p5sound = require('master');\r\n\tvar Effect = require('effect');\r\n var CustomError = require('errorHandler');\r\n\r\n /**\r\n * Compressor is an audio effect class that performs dynamics compression\r\n * on an audio input source. This is a very commonly used technique in music\r\n * and sound production. Compression creates an overall louder, richer,\r\n * and fuller sound by lowering the volume of louds and raising that of softs.\r\n * Compression can be used to avoid clipping (sound distortion due to\r\n * peaks in volume) and is especially useful when many sounds are played\r\n * at once. Compression can be used on indivudal sound sources in addition\r\n * to the master output.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Compressor\r\n * @constructor\r\n * @extends p5.Effect\r\n *\r\n *\r\n */\r\n\tp5.Compressor = function() {\r\n\t\tEffect.call(this);\r\n\r\n /**\r\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\r\n * \r\n * @property {AudioNode} compressor\r\n */\r\n\r\n\r\n\t\tthis.compressor = this.ac.createDynamicsCompressor();\r\n\r\n this.input.connect(this.compressor);\r\n this.compressor.connect(this.wet);\r\n\t};\r\n\r\n\tp5.Compressor.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Performs the same function as .connect, but also accepts\r\n * optional parameters to set compressor's audioParams\r\n * @method process\r\n * @for p5.Compressor\r\n *\r\n * @param {Object} src Sound source to be connected\r\n *\r\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n\tp5.Compressor.prototype.process = function(src, attack, knee,\r\n ratio, threshold, release) {\r\n\t\tsrc.connect(this.input);\r\n\t\tthis.set(attack, knee, ratio, threshold, release);\r\n\t};\r\n\r\n /**\r\n * Set the paramters of a compressor.\r\n * @method set\r\n * @for p5.Compressor\r\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} knee A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n p5.Compressor.prototype.set = function (attack, knee,\r\n ratio, threshold, release) {\r\n\r\n if (typeof attack !== 'undefined') {this.attack(attack);}\r\n if (typeof knee !== 'undefined') {this.knee(knee);}\r\n if (typeof ratio !== 'undefined') {this.ratio(ratio);}\r\n if (typeof threshold !== 'undefined') {this.threshold(threshold);}\r\n if (typeof release !== 'undefined') {this.release(release);}\r\n };\r\n\r\n\r\n /**\r\n * Get current attack or set value w/ time ramp\r\n *\r\n *\r\n * @method attack\r\n * @for p5.Compressor\r\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.attack = function (attack, time){\r\n var t = time || 0;\r\n if (typeof attack == 'number'){\r\n this.compressor.attack.value = attack;\r\n this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof attack !== 'undefined') {\r\n attack.connect(this.compressor.attack);\r\n }\r\n return this.compressor.attack.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current knee or set value w/ time ramp\r\n *\r\n * @method knee\r\n * @for p5.Compressor\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.knee = function (knee, time){\r\n var t = time || 0;\r\n if (typeof knee == 'number'){\r\n this.compressor.knee.value = knee;\r\n this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof knee !== 'undefined') {\r\n knee.connect(this.compressor.knee);\r\n }\r\n return this.compressor.knee.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current ratio or set value w/ time ramp\r\n * @method ratio\r\n * @for p5.Compressor\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.ratio = function (ratio, time){\r\n var t = time || 0;\r\n if (typeof ratio == 'number'){\r\n this.compressor.ratio.value = ratio;\r\n this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof ratio !== 'undefined') {\r\n ratio.connect(this.compressor.ratio);\r\n }\r\n return this.compressor.ratio.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current threshold or set value w/ time ramp\r\n * @method threshold\r\n * @for p5.Compressor\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.threshold = function (threshold, time){\r\n var t = time || 0;\r\n if (typeof threshold == 'number'){\r\n this.compressor.threshold.value = threshold;\r\n this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof threshold !== 'undefined') {\r\n threshold.connect(this.compressor.threshold);\r\n }\r\n return this.compressor.threshold.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current release or set value w/ time ramp\r\n * @method release\r\n * @for p5.Compressor\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n *\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.release = function (release, time){\r\n var t = time || 0;\r\n if (typeof release == 'number'){\r\n this.compressor.release.value = release;\r\n this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof number !== 'undefined') {\r\n release.connect(this.compressor.release);\r\n }\r\n return this.compressor.release.value;\r\n };\r\n\r\n /**\r\n * Return the current reduction value\r\n *\r\n * @method reduction\r\n * @for p5.Compressor\r\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\r\n */\r\n p5.Compressor.prototype.reduction =function() {\r\n return this.compressor.reduction.value;\r\n };\r\n\r\n\r\n\tp5.Compressor.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.compressor) {\r\n this.compressor.disconnect();\r\n delete this.compressor;\r\n }\r\n\t};\r\n\r\n return p5.Compressor;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // inspiration: recorder.js, Tone.js & typedarray.org\r\n\r\n var p5sound = require('master');\r\n var convertToWav = require('helpers').convertToWav;\r\n var processorNames = require('./audioWorklet/processorNames');\r\n var ac = p5sound.audiocontext;\r\n\r\n /**\r\n *
Record sounds for playback and/or to save as a .wav file.\r\n * The p5.SoundRecorder records all sound output from your sketch,\r\n * or can be assigned a specific source with setInput().
\r\n *
The record() method accepts a p5.SoundFile as a parameter.\r\n * When playback is stopped (either after the given amount of time,\r\n * or with the stop() method), the p5.SoundRecorder will send its\r\n * recording to that p5.SoundFile for playback.
\r\n * var mic, recorder, soundFile;\r\n * var state = 0;\r\n *\r\n * function setup() {\r\n * background(200);\r\n * // create an audio in\r\n * mic = new p5.AudioIn();\r\n *\r\n * // prompts user to enable their browser mic\r\n * mic.start();\r\n *\r\n * // create a sound recorder\r\n * recorder = new p5.SoundRecorder();\r\n *\r\n * // connect the mic to the recorder\r\n * recorder.setInput(mic);\r\n *\r\n * // this sound file will be used to\r\n * // playback & save the recording\r\n * soundFile = new p5.SoundFile();\r\n *\r\n * text('keyPress to record', 20, 20);\r\n * }\r\n *\r\n * function keyPressed() {\r\n * // make sure user enabled the mic\r\n * if (state === 0 && mic.enabled) {\r\n *\r\n * // record to our p5.SoundFile\r\n * recorder.record(soundFile);\r\n *\r\n * background(255,0,0);\r\n * text('Recording!', 20, 20);\r\n * state++;\r\n * }\r\n * else if (state === 1) {\r\n * background(0,255,0);\r\n *\r\n * // stop recorder and\r\n * // send result to soundFile\r\n * recorder.stop();\r\n *\r\n * text('Stopped', 20, 20);\r\n * state++;\r\n * }\r\n *\r\n * else if (state === 2) {\r\n * soundFile.play(); // play the result!\r\n * save(soundFile, 'mySound.wav');\r\n * state++;\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.SoundRecorder = function() {\r\n this.input = ac.createGain();\r\n this.output = ac.createGain();\r\n\r\n this._inputChannels = 2;\r\n this._outputChannels = 2; // stereo output, even if input is mono\r\n\r\n this._workletNode = new AudioWorkletNode(ac, processorNames.recorderProcessor, {\r\n outputChannelCount: [this._outputChannels],\r\n processorOptions: { numInputChannels: this._inputChannels }\r\n });\r\n\r\n this._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'buffers') {\r\n const buffers = [\r\n new Float32Array(event.data.leftBuffer),\r\n new Float32Array(event.data.rightBuffer)\r\n ];\r\n this._callback(buffers);\r\n }\r\n }.bind(this);\r\n\r\n /**\r\n * callback invoked when the recording is over\r\n * @private\r\n * @type Function(Float32Array)\r\n */\r\n this._callback = function() {};\r\n\r\n // connections\r\n this._workletNode.connect(p5.soundOut._silentNode);\r\n this.setInput();\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a specific device to the p5.SoundRecorder.\r\n * If no parameter is given, p5.SoundRecorer will record\r\n * all audible p5.sound from your sketch.\r\n *\r\n * @method setInput\r\n * @for p5.SoundRecorder\r\n * @param {Object} [unit] p5.sound object or a web audio unit\r\n * that outputs sound\r\n */\r\n p5.SoundRecorder.prototype.setInput = function(unit) {\r\n this.input.disconnect();\r\n this.input = null;\r\n this.input = ac.createGain();\r\n this.input.connect(this._workletNode);\r\n this.input.connect(this.output);\r\n if (unit) {\r\n unit.connect(this.input);\r\n } else {\r\n p5.soundOut.output.connect(this.input);\r\n }\r\n };\r\n\r\n /**\r\n * Start recording. To access the recording, provide\r\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\r\n * will send its recording to that p5.SoundFile for playback once\r\n * recording is complete. Optional parameters include duration\r\n * (in seconds) of the recording, and a callback function that\r\n * will be called once the complete recording has been\r\n * transfered to the p5.SoundFile.\r\n *\r\n * @method record\r\n * @for p5.SoundRecorder\r\n * @param {p5.SoundFile} soundFile p5.SoundFile\r\n * @param {Number} [duration] Time (in seconds)\r\n * @param {Function} [callback] The name of a function that will be\r\n * called once the recording completes\r\n */\r\n p5.SoundRecorder.prototype.record = function(sFile, duration, callback) {\r\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\r\n\r\n if (sFile && callback) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n callback();\r\n };\r\n }\r\n else if (sFile) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Stop the recording. Once the recording is stopped,\r\n * the results will be sent to the p5.SoundFile that\r\n * was given on .record(), and if a callback function\r\n * was provided on record, that function will be called.\r\n *\r\n * @method stop\r\n * @for p5.SoundRecorder\r\n */\r\n p5.SoundRecorder.prototype.stop = function() {\r\n this._workletNode.port.postMessage({ name: 'stop' });\r\n };\r\n\r\n p5.SoundRecorder.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this._callback = function() {};\r\n if (this.input) {\r\n this.input.disconnect();\r\n }\r\n this.input = null;\r\n this._workletNode = null;\r\n };\r\n\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device.\r\n * For uploading audio to a server, use\r\n * `p5.SoundFile.saveBlob`.\r\n *\r\n * @for p5\r\n * @method saveSound\r\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\r\n * @param {String} fileName name of the resulting .wav file.\r\n */\r\n // add to p5.prototype as this is used by the p5 `save()` method.\r\n p5.prototype.saveSound = function (soundFile, fileName) {\r\n const dataView = convertToWav(soundFile.buffer);\r\n p5.prototype.writeFile([dataView], fileName, 'wav');\r\n };\r\n});\r\n","module.exports = {\r\n recorderProcessor: 'recorder-processor'\r\n};\r\n","'use strict';\r\n\r\ndefine(function () {\r\n /**\r\n *
PeakDetect works in conjunction with p5.FFT to\r\n * look for onsets in some or all of the frequency spectrum.\r\n *
\r\n *
\r\n * To use p5.PeakDetect, call update in the draw loop\r\n * and pass in a p5.FFT object.\r\n *
\r\n *
\r\n * You can listen for a specific part of the frequency spectrum by\r\n * setting the range between freq1 and freq2.\r\n *
\r\n *\r\n *
threshold is the threshold for detecting a peak,\r\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\r\n * as 1.0.
\r\n *\r\n *
\r\n * The update method is meant to be run in the draw loop, and\r\n * frames determines how many loops must pass before\r\n * another peak can be detected.\r\n * For example, if the frameRate() = 60, you could detect the beat of a\r\n * 120 beat-per-minute song with this equation:\r\n * framesPerPeak = 60 / (estimatedBPM / 60 );\r\n *
\r\n *\r\n *
\r\n * Based on example contribtued by @b2renger, and a simple beat detection\r\n * explanation by Felix Turner.\r\n *
\r\n *\r\n * @class p5.PeakDetect\r\n * @constructor\r\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\r\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\r\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\r\n * scaled logarithmically where 0.1 is 1/2 the loudness\r\n * of 1.0. Defaults to 0.35.\r\n * @param {Number} [framesPerPeak] Defaults to 20.\r\n * @example\r\n *
\r\n */\r\n p5.PeakDetect = function(freq1, freq2, threshold, _framesPerPeak) {\r\n // framesPerPeak determines how often to look for a beat.\r\n // If a beat is provided, try to look for a beat based on bpm\r\n this.framesPerPeak = _framesPerPeak || 20;\r\n this.framesSinceLastPeak = 0;\r\n this.decayRate = 0.95;\r\n\r\n this.threshold = threshold || 0.35;\r\n this.cutoff = 0;\r\n\r\n // how much to increase the cutoff\r\n // TO DO: document this / figure out how to make it accessible\r\n this.cutoffMult = 1.5;\r\n\r\n this.energy = 0;\r\n this.penergy = 0;\r\n\r\n // TO DO: document this property / figure out how to make it accessible\r\n this.currentValue = 0;\r\n\r\n /**\r\n * isDetected is set to true when a peak is detected.\r\n *\r\n * @attribute isDetected {Boolean}\r\n * @default false\r\n */\r\n this.isDetected = false;\r\n\r\n this.f1 = freq1 || 40;\r\n this.f2 = freq2 || 20000;\r\n\r\n // function to call when a peak is detected\r\n this._onPeak = function() {};\r\n };\r\n\r\n\r\n /**\r\n * The update method is run in the draw loop.\r\n *\r\n * Accepts an FFT object. You must call .analyze()\r\n * on the FFT object prior to updating the peakDetect\r\n * because it relies on a completed FFT analysis.\r\n *\r\n * @method update\r\n * @param {p5.FFT} fftObject A p5.FFT object\r\n */\r\n p5.PeakDetect.prototype.update = function(fftObject) {\r\n var nrg = this.energy = fftObject.getEnergy(this.f1,this.f2)/255;\r\n if (nrg > this.cutoff && nrg > this.threshold && nrg-this.penergy > 0) {\r\n\r\n // trigger callback\r\n this._onPeak();\r\n this.isDetected = true;\r\n\r\n // debounce\r\n this.cutoff = nrg * this.cutoffMult;\r\n this.framesSinceLastPeak = 0;\r\n } else {\r\n this.isDetected = false;\r\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\r\n this.framesSinceLastPeak++;\r\n } else {\r\n this.cutoff *= this.decayRate;\r\n this.cutoff = Math.max(this.cutoff, this.threshold);\r\n }\r\n }\r\n\r\n this.currentValue = nrg;\r\n this.penergy = nrg;\r\n };\r\n\r\n /**\r\n * onPeak accepts two arguments: a function to call when\r\n * a peak is detected. The value of the peak,\r\n * between 0.0 and 1.0, is passed to the callback.\r\n *\r\n * @method onPeak\r\n * @param {Function} callback Name of a function that will\r\n * be called when a peak is\r\n * detected.\r\n * @param {Object} [val] Optional value to pass\r\n * into the function when\r\n * a peak is detected.\r\n * @example\r\n *
\r\n * var cnv, soundFile, fft, peakDetect;\r\n * var ellipseWidth = 0;\r\n *\r\n * function preload() {\r\n * soundFile = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * textAlign(CENTER);\r\n *\r\n * fft = new p5.FFT();\r\n * peakDetect = new p5.PeakDetect();\r\n *\r\n * setupSound();\r\n *\r\n * // when a beat is detected, call triggerBeat()\r\n * peakDetect.onPeak(triggerBeat);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * fft.analyze();\r\n * peakDetect.update(fft);\r\n *\r\n * ellipseWidth *= 0.95;\r\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\r\n * }\r\n *\r\n * // this function is called by peakDetect.onPeak\r\n * function triggerBeat() {\r\n * ellipseWidth = 50;\r\n * }\r\n *\r\n * // mouseclick starts/stops sound\r\n * function setupSound() {\r\n * cnv.mouseClicked( function() {\r\n * if (soundFile.isPlaying() ) {\r\n * soundFile.stop();\r\n * } else {\r\n * soundFile.play();\r\n * }\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.PeakDetect.prototype.onPeak = function(callback, val) {\r\n var self = this;\r\n\r\n self._onPeak = function() {\r\n callback(self.energy, val);\r\n };\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * A gain node is usefull to set the relative volume of sound.\r\n * It's typically used to build mixers.\r\n *\r\n * @class p5.Gain\r\n * @constructor\r\n * @example\r\n *
\r\n *\r\n * // load two soundfile and crossfade beetween them\r\n * var sound1,sound2;\r\n * var gain1, gain2, gain3;\r\n *\r\n * function preload(){\r\n * soundFormats('ogg', 'mp3');\r\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\r\n * sound2 = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * createCanvas(400,200);\r\n *\r\n * // create a 'master' gain to which we will connect both soundfiles\r\n * gain3 = new p5.Gain();\r\n * gain3.connect();\r\n *\r\n * // setup first sound for playing\r\n * sound1.rate(1);\r\n * sound1.loop();\r\n * sound1.disconnect(); // diconnect from p5 output\r\n *\r\n * gain1 = new p5.Gain(); // setup a gain node\r\n * gain1.setInput(sound1); // connect the first sound to its input\r\n * gain1.connect(gain3); // connect its output to the 'master'\r\n *\r\n * sound2.rate(1);\r\n * sound2.disconnect();\r\n * sound2.loop();\r\n *\r\n * gain2 = new p5.Gain();\r\n * gain2.setInput(sound2);\r\n * gain2.connect(gain3);\r\n *\r\n * }\r\n *\r\n * function draw(){\r\n * background(180);\r\n *\r\n * // calculate the horizontal distance beetween the mouse and the right of the screen\r\n * var d = dist(mouseX,0,width,0);\r\n *\r\n * // map the horizontal position of the mouse to values useable for volume control of sound1\r\n * var vol1 = map(mouseX,0,width,0,1);\r\n * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa\r\n *\r\n * gain1.amp(vol1,0.5,0);\r\n * gain2.amp(vol2,0.5,0);\r\n *\r\n * // map the vertical position of the mouse to values useable for 'master volume control'\r\n * var vol3 = map(mouseY,0,height,0,1);\r\n * gain3.amp(vol3,0.5,0);\r\n * }\r\n *
\r\n *\r\n */\r\n\r\n p5.Gain = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n this.input.connect(this.output);\r\n\r\n // add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a source to the gain node.\r\n *\r\n * @method setInput\r\n * @for p5.Gain\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n */\r\n\r\n\r\n p5.Gain.prototype.setInput = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Gain\r\n * @param {Object} unit\r\n */\r\n p5.Gain.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Gain\r\n */\r\n p5.Gain.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Set the output level of the gain node.\r\n *\r\n * @method amp\r\n * @for p5.Gain\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Gain.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n };\r\n\r\n p5.Gain.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n\r\n /*\r\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n */\r\n function makeDistortionCurve(amount) {\r\n var k = typeof amount === 'number' ? amount : 50;\r\n var numSamples = 44100;\r\n var curve = new Float32Array(numSamples);\r\n var deg = Math.PI / 180;\r\n var i = 0;\r\n var x;\r\n for ( ; i < numSamples; ++i ) {\r\n x = i * 2 / numSamples - 1;\r\n curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );\r\n }\r\n return curve;\r\n }\r\n\r\n /**\r\n * A Distortion effect created with a Waveshaper Node,\r\n * with an approach adapted from\r\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Distortion\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n *\r\n */\r\n p5.Distortion = function(amount, oversample) {\r\n Effect.call(this);\r\n\r\n if (typeof amount === 'undefined') {\r\n amount = 0.25;\r\n } if (typeof amount !== 'number') {\r\n throw new Error('amount must be a number');\r\n } if (typeof oversample === 'undefined') {\r\n oversample = '2x';\r\n } if (typeof oversample !== 'string') {\r\n throw new Error('oversample must be a String');\r\n }\r\n\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n\r\n /**\r\n * The p5.Distortion is built with a\r\n * \r\n * Web Audio WaveShaper Node.\r\n *\r\n * @property {AudioNode} WaveShaperNode\r\n */\r\n this.waveShaperNode = this.ac.createWaveShaper();\r\n\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n this.waveShaperNode.oversample = oversample;\r\n\r\n this.input.connect(this.waveShaperNode);\r\n\r\n this.waveShaperNode.connect(this.wet);\r\n };\r\n\r\n p5.Distortion.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Process a sound source, optionally specify amount and oversample values.\r\n *\r\n * @method process\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.process = function(src, amount, oversample) {\r\n src.connect(this.input);\r\n this.set(amount, oversample);\r\n };\r\n\r\n /**\r\n * Set the amount and oversample of the waveshaper distortion.\r\n *\r\n * @method set\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.set = function(amount, oversample) {\r\n if (amount) {\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n }\r\n if (oversample) {\r\n this.waveShaperNode.oversample = oversample;\r\n }\r\n };\r\n\r\n /**\r\n * Return the distortion amount, typically between 0-1.\r\n *\r\n * @method getAmount\r\n * @for p5.Distortion\r\n * @return {Number} Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n */\r\n p5.Distortion.prototype.getAmount = function() {\r\n return this.amount;\r\n };\r\n\r\n /**\r\n * Return the oversampling.\r\n *\r\n * @method getOversample\r\n * @for p5.Distortion\r\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.getOversample = function() {\r\n return this.waveShaperNode.oversample;\r\n };\r\n\r\n\r\n p5.Distortion.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.waveShaperNode) {\r\n this.waveShaperNode.disconnect();\r\n this.waveShaperNode = null;\r\n }\r\n };\r\n});\r\n"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///../node_modules/tone/Tone/core/Tone.js","webpack:///./master.js","webpack:///../node_modules/tone/Tone/signal/Signal.js","webpack:///../node_modules/tone/Tone/signal/Multiply.js","webpack:///./effect.js","webpack:///../node_modules/tone/Tone/signal/WaveShaper.js","webpack:///./helpers.js","webpack:///../node_modules/tone/Tone/signal/Add.js","webpack:///../node_modules/tone/Tone/type/Type.js","webpack:///../node_modules/tone/Tone/core/Gain.js","webpack:///./errorHandler.js","webpack:///../node_modules/tone/Tone/core/Context.js","webpack:///../node_modules/tone/Tone/signal/Scale.js","webpack:///../node_modules/tone/Tone/signal/TimelineSignal.js","webpack:///./filter.js","webpack:///../node_modules/tone/Tone/signal/Subtract.js","webpack:///./audiocontext.js","webpack:///../node_modules/tone/Tone/core/Emitter.js","webpack:///./audioWorklet/processorNames.js","webpack:///../node_modules/tone/Tone/signal/SignalBase.js","webpack:///../node_modules/tone/Tone/type/Time.js","webpack:///../node_modules/tone/Tone/type/TimeBase.js","webpack:///../node_modules/tone/Tone/core/Param.js","webpack:///./oscillator.js","webpack:///../node_modules/tone/Tone/core/Timeline.js","webpack:///../node_modules/tone/Tone/signal/Negate.js","webpack:///../node_modules/tone/Tone/signal/GreaterThanZero.js","webpack:///../node_modules/tone/Tone/core/Clock.js","webpack:///./monosynth.js","webpack:///./audioVoice.js","webpack:///./polysynth.js","webpack:///./app.js","webpack:///../node_modules/audioworklet-polyfill/dist/audioworklet-polyfill.js","webpack:///./shims.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///../node_modules/startaudiocontext/StartAudioContext.js","webpack:///./audioWorklet/index.js","webpack:///./audioWorklet/recorderProcessor.js","webpack:///./audioWorklet/soundFileProcessor.js","webpack:///./panner.js","webpack:///./soundfile.js","webpack:///./amplitude.js","webpack:///./fft.js","webpack:///./signal.js","webpack:///../node_modules/tone/Tone/type/Frequency.js","webpack:///../node_modules/tone/Tone/type/TransportTime.js","webpack:///./envelope.js","webpack:///./pulse.js","webpack:///./noise.js","webpack:///./audioin.js","webpack:///../node_modules/tone/Tone/component/CrossFade.js","webpack:///../node_modules/tone/Tone/signal/Expr.js","webpack:///../node_modules/tone/Tone/signal/GreaterThan.js","webpack:///../node_modules/tone/Tone/signal/Abs.js","webpack:///../node_modules/tone/Tone/signal/Modulo.js","webpack:///../node_modules/tone/Tone/signal/Pow.js","webpack:///../node_modules/tone/Tone/signal/AudioToGain.js","webpack:///../node_modules/tone/Tone/signal/EqualPowerGain.js","webpack:///./eq.js","webpack:///./eqFilter.js","webpack:///./panner3d.js","webpack:///./listener3d.js","webpack:///./delay.js","webpack:///./reverb.js","webpack:///./metro.js","webpack:///../node_modules/tone/Tone/core/TimelineState.js","webpack:///./looper.js","webpack:///./soundLoop.js","webpack:///./compressor.js","webpack:///./soundRecorder.js","webpack:///./peakDetect.js","webpack:///./gain.js","webpack:///./distortion.js","webpack:///./audioWorklet/amplitudeProcessor.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","define","Tone","inputs","outputs","this","isUndef","input","context","createGain","Array","output","audioContext","set","params","rampTime","isObject","isString","tmpObj","paramLoop","attr","parent","indexOf","attrSplit","split","length","splice","innerParam","join","param","Signal","Param","rampTo","AudioParam","_collectDefaults","constructor","ret","subRet","j","subAttr","isFunction","constr","defaults","keys","_super","superDefs","push","toString","className","isLetter","match","sameConstructor","isArray","dispose","AudioNode","disconnect","connect","unit","outputNum","inputNum","defaultArg","destination","isNumber","apply","arguments","connectSeries","currentUnit","toUnit","chain","fan","given","fallback","givenProp","fallbackProp","optionsObject","values","options","val","arg","isBoolean","noOp","_readOnly","writable","_writable","State","Started","Stopped","Paused","equalPowerScale","percent","piFactor","Math","PI","sin","dbToGain","db","pow","gainToDb","gain","log","LN10","intervalToFrequencyRatio","interval","now","extend","child","TempConstructor","Context","emit","setContext","ctx","sampleRate","hasAudioContext","window","hasPromises","hasWorkers","version","TONE_SILENCE_VERSION_LOGGING","__WEBPACK_AMD_DEFINE_ARRAY__","__WEBPACK_AMD_DEFINE_RESULT__","undefined","audiocontext","p5sound","limiter","createDynamicsCompressor","threshold","ratio","knee","meter","fftMeter","soundArray","parts","extensions","p5","getMasterVolume","masterVolume","vol","tFromNow","currentTime","currentVol","cancelScheduledValues","linearRampToValueAtTime","soundOut","_silentNode","_gain","_param","getConstant","units","Type","Default","convert","SignalBase","Multiply","createInsOuts","_mult","Gain","require","CrossFade","Effect","ac","_drywet","wet","a","b","amp","drywet","fade","u","index","WaveShaper","mapping","bufferLen","_shaper","createWaveShaper","_curve","curve","isFinite","Float32Array","setMap","len","normalized","oversample","oversampling","RangeError","freqToMidi","f","mathlog2","round","midiToFreq","writeUTFBytes","view","offset","string","lng","setUint8","charCodeAt","soundFormats","toLowerCase","disposeSound","registerMethod","_checkFileFormats","paths","path","extTest","pop","isFileSupported","pathSplit","pathCore","extension","_typeof","_mathChain","math","thisChain","nextChain","type","mathOps","convertToWav","audioBuffer","leftChannel","interleaved","rightChannel","result","inputIndex","interleave","getChannelData","numberOfChannels","buffer","ArrayBuffer","DataView","setUint32","setUint16","setInt16","noteToFreq","note","A","B","C","D","E","F","G","toUpperCase","slice","Add","_sum","Time","Frequency","TransportTime","Ticks","NormalRange","AudioRange","Decibels","Interval","BPM","Positive","Cents","Degrees","MIDI","BarsBeatsSixteenths","Samples","Hertz","Note","Milliseconds","Seconds","Notation","toSeconds","time","TimeBase","toFrequency","freq","valueOf","toTicks","Transport","ticks","GainNode","AudioContext","createGainNode","_gainNode","errorTrace","failedPath","tempStack","splitStack","err","Error","originalStack","stack","filter","ln","toneConnect","outNum","inNum","nativeConnect","e","nativeDisconnect","webkitAudioContext","prop","Emitter","_context","_defineProperty","_latencyHint","_lookAhead","_updateInterval","_computedUpdateInterval","_worker","_createWorker","_constants","mixin","URL","webkitURL","blob","Blob","toFixed","blobUrl","createObjectURL","worker","Worker","addEventListener","_lastUpdate","diff","max","createBuffer","arr","constant","createBufferSource","channelCount","channelCountMode","loop","start","lA","blockTime","postMessage","hint","lookAhead","latencyHint","updateInterval","supported","Scale","outputMin","outputMax","_outputMin","_outputMax","_scale","_add","_setRange","min","TimelineSignal","_events","Timeline","_initial","_fromUnits","Linear","Exponential","Target","Curve","Set","getValueAtTime","_toUnits","convertedVal","setValueAtTime","startTime","add","endTime","exponentialRampToValueAtTime","beforeEvent","_searchBefore","_minOutput","setValue","sampleTime","setTargetAtTime","timeConstant","setValueCurveAtTime","duration","scaling","floats","segmentTime","after","cancel","setRampPoint","before","_searchAfter","linearRampToValueBetween","finish","exponentialRampToValueBetween","getAfter","previouVal","previous","getBefore","_exponentialApproach","_curveInterpolate","_linearInterpolate","_exponentialInterpolate","t0","v0","v1","exp","t1","progress","lowerIndex","floor","upperIndex","ceil","lowerVal","upperVal","Filter","biquad","createBiquadFilter","setType","_on","_untoggledType","process","src","res","frequency","Q","toggle","LowPass","HighPass","BandPass","Subtract","_neg","Negate","global","StartAudioContext","getAudioContext","userStartAudio","elements","callback","elt","Element","map","on","event","events","eventName","off","ev","eventList","args","functions","func","emitterFunc","recorderProcessor","soundFileProcessor","amplitudeProcessor","node","outputNumber","inputNumber","overridden","_plusNow","_unaryExpressions","quantize","regexp","method","rh","nextSubdivision","lh","subdiv","_expr","expr","subdivision","addNow","_defaultExpr","_noOp","copy","toNotation","retNotation","_toNotationHelper","retTripletNotation","testNotations","_notationToUnits","notationTime","multiple","notation","primaryExprs","_primaryExpressions","notationExprs","toBarsBeatsSixteenths","quarterTime","_beatsToUnits","quarters","measures","_timeSignature","sixteenths","parseFloat","PPQ","toSamples","toMilliseconds","_defaultUnits","exprString","_parseExprString","clone","instance","parseInt","_ticksToUnits","hz","_frequencyToUnits","tr","q","total","_secondsToUnits","samples","default","_binaryExpressions","+","precedence","-","*","/","neg","_syntaxGlue","(",")","_tokenize","position","tokens","token","getNextToken","trim","substr","expressions","group","opName","op","reg","SyntaxError","next","peek","_matchGroup","prec","test","_parseBinary","lexer","_parseUnary","_parsePrimary","matching","beats","bpm","seconds","timeSignature","_pushExpr","sub","mult","div","_lfo","lfo","LFO","currentVal","exponentialRampToValue","linearRampToValue","Mult","Oscillator","started","phaseAmount","oscillator","createOscillator","_freqMods","panPosition","connection","panner","Panner","stop","abs","freqNode","getAmp","isNaN","phase","getFreq","getType","oscMods","pan","pval","getPan","osc2","delayAmt","dNode","createDelay","delayTime","sigChain","mathObj","chainSource","num","scale","inMin","inMax","outMin","outMax","mapOutMin","mapOutMax","SinOsc","TriOsc","SawOsc","SqrOsc","_timeline","_toRemove","_iterating","memory","Infinity","_search","remove","shift","cancelBefore","beginning","end","midPoint","nextEvent","_iterate","lowerBound","upperBound","forEach","forEachBefore","forEachAfter","forEachFrom","forEachAtTime","_multiply","GreaterThanZero","_thresh","Clock","_nextTick","_lastState","_state","TimelineState","_boundLoop","_loop","state","setStateAtTime","pause","loopInterval","lag","currentState","tickTime","getStateAtTime","AudioVoice","MonoSynth","env","Envelope","setRange","setExp","setADSR","setInput","play","velocity","secondsFromNow","susTime","triggerAttack","triggerRelease","vel","ramp","attack","decay","sustain","release","defineProperties","aTime","dTime","sPercent","rTime","sustime","PolySynth","audioVoice","maxVoices","audiovoices","notes","_newest","_oldest","_voicesInUse","_allocateVoices","noteAttack","noteRelease","noteADSR","timeFromNow","voice","_note","_velocity","currentVoice","acTime","oldestNote","previousVal","_updateAfter","maxRange","nextTime","p5SOUND","parameters","bufferSize","fill","processor","realm","exec","inputBuffer","outputBuffer","$$processors","$$context","AudioWorkletNode","self","createScriptProcessor","outputChannelCount","Map","properties","defaultValue","MessageChannel","port2","Processor","port","port1","onaudioprocess","$$audioWorklet","AudioWorklet","addModule","fetch","then","ok","status","text","AudioWorkletProcessor","registerProcessor","parameterDescriptors","document","createElement","style","cssText","appendChild","contentWindow","createTextNode","body","$hook","console","documentElement","transpile","String","fixSetTarget","setTargetValueAtTime","createDelayNode","createJavaScriptNode","createPeriodicWave","createWaveTable","internal_createGain","internal_createDelay","maxDelayTime","internal_createBufferSource","internal_start","when","noteGrainOn","noteOn","internal_stop","noteOff","playbackRate","internal_createDynamicsCompressor","reduction","internal_createBiquadFilter","detune","internal_createOscillator","setPeriodicWave","setWaveTable","OfflineAudioContext","webkitOfflineAudioContext","navigator","getUserMedia","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","el","isSupported","canPlayType","g","Function","__WEBPACK_AMD_DEFINE_FACTORY__","TapListener","element","_dragged","_element","_bindedMove","_moved","_bindedEnd","_ended","isStarted","source","resume","startContext","removeEventListener","promise","Promise","success","checkLoop","requestAnimationFrame","onStarted","tapListeners","bindTapListener","NodeList","querySelectorAll","jquery","toArray","tap","moduleSources","preload","_preloadCount","onWorkletModulesLoad","_decrementPreload","all","moduleSrc","objectURL","audioWorklet","__webpack_exports__","createStereoPanner","stereoPanner","inputChannels","obj","numInputChannels","left","right","channelInterpretation","splitter","createChannelSplitter","createChannelMerger","v","rightVal","cos","leftVal","numChannels","CustomError","processorNames","SoundFile","onload","onerror","whileLoading","url","File","FileReader","FileList","file","_onended","_looping","_playing","_paused","_pauseTime","_cues","_cueIDCounter","_lastPos","_counterNode","_workletNode","bufferSourceNodes","bufferSourceNode","reversed","pauseTime","startMillis","load","_whileLoading","_onAudioProcess","processEvent","_onTimeUpdate","_clearOnEnd","thisBufferSourceNode","target","soundFile","registerPreloadMethod","loadSound","location","origin","cordova","alert","errorCallback","request","XMLHttpRequest","evt","_updateProgress","open","responseType","decodeAudioData","response","buff","msg","statusText","message","send","reader","readAsArrayBuffer","lengthComputable","percentComplete","loaded","isLoaded","rate","_cueStart","cueStart","cueEnd","setVolume","isPlaying","_initSourceNode","_initCounterNode","_arrayIndex","loopStart","loopEnd","playMode","str","pTime","setLoop","bool","isLooping","isPaused","stopAll","_time","_rampTime","_tFromNow","getVolume","reverse","reverseBuffer","setPitch","newPlaybackRate","getPlaybackRate","jump","cueTime","cTime","dur","channels","frames","getPeaks","width","sampleSize","sampleStep","peaks","chan","currentPos","curVol","onended","getLevel","setPath","setBuffer","buf","size","newBuffer","channelNum","cNode","onmessage","data","audioBuf","arrayBuffer","_createCounterBuffer","processPeaks","_initThreshold","_minThreshold","_minPeaks","bufLen","allPeaks","minThreshold","minPeaks","offlineContext","startRendering","oncomplete","filteredBuffer","renderedBuffer","bufferData","getPeaksAtThreshold","topTempos","intervalCounts","tempoCounts","intervalCount","theoreticalTempo","mapTempo","some","tempoCount","tempo","count","groupNeighborsByTempo","peaksObj","peaksArray","sort","startPeak","endPeak","startPos","sampleIndex","intervals","countIntervalsBetweenNearbyPeaks","intA","intB","tempoPeaks","bpmVariance","peaksAtTopTempo","peak","intervalBPM","peakTime","getPeaksAtTopTempo","Peak","amplitude","tempos","Cue","id","addCue","cue","removeCue","cueLength","clearCues","playbackTime","callbackTime","_prevTime","save","fileName","dataView","saveSound","getBlob","Amplitude","smoothing","parameterData","processorOptions","normalize","volume","volNorm","stereoVol","stereoVolNorm","channel","toggleNormalize","smooth","FFT","bins","analyser","createAnalyser","fftSize","configurable","smoothingTimeConstant","freqDomain","Uint8Array","frequencyBinCount","timeDomain","bass","lowMid","mid","highMid","treble","waveform","_isSafari","timeToFloat","getFloatTimeDomainData","timeToInt","getByteTimeDomainData","normalArray","scaled","analyze","freqToFloat","getFloatFrequencyData","freqToInt","getByteFrequencyData","getEnergy","frequency1","frequency2","nyquist","swap","lowIndex","highIndex","numFrequencies","freq1","freq2","getCentroid","cumulative_sum","centroid_normalization","mean_freq_index","linAverages","N","spectrum","spectrumLength","spectrumStep","linearAverages","groupIndex","specIndex","logAverages","octaveBands","octaveIndex","hi","getOctaveBands","fCtr0","lastFrequencyBand","lo","ctr","newFrequencyBand","fft","_input","midi","midiToFrequency","pitch","octave","noteNumber","noteToScaleIndex","transpose","harmonize","toMidi","frequencyToMidi","toNote","A4","LN2","scaleIndexToNote","cbb","cb","c#","cx","dbb","d#","dx","ebb","eb","e#","ex","fbb","fb","f#","fx","gbb","gb","g#","gx","abb","ab","a#","ax","bbb","bb","b#","bx","_secondsToTicks","l1","t2","l2","t3","l3","aLevel","dLevel","rLevel","_rampHighPercentage","_rampLowPercentage","control","_init","isExponential","sourceToClear","wasTriggered","_setRampAD","_rampAttackTime","checkExpInput","_rampDecayTime","TCDenominator","_rampAttackTC","_rampDecayTC","setRampPercentages","p1","p2","isExp","lastAttack","valToSet","v2","destination1","destination2","AudioIn","Reverb","Noise","Delay","Env","createDCOffset","bufferSource","Pulse","w","dcOffset","dcGain","mW","sig","SignalAdd","mods","currentFreq","freqMod","assignType","_brownNoise","_pinkNoise","_whiteNoise","whiteBuffer","noiseData","random","b0","b1","b2","b3","b4","b5","b6","pinkBuffer","white","brownBuffer","lastOut","noise","inputSources","stream","mediaStream","currentSource","enabled","MediaStreamTrack","mediaDevices","successCallback","audioSource","constraints","audio","echoCancellation","deviceId","createMediaStreamSource","getTracks","track","getSources","onSuccess","onError","resolve","reject","enumerateDevices","devices","device","kind","error","setSource","active","initialFade","_equalPowerA","EqualPowerGain","_equalPowerB","_invert","Expr","applyBinary","Constructor","_eval","applyUnary","getNumber","literalNumber","_replacements","inputCount","_parseInputs","_nodes","tree","_parseTree","_disposeNodes","_Expressions","signal","glue",",","Abs","mod","modulus","Modulo","Pow","a2g","AudioToGain","binary","unary","!","NOT","inputArray","inputMax","replace","matchSyntax","syn","matchGroup","groupName","parseExpression","parseUnary","operator","parsePrimary","GreaterThan","_gtz","_abs","_subtract","_modSignal","_setWaveShaper","_exp","_expScaler","_expFunc","_norm","x","_eqPower","EQFilter","EQ","_eqsize","factor","bands","_newBand","Panner3D","createPanner","panningModel","distanceModel","xVal","yVal","zVal","positionX","positionY","positionZ","orient","orientX","orientY","orientZ","orientationX","orientationY","orientationZ","setFalloff","maxDistance","rolloffFactor","maxDist","rolloff","Listener3D","listener","xValF","yValF","zValF","xValU","yValU","zValU","orientForward","orientUp","forwardX","forwardY","forwardZ","upX","upY","upZ","_split","_merge","_leftGain","_rightGain","leftDelay","rightDelay","_leftFilter","_rightFilter","_maxDelay","maxValue","feedback","_delayTime","_feedback","_filter","_initConvolverNode","_seconds","_decay","_reverse","_buildImpulse","convolverNode","createConvolver","_teardownConvolverNode","_setBuffer","decayRate","rebuild","impulse","impulseL","impulseR","Convolver","impulses","_loadBuffer","cReverb","chunks","addImpulse","resetImpulse","toggleImpulse","Metro","clock","ontick","syncedParts","prevTick","tatumTime","tickCallback","elapsedTime","thisPart","incrementStep","phrases","thisPhrase","phraseArray","sequence","bNum","metroTicks","looping","setBPM","beatTime","tatums","getBPM","getRate","resetSync","part","pushSync","beatLength","initial","playNextPart","aScore","currentPart","scoreStep","Phrase","phraseStep","Part","steps","bLength","partStep","noLoop","metro","addPhrase","array","removePhrase","getPhrase","replaceSequence","onStep","Score","thisScore","nextPart","resetPart","resetParts","SoundLoop","musicalTimeMode","_interval","_bpm","maxIterations","iterations","_calcFreq","syncedStart","otherLoop","_update","_convertNotation","Number","_measure","timeSig","Compressor","compressor","number","SoundRecorder","_inputChannels","_outputChannels","buffers","leftBuffer","rightBuffer","_callback","record","sFile","writeFile","PeakDetect","_framesPerPeak","framesPerPeak","framesSinceLastPeak","cutoff","cutoffMult","energy","penergy","currentValue","isDetected","f1","f2","_onPeak","update","fftObject","nrg","onPeak","makeDistortionCurve","amount","k","deg","Distortion","curveAmount","waveShaperNode","getAmount","getOversample"],"mappings":"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","file":"p5.sound.min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 31);\n","/**\n * Tone.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2014-2017 Yotam Mann\n */\ndefine(function(){\n\n\t\"use strict\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTONE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * @class Tone is the base class of all other classes. It provides \n\t * a lot of methods and functionality to all classes that extend\n\t * it. \n\t * \n\t * @constructor\n\t * @alias Tone\n\t * @param {number} [inputs=1] the number of input nodes\n\t * @param {number} [outputs=1] the number of output nodes\n\t */\n\tvar Tone = function(inputs, outputs){\n\n\t\t/**\n\t\t * the input node(s)\n\t\t * @type {GainNode|Array}\n\t\t */\n\t\tif (this.isUndef(inputs) || inputs === 1){\n\t\t\tthis.input = this.context.createGain();\n\t\t} else if (inputs > 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\t/**\n\t\t * the output node(s)\n\t\t * @type {GainNode|Array}\n\t\t */\n\t\tif (this.isUndef(outputs) || outputs === 1){\n\t\t\tthis.output = this.context.createGain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t/**\n\t * Set the parameters at once. Either pass in an\n\t * object mapping parameters to values, or to set a\n\t * single parameter, by passing in a string and value.\n\t * The last argument is an optional ramp time which \n\t * will ramp any signal values to their destination value\n\t * over the duration of the rampTime.\n\t * @param {Object|string} params\n\t * @param {number=} value\n\t * @param {Time=} rampTime\n\t * @returns {Tone} this\n\t * @example\n\t * //set values using an object\n\t * filter.set({\n\t * \t\"frequency\" : 300,\n\t * \t\"type\" : highpass\n\t * });\n\t * @example\n\t * filter.set(\"type\", \"highpass\");\n\t * @example\n\t * //ramp to the value 220 over 3 seconds. \n\t * oscillator.set({\n\t * \t\"frequency\" : 220\n\t * }, 3);\n\t */\n\tTone.prototype.set = function(params, value, rampTime){\n\t\tif (this.isObject(params)){\n\t\t\trampTime = value;\n\t\t} else if (this.isString(params)){\n\t\t\tvar tmpObj = {};\n\t\t\ttmpObj[params] = value;\n\t\t\tparams = tmpObj;\n\t\t}\n\n\t\tparamLoop:\n\t\tfor (var attr in params){\n\t\t\tvalue = params[attr];\n\t\t\tvar parent = this;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var i = 0; i < attrSplit.length - 1; i++){\n\t\t\t\t\tparent = parent[attrSplit[i]];\n\t\t\t\t\tif (parent instanceof Tone) {\n\t\t\t\t\t\tattrSplit.splice(0,i+1);\n\t\t\t\t\t\tvar innerParam = attrSplit.join(\".\");\n\t\t\t\t\t\tparent.set(innerParam, value);\n\t\t\t\t\t\tcontinue paramLoop;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isUndef(param)){\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((Tone.Signal && param instanceof Tone.Signal) || \n\t\t\t\t\t(Tone.Param && param instanceof Tone.Param)){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tif (this.isUndef(rampTime)){\n\t\t\t\t\t\tparam.value = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparam.rampTo(value, rampTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tif (param.value !== value){\n\t\t\t\t\tparam.value = value;\n\t\t\t\t}\t\t\t\t\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tparam.set(value);\n\t\t\t} else if (param !== value){\n\t\t\t\tparent[attr] = value;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the object's attributes. Given no arguments get\n\t * will return all available object properties and their corresponding\n\t * values. Pass in a single attribute to retrieve or an array\n\t * of attributes. The attribute strings can also include a \".\"\n\t * to access deeper properties.\n\t * @example\n\t * osc.get();\n\t * //returns {\"type\" : \"sine\", \"frequency\" : 440, ...etc}\n\t * @example\n\t * osc.get(\"type\");\n\t * //returns { \"type\" : \"sine\"}\n\t * @example\n\t * //use dot notation to access deep properties\n\t * synth.get([\"envelope.attack\", \"envelope.release\"]);\n\t * //returns {\"envelope\" : {\"attack\" : 0.2, \"release\" : 0.4}}\n\t * @param {Array=|string|undefined} params the parameters to get, otherwise will return \n\t * \t\t\t\t\t all available.\n\t * @returns {Object}\n\t */\n\tTone.prototype.get = function(params){\n\t\tif (this.isUndef(params)){\n\t\t\tparams = this._collectDefaults(this.constructor);\n\t\t} else if (this.isString(params)){\n\t\t\tparams = [params];\n\t\t} \n\t\tvar ret = {};\n\t\tfor (var i = 0; i < params.length; i++){\n\t\t\tvar attr = params[i];\n\t\t\tvar parent = this;\n\t\t\tvar subRet = ret;\n\t\t\tif (attr.indexOf(\".\") !== -1){\n\t\t\t\tvar attrSplit = attr.split(\".\");\n\t\t\t\tfor (var j = 0; j < attrSplit.length - 1; j++){\n\t\t\t\t\tvar subAttr = attrSplit[j];\n\t\t\t\t\tsubRet[subAttr] = subRet[subAttr] || {};\n\t\t\t\t\tsubRet = subRet[subAttr];\n\t\t\t\t\tparent = parent[subAttr];\n\t\t\t\t}\n\t\t\t\tattr = attrSplit[attrSplit.length - 1];\n\t\t\t}\n\t\t\tvar param = parent[attr];\n\t\t\tif (this.isObject(params[attr])){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (Tone.Signal && param instanceof Tone.Signal){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (Tone.Param && param instanceof Tone.Param){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof AudioParam){\n\t\t\t\tsubRet[attr] = param.value;\n\t\t\t} else if (param instanceof Tone){\n\t\t\t\tsubRet[attr] = param.get();\n\t\t\t} else if (!this.isFunction(param) && !this.isUndef(param)){\n\t\t\t\tsubRet[attr] = param;\n\t\t\t} \n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * collect all of the default attributes in one\n\t * @private\n\t * @param {function} constr the constructor to find the defaults from\n\t * @return {Array} all of the attributes which belong to the class\n\t */\n\tTone.prototype._collectDefaults = function(constr){\n\t\tvar ret = [];\n\t\tif (!this.isUndef(constr.defaults)){\n\t\t\tret = Object.keys(constr.defaults);\n\t\t}\n\t\tif (!this.isUndef(constr._super)){\n\t\t\tvar superDefs = this._collectDefaults(constr._super);\n\t\t\t//filter out repeats\n\t\t\tfor (var i = 0; i < superDefs.length; i++){\n\t\t\t\tif (ret.indexOf(superDefs[i]) === -1){\n\t\t\t\t\tret.push(superDefs[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * @returns {string} returns the name of the class as a string\n\t */\n\tTone.prototype.toString = function(){\n\t\tfor (var className in Tone){\n\t\t\tvar isLetter = className[0].match(/^[A-Z]$/);\n\t\t\tvar sameConstructor = Tone[className] === this.constructor;\n\t\t\tif (this.isFunction(Tone[className]) && isLetter && sameConstructor){\n\t\t\t\treturn className;\n\t\t\t}\n\t\t}\n\t\treturn \"Tone\";\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCLASS VARS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The number of inputs feeding into the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfInputs\", {\n\t\tget : function(){\n\t\t\tif (this.input){\n\t\t\t\tif (this.isArray(this.input)){\n\t\t\t\t\treturn this.input.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The number of outputs coming out of the AudioNode. \n\t * For source nodes, this will be 0.\n\t * @memberOf Tone#\n\t * @name numberOfInputs\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"numberOfOutputs\", {\n\t\tget : function(){\n\t\t\tif (this.output){\n\t\t\t\tif (this.isArray(this.output)){\n\t\t\t\t\treturn this.output.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\t\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONNECTIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * disconnect and dispose\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.dispose = function(){\n\t\tif (!this.isUndef(this.input)){\n\t\t\tif (this.input instanceof AudioNode){\n\t\t\t\tthis.input.disconnect();\n\t\t\t} \n\t\t\tthis.input = null;\n\t\t}\n\t\tif (!this.isUndef(this.output)){\n\t\t\tif (this.output instanceof AudioNode){\n\t\t\t\tthis.output.disconnect();\n\t\t\t} \n\t\t\tthis.output = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode\n\t * @param {Tone | AudioParam | AudioNode} unit \n\t * @param {number} [outputNum=0] optionally which output to connect from\n\t * @param {number} [inputNum=0] optionally which input to connect to\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connect = function(unit, outputNum, inputNum){\n\t\tif (Array.isArray(this.output)){\n\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\tthis.output[outputNum].connect(unit, 0, inputNum);\n\t\t} else {\n\t\t\tthis.output.connect(unit, outputNum, inputNum);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * disconnect the output\n\t * @param {Number|AudioNode} output Either the output index to disconnect\n\t * if the output is an array, or the\n\t * node to disconnect from.\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.disconnect = function(destination, outputNum, inputNum){\n\t\tif (this.isArray(this.output)){\n\t\t\tif (this.isNumber(destination)){\n\t\t\t\tthis.output[destination].disconnect();\n\t\t\t} else {\n\t\t\t\toutputNum = this.defaultArg(outputNum, 0);\n\t\t\t\tthis.output[outputNum].disconnect(destination, 0, inputNum);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.output.disconnect.apply(this.output, arguments);\n\t\t}\n\t};\n\n\t/**\n\t * connect together all of the arguments in series\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.connectSeries = function(){\n\t\tif (arguments.length > 1){\n\t\t\tvar currentUnit = arguments[0];\n\t\t\tfor (var i = 1; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Connect the output of this node to the rest of the nodes in series.\n\t * @example\n\t * //connect a node to an effect, panVol and then to the master output\n\t * node.chain(effect, panVol, Tone.Master);\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.chain = function(){\n\t\tif (arguments.length > 0){\n\t\t\tvar currentUnit = this;\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tvar toUnit = arguments[i];\n\t\t\t\tcurrentUnit.connect(toUnit);\n\t\t\t\tcurrentUnit = toUnit;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * connect the output of this node to the rest of the nodes in parallel.\n\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t * @returns {Tone} this\n\t */\n\tTone.prototype.fan = function(){\n\t\tif (arguments.length > 0){\n\t\t\tfor (var i = 0; i < arguments.length; i++){\n\t\t\t\tthis.connect(arguments[i]);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t//give native nodes chain and fan methods\n\tAudioNode.prototype.chain = Tone.prototype.chain;\n\tAudioNode.prototype.fan = Tone.prototype.fan;\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUTILITIES / HELPERS / MATHS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * If the `given` parameter is undefined, use the `fallback`. \n\t * If both `given` and `fallback` are object literals, it will\n\t * return a deep copy which includes all of the parameters from both \n\t * objects. If a parameter is undefined in given, it will return\n\t * the fallback property. \n\t *
\n\t * WARNING: if object is self referential, it will go into an an \n\t * infinite recursive loop.\n\t * \n\t * @param {*} given \n\t * @param {*} fallback \n\t * @return {*} \n\t */\n\tTone.prototype.defaultArg = function(given, fallback){\n\t\tif (this.isObject(given) && this.isObject(fallback)){\n\t\t\tvar ret = {};\n\t\t\t//make a deep copy of the given object\n\t\t\tfor (var givenProp in given) {\n\t\t\t\tret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);\n\t\t\t}\n\t\t\tfor (var fallbackProp in fallback) {\n\t\t\t\tret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn this.isUndef(given) ? fallback : given;\n\t\t}\n\t};\n\n\t/**\n\t * returns the args as an options object with given arguments\n\t * mapped to the names provided. \n\t *\n\t * if the args given is an array containing only one object, it is assumed\n\t * that that's already the options object and will just return it. \n\t * \n\t * @param {Array} values the 'arguments' object of the function\n\t * @param {Array} keys the names of the arguments as they\n\t * should appear in the options object\n\t * @param {Object=} defaults optional defaults to mixin to the returned \n\t * options object \n\t * @return {Object} the options object with the names mapped to the arguments\n\t */\n\tTone.prototype.optionsObject = function(values, keys, defaults){\n\t\tvar options = {};\n\t\tif (values.length === 1 && this.isObject(values[0])){\n\t\t\toptions = values[0];\n\t\t} else {\n\t\t\tfor (var i = 0; i < keys.length; i++){\n\t\t\t\toptions[keys[i]] = values[i];\n\t\t\t}\n\t\t}\n\t\tif (!this.isUndef(defaults)){\n\t\t\treturn this.defaultArg(options, defaults);\n\t\t} else {\n\t\t\treturn options;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// TYPE CHECKING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * test if the arg is undefined\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is undefined\n\t * @function\n\t */\n\tTone.prototype.isUndef = function(val){\n\t\treturn typeof val === \"undefined\";\n\t};\n\n\t/**\n\t * test if the arg is a function\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a function\n\t * @function\n\t */\n\tTone.prototype.isFunction = function(val){\n\t\treturn typeof val === \"function\";\n\t};\n\n\t/**\n\t * Test if the argument is a number.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a number\n\t */\n\tTone.prototype.isNumber = function(arg){\n\t\treturn (typeof arg === \"number\");\n\t};\n\n\t/**\n\t * Test if the given argument is an object literal (i.e. `{}`);\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an object literal.\n\t */\n\tTone.prototype.isObject = function(arg){\n\t\treturn (Object.prototype.toString.call(arg) === \"[object Object]\" && arg.constructor === Object);\n\t};\n\n\t/**\n\t * Test if the argument is a boolean.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a boolean\n\t */\n\tTone.prototype.isBoolean = function(arg){\n\t\treturn (typeof arg === \"boolean\");\n\t};\n\n\t/**\n\t * Test if the argument is an Array\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is an array\n\t */\n\tTone.prototype.isArray = function(arg){\n\t\treturn (Array.isArray(arg));\n\t};\n\n\t/**\n\t * Test if the argument is a string.\n\t * @param {*} arg the argument to test\n\t * @returns {boolean} true if the arg is a string\n\t */\n\tTone.prototype.isString = function(arg){\n\t\treturn (typeof arg === \"string\");\n\t};\n\n \t/**\n\t * An empty function.\n\t * @static\n\t */\n\tTone.noOp = function(){};\n\n\t/**\n\t * Make the property not writable. Internal use only. \n\t * @private\n\t * @param {string} property the property to make not writable\n\t */\n\tTone.prototype._readOnly = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._readOnly(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: false,\n\t\t\t\tenumerable : true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Make an attribute writeable. Interal use only. \n\t * @private\n\t * @param {string} property the property to make writable\n\t */\n\tTone.prototype._writable = function(property){\n\t\tif (Array.isArray(property)){\n\t\t\tfor (var i = 0; i < property.length; i++){\n\t\t\t\tthis._writable(property[i]);\n\t\t\t}\n\t\t} else {\n\t\t\tObject.defineProperty(this, property, { \n\t\t\t\twritable: true,\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * Possible play states. \n\t * @enum {string}\n\t */\n\tTone.State = {\n\t\tStarted : \"started\",\n\t\tStopped : \"stopped\",\n\t\tPaused : \"paused\",\n \t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Equal power gain scale. Good for cross-fading.\n\t * @param {NormalRange} percent (0-1)\n\t * @return {Number} output gain (0-1)\n\t */\n\tTone.prototype.equalPowerScale = function(percent){\n\t\tvar piFactor = 0.5 * Math.PI;\n\t\treturn Math.sin(percent * piFactor);\n\t};\n\n\t/**\n\t * Convert decibels into gain.\n\t * @param {Decibels} db\n\t * @return {Number} \n\t */\n\tTone.prototype.dbToGain = function(db) {\n\t\treturn Math.pow(2, db / 6);\n\t};\n\n\t/**\n\t * Convert gain to decibels.\n\t * @param {Number} gain (0-1)\n\t * @return {Decibels} \n\t */\n\tTone.prototype.gainToDb = function(gain) {\n\t\treturn 20 * (Math.log(gain) / Math.LN10);\n\t};\n\n\t/**\n\t * Convert an interval (in semitones) to a frequency ratio.\n\t * @param {Interval} interval the number of semitones above the base note\n\t * @return {number} the frequency ratio\n\t * @example\n\t * tone.intervalToFrequencyRatio(0); // 1\n\t * tone.intervalToFrequencyRatio(12); // 2\n\t * tone.intervalToFrequencyRatio(-12); // 0.5\n\t */\n\tTone.prototype.intervalToFrequencyRatio = function(interval){\n\t\treturn Math.pow(2,(interval/12));\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTIMING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t */\n\tTone.prototype.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t/**\n\t * Return the current time of the AudioContext clock.\n\t * @return {Number} the currentTime from the AudioContext\n\t * @static\n\t */\n\tTone.now = function(){\n\t\treturn Tone.context.now();\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tINHERITANCE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * have a child inherit all of Tone's (or a parent's) prototype\n\t * to inherit the parent's properties, make sure to call \n\t * Parent.call(this) in the child's constructor\n\t *\n\t * based on closure library's inherit function\n\t *\n\t * @static\n\t * @param {function} \tchild \n\t * @param {function=} parent (optional) parent to inherit from\n\t * if no parent is supplied, the child\n\t * will inherit from Tone\n\t */\n\tTone.extend = function(child, parent){\n\t\tif (Tone.prototype.isUndef(parent)){\n\t\t\tparent = Tone;\n\t\t}\n\t\tfunction TempConstructor(){}\n\t\tTempConstructor.prototype = parent.prototype;\n\t\tchild.prototype = new TempConstructor();\n\t\t/** @override */\n\t\tchild.prototype.constructor = child;\n\t\tchild._super = parent;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tCONTEXT\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The private audio context shared by all Tone Nodes. \n\t * @private\n\t * @type {Tone.Context|undefined}\n\t */\n\tvar audioContext;\n\n\t/**\n\t * A static pointer to the audio context accessible as Tone.context. \n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone\n\t */\n\tObject.defineProperty(Tone, \"context\", {\n\t\tget : function(){\n\t\t\treturn audioContext;\n\t\t},\n\t\tset : function(context){\n\t\t\tif (Tone.Context && context instanceof Tone.Context){\n\t\t\t\taudioContext = context;\n\t\t\t} else {\n\t\t\t\taudioContext = new Tone.Context(context);\n\t\t\t}\n\t\t\t//initialize the new audio context\n\t\t\tif (Tone.Context){\n\t\t\t\tTone.Context.emit(\"init\", audioContext);\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * The AudioContext\n\t * @type {Tone.Context}\n\t * @name context\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"context\", {\n\t\tget : function(){\n\t\t\treturn Tone.context;\n\t\t}\n\t});\n\n\t/**\n\t * Tone automatically creates a context on init, but if you are working\n\t * with other libraries which also create an AudioContext, it can be\n\t * useful to set your own. If you are going to set your own context, \n\t * be sure to do it at the start of your code, before creating any objects.\n\t * @static\n\t * @param {AudioContext} ctx The new audio context to set\n\t */\n\tTone.setContext = function(ctx){\n\t\tTone.context = ctx;\n\t};\n\n\t/**\n\t * The number of seconds of 1 processing block (128 samples)\n\t * @type {Number}\n\t * @name blockTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"blockTime\", {\n\t\tget : function(){\n\t\t\treturn 128 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * The duration in seconds of one sample.\n\t * @type {Number}\n\t * @name sampleTime\n\t * @memberOf Tone#\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.prototype, \"sampleTime\", {\n\t\tget : function(){\n\t\t\treturn 1 / this.context.sampleRate;\n\t\t}\n\t});\n\n\t/**\n\t * Whether or not all the technologies that Tone.js relies on are supported by the current browser. \n\t * @type {Boolean}\n\t * @name supported\n\t * @memberOf Tone\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone, \"supported\", {\n\t\tget : function(){\n\t\t\tvar hasAudioContext = window.hasOwnProperty(\"AudioContext\") || window.hasOwnProperty(\"webkitAudioContext\");\n\t\t\tvar hasPromises = window.hasOwnProperty(\"Promise\");\n\t\t\tvar hasWorkers = window.hasOwnProperty(\"Worker\");\n\t\t\treturn hasAudioContext && hasPromises && hasWorkers;\n\t\t}\n\t});\n\n\tTone.version = \"r10\";\n\n\t// allow optional silencing of this log\n\tif (!window.TONE_SILENCE_VERSION_LOGGING) {\n\t\tconsole.log(\"%c * Tone.js \" + Tone.version + \" * \", \"background: #000; color: #fff\");\n\t}\n\n\treturn Tone;\n});\n","'use strict';\r\n\r\n\r\ndefine(['audiocontext'], function (audiocontext) {\r\n /**\r\n * Master contains AudioContext and the master sound output.\r\n * @for p5\r\n */\r\n var Master = function() {\r\n this.input = audiocontext.createGain();\r\n this.output = audiocontext.createGain();\r\n\r\n //put a hard limiter on the output\r\n this.limiter = audiocontext.createDynamicsCompressor();\r\n this.limiter.threshold.value = -3;\r\n this.limiter.ratio.value = 20;\r\n this.limiter.knee.value = 1;\r\n\r\n this.audiocontext = audiocontext;\r\n\r\n this.output.disconnect();\r\n\r\n // connect input to limiter\r\n this.input.connect(this.limiter);\r\n\r\n // connect limiter to output\r\n this.limiter.connect(this.output);\r\n\r\n // meter is just for global Amplitude / FFT analysis\r\n this.meter = audiocontext.createGain();\r\n this.fftMeter = audiocontext.createGain();\r\n this.output.connect(this.meter);\r\n this.output.connect(this.fftMeter);\r\n\r\n // connect output to destination\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // an array of all sounds in the sketch\r\n this.soundArray = [];\r\n // an array of all musical parts in the sketch\r\n this.parts = [];\r\n\r\n // file extensions to search for\r\n this.extensions = [];\r\n };\r\n\r\n // create a single instance of the p5Sound / master output for use within this sketch\r\n var p5sound = new Master();\r\n\r\n /**\r\n * Returns a number representing the master amplitude (volume) for sound\r\n * in this sketch.\r\n *\r\n * @method getMasterVolume\r\n * @return {Number} Master amplitude (volume) for sound in this sketch.\r\n * Should be between 0.0 (silence) and 1.0.\r\n */\r\n p5.prototype.getMasterVolume = function() {\r\n return p5sound.output.gain.value;\r\n };\r\n\r\n /**\r\n *
Scale the output of all sound in this sketch
\r\n * Scaled between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n *
How This Works: When you load the p5.sound module, it\r\n * creates a single instance of p5sound. All sound objects in this\r\n * module output to p5sound before reaching your computer's output.\r\n * So if you change the amplitude of p5sound, it impacts all of the\r\n * sound in this module.
\r\n *\r\n *
If no value is provided, returns a Web Audio API Gain Node
\r\n *\r\n * @method masterVolume\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.prototype.masterVolume = function(vol, rampTime, tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = p5sound.output.gain.value;\r\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(p5sound.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return p5sound.output.gain;\r\n }\r\n };\r\n\r\n /**\r\n * `p5.soundOut` is the p5.sound master output. It sends output to\r\n * the destination of this window's web audio context. It contains\r\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\r\n * and Gain Nodes for .input and .output.\r\n *\r\n * @property {Object} soundOut\r\n */\r\n p5.prototype.soundOut = p5.soundOut = p5sound;\r\n\r\n /**\r\n * a silent connection to the DesinationNode\r\n * which will ensure that anything connected to it\r\n * will not be garbage collected\r\n *\r\n * @private\r\n */\r\n p5.soundOut._silentNode = p5sound.audiocontext.createGain();\r\n p5.soundOut._silentNode.gain.value = 0;\r\n p5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\r\n\r\n\r\n return p5sound;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/type/Type\", \"Tone/core/Param\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal is an audio-rate value. Tone.Signal is a core component of the library.\n\t * Unlike a number, Signals can be scheduled with sample-level accuracy. Tone.Signal\n\t * has all of the methods available to native Web Audio \n\t * [AudioParam](http://webaudio.github.io/web-audio-api/#the-audioparam-interface)\n\t * as well as additional conveniences. Read more about working with signals \n\t * [here](https://github.com/Tonejs/Tone.js/wiki/Signals).\n\t *\n\t * @constructor\n\t * @extends {Tone.Param}\n\t * @param {Number|AudioParam} [value] Initial value of the signal. If an AudioParam\n\t * is passed in, that parameter will be wrapped\n\t * and controlled by the Signal. \n\t * @param {string} [units=Number] unit The units the signal is in. \n\t * @example\n\t * var signal = new Tone.Signal(10);\n\t */\n\tTone.Signal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\n\t\t/**\n\t\t * The node where the constant signal value is scaled.\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.output = this._gain = this.context.createGain();\n\n\t\toptions.param = this._gain.gain;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The node where the value is set.\n\t\t * @type {Tone.Param}\n\t\t * @private\n\t\t */\n\t\tthis.input = this._param = this._gain.gain;\n\n\t\t//connect the const output to the node output\n\t\tthis.context.getConstant(1).chain(this._gain);\n\t};\n\n\tTone.extend(Tone.Signal, Tone.Param);\n\n\t/**\n\t * The default values\n\t * @type {Object}\n\t * @static\n\t * @const\n\t */\n\tTone.Signal.defaults = {\n\t\t\"value\" : 0,\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t * @method\n\t */\n\tTone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\t/**\n\t * dispose and disconnect\n\t * @returns {Tone.Signal} this\n\t */\n\tTone.Signal.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tthis._gain.disconnect();\n\t\tthis._gain = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Signal;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Multiply two incoming signals. Or, if a number is given in the constructor, \n\t * multiplies the incoming signal by that value. \n\t *\n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value Constant value to multiple. If no value is provided,\n\t * it will return the product of the first and second inputs\n\t * @example\n\t * var mult = new Tone.Multiply();\n\t * var sigA = new Tone.Signal(3);\n\t * var sigB = new Tone.Signal(4);\n\t * sigA.connect(mult, 0, 0);\n\t * sigB.connect(mult, 0, 1);\n\t * //output of mult is 12.\n\t * @example\n\t * var mult = new Tone.Multiply(10);\n\t * var sig = new Tone.Signal(2).connect(mult);\n\t * //the output of mult is 20. \n\t */\n\tTone.Multiply = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the input node is the same as the output node\n\t\t * it is also the GainNode which handles the scaling of incoming signal\n\t\t * \n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._mult = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * the scaling parameter\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[1] = this.output.gain;\n\t\t\n\t\tthis._param.value = this.defaultArg(value, 0);\n\t};\n\n\tTone.extend(Tone.Multiply, Tone.Signal);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Multiply} this\n\t */\n\tTone.Multiply.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._mult.dispose();\n\t\tthis._mult = null;\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Multiply;\n});\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var CrossFade = require('Tone/component/CrossFade');\r\n\r\n /**\r\n * Effect is a base class for audio effects in p5. \r\n * This module handles the nodes and methods that are\r\n * common and useful for current and future effects.\r\n *\r\n *\r\n * This class is extended by p5.Distortion,\r\n * p5.Compressor,\r\n * p5.Delay,\r\n * p5.Filter,\r\n * p5.Reverb.\r\n *\r\n * @class p5.Effect\r\n * @constructor\r\n *\r\n * @param {Object} [ac] Reference to the audio context of the p5 object\r\n * @param {AudioNode} [input] Gain Node effect wrapper\r\n * @param {AudioNode} [output] Gain Node effect wrapper\r\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\r\n * @param {AudioNode} [wet] Effects that extend this class should connect\r\n * to the wet signal to this gain node, so that dry and wet\r\n * signals are mixed properly.\r\n */\r\n p5.Effect = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n /**\r\n *\tThe p5.Effect class is built\r\n * \tusing Tone.js CrossFade\r\n * \t@private\r\n */\r\n\r\n this._drywet = new CrossFade(1);\r\n\r\n /**\r\n *\tIn classes that extend\r\n *\tp5.Effect, connect effect nodes\r\n *\tto the wet parameter\r\n */\r\n this.wet = this.ac.createGain();\r\n\r\n this.input.connect(this._drywet.a);\r\n this.wet.connect(this._drywet.b);\r\n this._drywet.connect(this.output);\r\n\r\n this.connect();\r\n\r\n //Add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the output volume of the filter.\r\n *\r\n * @method amp\r\n * @for p5.Effect\r\n * @param {Number} [vol] amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts until rampTime\r\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\r\n */\r\n p5.Effect.prototype.amp = function(vol, rampTime, tFromNow){\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + .001);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + .001);\r\n };\r\n\r\n /**\r\n * Link effects together in a chain\r\n * Example usage: filter.chain(reverb, delay, panner);\r\n * May be used with an open-ended number of arguments\r\n *\r\n * @method chain\r\n * @for p5.Effect\r\n * @param {Object} [arguments] Chain together multiple sound objects\r\n */\r\n p5.Effect.prototype.chain = function(){\r\n if (arguments.length>0){\r\n this.connect(arguments[0]);\r\n for(var i=1;i\r\n * var notes = [60, 64, 67, 72];\r\n * var i = 0;\r\n *\r\n * function setup() {\r\n * osc = new p5.Oscillator('Triangle');\r\n * osc.start();\r\n * frameRate(1);\r\n * }\r\n *\r\n * function draw() {\r\n * var freq = midiToFreq(notes[i]);\r\n * osc.freq(freq);\r\n * i++;\r\n * if (i >= notes.length){\r\n * i = 0;\r\n * }\r\n * }\r\n * \r\n */\r\n var midiToFreq = p5.prototype.midiToFreq = function(m) {\r\n return 440 * Math.pow(2, (m-69)/12.0);\r\n };\r\n\r\n // This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\r\n var noteToFreq = function(note) {\r\n if (typeof note !== 'string') {\r\n return note;\r\n }\r\n var wholeNotes = {A:21, B:23, C:24, D:26, E:28, F:29, G:31};\r\n var value = wholeNotes[ note[0].toUpperCase() ];\r\n var octave = ~~note.slice(-1);\r\n value += 12 * (octave -1);\r\n\r\n switch(note[1]) {\r\n case '#':\r\n value += 1;\r\n break;\r\n case 'b':\r\n value -= 1;\r\n break;\r\n default:\r\n break;\r\n }\r\n return midiToFreq(value);\r\n };\r\n\r\n /**\r\n * List the SoundFile formats that you will include. LoadSound\r\n * will search your directory for these extensions, and will pick\r\n * a format that is compatable with the client's web browser.\r\n * Here is a free online file\r\n * converter.\r\n *\r\n * @method soundFormats\r\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\r\n * @example\r\n *
\r\n * function preload() {\r\n * // set the global sound formats\r\n * soundFormats('mp3', 'ogg');\r\n *\r\n * // load either beatbox.mp3, or .ogg, depending on browser\r\n * mySound = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * mySound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.soundFormats = function() {\r\n // reset extensions array\r\n p5sound.extensions = [];\r\n // add extensions\r\n for (var i = 0; i < arguments.length; i++) {\r\n arguments[i] = arguments[i].toLowerCase();\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\r\n p5sound.extensions.push(arguments[i]);\r\n } else {\r\n throw arguments[i] + ' is not a valid sound format!';\r\n }\r\n }\r\n };\r\n\r\n p5.prototype.disposeSound = function() {\r\n for (var i = 0; i < p5sound.soundArray.length; i++) {\r\n p5sound.soundArray[i].dispose();\r\n }\r\n };\r\n\r\n // register removeSound to dispose of p5sound SoundFiles, Convolvers,\r\n // Oscillators etc when sketch ends\r\n p5.prototype.registerMethod('remove', p5.prototype.disposeSound);\r\n\r\n p5.prototype._checkFileFormats = function(paths) {\r\n var path;\r\n // if path is a single string, check to see if extension is provided\r\n if (typeof paths === 'string') {\r\n path = paths;\r\n // see if extension is provided\r\n var extTest = path.split('.').pop();\r\n // if an extension is provided...\r\n if (['mp3','wav','ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\r\n if (p5.prototype.isFileSupported(extTest)) {\r\n path = path;\r\n }\r\n else {\r\n var pathSplit = path.split('.');\r\n var pathCore = pathSplit[pathSplit.length - 1];\r\n for (var i = 0; i 1) {\r\n rightChannel = audioBuffer.getChannelData(1);\r\n } else {\r\n rightChannel = leftChannel;\r\n }\r\n\r\n var interleaved = interleave(leftChannel, rightChannel);\r\n\r\n // create the buffer and view to create the .WAV file\r\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\r\n var view = new window.DataView(buffer);\r\n\r\n // write the WAV container,\r\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\r\n\r\n // RIFF chunk descriptor\r\n writeUTFBytes(view, 0, 'RIFF');\r\n view.setUint32(4, 36 + interleaved.length * 2, true);\r\n writeUTFBytes(view, 8, 'WAVE');\r\n // FMT sub-chunk\r\n writeUTFBytes(view, 12, 'fmt ');\r\n view.setUint32(16, 16, true);\r\n view.setUint16(20, 1, true);\r\n // stereo (2 channels)\r\n view.setUint16(22, 2, true);\r\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\r\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\r\n view.setUint16(32, 4, true);\r\n view.setUint16(34, 16, true);\r\n // data sub-chunk\r\n writeUTFBytes(view, 36, 'data');\r\n view.setUint32(40, interleaved.length * 2, true);\r\n\r\n // write the PCM samples\r\n var lng = interleaved.length;\r\n var index = 44;\r\n var volume = 1;\r\n for (var i = 0; i < lng; i++) {\r\n view.setInt16(index, interleaved[i] * (0x7FFF * volume), true);\r\n index += 2;\r\n }\r\n\r\n return view;\r\n }\r\n\r\n // helper methods to save waves\r\n function interleave(leftChannel, rightChannel) {\r\n var length = leftChannel.length + rightChannel.length;\r\n var result = new Float32Array(length);\r\n\r\n var inputIndex = 0;\r\n\r\n for (var index = 0; index < length;) {\r\n result[index++] = leftChannel[inputIndex];\r\n result[index++] = rightChannel[inputIndex];\r\n inputIndex++;\r\n }\r\n return result;\r\n }\r\n\r\n function writeUTFBytes(view, offset, string) {\r\n var lng = string.length;\r\n for (var i = 0; i < lng; i++) {\r\n view.setUint8(offset + i, string.charCodeAt(i));\r\n }\r\n }\r\n\r\n return {\r\n convertToWav: convertToWav,\r\n midiToFreq: midiToFreq,\r\n noteToFreq: noteToFreq\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Add a signal and a number or two signals. When no value is\n\t * passed into the constructor, Tone.Add will sum input[0]\n\t * and input[1]. If a value is passed into the constructor, \n\t * the it will be added to the input.\n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number=} value If no value is provided, Tone.Add will sum the first\n\t * and second inputs. \n\t * @example\n\t * var signal = new Tone.Signal(2);\n\t * var add = new Tone.Add(2);\n\t * signal.connect(add);\n\t * //the output of add equals 4\n\t * @example\n\t * //if constructed with no arguments\n\t * //it will add the first and second inputs\n\t * var add = new Tone.Add();\n\t * var sig0 = new Tone.Signal(3).connect(add, 0, 0);\n\t * var sig1 = new Tone.Signal(4).connect(add, 0, 1);\n\t * //the output of add equals 7. \n\t */\n\tTone.Add = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.connect(this._sum);\n\t};\n\n\tTone.extend(Tone.Add, Tone.Signal);\n\t\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Add} this\n\t */\n\tTone.Add.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._sum.dispose();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Add;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\", \"Tone/type/Frequency\", \"Tone/type/TransportTime\", \"Tone/core/Context\"],\nfunction (Tone) {\t\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tTYPES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Units which a value can take on.\n\t * @enum {String}\n\t */\n\tTone.Type = {\n\t\t/** \n\t\t * Default units\n\t\t * @typedef {Default}\n\t\t */\n\t\tDefault : \"number\",\n\t\t/**\n\t\t * Time can be described in a number of ways. Read more [Time](https://github.com/Tonejs/Tone.js/wiki/Time).\n\t\t *\n\t\t *
\n\t\t *
Numbers, which will be taken literally as the time (in seconds).
\n\t\t *
Notation, (\"4n\", \"8t\") describes time in BPM and time signature relative values.
\n\t\t *
TransportTime, (\"4:3:2\") will also provide tempo and time signature relative times \n\t\t * in the form BARS:QUARTERS:SIXTEENTHS.
\n\t\t *
Frequency, (\"8hz\") is converted to the length of the cycle in seconds.
\n\t\t *
Now-Relative, (\"+1\") prefix any of the above with \"+\" and it will be interpreted as \n\t\t * \"the current time plus whatever expression follows\".
\n\t\t *
Expressions, (\"3:0 + 2 - (1m / 7)\") any of the above can also be combined \n\t\t * into a mathematical expression which will be evaluated to compute the desired time.
\n\t\t *
No Argument, for methods which accept time, no argument will be interpreted as \n\t\t * \"now\" (i.e. the currentTime).
\n\t\t *
\n\t\t * \n\t\t * @typedef {Time}\n\t\t */\n\t\tTime : \"time\",\n\t\t/**\n\t\t * Frequency can be described similar to time, except ultimately the\n\t\t * values are converted to frequency instead of seconds. A number\n\t\t * is taken literally as the value in hertz. Additionally any of the \n\t\t * Time encodings can be used. Note names in the form\n\t\t * of NOTE OCTAVE (i.e. C4) are also accepted and converted to their\n\t\t * frequency value. \n\t\t * @typedef {Frequency}\n\t\t */\n\t\tFrequency : \"frequency\",\n\t\t/**\n\t\t * TransportTime describes a position along the Transport's timeline. It is\n\t\t * similar to Time in that it uses all the same encodings, but TransportTime specifically\n\t\t * pertains to the Transport's timeline, which is startable, stoppable, loopable, and seekable. \n\t\t * [Read more](https://github.com/Tonejs/Tone.js/wiki/TransportTime)\n\t\t * @typedef {TransportTime}\n\t\t */\n\t\tTransportTime : \"transportTime\",\n\t\t/** \n\t\t * Ticks are the basic subunit of the Transport. They are\n\t\t * the smallest unit of time that the Transport supports.\n\t\t * @typedef {Ticks}\n\t\t */\n\t\tTicks : \"ticks\",\n\t\t/** \n\t\t * Normal values are within the range [0, 1].\n\t\t * @typedef {NormalRange}\n\t\t */\n\t\tNormalRange : \"normalRange\",\n\t\t/** \n\t\t * AudioRange values are between [-1, 1].\n\t\t * @typedef {AudioRange}\n\t\t */\n\t\tAudioRange : \"audioRange\",\n\t\t/** \n\t\t * Decibels are a logarithmic unit of measurement which is useful for volume\n\t\t * because of the logarithmic way that we perceive loudness. 0 decibels \n\t\t * means no change in volume. -10db is approximately half as loud and 10db \n\t\t * is twice is loud. \n\t\t * @typedef {Decibels}\n\t\t */\n\t\tDecibels : \"db\",\n\t\t/** \n\t\t * Half-step note increments, i.e. 12 is an octave above the root. and 1 is a half-step up.\n\t\t * @typedef {Interval}\n\t\t */\n\t\tInterval : \"interval\",\n\t\t/** \n\t\t * Beats per minute. \n\t\t * @typedef {BPM}\n\t\t */\n\t\tBPM : \"bpm\",\n\t\t/** \n\t\t * The value must be greater than or equal to 0.\n\t\t * @typedef {Positive}\n\t\t */\n\t\tPositive : \"positive\",\n\t\t/** \n\t\t * A cent is a hundredth of a semitone. \n\t\t * @typedef {Cents}\n\t\t */\n\t\tCents : \"cents\",\n\t\t/** \n\t\t * Angle between 0 and 360. \n\t\t * @typedef {Degrees}\n\t\t */\n\t\tDegrees : \"degrees\",\n\t\t/** \n\t\t * A number representing a midi note.\n\t\t * @typedef {MIDI}\n\t\t */\n\t\tMIDI : \"midi\",\n\t\t/** \n\t\t * A colon-separated representation of time in the form of\n\t\t * Bars:Beats:Sixteenths. \n\t\t * @typedef {BarsBeatsSixteenths}\n\t\t */\n\t\tBarsBeatsSixteenths : \"barsBeatsSixteenths\",\n\t\t/** \n\t\t * Sampling is the reduction of a continuous signal to a discrete signal.\n\t\t * Audio is typically sampled 44100 times per second. \n\t\t * @typedef {Samples}\n\t\t */\n\t\tSamples : \"samples\",\n\t\t/** \n\t\t * Hertz are a frequency representation defined as one cycle per second.\n\t\t * @typedef {Hertz}\n\t\t */\n\t\tHertz : \"hertz\",\n\t\t/** \n\t\t * A frequency represented by a letter name, \n\t\t * accidental and octave. This system is known as\n\t\t * [Scientific Pitch Notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation).\n\t\t * @typedef {Note}\n\t\t */\n\t\tNote : \"note\",\n\t\t/** \n\t\t * One millisecond is a thousandth of a second. \n\t\t * @typedef {Milliseconds}\n\t\t */\n\t\tMilliseconds : \"milliseconds\",\n\t\t/** \n\t\t * Seconds are the time unit of the AudioContext. In the end, \n\t\t * all values need to be evaluated to seconds. \n\t\t * @typedef {Seconds}\n\t\t */\n\t\tSeconds : \"seconds\",\n\t\t/** \n\t\t * A string representing a duration relative to a measure. \n\t\t *
\n\t\t * \t
\"4n\" = quarter note
\n\t\t * \t
\"2m\" = two measures
\n\t\t * \t
\"8t\" = eighth-note triplet
\n\t\t *
\n\t\t * @typedef {Notation}\n\t\t */\n\t\tNotation : \"notation\",\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// AUGMENT TONE's PROTOTYPE\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert Time into seconds.\n\t * \n\t * Unlike the method which it overrides, this takes into account \n\t * transporttime and musical notation.\n\t *\n\t * Time : 1.40\n\t * Notation: 4n|1m|2t\n\t * Now Relative: +3n\n\t * Math: 3n+16n or even complicated expressions ((3n*2)/6 + 1)\n\t *\n\t * @param {Time} time \n\t * @return {Seconds} \n\t */\n\tTone.prototype.toSeconds = function(time){\n\t\tif (this.isNumber(time)){\n\t\t\treturn time;\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn this.now();\t\t\t\n\t\t} else if (this.isString(time)){\n\t\t\treturn (new Tone.Time(time)).toSeconds();\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toSeconds();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a frequency representation into a number.\n\t * @param {Frequency} freq \n\t * @return {Hertz} the frequency in hertz\n\t */\n\tTone.prototype.toFrequency = function(freq){\n\t\tif (this.isNumber(freq)){\n\t\t\treturn freq;\n\t\t} else if (this.isString(freq) || this.isUndef(freq)){\n\t\t\treturn (new Tone.Frequency(freq)).valueOf();\n\t\t} else if (freq instanceof Tone.TimeBase){\n\t\t\treturn freq.toFrequency();\n\t\t}\n\t};\n\n\t/**\n\t * Convert a time representation into ticks.\n\t * @param {Time} time\n\t * @return {Ticks} the time in ticks\n\t */\n\tTone.prototype.toTicks = function(time){\n\t\tif (this.isNumber(time) || this.isString(time)){\n\t\t\treturn (new Tone.TransportTime(time)).toTicks();\n\t\t} else if (this.isUndef(time)){\n\t\t\treturn Tone.Transport.ticks;\t\t\t\n\t\t} else if (time instanceof Tone.TimeBase){\n\t\t\treturn time.toTicks();\n\t\t}\n\t};\n\n\treturn Tone;\n});","define([\"Tone/core/Tone\", \"Tone/core/Param\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * createGain shim\n\t * @private\n\t */\n\tif (window.GainNode && !AudioContext.prototype.createGain){\n\t\tAudioContext.prototype.createGain = AudioContext.prototype.createGainNode;\n\t}\n\n\t/**\n\t * @class A thin wrapper around the Native Web Audio GainNode.\n\t * The GainNode is a basic building block of the Web Audio\n\t * API and is useful for routing audio and adjusting gains. \n\t * @extends {Tone}\n\t * @param {Number=} gain The initial gain of the GainNode\n\t * @param {Tone.Type=} units The units of the gain parameter. \n\t */\n\tTone.Gain = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"gain\", \"units\"], Tone.Gain.defaults);\n\n\t\t/**\n\t\t * The GainNode\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis.input = this.output = this._gainNode = this.context.createGain();\n\n\t\t/**\n\t\t * The gain parameter of the gain node.\n\t\t * @type {Tone.Param}\n\t\t * @signal\n\t\t */\n\t\tthis.gain = new Tone.Param({\n\t\t\t\"param\" : this._gainNode.gain, \n\t\t\t\"units\" : options.units,\n\t\t\t\"value\" : options.gain,\n\t\t\t\"convert\" : options.convert\n\t\t});\n\t\tthis._readOnly(\"gain\");\n\t};\n\n\tTone.extend(Tone.Gain);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Gain.defaults = {\n\t\t\"gain\" : 1,\n\t\t\"convert\" : true,\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Gain} this\n\t */\n\tTone.Gain.prototype.dispose = function(){\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._gainNode.disconnect();\n\t\tthis._gainNode = null;\n\t\tthis._writable(\"gain\");\n\t\tthis.gain.dispose();\n\t\tthis.gain = null;\n\t};\n\n\t//STATIC///////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Create input and outputs for this object.\n\t * @param {Number} input The number of inputs\n\t * @param {Number=} outputs The number of outputs\n\t * @return {Tone} this\n\t * @internal\n\t */\n\tTone.prototype.createInsOuts = function(inputs, outputs){\n\n\t\tif (inputs === 1){\n\t\t\tthis.input = new Tone.Gain();\n\t\t} else if (inputs > 1){\n\t\t\tthis.input = new Array(inputs);\n\t\t}\n\n\t\tif (outputs === 1){\n\t\t\tthis.output = new Tone.Gain();\n\t\t} else if (outputs > 1){\n\t\t\tthis.output = new Array(inputs);\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\n\treturn Tone.Gain;\n});","'use strict';\r\n\r\ndefine(function () {\r\n /*\r\n Helper function to generate an error\r\n with a custom stack trace that points to the sketch\r\n and removes other parts of the stack trace.\r\n\r\n @private\r\n @class customError\r\n @constructor\r\n @param {String} name custom error name\r\n @param {String} errorTrace custom error trace\r\n @param {String} failedPath path to the file that failed to load\r\n @property {String} name custom error name\r\n @property {String} message custom error message\r\n @property {String} stack trace the error back to a line in the user's sketch.\r\n Note: this edits out stack trace within p5.js and p5.sound.\r\n @property {String} originalStack unedited, original stack trace\r\n @property {String} failedPath path to the file that failed to load\r\n @return {Error} returns a custom Error object\r\n */\r\n var CustomError = function(name, errorTrace, failedPath) {\r\n var err = new Error();\r\n var tempStack, splitStack;\r\n\r\n err.name = name;\r\n err.originalStack = err.stack + errorTrace;\r\n tempStack = err.stack + errorTrace;\r\n err.failedPath = failedPath;\r\n\r\n // only print the part of the stack trace that refers to the user code:\r\n var splitStack = tempStack.split('\\n');\r\n splitStack = splitStack.filter(function(ln) {\r\n return !ln.match(/(p5.|native code|globalInit)/g);\r\n });\r\n err.stack = splitStack.join('\\n');\r\n\r\n return err; // TODO: is this really a constructor?\r\n };\r\n\r\n return CustomError;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Emitter\"], function (Tone) {\n\n\t/**\n\t * shim\n\t * @private\n\t */\n\tif (!window.hasOwnProperty(\"AudioContext\") && window.hasOwnProperty(\"webkitAudioContext\")){\n\t\twindow.AudioContext = window.webkitAudioContext;\n\t}\n\n\t/**\n\t * @class Wrapper around the native AudioContext.\n\t * @extends {Tone.Emitter}\n\t * @param {AudioContext=} context optionally pass in a context\n\t */\n\tTone.Context = function(context){\n\n\t\tTone.Emitter.call(this);\n\n\t\tif (!context){\n\t\t\tcontext = new window.AudioContext();\n\t\t}\n\t\tthis._context = context;\n\t\t// extend all of the methods\n\t\tfor (var prop in this._context){\n\t\t\tthis._defineProperty(this._context, prop);\n\t\t}\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// WORKER\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\t/**\n\t\t * The default latency hint\n\t\t * @type {String}\n\t\t * @private\n\t\t */\n\t\tthis._latencyHint = \"interactive\";\n\n\t\t/**\n\t\t * The amount of time events are scheduled\n\t\t * into the future\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._lookAhead = 0.1;\n\n\t\t/**\n\t\t * How often the update look runs\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._updateInterval = this._lookAhead/3;\n\n\t\t/**\n\t\t * A reference to the actual computed update interval\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._computedUpdateInterval = 0;\n\n\t\t/**\n\t\t * The web worker which is used to update Tone.Clock\n\t\t * @private\n\t\t * @type {WebWorker}\n\t\t */\n\t\tthis._worker = this._createWorker();\n\n\t\t/**\n\t\t * An object containing all of the constants AudioBufferSourceNodes\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t\tthis._constants = {};\n\n\t};\n\n\tTone.extend(Tone.Context, Tone.Emitter);\n\tTone.Emitter.mixin(Tone.Context);\n\n\t/**\n\t * Define a property on this Tone.Context. \n\t * This is used to extend the native AudioContext\n\t * @param {AudioContext} context\n\t * @param {String} prop \n\t * @private\n\t */\n\tTone.Context.prototype._defineProperty = function(context, prop){\n\t\tif (this.isUndef(this[prop])){\n\t\t\tObject.defineProperty(this, prop, {\n\t\t\t\tget : function(){\n\t\t\t\t\tif (typeof context[prop] === \"function\"){\n\t\t\t\t\t\treturn context[prop].bind(context);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn context[prop];\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tset : function(val){\n\t\t\t\t\tcontext[prop] = val;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t/**\n\t * The current audio context time\n\t * @return {Number}\n\t */\n\tTone.Context.prototype.now = function(){\n\t\treturn this._context.currentTime;\n\t};\n\n\t/**\n\t * Generate a web worker\n\t * @return {WebWorker}\n\t * @private\n\t */\n\tTone.Context.prototype._createWorker = function(){\n\t\t\n\t\t//URL Shim\n\t\twindow.URL = window.URL || window.webkitURL;\n\n\t\tvar blob = new Blob([\n\t\t\t//the initial timeout time\n\t\t\t\"var timeoutTime = \"+(this._updateInterval * 1000).toFixed(1)+\";\" +\n\t\t\t//onmessage callback\n\t\t\t\"self.onmessage = function(msg){\" +\n\t\t\t\"\ttimeoutTime = parseInt(msg.data);\" + \n\t\t\t\"};\" + \n\t\t\t//the tick function which posts a message\n\t\t\t//and schedules a new tick\n\t\t\t\"function tick(){\" +\n\t\t\t\"\tsetTimeout(tick, timeoutTime);\" +\n\t\t\t\"\tself.postMessage('tick');\" +\n\t\t\t\"}\" +\n\t\t\t//call tick initially\n\t\t\t\"tick();\"\n\t\t]);\n\t\tvar blobUrl = URL.createObjectURL(blob);\n\t\tvar worker = new Worker(blobUrl);\n\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\t// tick the clock\n\t\t\tthis.emit(\"tick\");\n\t\t}.bind(this));\n\n\t\t//lag compensation\n\t\tworker.addEventListener(\"message\", function(){\n\t\t\tvar now = this.now();\n\t\t\tif (this.isNumber(this._lastUpdate)){\n\t\t\t\tvar diff = now - this._lastUpdate;\n\t\t\t\tthis._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);\n\t\t\t}\n\t\t\tthis._lastUpdate = now;\n\t\t}.bind(this));\n\n\t\treturn worker;\n\t};\n\n\t/**\n\t * Generate a looped buffer at some constant value.\n\t * @param {Number} val\n\t * @return {BufferSourceNode}\n\t */\n\tTone.Context.prototype.getConstant = function(val){\n\t\tif (this._constants[val]){\n\t\t\treturn this._constants[val];\n\t\t} else {\n\t\t\tvar buffer = this._context.createBuffer(1, 128, this._context.sampleRate);\n\t\t\tvar arr = buffer.getChannelData(0);\n\t\t\tfor (var i = 0; i < arr.length; i++){\n\t\t\t\tarr[i] = val;\n\t\t\t}\n\t\t\tvar constant = this._context.createBufferSource();\n\t\t\tconstant.channelCount = 1;\n\t\t\tconstant.channelCountMode = \"explicit\";\n\t\t\tconstant.buffer = buffer;\n\t\t\tconstant.loop = true;\n\t\t\tconstant.start(0);\n\t\t\tthis._constants[val] = constant;\n\t\t\treturn constant;\n\t\t}\n\t};\n\n\t/**\n\t * This is the time that the clock is falling behind\n\t * the scheduled update interval. The Context automatically\n\t * adjusts for the lag and schedules further in advance.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lag\n\t * @static\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lag\", {\n\t\tget : function(){\n\t\t\tvar diff = this._computedUpdateInterval - this._updateInterval;\n\t\t\tdiff = Math.max(diff, 0);\n\t\t\treturn diff;\n\t\t}\n\t});\n\n\t/**\n\t * The amount of time in advance that events are scheduled.\n\t * The lookAhead will adjust slightly in response to the \n\t * measured update time to try to avoid clicks.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name lookAhead\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"lookAhead\", {\n\t\tget : function(){\n\t\t\treturn this._lookAhead;\n\t\t},\n\t\tset : function(lA){\n\t\t\tthis._lookAhead = lA;\n\t\t}\n\t});\n\n\t/**\n\t * How often the Web Worker callback is invoked.\n\t * This number corresponds to how responsive the scheduling\n\t * can be. Context.updateInterval + Context.lookAhead gives you the\n\t * total latency between scheduling an event and hearing it.\n\t * @type {Number}\n\t * @memberOf Tone.Context\n\t * @name updateInterval\n\t * @static\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"updateInterval\", {\n\t\tget : function(){\n\t\t\treturn this._updateInterval;\n\t\t},\n\t\tset : function(interval){\n\t\t\tthis._updateInterval = Math.max(interval, Tone.prototype.blockTime);\n\t\t\tthis._worker.postMessage(Math.max(interval * 1000, 1));\n\t\t}\n\t});\n\n\t/**\n\t * The type of playback, which affects tradeoffs between audio \n\t * output latency and responsiveness. \n\t * \n\t * In addition to setting the value in seconds, the latencyHint also\n\t * accepts the strings \"interactive\" (prioritizes low latency), \n\t * \"playback\" (prioritizes sustained playback), \"balanced\" (balances\n\t * latency and performance), and \"fastest\" (lowest latency, might glitch more often). \n\t * @type {String|Seconds}\n\t * @memberOf Tone.Context#\n\t * @name latencyHint\n\t * @static\n\t * @example\n\t * //set the lookAhead to 0.3 seconds\n\t * Tone.context.latencyHint = 0.3;\n\t */\n\tObject.defineProperty(Tone.Context.prototype, \"latencyHint\", {\n\t\tget : function(){\n\t\t\treturn this._latencyHint;\n\t\t},\n\t\tset : function(hint){\n\t\t\tvar lookAhead = hint;\n\t\t\tthis._latencyHint = hint;\n\t\t\tif (this.isString(hint)){\n\t\t\t\tswitch(hint){\n\t\t\t\t\tcase \"interactive\" :\n\t\t\t\t\t\tlookAhead = 0.1;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"playback\" :\n\t\t\t\t\t\tlookAhead = 0.8;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"balanced\" :\n\t\t\t\t\t\tlookAhead = 0.25;\n\t\t\t\t\t\tthis._context.latencyHint = hint;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"fastest\" :\n\t\t\t\t\t\tlookAhead = 0.01;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.lookAhead = lookAhead;\n\t\t\tthis.updateInterval = lookAhead/3;\n\t\t}\n\t});\n\n\t/**\n\t * Shim all connect/disconnect and some deprecated methods which are still in\n\t * some older implementations.\n\t * @private\n\t */\n\tfunction shimConnect(){\n\n\t\tvar nativeConnect = AudioNode.prototype.connect;\n\t\tvar nativeDisconnect = AudioNode.prototype.disconnect;\n\n\t\t//replace the old connect method\n\t\tfunction toneConnect(B, outNum, inNum){\n\t\t\tif (B.input){\n\t\t\t\tif (Array.isArray(B.input)){\n\t\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\t\tinNum = 0;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connect(B.input[inNum]);\n\t\t\t\t} else {\n\t\t\t\t\tthis.connect(B.input, outNum, inNum);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (B instanceof AudioNode){\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum, inNum);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnativeConnect.call(this, B, outNum);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error connecting to node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//replace the old disconnect method\n\t\tfunction toneDisconnect(B, outNum, inNum){\n\t\t\tif (B && B.input && Array.isArray(B.input)){\n\t\t\t\tif (Tone.prototype.isUndef(inNum)){\n\t\t\t\t\tinNum = 0;\n\t\t\t\t}\n\t\t\t\tthis.disconnect(B.input[inNum], outNum, inNum);\n\t\t\t} else if (B && B.input){\n\t\t\t\tthis.disconnect(B.input, outNum, inNum);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tnativeDisconnect.apply(this, arguments);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\"error disconnecting node: \"+B+\"\\n\"+e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (AudioNode.prototype.connect !== toneConnect){\n\t\t\tAudioNode.prototype.connect = toneConnect;\n\t\t\tAudioNode.prototype.disconnect = toneDisconnect;\n\t\t}\n\t}\n\n\t// set the audio context initially\n\tif (Tone.supported){\n\t\tshimConnect();\n\t\tTone.context = new Tone.Context();\n\t} else {\n\t\tconsole.warn(\"This browser does not support Tone.js\");\n\t}\n\n\treturn Tone.Context;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\t\n\t/**\n\t * @class Performs a linear scaling on an input signal.\n\t * Scales a NormalRange input to between\n\t * outputMin and outputMax.\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {number} [outputMin=0] The output value when the input is 0. \n\t * @param {number} [outputMax=1]\tThe output value when the input is 1. \n\t * @example\n\t * var scale = new Tone.Scale(50, 100);\n\t * var signal = new Tone.Signal(0.5).connect(scale);\n\t * //the output of scale equals 75\n\t */\n\tTone.Scale = function(outputMin, outputMax){\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMin = this.defaultArg(outputMin, 0);\n\n\t\t/** \n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._outputMax = this.defaultArg(outputMax, 1);\n\n\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(1);\n\t\t\n\t\t/** \n\t\t * @private\n\t\t * @type {Tone.Add}\n\t\t * @private\n\t\t */\n\t\tthis._add = this.output = new Tone.Add(0);\n\n\t\tthis._scale.connect(this._add);\n\t\tthis._setRange();\n\t};\n\n\tTone.extend(Tone.Scale, Tone.SignalBase);\n\n\t/**\n\t * The minimum output value. This number is output when \n\t * the value input value is 0. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name min\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"min\", {\n\t\tget : function(){\n\t\t\treturn this._outputMin;\n\t\t},\n\t\tset : function(min){\n\t\t\tthis._outputMin = min;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * The maximum output value. This number is output when \n\t * the value input value is 1. \n\t * @memberOf Tone.Scale#\n\t * @type {number}\n\t * @name max\n\t */\n\tObject.defineProperty(Tone.Scale.prototype, \"max\", {\n\t\tget : function(){\n\t\t\treturn this._outputMax;\n\t\t},\n\t\tset : function(max){\n\t\t\tthis._outputMax = max;\n\t\t\tthis._setRange();\n\t\t}\n\t});\n\n\t/**\n\t * set the values\n\t * @private\n\t */\n\tTone.Scale.prototype._setRange = function() {\n\t\tthis._add.value = this._outputMin;\n\t\tthis._scale.value = this._outputMax - this._outputMin;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Scale} this\n\t */\n\tTone.Scale.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._add.dispose();\n\t\tthis._add = null;\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Scale;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/core/Timeline\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A signal which adds the method getValueAtTime. \n\t * Code and inspiration from https://github.com/jsantell/web-audio-automation-timeline\n\t * @extends {Tone.Param}\n\t * @param {Number=} value The initial value of the signal\n\t * @param {String=} units The conversion units of the signal.\n\t */\n\tTone.TimelineSignal = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"value\", \"units\"], Tone.Signal.defaults);\n\t\t\n\t\t/**\n\t\t * The scheduled events\n\t\t * @type {Tone.Timeline}\n\t\t * @private\n\t\t */\n\t\tthis._events = new Tone.Timeline(10);\n\n\t\t//constructors\n\t\tTone.Signal.apply(this, options);\n\t\toptions.param = this._param;\n\t\tTone.Param.call(this, options);\n\n\t\t/**\n\t\t * The initial scheduled value\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._initial = this._fromUnits(this._param.value);\n\t};\n\n\tTone.extend(Tone.TimelineSignal, Tone.Param);\n\n\t/**\n\t * The event types of a schedulable signal.\n\t * @enum {String}\n\t * @private\n\t */\n\tTone.TimelineSignal.Type = {\n\t\tLinear : \"linear\",\n\t\tExponential : \"exponential\",\n\t\tTarget : \"target\",\n\t\tCurve : \"curve\",\n\t\tSet : \"set\"\n\t};\n\n\t/**\n\t * The current value of the signal. \n\t * @memberOf Tone.TimelineSignal#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.TimelineSignal.prototype, \"value\", {\n\t\tget : function(){\n\t\t\tvar now = this.now();\n\t\t\tvar val = this.getValueAtTime(now);\n\t\t\treturn this._toUnits(val);\n\t\t},\n\t\tset : function(value){\n\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\tthis._initial = convertedVal;\n\t\t\tthis.cancelScheduledValues();\n\t\t\tthis._param.value = convertedVal;\n\t\t}\n\t});\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tSCHEDULING\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.TimelineSignal} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Set,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime\n\t\t});\n\t\t//invoke the original event\n\t\tthis._param.setValueAtTime(value, startTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {\n\t\tvalue = this._fromUnits(value);\n\t\tendTime = this.toSeconds(endTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Linear,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\tthis._param.linearRampToValueAtTime(value, endTime);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {\n\t\t//get the previous event and make sure it's not starting from 0\n\t\tendTime = this.toSeconds(endTime);\n\t\tvar beforeEvent = this._searchBefore(endTime);\n\t\tif (beforeEvent && beforeEvent.value === 0){\n\t\t\t//reschedule that event\n\t\t\tthis.setValueAtTime(this._minOutput, beforeEvent.time);\n\t\t}\n\t\tvalue = this._fromUnits(value);\n\t\tvar setValue = Math.max(value, this._minOutput);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Exponential,\n\t\t\t\"value\" : setValue,\n\t\t\t\"time\" : endTime\n\t\t});\n\t\t//if the ramped to value is 0, make it go to the min output, and then set to 0.\n\t\tif (value < this._minOutput){\n\t\t\tthis._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);\n\t\t\tthis.setValueAtTime(0, endTime);\n\t\t} else {\n\t\t\tthis._param.exponentialRampToValueAtTime(value, endTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Target,\n\t\t\t\"value\" : value,\n\t\t\t\"time\" : startTime,\n\t\t\t\"constant\" : timeConstant\n\t\t});\n\t\tthis._param.setTargetAtTime(value, startTime, timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Set an array of arbitrary values starting at the given time for the given duration.\n\t * @param {Float32Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration\n\t * @param {NormalRange} [scaling=1] If the values in the curve should be scaled by some value\n\t * @returns {Tone.TimelineSignal} this \n\t */\n\tTone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {\n\t\tscaling = this.defaultArg(scaling, 1);\n\t\t//copy the array\n\t\tvar floats = new Array(values.length);\n\t\tfor (var i = 0; i < floats.length; i++){\n\t\t\tfloats[i] = this._fromUnits(values[i]) * scaling;\n\t\t}\n\t\tstartTime = this.toSeconds(startTime);\n\t\tduration = this.toSeconds(duration);\n\t\tthis._events.add({\n\t\t\t\"type\" : Tone.TimelineSignal.Type.Curve,\n\t\t\t\"value\" : floats,\n\t\t\t\"time\" : startTime,\n\t\t\t\"duration\" : duration\n\t\t});\n\t\t//set the first value\n\t\tthis._param.setValueAtTime(floats[0], startTime);\n\t\t//schedule a lienar ramp for each of the segments\n\t\tfor (var j = 1; j < floats.length; j++){\n\t\t\tvar segmentTime = startTime + (j / (floats.length - 1) * duration);\n\t\t\tthis._param.linearRampToValueAtTime(floats[j], segmentTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.cancelScheduledValues = function (after) {\n\t\tafter = this.toSeconds(after);\n\t\tthis._events.cancel(after);\n\t\tthis._param.cancelScheduledValues(after);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets the computed value at the given time. This provides\n\t * a point from which a linear or exponential curve\n\t * can be scheduled after. Will cancel events after \n\t * the given time and shorten the currently scheduled\n\t * linear or exponential ramp so that it ends at `time` .\n\t * This is to avoid discontinuities and clicks in envelopes. \n\t * @param {Time} time When to set the ramp point\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.setRampPoint = function (time) {\n\t\ttime = this.toSeconds(time);\n\t\t//get the value at the given time\n\t\tvar val = this._toUnits(this.getValueAtTime(time));\n\t\t//if there is an event at the given time\n\t\t//and that even is not a \"set\"\n\t\tvar before = this._searchBefore(time);\n\t\tif (before && before.time === time){\n\t\t\t//remove everything after\n\t\t\tthis.cancelScheduledValues(time + this.sampleTime);\n\t\t} else if (before && \n\t\t\t\t before.type === Tone.TimelineSignal.Type.Curve &&\n\t\t\t\t before.time + before.duration > time){\n\t\t\t//if the curve is still playing\n\t\t\t//cancel the curve\n\t\t\tthis.cancelScheduledValues(time);\n\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t} else {\n\t\t\t//reschedule the next event to end at the given time\n\t\t\tvar after = this._searchAfter(time);\n\t\t\tif (after){\n\t\t\t\t//cancel the next event(s)\n\t\t\t\tthis.cancelScheduledValues(time);\n\t\t\t\tif (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\t\t\tthis.linearRampToValueAtTime(val, time);\n\t\t\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\t\t\tthis.exponentialRampToValueAtTime(val, time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.setValueAtTime(val, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a linear ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the linear ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.linearRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Do a exponential ramp to the given value between the start and finish times.\n\t * @param {Number} value The value to ramp to.\n\t * @param {Time} start The beginning anchor point to do the exponential ramp\n\t * @param {Time} finish The ending anchor point by which the value of\n\t * the signal will equal the given value.\n\t * @returns {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {\n\t\tthis.setRampPoint(start);\n\t\tthis.exponentialRampToValueAtTime(value, finish);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tGETTING SCHEDULED VALUES\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value before or equal to the given time\n\t * @param {Number} time The time to query\n\t * @return {Object} The event at or before the given time.\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchBefore = function(time){\n\t\treturn this._events.get(time);\n\t};\n\n\t/**\n\t * The event after the given time\n\t * @param {Number} time The time to query.\n\t * @return {Object} The next event after the given time\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._searchAfter = function(time){\n\t\treturn this._events.getAfter(time);\n\t};\n\n\t/**\n\t * Get the scheduled value at the given time. This will\n\t * return the unconverted (raw) value.\n\t * @param {Number} time The time in seconds.\n\t * @return {Number} The scheduled value at the given time.\n\t */\n\tTone.TimelineSignal.prototype.getValueAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tvar after = this._searchAfter(time);\n\t\tvar before = this._searchBefore(time);\n\t\tvar value = this._initial;\n\t\t//if it was set by\n\t\tif (before === null){\n\t\t\tvalue = this._initial;\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Target){\n\t\t\tvar previous = this._events.getBefore(before.time);\n\t\t\tvar previouVal;\n\t\t\tif (previous === null){\n\t\t\t\tpreviouVal = this._initial;\n\t\t\t} else {\n\t\t\t\tpreviouVal = previous.value;\n\t\t\t}\n\t\t\tvalue = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);\n\t\t} else if (before.type === Tone.TimelineSignal.Type.Curve){\n\t\t\tvalue = this._curveInterpolate(before.time, before.value, before.duration, time);\n\t\t} else if (after === null){\n\t\t\tvalue = before.value;\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Linear){\n\t\t\tvalue = this._linearInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else if (after.type === Tone.TimelineSignal.Type.Exponential){\n\t\t\tvalue = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);\n\t\t} else {\n\t\t\tvalue = before.value;\n\t\t}\n\t\treturn value;\n\t};\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.TimelineSignal} this\n\t * @method\n\t */\n\tTone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUTOMATION CURVE CALCULATIONS\n\t//\tMIT License, copyright (c) 2014 Jordan Santell\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Calculates the the value along the curve produced by setTargetAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {\n\t\treturn v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by linearRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {\n\t\treturn v0 + (v1 - v0) * ((t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by exponentialRampToValueAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {\n\t\tv0 = Math.max(this._minOutput, v0);\n\t\treturn v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));\n\t};\n\n\t/**\n\t * Calculates the the value along the curve produced by setValueCurveAtTime\n\t * @private\n\t */\n\tTone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {\n\t\tvar len = curve.length;\n\t\t// If time is after duration, return the last curve value\n\t\tif (time >= start + duration) {\n\t\t\treturn curve[len - 1];\n\t\t} else if (time <= start){\n\t\t\treturn curve[0];\n\t\t} else {\n\t\t\tvar progress = (time - start) / duration;\n\t\t\tvar lowerIndex = Math.floor((len - 1) * progress);\n\t\t\tvar upperIndex = Math.ceil((len - 1) * progress);\n\t\t\tvar lowerVal = curve[lowerIndex];\n\t\t\tvar upperVal = curve[upperIndex];\n\t\t\tif (upperIndex === lowerIndex){\n\t\t\t\treturn lowerVal;\n\t\t\t} else {\n\t\t\t\treturn this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.TimelineSignal} this\n\t */\n\tTone.TimelineSignal.prototype.dispose = function(){\n\t\tTone.Signal.prototype.dispose.call(this);\n\t\tTone.Param.prototype.dispose.call(this);\n\t\tthis._events.dispose();\n\t\tthis._events = null;\n\t};\n\n\treturn Tone.TimelineSignal;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Effect = require('effect');\r\n\r\n /**\r\n *
A p5.Filter uses a Web Audio Biquad Filter to filter\r\n * the frequency response of an input source. Subclasses\r\n * include:
\r\n * p5.LowPass:\r\n * Allows frequencies below the cutoff frequency to pass through,\r\n * and attenuates frequencies above the cutoff. \r\n * p5.HighPass:\r\n * The opposite of a lowpass filter. \r\n * p5.BandPass:\r\n * Allows a range of frequencies to pass through and attenuates\r\n * the frequencies below and above this frequency range. \r\n *\r\n * The .res() method controls either width of the\r\n * bandpass, or resonance of the low/highpass cutoff frequency.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Filter\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\r\n * @example\r\n *
\r\n * var fft, noise, filter;\r\n *\r\n * function setup() {\r\n * fill(255, 40, 255);\r\n *\r\n * filter = new p5.BandPass();\r\n *\r\n * noise = new p5.Noise();\r\n * // disconnect unfiltered noise,\r\n * // and connect to filter\r\n * noise.disconnect();\r\n * noise.connect(filter);\r\n * noise.start();\r\n *\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n *\r\n * // set the BandPass frequency based on mouseX\r\n * var freq = map(mouseX, 0, width, 20, 10000);\r\n * filter.freq(freq);\r\n * // give the filter a narrow band (lower res = wider bandpass)\r\n * filter.res(50);\r\n *\r\n * // draw filtered spectrum\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * for (var i = 0; i < spectrum.length; i++) {\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width/spectrum.length, h);\r\n * }\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * noise.amp(0.5, 0.2);\r\n * } else {\r\n * noise.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Filter = function (type) {\r\n\r\n Effect.call(this);\r\n //add extend Effect by adding a Biquad Filter\r\n\r\n /**\r\n * The p5.Filter is built with a\r\n * \r\n * Web Audio BiquadFilter Node.\r\n *\r\n * @property {DelayNode} biquadFilter\r\n\t */\r\n\r\n this.biquad = this.ac.createBiquadFilter();\r\n\r\n this.input.connect(this.biquad);\r\n\r\n this.biquad.connect(this.wet);\r\n\r\n if (type) {\r\n this.setType(type);\r\n }\r\n\r\n //Properties useful for the toggle method.\r\n this._on = true;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n p5.Filter.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Filter an audio signal according to a set\r\n * of filter parameters.\r\n *\r\n * @method process\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance/Width of the filter frequency\r\n * from 0.001 to 1000\r\n */\r\n p5.Filter.prototype.process = function(src, freq, res, time) {\r\n src.connect(this.input);\r\n this.set(freq, res, time);\r\n };\r\n\r\n\r\n /**\r\n * Set the frequency and the resonance of the filter.\r\n *\r\n * @method set\r\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\r\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Filter.prototype.set = function(freq, res, time) {\r\n if (freq) {\r\n this.freq(freq, time);\r\n }\r\n if (res) {\r\n this.res(res, time);\r\n }\r\n };\r\n\r\n /**\r\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\r\n * human hearing, although in reality most people hear in a narrower\r\n * range).\r\n *\r\n * @method freq\r\n * @param {Number} freq Filter Frequency\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current frequency value\r\n */\r\n p5.Filter.prototype.freq = function(freq, time) {\r\n var t = time || 0;\r\n if (freq <= 0) {\r\n freq = 1;\r\n }\r\n if (typeof freq === 'number') {\r\n this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t);\r\n } else if (freq) {\r\n freq.connect(this.biquad.frequency);\r\n }\r\n return this.biquad.frequency.value;\r\n };\r\n\r\n /**\r\n * Controls either width of a bandpass frequency,\r\n * or the resonance of a low/highpass cutoff frequency.\r\n *\r\n * @method res\r\n * @param {Number} res Resonance/Width of filter freq\r\n * from 0.001 to 1000\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {Number} value Returns the current res value\r\n */\r\n p5.Filter.prototype.res = function(res, time) {\r\n var t = time || 0;\r\n if (typeof res === 'number') {\r\n this.biquad.Q.value = res;\r\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);\r\n } else if (res) {\r\n res.connect(this.biquad.Q);\r\n }\r\n return this.biquad.Q.value;\r\n };\r\n\r\n /**\r\n * Controls the gain attribute of a Biquad Filter.\r\n * This is distinctly different from .amp() which is inherited from p5.Effect\r\n * .amp() controls the volume via the output gain node\r\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\r\n *\r\n * @method gain\r\n * @param {Number} gain\r\n * @return {Number} Returns the current or updated gain value\r\n */\r\n p5.Filter.prototype.gain = function(gain, time) {\r\n var t = time || 0;\r\n if (typeof gain === 'number') {\r\n this.biquad.gain.value = gain;\r\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t);\r\n } else if (gain) {\r\n gain.connect(this.biquad.gain);\r\n }\r\n return this.biquad.gain.value;\r\n };\r\n\r\n\r\n /**\r\n * Toggle function. Switches between the specified type and allpass\r\n *\r\n * @method toggle\r\n * @return {boolean} [Toggle value]\r\n */\r\n p5.Filter.prototype.toggle = function() {\r\n this._on = !this._on;\r\n\r\n if (this._on === true) {\r\n this.biquad.type = this._untoggledType;\r\n } else if (this._on === false) {\r\n this.biquad.type = 'allpass';\r\n }\r\n\r\n return this._on;\r\n };\r\n\r\n /**\r\n * Set the type of a p5.Filter. Possible types include:\r\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\r\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\r\n * \"allpass\".\r\n *\r\n * @method setType\r\n * @param {String} t\r\n */\r\n p5.Filter.prototype.setType = function(t) {\r\n this.biquad.type = t;\r\n this._untoggledType = this.biquad.type;\r\n };\r\n\r\n p5.Filter.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n Effect.prototype.dispose.apply(this);\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n delete this.biquad;\r\n }\r\n };\r\n\r\n /**\r\n * Constructor: new p5.LowPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('lowpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.LowPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.LowPass = function() {\r\n p5.Filter.call(this, 'lowpass');\r\n };\r\n p5.LowPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.HighPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('highpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.HighPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.HighPass = function() {\r\n p5.Filter.call(this, 'highpass');\r\n };\r\n p5.HighPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n /**\r\n * Constructor: new p5.BandPass() Filter.\r\n * This is the same as creating a p5.Filter and then calling\r\n * its method setType('bandpass').\r\n * See p5.Filter for methods.\r\n *\r\n * @class p5.BandPass\r\n * @constructor\r\n * @extends p5.Filter\r\n */\r\n p5.BandPass = function() {\r\n p5.Filter.call(this, 'bandpass');\r\n };\r\n p5.BandPass.prototype = Object.create(p5.Filter.prototype);\r\n\r\n return p5.Filter;\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Negate\", \"Tone/signal/Signal\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Subtract the signal connected to input[1] from the signal connected \n\t * to input[0]. If an argument is provided in the constructor, the \n\t * signals .value will be subtracted from the incoming signal.\n\t *\n\t * @extends {Tone.Signal}\n\t * @constructor\n\t * @param {number=} value The value to subtract from the incoming signal. If the value\n\t * is omitted, it will subtract the second signal from the first.\n\t * @example\n\t * var sub = new Tone.Subtract(1);\n\t * var sig = new Tone.Signal(4).connect(sub);\n\t * //the output of sub is 3. \n\t * @example\n\t * var sub = new Tone.Subtract();\n\t * var sigA = new Tone.Signal(10);\n\t * var sigB = new Tone.Signal(2.5);\n\t * sigA.connect(sub, 0, 0);\n\t * sigB.connect(sub, 0, 1);\n\t * //output of sub is 7.5\n\t */\n\tTone.Subtract = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\n\t\t/**\n\t\t * the summing node\n\t\t * @type {GainNode}\n\t\t * @private\n\t\t */\n\t\tthis._sum = this.input[0] = this.output = new Tone.Gain();\n\n\t\t/**\n\t\t * negate the input of the second input before connecting it\n\t\t * to the summing node.\n\t\t * @type {Tone.Negate}\n\t\t * @private\n\t\t */\n\t\tthis._neg = new Tone.Negate();\n\n\t\t/**\n\t\t * the node where the value is set\n\t\t * @private\n\t\t * @type {Tone.Signal}\n\t\t */\n\t\tthis._param = this.input[1] = new Tone.Signal(value);\n\n\t\tthis._param.chain(this._neg, this._sum);\n\t};\n\n\tTone.extend(Tone.Subtract, Tone.Signal);\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.Subtract.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._neg.dispose();\n\t\tthis._neg = null;\n\t\tthis._sum.disconnect();\n\t\tthis._sum = null;\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Subtract;\n});","'use strict';\r\n\r\nglobal.TONE_SILENCE_VERSION_LOGGING = true;\r\n\r\ndefine(['startaudiocontext', 'Tone/core/Context', 'Tone/core/Tone'], function (StartAudioContext, Context, Tone) {\r\n // Create the Audio Context\r\n const audiocontext = new window.AudioContext();\r\n\r\n // Tone and p5.sound share the same audio context\r\n Tone.context.dispose();\r\n Tone.setContext(audiocontext);\r\n\r\n /**\r\n *
Returns the Audio Context for this sketch. Useful for users\r\n * who would like to dig deeper into the Web Audio API\r\n * .
\r\n *\r\n *
Some browsers require users to startAudioContext\r\n * with a user gesture, such as touchStarted in the example below.
\r\n *\r\n * @method getAudioContext\r\n * @return {Object} AudioContext for this sketch\r\n * @example\r\n *
\r\n * function draw() {\r\n * background(255);\r\n * textAlign(CENTER);\r\n *\r\n * if (getAudioContext().state !== 'running') {\r\n * text('click to start audio', width/2, height/2);\r\n * } else {\r\n * text('audio is enabled', width/2, height/2);\r\n * }\r\n * }\r\n *\r\n * function touchStarted() {\r\n * if (getAudioContext().state !== 'running') {\r\n * getAudioContext().resume();\r\n * }\r\n * var synth = new p5.MonoSynth();\r\n * synth.play('A4', 0.5, 0, 0.2);\r\n * }\r\n *\r\n *
It is a good practice to give users control over starting audio playback.\r\n * This practice is enforced by Google Chrome's autoplay policy as of r70\r\n * (info), iOS Safari, and other browsers.\r\n *
\r\n *\r\n *
\r\n * userStartAudio() starts the Audio Context on a user gesture. It utilizes\r\n * the StartAudioContext library by\r\n * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext.\r\n *
\r\n *\r\n *
Starting the audio context on a user gesture can be as simple as userStartAudio().\r\n * Optional parameters let you decide on a specific element that will start the audio context,\r\n * and/or call a function once the audio context is started.
\r\n * @param {Element|Array} [element(s)] This argument can be an Element,\r\n * Selector String, NodeList, p5.Element,\r\n * jQuery Element, or an Array of any of those.\r\n * @param {Function} [callback] Callback to invoke when the AudioContext has started\r\n * @return {Promise} Returns a Promise which is resolved when\r\n * the AudioContext state is 'running'\r\n * @method userStartAudio\r\n * @for p5\r\n * @example\r\n *
\r\n * function setup() {\r\n * var myDiv = createDiv('click to start audio');\r\n * myDiv.position(0, 0);\r\n *\r\n * var mySynth = new p5.MonoSynth();\r\n *\r\n * // This won't play until the context has started\r\n * mySynth.play('A6');\r\n *\r\n * // Start the audio context on a click/touch event\r\n * userStartAudio().then(function() {\r\n * myDiv.remove();\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.prototype.userStartAudio = function(elements, callback) {\r\n var elt = elements;\r\n if (elements instanceof p5.Element) {\r\n elt = elements.elt;\r\n } else if (elements instanceof Array && elements[0] instanceof p5.Element ) {\r\n elt = elements.map(function(e) { return e.elt});\r\n }\r\n return StartAudioContext(audiocontext, elt, callback);\r\n };\r\n\r\n return audiocontext;\r\n});\r\n","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Emitter gives classes which extend it\n\t * the ability to listen for and emit events. \n\t * Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).\n\t * MIT (c) 2011 Jerome Etienne.\n\t * \n\t * @extends {Tone}\n\t */\n\tTone.Emitter = function(){\n\t\t/**\n\t\t * Contains all of the events.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t\tthis._events = {};\n\t};\n\n\tTone.extend(Tone.Emitter);\n\n\t/**\n\t * Bind a callback to a specific event.\n\t * @param {String} event The name of the event to listen for.\n\t * @param {Function} callback The callback to invoke when the\n\t * event is emitted\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.on = function(event, callback){\n\t\t//split the event\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var i = 0; i < events.length; i++){\n\t\t\tvar eventName = events[i];\n\t\t\tif (!this._events.hasOwnProperty(eventName)){\n\t\t\t\tthis._events[eventName] = [];\n\t\t\t}\n\t\t\tthis._events[eventName].push(callback);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove the event listener.\n\t * @param {String} event The event to stop listening to.\n\t * @param {Function=} callback The callback which was bound to \n\t * the event with Tone.Emitter.on.\n\t * If no callback is given, all callbacks\n\t * events are removed.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.off = function(event, callback){\n\t\tvar events = event.split(/\\W+/);\n\t\tfor (var ev = 0; ev < events.length; ev++){\n\t\t\tevent = events[ev];\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tif (Tone.prototype.isUndef(callback)){\n\t\t\t\t\tthis._events[event] = [];\n\t\t\t\t} else {\n\t\t\t\t\tvar eventList = this._events[event];\n\t\t\t\t\tfor (var i = 0; i < eventList.length; i++){\n\t\t\t\t\t\tif (eventList[i] === callback){\n\t\t\t\t\t\t\teventList.splice(i, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Invoke all of the callbacks bound to the event\n\t * with any arguments passed in. \n\t * @param {String} event The name of the event.\n\t * @param {*...} args The arguments to pass to the functions listening.\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.emit = function(event){\n\t\tif (this._events){\n\t\t\tvar args = Array.apply(null, arguments).slice(1);\n\t\t\tif (this._events.hasOwnProperty(event)){\n\t\t\t\tvar eventList = this._events[event];\n\t\t\t\tfor (var i = 0, len = eventList.length; i < len; i++){\n\t\t\t\t\teventList[i].apply(this, args);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add Emitter functions (on/off/emit) to the object\n\t * @param {Object|Function} object The object or class to extend.\n\t */\n\tTone.Emitter.mixin = function(object){\n\t\tvar functions = [\"on\", \"off\", \"emit\"];\n\t\tobject._events = {};\n\t\tfor (var i = 0; i < functions.length; i++){\n\t\t\tvar func = functions[i];\n\t\t\tvar emitterFunc = Tone.Emitter.prototype[func];\n\t\t\tobject[func] = emitterFunc;\n\t\t}\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.Emitter} this\n\t */\n\tTone.Emitter.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._events = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Emitter;\n});","module.exports = {\r\n recorderProcessor: 'recorder-processor',\r\n soundFileProcessor: 'sound-file-processor',\r\n amplitudeProcessor: 'amplitude-processor'\r\n};\r\n","define([\"Tone/core/Tone\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Base class for all Signals. Used Internally. \n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t */\n\tTone.SignalBase = function(){};\n\n\tTone.extend(Tone.SignalBase);\n\n\t/**\n\t * When signals connect to other signals or AudioParams, \n\t * they take over the output value of that signal or AudioParam. \n\t * For all other nodes, the behavior is the same as a default connect. \n\t *\n\t * @override\n\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t * @param {number} [outputNumber=0] The output number to connect from.\n\t * @param {number} [inputNumber=0] The input number to connect to.\n\t * @returns {Tone.SignalBase} this\n\t */\n\tTone.SignalBase.prototype.connect = function(node, outputNumber, inputNumber){\n\t\t//zero it out so that the signal can have full control\n\t\tif ((Tone.Signal && Tone.Signal === node.constructor) || \n\t\t\t\t(Tone.Param && Tone.Param === node.constructor) || \n\t\t\t\t(Tone.TimelineSignal && Tone.TimelineSignal === node.constructor)){\n\t\t\t//cancel changes\n\t\t\tnode._param.cancelScheduledValues(0);\n\t\t\t//reset the value\n\t\t\tnode._param.value = 0;\n\t\t\t//mark the value as overridden\n\t\t\tnode.overridden = true;\n\t\t} else if (node instanceof AudioParam){\n\t\t\tnode.cancelScheduledValues(0);\n\t\t\tnode.value = 0;\n\t\t} \n\t\tTone.prototype.connect.call(this, node, outputNumber, inputNumber);\n\t\treturn this;\n\t};\n\n\treturn Tone.SignalBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Time is a primitive type for encoding Time values. \n\t * Eventually all time values are evaluated to seconds\n\t * using the `eval` method. Tone.Time can be constructed\n\t * with or without the `new` keyword. Tone.Time can be passed\n\t * into the parameter of any method which takes time as an argument. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * var t = Tone.Time(\"4n\");//encodes a quarter note\n\t * t.mult(4); // multiply that value by 4\n\t * t.toNotation(); //returns \"1m\"\n\t */\n\tTone.Time = function(val, units){\n\t\tif (this instanceof Tone.Time){\n\n\t\t\t/**\n\t\t\t * If the current clock time should\n\t\t\t * be added to the output\n\t\t\t * @type {Boolean}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._plusNow = false;\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Time(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Time, Tone.TimeBase);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);\n\n\t/*\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\treturn Tone.Transport.nextSubdivision(rh());\n\t\t}\n\t};\n\n\t/*\n\t * Adds an additional unary expression\n\t * which adds the current clock time.\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Time.prototype._unaryExpressions.now = {\n\t\tregexp : /^\\+/,\n\t\tmethod : function(lh){\n\t\t\tthis._plusNow = true;\n\t\t\treturn lh();\n\t\t}\n\t};\n\n\t/**\n\t * Quantize the time by the given subdivision. Optionally add a\n\t * percentage which will move the time value towards the ideal\n\t * quantized value by that percentage. \n\t * @param {Number|Time} val The subdivision to quantize to\n\t * @param {NormalRange} [percent=1] Move the time value\n\t * towards the quantized value by\n\t * a percentage.\n\t * @return {Tone.Time} this\n\t * @example\n\t * Tone.Time(21).quantize(2) //returns 22\n\t * Tone.Time(0.6).quantize(\"4n\", 0.5) //returns 0.55\n\t */\n\tTone.Time.prototype.quantize = function(subdiv, percent){\n\t\tpercent = this.defaultArg(percent, 1);\n\t\tthis._expr = function(expr, subdivision, percent){\n\t\t\texpr = expr();\n\t\t\tsubdivision = subdivision.toSeconds();\n\t\t\tvar multiple = Math.round(expr / subdivision);\n\t\t\tvar ideal = multiple * subdivision;\n\t\t\tvar diff = ideal - expr;\n\t\t\treturn expr + diff * percent;\n\t\t}.bind(this, this._expr, new this.constructor(subdiv), percent);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Adds the clock time to the time expression at the \n\t * moment of evaluation. \n\t * @return {Tone.Time} this\n\t */\n\tTone.Time.prototype.addNow = function(){\n\t\tthis._plusNow = true;\n\t\treturn this;\n\t};\n\n\t/**\n\t * @override\n\t * Override the default value return when no arguments are passed in.\n\t * The default value is 'now'\n\t * @private\n\t */\n\tTone.Time.prototype._defaultExpr = function(){\n\t\tthis._plusNow = true;\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.Time} time\n\t * @return {Time}\n\t */\n\tTone.Time.prototype.copy = function(time){\n\t\tTone.TimeBase.prototype.copy.call(this, time);\n\t\tthis._plusNow = time._plusNow;\n\t\treturn this;\n\t};\n\n\t//CONVERSIONS//////////////////////////////////////////////////////////////\n\n\t/**\n\t * Convert a Time to Notation. Values will be thresholded to the nearest 128th note. \n\t * @return {Notation} \n\t * @example\n\t * //if the Transport is at 120bpm:\n\t * Tone.Time(2).toNotation();//returns \"1m\"\n\t */\n\tTone.Time.prototype.toNotation = function(){\n\t\tvar time = this.toSeconds();\n\t\tvar testNotations = [\"1m\", \"2n\", \"4n\", \"8n\", \"16n\", \"32n\", \"64n\", \"128n\"];\n\t\tvar retNotation = this._toNotationHelper(time, testNotations);\n\t\t//try the same thing but with tripelets\n\t\tvar testTripletNotations = [\"1m\", \"2n\", \"2t\", \"4n\", \"4t\", \"8n\", \"8t\", \"16n\", \"16t\", \"32n\", \"32t\", \"64n\", \"64t\", \"128n\"];\n\t\tvar retTripletNotation = this._toNotationHelper(time, testTripletNotations);\n\t\t//choose the simpler expression of the two\n\t\tif (retTripletNotation.split(\"+\").length < retNotation.split(\"+\").length){\n\t\t\treturn retTripletNotation;\n\t\t} else {\n\t\t\treturn retNotation;\n\t\t}\n\t};\n\n\t/**\n\t * Helper method for Tone.toNotation\n\t * @param {Number} units \n\t * @param {Array} testNotations\n\t * @return {String}\n\t * @private\n\t */\n\tTone.Time.prototype._toNotationHelper = function(units, testNotations){\n\t\t//the threshold is the last value in the array\n\t\tvar threshold = this._notationToUnits(testNotations[testNotations.length - 1]);\n\t\tvar retNotation = \"\";\n\t\tfor (var i = 0; i < testNotations.length; i++){\n\t\t\tvar notationTime = this._notationToUnits(testNotations[i]);\n\t\t\t//account for floating point errors (i.e. round up if the value is 0.999999)\n\t\t\tvar multiple = units / notationTime;\n\t\t\tvar floatingPointError = 0.000001;\n\t\t\tif (1 - multiple % 1 < floatingPointError){\n\t\t\t\tmultiple += floatingPointError;\n\t\t\t}\n\t\t\tmultiple = Math.floor(multiple);\n\t\t\tif (multiple > 0){\n\t\t\t\tif (multiple === 1){\n\t\t\t\t\tretNotation += testNotations[i];\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += multiple.toString() + \"*\" + testNotations[i];\n\t\t\t\t}\n\t\t\t\tunits -= multiple * notationTime;\n\t\t\t\tif (units < threshold){\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tretNotation += \" + \";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (retNotation === \"\"){\n\t\t\tretNotation = \"0\";\n\t\t}\n\t\treturn retNotation;\n\t};\n\n\t/**\n\t * Convert a notation value to the current units\n\t * @param {Notation} notation \n\t * @return {Number} \n\t * @private\n\t */\n\tTone.Time.prototype._notationToUnits = function(notation){\n\t\tvar primaryExprs = this._primaryExpressions;\n\t\tvar notationExprs = [primaryExprs.n, primaryExprs.t, primaryExprs.m];\n\t\tfor (var i = 0; i < notationExprs.length; i++){\n\t\t\tvar expr = notationExprs[i];\n\t\t\tvar match = notation.match(expr.regexp);\n\t\t\tif (match){\n\t\t\t\treturn expr.method.call(this, match[1]);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Return the time encoded as Bars:Beats:Sixteenths.\n\t * @return {BarsBeatsSixteenths}\n\t */\n\tTone.Time.prototype.toBarsBeatsSixteenths = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.toSeconds() / quarterTime;\n\t\tvar measures = Math.floor(quarters / this._timeSignature());\n\t\tvar sixteenths = (quarters % 1) * 4;\n\t\tquarters = Math.floor(quarters) % this._timeSignature();\n\t\tsixteenths = sixteenths.toString();\n\t\tif (sixteenths.length > 3){\n\t\t\tsixteenths = parseFloat(sixteenths).toFixed(3);\n\t\t}\n\t\tvar progress = [measures, quarters, sixteenths];\n\t\treturn progress.join(\":\");\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.Time.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time in samples\n\t * @return {Samples} \n\t */\n\tTone.Time.prototype.toSamples = function(){\n\t\treturn this.toSeconds() * this.context.sampleRate;\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t * @example\n\t * Tone.Time(2).toFrequency(); //0.5\n\t */\n\tTone.Time.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.toSeconds = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in milliseconds.\n\t * @return {Milliseconds} \n\t */\n\tTone.Time.prototype.toMilliseconds = function(){\n\t\treturn this.toSeconds() * 1000;\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.Time.prototype.valueOf = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow?this.now():0);\n\t};\n\n\treturn Tone.Time;\n});","define([\"Tone/core/Tone\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TimeBase is a flexible encoding of time\n\t * which can be evaluated to and from a string.\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t * @extends {Tone}\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @example\n\t * Tone.TimeBase(4, \"n\")\n\t * Tone.TimeBase(2, \"t\")\n\t * Tone.TimeBase(\"2t\").add(\"1m\")\n\t * Tone.TimeBase(\"2t + 1m\");\n\t */\n\tTone.TimeBase = function(val, units){\n\n\t\t//allows it to be constructed with or without 'new'\n\t\tif (this instanceof Tone.TimeBase) {\n\n\t\t\t/**\n\t\t\t * Any expressions parsed from the Time\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t\t\tthis._expr = this._noOp;\n\n\t\t\tif (val instanceof Tone.TimeBase){\n\t\t\t\tthis.copy(val);\n\t\t\t} else if (!this.isUndef(units) || this.isNumber(val)){\n\t\t\t\t//default units\n\t\t\t\tunits = this.defaultArg(units, this._defaultUnits);\n\t\t\t\tvar method = this._primaryExpressions[units].method;\n\t\t\t\tthis._expr = method.bind(this, val);\n\t\t\t} else if (this.isString(val)){\n\t\t\t\tthis.set(val);\n\t\t\t} else if (this.isUndef(val)){\n\t\t\t\t//default expression\n\t\t\t\tthis._expr = this._defaultExpr();\n\t\t\t}\n\t\t} else {\n\n\t\t\treturn new Tone.TimeBase(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TimeBase);\n\n\t/**\n\t * Repalce the current time value with the value\n\t * given by the expression string.\n\t * @param {String} exprString\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.set = function(exprString){\n\t\tthis._expr = this._parseExprString(exprString);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Return a clone of the TimeBase object.\n\t * @return {Tone.TimeBase} The new cloned Tone.TimeBase\n\t */\n\tTone.TimeBase.prototype.clone = function(){\n\t\tvar instance = new this.constructor();\n\t\tinstance.copy(this);\n\t\treturn instance;\n\t};\n\n\t/**\n\t * Copies the value of time to this Time\n\t * @param {Tone.TimeBase} time\n\t * @return {TimeBase}\n\t */\n\tTone.TimeBase.prototype.copy = function(time){\n\t\tvar val = time._expr();\n\t\treturn this.set(val);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tABSTRACT SYNTAX TREE PARSER\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * All the primary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._primaryExpressions = {\n\t\t\"n\" : {\n\t\t\tregexp : /^(\\d+)n/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\tif (value === 1){\n\t\t\t\t\treturn this._beatsToUnits(this._timeSignature());\n\t\t\t\t} else {\n\t\t\t\t\treturn this._beatsToUnits(4 / value);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"t\" : {\n\t\t\tregexp : /^(\\d+)t/i,\n\t\t\tmethod : function(value){\n\t\t\t\tvalue = parseInt(value);\n\t\t\t\treturn this._beatsToUnits(8 / (parseInt(value) * 3));\n\t\t\t}\n\t\t},\n\t\t\"m\" : {\n\t\t\tregexp : /^(\\d+)m/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._beatsToUnits(parseInt(value) * this._timeSignature());\n\t\t\t}\n\t\t},\n\t\t\"i\" : {\n\t\t\tregexp : /^(\\d+)i/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._ticksToUnits(parseInt(value));\n\t\t\t}\n\t\t},\n\t\t\"hz\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)hz/i,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._frequencyToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"tr\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\t\tvar total = 0;\n\t\t\t\tif (m && m !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t\t}\n\t\t\t\tif (q && q !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(q));\n\t\t\t\t}\n\t\t\t\tif (s && s !== \"0\"){\n\t\t\t\t\ttotal += this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t\t}\n\t\t\t\treturn total;\n\t\t\t}\n\t\t},\n\t\t\"s\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?s)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._secondsToUnits(parseFloat(value));\n\t\t\t}\n\t\t},\n\t\t\"samples\" : {\n\t\t\tregexp : /^(\\d+)samples/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn parseInt(value) / this.context.sampleRate;\n\t\t\t}\n\t\t},\n\t\t\"default\" : {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?)/,\n\t\t\tmethod : function(value){\n\t\t\t\treturn this._primaryExpressions[this._defaultUnits].method.call(this, value);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the binary expressions that TimeBase can accept.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._binaryExpressions = {\n\t\t\"+\" : {\n\t\t\tregexp : /^\\+/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() + rh();\n\t\t\t}\n\t\t},\n\t\t\"-\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tprecedence : 2,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() - rh();\n\t\t\t}\n\t\t},\n\t\t\"*\" : {\n\t\t\tregexp : /^\\*/,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() * rh();\n\t\t\t}\n\t\t},\n\t\t\"/\" : {\n\t\t\tregexp : /^\\//,\n\t\t\tprecedence : 1,\n\t\t\tmethod : function(lh, rh){\n\t\t\t\treturn lh() / rh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * All the unary expressions.\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._unaryExpressions = {\n\t\t\"neg\" : {\n\t\t\tregexp : /^\\-/,\n\t\t\tmethod : function(lh){\n\t\t\t\treturn -lh();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Syntactic glue which holds expressions together\n\t * @private\n\t * @type {Object}\n\t */\n\tTone.TimeBase.prototype._syntaxGlue = {\n\t\t\"(\" : {\n\t\t\tregexp : /^\\(/\n\t\t},\n\t\t\")\" : {\n\t\t\tregexp : /^\\)/\n\t\t}\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.TimeBase.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr, this);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr, context){\n\t\t\tvar expressions = [\"_binaryExpressions\", \"_unaryExpressions\", \"_primaryExpressions\", \"_syntaxGlue\"];\n\t\t\tfor (var i = 0; i < expressions.length; i++){\n\t\t\t\tvar group = context[expressions[i]];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tmethod : op.method,\n\t\t\t\t\t\t\tprecedence : op.precedence,\n\t\t\t\t\t\t\tregexp : op.regexp,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * Given a token, find the value within the groupName\n\t * @param {Object} token\n\t * @param {String} groupName\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._matchGroup = function(token, group, prec) {\n\t\tvar ret = false;\n\t\tif (!this.isUndef(token)){\n\t\t\tfor (var opName in group){\n\t\t\t\tvar op = group[opName];\n\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\tif (!this.isUndef(prec)){\n\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\treturn op;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn op;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\t/**\n\t * Match a binary expression given the token and the precedence\n\t * @param {Lexer} lexer\n\t * @param {Number} precedence\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseBinary = function(lexer, precedence){\n\t\tif (this.isUndef(precedence)){\n\t\t\tprecedence = 2;\n\t\t}\n\t\tvar expr;\n\t\tif (precedence < 0){\n\t\t\texpr = this._parseUnary(lexer);\n\t\t} else {\n\t\t\texpr = this._parseBinary(lexer, precedence - 1);\n\t\t}\n\t\tvar token = lexer.peek();\n\t\twhile (token && this._matchGroup(token, this._binaryExpressions, precedence)){\n\t\t\ttoken = lexer.next();\n\t\t\texpr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));\n\t\t\ttoken = lexer.peek();\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * Match a unary expression.\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseUnary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tvar op = this._matchGroup(token, this._unaryExpressions);\n\t\tif (op) {\n\t\t\ttoken = lexer.next();\n\t\t\texpr = this._parseUnary(lexer);\n\t\t\treturn op.method.bind(this, expr);\n\t\t}\n\t\treturn this._parsePrimary(lexer);\n\t};\n\n\t/**\n\t * Match a primary expression (a value).\n\t * @param {Lexer} lexer\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parsePrimary = function(lexer){\n\t\tvar token, expr;\n\t\ttoken = lexer.peek();\n\t\tif (this.isUndef(token)) {\n\t\t\tthrow new SyntaxError(\"Tone.TimeBase: Unexpected end of expression\");\n\t\t}\n\t\tif (this._matchGroup(token, this._primaryExpressions)) {\n\t\t\ttoken = lexer.next();\n\t\t\tvar matching = token.value.match(token.regexp);\n\t\t\treturn token.method.bind(this, matching[1], matching[2], matching[3]);\n\t\t}\n\t\tif (token && token.value === \"(\"){\n\t\t\tlexer.next();\n\t\t\texpr = this._parseBinary(lexer);\n\t\t\ttoken = lexer.next();\n\t\t\tif (!(token && token.value === \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\t\tthrow new SyntaxError(\"Tone.TimeBase: Cannot process token \" + token.value);\n\t};\n\n\t/**\n\t * Recursively parse the string expression into a syntax tree.\n\t * @param {string} expr \n\t * @return {Function} the bound method to be evaluated later\n\t * @private\n\t */\n\tTone.TimeBase.prototype._parseExprString = function(exprString){\n\t\tif (!this.isString(exprString)){\n\t\t\texprString = exprString.toString();\n\t\t}\n\t\tvar lexer = this._tokenize(exprString);\n\t\tvar tree = this._parseBinary(lexer);\n\t\treturn tree;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tDEFAULTS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * The initial expression value\n\t * @return {Number} The initial value 0\n\t * @private\n\t */\n\tTone.TimeBase.prototype._noOp = function(){\n\t\treturn 0;\n\t};\n\n\t/**\n\t * The default expression value if no arguments are given\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultExpr = function(){\n\t\treturn this._noOp;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.TimeBase.prototype._defaultUnits = \"s\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._frequencyToUnits = function(freq){\n\t\treturn 1/freq;\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._beatsToUnits = function(beats){\n\t\treturn (60 / Tone.Transport.bpm.value) * beats;\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._secondsToUnits = function(seconds){\n\t\treturn seconds;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._ticksToUnits = function(ticks){\n\t\treturn ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Return the time signature.\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.TimeBase.prototype._timeSignature = function(){\n\t\treturn Tone.Transport.timeSignature;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Push an expression onto the expression list\n\t * @param {Time} val\n\t * @param {String} type\n\t * @param {String} units\n\t * @return {Tone.TimeBase} \n\t * @private\n\t */\n\tTone.TimeBase.prototype._pushExpr = function(val, name, units){\n\t\t//create the expression\n\t\tif (!(val instanceof Tone.TimeBase)){\n\t\t\tval = new this.constructor(val, units);\n\t\t}\n\t\tthis._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Add to the current value.\n\t * @param {Time} val The value to add\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").add(\"1m\"); //\"3m\"\n\t */\n\tTone.TimeBase.prototype.add = function(val, units){\n\t\treturn this._pushExpr(val, \"+\", units);\n\t};\n\n\t/**\n\t * Subtract the value from the current time.\n\t * @param {Time} val The value to subtract\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").sub(\"1m\"); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.sub = function(val, units){\n\t\treturn this._pushExpr(val, \"-\", units);\n\t};\n\n\t/**\n\t * Multiply the current value by the given time.\n\t * @param {Time} val The value to multiply\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").mult(\"2\"); //\"4m\"\n\t */\n\tTone.TimeBase.prototype.mult = function(val, units){\n\t\treturn this._pushExpr(val, \"*\", units);\n\t};\n\n\t/**\n\t * Divide the current value by the given time.\n\t * @param {Time} val The value to divide by\n\t * @param {String=} units Optional units to use with the value.\n\t * @return {Tone.TimeBase} this\n\t * @example\n\t * Tone.TimeBase(\"2m\").div(2); //\"1m\"\n\t */\n\tTone.TimeBase.prototype.div = function(val, units){\n\t\treturn this._pushExpr(val, \"/\", units);\n\t};\n\n\t/**\n\t * Evaluate the time value. Returns the time\n\t * in seconds.\n\t * @return {Seconds} \n\t */\n\tTone.TimeBase.prototype.valueOf = function(){\n\t\treturn this._expr();\n\t};\n\n\t/**\n\t * Clean up\n\t * @return {Tone.TimeBase} this\n\t */\n\tTone.TimeBase.prototype.dispose = function(){\n\t\tthis._expr = null;\n\t};\n\n\treturn Tone.TimeBase;\n});","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Param wraps the native Web Audio's AudioParam to provide\n\t * additional unit conversion functionality. It also\n\t * serves as a base-class for classes which have a single,\n\t * automatable parameter. \n\t * @extends {Tone}\n\t * @param {AudioParam} param The parameter to wrap.\n\t * @param {Tone.Type} units The units of the audio param.\n\t * @param {Boolean} convert If the param should be converted.\n\t */\n\tTone.Param = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"param\", \"units\", \"convert\"], Tone.Param.defaults);\n\n\t\t/**\n\t\t * The native parameter to control\n\t\t * @type {AudioParam}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input = options.param;\n\n\t\t/**\n\t\t * The units of the parameter\n\t\t * @type {Tone.Type}\n\t\t */\n\t\tthis.units = options.units;\n\n\t\t/**\n\t\t * If the value should be converted or not\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis.convert = options.convert;\n\n\t\t/**\n\t\t * True if the signal value is being overridden by \n\t\t * a connected signal.\n\t\t * @readOnly\n\t\t * @type {boolean}\n\t\t * @private\n\t\t */\n\t\tthis.overridden = false;\n\n\t\t/**\n\t\t * If there is an LFO, this is where it is held.\n\t\t * @type {Tone.LFO}\n\t\t * @private\n\t\t */\n\t\tthis._lfo = null;\n\n\t\tif (this.isObject(options.lfo)){\n\t\t\tthis.value = options.lfo;\n\t\t} else if (!this.isUndef(options.value)){\n\t\t\tthis.value = options.value;\n\t\t}\n\t};\n\n\tTone.extend(Tone.Param);\n\t\n\t/**\n\t * Defaults\n\t * @type {Object}\n\t * @const\n\t */\n\tTone.Param.defaults = {\n\t\t\"units\" : Tone.Type.Default,\n\t\t\"convert\" : true,\n\t\t\"param\" : undefined\n\t};\n\n\t/**\n\t * The current value of the parameter. \n\t * @memberOf Tone.Param#\n\t * @type {Number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._toUnits(this._param.value);\n\t\t},\n\t\tset : function(value){\n\t\t\tif (this.isObject(value)){\n\t\t\t\t//throw an error if the LFO needs to be included\n\t\t\t\tif (this.isUndef(Tone.LFO)){\n\t\t\t\t\tthrow new Error(\"Include 'Tone.LFO' to use an LFO as a Param value.\");\n\t\t\t\t}\n\t\t\t\t//remove the old one\n\t\t\t\tif (this._lfo){\n\t\t\t\t\tthis._lfo.dispose();\n\t\t\t\t}\n\t\t\t\tthis._lfo = new Tone.LFO(value).start();\n\t\t\t\tthis._lfo.connect(this.input);\n\t\t\t} else {\n\t\t\t\tvar convertedVal = this._fromUnits(value);\n\t\t\t\tthis._param.cancelScheduledValues(0);\n\t\t\t\tthis._param.value = convertedVal;\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Convert the given value from the type specified by Tone.Param.units\n\t * into the destination value (such as Gain or Frequency).\n\t * @private\n\t * @param {*} val the value to convert\n\t * @return {number} the number which the value should be set to\n\t */\n\tTone.Param.prototype._fromUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Time: \n\t\t\t\t\treturn this.toSeconds(val);\n\t\t\t\tcase Tone.Type.Frequency: \n\t\t\t\t\treturn this.toFrequency(val);\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.dbToGain(val);\n\t\t\t\tcase Tone.Type.NormalRange: \n\t\t\t\t\treturn Math.min(Math.max(val, 0), 1);\n\t\t\t\tcase Tone.Type.AudioRange: \n\t\t\t\t\treturn Math.min(Math.max(val, -1), 1);\n\t\t\t\tcase Tone.Type.Positive: \n\t\t\t\t\treturn Math.max(val, 0);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * Convert the parameters value into the units specified by Tone.Param.units.\n\t * @private\n\t * @param {number} val the value to convert\n\t * @return {number}\n\t */\n\tTone.Param.prototype._toUnits = function(val){\n\t\tif (this.convert || this.isUndef(this.convert)){\n\t\t\tswitch(this.units){\n\t\t\t\tcase Tone.Type.Decibels: \n\t\t\t\t\treturn this.gainToDb(val);\n\t\t\t\tdefault:\n\t\t\t\t\treturn val;\n\t\t\t}\n\t\t} else {\n\t\t\treturn val;\n\t\t}\n\t};\n\n\t/**\n\t * the minimum output value\n\t * @type {Number}\n\t * @private\n\t */\n\tTone.Param.prototype._minOutput = 0.00001;\n\n\t/**\n\t * Schedules a parameter value change at the given time.\n\t * @param {*}\tvalue The value to set the signal.\n\t * @param {Time} time The time when the change should occur.\n\t * @returns {Tone.Param} this\n\t * @example\n\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t */\n\tTone.Param.prototype.setValueAtTime = function(value, time){\n\t\tvalue = this._fromUnits(value);\n\t\ttime = this.toSeconds(time);\n\t\tif (time <= this.now() + this.blockTime){\n\t\t\tthis._param.value = value;\n\t\t} else {\n\t\t\tthis._param.setValueAtTime(value, time);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Creates a schedule point with the current value at the current time.\n\t * This is useful for creating an automation anchor point in order to \n\t * schedule changes from the current value. \n\t *\n\t * @param {number=} now (Optionally) pass the now value in. \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setRampPoint = function(now){\n\t\tnow = this.defaultArg(now, this.now());\n\t\tvar currentVal = this._param.value;\n\t\t// exponentialRampToValueAt cannot ever ramp from or to 0\n\t\t// More info: https://bugzilla.mozilla.org/show_bug.cgi?id=1125600#c2\n\t\tif (currentVal === 0){\n\t\t\tcurrentVal = this._minOutput;\n\t\t}\n\t\tthis._param.setValueAtTime(currentVal, now);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules a linear continuous change in parameter value from the \n\t * previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.linearRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tthis._param.linearRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the previous scheduled parameter value to the given value.\n\t * \n\t * @param {number} value \n\t * @param {Time} endTime \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.exponentialRampToValueAtTime = function(value, endTime){\n\t\tvalue = this._fromUnits(value);\n\t\tvalue = Math.max(this._minOutput, value);\n\t\tthis._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an exponential continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //exponentially ramp to the value 2 over 4 seconds. \n\t * signal.exponentialRampToValue(2, 4);\n\t */\n\tTone.Param.prototype.exponentialRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Schedules an linear continuous change in parameter value from \n\t * the current time and current value to the given value over the \n\t * duration of the rampTime.\n\t * \n\t * @param {number} value The value to ramp to.\n\t * @param {Time} rampTime the time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //linearly ramp to the value 4 over 3 seconds. \n\t * signal.linearRampToValue(4, 3);\n\t */\n\tTone.Param.prototype.linearRampToValue = function(value, rampTime, startTime){\n\t\tstartTime = this.toSeconds(startTime);\n\t\tthis.setRampPoint(startTime);\n\t\tthis.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Start exponentially approaching the target value at the given time with\n\t * a rate having the given time constant.\n\t * @param {number} value \n\t * @param {Time} startTime \n\t * @param {number} timeConstant \n\t * @returns {Tone.Param} this \n\t */\n\tTone.Param.prototype.setTargetAtTime = function(value, startTime, timeConstant){\n\t\tvalue = this._fromUnits(value);\n\t\t// The value will never be able to approach without timeConstant > 0.\n\t\t// http://www.w3.org/TR/webaudio/#dfn-setTargetAtTime, where the equation\n\t\t// is described. 0 results in a division by 0.\n\t\tvalue = Math.max(this._minOutput, value);\n\t\ttimeConstant = Math.max(this._minOutput, timeConstant);\n\t\tthis._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Sets an array of arbitrary parameter values starting at the given time\n\t * for the given duration.\n\t * \t\n\t * @param {Array} values \n\t * @param {Time} startTime \n\t * @param {Time} duration \n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.setValueCurveAtTime = function(values, startTime, duration){\n\t\tfor (var i = 0; i < values.length; i++){\n\t\t\tvalues[i] = this._fromUnits(values[i]);\n\t\t}\n\t\tthis._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancels all scheduled parameter changes with times greater than or \n\t * equal to startTime.\n\t * \n\t * @param {Time} startTime\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.cancelScheduledValues = function(startTime){\n\t\tthis._param.cancelScheduledValues(this.toSeconds(startTime));\n\t\treturn this;\n\t};\n\n\t/**\n\t * Ramps to the given value over the duration of the rampTime. \n\t * Automatically selects the best ramp type (exponential or linear)\n\t * depending on the `units` of the signal\n\t * \n\t * @param {number} value \n\t * @param {Time} rampTime \tThe time that it takes the \n\t * value to ramp from it's current value\n\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t * @returns {Tone.Param} this\n\t * @example\n\t * //ramp to the value either linearly or exponentially \n\t * //depending on the \"units\" value of the signal\n\t * signal.rampTo(0, 10);\n\t * @example\n\t * //schedule it to ramp starting at a specific time\n\t * signal.rampTo(0, 10, 5)\n\t */\n\tTone.Param.prototype.rampTo = function(value, rampTime, startTime){\n\t\trampTime = this.defaultArg(rampTime, 0);\n\t\tif (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels){\n\t\t\tthis.exponentialRampToValue(value, rampTime, startTime);\n\t\t} else {\n\t\t\tthis.linearRampToValue(value, rampTime, startTime);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * The LFO created by the signal instance. If none\n\t * was created, this is null.\n\t * @type {Tone.LFO}\n\t * @readOnly\n\t * @memberOf Tone.Param#\n\t * @name lfo\n\t */\n\tObject.defineProperty(Tone.Param.prototype, \"lfo\", {\n\t\tget : function(){\n\t\t\treturn this._lfo;\n\t\t}\n\t});\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Param} this\n\t */\n\tTone.Param.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param = null;\n\t\tif (this._lfo){\n\t\t\tthis._lfo.dispose();\n\t\t\tthis._lfo = null;\n\t\t}\n\t\treturn this;\n\t};\n\n\treturn Tone.Param;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
Creates a signal that oscillates between -1.0 and 1.0.\r\n * By default, the oscillation takes the form of a sinusoidal\r\n * shape ('sine'). Additional types include 'triangle',\r\n * 'sawtooth' and 'square'. The frequency defaults to\r\n * 440 oscillations per second (440Hz, equal to the pitch of an\r\n * 'A' note).
\r\n *\r\n *
Set the type of oscillation with setType(), or by instantiating a\r\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\r\n *
\r\n *\r\n * @class p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] frequency defaults to 440Hz\r\n * @param {String} [type] type of oscillator. Options:\r\n * 'sine' (default), 'triangle',\r\n * 'sawtooth', 'square'\r\n * @example\r\n *
\r\n * var osc;\r\n * var playing = false;\r\n *\r\n * function setup() {\r\n * backgroundColor = color(255,0,255);\r\n * textAlign(CENTER);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.setType('sine');\r\n * osc.freq(240);\r\n * osc.amp(0);\r\n * osc.start();\r\n * }\r\n *\r\n * function draw() {\r\n * background(backgroundColor)\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * if (!playing) {\r\n * // ramp amplitude to 0.5 over 0.05 seconds\r\n * osc.amp(0.5, 0.05);\r\n * playing = true;\r\n * backgroundColor = color(0,255,255);\r\n * } else {\r\n * // ramp amplitude to 0 over 0.5 seconds\r\n * osc.amp(0, 0.5);\r\n * playing = false;\r\n * backgroundColor = color(255,0,255);\r\n * }\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Oscillator = function(freq, type) {\r\n if (typeof freq === 'string') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n } if (typeof type === 'number') {\r\n var f = type;\r\n type = freq;\r\n freq = f;\r\n }\r\n this.started = false;\r\n\r\n // components\r\n this.phaseAmount = undefined;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.f = freq || 440.0; // frequency\r\n this.oscillator.type = type || 'sine';\r\n this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime);\r\n\r\n // connections\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this._freqMods = []; // modulators connected to this oscillator's frequency\r\n\r\n // set default output gain to 0.5\r\n this.output.gain.value = 0.5;\r\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\r\n\r\n this.oscillator.connect(this.output);\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.connection = p5sound.input; // connect to p5sound by default\r\n this.panner = new p5.Panner(this.output, this.connection, 1);\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.output];\r\n\r\n // add to the soundArray so we can dispose of the osc later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start an oscillator. Accepts an optional parameter to\r\n * determine how long (in seconds from now) until the\r\n * oscillator starts.\r\n *\r\n * @method start\r\n * @for p5.Oscillator\r\n * @param {Number} [time] startTime in seconds from now.\r\n * @param {Number} [frequency] frequency in Hz.\r\n */\r\n p5.Oscillator.prototype.start = function(time, f) {\r\n if (this.started) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n }\r\n if (!this.started) {\r\n var freq = f || this.f;\r\n var type = this.oscillator.type;\r\n\r\n // set old osc free to be garbage collected (memory)\r\n if (this.oscillator) {\r\n this.oscillator.disconnect();\r\n delete this.oscillator;\r\n }\r\n\r\n // var detune = this.oscillator.frequency.value;\r\n this.oscillator = p5sound.audiocontext.createOscillator();\r\n this.oscillator.frequency.value = Math.abs(freq);\r\n this.oscillator.type = type;\r\n // this.oscillator.detune.value = detune;\r\n this.oscillator.connect(this.output);\r\n time = time || 0;\r\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\r\n this.freqNode = this.oscillator.frequency;\r\n\r\n // if other oscillators are already connected to this osc's freq\r\n for (var i in this._freqMods) {\r\n if (typeof this._freqMods[i].connect !== 'undefined') {\r\n this._freqMods[i].connect(this.oscillator.frequency);\r\n }\r\n }\r\n\r\n this.started = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop an oscillator. Accepts an optional parameter\r\n * to determine how long (in seconds from now) until the\r\n * oscillator stops.\r\n *\r\n * @method stop\r\n * @for p5.Oscillator\r\n * @param {Number} secondsFromNow Time, in seconds from now.\r\n */\r\n p5.Oscillator.prototype.stop = function(time) {\r\n if (this.started) {\r\n var t = time || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.oscillator.stop(t + now);\r\n this.started = false;\r\n }\r\n };\r\n\r\n /**\r\n * Set the amplitude between 0 and 1.0. Or, pass in an object\r\n * such as an oscillator to modulate amplitude with an audio signal.\r\n *\r\n * @method amp\r\n * @for p5.Oscillator\r\n * @param {Number|Object} vol between 0 and 1.0\r\n * or a modulating signal/oscillator\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @return {AudioParam} gain If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's\r\n * gain/amplitude/volume)\r\n */\r\n p5.Oscillator.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var self = this;\r\n if (typeof vol === 'number') {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n\r\n else if (vol) {\r\n vol.connect(self.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // these are now the same thing\r\n p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;\r\n\r\n p5.Oscillator.prototype.getAmp = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set frequency of an oscillator to a value. Or, pass in an object\r\n * such as an oscillator to modulate the frequency with an audio signal.\r\n *\r\n * @method freq\r\n * @for p5.Oscillator\r\n * @param {Number|Object} Frequency Frequency in Hz\r\n * or modulating signal/oscillator\r\n * @param {Number} [rampTime] Ramp time (in seconds)\r\n * @param {Number} [timeFromNow] Schedule this event to happen\r\n * at x seconds from now\r\n * @return {AudioParam} Frequency If no value is provided,\r\n * returns the Web Audio API\r\n * AudioParam that controls\r\n * this oscillator's frequency\r\n * @example\r\n *
\r\n * var osc = new p5.Oscillator(300);\r\n * osc.start();\r\n * osc.freq(40, 10);\r\n *
\r\n */\r\n p5.Oscillator.prototype.freq = function(val, rampTime, tFromNow) {\r\n if (typeof val === 'number' && !isNaN(val)) {\r\n this.f = val;\r\n var now = p5sound.audiocontext.currentTime;\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var t = now + tFromNow + rampTime;\r\n // var currentFreq = this.oscillator.frequency.value;\r\n // this.oscillator.frequency.cancelScheduledValues(now);\r\n\r\n if (rampTime === 0) {\r\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\r\n } else {\r\n if (val > 0 ) {\r\n this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);\r\n } else {\r\n this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now);\r\n }\r\n }\r\n\r\n // reset phase if oscillator has a phase\r\n if (this.phaseAmount) {\r\n this.phase(this.phaseAmount);\r\n }\r\n\r\n } else if (val) {\r\n if (val.output) {\r\n val = val.output;\r\n }\r\n val.connect(this.oscillator.frequency);\r\n\r\n // keep track of what is modulating this param\r\n // so it can be re-connected if\r\n this._freqMods.push( val );\r\n } else {\r\n // return the Frequency Node\r\n return this.oscillator.frequency;\r\n }\r\n };\r\n\r\n p5.Oscillator.prototype.getFreq = function() {\r\n return this.oscillator.frequency.value;\r\n };\r\n\r\n /**\r\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\r\n *\r\n * @method setType\r\n * @for p5.Oscillator\r\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\r\n */\r\n p5.Oscillator.prototype.setType = function(type) {\r\n this.oscillator.type = type;\r\n };\r\n\r\n p5.Oscillator.prototype.getType = function() {\r\n return this.oscillator.type;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.Oscillator\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.Oscillator.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n this.connection = unit.input;\r\n }\r\n else {\r\n this.panner.connect(unit);\r\n this.connection = unit;\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.Oscillator\r\n */\r\n p5.Oscillator.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n if (this.output) {\r\n this.output.connect(this.panner);\r\n }\r\n }\r\n this.oscMods = [];\r\n };\r\n\r\n /**\r\n * Pan between Left (-1) and Right (1)\r\n *\r\n * @method pan\r\n * @for p5.Oscillator\r\n * @param {Number} panning Number between -1 and 1\r\n * @param {Number} timeFromNow schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Oscillator.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n p5.Oscillator.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n // get rid of the oscillator\r\n p5.Oscillator.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.oscillator) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.stop(now);\r\n this.disconnect();\r\n this.panner = null;\r\n this.oscillator = null;\r\n }\r\n // if it is a Pulse\r\n if (this.osc2) {\r\n this.osc2.dispose();\r\n }\r\n };\r\n\r\n /**\r\n * Set the phase of an oscillator between 0.0 and 1.0.\r\n * In this implementation, phase is a delay time\r\n * based on the oscillator's current frequency.\r\n *\r\n * @method phase\r\n * @for p5.Oscillator\r\n * @param {Number} phase float between 0.0 and 1.0\r\n */\r\n p5.Oscillator.prototype.phase = function(p) {\r\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1/this.f);\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n this.phaseAmount = p;\r\n\r\n if (!this.dNode) {\r\n // create a delay node\r\n this.dNode = p5sound.audiocontext.createDelay();\r\n // put the delay node in between output and panner\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.dNode);\r\n this.dNode.connect(this.output);\r\n }\r\n\r\n // set delay time to match phase:\r\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\r\n };\r\n\r\n // ========================== //\r\n // SIGNAL MATH FOR MODULATION //\r\n // ========================== //\r\n\r\n // return sigChain(this, scale, thisChain, nextChain, Scale);\r\n var sigChain = function(o, mathObj, thisChain, nextChain, type) {\r\n var chainSource = o.oscillator;\r\n // if this type of math already exists in the chain, replace it\r\n for (var i in o.mathOps) {\r\n if (o.mathOps[i] instanceof type) {\r\n chainSource.disconnect();\r\n o.mathOps[i].dispose();\r\n thisChain = i;\r\n // assume nextChain is output gain node unless...\r\n if (thisChain < o.mathOps.length - 2) {\r\n nextChain = o.mathOps[i+1];\r\n }\r\n }\r\n }\r\n if (thisChain === o.mathOps.length - 1) {\r\n o.mathOps.push(nextChain);\r\n }\r\n // assume source is the oscillator unless i > 0\r\n if (i > 0) {\r\n chainSource = o.mathOps[i-1];\r\n }\r\n chainSource.disconnect();\r\n chainSource.connect(mathObj);\r\n mathObj.connect(nextChain);\r\n o.mathOps[thisChain] = mathObj;\r\n return o;\r\n };\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method again\r\n * will override the initial add() with a new value.\r\n *\r\n * @method add\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n *\r\n */\r\n p5.Oscillator.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Oscillator's output amplitude\r\n * by a fixed value (i.e. turn it up!). Calling this method\r\n * again will override the initial mult() with a new value.\r\n *\r\n * @method mult\r\n * @for p5.Oscillator\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with multiplied output\r\n */\r\n p5.Oscillator.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this oscillator's amplitude values to a given\r\n * range, and return the oscillator. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Oscillator\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Oscillator} Oscillator Returns this oscillator\r\n * with scaled output\r\n */\r\n p5.Oscillator.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n var thisChain = this.mathOps.length-1;\r\n var nextChain = this.output;\r\n return sigChain(this, scale, thisChain, nextChain, Scale);\r\n\r\n // this.output.disconnect();\r\n // this.output.connect(scale)\r\n };\r\n\r\n // ============================== //\r\n // SinOsc, TriOsc, SqrOsc, SawOsc //\r\n // ============================== //\r\n\r\n /**\r\n * Constructor: new p5.SinOsc().\r\n * This creates a Sine Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sine')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sine').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SinOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SinOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sine');\r\n };\r\n\r\n p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.TriOsc().\r\n * This creates a Triangle Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('triangle')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('triangle').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.TriOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.TriOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'triangle');\r\n };\r\n\r\n p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SawOsc().\r\n * This creates a SawTooth Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('sawtooth')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('sawtooth').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SawOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SawOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'sawtooth');\r\n };\r\n\r\n p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n /**\r\n * Constructor: new p5.SqrOsc().\r\n * This creates a Square Wave Oscillator and is\r\n * equivalent to new p5.Oscillator('square')\r\n * or creating a p5.Oscillator and then calling\r\n * its method setType('square').\r\n * See p5.Oscillator for methods.\r\n *\r\n * @class p5.SqrOsc\r\n * @constructor\r\n * @extends p5.Oscillator\r\n * @param {Number} [freq] Set the frequency\r\n */\r\n p5.SqrOsc = function(freq) {\r\n p5.Oscillator.call(this, freq, 'square');\r\n };\r\n\r\n p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline class for scheduling and maintaining state\n\t * along a timeline. All events must have a \"time\" property. \n\t * Internally, events are stored in time order for fast \n\t * retrieval.\n\t * @extends {Tone}\n\t * @param {Positive} [memory=Infinity] The number of previous events that are retained.\n\t */\n\tTone.Timeline = function(){\n\n\t\tvar options = this.optionsObject(arguments, [\"memory\"], Tone.Timeline.defaults);\n\n\t\t/**\n\t\t * The array of scheduled timeline events\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._timeline = [];\n\n\t\t/**\n\t\t * An array of items to remove from the list. \n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._toRemove = [];\n\n\t\t/**\n\t\t * Flag if the tieline is mid iteration\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._iterating = false;\n\n\t\t/**\n\t\t * The memory of the timeline, i.e.\n\t\t * how many events in the past it will retain\n\t\t * @type {Positive}\n\t\t */\n\t\tthis.memory = options.memory;\n\t};\n\n\tTone.extend(Tone.Timeline);\n\n\t/**\n\t * the default parameters\n\t * @static\n\t * @const\n\t */\n\tTone.Timeline.defaults = {\n\t\t\"memory\" : Infinity\n\t};\n\n\t/**\n\t * The number of items in the timeline.\n\t * @type {Number}\n\t * @memberOf Tone.Timeline#\n\t * @name length\n\t * @readOnly\n\t */\n\tObject.defineProperty(Tone.Timeline.prototype, \"length\", {\n\t\tget : function(){\n\t\t\treturn this._timeline.length;\n\t\t}\n\t});\n\n\t/**\n\t * Insert an event object onto the timeline. Events must have a \"time\" attribute.\n\t * @param {Object} event The event object to insert into the \n\t * timeline. \n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.add = function(event){\n\t\t//the event needs to have a time attribute\n\t\tif (this.isUndef(event.time)){\n\t\t\tthrow new Error(\"Tone.Timeline: events must have a time attribute\");\n\t\t}\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(event.time);\n\t\t\tthis._timeline.splice(index + 1, 0, event);\n\t\t} else {\n\t\t\tthis._timeline.push(event);\t\t\t\n\t\t}\n\t\t//if the length is more than the memory, remove the previous ones\n\t\tif (this.length > this.memory){\n\t\t\tvar diff = this.length - this.memory;\n\t\t\tthis._timeline.splice(0, diff);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Remove an event from the timeline.\n\t * @param {Object} event The event object to remove from the list.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.remove = function(event){\n\t\tif (this._iterating){\n\t\t\tthis._toRemove.push(event);\n\t\t} else {\n\t\t\tvar index = this._timeline.indexOf(event);\n\t\t\tif (index !== -1){\n\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Get the nearest event whose time is less than or equal to the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object set after that time.\n\t */\n\tTone.Timeline.prototype.get = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index !== -1){\n\t\t\treturn this._timeline[index];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Return the first event in the timeline without removing it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.peek = function(){\n\t\treturn this._timeline[0];\n\t};\n\n\t/**\n\t * Return the first event in the timeline and remove it\n\t * @returns {Object} The first event object\n\t */\n\tTone.Timeline.prototype.shift = function(){\n\t\treturn this._timeline.shift();\n\t};\n\n\t/**\n\t * Get the event which is scheduled after the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object after the given time\n\t */\n\tTone.Timeline.prototype.getAfter = function(time){\n\t\tvar index = this._search(time);\n\t\tif (index + 1 < this._timeline.length){\n\t\t\treturn this._timeline[index + 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Get the event before the event at the given time.\n\t * @param {Number} time The time to query.\n\t * @returns {Object} The event object before the given time\n\t */\n\tTone.Timeline.prototype.getBefore = function(time){\n\t\tvar len = this._timeline.length;\n\t\t//if it's after the last item, return the last item\n\t\tif (len > 0 && this._timeline[len - 1].time < time){\n\t\t\treturn this._timeline[len - 1];\n\t\t}\n\t\tvar index = this._search(time);\n\t\tif (index - 1 >= 0){\n\t\t\treturn this._timeline[index - 1];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Cancel events after the given time\n\t * @param {Number} time The time to query.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancel = function(after){\n\t\tif (this._timeline.length > 1){\n\t\t\tvar index = this._search(after);\n\t\t\tif (index >= 0){\n\t\t\t\tif (this._timeline[index].time === after){\n\t\t\t\t\t//get the first item with that time\n\t\t\t\t\tfor (var i = index; i >= 0; i--){\n\t\t\t\t\t\tif (this._timeline[i].time === after){\n\t\t\t\t\t\t\tindex = i;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index);\n\t\t\t\t} else {\n\t\t\t\t\tthis._timeline = this._timeline.slice(0, index + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t} else if (this._timeline.length === 1){\n\t\t\t//the first item's time\n\t\t\tif (this._timeline[0].time >= after){\n\t\t\t\tthis._timeline = [];\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Cancel events before or equal to the given time.\n\t * @param {Number} time The time to cancel before.\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.cancelBefore = function(time){\n\t\tif (this._timeline.length){\n\t\t\tvar index = this._search(time);\n\t\t\tif (index >= 0){\n\t\t\t\tthis._timeline = this._timeline.slice(index + 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Does a binary serach on the timeline array and returns the \n\t * nearest event index whose time is after or equal to the given time.\n\t * If a time is searched before the first index in the timeline, -1 is returned.\n\t * If the time is after the end, the index of the last item is returned.\n\t * @param {Number} time \n\t * @return {Number} the index in the timeline array \n\t * @private\n\t */\n\tTone.Timeline.prototype._search = function(time){\n\t\tvar beginning = 0;\n\t\tvar len = this._timeline.length;\n\t\tvar end = len;\n\t\tif (len > 0 && this._timeline[len - 1].time <= time){\n\t\t\treturn len - 1;\n\t\t}\n\t\twhile (beginning < end){\n\t\t\t// calculate the midpoint for roughly equal partition\n\t\t\tvar midPoint = Math.floor(beginning + (end - beginning) / 2);\n\t\t\tvar event = this._timeline[midPoint];\n\t\t\tvar nextEvent = this._timeline[midPoint + 1];\n\t\t\tif (event.time === time){\n\t\t\t\t//choose the last one that has the same time\n\t\t\t\tfor (var i = midPoint; i < this._timeline.length; i++){\n\t\t\t\t\tvar testEvent = this._timeline[i];\n\t\t\t\t\tif (testEvent.time === time){\n\t\t\t\t\t\tmidPoint = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time < time && nextEvent.time > time){\n\t\t\t\treturn midPoint;\n\t\t\t} else if (event.time > time){\n\t\t\t\t//search lower\n\t\t\t\tend = midPoint;\n\t\t\t} else if (event.time < time){\n\t\t\t\t//search upper\n\t\t\t\tbeginning = midPoint + 1;\n\t\t\t} \n\t\t}\n\t\treturn -1;\n\t};\n\n\t/**\n\t * Internal iterator. Applies extra safety checks for \n\t * removing items from the array. \n\t * @param {Function} callback \n\t * @param {Number=} lowerBound \n\t * @param {Number=} upperBound \n\t * @private\n\t */\n\tTone.Timeline.prototype._iterate = function(callback, lowerBound, upperBound){\n\t\tthis._iterating = true;\n\t\tlowerBound = this.defaultArg(lowerBound, 0);\n\t\tupperBound = this.defaultArg(upperBound, this._timeline.length - 1);\n\t\tfor (var i = lowerBound; i <= upperBound; i++){\n\t\t\tcallback(this._timeline[i]);\n\t\t}\n\t\tthis._iterating = false;\n\t\tif (this._toRemove.length > 0){\n\t\t\tfor (var j = 0; j < this._toRemove.length; j++){\n\t\t\t\tvar index = this._timeline.indexOf(this._toRemove[j]);\n\t\t\t\tif (index !== -1){\n\t\t\t\t\tthis._timeline.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._toRemove = [];\n\t\t}\n\t};\n\n\t/**\n\t * Iterate over everything in the array\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEach = function(callback){\n\t\tthis._iterate(callback);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or before the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachBefore = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(callback, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array after the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAfter = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at or after the given time. Similar to \n\t * forEachAfter, but includes the item(s) at the given time.\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachFrom = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar lowerBound = this._search(time);\n\t\t//work backwards until the event time is less than time\n\t\twhile (lowerBound >= 0 && this._timeline[lowerBound].time >= time){\n\t\t\tlowerBound--;\n\t\t}\n\t\tthis._iterate(callback, lowerBound + 1);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Iterate over everything in the array at the given time\n\t * @param {Number} time The time to check if items are before\n\t * @param {Function} callback The callback to invoke with every item\n\t * @returns {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.forEachAtTime = function(time, callback){\n\t\t//iterate over the items in reverse so that removing an item doesn't break things\n\t\tvar upperBound = this._search(time);\n\t\tif (upperBound !== -1){\n\t\t\tthis._iterate(function(event){\n\t\t\t\tif (event.time === time){\n\t\t\t\t\tcallback(event);\n\t\t\t\t} \n\t\t\t}, 0, upperBound);\n\t\t}\n\t\treturn this;\n\t};\n\n\t/**\n\t * Clean up.\n\t * @return {Tone.Timeline} this\n\t */\n\tTone.Timeline.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._timeline = null;\n\t\tthis._toRemove = null;\n\t};\n\n\treturn Tone.Timeline;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Multiply\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Negate the incoming signal. i.e. an input signal of 10 will output -10\n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var neg = new Tone.Negate();\n\t * var sig = new Tone.Signal(-2).connect(neg);\n\t * //output of neg is positive 2. \n\t */\n\tTone.Negate = function(){\n\t\t/**\n\t\t * negation is done by multiplying by -1\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = this.input = this.output = new Tone.Multiply(-1);\n\t};\n\n\tTone.extend(Tone.Negate, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Negate} this\n\t */\n\tTone.Negate.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Negate;\n});","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Multiply\", \"Tone/signal/WaveShaper\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class GreaterThanZero outputs 1 when the input is strictly greater than zero\n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var gt0 = new Tone.GreaterThanZero();\n\t * var sig = new Tone.Signal(0.01).connect(gt0);\n\t * //the output of gt0 is 1. \n\t * sig.value = 0;\n\t * //the output of gt0 is 0. \n\t */\n\tTone.GreaterThanZero = function(){\n\t\t\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._thresh = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val <= 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}, 127);\n\n\t\t/**\n\t\t * scale the first thresholded signal by a large value.\n\t\t * this will help with values which are very close to 0\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._scale = this.input = new Tone.Multiply(10000);\n\n\t\t//connections\n\t\tthis._scale.connect(this._thresh);\n\t};\n\n\tTone.extend(Tone.GreaterThanZero, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThanZero} this\n\t */\n\tTone.GreaterThanZero.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._scale.dispose();\n\t\tthis._scale = null;\n\t\tthis._thresh.dispose();\n\t\tthis._thresh = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThanZero;\n});","define([\"Tone/core/Tone\", \"Tone/signal/TimelineSignal\", \"Tone/core/TimelineState\", \n\t\"Tone/core/Emitter\", \"Tone/core/Context\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A sample accurate clock which provides a callback at the given rate. \n\t * While the callback is not sample-accurate (it is still susceptible to\n\t * loose JS timing), the time passed in as the argument to the callback\n\t * is precise. For most applications, it is better to use Tone.Transport\n\t * instead of the Clock by itself since you can synchronize multiple callbacks.\n\t *\n\t * \t@constructor\n\t * @extends {Tone.Emitter}\n\t * \t@param {function} callback The callback to be invoked with the time of the audio event\n\t * \t@param {Frequency} frequency The rate of the callback\n\t * \t@example\n\t * //the callback will be invoked approximately once a second\n\t * //and will print the time exactly once a second apart.\n\t * var clock = new Tone.Clock(function(time){\n\t * \tconsole.log(time);\n\t * }, 1);\n\t */\n\tTone.Clock = function(){\n\n\t\tTone.Emitter.call(this);\n\n\t\tvar options = this.optionsObject(arguments, [\"callback\", \"frequency\"], Tone.Clock.defaults);\n\n\t\t/**\n\t\t * The callback function to invoke at the scheduled tick.\n\t\t * @type {Function}\n\t\t */\n\t\tthis.callback = options.callback;\n\n\t\t/**\n\t\t * The next time the callback is scheduled.\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t\tthis._nextTick = 0;\n\n\t\t/**\n\t\t * The last state of the clock.\n\t\t * @type {State}\n\t\t * @private\n\t\t */\n\t\tthis._lastState = Tone.State.Stopped;\n\n\t\t/**\n\t\t * The rate the callback function should be invoked. \n\t\t * @type {BPM}\n\t\t * @signal\n\t\t */\n\t\tthis.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);\n\t\tthis._readOnly(\"frequency\");\n\n\t\t/**\n\t\t * The number of times the callback was invoked. Starts counting at 0\n\t\t * and increments after the callback was invoked. \n\t\t * @type {Ticks}\n\t\t * @readOnly\n\t\t */\n\t\tthis.ticks = 0;\n\n\t\t/**\n\t\t * The state timeline\n\t\t * @type {Tone.TimelineState}\n\t\t * @private\n\t\t */\n\t\tthis._state = new Tone.TimelineState(Tone.State.Stopped);\n\n\t\t/**\n\t\t * The loop function bound to its context. \n\t\t * This is necessary to remove the event in the end.\n\t\t * @type {Function}\n\t\t * @private\n\t\t */\n\t\tthis._boundLoop = this._loop.bind(this);\n\n\t\t//bind a callback to the worker thread\n \tthis.context.on(\"tick\", this._boundLoop);\n\t};\n\n\tTone.extend(Tone.Clock, Tone.Emitter);\n\n\t/**\n\t * The defaults\n\t * @const\n\t * @type {Object}\n\t */\n\tTone.Clock.defaults = {\n\t\t\"callback\" : Tone.noOp,\n\t\t\"frequency\" : 1,\n\t\t\"lookAhead\" : \"auto\",\n\t};\n\n\t/**\n\t * Returns the playback state of the source, either \"started\", \"stopped\" or \"paused\".\n\t * @type {Tone.State}\n\t * @readOnly\n\t * @memberOf Tone.Clock#\n\t * @name state\n\t */\n\tObject.defineProperty(Tone.Clock.prototype, \"state\", {\n\t\tget : function(){\n\t\t\treturn this._state.getValueAtTime(this.now());\n\t\t}\n\t});\n\n\t/**\n\t * Start the clock at the given time. Optionally pass in an offset\n\t * of where to start the tick counter from.\n\t * @param {Time} time The time the clock should start\n\t * @param {Ticks=} offset Where the tick counter starts counting from.\n\t * @return {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.start = function(time, offset){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) !== Tone.State.Started){\n\t\t\tthis._state.add({\n\t\t\t\t\"state\" : Tone.State.Started, \n\t\t\t\t\"time\" : time,\n\t\t\t\t\"offset\" : offset\n\t\t\t});\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * Stop the clock. Stopping the clock resets the tick counter to 0.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t * @example\n\t * clock.stop();\n\t */\n\tTone.Clock.prototype.stop = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tthis._state.cancel(time);\n\t\tthis._state.setStateAtTime(Tone.State.Stopped, time);\n\t\treturn this;\t\n\t};\n\n\n\t/**\n\t * Pause the clock. Pausing does not reset the tick counter.\n\t * @param {Time} [time=now] The time when the clock should stop.\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.pause = function(time){\n\t\ttime = this.toSeconds(time);\n\t\tif (this._state.getValueAtTime(time) === Tone.State.Started){\n\t\t\tthis._state.setStateAtTime(Tone.State.Paused, time);\n\t\t}\n\t\treturn this;\t\n\t};\n\n\t/**\n\t * The scheduling loop.\n\t * @param {Number} time The current page time starting from 0\n\t * when the page was loaded.\n\t * @private\n\t */\n\tTone.Clock.prototype._loop = function(){\n\t\t//get the frequency value to compute the value of the next loop\n\t\tvar now = this.now();\n\t\t//if it's started\n\t\tvar lookAhead = this.context.lookAhead;\n\t\tvar updateInterval = this.context.updateInterval;\n\t\tvar lagCompensation = this.context.lag * 2;\n\t\tvar loopInterval = now + lookAhead + updateInterval + lagCompensation;\n\t\twhile (loopInterval > this._nextTick && this._state){\n\t\t\tvar currentState = this._state.getValueAtTime(this._nextTick);\n\t\t\tif (currentState !== this._lastState){\n\t\t\t\tthis._lastState = currentState;\n\t\t\t\tvar event = this._state.get(this._nextTick);\n\t\t\t\t// emit an event\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\t//correct the time\n\t\t\t\t\tthis._nextTick = event.time;\n\t\t\t\t\tif (!this.isUndef(event.offset)){\n\t\t\t\t\t\tthis.ticks = event.offset;\n\t\t\t\t\t}\n\t\t\t\t\tthis.emit(\"start\", event.time, this.ticks);\n\t\t\t\t} else if (currentState === Tone.State.Stopped){\n\t\t\t\t\tthis.ticks = 0;\n\n\t\t\t\t\tthis.emit(\"stop\", event.time);\n\t\t\t\t} else if (currentState === Tone.State.Paused){\n\t\t\t\t\tthis.emit(\"pause\", event.time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar tickTime = this._nextTick;\n\t\t\tif (this.frequency){\n\t\t\t\tthis._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);\n\t\t\t\tif (currentState === Tone.State.Started){\n\t\t\t\t\tthis.callback(tickTime);\n\t\t\t\t\tthis.ticks++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state at the given time.\n\t * @param {Time} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t * @example\n\t * clock.start(\"+0.1\");\n\t * clock.getStateAtTime(\"+0.1\"); //returns \"started\"\n\t */\n\tTone.Clock.prototype.getStateAtTime = function(time){\n\t\ttime = this.toSeconds(time);\n\t\treturn this._state.getValueAtTime(time);\n\t};\n\n\t/**\n\t * Clean up\n\t * @returns {Tone.Clock} this\n\t */\n\tTone.Clock.prototype.dispose = function(){\n\t\tTone.Emitter.prototype.dispose.call(this);\n\t\tthis.context.off(\"tick\", this._boundLoop);\n\t\tthis._writable(\"frequency\");\n\t\tthis.frequency.dispose();\n\t\tthis.frequency = null;\n\t\tthis._boundLoop = null;\n\t\tthis._nextTick = Infinity;\n\t\tthis.callback = null;\n\t\tthis._state.dispose();\n\t\tthis._state = null;\n\t};\n\n\treturn Tone.Clock;\n});","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var AudioVoice = require('audioVoice');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n var DEFAULT_SUSTAIN = 0.15;\r\n\r\n /**\r\n * A MonoSynth is used as a single voice for sound synthesis.\r\n * This is a class to be used in conjunction with the PolySynth\r\n * class. Custom synthetisers should be built inheriting from\r\n * this class.\r\n *\r\n * @class p5.MonoSynth\r\n * @constructor\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 0.25;\r\n * // velocity (volume, from 0 to 1)\r\n * var v = 0.2;\r\n *\r\n * monoSynth.play(\"G3\", v, time, dur);\r\n * monoSynth.play(\"C4\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n\r\n p5.MonoSynth = function () {\r\n AudioVoice.call(this);\r\n\r\n this.oscillator = new p5.Oscillator();\r\n\r\n this.env = new p5.Envelope();\r\n this.env.setRange(1, 0);\r\n this.env.setExp(true);\r\n\r\n //set params\r\n this.setADSR(0.02, 0.25, 0.05, 0.35);\r\n\r\n // oscillator --> env --> this.output (gain) --> p5.soundOut\r\n this.oscillator.disconnect();\r\n this.oscillator.connect(this.output);\r\n\r\n this.env.disconnect();\r\n this.env.setInput(this.output.gain);\r\n\r\n // reset oscillator gain to 1.0\r\n this.oscillator.output.gain.value = 1.0;\r\n\r\n this.oscillator.start();\r\n this.connect();\r\n\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);\r\n\r\n /**\r\n * Play tells the MonoSynth to start playing a note. This method schedules\r\n * the calling of .triggerAttack and .triggerRelease.\r\n *\r\n * @method play\r\n * @for p5.MonoSynth\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var monoSynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * monoSynth = new p5.MonoSynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n * // note duration (in seconds)\r\n * var dur = 1/6;\r\n * // note velocity (volume, from 0 to 1)\r\n * var v = random();\r\n *\r\n * monoSynth.play(\"Fb3\", v, 0, dur);\r\n * monoSynth.play(\"Gb3\", v, time += dur, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n *\r\n */\r\n p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) {\r\n this.triggerAttack(note, velocity, ~~secondsFromNow);\r\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @param {String | Number} note the note you want to play, specified as a\r\n * frequency in Hertz (Number) or as a midi\r\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\r\n * See \r\n * Tone. Defaults to 440 hz\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @method triggerAttack\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n var secondsFromNow = ~~secondsFromNow;\r\n var freq = noteToFreq(note);\r\n var vel = velocity || 0.1;\r\n this.oscillator.freq(freq, 0, secondsFromNow);\r\n this.env.ramp(this.output.gain, secondsFromNow, vel);\r\n };\r\n\r\n /**\r\n * Trigger the release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @method triggerRelease\r\n * @for p5.MonoSynth\r\n * @example\r\n *
\r\n * var monoSynth = new p5.MonoSynth();\r\n *\r\n * function mousePressed() {\r\n * monoSynth.triggerAttack(\"E3\");\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * monoSynth.triggerRelease();\r\n * }\r\n *
\r\n */\r\n p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) {\r\n var secondsFromNow = secondsFromNow || 0;\r\n this.env.ramp(this.output.gain, secondsFromNow, 0);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.MonoSynth\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n */\r\n p5.MonoSynth.prototype.setADSR = function (attack,decay,sustain,release) {\r\n this.env.setADSR(attack, decay, sustain, release);\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters\r\n * @property {Number} attack\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} decay\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} sustain\r\n * @for p5.MonoSynth\r\n */\r\n /**\r\n * @property {Number} release\r\n * @for p5.MonoSynth\r\n */\r\n Object.defineProperties(p5.MonoSynth.prototype, {\r\n 'attack': {\r\n get : function() {\r\n return this.env.aTime;\r\n },\r\n set : function(attack) {\r\n this.env.setADSR(attack, this.env.dTime,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'decay': {\r\n get : function() {\r\n return this.env.dTime;\r\n },\r\n set : function(decay) {\r\n this.env.setADSR(this.env.aTime, decay,\r\n this.env.sPercent, this.env.rTime);\r\n }\r\n },\r\n 'sustain': {\r\n get : function() {\r\n return this.env.sPercent;\r\n },\r\n set : function(sustain) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n sustain, this.env.rTime);\r\n }\r\n },\r\n 'release': {\r\n get : function() {\r\n return this.env.rTime;\r\n },\r\n set : function(release) {\r\n this.env.setADSR(this.env.aTime, this.env.dTime,\r\n this.env.sPercent, release);\r\n }\r\n },\r\n });\r\n\r\n\r\n /**\r\n * MonoSynth amp\r\n * @method amp\r\n * @for p5.MonoSynth\r\n * @param {Number} vol desired volume\r\n * @param {Number} [rampTime] Time to reach new volume\r\n * @return {Number} new volume value\r\n */\r\n p5.MonoSynth.prototype.amp = function(vol, rampTime) {\r\n var t = rampTime || 0;\r\n if (typeof vol !== 'undefined') {\r\n this.oscillator.amp(vol, t);\r\n }\r\n return this.oscillator.amp().value;\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.MonoSynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n\r\n p5.MonoSynth.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.MonoSynth\r\n */\r\n p5.MonoSynth.prototype.dispose = function() {\r\n AudioVoice.prototype.dispose.apply(this);\r\n\r\n if (this.env) {\r\n this.env.dispose();\r\n }\r\n if (this.oscillator) {\r\n this.oscillator.dispose();\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\ndefine(function() {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * Base class for monophonic synthesizers. Any extensions of this class\r\n * should follow the API and implement the methods below in order to\r\n * remain compatible with p5.PolySynth();\r\n *\r\n * @class p5.AudioVoice\r\n * @constructor\r\n */\r\n p5.AudioVoice = function () {\r\n\t this.ac = p5sound.audiocontext;\r\n\t this.output = this.ac.createGain();\r\n\t this.connect();\r\n\t p5sound.soundArray.push(this);\r\n };\r\n\r\n p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {\r\n };\r\n\r\n p5.AudioVoice.prototype.amp = function(vol, rampTime) {\r\n };\r\n\r\n /**\r\n * Connect to p5 objects or Web Audio Nodes\r\n * @method connect\r\n * @for p5.AudioVoice\r\n * @param {Object} unit\r\n */\r\n p5.AudioVoice.prototype.connect = function(unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect from soundOut\r\n * @method disconnect\r\n * @for p5.AudioVoice\r\n */\r\n p5.AudioVoice.prototype.disconnect = function() {\r\n this.output.disconnect();\r\n };\r\n\r\n p5.AudioVoice.prototype.dispose = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n return p5.AudioVoice;\r\n});\r\n","'use strict';\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n var noteToFreq = require('helpers').noteToFreq;\r\n\r\n /**\r\n * An AudioVoice is used as a single voice for sound synthesis.\r\n * The PolySynth class holds an array of AudioVoice, and deals\r\n * with voices allocations, with setting notes to be played, and\r\n * parameters to be set.\r\n *\r\n * @class p5.PolySynth\r\n * @constructor\r\n *\r\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\r\n * the AudioVoice class. Defaults to p5.MonoSynth\r\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 1.5;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * // notes can overlap with each other\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, time += 1/3, dur);\r\n * polySynth.play(\"G3\", vel, time += 1/3, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n **/\r\n p5.PolySynth = function(audioVoice, maxVoices) {\r\n //audiovoices will contain maxVoices many monophonic synths\r\n this.audiovoices = [];\r\n\r\n /**\r\n * An object that holds information about which notes have been played and\r\n * which notes are currently being played. New notes are added as keys\r\n * on the fly. While a note has been attacked, but not released, the value of the\r\n * key is the audiovoice which is generating that note. When notes are released,\r\n * the value of the key becomes undefined.\r\n * @property notes\r\n */\r\n this.notes = {};\r\n\r\n //indices of the most recently used, and least recently used audiovoice\r\n this._newest = 0;\r\n this._oldest = 0;\r\n\r\n /**\r\n * A PolySynth must have at least 1 voice, defaults to 8\r\n * @property polyvalue\r\n */\r\n this.maxVoices = maxVoices || 8;\r\n\r\n /**\r\n * Monosynth that generates the sound for each note that is triggered. The\r\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\r\n * @property AudioVoice\r\n */\r\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\r\n\r\n /**\r\n * This value must only change as a note is attacked or released. Due to delay\r\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\r\n\t * @private\r\n * @property {Tone.TimelineSignal} _voicesInUse\r\n */\r\n this._voicesInUse = new TimelineSignal(0);\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n this.connect();\r\n\r\n //Construct the appropriate number of audiovoices\r\n this._allocateVoices();\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Construct the appropriate number of audiovoices\r\n * @private\r\n * @for p5.PolySynth\r\n * @method _allocateVoices\r\n */\r\n p5.PolySynth.prototype._allocateVoices = function() {\r\n for(var i = 0; i< this.maxVoices; i++) {\r\n this.audiovoices.push(new this.AudioVoice());\r\n this.audiovoices[i].disconnect();\r\n this.audiovoices[i].connect(this.output);\r\n }\r\n };\r\n\r\n /**\r\n * Play a note by triggering noteAttack and noteRelease with sustain time\r\n *\r\n * @method play\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\r\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var polySynth;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * cnv.mousePressed(playSynth);\r\n *\r\n * polySynth = new p5.PolySynth();\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *\r\n * function playSynth() {\r\n * // note duration (in seconds)\r\n * var dur = 0.1;\r\n *\r\n * // time from now (in seconds)\r\n * var time = 0;\r\n *\r\n * // velocity (volume, from 0 to 1)\r\n * var vel = 0.1;\r\n *\r\n * polySynth.play(\"G2\", vel, 0, dur);\r\n * polySynth.play(\"C3\", vel, 0, dur);\r\n * polySynth.play(\"G3\", vel, 0, dur);\r\n *\r\n * background(random(255), random(255), 255);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.play = function (note,velocity, secondsFromNow, susTime) {\r\n var susTime = susTime || 1;\r\n this.noteAttack(note, velocity, secondsFromNow);\r\n this.noteRelease(note, secondsFromNow + susTime);\r\n };\r\n\r\n\r\n /**\r\n * noteADSR sets the envelope for a specific note that has just been triggered.\r\n * Using this method modifies the envelope of whichever audiovoice is being used\r\n * to play the desired note. The envelope should be reset before noteRelease is called\r\n * in order to prevent the modified envelope from being used on other notes.\r\n *\r\n * @method noteADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [note] Midi note on which ADSR should be set.\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n\r\n p5.PolySynth.prototype.noteADSR = function (note,a,d,s,r,timeFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var timeFromNow = timeFromNow || 0;\r\n var t = now + timeFromNow\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].setADSR(a,d,s,r);\r\n };\r\n\r\n\r\n /**\r\n * Set the PolySynths global envelope. This method modifies the envelopes of each\r\n * monosynth so that all notes are played with this envelope.\r\n *\r\n * @method setADSR\r\n * @for p5.PolySynth\r\n * @param {Number} [attackTime] Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n **/\r\n p5.PolySynth.prototype.setADSR = function(a,d,s,r) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.setADSR(a,d,s,r);\r\n });\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of a MonoSynth.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go.\r\n *\r\n * @method noteAttack\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\r\n * @param {Number} [secondsFromNow] time from now (in seconds)\r\n * @example\r\n *
\r\n * var polySynth = new p5.PolySynth();\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n */\r\n p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) {\r\n //this value goes to the audiovoices which handle their own scheduling\r\n var secondsFromNow = ~~secondsFromNow;\r\n\r\n //this value is used by this._voicesInUse\r\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\r\n\r\n //Convert note to frequency if necessary. This is because entries into this.notes\r\n //should be based on frequency for the sake of consistency.\r\n var note = noteToFreq(_note);\r\n var velocity = _velocity || 0.1;\r\n\r\n var currentVoice;\r\n\r\n //Release the note if it is already playing\r\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\r\n this.noteRelease(note, 0);\r\n }\r\n\r\n //Check to see how many voices are in use at the time the note will start\r\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\r\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\r\n }\r\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\r\n //with a new note\r\n else {\r\n currentVoice = this._oldest;\r\n\r\n var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value);\r\n this.noteRelease(oldestNote);\r\n this._oldest = ( this._oldest + 1 ) % (this.maxVoices - 1);\r\n }\r\n\r\n //Overrite the entry in the notes object. A note (frequency value)\r\n //corresponds to the index of the audiovoice that is playing it\r\n this.notes[note] = new TimelineSignal();\r\n this.notes[note].setValueAtTime(currentVoice, acTime);\r\n\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //Add 1 and schedule this value at time 't', when this note will start playing\r\n var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value;\r\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\r\n\r\n //Then update all scheduled values that follow to increase by 1\r\n this._updateAfter(acTime, 1);\r\n\r\n this._newest = currentVoice;\r\n //The audiovoice handles the actual scheduling of the note\r\n if (typeof velocity === 'number') {\r\n var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2;\r\n velocity = velocity > maxRange ? maxRange : velocity;\r\n }\r\n this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);\r\n };\r\n\r\n /**\r\n * Private method to ensure accurate values of this._voicesInUse\r\n * Any time a new value is scheduled, it is necessary to increment all subsequent\r\n * scheduledValues after attack, and decrement all subsequent\r\n * scheduledValues after release\r\n *\r\n * @private\r\n * @for p5.PolySynth\r\n * @param {[type]} time [description]\r\n * @param {[type]} value [description]\r\n * @return {[type]} [description]\r\n */\r\n p5.PolySynth.prototype._updateAfter = function(time, value) {\r\n if(this._voicesInUse._searchAfter(time) === null) {\r\n return;\r\n } else{\r\n this._voicesInUse._searchAfter(time).value += value;\r\n var nextTime = this._voicesInUse._searchAfter(time).time;\r\n this._updateAfter(nextTime, value);\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Trigger the Release of an AudioVoice note. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method noteRelease\r\n * @for p5.PolySynth\r\n * @param {Number} [note] midi note on which attack should be triggered.\r\n * If no value is provided, all notes will be released.\r\n * @param {Number} [secondsFromNow] time to trigger the release\r\n * @example\r\n *
\r\n * var pitches = [\"G\", \"D\", \"G\", \"C\"];\r\n * var octaves = [2, 3, 4];\r\n * var polySynth = new p5.PolySynth();\r\n *\r\n * function mousePressed() {\r\n * // play a chord: multiple notes at the same time\r\n * for (var i = 0; i < 4; i++) {\r\n * var note = random(pitches) + random(octaves);\r\n * polySynth.noteAttack(note, 0.1);\r\n * }\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * // release all voices\r\n * polySynth.noteRelease();\r\n * }\r\n *
\r\n *\r\n */\r\n p5.PolySynth.prototype.noteRelease = function (_note,secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n // if a note value is not provided, release all voices\r\n if (!_note) {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.triggerRelease(tFromNow)\r\n });\r\n this._voicesInUse.setValueAtTime(0, t);\r\n for (var n in this.notes) {\r\n this.notes[n].dispose();\r\n delete this.notes[n];\r\n }\r\n return;\r\n }\r\n\r\n //Make sure note is in frequency inorder to query the this.notes object\r\n var note = noteToFreq(_note);\r\n\r\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\r\n console.warn('Cannot release a note that is not already playing');\r\n } else {\r\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\r\n //subtract 1 and schedule this value at time 't', when this note will stop playing\r\n var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);\r\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\r\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\r\n if (previousVal > 0) {\r\n this._updateAfter(t, -1);\r\n }\r\n\r\n this.audiovoices[ this.notes[note].getValueAtTime(t) ].triggerRelease(tFromNow);\r\n this.notes[note].dispose();\r\n delete this.notes[note];\r\n\r\n this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\r\n }\r\n\r\n };\r\n\r\n /**\r\n * Connect to a p5.sound / Web Audio object.\r\n *\r\n * @method connect\r\n * @for p5.PolySynth\r\n * @param {Object} unit A p5.sound or Web Audio object\r\n */\r\n p5.PolySynth.prototype.connect = function (unit) {\r\n var u = unit || p5sound.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all outputs\r\n *\r\n * @method disconnect\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Get rid of the MonoSynth and free up its resources / memory.\r\n *\r\n * @method dispose\r\n * @for p5.PolySynth\r\n */\r\n p5.PolySynth.prototype.dispose = function() {\r\n this.audiovoices.forEach(function(voice) {\r\n voice.dispose();\r\n });\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n require('audioworklet-polyfill');\r\n require('shims');\r\n require('audiocontext');\r\n var p5SOUND = require('master');\r\n require('helpers');\r\n require('errorHandler');\r\n require('audioWorklet');\r\n require('panner');\r\n require('soundfile');\r\n require('amplitude');\r\n require('fft');\r\n require('signal');\r\n require('oscillator');\r\n require('envelope');\r\n require('pulse');\r\n require('noise');\r\n require('audioin');\r\n require('filter');\r\n require('eq');\r\n require('panner3d');\r\n require('listener3d');\r\n require('delay');\r\n require('reverb');\r\n require('metro');\r\n require('looper');\r\n require('soundLoop');\r\n require('compressor');\r\n require('soundRecorder');\r\n require('peakDetect');\r\n require('gain');\r\n require('monosynth');\r\n require('polysynth');\r\n require('distortion');\r\n require('audioVoice');\r\n require('monosynth');\r\n require('polysynth');\r\n\r\n return p5SOUND;\r\n\r\n});\r\n","!function(){var e,t=[];function r(e){var r=this,n={},i=-1;this.parameters.forEach(function(e,o){var s=t[++i]||(t[i]=new Float32Array(r.bufferSize));s.fill(e.value),n[o]=s}),this.processor.realm.exec(\"self.sampleRate=sampleRate=\"+this.context.sampleRate+\";self.currentTime=currentTime=\"+this.context.currentTime);var s=o(e.inputBuffer),a=o(e.outputBuffer);this.instance.process([s],[a],n)}function o(e){for(var t=[],r=0;r= this.sampleLimit) {\\n this.stop();\\n return true;\\n }\\n\\n var input = inputs[0];\\n var output = outputs[0];\\n\\n for (var channel = 0; channel < output.length; ++channel) {\\n var inputChannel = input[channel];\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannel);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannel);\\n }\\n }\\n\\n this.recordedSamples += output[0].length;\\n return true;\\n }\\n }, {\\n key: \\\"record\\\",\\n value: function record(duration) {\\n if (duration) {\\n this.sampleLimit = Math.round(duration * sampleRate);\\n }\\n\\n this.recording = true;\\n }\\n }, {\\n key: \\\"stop\\\",\\n value: function stop() {\\n this.recording = false;\\n var buffers = this.getBuffers();\\n var leftBuffer = buffers[0].buffer;\\n var rightBuffer = buffers[1].buffer;\\n this.port.postMessage({\\n name: 'buffers',\\n leftBuffer: leftBuffer,\\n rightBuffer: rightBuffer\\n }, [leftBuffer, rightBuffer]);\\n this.clear();\\n }\\n }, {\\n key: \\\"getBuffers\\\",\\n value: function getBuffers() {\\n var buffers = [];\\n buffers.push(this.mergeBuffers(this.leftBuffers));\\n buffers.push(this.mergeBuffers(this.rightBuffers));\\n return buffers;\\n }\\n }, {\\n key: \\\"mergeBuffers\\\",\\n value: function mergeBuffers(channelBuffer) {\\n var result = new Float32Array(this.recordedSamples);\\n var offset = 0;\\n var lng = channelBuffer.length;\\n\\n for (var i = 0; i < lng; i++) {\\n var buffer = channelBuffer[i];\\n result.set(buffer, offset);\\n offset += buffer.length;\\n }\\n\\n return result;\\n }\\n }, {\\n key: \\\"clear\\\",\\n value: function clear() {\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.recordedSamples = 0;\\n this.sampleLimit = null;\\n }\\n }]);\\n\\n return RecorderProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);\"","export default \"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \\\"function\\\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \\\"function\\\") { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } if (typeof _cache !== \\\"undefined\\\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\\n\\nfunction isNativeReflectConstruct() { if (typeof Reflect === \\\"undefined\\\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \\\"function\\\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\\n\\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\\n\\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\\\"[native code]\\\") !== -1; }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\n// import processor name via preval.require so that it's available as a value at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\n\\nvar SoundFileProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\\n\\n function SoundFileProcessor() {\\n _classCallCheck(this, SoundFileProcessor);\\n\\n return _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).apply(this, arguments));\\n }\\n\\n _createClass(SoundFileProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs) {\\n var input = inputs[0];\\n var inputChannel = input[0];\\n var position = inputChannel[inputChannel.length - 1] || 0;\\n this.port.postMessage({\\n name: 'position',\\n position: position\\n });\\n return true;\\n }\\n }]);\\n\\n return SoundFileProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);\"","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n\r\n // Stereo panner\r\n // if there is a stereo panner node use it\r\n if(typeof ac.createStereoPanner !== 'undefined') {\r\n p5.Panner = function (input, output) {\r\n this.stereoPanner = this.input = ac.createStereoPanner();\r\n input.connect(this.stereoPanner);\r\n this.stereoPanner.connect(output);\r\n };\r\n\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n\r\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\r\n };\r\n\r\n //not implemented because stereopanner\r\n //node does not require this and will automatically\r\n //convert single channel or multichannel to stereo.\r\n //tested with single and stereo, not with (>2) multichannel\r\n p5.Panner.prototype.inputChannels = function() {};\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.stereoPanner.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.stereoPanner) {\r\n this.stereoPanner.disconnect();\r\n }\r\n };\r\n\r\n } else {\r\n // if there is no createStereoPanner object\r\n // such as in safari 7.1.7 at the time of writing this\r\n // use this method to create the effect\r\n p5.Panner = function(input, output, numInputChannels) {\r\n this.input = ac.createGain();\r\n input.connect(this.input);\r\n\r\n this.left = ac.createGain();\r\n this.right = ac.createGain();\r\n this.left.channelInterpretation = 'discrete';\r\n this.right.channelInterpretation = 'discrete';\r\n\r\n // if input is stereo\r\n if (numInputChannels > 1) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n this.input.connect(this.splitter);\r\n\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n else {\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n }\r\n\r\n this.output = ac.createChannelMerger(2);\r\n this.left.connect(this.output, 0, 1);\r\n this.right.connect(this.output, 0, 0);\r\n this.output.connect(output);\r\n };\r\n\r\n // -1 is left, +1 is right\r\n p5.Panner.prototype.pan = function(val, tFromNow) {\r\n var time = tFromNow || 0;\r\n var t = ac.currentTime + time;\r\n var v = (val + 1) / 2;\r\n var rightVal = Math.cos(v*Math.PI/2);\r\n var leftVal = Math.sin(v * Math.PI/2);\r\n this.left.gain.linearRampToValueAtTime(leftVal, t);\r\n this.right.gain.linearRampToValueAtTime(rightVal, t);\r\n };\r\n\r\n p5.Panner.prototype.inputChannels = function(numChannels) {\r\n if (numChannels === 1) {\r\n this.input.disconnect();\r\n this.input.connect(this.left);\r\n this.input.connect(this.right);\r\n } else if (numChannels === 2) {\r\n if (typeof(this.splitter === 'undefined')) {\r\n this.splitter = ac.createChannelSplitter(2);\r\n }\r\n this.input.disconnect();\r\n this.input.connect(this.splitter);\r\n this.splitter.connect(this.left, 1);\r\n this.splitter.connect(this.right, 0);\r\n }\r\n };\r\n\r\n p5.Panner.prototype.connect = function(obj) {\r\n this.output.connect(obj);\r\n };\r\n\r\n p5.Panner.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var CustomError = require('errorHandler');\r\n var p5sound = require('master');\r\n var ac = p5sound.audiocontext;\r\n var midiToFreq = require('helpers').midiToFreq;\r\n var convertToWav = require('helpers').convertToWav;\r\n var processorNames = require('./audioWorklet/processorNames');\r\n\r\n /**\r\n *
SoundFile object with a path to a file.
\r\n *\r\n *
The p5.SoundFile may not be available immediately because\r\n * it loads the file information asynchronously.
\r\n *\r\n *
To do something with the sound as soon as it loads\r\n * pass the name of a function as the second parameter.
\r\n *\r\n *
Only one file path is required. However, audio file formats\r\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\r\n * web browsers. If you want to ensure compatability, instead of a single\r\n * file path, you may include an Array of filepaths, and the browser will\r\n * choose a format that works.
\r\n *\r\n * @class p5.SoundFile\r\n * @constructor\r\n * @param {String|Array} path path to a sound file (String). Optionally,\r\n * you may include multiple file formats in\r\n * an array. Alternately, accepts an object\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if file fails to\r\n * load. This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\r\n * is loading. That function will\r\n * receive progress of the request to\r\n * load the sound file\r\n * (between 0 and 1) as its first\r\n * parameter. This progress\r\n * does not account for the additional\r\n * time needed to decode the audio data.\r\n *\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile = function(paths, onload, onerror, whileLoading) {\r\n if (typeof paths !== 'undefined') {\r\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\r\n var path = p5.prototype._checkFileFormats(paths);\r\n this.url = path;\r\n }\r\n else if(typeof paths === 'object') {\r\n if (!(window.File && window.FileReader && window.FileList && window.Blob)) {\r\n // The File API isn't supported in this browser\r\n throw 'Unable to load file because the File API is not supported';\r\n }\r\n }\r\n\r\n // if type is a p5.File...get the actual file\r\n if (paths.file) {\r\n paths = paths.file;\r\n }\r\n\r\n this.file = paths;\r\n }\r\n\r\n // private _onended callback, set by the method: onended(callback)\r\n this._onended = function() {};\r\n\r\n this._looping = false;\r\n this._playing = false;\r\n this._paused = false;\r\n this._pauseTime = 0;\r\n\r\n // cues for scheduling events with addCue() removeCue()\r\n this._cues = [];\r\n this._cueIDCounter = 0;\r\n\r\n // position of the most recently played sample\r\n this._lastPos = 0;\r\n this._counterNode = null;\r\n this._workletNode = null;\r\n\r\n // array of sources so that they can all be stopped!\r\n this.bufferSourceNodes = [];\r\n\r\n // current source\r\n this.bufferSourceNode = null;\r\n\r\n this.buffer = null;\r\n this.playbackRate = 1;\r\n\r\n this.input = p5sound.audiocontext.createGain();\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.reversed = false;\r\n\r\n // start and end of playback / loop\r\n this.startTime = 0;\r\n this.endTime = null;\r\n this.pauseTime = 0;\r\n\r\n // \"restart\" would stop playback before retriggering\r\n this.mode = 'sustain';\r\n\r\n // time that playback was started, in millis\r\n this.startMillis = null;\r\n\r\n // stereo panning\r\n this.panPosition = 0.0;\r\n this.panner = new p5.Panner(this.output, p5sound.input, 2);\r\n\r\n // it is possible to instantiate a soundfile with no path\r\n if (this.url || this.file) {\r\n this.load(onload, onerror);\r\n }\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n\r\n if (typeof whileLoading === 'function') {\r\n this._whileLoading = whileLoading;\r\n } else {\r\n this._whileLoading = function() {};\r\n }\r\n\r\n this._onAudioProcess = _onAudioProcess.bind(this);\r\n this._clearOnEnd = _clearOnEnd.bind(this);\r\n };\r\n\r\n // register preload handling of loadSound\r\n p5.prototype.registerPreloadMethod('loadSound', p5.prototype);\r\n\r\n /**\r\n * loadSound() returns a new p5.SoundFile from a specified\r\n * path. If called during preload(), the p5.SoundFile will be ready\r\n * to play in time for setup() and draw(). If called outside of\r\n * preload, the p5.SoundFile will not be ready immediately, so\r\n * loadSound accepts a callback as the second parameter. Using a\r\n * \r\n * local server is recommended when loading external files.\r\n *\r\n * @method loadSound\r\n * @for p5\r\n * @param {String|Array} path Path to the sound file, or an array with\r\n * paths to soundfiles in multiple formats\r\n * i.e. ['sound.ogg', 'sound.mp3'].\r\n * Alternately, accepts an object: either\r\n * from the HTML5 File API, or a p5.File.\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is\r\n * an error loading the file.\r\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\r\n * This function will receive the percentage loaded\r\n * so far, from 0.0 to 1.0.\r\n * @return {SoundFile} Returns a p5.SoundFile\r\n * @example\r\n *
\r\n */\r\n p5.prototype.loadSound = function(path, callback, onerror, whileLoading) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined' ) {\r\n window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n\r\n var self = this;\r\n var s = new p5.SoundFile(path, function() {\r\n if(typeof callback === 'function') {\r\n callback.apply(self, arguments);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, onerror, whileLoading);\r\n\r\n return s;\r\n };\r\n\r\n /**\r\n * This is a helper function that the p5.SoundFile calls to load\r\n * itself. Accepts a callback (the name of another function)\r\n * as an optional parameter.\r\n *\r\n * @private\r\n * @for p5.SoundFile\r\n * @param {Function} [successCallback] Name of a function to call once file loads\r\n * @param {Function} [errorCallback] Name of a function to call if there is an error\r\n */\r\n p5.SoundFile.prototype.load = function(callback, errorCallback) {\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n\r\n if (this.url !== undefined && this.url !== '') {\r\n var request = new XMLHttpRequest();\r\n request.addEventListener('progress', function(evt) {\r\n self._updateProgress(evt);\r\n }, false);\r\n request.open('GET', this.url, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on sucess loading file:\r\n if (!self.panner) return;\r\n ac.decodeAudioData(request.response,\r\n // success decoding buffer:\r\n function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n if (!self.panner) return;\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n if (!self.panner) return;\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url + '. The request status was: ' +\r\n request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadSound', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n\r\n request.send();\r\n }\r\n else if (this.file !== undefined) {\r\n var reader = new FileReader();\r\n reader.onload = function() {\r\n if (!self.panner) return;\r\n ac.decodeAudioData(reader.result, function(buff) {\r\n if (!self.panner) return;\r\n self.buffer = buff;\r\n self.panner.inputChannels(buff.numberOfChannels);\r\n if (callback) {\r\n callback(self);\r\n }\r\n });\r\n };\r\n reader.onerror = function(e) {\r\n if (!self.panner) return;\r\n if (onerror) {\r\n onerror(e);\r\n }\r\n };\r\n reader.readAsArrayBuffer(this.file);\r\n }\r\n };\r\n\r\n // TO DO: use this method to create a loading bar that shows progress during file upload/decode.\r\n p5.SoundFile.prototype._updateProgress = function(evt) {\r\n if (evt.lengthComputable) {\r\n var percentComplete = evt.loaded / evt.total * 0.99;\r\n this._whileLoading(percentComplete, evt);\r\n // ...\r\n } else {\r\n // Unable to compute progress information since the total size is unknown\r\n this._whileLoading('size unknown');\r\n }\r\n };\r\n\r\n /**\r\n * Returns true if the sound file finished loading successfully.\r\n *\r\n * @method isLoaded\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLoaded = function() {\r\n if (this.buffer) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n };\r\n\r\n /**\r\n * Play the p5.SoundFile\r\n *\r\n * @method play\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) amplitude (volume)\r\n * of playback\r\n * @param {Number} [cueStart] (optional) cue start time in seconds\r\n * @param {Number} [duration] (optional) duration of playback in seconds\r\n */\r\n p5.SoundFile.prototype.play = function(startTime, rate, amp, _cueStart, duration) {\r\n if (!this.output) {\r\n console.warn('SoundFile.play() called after dispose');\r\n return;\r\n }\r\n\r\n var self = this;\r\n var now = p5sound.audiocontext.currentTime;\r\n var cueStart, cueEnd;\r\n var time = startTime || 0;\r\n if (time < 0) {\r\n time = 0;\r\n }\r\n\r\n time = time + now;\r\n\r\n if (typeof rate !== 'undefined') {\r\n this.rate(rate);\r\n }\r\n\r\n if (typeof amp !== 'undefined') {\r\n this.setVolume(amp);\r\n }\r\n\r\n // TO DO: if already playing, create array of buffers for easy stop()\r\n if (this.buffer) {\r\n\r\n // reset the pause time (if it was paused)\r\n this._pauseTime = 0;\r\n\r\n // handle restart playmode\r\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\r\n this.bufferSourceNode.stop(time);\r\n this._counterNode.stop(time);\r\n }\r\n\r\n //dont create another instance if already playing\r\n if (this.mode === 'untildone' && this.isPlaying()) {\r\n return;\r\n }\r\n // make a new source and counter. They are automatically assigned playbackRate and buffer\r\n this.bufferSourceNode = this._initSourceNode();\r\n\r\n // garbage collect counterNode and create a new one\r\n delete this._counterNode;\r\n this._counterNode = this._initCounterNode();\r\n\r\n if (_cueStart) {\r\n if (_cueStart >=0 && _cueStart < this.buffer.duration) {\r\n // this.startTime = cueStart;\r\n cueStart = _cueStart;\r\n } else { throw 'start time out of range'; }\r\n } else {\r\n cueStart = 0;\r\n }\r\n\r\n if (duration) {\r\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\r\n duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration;\r\n }\r\n\r\n // if it was paused, play at the pause position\r\n if (this._paused) {\r\n this.bufferSourceNode.start(time, this.pauseTime, duration);\r\n this._counterNode.start(time, this.pauseTime, duration);\r\n } else {\r\n this.bufferSourceNode.start(time, cueStart, duration);\r\n this._counterNode.start(time, cueStart, duration);\r\n }\r\n\r\n this._playing = true;\r\n this._paused = false;\r\n\r\n // add source to sources array, which is used in stopAll()\r\n this.bufferSourceNodes.push(this.bufferSourceNode);\r\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\r\n\r\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\r\n }\r\n // If soundFile hasn't loaded the buffer yet, throw an error\r\n else {\r\n throw 'not ready to play file, buffer has yet to load. Try preload()';\r\n }\r\n\r\n // if looping, will restart at original time\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n\r\n if (this._looping === true) {\r\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\r\n this.bufferSourceNode.loopStart = cueStart;\r\n this.bufferSourceNode.loopEnd = cueEnd;\r\n this._counterNode.loopStart = cueStart;\r\n this._counterNode.loopEnd = cueEnd;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * p5.SoundFile has two play modes: restart and\r\n * sustain. Play Mode determines what happens to a\r\n * p5.SoundFile if it is triggered while in the middle of playback.\r\n * In sustain mode, playback will continue simultaneous to the\r\n * new playback. In restart mode, play() will stop playback\r\n * and start over. With untilDone, a sound will play only if it's\r\n * not already playing. Sustain is the default mode.\r\n *\r\n * @method playMode\r\n * @for p5.SoundFile\r\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\r\n * @example\r\n *
\r\n * var mySound;\r\n * function preload(){\r\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n * function mouseClicked() {\r\n * mySound.playMode('sustain');\r\n * mySound.play();\r\n * }\r\n * function keyPressed() {\r\n * mySound.playMode('restart');\r\n * mySound.play();\r\n * }\r\n *\r\n *
\r\n */\r\n p5.SoundFile.prototype.playMode = function(str) {\r\n var s = str.toLowerCase();\r\n\r\n // if restart, stop all other sounds from playing\r\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNodes[i].stop(now);\r\n }\r\n }\r\n\r\n // set play mode to effect future playback\r\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\r\n this.mode = s;\r\n } else {\r\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\r\n }\r\n };\r\n\r\n /**\r\n * Pauses a file that is currently playing. If the file is not\r\n * playing, then nothing will happen.\r\n *\r\n * After pausing, .play() will resume from the paused\r\n * position.\r\n * If p5.SoundFile had been set to loop before it was paused,\r\n * it will continue to loop after it is unpaused with .play().\r\n *\r\n * @method pause\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.pause = function(startTime) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = startTime || 0;\r\n var pTime = time + now;\r\n\r\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\r\n this.pauseTime = this.currentTime();\r\n this.bufferSourceNode.stop(pTime);\r\n this._counterNode.stop(pTime);\r\n this._paused = true;\r\n this._playing = false;\r\n\r\n this._pauseTime = this.currentTime();\r\n // TO DO: make sure play() still starts from orig start position\r\n } else {\r\n this._pauseTime = 0;\r\n }\r\n };\r\n\r\n /**\r\n * Loop the p5.SoundFile. Accepts optional parameters to set the\r\n * playback rate, playback volume, loopStart, loopEnd.\r\n *\r\n * @method loop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * seconds from now\r\n * @param {Number} [rate] (optional) playback rate\r\n * @param {Number} [amp] (optional) playback volume\r\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\r\n * @param {Number} [duration] (optional) loop duration in seconds\r\n */\r\n p5.SoundFile.prototype.loop = function(startTime, rate, amp, loopStart, duration) {\r\n this._looping = true;\r\n this.play(startTime, rate, amp, loopStart, duration);\r\n };\r\n\r\n /**\r\n * Set a p5.SoundFile's looping flag to true or false. If the sound\r\n * is currently playing, this change will take effect when it\r\n * reaches the end of the current playback.\r\n *\r\n * @method setLoop\r\n * @for p5.SoundFile\r\n * @param {Boolean} Boolean set looping to true or false\r\n */\r\n p5.SoundFile.prototype.setLoop = function(bool) {\r\n if (bool === true) {\r\n this._looping = true;\r\n }\r\n else if (bool === false) {\r\n this._looping = false;\r\n }\r\n else {\r\n throw 'Error: setLoop accepts either true or false';\r\n }\r\n if (this.bufferSourceNode) {\r\n this.bufferSourceNode.loop = this._looping;\r\n this._counterNode.loop = this._looping;\r\n }\r\n };\r\n\r\n /**\r\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\r\n *\r\n * @method isLooping\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isLooping = function() {\r\n if (!this.bufferSourceNode) {\r\n return false;\r\n }\r\n if (this._looping === true && this.isPlaying() === true) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\r\n * paused or stopped).\r\n *\r\n * @method isPlaying\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPlaying = function() {\r\n return this._playing;\r\n };\r\n\r\n /**\r\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\r\n * playing or stopped).\r\n *\r\n * @method isPaused\r\n * @for p5.SoundFile\r\n * @return {Boolean}\r\n */\r\n p5.SoundFile.prototype.isPaused = function() {\r\n return this._paused;\r\n };\r\n\r\n /**\r\n * Stop soundfile playback.\r\n *\r\n * @method stop\r\n * @for p5.SoundFile\r\n * @param {Number} [startTime] (optional) schedule event to occur\r\n * in seconds from now\r\n */\r\n p5.SoundFile.prototype.stop = function(timeFromNow) {\r\n var time = timeFromNow || 0;\r\n\r\n if (this.mode === 'sustain' || this.mode === 'untildone') {\r\n this.stopAll(time);\r\n this._playing = false;\r\n this.pauseTime = 0;\r\n this._paused = false;\r\n }\r\n else if (this.buffer && this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = time || 0;\r\n this.pauseTime = 0;\r\n this.bufferSourceNode.stop(now + t);\r\n this._counterNode.stop(now + t);\r\n this._playing = false;\r\n this._paused = false;\r\n }\r\n };\r\n\r\n /**\r\n * Stop playback on all of this soundfile's sources.\r\n * @private\r\n */\r\n p5.SoundFile.prototype.stopAll = function(_time) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var time = _time || 0;\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i in this.bufferSourceNodes) {\r\n const bufferSourceNode = this.bufferSourceNodes[i];\r\n if (!!bufferSourceNode) {\r\n try {\r\n bufferSourceNode.stop(now + time);\r\n } catch(e) {\r\n // this was throwing errors only on Safari\r\n }\r\n }\r\n }\r\n this._counterNode.stop(now + time);\r\n this._onended(this);\r\n }\r\n };\r\n\r\n /**\r\n * Multiply the output volume (amplitude) of a sound file\r\n * between 0.0 (silence) and 1.0 (full volume).\r\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\r\n * by greater than 1.0 may cause digital distortion. To\r\n * fade, provide a rampTime parameter. For more\r\n * complex fades, see the Envelope class.\r\n *\r\n * Alternately, you can pass in a signal source such as an\r\n * oscillator to modulate the amplitude with an audio signal.\r\n *\r\n * @method setVolume\r\n * @for p5.SoundFile\r\n * @param {Number|Object} volume Volume (amplitude) between 0.0\r\n * and 1.0 or modulating signal/oscillator\r\n * @param {Number} [rampTime] Fade for t seconds\r\n * @param {Number} [timeFromNow] Schedule this event to happen at\r\n * t seconds in the future\r\n */\r\n p5.SoundFile.prototype.setVolume = function(vol, _rampTime, _tFromNow) {\r\n if (typeof vol === 'number') {\r\n var rampTime = _rampTime || 0;\r\n var tFromNow = _tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n }\r\n else if (vol) {\r\n vol.connect(this.output.gain);\r\n } else {\r\n // return the Gain Node\r\n return this.output.gain;\r\n }\r\n };\r\n\r\n // same as setVolume, to match Processing Sound\r\n p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;\r\n\r\n // these are the same thing\r\n p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;\r\n\r\n p5.SoundFile.prototype.getVolume = function() {\r\n return this.output.gain.value;\r\n };\r\n\r\n /**\r\n * Set the stereo panning of a p5.sound object to\r\n * a floating point number between -1.0 (left) and 1.0 (right).\r\n * Default is 0.0 (center).\r\n *\r\n * @method pan\r\n * @for p5.SoundFile\r\n * @param {Number} [panValue] Set the stereo panner\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n * @example\r\n *
\r\n *\r\n * var ball = {};\r\n * var soundFile;\r\n *\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n * soundFile = loadSound('assets/beatbox.mp3');\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * ball.x = constrain(mouseX, 0, width);\r\n * ellipse(ball.x, height/2, 20, 20)\r\n * }\r\n *\r\n * function mousePressed(){\r\n * // map the ball's x location to a panning degree\r\n * // between -1.0 (left) and 1.0 (right)\r\n * var panning = map(ball.x, 0., width,-1.0, 1.0);\r\n * soundFile.pan(panning);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.pan = function(pval, tFromNow) {\r\n this.panPosition = pval;\r\n this.panner.pan(pval, tFromNow);\r\n };\r\n\r\n /**\r\n * Returns the current stereo pan position (-1.0 to 1.0)\r\n *\r\n * @method getPan\r\n * @for p5.SoundFile\r\n * @return {Number} Returns the stereo pan setting of the Oscillator\r\n * as a number between -1.0 (left) and 1.0 (right).\r\n * 0.0 is center and default.\r\n */\r\n p5.SoundFile.prototype.getPan = function() {\r\n return this.panPosition;\r\n };\r\n\r\n /**\r\n * Set the playback rate of a sound file. Will change the speed and the pitch.\r\n * Values less than zero will reverse the audio buffer.\r\n *\r\n * @method rate\r\n * @for p5.SoundFile\r\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\r\n * .5 is half-speed, 2.0 is twice as fast.\r\n * Values less than zero play backwards.\r\n * @example\r\n *
\r\n * var song;\r\n *\r\n * function preload() {\r\n * song = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * song.loop();\r\n * }\r\n *\r\n * function draw() {\r\n * background(200);\r\n *\r\n * // Set the rate to a range between 0.1 and 4\r\n * // Changing the rate also alters the pitch\r\n * var speed = map(mouseY, 0.1, height, 0, 2);\r\n * speed = constrain(speed, 0.01, 4);\r\n * song.rate(speed);\r\n *\r\n * // Draw a circle to show what is going on\r\n * stroke(0);\r\n * fill(51, 100);\r\n * ellipse(mouseX, 100, 48, 48);\r\n * }\r\n *\r\n * \r\n *
\r\n *\r\n */\r\n p5.SoundFile.prototype.rate = function(playbackRate) {\r\n var reverse = false;\r\n if (typeof playbackRate === 'undefined') {\r\n return this.playbackRate;\r\n }\r\n\r\n this.playbackRate = playbackRate;\r\n\r\n if (playbackRate === 0) {\r\n playbackRate = 0.0000000000001;\r\n }\r\n\r\n else if (playbackRate < 0 && !this.reversed) {\r\n playbackRate = Math.abs(playbackRate);\r\n reverse = true;\r\n }\r\n\r\n else if (playbackRate > 0 && this.reversed) {\r\n reverse = true;\r\n }\r\n\r\n if (this.bufferSourceNode) {\r\n var now = p5sound.audiocontext.currentTime;\r\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\r\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n this._counterNode.playbackRate.cancelScheduledValues(now);\r\n this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);\r\n }\r\n\r\n if (reverse) {\r\n this.reverseBuffer();\r\n }\r\n return this.playbackRate;\r\n };\r\n\r\n // TO DO: document this\r\n p5.SoundFile.prototype.setPitch = function(num) {\r\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\r\n this.rate(newPlaybackRate);\r\n };\r\n\r\n p5.SoundFile.prototype.getPlaybackRate = function() {\r\n return this.playbackRate;\r\n };\r\n\r\n /**\r\n * Returns the duration of a sound file in seconds.\r\n *\r\n * @method duration\r\n * @for p5.SoundFile\r\n * @return {Number} The duration of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.duration = function() {\r\n // Return Duration\r\n if (this.buffer) {\r\n return this.buffer.duration;\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n /**\r\n * Return the current position of the p5.SoundFile playhead, in seconds.\r\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\r\n * has been called, currentTime will count backwards.\r\n *\r\n * @method currentTime\r\n * @for p5.SoundFile\r\n * @return {Number} currentTime of the soundFile in seconds.\r\n */\r\n p5.SoundFile.prototype.currentTime = function() {\r\n return this.reversed\r\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\r\n : this._lastPos / ac.sampleRate;\r\n };\r\n\r\n /**\r\n * Move the playhead of the song to a position, in seconds. Start timing\r\n * and playback duration. If none are given, will reset the file to play\r\n * entire duration from start to finish.\r\n *\r\n * @method jump\r\n * @for p5.SoundFile\r\n * @param {Number} cueTime cueTime of the soundFile in seconds.\r\n * @param {Number} duration duration in seconds.\r\n */\r\n p5.SoundFile.prototype.jump = function(cueTime, duration) {\r\n if (cueTime < 0 || cueTime > this.buffer.duration) {\r\n throw 'jump time out of range';\r\n }\r\n if (duration > this.buffer.duration - cueTime) {\r\n throw 'end time out of range';\r\n }\r\n\r\n var cTime = cueTime || 0;\r\n var dur = duration || undefined;\r\n if (this.isPlaying()) {\r\n this.stop(0);\r\n }\r\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\r\n };\r\n\r\n /**\r\n * Return the number of channels in a sound file.\r\n * For example, Mono = 1, Stereo = 2.\r\n *\r\n * @method channels\r\n * @for p5.SoundFile\r\n * @return {Number} [channels]\r\n */\r\n p5.SoundFile.prototype.channels = function() {\r\n return this.buffer.numberOfChannels;\r\n };\r\n\r\n /**\r\n * Return the sample rate of the sound file.\r\n *\r\n * @method sampleRate\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleRate]\r\n */\r\n p5.SoundFile.prototype.sampleRate = function() {\r\n return this.buffer.sampleRate;\r\n };\r\n\r\n /**\r\n * Return the number of samples in a sound file.\r\n * Equal to sampleRate * duration.\r\n *\r\n * @method frames\r\n * @for p5.SoundFile\r\n * @return {Number} [sampleCount]\r\n */\r\n p5.SoundFile.prototype.frames = function() {\r\n return this.buffer.length;\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\r\n * used to draw a static waveform. Scans through the p5.SoundFile's\r\n * audio buffer to find the greatest amplitudes. Accepts one\r\n * parameter, 'length', which determines size of the array.\r\n * Larger arrays result in more precise waveform visualizations.\r\n *\r\n * Inspired by Wavesurfer.js.\r\n *\r\n * @method getPeaks\r\n * @for p5.SoundFile\r\n * @params {Number} [length] length is the size of the returned array.\r\n * Larger length results in more precision.\r\n * Defaults to 5*width of the browser window.\r\n * @returns {Float32Array} Array of peaks.\r\n */\r\n p5.SoundFile.prototype.getPeaks = function(length) {\r\n\r\n if (this.buffer) {\r\n // set length to window's width if no length is provided\r\n if (!length) {\r\n length = window.width*5;\r\n }\r\n if (this.buffer) {\r\n var buffer = this.buffer;\r\n var sampleSize = buffer.length / length;\r\n var sampleStep = ~~(sampleSize / 10) || 1;\r\n var channels = buffer.numberOfChannels;\r\n var peaks = new Float32Array(Math.round(length));\r\n\r\n for (var c = 0; c < channels; c++) {\r\n var chan = buffer.getChannelData(c);\r\n for (var i = 0; i < length; i++) {\r\n var start = ~~(i*sampleSize);\r\n var end = ~~(start + sampleSize);\r\n var max = 0;\r\n for (var j = start; j < end; j+= sampleStep) {\r\n var value = chan[j];\r\n if (value > max) {\r\n max = value;\r\n // faster than Math.abs\r\n } else if (-value > max) {\r\n max = value;\r\n }\r\n }\r\n if (c === 0 || Math.abs(max) > peaks[i]) {\r\n peaks[i] = max;\r\n }\r\n }\r\n }\r\n\r\n return peaks;\r\n }\r\n }\r\n\r\n else {\r\n throw 'Cannot load peaks yet, buffer is not loaded';\r\n }\r\n };\r\n\r\n /**\r\n * Reverses the p5.SoundFile's buffer source.\r\n * Playback must be handled separately (see example).\r\n *\r\n * @method reverseBuffer\r\n * @for p5.SoundFile\r\n * @example\r\n *
\r\n * var drum;\r\n *\r\n * function preload() {\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * drum.reverseBuffer();\r\n * drum.play();\r\n * }\r\n *\r\n * \r\n *
\r\n */\r\n p5.SoundFile.prototype.reverseBuffer = function() {\r\n if (this.buffer) {\r\n var currentPos = this._lastPos / ac.sampleRate;\r\n var curVol = this.getVolume();\r\n this.setVolume(0, 0.001);\r\n\r\n const numChannels = this.buffer.numberOfChannels;\r\n for (var i = 0; i < numChannels; i++) {\r\n this.buffer.getChannelData(i).reverse();\r\n }\r\n // set reversed flag\r\n this.reversed = !this.reversed;\r\n\r\n if (currentPos) {\r\n this.jump(this.duration() - currentPos);\r\n }\r\n this.setVolume(curVol, 0.001);\r\n } else {\r\n throw 'SoundFile is not done loading';\r\n }\r\n };\r\n\r\n /**\r\n * Schedule an event to be called when the soundfile\r\n * reaches the end of a buffer. If the soundfile is\r\n * playing through once, this will be called when it\r\n * ends. If it is looping, it will be called when\r\n * stop is called.\r\n *\r\n * @method onended\r\n * @for p5.SoundFile\r\n * @param {Function} callback function to call when the\r\n * soundfile has ended.\r\n */\r\n p5.SoundFile.prototype.onended = function(callback) {\r\n this._onended = callback;\r\n return this;\r\n };\r\n\r\n p5.SoundFile.prototype.add = function() {\r\n // TO DO\r\n };\r\n\r\n p5.SoundFile.prototype.dispose = function() {\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n // remove reference to soundfile\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop(now);\r\n if (this.buffer && this.bufferSourceNode) {\r\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\r\n if (this.bufferSourceNodes[i] !== null) {\r\n this.bufferSourceNodes[i].disconnect();\r\n try {\r\n this.bufferSourceNodes[i].stop(now);\r\n } catch(e) {\r\n console.warning('no buffer source node to dispose');\r\n }\r\n this.bufferSourceNodes[i] = null;\r\n }\r\n }\r\n if ( this.isPlaying() ) {\r\n try {\r\n this._counterNode.stop(now);\r\n } catch(e) {\r\n console.log(e);\r\n }\r\n this._counterNode = null;\r\n }\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n this.output = null;\r\n }\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n this.panner = null;\r\n }\r\n };\r\n\r\n /**\r\n * Connects the output of a p5sound object to input of another\r\n * p5.sound object. For example, you may connect a p5.SoundFile to an\r\n * FFT or an Effect. If no parameter is given, it will connect to\r\n * the master output. Most p5sound objects connect to the master\r\n * output when they are created.\r\n *\r\n * @method connect\r\n * @for p5.SoundFile\r\n * @param {Object} [object] Audio object that accepts an input\r\n */\r\n p5.SoundFile.prototype.connect = function(unit) {\r\n if (!unit) {\r\n this.panner.connect(p5sound.input);\r\n }\r\n else {\r\n if (unit.hasOwnProperty('input')) {\r\n this.panner.connect(unit.input);\r\n } else {\r\n this.panner.connect(unit);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Disconnects the output of this p5sound object.\r\n *\r\n * @method disconnect\r\n * @for p5.SoundFile\r\n */\r\n p5.SoundFile.prototype.disconnect = function() {\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n */\r\n p5.SoundFile.prototype.getLevel = function() {\r\n console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead');\r\n };\r\n\r\n /**\r\n * Reset the source for this SoundFile to a\r\n * new path (URL).\r\n *\r\n * @method setPath\r\n * @for p5.SoundFile\r\n * @param {String} path path to audio file\r\n * @param {Function} callback Callback\r\n */\r\n p5.SoundFile.prototype.setPath = function(p, callback) {\r\n var path = p5.prototype._checkFileFormats(p);\r\n this.url = path;\r\n this.load(callback);\r\n };\r\n\r\n /**\r\n * Replace the current Audio Buffer with a new Buffer.\r\n *\r\n * @method setBuffer\r\n * @for p5.SoundFile\r\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\r\n * will create a stereo source. 1 will create\r\n * a mono source.\r\n */\r\n p5.SoundFile.prototype.setBuffer = function(buf) {\r\n var numChannels = buf.length;\r\n var size = buf[0].length;\r\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\r\n\r\n if (!(buf[0] instanceof Float32Array)) {\r\n buf[0] = new Float32Array(buf[0]);\r\n }\r\n\r\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\r\n var channel = newBuffer.getChannelData( channelNum );\r\n channel.set(buf[channelNum]);\r\n }\r\n\r\n this.buffer = newBuffer;\r\n\r\n // set numbers of channels on input to the panner\r\n this.panner.inputChannels(numChannels);\r\n };\r\n\r\n //////////////////////////////////////////////////\r\n // script processor node with an empty buffer to help\r\n // keep a sample-accurate position in playback buffer.\r\n // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV\r\n // Copyright [2015] [Sonoport (Asia) Pte. Ltd.],\r\n // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0\r\n ////////////////////////////////////////////////////////////////////////////////////\r\n\r\n var _createCounterBuffer = function(buffer) {\r\n const len = buffer.length;\r\n const audioBuf = ac.createBuffer( 1, buffer.length, ac.sampleRate );\r\n const arrayBuffer = audioBuf.getChannelData(0);\r\n for (var index = 0; index < len; index++) {\r\n arrayBuffer[index] = index;\r\n }\r\n return audioBuf;\r\n };\r\n\r\n // initialize counterNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initCounterNode = function() {\r\n var self = this;\r\n var now = ac.currentTime;\r\n var cNode = ac.createBufferSource();\r\n\r\n // dispose of worklet node if it already exists\r\n if (self._workletNode) {\r\n self._workletNode.disconnect();\r\n delete self._workletNode;\r\n }\r\n self._workletNode = new AudioWorkletNode(ac, processorNames.soundFileProcessor);\r\n self._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'position') {\r\n this._lastPos = event.data.position;\r\n\r\n // do any callbacks that have been scheduled\r\n this._onTimeUpdate(self._lastPos);\r\n }\r\n }.bind(self);\r\n\r\n // create counter buffer of the same length as self.buffer\r\n cNode.buffer = _createCounterBuffer( self.buffer );\r\n\r\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\r\n\r\n cNode.connect(self._workletNode);\r\n self._workletNode.connect(p5.soundOut._silentNode);\r\n\r\n return cNode;\r\n };\r\n\r\n // initialize sourceNode, set its initial buffer and playbackRate\r\n p5.SoundFile.prototype._initSourceNode = function() {\r\n var bufferSourceNode = ac.createBufferSource();\r\n bufferSourceNode.buffer = this.buffer;\r\n bufferSourceNode.playbackRate.value = this.playbackRate;\r\n bufferSourceNode.connect(this.output);\r\n return bufferSourceNode;\r\n };\r\n\r\n /**\r\n * processPeaks returns an array of timestamps where it thinks there is a beat.\r\n *\r\n * This is an asynchronous function that processes the soundfile in an offline audio context,\r\n * and sends the results to your callback function.\r\n *\r\n * The process involves running the soundfile through a lowpass filter, and finding all of the\r\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\r\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\r\n *\r\n * @method processPeaks\r\n * @for p5.SoundFile\r\n * @param {Function} callback a function to call once this data is returned\r\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\r\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\r\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\r\n * @return {Array} Array of timestamped peaks\r\n */\r\n p5.SoundFile.prototype.processPeaks = function(callback, _initThreshold, _minThreshold, _minPeaks) {\r\n var bufLen = this.buffer.length;\r\n var sampleRate = this.buffer.sampleRate;\r\n var buffer = this.buffer;\r\n var allPeaks = [];\r\n\r\n var initialThreshold = _initThreshold || 0.9,\r\n threshold = initialThreshold,\r\n minThreshold = _minThreshold || 0.22,\r\n minPeaks = _minPeaks || 200;\r\n\r\n // Create offline context\r\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\r\n\r\n // create buffer source\r\n var source = offlineContext.createBufferSource();\r\n source.buffer = buffer;\r\n\r\n // Create filter. TO DO: allow custom setting of filter\r\n var filter = offlineContext.createBiquadFilter();\r\n filter.type = 'lowpass';\r\n source.connect(filter);\r\n filter.connect(offlineContext.destination);\r\n\r\n // start playing at time:0\r\n source.start(0);\r\n offlineContext.startRendering(); // Render the song\r\n\r\n // act on the result\r\n offlineContext.oncomplete = function(e) {\r\n if (!self.panner) return;\r\n var filteredBuffer = e.renderedBuffer;\r\n var bufferData = filteredBuffer.getChannelData(0);\r\n\r\n\r\n // step 1:\r\n // create Peak instances, add them to array, with strength and sampleIndex\r\n do {\r\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\r\n threshold -= 0.005;\r\n } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold);\r\n\r\n\r\n // step 2:\r\n // find intervals for each peak in the sampleIndex, add tempos array\r\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\r\n\r\n // step 3: find top tempos\r\n var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate);\r\n\r\n // sort top intervals\r\n var topTempos = groups.sort(function(intA, intB) {\r\n return intB.count - intA.count;\r\n\r\n }).splice(0,5);\r\n\r\n // set this SoundFile's tempo to the top tempo ??\r\n this.tempo = topTempos[0].tempo;\r\n\r\n // step 4:\r\n // new array of peaks at top tempo within a bpmVariance\r\n var bpmVariance = 5;\r\n var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance);\r\n\r\n callback(tempoPeaks);\r\n };\r\n };\r\n\r\n // process peaks\r\n var Peak = function(amp, i) {\r\n this.sampleIndex = i;\r\n this.amplitude = amp;\r\n this.tempos = [];\r\n this.intervals = [];\r\n };\r\n\r\n // 1. for processPeaks() Function to identify peaks above a threshold\r\n // returns an array of peak indexes as frames (samples) of the original soundfile\r\n function getPeaksAtThreshold(data, threshold) {\r\n var peaksObj = {};\r\n var length = data.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (data[i] > threshold) {\r\n var amp = data[i];\r\n var peak = new Peak(amp, i);\r\n peaksObj[i] = peak;\r\n // Skip forward ~ 1/8s to get past this peak.\r\n i += 6000;\r\n }\r\n i++;\r\n }\r\n return peaksObj;\r\n }\r\n\r\n // 2. for processPeaks()\r\n function countIntervalsBetweenNearbyPeaks(peaksObj) {\r\n var intervalCounts = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n for (var index = 0; index < peaksArray.length; index++) {\r\n\r\n // find intervals in comparison to nearby peaks\r\n for (var i = 0; i < 10; i++) {\r\n var startPeak = peaksObj[peaksArray[index]];\r\n var endPeak = peaksObj[peaksArray[index + i]];\r\n\r\n if (startPeak && endPeak) {\r\n var startPos = startPeak.sampleIndex;\r\n var endPos = endPeak.sampleIndex;\r\n var interval = endPos - startPos;\r\n\r\n // add a sample interval to the startPeak in the allPeaks array\r\n if (interval > 0) {\r\n startPeak.intervals.push(interval);\r\n }\r\n\r\n // tally the intervals and return interval counts\r\n var foundInterval = intervalCounts.some(function(intervalCount) {\r\n if (intervalCount.interval === interval) {\r\n intervalCount.count++;\r\n return intervalCount;\r\n }\r\n });\r\n\r\n // store with JSON like formatting\r\n if (!foundInterval) {\r\n intervalCounts.push({\r\n interval: interval,\r\n count: 1,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return intervalCounts;\r\n }\r\n\r\n\r\n // 3. for processPeaks --> find tempo\r\n function groupNeighborsByTempo(intervalCounts, sampleRate) {\r\n var tempoCounts = [];\r\n\r\n intervalCounts.forEach(function(intervalCount) {\r\n\r\n try {\r\n // Convert an interval to tempo\r\n var theoreticalTempo = Math.abs( 60 / (intervalCount.interval / sampleRate ) );\r\n\r\n theoreticalTempo = mapTempo(theoreticalTempo);\r\n\r\n var foundTempo = tempoCounts.some(function(tempoCount) {\r\n if (tempoCount.tempo === theoreticalTempo)\r\n return tempoCount.count += intervalCount.count;\r\n });\r\n if (!foundTempo) {\r\n if (isNaN(theoreticalTempo)) {\r\n return;\r\n }\r\n tempoCounts.push({\r\n tempo: Math.round(theoreticalTempo),\r\n count: intervalCount.count\r\n });\r\n }\r\n } catch(e) {\r\n throw e;\r\n }\r\n\r\n });\r\n\r\n return tempoCounts;\r\n }\r\n\r\n // 4. for processPeaks - get peaks at top tempo\r\n function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\r\n var peaksAtTopTempo = [];\r\n var peaksArray = Object.keys(peaksObj).sort();\r\n\r\n // TO DO: filter out peaks that have the tempo and return\r\n for (var i = 0; i < peaksArray.length; i++) {\r\n var key = peaksArray[i];\r\n var peak = peaksObj[key];\r\n\r\n for (var j = 0; j < peak.intervals.length; j++) {\r\n var intervalBPM = Math.round(Math.abs( 60 / (peak.intervals[j] / sampleRate) ) );\r\n\r\n intervalBPM = mapTempo(intervalBPM);\r\n\r\n if ( Math.abs(intervalBPM - tempo) < bpmVariance ) {\r\n // convert sampleIndex to seconds\r\n peaksAtTopTempo.push(peak.sampleIndex/sampleRate);\r\n }\r\n }\r\n }\r\n\r\n // filter out peaks that are very close to each other\r\n peaksAtTopTempo = peaksAtTopTempo.filter(function(peakTime, index, arr) {\r\n var dif = arr[index + 1] - peakTime;\r\n if (dif > 0.01) {\r\n return true;\r\n }\r\n });\r\n\r\n return peaksAtTopTempo;\r\n }\r\n\r\n // helper function for processPeaks\r\n function mapTempo(theoreticalTempo) {\r\n // these scenarios create infinite while loop\r\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0 ) {\r\n return;\r\n }\r\n\r\n // Adjust the tempo to fit within the 90-180 BPM range\r\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\r\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\r\n\r\n return theoreticalTempo;\r\n }\r\n\r\n\r\n /*** SCHEDULE EVENTS ***/\r\n\r\n // Cue inspired by JavaScript setTimeout, and the\r\n // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\r\n var Cue = function(callback, time, id, val) {\r\n this.callback = callback;\r\n this.time = time;\r\n this.id = id;\r\n this.val = val;\r\n };\r\n\r\n /**\r\n * Schedule events to trigger every time a MediaElement\r\n * (audio/video) reaches a playback cue point.\r\n *\r\n * Accepts a callback function, a time (in seconds) at which to trigger\r\n * the callback, and an optional parameter for the callback.\r\n *\r\n * Time will be passed as the first parameter to the callback function,\r\n * and param will be the second parameter.\r\n *\r\n *\r\n * @method addCue\r\n * @for p5.SoundFile\r\n * @param {Number} time Time in seconds, relative to this media\r\n * element's playback. For example, to trigger\r\n * an event every time playback reaches two\r\n * seconds, pass in the number 2. This will be\r\n * passed as the first parameter to\r\n * the callback function.\r\n * @param {Function} callback Name of a function that will be\r\n * called at the given time. The callback will\r\n * receive time and (optionally) param as its\r\n * two parameters.\r\n * @param {Object} [value] An object to be passed as the\r\n * second parameter to the\r\n * callback function.\r\n * @return {Number} id ID of this cue,\r\n * useful for removeCue(id)\r\n * @example\r\n *
\r\n */\r\n p5.SoundFile.prototype.addCue = function(time, callback, val) {\r\n var id = this._cueIDCounter++;\r\n\r\n var cue = new Cue(callback, time, id, val);\r\n this._cues.push(cue);\r\n\r\n // if (!this.elt.ontimeupdate) {\r\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\r\n // }\r\n\r\n return id;\r\n };\r\n\r\n /**\r\n * Remove a callback based on its ID. The ID is returned by the\r\n * addCue method.\r\n *\r\n * @method removeCue\r\n * @for p5.SoundFile\r\n * @param {Number} id ID of the cue, as returned by addCue\r\n */\r\n p5.SoundFile.prototype.removeCue = function(id) {\r\n var cueLength = this._cues.length;\r\n for (var i = 0; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n if (cue.id === id) {\r\n this._cues.splice(i, 1);\r\n break;\r\n }\r\n }\r\n\r\n if (this._cues.length === 0) {\r\n // TO DO: remove callback\r\n // this.elt.ontimeupdate = null\r\n }\r\n };\r\n\r\n /**\r\n * Remove all of the callbacks that had originally been scheduled\r\n * via the addCue method.\r\n *\r\n * @method clearCues\r\n */\r\n p5.SoundFile.prototype.clearCues = function() {\r\n this._cues = [];\r\n // this.elt.ontimeupdate = null;\r\n };\r\n\r\n // private method that checks for cues to be fired if events\r\n // have been scheduled using addCue(callback, time).\r\n p5.SoundFile.prototype._onTimeUpdate = function(position) {\r\n var playbackTime = position/this.buffer.sampleRate;\r\n var cueLength = this._cues.length;\r\n\r\n for (var i = 0 ; i < cueLength; i++) {\r\n var cue = this._cues[i];\r\n var callbackTime = cue.time;\r\n var val = cue.val;\r\n\r\n if (this._prevTime < callbackTime && callbackTime <= playbackTime) {\r\n\r\n // pass the scheduled callbackTime as parameter to the callback\r\n cue.callback(val);\r\n }\r\n\r\n }\r\n\r\n this._prevTime = playbackTime;\r\n };\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device. To upload a file to a server, see\r\n * getBlob\r\n *\r\n * @method save\r\n * @for p5.SoundFile\r\n * @param {String} [fileName] name of the resulting .wav file.\r\n * @example\r\n *
\r\n * var inp, button, mySound;\r\n * var fileName = 'cool';\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n * function setup() {\r\n * btn = createButton('click to save file');\r\n * btn.position(0, 0);\r\n * btn.mouseClicked(handleMouseClick);\r\n * }\r\n *\r\n * function handleMouseClick() {\r\n * mySound.save(fileName);\r\n * }\r\n *
\r\n */\r\n p5.SoundFile.prototype.save = function(fileName) {\r\n const dataView = convertToWav(this.buffer);\r\n p5.prototype.saveSound([dataView], fileName, 'wav');\r\n };\r\n\r\n /**\r\n * This method is useful for sending a SoundFile to a server. It returns the\r\n * .wav-encoded audio data as a \"Blob\".\r\n * A Blob is a file-like data object that can be uploaded to a server\r\n * with an http request. We'll\r\n * use the `httpDo` options object to send a POST request with some\r\n * specific options: we encode the request as `multipart/form-data`,\r\n * and attach the blob as one of the form values using `FormData`.\r\n *\r\n *\r\n * @method getBlob\r\n * @for p5.SoundFile\r\n * @returns {Blob} A file-like data object\r\n * @example\r\n *
\r\n *\r\n * function preload() {\r\n * mySound = loadSound('assets/doorbell.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noCanvas();\r\n * var soundBlob = mySound.getBlob();\r\n *\r\n * // Now we can send the blob to a server...\r\n * var serverUrl = 'https://jsonplaceholder.typicode.com/posts';\r\n * var httpRequestOptions = {\r\n * method: 'POST',\r\n * body: new FormData().append('soundBlob', soundBlob),\r\n * headers: new Headers({\r\n * 'Content-Type': 'multipart/form-data'\r\n * })\r\n * };\r\n * httpDo(serverUrl, httpRequestOptions);\r\n *\r\n * // We can also create an `ObjectURL` pointing to the Blob\r\n * var blobUrl = URL.createObjectURL(soundBlob);\r\n *\r\n * // The `
\r\n */\r\n p5.SoundFile.prototype.getBlob = function() {\r\n const dataView = convertToWav(this.buffer);\r\n return new Blob([dataView], { type: 'audio/wav' });\r\n };\r\n\r\n // event handler to keep track of current position\r\n function _onAudioProcess(processEvent) {\r\n var inputBuffer = processEvent.inputBuffer.getChannelData(0);\r\n\r\n this._lastPos = inputBuffer[inputBuffer.length - 1] || 0;\r\n\r\n // do any callbacks that have been scheduled\r\n this._onTimeUpdate(self._lastPos);\r\n }\r\n\r\n // event handler to remove references to the bufferSourceNode when it is done playing\r\n function _clearOnEnd(e) {\r\n const thisBufferSourceNode = e.target;\r\n const soundFile = this;\r\n\r\n // delete this.bufferSourceNode from the sources array when it is done playing:\r\n thisBufferSourceNode._playing = false;\r\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\r\n\r\n // call the onended callback\r\n soundFile._onended(soundFile);\r\n\r\n soundFile.bufferSourceNodes.forEach(function (n, i) {\r\n if (n._playing === false) {\r\n soundFile.bufferSourceNodes.splice(i);\r\n }\r\n });\r\n\r\n if (soundFile.bufferSourceNodes.length === 0) {\r\n soundFile._playing = false;\r\n }\r\n }\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var processorNames = require('./audioWorklet/processorNames');\r\n\r\n /**\r\n * Amplitude measures volume between 0.0 and 1.0.\r\n * Listens to all p5sound by default, or use setInput()\r\n * to listen to a specific sound source. Accepts an optional\r\n * smoothing value, which defaults to 0.\r\n *\r\n * @class p5.Amplitude\r\n * @constructor\r\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\r\n * amplitude readings (defaults to 0)\r\n * @example\r\n *
\r\n * var sound, amplitude, cnv;\r\n *\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * amplitude = new p5.Amplitude();\r\n *\r\n * // start / stop the sound when canvas is clicked\r\n * cnv.mouseClicked(function() {\r\n * if (sound.isPlaying() ){\r\n * sound.stop();\r\n * } else {\r\n * sound.play();\r\n * }\r\n * });\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n *\r\n *
\r\n */\r\n p5.Amplitude = function(smoothing) {\r\n\r\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\r\n this.bufferSize = 2048;\r\n\r\n // set audio context\r\n this.audiocontext = p5sound.audiocontext;\r\n this._workletNode = new AudioWorkletNode(this.audiocontext, processorNames.amplitudeProcessor, {\r\n outputChannelCount: [1],\r\n parameterData: { smoothing: smoothing || 0 },\r\n processorOptions: { normalize: false }\r\n });\r\n\r\n this._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'amplitude') {\r\n this.volume = event.data.volume;\r\n this.volNorm = event.data.volNorm;\r\n this.stereoVol = event.data.stereoVol;\r\n this.stereoVolNorm = event.data.stereoVolNorm;\r\n }\r\n }.bind(this);\r\n\r\n // for connections\r\n this.input = this._workletNode;\r\n\r\n this.output = this.audiocontext.createGain();\r\n\r\n // the variables to return\r\n this.volume = 0;\r\n this.volNorm = 0;\r\n this.stereoVol = [0, 0];\r\n this.stereoVolNorm = [0, 0];\r\n\r\n this.normalize = false;\r\n\r\n this._workletNode.connect(this.output);\r\n this.output.gain.value = 0;\r\n\r\n // this may only be necessary because of a Chrome bug\r\n this.output.connect(this.audiocontext.destination);\r\n\r\n // connect to p5sound master output by default, unless set by input()\r\n p5sound.meter.connect(this._workletNode);\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connects to the p5sound instance (master output) by default.\r\n * Optionally, you can pass in a specific source (i.e. a soundfile).\r\n *\r\n * @method setInput\r\n * @for p5.Amplitude\r\n * @param {soundObject|undefined} [snd] set the sound source\r\n * (optional, defaults to\r\n * master output)\r\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\r\n * to smooth amplitude readings\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound1 = loadSound('assets/beat.mp3');\r\n * sound2 = loadSound('assets/drum.mp3');\r\n * }\r\n * function setup(){\r\n * amplitude = new p5.Amplitude();\r\n * sound1.play();\r\n * sound2.play();\r\n * amplitude.setInput(sound2);\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound1.stop();\r\n * sound2.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.setInput = function(source, smoothing) {\r\n\r\n p5sound.meter.disconnect();\r\n\r\n if (smoothing) {\r\n this._workletNode.parameters.get('smoothing').value = smoothing;\r\n }\r\n\r\n // connect to the master out of p5s instance if no snd is provided\r\n if (source == null) {\r\n console.log('Amplitude input source is not ready! Connecting to master output instead');\r\n p5sound.meter.connect(this._workletNode);\r\n }\r\n\r\n // if it is a p5.Signal\r\n else if (source instanceof p5.Signal) {\r\n source.output.connect(this._workletNode);\r\n }\r\n // connect to the sound if it is available\r\n else if (source) {\r\n source.connect(this._workletNode);\r\n this._workletNode.disconnect();\r\n this._workletNode.connect(this.output);\r\n }\r\n\r\n // otherwise, connect to the master out of p5s instance (default)\r\n else {\r\n p5sound.meter.connect(this._workletNode);\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n } else {\r\n this.output.connect(unit);\r\n }\r\n } else {\r\n this.output.connect(this.panner.connect(p5sound.input));\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Returns a single Amplitude reading at the moment it is called.\r\n * For continuous readings, run in the draw loop.\r\n *\r\n * @method getLevel\r\n * @for p5.Amplitude\r\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\r\n * @return {Number} Amplitude as a number between 0.0 and 1.0\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n * function setup() {\r\n * amplitude = new p5.Amplitude();\r\n * sound.play();\r\n * }\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * var level = amplitude.getLevel();\r\n * var size = map(level, 0, 1, 0, 200);\r\n * ellipse(width/2, height/2, size, size);\r\n * }\r\n * function mouseClicked(){\r\n * sound.stop();\r\n * }\r\n *
\r\n */\r\n p5.Amplitude.prototype.getLevel = function(channel) {\r\n if (typeof channel !== 'undefined') {\r\n if (this.normalize) {\r\n return this.stereoVolNorm[channel];\r\n } else {\r\n return this.stereoVol[channel];\r\n }\r\n }\r\n else if (this.normalize) {\r\n return this.volNorm;\r\n }\r\n else {\r\n return this.volume;\r\n }\r\n };\r\n\r\n /**\r\n * Determines whether the results of Amplitude.process() will be\r\n * Normalized. To normalize, Amplitude finds the difference the\r\n * loudest reading it has processed and the maximum amplitude of\r\n * 1.0. Amplitude adds this difference to all values to produce\r\n * results that will reliably map between 0.0 and 1.0. However,\r\n * if a louder moment occurs, the amount that Normalize adds to\r\n * all the values will change. Accepts an optional boolean parameter\r\n * (true or false). Normalizing is off by default.\r\n *\r\n * @method toggleNormalize\r\n * @for p5.Amplitude\r\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\r\n */\r\n p5.Amplitude.prototype.toggleNormalize = function(bool) {\r\n if (typeof bool === 'boolean') {\r\n this.normalize = bool;\r\n }\r\n else {\r\n this.normalize = !this.normalize;\r\n }\r\n this._workletNode.port.postMessage({ name: 'toggleNormalize', normalize: this.normalize });\r\n };\r\n\r\n /**\r\n * Smooth Amplitude analysis by averaging with the last analysis\r\n * frame. Off by default.\r\n *\r\n * @method smooth\r\n * @for p5.Amplitude\r\n * @param {Number} set smoothing from 0.0 <= 1\r\n */\r\n p5.Amplitude.prototype.smooth = function(s) {\r\n if (s >= 0 && s < 1) {\r\n this._workletNode.parameters.get('smoothing').value = s;\r\n } else {\r\n console.log('Error: smoothing must be between 0 and 1');\r\n }\r\n };\r\n\r\n p5.Amplitude.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n\r\n this._workletNode.disconnect();\r\n delete this._workletNode;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n *
FFT (Fast Fourier Transform) is an analysis algorithm that\r\n * isolates individual\r\n * \r\n * audio frequencies within a waveform.
\r\n *\r\n *
Once instantiated, a p5.FFT object can return an array based on\r\n * two types of analyses: • FFT.waveform() computes\r\n * amplitude values along the time domain. The array indices correspond\r\n * to samples across a brief moment in time. Each value represents\r\n * amplitude of the waveform at that sample of time. \r\n * • FFT.analyze() computes amplitude values along the\r\n * frequency domain. The array indices correspond to frequencies (i.e.\r\n * pitches), from the lowest to the highest that humans can hear. Each\r\n * value represents amplitude at that slice of the frequency spectrum.\r\n * Use with getEnergy() to measure amplitude at specific\r\n * frequencies, or within a range of frequencies.
\r\n *\r\n *
FFT analyzes a very short snapshot of sound called a sample\r\n * buffer. It returns an array of amplitude measurements, referred\r\n * to as bins. The array is 1024 bins long by default.\r\n * You can change the bin array length, but it must be a power of 2\r\n * between 16 and 1024 in order for the FFT algorithm to function\r\n * correctly. The actual size of the FFT buffer is twice the\r\n * number of bins, so given a standard sample rate, the buffer is\r\n * 2048/44100 seconds long.
\r\n *\r\n *\r\n * @class p5.FFT\r\n * @constructor\r\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\r\n * 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n * @param {Number} [bins] Length of resulting array.\r\n * Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @example\r\n *
\r\n * function preload(){\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup(){\r\n * var cnv = createCanvas(100,100);\r\n * cnv.mouseClicked(togglePlay);\r\n * fft = new p5.FFT();\r\n * sound.amp(0.2);\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h )\r\n * }\r\n *\r\n * var waveform = fft.waveform();\r\n * noFill();\r\n * beginShape();\r\n * stroke(255,0,0); // waveform is red\r\n * strokeWeight(1);\r\n * for (var i = 0; i< waveform.length; i++){\r\n * var x = map(i, 0, waveform.length, 0, width);\r\n * var y = map( waveform[i], -1, 1, 0, height);\r\n * vertex(x,y);\r\n * }\r\n * endShape();\r\n *\r\n * text('click to play/pause', 4, 10);\r\n * }\r\n *\r\n * // fade sound if mouse is over canvas\r\n * function togglePlay() {\r\n * if (sound.isPlaying()) {\r\n * sound.pause();\r\n * } else {\r\n * sound.loop();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.FFT = function(smoothing, bins) {\r\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\r\n\r\n Object.defineProperties(this, {\r\n bins: {\r\n get: function() {\r\n return this.analyser.fftSize / 2;\r\n },\r\n set: function(b) {\r\n this.analyser.fftSize = b * 2;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n },\r\n smoothing: {\r\n get: function() {\r\n return this.analyser.smoothingTimeConstant;\r\n },\r\n set: function(s) {\r\n this.analyser.smoothingTimeConstant = s;\r\n },\r\n configurable: true,\r\n enumerable: true\r\n }\r\n });\r\n\r\n // set default smoothing and bins\r\n this.smooth(smoothing);\r\n this.bins = bins || 1024;\r\n\r\n // default connections to p5sound fftMeter\r\n p5sound.fftMeter.connect(this.analyser);\r\n\r\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\r\n\r\n // predefined frequency ranges, these will be tweakable\r\n this.bass = [20, 140];\r\n this.lowMid = [140, 400];\r\n this.mid = [400, 2600];\r\n this.highMid = [2600, 5200];\r\n this.treble = [5200, 14000];\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Set the input source for the FFT analysis. If no source is\r\n * provided, FFT will analyze all sound in the sketch.\r\n *\r\n * @method setInput\r\n * @for p5.FFT\r\n * @param {Object} [source] p5.sound object (or web audio API source node)\r\n */\r\n p5.FFT.prototype.setInput = function(source) {\r\n if (!source) {\r\n p5sound.fftMeter.connect(this.analyser);\r\n } else {\r\n if (source.output) {\r\n source.output.connect(this.analyser);\r\n } else if (source.connect) {\r\n source.connect(this.analyser);\r\n }\r\n p5sound.fftMeter.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\r\n * a snapshot of amplitude readings in a single buffer. Length will be\r\n * equal to bins (defaults to 1024). Can be used to draw the waveform\r\n * of a sound.\r\n *\r\n * @method waveform\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {String} [precision] If any value is provided, will return results\r\n * in a Float32 Array which is more precise\r\n * than a regular array.\r\n * @return {Array} Array Array of amplitude values (-1 to 1)\r\n * over time. Array length = bins.\r\n *\r\n */\r\n p5.FFT.prototype.waveform = function() {\r\n var bins, mode, normalArray;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n bins = arguments[i];\r\n this.analyser.fftSize = bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\r\n if (mode && !p5.prototype._isSafari()) {\r\n timeToFloat(this, this.timeDomain);\r\n this.analyser.getFloatTimeDomainData(this.timeDomain);\r\n return this.timeDomain;\r\n } else {\r\n timeToInt(this, this.timeDomain);\r\n this.analyser.getByteTimeDomainData(this.timeDomain);\r\n var normalArray = new Array();\r\n for (var j = 0; j < this.timeDomain.length; j++) {\r\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\r\n normalArray.push(scaled);\r\n }\r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of amplitude values (between 0 and 255)\r\n * across the frequency spectrum. Length is equal to FFT bins\r\n * (1024 by default). The array indices correspond to frequencies\r\n * (i.e. pitches), from the lowest to the highest that humans can\r\n * hear. Each value represents amplitude at that slice of the\r\n * frequency spectrum. Must be called prior to using\r\n * getEnergy().\r\n *\r\n * @method analyze\r\n * @for p5.FFT\r\n * @param {Number} [bins] Must be a power of two between\r\n * 16 and 1024. Defaults to 1024.\r\n * @param {Number} [scale] If \"dB,\" returns decibel\r\n * float measurements between\r\n * -140 and 0 (max).\r\n * Otherwise returns integers from 0-255.\r\n * @return {Array} spectrum Array of energy (amplitude/volume)\r\n * values across the frequency spectrum.\r\n * Lowest energy (silence) = 0, highest\r\n * possible is 255.\r\n * @example\r\n *
\r\n * var osc;\r\n * var fft;\r\n *\r\n * function setup(){\r\n * createCanvas(100,100);\r\n * osc = new p5.Oscillator();\r\n * osc.amp(0);\r\n * osc.start();\r\n * fft = new p5.FFT();\r\n * }\r\n *\r\n * function draw(){\r\n * background(0);\r\n *\r\n * var freq = map(mouseX, 0, 800, 20, 15000);\r\n * freq = constrain(freq, 1, 20000);\r\n * osc.freq(freq);\r\n *\r\n * var spectrum = fft.analyze();\r\n * noStroke();\r\n * fill(0,255,0); // spectrum is green\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(i, 0, spectrum.length, 0, width);\r\n * var h = -height + map(spectrum[i], 0, 255, height, 0);\r\n * rect(x, height, width / spectrum.length, h );\r\n * }\r\n *\r\n * stroke(255);\r\n * text('Freq: ' + round(freq)+'Hz', 10, 10);\r\n *\r\n * isMouseOverCanvas();\r\n * }\r\n *\r\n * // only play sound when mouse is over canvas\r\n * function isMouseOverCanvas() {\r\n * var mX = mouseX, mY = mouseY;\r\n * if (mX > 0 && mX < width && mY < height && mY > 0) {\r\n * osc.amp(0.5, 0.2);\r\n * } else {\r\n * osc.amp(0, 0.2);\r\n * }\r\n * }\r\n *
\r\n *\r\n *\r\n */\r\n p5.FFT.prototype.analyze = function() {\r\n var mode;\r\n\r\n for (var i = 0; i < arguments.length; i++) {\r\n if (typeof arguments[i] === 'number') {\r\n this.bins = arguments[i];\r\n this.analyser.fftSize = this.bins * 2;\r\n }\r\n if (typeof arguments[i] === 'string') {\r\n mode = arguments[i];\r\n }\r\n }\r\n\r\n if (mode && mode.toLowerCase() === 'db') {\r\n freqToFloat(this);\r\n this.analyser.getFloatFrequencyData(this.freqDomain);\r\n return this.freqDomain;\r\n } else {\r\n freqToInt(this, this.freqDomain);\r\n this.analyser.getByteFrequencyData(this.freqDomain);\r\n var normalArray = Array.apply([], this.freqDomain);\r\n \r\n return normalArray;\r\n }\r\n };\r\n\r\n /**\r\n * Returns the amount of energy (volume) at a specific\r\n * \r\n * frequency, or the average amount of energy between two\r\n * frequencies. Accepts Number(s) corresponding\r\n * to frequency (in Hz), or a String corresponding to predefined\r\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\r\n * Returns a range between 0 (no energy/volume at that frequency) and\r\n * 255 (maximum energy).\r\n * NOTE: analyze() must be called prior to getEnergy(). Analyze()\r\n * tells the FFT to analyze frequency data, and getEnergy() uses\r\n * the results determine the value at a specific frequency or\r\n * range of frequencies.\r\n *\r\n * @method getEnergy\r\n * @for p5.FFT\r\n * @param {Number|String} frequency1 Will return a value representing\r\n * energy at this frequency. Alternately,\r\n * the strings \"bass\", \"lowMid\" \"mid\",\r\n * \"highMid\", and \"treble\" will return\r\n * predefined frequency ranges.\r\n * @param {Number} [frequency2] If a second frequency is given,\r\n * will return average amount of\r\n * energy that exists between the\r\n * two frequencies.\r\n * @return {Number} Energy Energy (volume/amplitude) from\r\n * 0 and 255.\r\n *\r\n */\r\n p5.FFT.prototype.getEnergy = function(frequency1, frequency2) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n\r\n if (frequency1 === 'bass') {\r\n frequency1 = this.bass[0];\r\n frequency2 = this.bass[1];\r\n } else if (frequency1 === 'lowMid') {\r\n frequency1 = this.lowMid[0];\r\n frequency2 = this.lowMid[1];\r\n } else if (frequency1 === 'mid') {\r\n frequency1 = this.mid[0];\r\n frequency2 = this.mid[1];\r\n } else if (frequency1 === 'highMid') {\r\n frequency1 = this.highMid[0];\r\n frequency2 = this.highMid[1];\r\n } else if (frequency1 === 'treble') {\r\n frequency1 = this.treble[0];\r\n frequency2 = this.treble[1];\r\n }\r\n\r\n if (typeof frequency1 !== 'number') {\r\n throw 'invalid input for getEnergy()';\r\n } else if (!frequency2) {\r\n // if only one parameter:\r\n var index = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n return this.freqDomain[index];\r\n } else if (frequency1 && frequency2) {\r\n // if two parameters:\r\n // if second is higher than first\r\n if (frequency1 > frequency2) {\r\n var swap = frequency2;\r\n frequency2 = frequency1;\r\n frequency1 = swap;\r\n }\r\n var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length);\r\n var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length);\r\n\r\n var total = 0;\r\n var numFrequencies = 0;\r\n // add up all of the values for the frequencies\r\n for (var i = lowIndex; i <= highIndex; i++) {\r\n total += this.freqDomain[i];\r\n numFrequencies += 1;\r\n }\r\n // divide by total number of frequencies\r\n var toReturn = total / numFrequencies;\r\n return toReturn;\r\n } else {\r\n throw 'invalid input for getEnergy()';\r\n }\r\n };\r\n\r\n // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\r\n p5.FFT.prototype.getFreq = function(freq1, freq2) {\r\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\r\n var x = this.getEnergy(freq1, freq2);\r\n return x;\r\n };\r\n\r\n /**\r\n * Returns the\r\n * \r\n * spectral centroid of the input signal.\r\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\r\n * tells the FFT to analyze frequency data, and getCentroid() uses\r\n * the results determine the spectral centroid.\r\n *\r\n * @method getCentroid\r\n * @for p5.FFT\r\n * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz.\r\n *\r\n *\r\n * @example\r\n *
\r\n *\r\n *\r\n *function setup(){\r\n * cnv = createCanvas(100,100);\r\n * sound = new p5.AudioIn();\r\n * sound.start();\r\n * fft = new p5.FFT();\r\n * sound.connect(fft);\r\n *}\r\n *\r\n *\r\n *function draw(){\r\n *\r\n * var centroidplot = 0.0;\r\n * var spectralCentroid = 0;\r\n *\r\n *\r\n * background(0);\r\n * stroke(0,255,0);\r\n * var spectrum = fft.analyze();\r\n * fill(0,255,0); // spectrum is green\r\n *\r\n * //draw the spectrum\r\n * for (var i = 0; i< spectrum.length; i++){\r\n * var x = map(log(i), 0, log(spectrum.length), 0, width);\r\n * var h = map(spectrum[i], 0, 255, 0, height);\r\n * var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\r\n * rect(x, height, rectangle_width, -h )\r\n * }\r\n\r\n * var nyquist = 22050;\r\n *\r\n * // get the centroid\r\n * spectralCentroid = fft.getCentroid();\r\n *\r\n * // the mean_freq_index calculation is for the display.\r\n * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\r\n *\r\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\r\n *\r\n *\r\n * stroke(255,0,0); // the line showing where the centroid is will be red\r\n *\r\n * rect(centroidplot, 0, width / spectrum.length, height)\r\n * noStroke();\r\n * fill(255,255,255); // text is white\r\n * text(\"centroid: \", 10, 20);\r\n * text(round(spectralCentroid)+\" Hz\", 10, 40);\r\n *}\r\n *
\r\n */\r\n p5.FFT.prototype.getCentroid = function() {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var cumulative_sum = 0;\r\n var centroid_normalization = 0;\r\n\r\n for (var i = 0; i < this.freqDomain.length; i++) {\r\n cumulative_sum += i * this.freqDomain[i];\r\n centroid_normalization += this.freqDomain[i];\r\n }\r\n\r\n var mean_freq_index = 0;\r\n\r\n if (centroid_normalization !== 0) {\r\n mean_freq_index = cumulative_sum / centroid_normalization;\r\n }\r\n\r\n var spec_centroid_freq =\r\n mean_freq_index * (nyquist / this.freqDomain.length);\r\n return spec_centroid_freq;\r\n };\r\n\r\n /**\r\n * Smooth FFT analysis by averaging with the last analysis frame.\r\n *\r\n * @method smooth\r\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\r\n * Defaults to 0.8.\r\n */\r\n p5.FFT.prototype.smooth = function(s) {\r\n if (typeof s !== 'undefined') {\r\n this.smoothing = s;\r\n }\r\n return this.smoothing;\r\n };\r\n\r\n p5.FFT.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n if (this.analyser) {\r\n this.analyser.disconnect();\r\n delete this.analyser;\r\n }\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values for a given number\r\n * of frequency bands split equally. N defaults to 16.\r\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and linAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method linAverages\r\n * @for p5.FFT\r\n * @param {Number} N Number of returned frequency groups\r\n * @return {Array} linearAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.linAverages = function(N) {\r\n var N = N || 16; // This prevents undefined, null or 0 values of N\r\n\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n var spectrumStep = Math.floor(spectrumLength / N);\r\n\r\n var linearAverages = new Array(N);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // with only one loop in the spectrum data\r\n var groupIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n linearAverages[groupIndex] =\r\n linearAverages[groupIndex] !== undefined\r\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n\r\n // Increase the group index when the last element of the group is processed\r\n if (specIndex % spectrumStep === spectrumStep - 1) {\r\n groupIndex++;\r\n }\r\n }\r\n\r\n return linearAverages;\r\n };\r\n\r\n /**\r\n * Returns an array of average amplitude values of the spectrum, for a given\r\n * set of \r\n * Octave Bands\r\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\r\n * tells the FFT to analyze frequency data, and logAverages() uses\r\n * the results to group them into a smaller set of averages.\r\n *\r\n * @method logAverages\r\n * @for p5.FFT\r\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\r\n * @return {Array} logAverages Array of average amplitude values for each group\r\n */\r\n p5.FFT.prototype.logAverages = function(octaveBands) {\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n var spectrum = this.freqDomain;\r\n var spectrumLength = spectrum.length;\r\n\r\n var logAverages = new Array(octaveBands.length);\r\n // Keep a second index for the current average group and place the values accordingly\r\n // With only one loop in the spectrum data\r\n var octaveIndex = 0;\r\n\r\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\r\n var specIndexFrequency = Math.round(\r\n specIndex * nyquist / this.freqDomain.length\r\n );\r\n\r\n // Increase the group index if the current frequency exceeds the limits of the band\r\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\r\n octaveIndex++;\r\n }\r\n\r\n logAverages[octaveIndex] =\r\n logAverages[octaveIndex] !== undefined\r\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\r\n : spectrum[specIndex];\r\n }\r\n\r\n return logAverages;\r\n };\r\n\r\n /**\r\n * Calculates and Returns the 1/N\r\n * Octave Bands\r\n * N defaults to 3 and minimum central frequency to 15.625Hz.\r\n * (1/3 Octave Bands ~= 31 Frequency Bands)\r\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\r\n * and produce less frequency groups.\r\n *\r\n * @method getOctaveBands\r\n * @for p5.FFT\r\n * @param {Number} N Specifies the 1/N type of generated octave bands\r\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\r\n * @return {Array} octaveBands Array of octave band objects with their bounds\r\n */\r\n p5.FFT.prototype.getOctaveBands = function(N, fCtr0) {\r\n var N = N || 3; // Default to 1/3 Octave Bands\r\n var fCtr0 = fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\r\n\r\n var octaveBands = [];\r\n var lastFrequencyBand = {\r\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\r\n ctr: fCtr0,\r\n hi: fCtr0 * Math.pow(2, 1 / (2 * N))\r\n };\r\n octaveBands.push(lastFrequencyBand);\r\n\r\n var nyquist = p5sound.audiocontext.sampleRate / 2;\r\n while (lastFrequencyBand.hi < nyquist) {\r\n var newFrequencyBand = {};\r\n newFrequencyBand.lo = lastFrequencyBand.hi;\r\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\r\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\r\n\r\n octaveBands.push(newFrequencyBand);\r\n lastFrequencyBand = newFrequencyBand;\r\n }\r\n\r\n return octaveBands;\r\n };\r\n\r\n // helper methods to convert type from float (dB) to int (0-255)\r\n var freqToFloat = function(fft) {\r\n if (fft.freqDomain instanceof Float32Array === false) {\r\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var freqToInt = function(fft) {\r\n if (fft.freqDomain instanceof Uint8Array === false) {\r\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToFloat = function(fft) {\r\n if (fft.timeDomain instanceof Float32Array === false) {\r\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n var timeToInt = function(fft) {\r\n if (fft.timeDomain instanceof Uint8Array === false) {\r\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\r\n }\r\n };\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // Signal is built with the Tone.js signal by Yotam Mann\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Signal = require('Tone/signal/Signal');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n\r\n /**\r\n *
p5.Signal is a constant audio-rate signal used by p5.Oscillator\r\n * and p5.Envelope for modulation math.
\r\n *\r\n *
This is necessary because Web Audio is processed on a seprate clock.\r\n * For example, the p5 draw loop runs about 60 times per second. But\r\n * the audio clock must process samples 44100 times per second. If we\r\n * want to add a value to each of those samples, we can't do it in the\r\n * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns\r\n * a Tone.Signal from the Tone.js library by Yotam Mann.\r\n * If you want to work directly with audio signals for modular\r\n * synthesis, check out\r\n * tone.js.
\r\n *\r\n * @class p5.Signal\r\n * @constructor\r\n * @return {Tone.Signal} A Signal object from the Tone.js library\r\n * @example\r\n *
\r\n * function setup() {\r\n * carrier = new p5.Oscillator('sine');\r\n * carrier.amp(1); // set amplitude\r\n * carrier.freq(220); // set frequency\r\n * carrier.start(); // start oscillating\r\n *\r\n * modulator = new p5.Oscillator('sawtooth');\r\n * modulator.disconnect();\r\n * modulator.amp(1);\r\n * modulator.freq(4);\r\n * modulator.start();\r\n *\r\n * // Modulator's default amplitude range is -1 to 1.\r\n * // Multiply it by -200, so the range is -200 to 200\r\n * // then add 220 so the range is 20 to 420\r\n * carrier.freq( modulator.mult(-200).add(220) );\r\n * }\r\n *
\r\n */\r\n p5.Signal = function(value) {\r\n var s = new Signal(value);\r\n // p5sound.soundArray.push(s);\r\n return s; // TODO: is this really a constructor?\r\n };\r\n\r\n /**\r\n * Fade to value, for smooth transitions\r\n *\r\n * @method fade\r\n * @for p5.Signal\r\n * @param {Number} value Value to set this signal\r\n * @param {Number} [secondsFromNow] Length of fade, in seconds from now\r\n */\r\n Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime;\r\n Mult.prototype.fade = Signal.prototype.fade;\r\n Add.prototype.fade = Signal.prototype.fade;\r\n Scale.prototype.fade = Signal.prototype.fade;\r\n\r\n\r\n /**\r\n * Connect a p5.sound object or Web Audio node to this\r\n * p5.Signal so that its amplitude values can be scaled.\r\n *\r\n * @method setInput\r\n * @for p5.Signal\r\n * @param {Object} input\r\n */\r\n Signal.prototype.setInput = function(_input) {\r\n _input.connect(this);\r\n };\r\n Mult.prototype.setInput = Signal.prototype.setInput;\r\n Add.prototype.setInput = Signal.prototype.setInput;\r\n Scale.prototype.setInput = Signal.prototype.setInput;\r\n\r\n\r\n // signals can add / mult / scale themselves\r\n\r\n /**\r\n * Add a constant value to this audio signal,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalAdd.\r\n *\r\n * @method add\r\n * @for p5.Signal\r\n * @param {Number} number\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.add = function(num) {\r\n var add = new Add(num);\r\n // add.setInput(this);\r\n this.connect(add);\r\n return add;\r\n };\r\n Mult.prototype.add = Signal.prototype.add;\r\n Add.prototype.add = Signal.prototype.add;\r\n Scale.prototype.add = Signal.prototype.add;\r\n\r\n /**\r\n * Multiply this signal by a constant value,\r\n * and return the resulting audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalMult.\r\n *\r\n * @method mult\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n // mult.setInput(this);\r\n this.connect(mult);\r\n return mult;\r\n };\r\n Mult.prototype.mult = Signal.prototype.mult;\r\n Add.prototype.mult = Signal.prototype.mult;\r\n Scale.prototype.mult = Signal.prototype.mult;\r\n\r\n /**\r\n * Scale this signal value to a given range,\r\n * and return the result as an audio signal. Does\r\n * not change the value of the original signal,\r\n * instead it returns a new p5.SignalScale.\r\n *\r\n * @method scale\r\n * @for p5.Signal\r\n * @param {Number} number to multiply\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Signal} object\r\n */\r\n Signal.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var mapOutMin, mapOutMax;\r\n if (arguments.length === 4) {\r\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\r\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\r\n }\r\n else {\r\n mapOutMin = arguments[0];\r\n mapOutMax = arguments[1];\r\n }\r\n var scale = new Scale(mapOutMin, mapOutMax);\r\n this.connect(scale);\r\n return scale;\r\n };\r\n Mult.prototype.scale = Signal.prototype.scale;\r\n Add.prototype.scale = Signal.prototype.scale;\r\n Scale.prototype.scale = Signal.prototype.scale;\r\n\r\n});\r\n\r\n\r\n","define([\"Tone/core/Tone\", \"Tone/type/TimeBase\"], function (Tone) {\n\n\t/**\n\t * @class Tone.Frequency is a primitive type for encoding Frequency values. \n\t * Eventually all time values are evaluated to hertz\n\t * using the `eval` method. \n\t * @constructor\n\t * @extends {Tone.TimeBase}\n\t * @param {String|Number} val The time value.\n\t * @param {String=} units The units of the value.\n\t * @example\n\t * Tone.Frequency(\"C3\") // 261\n\t * Tone.Frequency(38, \"midi\") //\n\t * Tone.Frequency(\"C3\").transpose(4);\n\t */\n\tTone.Frequency = function(val, units){\n\t\tif (this instanceof Tone.Frequency){\n\t\t\t\n\t\t\tTone.TimeBase.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.Frequency(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.Frequency, Tone.TimeBase);\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tAUGMENT BASE EXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);\n\n\t/*\n\t * midi type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.midi = {\n\t\tregexp : /^(\\d+(?:\\.\\d+)?midi)/,\n\t\tmethod : function(value){\n\t\t\treturn this.midiToFrequency(value);\n\t\t}\t\n\t};\n\n\t/*\n\t * note type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.note = {\n\t\tregexp : /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,\n\t\tmethod : function(pitch, octave){\n\t\t\tvar index = noteToScaleIndex[pitch.toLowerCase()];\n\t\t\tvar noteNumber = index + (parseInt(octave) + 1) * 12;\n\t\t\treturn this.midiToFrequency(noteNumber);\n\t\t}\t\n\t};\n\n\t/*\n\t * BeatsBarsSixteenths type primary expression\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Frequency.prototype._primaryExpressions.tr = {\n\t\t\tregexp : /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t\t\tmethod : function(m, q, s){\n\t\t\tvar total = 1;\n\t\t\tif (m && m !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t\t\t}\n\t\t\tif (q && q !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(q));\n\t\t\t}\n\t\t\tif (s && s !== \"0\"){\n\t\t\t\ttotal *= this._beatsToUnits(parseFloat(s) / 4);\n\t\t\t}\n\t\t\treturn total;\n\t\t}\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tEXPRESSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Transposes the frequency by the given number of semitones.\n\t * @param {Interval} interval\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").transpose(3); //\"C5\"\n\t */\n\tTone.Frequency.prototype.transpose = function(interval){\n\t\tthis._expr = function(expr, interval){\n\t\t\tvar val = expr();\n\t\t\treturn val * this.intervalToFrequencyRatio(interval);\n\t\t}.bind(this, this._expr, interval);\n\t\treturn this;\n\t};\n\n\t/**\n\t * Takes an array of semitone intervals and returns\n\t * an array of frequencies transposed by those intervals.\n\t * @param {Array} intervals\n\t * @return {Tone.Frequency} this\n\t * @example\n\t * Tone.Frequency(\"A4\").harmonize([0, 3, 7]); //[\"A4\", \"C5\", \"E5\"]\n\t */\n\tTone.Frequency.prototype.harmonize = function(intervals){\n\t\tthis._expr = function(expr, intervals){\n\t\t\tvar val = expr();\n\t\t\tvar ret = [];\n\t\t\tfor (var i = 0; i < intervals.length; i++){\n\t\t\t\tret[i] = val * this.intervalToFrequencyRatio(intervals[i]);\n\t\t\t}\n\t\t\treturn ret;\n\t\t}.bind(this, this._expr, intervals);\n\t\treturn this;\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Return the value of the frequency as a MIDI note\n\t * @return {MIDI}\n\t * @example\n\t * Tone.Frequency(\"C4\").toMidi(); //60\n\t */\n\tTone.Frequency.prototype.toMidi = function(){\n\t\treturn this.frequencyToMidi(this.valueOf());\n\t};\n\n\t/**\n\t * Return the value of the frequency in Scientific Pitch Notation\n\t * @return {Note}\n\t * @example\n\t * Tone.Frequency(69, \"midi\").toNote(); //\"A4\"\n\t */\n\tTone.Frequency.prototype.toNote = function(){\n\t\tvar freq = this.valueOf();\n\t\tvar log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;\n\t\tvar noteNumber = Math.round(12 * log) + 57;\n\t\tvar octave = Math.floor(noteNumber/12);\n\t\tif(octave < 0){\n\t\t\tnoteNumber += -12 * octave;\n\t\t}\n\t\tvar noteName = scaleIndexToNote[noteNumber % 12];\n\t\treturn noteName + octave.toString();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.Frequency.prototype.toSeconds = function(){\n\t\treturn 1 / this.valueOf();\n\t};\n\n\t/**\n\t * Return the value in Hertz\n\t * @return {Frequency}\n\t */\n\tTone.Frequency.prototype.toFrequency = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the duration of one cycle in ticks\n\t * @return {Ticks}\n\t */\n\tTone.Frequency.prototype.toTicks = function(){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = this.valueOf() / quarterTime;\n\t\treturn Math.floor(quarters * Tone.Transport.PPQ);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tUNIT CONVERSIONS HELPERS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Returns the value of a frequency in the current units\n\t * @param {Frequency} freq\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._frequencyToUnits = function(freq){\n\t\treturn freq;\n\t};\n\n\t/**\n\t * Returns the value of a tick in the current time units\n\t * @param {Ticks} ticks\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._ticksToUnits = function(ticks){\n\t\treturn 1 / ((ticks * 60) / (Tone.Transport.bpm.value * Tone.Transport.PPQ));\n\t};\n\n\t/**\n\t * Return the value of the beats in the current units\n\t * @param {Number} beats\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._beatsToUnits = function(beats){\n\t\treturn 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);\n\t};\n\n\t/**\n\t * Returns the value of a second in the current units\n\t * @param {Seconds} seconds\n\t * @return {Number}\n\t * @private\n\t */\n\tTone.Frequency.prototype._secondsToUnits = function(seconds){\n\t\treturn 1 / seconds;\n\t};\n\n\t/**\n\t * The default units if none are given.\n\t * @private\n\t */\n\tTone.Frequency.prototype._defaultUnits = \"hz\";\n\n\t///////////////////////////////////////////////////////////////////////////\n\t//\tFREQUENCY CONVERSIONS\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/**\n\t * Note to scale index\n\t * @type {Object}\n\t */\n\tvar noteToScaleIndex = {\n\t\t\"cbb\" : -2, \"cb\" : -1, \"c\" : 0, \"c#\" : 1, \"cx\" : 2, \n\t\t\"dbb\" : 0, \"db\" : 1, \"d\" : 2, \"d#\" : 3, \"dx\" : 4,\n\t\t\"ebb\" : 2, \"eb\" : 3, \"e\" : 4, \"e#\" : 5, \"ex\" : 6, \n\t\t\"fbb\" : 3, \"fb\" : 4, \"f\" : 5, \"f#\" : 6, \"fx\" : 7,\n\t\t\"gbb\" : 5, \"gb\" : 6, \"g\" : 7, \"g#\" : 8, \"gx\" : 9,\n\t\t\"abb\" : 7, \"ab\" : 8, \"a\" : 9, \"a#\" : 10, \"ax\" : 11,\n\t\t\"bbb\" : 9, \"bb\" : 10, \"b\" : 11, \"b#\" : 12, \"bx\" : 13,\n\t};\n\n\t/**\n\t * scale index to note (sharps)\n\t * @type {Array}\n\t */\n\tvar scaleIndexToNote = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"];\n\n\t/**\n\t * The [concert pitch](https://en.wikipedia.org/wiki/Concert_pitch)\n\t * A4's values in Hertz. \n\t * @type {Frequency}\n\t * @static\n\t */\n\tTone.Frequency.A4 = 440;\n\n\t/**\n\t * Convert a MIDI note to frequency value. \n\t * @param {MIDI} midi The midi number to convert.\n\t * @return {Frequency} the corresponding frequency value\n\t * @example\n\t * tone.midiToFrequency(69); // returns 440\n\t */\n\tTone.Frequency.prototype.midiToFrequency = function(midi){\n\t\treturn Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);\n\t};\n\n\t/**\n\t * Convert a frequency value to a MIDI note.\n\t * @param {Frequency} frequency The value to frequency value to convert.\n\t * @returns {MIDI}\n\t * @example\n\t * tone.midiToFrequency(440); // returns 69\n\t */\n\tTone.Frequency.prototype.frequencyToMidi = function(frequency){\n\t\treturn 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;\n\t};\n\n\treturn Tone.Frequency;\n});","define([\"Tone/core/Tone\", \"Tone/type/Time\"], function (Tone) {\n\n\t/**\n\t * @class Tone.TransportTime is a the time along the Transport's\n\t * timeline. It is similar to Tone.Time, but instead of evaluating\n\t * against the AudioContext's clock, it is evaluated against\n\t * the Transport's position. See [TransportTime wiki](https://github.com/Tonejs/Tone.js/wiki/TransportTime).\n\t * @constructor\n\t * @param {Time} val The time value as a number or string\n\t * @param {String=} units Unit values\n\t * @extends {Tone.Time}\n\t */\n\tTone.TransportTime = function(val, units){\n\t\tif (this instanceof Tone.TransportTime){\n\t\t\t\n\t\t\tTone.Time.call(this, val, units);\n\n\t\t} else {\n\t\t\treturn new Tone.TransportTime(val, units);\n\t\t}\n\t};\n\n\tTone.extend(Tone.TransportTime, Tone.Time);\n\n\t//clone the expressions so that \n\t//we can add more without modifying the original\n\tTone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);\n\n\t/**\n\t * Adds an additional unary expression\n\t * which quantizes values to the next subdivision\n\t * @type {Object}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._unaryExpressions.quantize = {\n\t\tregexp : /^@/,\n\t\tmethod : function(rh){\n\t\t\tvar subdivision = this._secondsToTicks(rh());\n\t\t\tvar multiple = Math.ceil(Tone.Transport.ticks / subdivision);\n\t\t\treturn this._ticksToUnits(multiple * subdivision);\n\t\t}\n\t};\n\n\t/**\n\t * Convert seconds into ticks\n\t * @param {Seconds} seconds\n\t * @return {Ticks}\n\t * @private\n\t */\n\tTone.TransportTime.prototype._secondsToTicks = function(seconds){\n\t\tvar quarterTime = this._beatsToUnits(1);\n\t\tvar quarters = seconds / quarterTime;\n\t\treturn Math.round(quarters * Tone.Transport.PPQ);\n\t};\n\n\t/**\n\t * Evaluate the time expression. Returns values in ticks\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.valueOf = function(){\n\t\tvar val = this._secondsToTicks(this._expr());\n\t\treturn val + (this._plusNow ? Tone.Transport.ticks : 0);\n\t};\n\n\t/**\n\t * Return the time in ticks.\n\t * @return {Ticks}\n\t */\n\tTone.TransportTime.prototype.toTicks = function(){\n\t\treturn this.valueOf();\n\t};\n\n\t/**\n\t * Return the time in seconds.\n\t * @return {Seconds}\n\t */\n\tTone.TransportTime.prototype.toSeconds = function(){\n\t\tvar val = this._expr();\n\t\treturn val + (this._plusNow ? Tone.Transport.seconds : 0);\n\t};\n\n\t/**\n\t * Return the time as a frequency value\n\t * @return {Frequency} \n\t */\n\tTone.TransportTime.prototype.toFrequency = function(){\n\t\treturn 1/this.toSeconds();\n\t};\n\n\treturn Tone.TransportTime;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n var Add = require('Tone/signal/Add');\r\n var Mult = require('Tone/signal/Multiply');\r\n var Scale = require('Tone/signal/Scale');\r\n var TimelineSignal = require('Tone/signal/TimelineSignal');\r\n\r\n /**\r\n *
Envelopes are pre-defined amplitude distribution over time.\r\n * Typically, envelopes are used to control the output volume\r\n * of an object, a series of fades referred to as Attack, Decay,\r\n * Sustain and Release (\r\n * ADSR\r\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\r\n * control an Oscillator's frequency like this: osc.freq(env).
\r\n *
Use setRange to change the attack/release level.\r\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.
\r\n *
Use the play method to play the entire envelope,\r\n * the ramp method for a pingable trigger,\r\n * or triggerAttack/\r\n * triggerRelease to trigger noteOn/noteOff.
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope = function(t1, l1, t2, l2, t3, l3) {\r\n /**\r\n * Time until envelope reaches attackLevel\r\n * @property attackTime\r\n */\r\n this.aTime = t1 || 0.1;\r\n /**\r\n * Level once attack is complete.\r\n * @property attackLevel\r\n */\r\n this.aLevel = l1 || 1;\r\n /**\r\n * Time until envelope reaches decayLevel.\r\n * @property decayTime\r\n */\r\n this.dTime = t2 || 0.5;\r\n /**\r\n * Level after decay. The envelope will sustain here until it is released.\r\n * @property decayLevel\r\n */\r\n this.dLevel = l2 || 0;\r\n /**\r\n * Duration of the release portion of the envelope.\r\n * @property releaseTime\r\n */\r\n this.rTime = t3 || 0;\r\n /**\r\n * Level at the end of the release.\r\n * @property releaseLevel\r\n */\r\n this.rLevel = l3 || 0;\r\n\r\n this._rampHighPercentage = 0.98;\r\n\r\n this._rampLowPercentage = 0.02;\r\n\r\n\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n this.control = new TimelineSignal();\r\n\r\n this._init(); // this makes sure the envelope starts at zero\r\n\r\n this.control.connect(this.output); // connect to the output\r\n\r\n this.connection = null; // store connection\r\n\r\n //array of math operation signal chaining\r\n this.mathOps = [this.control];\r\n\r\n //whether envelope should be linear or exponential curve\r\n this.isExponential = false;\r\n\r\n // oscillator or buffer source to clear on env complete\r\n // to save resources if/when it is retriggered\r\n this.sourceToClear = null;\r\n\r\n // set to true if attack is set, then false on release\r\n this.wasTriggered = false;\r\n\r\n\r\n // add to the soundArray so we can dispose of the env later\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n // this init function just smooths the starting value to zero and gives a start point for the timeline\r\n // - it was necessary to remove glitches at the beginning.\r\n p5.Envelope.prototype._init = function () {\r\n var now = p5sound.audiocontext.currentTime;\r\n var t = now;\r\n this.control.setTargetAtTime(0.00001, t, .001);\r\n //also, compute the correct time constants\r\n this._setRampAD(this.aTime, this.dTime);\r\n };\r\n\r\n /**\r\n * Reset the envelope with a series of time/value pairs.\r\n *\r\n * @method set\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds) before level\r\n * reaches attackLevel\r\n * @param {Number} attackLevel Typically an amplitude between\r\n * 0.0 and 1.0\r\n * @param {Number} decayTime Time\r\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\r\n * decayLevel = sustainLevel)\r\n * @param {Number} releaseTime Release Time (in seconds)\r\n * @param {Number} releaseLevel Amplitude\r\n * @example\r\n *
\r\n * var t1 = 0.1; // attack time in seconds\r\n * var l1 = 0.7; // attack level 0.0 to 1.0\r\n * var t2 = 0.3; // decay time in seconds\r\n * var l2 = 0.1; // decay level 0.0 to 1.0\r\n * var t3 = 0.2; // sustain time in seconds\r\n * var l3 = 0.5; // sustain level 0.0 to 1.0\r\n * // release level defaults to zero\r\n *\r\n * var env;\r\n * var triOsc;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope(t1, l1, t2, l2, t3, l3);\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env); // give the env control of the triOsc's amp\r\n * triOsc.start();\r\n * }\r\n *\r\n * // mouseClick triggers envelope if over canvas\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(triOsc);\r\n * }\r\n * }\r\n *
\r\n *\r\n */\r\n p5.Envelope.prototype.set = function(t1, l1, t2, l2, t3, l3) {\r\n this.aTime = t1;\r\n this.aLevel = l1;\r\n this.dTime = t2 || 0;\r\n this.dLevel = l2 || 0;\r\n this.rTime = t3 || 0;\r\n this.rLevel = l3 || 0;\r\n\r\n // set time constants for ramp\r\n this._setRampAD(t1, t2);\r\n };\r\n\r\n /**\r\n * Set values like a traditional\r\n * \r\n * ADSR envelope\r\n * .\r\n *\r\n * @method setADSR\r\n * @for p5.Envelope\r\n * @param {Number} attackTime Time (in seconds before envelope\r\n * reaches Attack Level\r\n * @param {Number} [decayTime] Time (in seconds) before envelope\r\n * reaches Decay/Sustain Level\r\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\r\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\r\n * The susRatio determines the decayLevel and the level at which the\r\n * sustain portion of the envelope will sustain.\r\n * For example, if attackLevel is 0.4, releaseLevel is 0,\r\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\r\n * increased to 1.0 (using setRange),\r\n * then decayLevel would increase proportionally, to become 0.5.\r\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setADSR = function(aTime, dTime, sPercent, rTime) {\r\n this.aTime = aTime;\r\n this.dTime = dTime || 0;\r\n\r\n // lerp\r\n this.sPercent = sPercent || 0;\r\n this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n\r\n this.rTime = rTime || 0;\r\n\r\n // also set time constants for ramp\r\n this._setRampAD(aTime, dTime);\r\n };\r\n\r\n /**\r\n * Set max (attackLevel) and min (releaseLevel) of envelope.\r\n *\r\n * @method setRange\r\n * @for p5.Envelope\r\n * @param {Number} aLevel attack level (defaults to 1)\r\n * @param {Number} rLevel release level (defaults to 0)\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * env.play();\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.setRange = function(aLevel, rLevel) {\r\n this.aLevel = aLevel || 1;\r\n this.rLevel = rLevel || 0;\r\n\r\n // not sure if this belongs here:\r\n\r\n // {Number} [dLevel] decay/sustain level (optional)\r\n // if (typeof(dLevel) !== 'undefined') {\r\n // this.dLevel = dLevel\r\n // } else if (this.sPercent) {\r\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\r\n // }\r\n };\r\n\r\n // private (undocumented) method called when ADSR is set to set time constants for ramp\r\n //\r\n // Set the \r\n // time constants for simple exponential ramps.\r\n // The larger the time constant value, the slower the\r\n // transition will be.\r\n //\r\n // method _setRampAD\r\n // param {Number} attackTimeConstant attack time constant\r\n // param {Number} decayTimeConstant decay time constant\r\n //\r\n p5.Envelope.prototype._setRampAD = function(t1, t2) {\r\n this._rampAttackTime = this.checkExpInput(t1);\r\n this._rampDecayTime = this.checkExpInput(t2);\r\n\r\n var TCDenominator = 1.0;\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n // private method\r\n p5.Envelope.prototype.setRampPercentages = function(p1, p2) {\r\n //set the percentages that the simple exponential ramps go to\r\n this._rampHighPercentage = this.checkExpInput(p1);\r\n this._rampLowPercentage = this.checkExpInput(p2);\r\n var TCDenominator = 1.0;\r\n //now re-compute the time constants based on those percentages\r\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\r\n TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage));\r\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\r\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\r\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\r\n };\r\n\r\n\r\n /**\r\n * Assign a parameter to be controlled by this envelope.\r\n * If a p5.Sound object is given, then the p5.Envelope will control its\r\n * output gain. If multiple inputs are provided, the env will\r\n * control all of them.\r\n *\r\n * @method setInput\r\n * @for p5.Envelope\r\n * @param {Object} [...inputs] A p5.sound object or\r\n * Web Audio Param.\r\n */\r\n p5.Envelope.prototype.setInput = function() {\r\n for (var i = 0; i\r\n * Web Audio Audio Param.\r\n *\r\n * @method play\r\n * @for p5.Envelope\r\n * @param {Object} unit A p5.sound object or\r\n * Web Audio Param.\r\n * @param {Number} [startTime] time from now (in seconds) at which to play\r\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\r\n * @example\r\n *
\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var susPercent = 0.2;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n *\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(playEnv);\r\n * }\r\n *\r\n * function playEnv() {\r\n * // trigger env on triOsc, 0 seconds from now\r\n * // After decay, sustain for 0.2 seconds before release\r\n * env.play(triOsc, 0, 0.2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.play = function(unit, secondsFromNow, susTime) {\r\n var tFromNow = secondsFromNow || 0;\r\n var susTime = susTime || 0;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n this.triggerAttack(unit, tFromNow);\r\n\r\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime);\r\n\r\n };\r\n\r\n /**\r\n * Trigger the Attack, and Decay portion of the Envelope.\r\n * Similar to holding down a key on a piano, but it will\r\n * hold the sustain level until you let go. Input can be\r\n * any p5.sound object, or a \r\n * Web Audio Param.\r\n *\r\n * @method triggerAttack\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time from now (in seconds)\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerAttack = function(unit, secondsFromNow) {\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n this.lastAttack = t;\r\n this.wasTriggered = true;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // after each ramp completes, cancel scheduled values\r\n // (so they can be overridden in case env has been re-triggered)\r\n // then, set current value (with linearRamp to avoid click)\r\n // then, schedule the next automation...\r\n\r\n // attack\r\n t += this.aTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.aLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n\r\n }\r\n\r\n // decay to decay level (if using ADSR, then decay level == sustain level)\r\n t += this.dTime;\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.dLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n };\r\n\r\n /**\r\n * Trigger the Release of the Envelope. This is similar to releasing\r\n * the key on a piano and letting the sound fade according to the\r\n * release level and release time.\r\n *\r\n * @method triggerRelease\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow time to trigger the release\r\n * @example\r\n *
\r\n *\r\n * var attackLevel = 1.0;\r\n * var releaseLevel = 0;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.3;\r\n * var susPercent = 0.4;\r\n * var releaseTime = 0.5;\r\n *\r\n * var env, triOsc;\r\n *\r\n * function setup() {\r\n * var cnv = createCanvas(100, 100);\r\n * background(200);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\r\n * env.setRange(attackLevel, releaseLevel);\r\n *\r\n * triOsc = new p5.Oscillator('triangle');\r\n * triOsc.amp(env);\r\n * triOsc.start();\r\n * triOsc.freq(220);\r\n *\r\n * cnv.mousePressed(envAttack);\r\n * }\r\n *\r\n * function envAttack() {\r\n * console.log('trigger attack');\r\n * env.triggerAttack();\r\n *\r\n * background(0,255,0);\r\n * text('attack!', width/2, height/2);\r\n * }\r\n *\r\n * function mouseReleased() {\r\n * env.triggerRelease();\r\n *\r\n * background(200);\r\n * text('click to play', width/2, height/2);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.triggerRelease = function(unit, secondsFromNow) {\r\n\r\n // only trigger a release if an attack was triggered\r\n if (!this.wasTriggered) {\r\n // this currently causes a bit of trouble:\r\n // if a later release has been scheduled (via the play function)\r\n // a new earlier release won't interrupt it, because\r\n // this.wasTriggered has already been set to false.\r\n // If we want new earlier releases to override, then we need to\r\n // keep track of the last release time, and if the new release time is\r\n // earlier, then use it.\r\n return;\r\n }\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n // get and set value (with linear or exponential ramp) to anchor automation\r\n var valToSet = this.control.getValueAtTime(t);\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n // release\r\n t += this.rTime;\r\n\r\n if (this.isExponential === true)\r\n {\r\n this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t);\r\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\r\n this.control.cancelScheduledValues(t);\r\n this.control.exponentialRampToValueAtTime(valToSet, t);\r\n }\r\n else\r\n {\r\n this.control.linearRampToValueAtTime(this.rLevel, t);\r\n valToSet = this.control.getValueAtTime(t);\r\n this.control.cancelScheduledValues(t);\r\n this.control.linearRampToValueAtTime(valToSet, t);\r\n }\r\n\r\n this.wasTriggered = false;\r\n };\r\n\r\n /**\r\n * Exponentially ramp to a value using the first two\r\n * values from setADSR(attackTime, decayTime)\r\n * as \r\n * time constants for simple exponential ramps.\r\n * If the value is higher than current value, it uses attackTime,\r\n * while a decrease uses decayTime.\r\n *\r\n * @method ramp\r\n * @for p5.Envelope\r\n * @param {Object} unit p5.sound Object or Web Audio Param\r\n * @param {Number} secondsFromNow When to trigger the ramp\r\n * @param {Number} v Target value\r\n * @param {Number} [v2] Second target value (optional)\r\n * @example\r\n *
\r\n * var env, osc, amp, cnv;\r\n *\r\n * var attackTime = 0.001;\r\n * var decayTime = 0.2;\r\n * var attackLevel = 1;\r\n * var decayLevel = 0;\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100, 100);\r\n * fill(0,255,0);\r\n * noStroke();\r\n *\r\n * env = new p5.Envelope();\r\n * env.setADSR(attackTime, decayTime);\r\n *\r\n * osc = new p5.Oscillator();\r\n * osc.amp(env);\r\n * osc.start();\r\n *\r\n * amp = new p5.Amplitude();\r\n *\r\n * cnv.mousePressed(triggerRamp);\r\n * }\r\n *\r\n * function triggerRamp() {\r\n * env.ramp(osc, 0, attackLevel, decayLevel);\r\n * }\r\n *\r\n * function draw() {\r\n * background(20,20,20);\r\n * text('click me', 10, 20);\r\n * var h = map(amp.getLevel(), 0, 0.4, 0, height);;\r\n *\r\n * rect(0, height, width, -h);\r\n * }\r\n *
\r\n */\r\n p5.Envelope.prototype.ramp = function(unit, secondsFromNow, v1, v2) {\r\n\r\n var now = p5sound.audiocontext.currentTime;\r\n var tFromNow = secondsFromNow || 0;\r\n var t = now + tFromNow;\r\n var destination1 = this.checkExpInput(v1);\r\n var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\r\n\r\n // connect env to unit if not already connected\r\n if (unit) {\r\n if (this.connection !== unit) {\r\n this.connect(unit);\r\n }\r\n }\r\n\r\n //get current value\r\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\r\n // this.control.cancelScheduledValues(t);\r\n\r\n //if it's going up\r\n if (destination1 > currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\r\n t += this._rampAttackTime;\r\n }\r\n\r\n //if it's going down\r\n else if (destination1 < currentVal) {\r\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\r\n t += this._rampDecayTime;\r\n }\r\n\r\n // Now the second part of envelope begins\r\n if (destination2 === undefined) return;\r\n\r\n //if it's going up\r\n if (destination2 > destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\r\n }\r\n\r\n //if it's going down\r\n else if (destination2 < destination1) {\r\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\r\n }\r\n };\r\n\r\n\r\n p5.Envelope.prototype.connect = function(unit) {\r\n this.connection = unit;\r\n\r\n // assume we're talking about output gain\r\n // unless given a different audio param\r\n if (unit instanceof p5.Oscillator ||\r\n unit instanceof p5.SoundFile ||\r\n unit instanceof p5.AudioIn ||\r\n unit instanceof p5.Reverb ||\r\n unit instanceof p5.Noise ||\r\n unit instanceof p5.Filter ||\r\n unit instanceof p5.Delay\r\n ) {\r\n unit = unit.output.gain;\r\n }\r\n if (unit instanceof AudioParam) {\r\n //set the initial value\r\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\r\n }\r\n if (unit instanceof p5.Signal) {\r\n unit.setValue(0);\r\n }\r\n this.output.connect(unit);\r\n };\r\n\r\n p5.Envelope.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n\r\n // Signal Math\r\n\r\n /**\r\n * Add a value to the p5.Oscillator's output amplitude,\r\n * and return the oscillator. Calling this method\r\n * again will override the initial add() with new values.\r\n *\r\n * @method add\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to add\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.add = function(num) {\r\n var add = new Add(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\r\n };\r\n\r\n /**\r\n * Multiply the p5.Envelope's output amplitude\r\n * by a fixed value. Calling this method\r\n * again will override the initial mult() with new values.\r\n *\r\n * @method mult\r\n * @for p5.Envelope\r\n * @param {Number} number Constant number to multiply\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.mult = function(num) {\r\n var mult = new Mult(num);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\r\n };\r\n\r\n /**\r\n * Scale this envelope's amplitude values to a given\r\n * range, and return the envelope. Calling this method\r\n * again will override the initial scale() with new values.\r\n *\r\n * @method scale\r\n * @for p5.Envelope\r\n * @param {Number} inMin input range minumum\r\n * @param {Number} inMax input range maximum\r\n * @param {Number} outMin input range minumum\r\n * @param {Number} outMax input range maximum\r\n * @return {p5.Envelope} Envelope Returns this envelope\r\n * with scaled output\r\n */\r\n p5.Envelope.prototype.scale = function(inMin, inMax, outMin, outMax) {\r\n var scale = new Scale(inMin, inMax, outMin, outMax);\r\n var thisChain = this.mathOps.length;\r\n var nextChain = this.output;\r\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\r\n };\r\n\r\n\r\n // get rid of the oscillator\r\n p5.Envelope.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.disconnect();\r\n if (this.control) {\r\n this.control.dispose();\r\n this.control = null;\r\n }\r\n for (var i = 1; i < this.mathOps.length; i++) {\r\n this.mathOps[i].dispose();\r\n }\r\n };\r\n\r\n // Different name for backwards compatibility, replicates p5.Envelope class\r\n p5.Env = function(t1, l1, t2, l2, t3, l3) {\r\n console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\r\n 'Please use the new p5.Envelope instead.');\r\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\r\n };\r\n p5.Env.prototype = Object.create(p5.Envelope.prototype);\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var p5sound = require('master');\r\n require('oscillator');\r\n\r\n /**\r\n * Creates a Pulse object, an oscillator that implements\r\n * Pulse Width Modulation.\r\n * The pulse is created with two oscillators.\r\n * Accepts a parameter for frequency, and to set the\r\n * width between the pulses. See \r\n * p5.Oscillator for a full list of methods.\r\n *\r\n * @class p5.Pulse\r\n * @extends p5.Oscillator\r\n * @constructor\r\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\r\n * @param {Number} [w] Width between the pulses (0 to 1.0,\r\n * defaults to 0)\r\n * @example\r\n *
Note: This uses the getUserMedia/\r\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\r\n * is limited to localhost and https, but access over http may be limited.
\r\n *\r\n * @class p5.AudioIn\r\n * @constructor\r\n * @param {Function} [errorCallback] A function to call if there is an error\r\n * accessing the AudioIn. For example,\r\n * Safari and iOS devices do not\r\n * currently allow microphone access.\r\n * @example\r\n *
\r\n * var mic;\r\n * function setup(){\r\n * mic = new p5.AudioIn()\r\n * mic.start();\r\n * }\r\n * function draw(){\r\n * background(0);\r\n * micLevel = mic.getLevel();\r\n * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);\r\n * }\r\n *
\r\n */\r\n p5.AudioIn = function(errorCallback) {\r\n // set up audio input\r\n /**\r\n * @property {GainNode} input\r\n */\r\n this.input = p5sound.audiocontext.createGain();\r\n /**\r\n * @property {GainNode} output\r\n */\r\n this.output = p5sound.audiocontext.createGain();\r\n\r\n /**\r\n * @property {MediaStream|null} stream\r\n */\r\n this.stream = null;\r\n /**\r\n * @property {MediaStreamAudioSourceNode|null} mediaStream\r\n */\r\n this.mediaStream = null;\r\n /**\r\n * @property {Number|null} currentSource\r\n */\r\n this.currentSource = null;\r\n\r\n /**\r\n * Client must allow browser to access their microphone / audioin source.\r\n * Default: false. Will become true when the client enables acces.\r\n *\r\n * @property {Boolean} enabled\r\n */\r\n this.enabled = false;\r\n\r\n /**\r\n * Input amplitude, connect to it by default but not to master out\r\n *\r\n * @property {p5.Amplitude} amplitude\r\n */\r\n this.amplitude = new p5.Amplitude();\r\n this.output.connect(this.amplitude.input);\r\n\r\n if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) {\r\n errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices');\r\n }\r\n\r\n // add to soundArray so we can dispose on close\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Start processing audio input. This enables the use of other\r\n * AudioIn methods like getLevel(). Note that by default, AudioIn\r\n * is not connected to p5.sound's output. So you won't hear\r\n * anything unless you use the connect() method. \r\n *\r\n * Certain browsers limit access to the user's microphone. For example,\r\n * Chrome only allows access from localhost and over https. For this reason,\r\n * you may want to include an errorCallback—a function that is called in case\r\n * the browser won't provide mic access.\r\n *\r\n * @method start\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] Name of a function to call on\r\n * success.\r\n * @param {Function} [errorCallback] Name of a function to call if\r\n * there was an error. For example,\r\n * some browsers do not support\r\n * getUserMedia.\r\n */\r\n p5.AudioIn.prototype.start = function(successCallback, errorCallback) {\r\n var self = this;\r\n\r\n if (this.stream) {\r\n this.stop();\r\n }\r\n\r\n // set the audio source\r\n var audioSource = p5sound.inputSources[self.currentSource];\r\n var constraints = {\r\n audio: {\r\n sampleRate: p5sound.audiocontext.sampleRate,\r\n echoCancellation: false\r\n }\r\n };\r\n\r\n // if developers determine which source to use\r\n if (p5sound.inputSources[this.currentSource]) {\r\n constraints.audio.deviceId = audioSource.deviceId;\r\n }\r\n\r\n window.navigator.mediaDevices.getUserMedia( constraints )\r\n .then( function(stream) {\r\n self.stream = stream;\r\n self.enabled = true;\r\n // Wrap a MediaStreamSourceNode around the live input\r\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\r\n self.mediaStream.connect(self.output);\r\n // only send to the Amplitude reader, so we can see it but not hear it.\r\n self.amplitude.setInput(self.output);\r\n if (successCallback) successCallback();\r\n })\r\n .catch( function(err) {\r\n if (errorCallback) errorCallback(err);\r\n else console.error(err);\r\n });\r\n };\r\n\r\n /**\r\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\r\n * If re-starting, the user may be prompted for permission access.\r\n *\r\n * @method stop\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.stop = function() {\r\n if (this.stream) {\r\n this.stream.getTracks().forEach(function(track) {\r\n track.stop();\r\n });\r\n\r\n this.mediaStream.disconnect();\r\n\r\n delete this.mediaStream;\r\n delete this.stream;\r\n }\r\n };\r\n\r\n /**\r\n * Connect to an audio unit. If no parameter is provided, will\r\n * connect to the master output (i.e. your speakers). \r\n *\r\n * @method connect\r\n * @for p5.AudioIn\r\n * @param {Object} [unit] An object that accepts audio input,\r\n * such as an FFT\r\n */\r\n p5.AudioIn.prototype.connect = function(unit) {\r\n if (unit) {\r\n if (unit.hasOwnProperty('input')) {\r\n this.output.connect(unit.input);\r\n }\r\n else if (unit.hasOwnProperty('analyser')) {\r\n this.output.connect(unit.analyser);\r\n }\r\n else {\r\n this.output.connect(unit);\r\n }\r\n }\r\n else {\r\n this.output.connect(p5sound.input);\r\n }\r\n };\r\n\r\n /**\r\n * Disconnect the AudioIn from all audio units. For example, if\r\n * connect() had been called, disconnect() will stop sending\r\n * signal to your speakers. \r\n *\r\n * @method disconnect\r\n * @for p5.AudioIn\r\n */\r\n p5.AudioIn.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n // stay connected to amplitude even if not outputting to p5\r\n this.output.connect(this.amplitude.input);\r\n }\r\n };\r\n\r\n /**\r\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\r\n * class contains its own instance of the Amplitude class to help\r\n * make it easy to get a microphone's volume level. Accepts an\r\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\r\n * .start() before using .getLevel(). \r\n *\r\n * @method getLevel\r\n * @for p5.AudioIn\r\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\r\n * Smooths values based on previous values.\r\n * @return {Number} Volume level (between 0.0 and 1.0)\r\n */\r\n p5.AudioIn.prototype.getLevel = function(smoothing) {\r\n if (smoothing) {\r\n this.amplitude.smoothing = smoothing;\r\n }\r\n return this.amplitude.getLevel();\r\n };\r\n\r\n /**\r\n * Set amplitude (volume) of a mic input between 0 and 1.0. \r\n *\r\n * @method amp\r\n * @for p5.AudioIn\r\n * @param {Number} vol between 0 and 1.0\r\n * @param {Number} [time] ramp time (optional)\r\n */\r\n p5.AudioIn.prototype.amp = function(vol, t) {\r\n if (t) {\r\n var rampTime = t || 0;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime);\r\n this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime);\r\n } else {\r\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\r\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Returns a list of available input sources. This is a wrapper\r\n * for and it returns a Promise.\r\n *\r\n * @method getSources\r\n * @for p5.AudioIn\r\n * @param {Function} [successCallback] This callback function handles the sources when they\r\n * have been enumerated. The callback function\r\n * receives the deviceList array as its only argument\r\n * @param {Function} [errorCallback] This optional callback receives the error\r\n * message as its argument.\r\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\r\n * to the enumerateDevices() method\r\n * @example\r\n *
\r\n */\r\n p5.AudioIn.prototype.getSources = function (onSuccess, onError) {\r\n return new Promise( function(resolve, reject) {\r\n window.navigator.mediaDevices.enumerateDevices()\r\n .then( function(devices) {\r\n p5sound.inputSources = devices.filter(function(device) {\r\n return device.kind === 'audioinput';\r\n });\r\n resolve(p5sound.inputSources);\r\n if (onSuccess) {\r\n onSuccess(p5sound.inputSources);\r\n }\r\n })\r\n .catch( function(error) {\r\n reject(error);\r\n if (onError) {\r\n onError(error);\r\n } else {\r\n console.error('This browser does not support MediaStreamTrack.getSources()');\r\n }\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Set the input source. Accepts a number representing a\r\n * position in the array returned by getSources().\r\n * This is only available in browsers that support\r\n * navigator.mediaDevices.enumerateDevices(). \r\n *\r\n * @method setSource\r\n * @for p5.AudioIn\r\n * @param {number} num position of input source in the array\r\n */\r\n p5.AudioIn.prototype.setSource = function(num) {\r\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\r\n // set the current source\r\n this.currentSource = num;\r\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\r\n } else {\r\n console.log('unable to set input source');\r\n }\r\n\r\n // restart stream if currently active\r\n if (this.stream && this.stream.active) {\r\n this.start();\r\n }\r\n };\r\n\r\n // private method\r\n p5.AudioIn.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this.stop();\r\n\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n if (this.amplitude) {\r\n this.amplitude.disconnect();\r\n }\r\n delete this.amplitude;\r\n delete this.output;\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/signal/Signal\", \"Tone/signal/Expr\", \n\t\"Tone/signal/EqualPowerGain\", \"Tone/core/Gain\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Tone.Crossfade provides equal power fading between two inputs. \n\t * More on crossfading technique [here](https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Crossfading).\n\t *\n\t * @constructor\n\t * @extends {Tone}\n\t * @param {NormalRange} [initialFade=0.5]\n\t * @example\n\t * var crossFade = new Tone.CrossFade(0.5);\n\t * //connect effect A to crossfade from\n\t * //effect output 0 to crossfade input 0\n\t * effectA.connect(crossFade, 0, 0);\n\t * //connect effect B to crossfade from\n\t * //effect output 0 to crossfade input 1\n\t * effectB.connect(crossFade, 0, 1);\n\t * crossFade.fade.value = 0;\n\t * // ^ only effectA is output\n\t * crossFade.fade.value = 1;\n\t * // ^ only effectB is output\n\t * crossFade.fade.value = 0.5;\n\t * // ^ the two signals are mixed equally. \n\t */\t\t\n\tTone.CrossFade = function(initialFade){\n\n\t\tthis.createInsOuts(2, 1);\n\n\t\t/**\n\t\t * Alias for input[0]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.a = this.input[0] = new Tone.Gain();\n\n\t\t/**\n\t\t * Alias for input[1]. \n\t\t * @type {Tone.Gain}\n\t\t */\n\t\tthis.b = this.input[1] = new Tone.Gain();\n\n\t\t/**\n\t\t * \tThe mix between the two inputs. A fade value of 0\n\t\t * \twill output 100% input[0] and \n\t\t * \ta value of 1 will output 100% input[1]. \n\t\t * @type {NormalRange}\n\t\t * @signal\n\t\t */\n\t\tthis.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerA = new Tone.EqualPowerGain();\n\n\t\t/**\n\t\t * equal power gain cross fade\n\t\t * @private\n\t\t * @type {Tone.EqualPowerGain}\n\t\t */\n\t\tthis._equalPowerB = new Tone.EqualPowerGain();\n\t\t\n\t\t/**\n\t\t * invert the incoming signal\n\t\t * @private\n\t\t * @type {Tone}\n\t\t */\n\t\tthis._invert = new Tone.Expr(\"1 - $0\");\n\n\t\t//connections\n\t\tthis.a.connect(this.output);\n\t\tthis.b.connect(this.output);\n\t\tthis.fade.chain(this._equalPowerB, this.b.gain);\n\t\tthis.fade.chain(this._invert, this._equalPowerA, this.a.gain);\n\t\tthis._readOnly(\"fade\");\n\t};\n\n\tTone.extend(Tone.CrossFade);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.CrossFade} this\n\t */\n\tTone.CrossFade.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._writable(\"fade\");\n\t\tthis._equalPowerA.dispose();\n\t\tthis._equalPowerA = null;\n\t\tthis._equalPowerB.dispose();\n\t\tthis._equalPowerB = null;\n\t\tthis.fade.dispose();\n\t\tthis.fade = null;\n\t\tthis._invert.dispose();\n\t\tthis._invert = null;\n\t\tthis.a.dispose();\n\t\tthis.a = null;\n\t\tthis.b.dispose();\n\t\tthis.b = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.CrossFade;\n});\n","define([\"Tone/core/Tone\", \"Tone/signal/Add\", \"Tone/signal/Subtract\", \"Tone/signal/Multiply\", \n\t\"Tone/signal/GreaterThan\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Abs\", \"Tone/signal/Negate\", \n\t\"Tone/signal/Modulo\", \"Tone/signal/Pow\", \"Tone/signal/AudioToGain\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Evaluate an expression at audio rate.
\n\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {string} expr the expression to generate\n\t * @example\n\t * //adds the signals from input[0] and input[1].\n\t * var expr = new Tone.Expr(\"$0 + $1\");\n\t */\n\tTone.Expr = function(){\n\n\t\tvar expr = this._replacements(Array.prototype.slice.call(arguments));\n\t\tvar inputCount = this._parseInputs(expr);\n\n\t\t/**\n\t\t * hold onto all of the nodes for disposal\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t\tthis._nodes = [];\n\n\t\t/**\n\t\t * The inputs. The length is determined by the expression. \n\t\t * @type {Array}\n\t\t */\n\t\tthis.input = new Array(inputCount);\n\n\t\t//create a gain for each input\n\t\tfor (var i = 0; i < inputCount; i++){\n\t\t\tthis.input[i] = this.context.createGain();\n\t\t}\n\n\t\t//parse the syntax tree\n\t\tvar tree = this._parseTree(expr);\n\t\t//evaluate the results\n\t\tvar result;\n\t\ttry {\n\t\t\tresult = this._eval(tree);\n\t\t} catch (e){\n\t\t\tthis._disposeNodes();\n\t\t\tthrow new Error(\"Tone.Expr: Could evaluate expression: \"+expr);\n\t\t}\n\n\t\t/**\n\t\t * The output node is the result of the expression\n\t\t * @type {Tone}\n\t\t */\n\t\tthis.output = result;\n\t};\n\n\tTone.extend(Tone.Expr, Tone.SignalBase);\n\n\t//some helpers to cut down the amount of code\n\tfunction applyBinary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\tself._eval(args[1]).connect(op, 0, 1);\n\t\treturn op;\n\t}\n\tfunction applyUnary(Constructor, args, self){\n\t\tvar op = new Constructor();\n\t\tself._eval(args[0]).connect(op, 0, 0);\n\t\treturn op;\n\t}\n\tfunction getNumber(arg){\n\t\treturn arg ? parseFloat(arg) : undefined;\n\t}\n\tfunction literalNumber(arg){\n\t\treturn arg && arg.args ? parseFloat(arg.args) : undefined;\n\t}\n\n\t/*\n\t * the Expressions that Tone.Expr can parse.\n\t *\n\t * each expression belongs to a group and contains a regexp \n\t * for selecting the operator as well as that operators method\n\t * \n\t * @type {Object}\n\t * @private\n\t */\n\tTone.Expr._Expressions = {\n\t\t//values\n\t\t\"value\" : {\n\t\t\t\"signal\" : {\n\t\t\t\tregexp : /^\\d+\\.\\d+|^\\d+/,\n\t\t\t\tmethod : function(arg){\n\t\t\t\t\tvar sig = new Tone.Signal(getNumber(arg));\n\t\t\t\t\treturn sig;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"input\" : {\n\t\t\t\tregexp : /^\\$\\d/,\n\t\t\t\tmethod : function(arg, self){\n\t\t\t\t\treturn self.input[getNumber(arg.substr(1))];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t//syntactic glue\n\t\t\"glue\" : {\n\t\t\t\"(\" : {\n\t\t\t\tregexp : /^\\(/,\n\t\t\t},\n\t\t\t\")\" : {\n\t\t\t\tregexp : /^\\)/,\n\t\t\t},\n\t\t\t\",\" : {\n\t\t\t\tregexp : /^,/,\n\t\t\t}\n\t\t},\n\t\t//functions\n\t\t\"func\" : {\n\t\t\t\"abs\" : {\n\t\t\t\tregexp : /^abs/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Abs)\n\t\t\t},\n\t\t\t\"mod\" : {\n\t\t\t\tregexp : /^mod/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar modulus = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Modulo(modulus);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"pow\" : {\n\t\t\t\tregexp : /^pow/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar exp = literalNumber(args[1]);\n\t\t\t\t\tvar op = new Tone.Pow(exp);\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"a2g\" : {\n\t\t\t\tregexp : /^a2g/,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\tvar op = new Tone.AudioToGain();\n\t\t\t\t\tself._eval(args[0]).connect(op);\n\t\t\t\t\treturn op;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t//binary expressions\n\t\t\"binary\" : {\n\t\t\t\"+\" : {\n\t\t\t\tregexp : /^\\+/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Add)\n\t\t\t},\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tprecedence : 1,\n\t\t\t\tmethod : function(args, self){\n\t\t\t\t\t//both unary and binary op\n\t\t\t\t\tif (args.length === 1){\n\t\t\t\t\t\treturn applyUnary(Tone.Negate, args, self);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn applyBinary(Tone.Subtract, args, self);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"*\" : {\n\t\t\t\tregexp : /^\\*/,\n\t\t\t\tprecedence : 0,\n\t\t\t\tmethod : applyBinary.bind(this, Tone.Multiply)\n\t\t\t}\n\t\t},\n\t\t//unary expressions\n\t\t\"unary\" : {\n\t\t\t\"-\" : {\n\t\t\t\tregexp : /^\\-/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.Negate)\n\t\t\t},\n\t\t\t\"!\" : {\n\t\t\t\tregexp : /^\\!/,\n\t\t\t\tmethod : applyUnary.bind(this, Tone.NOT)\n\t\t\t},\n\t\t},\n\t};\n\t\t\n\t/**\n\t * @param {string} expr the expression string\n\t * @return {number} the input count\n\t * @private\n\t */\n\tTone.Expr.prototype._parseInputs = function(expr){\n\t\tvar inputArray = expr.match(/\\$\\d/g);\n\t\tvar inputMax = 0;\n\t\tif (inputArray !== null){\n\t\t\tfor (var i = 0; i < inputArray.length; i++){\n\t\t\t\tvar inputNum = parseInt(inputArray[i].substr(1)) + 1;\n\t\t\t\tinputMax = Math.max(inputMax, inputNum);\n\t\t\t}\n\t\t}\n\t\treturn inputMax;\n\t};\n\n\t/**\n\t * @param {Array} args \tan array of arguments\n\t * @return {string} the results of the replacements being replaced\n\t * @private\n\t */\n\tTone.Expr.prototype._replacements = function(args){\n\t\tvar expr = args.shift();\n\t\tfor (var i = 0; i < args.length; i++){\n\t\t\texpr = expr.replace(/\\%/i, args[i]);\n\t\t}\n\t\treturn expr;\n\t};\n\n\t/**\n\t * tokenize the expression based on the Expressions object\n\t * @param {string} expr \n\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t * @private\n\t */\n\tTone.Expr.prototype._tokenize = function(expr){\n\t\tvar position = -1;\n\t\tvar tokens = [];\n\n\t\twhile(expr.length > 0){\n\t\t\texpr = expr.trim();\n\t\t\tvar token = getNextToken(expr);\n\t\t\ttokens.push(token);\n\t\t\texpr = expr.substr(token.value.length);\n\t\t}\n\n\t\tfunction getNextToken(expr){\n\t\t\tfor (var type in Tone.Expr._Expressions){\n\t\t\t\tvar group = Tone.Expr._Expressions[type];\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tvar reg = op.regexp;\n\t\t\t\t\tvar match = expr.match(reg);\n\t\t\t\t\tif (match !== null){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype : type,\n\t\t\t\t\t\t\tvalue : match[0],\n\t\t\t\t\t\t\tmethod : op.method\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected token \"+expr);\n\t\t}\n\n\t\treturn {\n\t\t\tnext : function(){\n\t\t\t\treturn tokens[++position];\n\t\t\t},\n\t\t\tpeek : function(){\n\t\t\t\treturn tokens[position + 1];\n\t\t\t}\n\t\t};\n\t};\n\n\t/**\n\t * recursively parse the string expression into a syntax tree\n\t * \n\t * @param {string} expr \n\t * @return {Object}\n\t * @private\n\t */\n\tTone.Expr.prototype._parseTree = function(expr){\n\t\tvar lexer = this._tokenize(expr);\n\t\tvar isUndef = this.isUndef.bind(this);\n\n\t\tfunction matchSyntax(token, syn) {\n\t\t\treturn !isUndef(token) && \n\t\t\t\ttoken.type === \"glue\" &&\n\t\t\t\ttoken.value === syn;\n\t\t}\n\n\t\tfunction matchGroup(token, groupName, prec) {\n\t\t\tvar ret = false;\n\t\t\tvar group = Tone.Expr._Expressions[groupName];\n\t\t\tif (!isUndef(token)){\n\t\t\t\tfor (var opName in group){\n\t\t\t\t\tvar op = group[opName];\n\t\t\t\t\tif (op.regexp.test(token.value)){\n\t\t\t\t\t\tif (!isUndef(prec)){\n\t\t\t\t\t\t\tif(op.precedence === prec){\t\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\n\t\tfunction parseExpression(precedence) {\n\t\t\tif (isUndef(precedence)){\n\t\t\t\tprecedence = 5;\n\t\t\t}\n\t\t\tvar expr;\n\t\t\tif (precedence < 0){\n\t\t\t\texpr = parseUnary();\n\t\t\t} else {\n\t\t\t\texpr = parseExpression(precedence-1);\n\t\t\t}\n\t\t\tvar token = lexer.peek();\n\t\t\twhile (matchGroup(token, \"binary\", precedence)) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [\n\t\t\t\t\t\texpr,\n\t\t\t\t\t\tparseExpression(precedence-1)\n\t\t\t\t\t]\n\t\t\t\t};\n\t\t\t\ttoken = lexer.peek();\n\t\t\t}\n\t\t\treturn expr;\n\t\t}\n\n\t\tfunction parseUnary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (matchGroup(token, \"unary\")) {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\texpr = parseUnary();\n\t\t\t\treturn {\n\t\t\t\t\toperator: token.value,\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : [expr]\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn parsePrimary();\n\t\t}\n\n\t\tfunction parsePrimary() {\n\t\t\tvar token, expr;\n\t\t\ttoken = lexer.peek();\n\t\t\tif (isUndef(token)) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Unexpected termination of expression\");\n\t\t\t}\n\t\t\tif (token.type === \"func\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn parseFunctionCall(token);\n\t\t\t}\n\t\t\tif (token.type === \"value\") {\n\t\t\t\ttoken = lexer.next();\n\t\t\t\treturn {\n\t\t\t\t\tmethod : token.method,\n\t\t\t\t\targs : token.value\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (matchSyntax(token, \"(\")) {\n\t\t\t\tlexer.next();\n\t\t\t\texpr = parseExpression();\n\t\t\t\ttoken = lexer.next();\n\t\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\t\tthrow new SyntaxError(\"Expected )\");\n\t\t\t\t}\n\t\t\t\treturn expr;\n\t\t\t}\n\t\t\tthrow new SyntaxError(\"Tone.Expr: Parse error, cannot process token \" + token.value);\n\t\t}\n\n\t\tfunction parseFunctionCall(func) {\n\t\t\tvar token, args = [];\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \"(\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ( in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\ttoken = lexer.peek();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\targs = parseArgumentList();\n\t\t\t}\n\t\t\ttoken = lexer.next();\n\t\t\tif (!matchSyntax(token, \")\")) {\n\t\t\t\tthrow new SyntaxError(\"Tone.Expr: Expected ) in a function call \\\"\" + func.value + \"\\\"\");\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmethod : func.method,\n\t\t\t\targs : args,\n\t\t\t\tname : name\n\t\t\t};\n\t\t}\n\n\t\tfunction parseArgumentList() {\n\t\t\tvar token, expr, args = [];\n\t\t\twhile (true) {\n\t\t\t\texpr = parseExpression();\n\t\t\t\tif (isUndef(expr)) {\n\t\t\t\t\t// TODO maybe throw exception?\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\targs.push(expr);\n\t\t\t\ttoken = lexer.peek();\n\t\t\t\tif (!matchSyntax(token, \",\")) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlexer.next();\n\t\t\t}\n\t\t\treturn args;\n\t\t}\n\n\t\treturn parseExpression();\n\t};\n\n\t/**\n\t * recursively evaluate the expression tree\n\t * @param {Object} tree \n\t * @return {AudioNode} the resulting audio node from the expression\n\t * @private\n\t */\n\tTone.Expr.prototype._eval = function(tree){\n\t\tif (!this.isUndef(tree)){\n\t\t\tvar node = tree.method(tree.args, this);\n\t\t\tthis._nodes.push(node);\n\t\t\treturn node;\n\t\t} \n\t};\n\n\t/**\n\t * dispose all the nodes\n\t * @private\n\t */\n\tTone.Expr.prototype._disposeNodes = function(){\n\t\tfor (var i = 0; i < this._nodes.length; i++){\n\t\t\tvar node = this._nodes[i];\n\t\t\tif (this.isFunction(node.dispose)) {\n\t\t\t\tnode.dispose();\n\t\t\t} else if (this.isFunction(node.disconnect)) {\n\t\t\t\tnode.disconnect();\n\t\t\t}\n\t\t\tnode = null;\n\t\t\tthis._nodes[i] = null;\n\t\t}\n\t\tthis._nodes = null;\n\t};\n\n\t/**\n\t * clean up\n\t */\n\tTone.Expr.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._disposeNodes();\n\t};\n\n\treturn Tone.Expr;\n});","define([\"Tone/core/Tone\", \"Tone/signal/GreaterThanZero\", \"Tone/signal/Subtract\", \"Tone/signal/Signal\"], \n\tfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Output 1 if the signal is greater than the value, otherwise outputs 0.\n\t * can compare two signals or a signal and a number. \n\t * \n\t * @constructor\n\t * @extends {Tone.Signal}\n\t * @param {number} [value=0] the value to compare to the incoming signal\n\t * @example\n\t * var gt = new Tone.GreaterThan(2);\n\t * var sig = new Tone.Signal(4).connect(gt);\n\t * //output of gt is equal 1. \n\t */\n\tTone.GreaterThan = function(value){\n\n\t\tthis.createInsOuts(2, 0);\n\t\t\n\t\t/**\n\t\t * subtract the amount from the incoming signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._param = this.input[0] = new Tone.Subtract(value);\n\t\tthis.input[1] = this._param.input[1];\n\n\t\t/**\n\t\t * compare that amount to zero\n\t\t * @type {Tone.GreaterThanZero}\n\t\t * @private\n\t\t */\n\t\tthis._gtz = this.output = new Tone.GreaterThanZero();\n\n\t\t//connect\n\t\tthis._param.connect(this._gtz);\n\t};\n\n\tTone.extend(Tone.GreaterThan, Tone.Signal);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.GreaterThan} this\n\t */\n\tTone.GreaterThan.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._param.dispose();\n\t\tthis._param = null;\n\t\tthis._gtz.dispose();\n\t\tthis._gtz = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.GreaterThan;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/SignalBase\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Return the absolute value of an incoming signal. \n\t * \n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @example\n\t * var signal = new Tone.Signal(-1);\n\t * var abs = new Tone.Abs();\n\t * signal.connect(abs);\n\t * //the output of abs is 1. \n\t */\n\tTone.Abs = function(){\n\t\t/**\n\t\t * @type {Tone.LessThan}\n\t\t * @private\n\t\t */\n\t\tthis._abs = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (val === 0){\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn Math.abs(val);\n\t\t\t}\n\t\t}, 127);\n\t};\n\n\tTone.extend(Tone.Abs, Tone.SignalBase);\n\n\t/**\n\t * dispose method\n\t * @returns {Tone.Abs} this\n\t */\n\tTone.Abs.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._abs.dispose();\n\t\tthis._abs = null;\n\t\treturn this;\n\t}; \n\n\treturn Tone.Abs;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Multiply\", \"Tone/signal/Subtract\"], \nfunction(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Signal-rate modulo operator. Only works in AudioRange [-1, 1] and for modulus\n\t * values in the NormalRange. \n\t *\n\t * @constructor\n\t * @extends {Tone.SignalBase}\n\t * @param {NormalRange} modulus The modulus to apply.\n\t * @example\n\t * var mod = new Tone.Modulo(0.2)\n\t * var sig = new Tone.Signal(0.5).connect(mod);\n\t * //mod outputs 0.1\n\t */\n\tTone.Modulo = function(modulus){\n\n\t\tthis.createInsOuts(1, 0);\n\n\t\t/**\n\t\t * A waveshaper gets the integer multiple of \n\t\t * the input signal and the modulus.\n\t\t * @private\n\t\t * @type {Tone.WaveShaper}\n\t\t */\n\t\tthis._shaper = new Tone.WaveShaper(Math.pow(2, 16));\n\n\t\t/**\n\t\t * the integer multiple is multiplied by the modulus\n\t\t * @type {Tone.Multiply}\n\t\t * @private\n\t\t */\n\t\tthis._multiply = new Tone.Multiply();\n\n\t\t/**\n\t\t * and subtracted from the input signal\n\t\t * @type {Tone.Subtract}\n\t\t * @private\n\t\t */\n\t\tthis._subtract = this.output = new Tone.Subtract();\n\n\t\t/**\n\t\t * the modulus signal\n\t\t * @type {Tone.Signal}\n\t\t * @private\n\t\t */\n\t\tthis._modSignal = new Tone.Signal(modulus);\n\n\t\t//connections\n\t\tthis.input.fan(this._shaper, this._subtract);\n\t\tthis._modSignal.connect(this._multiply, 0, 0);\n\t\tthis._shaper.connect(this._multiply, 0, 1);\n\t\tthis._multiply.connect(this._subtract, 0, 1);\n\t\tthis._setWaveShaper(modulus);\n\t};\n\n\tTone.extend(Tone.Modulo, Tone.SignalBase);\n\n\t/**\n\t * @param {number} mod the modulus to apply\n\t * @private\n\t */\n\tTone.Modulo.prototype._setWaveShaper = function(mod){\n\t\tthis._shaper.setMap(function(val){\n\t\t\tvar multiple = Math.floor((val + 0.0001) / mod);\n\t\t\treturn multiple;\n\t\t});\n\t};\n\n\t/**\n\t * The modulus value.\n\t * @memberOf Tone.Modulo#\n\t * @type {NormalRange}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Modulo.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._modSignal.value;\n\t\t},\n\t\tset : function(mod){\n\t\t\tthis._modSignal.value = mod;\n\t\t\tthis._setWaveShaper(mod);\n\t\t}\n\t});\n\n\t/**\n\t * clean up\n\t * @returns {Tone.Modulo} this\n\t */\n\tTone.Modulo.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.dispose();\n\t\tthis._shaper = null;\n\t\tthis._multiply.dispose();\n\t\tthis._multiply = null;\n\t\tthis._subtract.dispose();\n\t\tthis._subtract = null;\n\t\tthis._modSignal.dispose();\n\t\tthis._modSignal = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Modulo;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Pow applies an exponent to the incoming signal. The incoming signal\n\t * must be AudioRange.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {Positive} exp The exponent to apply to the incoming signal, must be at least 2. \n\t * @example\n\t * var pow = new Tone.Pow(2);\n\t * var sig = new Tone.Signal(0.5).connect(pow);\n\t * //output of pow is 0.25. \n\t */\n\tTone.Pow = function(exp){\n\n\t\t/**\n\t\t * the exponent\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis._exp = this.defaultArg(exp, 1);\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);\n\t};\n\n\tTone.extend(Tone.Pow, Tone.SignalBase);\n\n\t/**\n\t * The value of the exponent.\n\t * @memberOf Tone.Pow#\n\t * @type {number}\n\t * @name value\n\t */\n\tObject.defineProperty(Tone.Pow.prototype, \"value\", {\n\t\tget : function(){\n\t\t\treturn this._exp;\n\t\t},\n\t\tset : function(exp){\n\t\t\tthis._exp = exp;\n\t\t\tthis._expScaler.setMap(this._expFunc(this._exp));\n\t\t}\n\t});\n\n\n\t/**\n\t * the function which maps the waveshaper\n\t * @param {number} exp\n\t * @return {function}\n\t * @private\n\t */\n\tTone.Pow.prototype._expFunc = function(exp){\n\t\treturn function(val){\n\t\t\treturn Math.pow(Math.abs(val), exp);\n\t\t};\n\t};\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.Pow} this\n\t */\n\tTone.Pow.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._expScaler.dispose();\n\t\tthis._expScaler = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.Pow;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\", \"Tone/signal/Signal\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class AudioToGain converts an input in AudioRange [-1,1] to NormalRange [0,1]. \n\t * See Tone.GainToAudio.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var a2g = new Tone.AudioToGain();\n\t */\n\tTone.AudioToGain = function(){\n\n\t\t/**\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._norm = this.input = this.output = new Tone.WaveShaper(function(x){\n\t\t\treturn (x + 1) / 2;\n\t\t});\n\t};\n\n\tTone.extend(Tone.AudioToGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.AudioToGain} this\n\t */\n\tTone.AudioToGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._norm.dispose();\n\t\tthis._norm = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.AudioToGain;\n});","define([\"Tone/core/Tone\", \"Tone/signal/WaveShaper\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Convert an incoming signal between 0, 1 to an equal power gain scale.\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @example\n\t * var eqPowGain = new Tone.EqualPowerGain();\n\t */\n\tTone.EqualPowerGain = function(){\n\n\t\t/**\n\t\t * @type {Tone.WaveShaper}\n\t\t * @private\n\t\t */\n\t\tthis._eqPower = this.input = this.output = new Tone.WaveShaper(function(val){\n\t\t\tif (Math.abs(val) < 0.001){\n\t\t\t\t//should output 0 when input is 0\n\t\t\t\treturn 0;\n\t\t\t} else {\n\t\t\t\treturn this.equalPowerScale(val);\n\t\t\t}\n\t\t}.bind(this), 4096);\n\t};\n\n\tTone.extend(Tone.EqualPowerGain, Tone.SignalBase);\n\n\t/**\n\t * clean up\n\t * @returns {Tone.EqualPowerGain} this\n\t */\n\tTone.EqualPowerGain.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._eqPower.dispose();\n\t\tthis._eqPower = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.EqualPowerGain;\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n var EQFilter = require('eqFilter');\r\n\r\n /**\r\n * p5.EQ is an audio effect that performs the function of a multiband\r\n * audio equalizer. Equalization is used to adjust the balance of\r\n * frequency compoenents of an audio signal. This process is commonly used\r\n * in sound production and recording to change the waveform before it reaches\r\n * a sound output device. EQ can also be used as an audio effect to create\r\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\r\n * built using a chain of Web Audio Biquad Filter Nodes and can be\r\n * instantiated with 3 or 8 bands. Bands can be added or removed from\r\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.EQ\r\n * @constructor\r\n * @extends p5.Effect\r\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\r\n * @return {Object} p5.EQ object\r\n *\r\n * @example\r\n *
\r\n * var eq;\r\n * var band_names;\r\n * var band_index;\r\n *\r\n * var soundFile, play;\r\n *\r\n * function preload() {\r\n * soundFormats('mp3', 'ogg');\r\n * soundFile = loadSound('assets/beat');\r\n * }\r\n *\r\n * function setup() {\r\n * eq = new p5.EQ(3);\r\n * soundFile.disconnect();\r\n * eq.process(soundFile);\r\n *\r\n * band_names = ['lows','mids','highs'];\r\n * band_index = 0;\r\n * play = false;\r\n * textAlign(CENTER);\r\n * }\r\n *\r\n * function draw() {\r\n * background(30);\r\n * noStroke();\r\n * fill(255);\r\n * text('click to kill',50,25);\r\n *\r\n * fill(255, 40, 255);\r\n * textSize(26);\r\n * text(band_names[band_index],50,55);\r\n *\r\n * fill(255);\r\n * textSize(9);\r\n * text('space = play/pause',50,80);\r\n * }\r\n *\r\n * //If mouse is over canvas, cycle to the next band and kill the frequency\r\n * function mouseClicked() {\r\n * for (var i = 0; i < eq.bands.length; i++) {\r\n * eq.bands[i].gain(0);\r\n * }\r\n * eq.bands[band_index].gain(-40);\r\n * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\r\n * band_index === 2 ? band_index = 0 : band_index++;\r\n * }\r\n * }\r\n *\r\n * //use space bar to trigger play / pause\r\n * function keyPressed() {\r\n * if (key===' ') {\r\n * play = !play\r\n * play ? soundFile.loop() : soundFile.pause();\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.EQ = function(_eqsize) {\r\n Effect.call(this);\r\n\r\n //p5.EQ can be of size (3) or (8), defaults to 3\r\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\r\n\r\n var factor;\r\n _eqsize === 3 ? factor = Math.pow(2,3) : factor = 2;\r\n\r\n /**\r\n * The p5.EQ is built with abstracted p5.Filter objects.\r\n * To modify any bands, use methods of the \r\n * p5.Filter API, especially `gain` and `freq`.\r\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\r\n * @property {Array} bands\r\n *\r\n */\r\n this.bands = [];\r\n\r\n\r\n var freq, res;\r\n for (var i = 0; i < _eqsize; i++) {\r\n if (i === _eqsize - 1) {\r\n freq = 21000;\r\n res = .01;\r\n } else if (i === 0) {\r\n freq = 100;\r\n res = .1;\r\n }\r\n else if (i===1) {\r\n freq = _eqsize === 3 ? 360 * factor : 360;\r\n res = 1;\r\n }else {\r\n freq = this.bands[i-1].freq() * factor;\r\n res = 1;\r\n }\r\n this.bands[i] = this._newBand(freq, res);\r\n\r\n if (i>0) {\r\n this.bands[i-1].connect(this.bands[i].biquad);\r\n } else {\r\n this.input.connect(this.bands[i].biquad);\r\n }\r\n }\r\n this.bands[_eqsize-1].connect(this.output);\r\n };\r\n p5.EQ.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Process an input by connecting it to the EQ\r\n * @method process\r\n * @param {Object} src Audio source\r\n */\r\n p5.EQ.prototype.process = function (src) {\r\n src.connect(this.input);\r\n };\r\n\r\n // /**\r\n // * Set the frequency and gain of each band in the EQ. This method should be\r\n // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\r\n // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\r\n // *\r\n // * @method set\r\n // * @for p5.EQ\r\n // * @param {Number} [freq0] Frequency value for band with index 0\r\n // * @param {Number} [gain0] Gain value for band with index 0\r\n // * @param {Number} [freq1] Frequency value for band with index 1\r\n // * @param {Number} [gain1] Gain value for band with index 1\r\n // * @param {Number} [freq2] Frequency value for band with index 2\r\n // * @param {Number} [gain2] Gain value for band with index 2\r\n // * @param {Number} [freq3] Frequency value for band with index 3\r\n // * @param {Number} [gain3] Gain value for band with index 3\r\n // * @param {Number} [freq4] Frequency value for band with index 4\r\n // * @param {Number} [gain4] Gain value for band with index 4\r\n // * @param {Number} [freq5] Frequency value for band with index 5\r\n // * @param {Number} [gain5] Gain value for band with index 5\r\n // * @param {Number} [freq6] Frequency value for band with index 6\r\n // * @param {Number} [gain6] Gain value for band with index 6\r\n // * @param {Number} [freq7] Frequency value for band with index 7\r\n // * @param {Number} [gain7] Gain value for band with index 7\r\n // */\r\n p5.EQ.prototype.set = function() {\r\n if (arguments.length === this.bands.length * 2) {\r\n for (var i = 0; i < arguments.length; i+=2) {\r\n this.bands[i/2].freq(arguments[i]);\r\n this.bands[i/2].gain(arguments[i+1]);\r\n }\r\n }\r\n else {\r\n console.error('Argument mismatch. .set() should be called with ' + this.bands.length*2 +\r\n ' arguments. (one frequency and gain value pair for each band of the eq)');\r\n }\r\n };\r\n\r\n /**\r\n * Add a new band. Creates a p5.Filter and strips away everything but\r\n * the raw biquad filter. This method returns an abstracted p5.Filter,\r\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\r\n * @private\r\n * @for p5.EQ\r\n * @method _newBand\r\n * @param {Number} freq\r\n * @param {Number} res\r\n * @return {Object} Abstracted Filter\r\n */\r\n p5.EQ.prototype._newBand = function(freq, res) {\r\n return new EQFilter(freq, res);\r\n };\r\n\r\n p5.EQ.prototype.dispose = function () {\r\n Effect.prototype.dispose.apply(this);\r\n\r\n if (this.bands) {\r\n while (this.bands.length > 0) {\r\n delete this.bands.pop().dispose();\r\n }\r\n delete this.bands;\r\n }\r\n };\r\n\r\n return p5.EQ;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var p5sound = require('master');\r\n\r\n /**\r\n * EQFilter extends p5.Filter with constraints\r\n * necessary for the p5.EQ\r\n *\r\n * @private\r\n */\r\n var EQFilter = function(freq, res) {\r\n Filter.call(this, 'peaking');\r\n this.disconnect();\r\n this.set(freq, res);\r\n this.biquad.gain.value = 0;\r\n delete this.input;\r\n delete this.output;\r\n delete this._drywet;\r\n delete this.wet;\r\n\r\n };\r\n EQFilter.prototype = Object.create(Filter.prototype);\r\n\r\n EQFilter.prototype.amp = function() {\r\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\r\n };\r\n EQFilter.prototype.drywet = function() {\r\n console.warn('`drywet()` is not available for p5.EQ bands.');\r\n };\r\n EQFilter.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n if (this.biquad) {\r\n this.biquad.connect(u.input ? u.input : u);\r\n } else {\r\n this.output.connect(u.input ? u.input : u);\r\n }\r\n };\r\n\r\n EQFilter.prototype.disconnect = function() {\r\n if (this.biquad) {\r\n this.biquad.disconnect();\r\n }\r\n };\r\n EQFilter.prototype.dispose = function() {\r\n // remove reference form soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n this.disconnect();\r\n delete this.biquad;\r\n };\r\n\r\n return EQFilter;\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Panner3D is based on the \r\n * Web Audio Spatial Panner Node.\r\n * This panner is a spatial processing node that allows audio to be positioned\r\n * and oriented in 3D space.\r\n *\r\n * The position is relative to an \r\n * Audio Context Listener, which can be accessed\r\n * by p5.soundOut.audiocontext.listener\r\n *\r\n *\r\n * @class p5.Panner3D\r\n * @constructor\r\n */\r\n\tp5.Panner3D = function() {\r\n Effect.call(this);\r\n\r\n /**\r\n * \r\n * Web Audio Spatial Panner Node\r\n *\r\n * Properties include\r\n * - panningModel: \"equal power\" or \"HRTF\"\r\n * - distanceModel: \"linear\", \"inverse\", or \"exponential\"\r\n *\r\n * @property {AudioNode} panner\r\n *\r\n */\r\n this.panner = this.ac.createPanner();\r\n this.panner.panningModel = 'HRTF';\r\n this.panner.distanceModel = 'linear';\r\n this.panner.connect(this.output);\r\n this.input.connect(this.panner);\r\n\t};\r\n\r\n p5.Panner3D.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Connect an audio sorce\r\n *\r\n * @method process\r\n * @for p5.Panner3D\r\n * @param {Object} src Input source\r\n */\r\n p5.Panner3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method set\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.set = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.panner.positionX.value,\r\n this.panner.positionY.value,\r\n this.panner.positionZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for position coordinates\r\n * @method positionZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.positionX.value = xVal;\r\n this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.positionX);\r\n }\r\n return this.panner.positionX.value;\r\n };\r\n p5.Panner3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.positionY.value = yVal;\r\n this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.positionY);\r\n }\r\n return this.panner.positionY.value;\r\n };\r\n p5.Panner3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.positionZ.value = zVal;\r\n this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.positionZ);\r\n }\r\n return this.panner.positionZ.value;\r\n };\r\n\r\n /**\r\n * Set the X,Y,Z position of the Panner\r\n * @method orient\r\n * @for p5.Panner3D\r\n * @param {Number} xVal\r\n * @param {Number} yVal\r\n * @param {Number} zVal\r\n * @param {Number} time\r\n * @return {Array} Updated x, y, z values as an array\r\n */\r\n p5.Panner3D.prototype.orient = function(xVal, yVal, zVal, time) {\r\n this.orientX(xVal,time);\r\n this.orientY(yVal,time);\r\n this.orientZ(zVal,time);\r\n return [this.panner.orientationX.value,\r\n this.panner.orientationY.value,\r\n this.panner.orientationZ.value];\r\n };\r\n\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientX\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientY\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n /**\r\n * Getter and setter methods for orient coordinates\r\n * @method orientZ\r\n * @for p5.Panner3D\r\n * @return {Number} updated coordinate value\r\n */\r\n p5.Panner3D.prototype.orientX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.panner.orientationX.value = xVal;\r\n this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.panner.orientationX);\r\n }\r\n return this.panner.orientationX.value;\r\n };\r\n p5.Panner3D.prototype.orientY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.panner.orientationY.value = yVal;\r\n this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.panner.orientationY);\r\n }\r\n return this.panner.orientationY.value;\r\n };\r\n p5.Panner3D.prototype.orientZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.panner.orientationZ.value = zVal;\r\n this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.panner.orientationZ);\r\n }\r\n return this.panner.orientationZ.value;\r\n };\r\n\r\n /**\r\n * Set the rolloff factor and max distance\r\n * @method setFalloff\r\n * @for p5.Panner3D\r\n * @param {Number} [maxDistance]\r\n * @param {Number} [rolloffFactor]\r\n */\r\n p5.Panner3D.prototype.setFalloff = function(maxDistance, rolloffFactor) {\r\n this.maxDist(maxDistance);\r\n this.rolloff(rolloffFactor);\r\n };\r\n /**\r\n * Maxium distance between the source and the listener\r\n * @method maxDist\r\n * @for p5.Panner3D\r\n * @param {Number} maxDistance\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.maxDist = function(maxDistance){\r\n if (typeof maxDistance === 'number') {\r\n this.panner.maxDistance = maxDistance;\r\n }\r\n return this.panner.maxDistance;\r\n };\r\n\r\n /**\r\n * How quickly the volume is reduced as the source moves away from the listener\r\n * @method rollof\r\n * @for p5.Panner3D\r\n * @param {Number} rolloffFactor\r\n * @return {Number} updated value\r\n */\r\n p5.Panner3D.prototype.rolloff = function(rolloffFactor){\r\n if (typeof rolloffFactor === 'number') {\r\n this.panner.rolloffFactor = rolloffFactor;\r\n }\r\n return this.panner.rolloffFactor;\r\n };\r\n\r\n p5.Panner3D.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.panner) {\r\n this.panner.disconnect();\r\n delete this.panner;\r\n }\r\n };\r\n\r\n return p5.Panner3D;\r\n\r\n});\r\n","'use strict'\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Effect = require('effect');\r\n\r\n// /**\r\n// * listener is a class that can construct both a Spatial Panner\r\n// * and a Spatial Listener. The panner is based on the \r\n// * Web Audio Spatial Panner Node\r\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\r\n// * This panner is a spatial processing node that allows audio to be positioned\r\n// * and oriented in 3D space. \r\n// *\r\n// * The Listener modifies the properties of the Audio Context Listener. \r\n// * Both objects types use the same methods. The default is a spatial panner.\r\n// *\r\n// * p5.Panner3D - Constructs a Spatial Panner \r\n// * p5.Listener3D - Constructs a Spatial Listener \r\n// *\r\n// * @class listener\r\n// * @constructor\r\n// * @return {Object} p5.Listener3D Object\r\n// *\r\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\r\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\r\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\r\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\r\n// */\r\n \r\n\tp5.Listener3D = function(type) {\r\n this.ac = p5sound.audiocontext;\r\n this.listener = this.ac.listener;\r\n\t}; \r\n\r\n// /**\r\n// * Connect an audio sorce\r\n// * @param {Object} src Input source\r\n// */\r\n p5.Listener3D.prototype.process = function(src) {\r\n src.connect(this.input);\r\n }\r\n// /**\r\n// * Set the X,Y,Z position of the Panner\r\n// * @param {[Number]} xVal\r\n// * @param {[Number]} yVal\r\n// * @param {[Number]} zVal\r\n// * @param {[Number]} time\r\n// * @return {[Array]} [Updated x, y, z values as an array]\r\n// */\r\n p5.Listener3D.prototype.position = function(xVal, yVal, zVal, time) {\r\n this.positionX(xVal,time);\r\n this.positionY(yVal,time);\r\n this.positionZ(zVal,time);\r\n return [this.listener.positionX.value, \r\n this.listener.positionY.value,\r\n this.listener.positionZ.value];\r\n };\r\n\r\n// /**\r\n// * Getter and setter methods for position coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.positionX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.positionX.value = xVal;\r\n this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.positionX);\r\n }\r\n return this.listener.positionX.value;\r\n };\r\n p5.Listener3D.prototype.positionY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.positionY.value = yVal;\r\n this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.positionY);\r\n }\r\n return this.listener.positionY.value;\r\n };\r\n p5.Listener3D.prototype.positionZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.positionZ.value = zVal;\r\n this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.positionZ);\r\n }\r\n return this.listener.positionZ.value;\r\n };\r\n\r\n// cannot define method when class definition is commented\r\n// /**\r\n// * Overrides the listener orient() method because Listener has slightly\r\n// * different params. In human terms, Forward vectors are the direction the \r\n// * nose is pointing. Up vectors are the direction of the top of the head.\r\n// *\r\n// * @method orient\r\n// * @param {Number} xValF Forward vector X direction\r\n// * @param {Number} yValF Forward vector Y direction\r\n// * @param {Number} zValF Forward vector Z direction\r\n// * @param {Number} xValU Up vector X direction\r\n// * @param {Number} yValU Up vector Y direction\r\n// * @param {Number} zValU Up vector Z direction\r\n// * @param {Number} time \r\n// * @return {Array} All orienation params\r\n// */\r\n p5.Listener3D.prototype.orient = function(xValF, yValF, zValF, \r\n xValU, yValU, zValU, time) {\r\n\r\n if (arguments.length === 3 || arguments.length === 4) {\r\n time = arguments[3];\r\n this.orientForward(xValF, yValF, zValF, time);\r\n } else if (arguments.length === 6 || arguments === 7) {\r\n this.orientForward(xValF, yValF, zValF);\r\n this.orientUp(xValU, yValU, zValU, time);\r\n }\r\n \r\n return [this.listener.forwardX.value, \r\n this.listener.forwardY.value,\r\n this.listener.forwardZ.value,\r\n this.listener.upX.value,\r\n this.listener.upY.value,\r\n this.listener.upZ.value];\r\n };\r\n\r\n\r\n p5.Listener3D.prototype.orientForward = function(xValF, yValF, zValF, time) {\r\n this.forwardX(xValF,time);\r\n this.forwardY(yValF,time);\r\n this.forwardZ(zValF,time);\r\n\r\n return [this.listener.forwardX, \r\n this.listener.forwardY,\r\n this.listener.forwardZ];\r\n };\r\n\r\n p5.Listener3D.prototype.orientUp = function(xValU, yValU, zValU, time) {\r\n this.upX(xValU,time);\r\n this.upY(yValU,time);\r\n this.upZ(zValU,time);\r\n\r\n return [this.listener.upX, \r\n this.listener.upY,\r\n this.listener.upZ];\r\n };\r\n// /**\r\n// * Getter and setter methods for orient coordinates\r\n// * @return {Number} [updated coordinate value]\r\n// */\r\n p5.Listener3D.prototype.forwardX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.forwardX.value = xVal;\r\n this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.forwardX);\r\n }\r\n return this.listener.forwardX.value;\r\n };\r\n p5.Listener3D.prototype.forwardY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.forwardY.value = yVal;\r\n this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.forwardY);\r\n }\r\n return this.listener.forwardY.value;\r\n };\r\n p5.Listener3D.prototype.forwardZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.forwardZ.value = zVal;\r\n this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.forwardZ);\r\n }\r\n return this.listener.forwardZ.value;\r\n };\r\n p5.Listener3D.prototype.upX = function(xVal, time) {\r\n var t = time || 0;\r\n if (typeof xVal === 'number') {\r\n this.listener.upX.value = xVal;\r\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);\r\n } else if (xVal) {\r\n xVal.connect(this.listener.upX);\r\n }\r\n return this.listener.upX.value;\r\n };\r\n p5.Listener3D.prototype.upY = function(yVal, time) {\r\n var t = time || 0;\r\n if (typeof yVal === 'number') {\r\n this.listener.upY.value = yVal;\r\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);\r\n } else if (yVal) {\r\n yVal.connect(this.listener.upY);\r\n }\r\n return this.listener.upY.value;\r\n };\r\n p5.Listener3D.prototype.upZ = function(zVal, time) {\r\n var t = time || 0;\r\n if (typeof zVal === 'number') {\r\n this.listener.upZ.value = zVal;\r\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);\r\n } else if (zVal) {\r\n zVal.connect(this.listener.upZ);\r\n }\r\n return this.listener.upZ.value;\r\n };\r\n \r\n return p5.Listener3D;\r\n\r\n});","'use strict';\r\n\r\ndefine(function (require) {\r\n var Filter = require('filter');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Delay is an echo effect. It processes an existing sound source,\r\n * and outputs a delayed version of that sound. The p5.Delay can\r\n * produce different effects depending on the delayTime, feedback,\r\n * filter, and type. In the example below, a feedback of 0.5 (the\r\n * defaul value) will produce a looping delay that decreases in\r\n * volume by 50% each repeat. A filter will cut out the high\r\n * frequencies so that the delay does not sound as piercing as the\r\n * original source.\r\n *\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n * @class p5.Delay\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var noise, env, delay;\r\n *\r\n * function setup() {\r\n * background(0);\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * noise = new p5.Noise('brown');\r\n * noise.amp(0);\r\n * noise.start();\r\n *\r\n * delay = new p5.Delay();\r\n *\r\n * // delay.process() accepts 4 parameters:\r\n * // source, delayTime, feedback, filter frequency\r\n * // play with these numbers!!\r\n * delay.process(noise, .12, .7, 2300);\r\n *\r\n * // play the noise with an envelope,\r\n * // a series of fades ( time / value pairs )\r\n * env = new p5.Envelope(.01, 0.2, .2, .1);\r\n * }\r\n *\r\n * // mouseClick triggers envelope\r\n * function mouseClicked() {\r\n * // is mouse over canvas?\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * env.play(noise);\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Delay = function() {\r\n \tEffect.call(this);\r\n\r\n this._split = this.ac.createChannelSplitter(2);\r\n this._merge = this.ac.createChannelMerger(2);\r\n\r\n this._leftGain = this.ac.createGain();\r\n this._rightGain = this.ac.createGain();\r\n\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} leftDelay\r\n */\r\n this.leftDelay = this.ac.createDelay();\r\n /**\r\n * The p5.Delay is built with two\r\n * \r\n * Web Audio Delay Nodes, one for each stereo channel.\r\n *\r\n * @property {DelayNode} rightDelay\r\n */\r\n this.rightDelay = this.ac.createDelay();\r\n\r\n this._leftFilter = new Filter();\r\n this._rightFilter = new Filter();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n\r\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\r\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\r\n\r\n // graph routing\r\n this.input.connect(this._split);\r\n this.leftDelay.connect(this._leftGain);\r\n this.rightDelay.connect(this._rightGain);\r\n this._leftGain.connect(this._leftFilter.input);\r\n this._rightGain.connect(this._rightFilter.input);\r\n this._merge.connect(this.wet);\r\n\r\n\r\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\r\n\r\n // default routing\r\n this.setType(0);\r\n\r\n this._maxDelay = this.leftDelay.delayTime.maxValue;\r\n\r\n // set initial feedback to 0.5\r\n this.feedback(0.5);\r\n\r\n\r\n };\r\n\r\n p5.Delay.prototype = Object.create(Effect.prototype);\r\n /**\r\n * Add delay to an audio signal according to a set\r\n * of delay parameters.\r\n *\r\n * @method process\r\n * @for p5.Delay\r\n * @param {Object} Signal An object that outputs audio\r\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\r\n * Some browsers limit delayTime to\r\n * 1 second.\r\n * @param {Number} [feedback] sends the delay back through itself\r\n * in a loop that decreases in volume\r\n * each time.\r\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\r\n * below the lowPass will be part of the\r\n * delay.\r\n */\r\n p5.Delay.prototype.process = function(src, _delayTime, _feedback, _filter) {\r\n var feedback = _feedback || 0;\r\n var delayTime = _delayTime || 0;\r\n if (feedback >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n if (delayTime >= this._maxDelay) {\r\n throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.');\r\n }\r\n\r\n src.connect(this.input);\r\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\r\n this._leftGain.gain.value = feedback;\r\n this._rightGain.gain.value = feedback;\r\n\r\n if (_filter) {\r\n this._leftFilter.freq(_filter);\r\n this._rightFilter.freq(_filter);\r\n }\r\n };\r\n\r\n /**\r\n * Set the delay (echo) time, in seconds. Usually this value will be\r\n * a floating point number between 0.0 and 1.0.\r\n *\r\n * @method delayTime\r\n * @for p5.Delay\r\n * @param {Number} delayTime Time (in seconds) of the delay\r\n */\r\n p5.Delay.prototype.delayTime = function(t) {\r\n // if t is an audio node...\r\n if (typeof t !== 'number') {\r\n t.connect(this.leftDelay.delayTime);\r\n t.connect(this.rightDelay.delayTime);\r\n }\r\n\r\n else {\r\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\r\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\r\n }\r\n };\r\n\r\n /**\r\n * Feedback occurs when Delay sends its signal back through its input\r\n * in a loop. The feedback amount determines how much signal to send each\r\n * time through the loop. A feedback greater than 1.0 is not desirable because\r\n * it will increase the overall output each time through the loop,\r\n * creating an infinite feedback loop. The default value is 0.5\r\n *\r\n * @method feedback\r\n * @for p5.Delay\r\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\r\n * Oscillator that can be used to\r\n * modulate this param\r\n * @returns {Number} Feedback value\r\n *\r\n */\r\n p5.Delay.prototype.feedback = function(f) {\r\n // if f is an audio node...\r\n if (f && typeof f !== 'number') {\r\n f.connect(this._leftGain.gain);\r\n f.connect(this._rightGain.gain);\r\n }\r\n else if (f >= 1.0) {\r\n throw new Error('Feedback value will force a positive feedback loop.');\r\n }\r\n else if (typeof f === 'number') {\r\n this._leftGain.gain.value = f;\r\n this._rightGain.gain.value = f;\r\n }\r\n\r\n // return value of feedback\r\n return this._leftGain.gain.value;\r\n };\r\n\r\n /**\r\n * Set a lowpass filter frequency for the delay. A lowpass filter\r\n * will cut off any frequencies higher than the filter frequency.\r\n *\r\n * @method filter\r\n * @for p5.Delay\r\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\r\n * frequencies higher than the filter frequency.\r\n * @param {Number|Object} res Resonance of the filter frequency\r\n * cutoff, or an object (i.e. a p5.Oscillator)\r\n * that can be used to modulate this parameter.\r\n * High numbers (i.e. 15) will produce a resonance,\r\n * low numbers (i.e. .2) will produce a slope.\r\n */\r\n p5.Delay.prototype.filter = function(freq, q) {\r\n this._leftFilter.set(freq, q);\r\n this._rightFilter.set(freq, q);\r\n };\r\n\r\n\r\n /**\r\n * Choose a preset type of delay. 'pingPong' bounces the signal\r\n * from the left to the right channel to produce a stereo effect.\r\n * Any other parameter will revert to the default delay setting.\r\n *\r\n * @method setType\r\n * @for p5.Delay\r\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\r\n */\r\n p5.Delay.prototype.setType = function(t) {\r\n if (t === 1) {\r\n t = 'pingPong';\r\n }\r\n this._split.disconnect();\r\n this._leftFilter.disconnect();\r\n this._rightFilter.disconnect();\r\n this._split.connect(this.leftDelay, 0);\r\n this._split.connect(this.rightDelay, 1);\r\n switch(t) {\r\n case 'pingPong':\r\n this._rightFilter.setType( this._leftFilter.biquad.type );\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.rightDelay);\r\n this._rightFilter.output.connect(this.leftDelay);\r\n break;\r\n default:\r\n this._leftFilter.output.connect(this._merge, 0, 0);\r\n this._rightFilter.output.connect(this._merge, 0, 1);\r\n this._leftFilter.output.connect(this.leftDelay);\r\n this._rightFilter.output.connect(this.rightDelay);\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the delay effect.\r\n *\r\n * @method amp\r\n * @for p5.Delay\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Delay\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Delay\r\n */\r\n\r\n p5.Delay.prototype.dispose = function() {\r\n\r\n Effect.prototype.dispose.apply(this);\r\n\r\n this._split.disconnect();\r\n this._leftFilter.dispose();\r\n this._rightFilter.dispose();\r\n this._merge.disconnect();\r\n this._leftGain.disconnect();\r\n this._rightGain.disconnect();\r\n this.leftDelay.disconnect();\r\n this.rightDelay.disconnect();\r\n\r\n this._split = undefined;\r\n this._leftFilter = undefined;\r\n this._rightFilter = undefined;\r\n this._merge = undefined;\r\n this._leftGain = undefined;\r\n this._rightGain = undefined;\r\n this.leftDelay = undefined;\r\n this.rightDelay = undefined;\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var CustomError = require('errorHandler');\r\n var Effect = require('effect');\r\n\r\n /**\r\n * Reverb adds depth to a sound through a large number of decaying\r\n * echoes. It creates the perception that sound is occurring in a\r\n * physical space. The p5.Reverb has paramters for Time (how long does the\r\n * reverb last) and decayRate (how much the sound decays with each echo)\r\n * that can be set with the .set() or .process() methods. The p5.Convolver\r\n * extends p5.Reverb allowing you to recreate the sound of actual physical\r\n * spaces through convolution.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Reverb\r\n * @extends p5.Effect\r\n * @constructor\r\n * @example\r\n *
\r\n * var soundFile, reverb;\r\n * function preload() {\r\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * reverb = new p5.Reverb();\r\n * soundFile.disconnect(); // so we'll only hear reverb...\r\n *\r\n * // connect soundFile to reverb, process w/\r\n * // 3 second reverbTime, decayRate of 2%\r\n * reverb.process(soundFile, 3, 2);\r\n * soundFile.play();\r\n * }\r\n *
\r\n */\r\n\r\n\r\n p5.Reverb = function() {\r\n Effect.call(this);\r\n\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n // default params\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n\r\n };\r\n\r\n p5.Reverb.prototype = Object.create(Effect.prototype);\r\n\r\n p5.Reverb.prototype._initConvolverNode = function() {\r\n this.convolverNode = this.ac.createConvolver();\r\n this.input.connect(this.convolverNode);\r\n this.convolverNode.connect(this.wet);\r\n };\r\n\r\n p5.Reverb.prototype._teardownConvolverNode = function() {\r\n if (this.convolverNode) {\r\n this.convolverNode.disconnect();\r\n delete this.convolverNode;\r\n }\r\n };\r\n\r\n p5.Reverb.prototype._setBuffer = function(audioBuffer) {\r\n this._teardownConvolverNode();\r\n this._initConvolverNode();\r\n this.convolverNode.buffer = audioBuffer;\r\n };\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Reverb\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.process = function(src, seconds, decayRate, reverse) {\r\n src.connect(this.input);\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n /**\r\n * Set the reverb settings. Similar to .process(), but without\r\n * assigning a new input.\r\n *\r\n * @method set\r\n * @for p5.Reverb\r\n * @param {Number} [seconds] Duration of the reverb, in seconds.\r\n * Min: 0, Max: 10. Defaults to 3.\r\n * @param {Number} [decayRate] Percentage of decay with each echo.\r\n * Min: 0, Max: 100. Defaults to 2.\r\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\r\n */\r\n p5.Reverb.prototype.set = function(seconds, decayRate, reverse) {\r\n var rebuild = false;\r\n if (seconds) {\r\n this._seconds = seconds;\r\n rebuild = true;\r\n }\r\n if (decayRate) {\r\n this._decay = decayRate;\r\n }\r\n if (reverse) {\r\n this._reverse = reverse;\r\n }\r\n if (rebuild) {\r\n this._buildImpulse();\r\n }\r\n };\r\n\r\n // DocBlocks for methods inherited from p5.Effect\r\n /**\r\n * Set the output level of the reverb effect.\r\n *\r\n * @method amp\r\n * @for p5.Reverb\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Reverb\r\n * @param {Object} unit\r\n */\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Reverb\r\n */\r\n\r\n /**\r\n * Inspired by Simple Reverb by Jordan Santell\r\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\r\n *\r\n * Utility function for building an impulse response\r\n * based on the module parameters.\r\n *\r\n * @private\r\n */\r\n p5.Reverb.prototype._buildImpulse = function() {\r\n var rate = this.ac.sampleRate;\r\n var length = rate*this._seconds;\r\n var decay = this._decay;\r\n var impulse = this.ac.createBuffer(2, length, rate);\r\n var impulseL = impulse.getChannelData(0);\r\n var impulseR = impulse.getChannelData(1);\r\n var n, i;\r\n for (i = 0; i < length; i++) {\r\n n = this._reverse ? length - i : i;\r\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\r\n }\r\n this._setBuffer(impulse);\r\n };\r\n\r\n p5.Reverb.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n this._teardownConvolverNode();\r\n };\r\n\r\n // =======================================================================\r\n // *** p5.Convolver ***\r\n // =======================================================================\r\n\r\n /**\r\n *
p5.Convolver extends p5.Reverb. It can emulate the sound of real\r\n * physical spaces through a process called \r\n * convolution.
\r\n *\r\n *
Convolution multiplies any audio input by an \"impulse response\"\r\n * to simulate the dispersion of sound over time. The impulse response is\r\n * generated from an audio file that you provide. One way to\r\n * generate an impulse response is to pop a balloon in a reverberant space\r\n * and record the echo. Convolution can also be used to experiment with\r\n * sound.
\r\n *\r\n *
Use the method createConvolution(path) to instantiate a\r\n * p5.Convolver with a path to your impulse response audio file.
\r\n *\r\n * @class p5.Convolver\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call when loading succeeds\r\n * @param {Function} [errorCallback] function to call if loading fails.\r\n * This function will receive an error or\r\n * XMLHttpRequest object with information\r\n * about what went wrong.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver = function(path, callback, errorCallback) {\r\n \t p5.Reverb.call(this);\r\n\r\n /**\r\n * Internally, the p5.Convolver uses the a\r\n * \r\n * Web Audio Convolver Node.\r\n *\r\n * @property {ConvolverNode} convolverNode\r\n */\r\n this._initConvolverNode();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n\r\n if (path) {\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n }\r\n else {\r\n // parameters\r\n this._seconds = 3;\r\n this._decay = 2;\r\n this._reverse = false;\r\n\r\n this._buildImpulse();\r\n }\r\n\r\n };\r\n\r\n p5.Convolver.prototype = Object.create(p5.Reverb.prototype);\r\n\r\n p5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\r\n\r\n /**\r\n * Create a p5.Convolver. Accepts a path to a soundfile\r\n * that will be used to generate an impulse response.\r\n *\r\n * @method createConvolver\r\n * @for p5\r\n * @param {String} path path to a sound file\r\n * @param {Function} [callback] function to call if loading is successful.\r\n * The object will be passed in as the argument\r\n * to the callback function.\r\n * @param {Function} [errorCallback] function to call if loading is not successful.\r\n * A custom error will be passed in as the argument\r\n * to the callback function.\r\n * @return {p5.Convolver}\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * // We have both MP3 and OGG versions of all sound assets\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * // Try replacing 'bx-spring' with other soundfiles like\r\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\r\n * cVerb = createConvolver('assets/bx-spring.mp3');\r\n *\r\n * // Try replacing 'Damscray_DancingTiger' with\r\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\r\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.prototype.createConvolver = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n var self = this;\r\n var cReverb = new p5.Convolver(path, function(buffer) {\r\n if (typeof callback === 'function') {\r\n callback(buffer);\r\n }\r\n\r\n if (typeof self._decrementPreload === 'function') {\r\n self._decrementPreload();\r\n }\r\n }, errorCallback);\r\n cReverb.impulses = [];\r\n return cReverb;\r\n };\r\n\r\n /**\r\n * Private method to load a buffer as an Impulse Response,\r\n * assign it to the convolverNode, and add to the Array of .impulses.\r\n *\r\n * @param {String} path\r\n * @param {Function} callback\r\n * @param {Function} errorCallback\r\n * @private\r\n */\r\n p5.Convolver.prototype._loadBuffer = function(path, callback, errorCallback) {\r\n var path = p5.prototype._checkFileFormats(path);\r\n var self = this;\r\n var errorTrace = new Error().stack;\r\n var ac = p5.prototype.getAudioContext();\r\n\r\n var request = new XMLHttpRequest();\r\n request.open('GET', path, true);\r\n request.responseType = 'arraybuffer';\r\n\r\n request.onload = function() {\r\n if (request.status === 200) {\r\n // on success loading file:\r\n ac.decodeAudioData(request.response,\r\n function(buff) {\r\n var buffer = {};\r\n var chunks = path.split('/');\r\n buffer.name = chunks[chunks.length - 1];\r\n buffer.audioBuffer = buff;\r\n self.impulses.push(buffer);\r\n self._setBuffer(buffer.audioBuffer);\r\n if (callback) {\r\n callback(buffer);\r\n }\r\n },\r\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\r\n function() {\r\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\r\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\r\n if (errorCallback) {\r\n err.msg = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n );\r\n }\r\n // if request status != 200, it failed\r\n else {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'Unable to load ' + self.url +\r\n '. The request status was: ' + request.status + ' (' + request.statusText + ')';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n }\r\n };\r\n\r\n // if there is another error, aside from 404...\r\n request.onerror = function() {\r\n var err = new CustomError('loadConvolver', errorTrace, self.url);\r\n var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';\r\n\r\n if (errorCallback) {\r\n err.message = msg;\r\n errorCallback(err);\r\n } else {\r\n console.error(msg +'\\n The error stack trace includes: \\n' + err.stack);\r\n }\r\n };\r\n request.send();\r\n };\r\n\r\n p5.Convolver.prototype.set = null;\r\n\r\n /**\r\n * Connect a source to the reverb, and assign reverb parameters.\r\n *\r\n * @method process\r\n * @for p5.Convolver\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n * @example\r\n *
\r\n * var cVerb, sound;\r\n * function preload() {\r\n * soundFormats('ogg', 'mp3');\r\n *\r\n * cVerb = createConvolver('assets/concrete-tunnel.mp3');\r\n *\r\n * sound = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * // disconnect from master output...\r\n * sound.disconnect();\r\n *\r\n * // ...and process with (i.e. connect to) cVerb\r\n * // so that we only hear the convolution\r\n * cVerb.process(sound);\r\n *\r\n * sound.play();\r\n * }\r\n *
\r\n */\r\n p5.Convolver.prototype.process = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * If you load multiple impulse files using the .addImpulse method,\r\n * they will be stored as Objects in this Array. Toggle between them\r\n * with the toggleImpulse(id) method.\r\n *\r\n * @property {Array} impulses\r\n * @for p5.Convolver\r\n */\r\n p5.Convolver.prototype.impulses = [];\r\n\r\n /**\r\n * Load and assign a new Impulse Response to the p5.Convolver.\r\n * The impulse is added to the .impulses array. Previous\r\n * impulses can be accessed with the .toggleImpulse(id)\r\n * method.\r\n *\r\n * @method addImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.addImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * Similar to .addImpulse, except that the .impulses\r\n * Array is reset to save memory. A new .impulses\r\n * array is created with this impulse as the only item.\r\n *\r\n * @method resetImpulse\r\n * @for p5.Convolver\r\n * @param {String} path path to a sound file\r\n * @param {Function} callback function (optional)\r\n * @param {Function} errorCallback function (optional)\r\n */\r\n p5.Convolver.prototype.resetImpulse = function(path, callback, errorCallback) {\r\n // if loading locally without a server\r\n if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {\r\n alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');\r\n }\r\n this.impulses = [];\r\n this._loadBuffer(path, callback, errorCallback);\r\n };\r\n\r\n /**\r\n * If you have used .addImpulse() to add multiple impulses\r\n * to a p5.Convolver, then you can use this method to toggle between\r\n * the items in the .impulses Array. Accepts a parameter\r\n * to identify which impulse you wish to use, identified either by its\r\n * original filename (String) or by its position in the .impulses\r\n * Array (Number). \r\n * You can access the objects in the .impulses Array directly. Each\r\n * Object has two attributes: an .audioBuffer (type:\r\n * Web Audio \r\n * AudioBuffer) and a .name, a String that corresponds\r\n * with the original filename.\r\n *\r\n * @method toggleImpulse\r\n * @for p5.Convolver\r\n * @param {String|Number} id Identify the impulse by its original filename\r\n * (String), or by its position in the\r\n * .impulses Array (Number).\r\n */\r\n p5.Convolver.prototype.toggleImpulse = function(id) {\r\n if (typeof id === 'number' && id < this.impulses.length) {\r\n this._setBuffer(this.impulses[id].audioBuffer);\r\n }\r\n if (typeof id === 'string') {\r\n for (var i = 0; i < this.impulses.length; i++) {\r\n if (this.impulses[i].name === id) {\r\n this._setBuffer(this.impulses[i].audioBuffer);\r\n break;\r\n }\r\n }\r\n }\r\n };\r\n\r\n p5.Convolver.prototype.dispose = function() {\r\n p5.Reverb.prototype.dispose.apply(this);\r\n\r\n // remove all the Impulse Response buffers\r\n for (var i in this.impulses) {\r\n if (this.impulses[i]) {\r\n this.impulses[i] = null;\r\n }\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n // requires the Tone.js library's Clock (MIT license, Yotam Mann)\r\n // https://github.com/TONEnoTONE/Tone.js/\r\n var Clock = require('Tone/core/Clock');\r\n\r\n p5.Metro = function() {\r\n this.clock = new Clock({\r\n 'callback': this.ontick.bind(this)\r\n });\r\n this.syncedParts = [];\r\n this.bpm = 120; // gets overridden by p5.Part\r\n this._init();\r\n\r\n this.prevTick = 0;\r\n this.tatumTime = 0;\r\n\r\n this.tickCallback = function() {};\r\n };\r\n\r\n p5.Metro.prototype.ontick = function(tickTime) {\r\n var elapsedTime = tickTime - this.prevTick;\r\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\r\n if (elapsedTime - this.tatumTime <= -0.02) {\r\n return;\r\n } else {\r\n // console.log('ok', this.syncedParts[0].phrases[0].name);\r\n this.prevTick = tickTime;\r\n\r\n // for all of the active things on the metro:\r\n var self = this;\r\n this.syncedParts.forEach(function(thisPart) {\r\n if (!thisPart.isPlaying) return;\r\n thisPart.incrementStep(secondsFromNow);\r\n // each synced source keeps track of its own beat number\r\n thisPart.phrases.forEach(function(thisPhrase) {\r\n var phraseArray = thisPhrase.sequence;\r\n var bNum = self.metroTicks % phraseArray.length;\r\n if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping) ) {\r\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\r\n }\r\n });\r\n });\r\n this.metroTicks += 1;\r\n this.tickCallback(secondsFromNow);\r\n }\r\n };\r\n\r\n p5.Metro.prototype.setBPM = function(bpm, rampTime) {\r\n var beatTime = 60 / (bpm*this.tatums);\r\n var now = p5sound.audiocontext.currentTime;\r\n this.tatumTime = beatTime;\r\n\r\n var rampTime = rampTime || 0;\r\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\r\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\r\n this.bpm = bpm;\r\n };\r\n\r\n p5.Metro.prototype.getBPM = function() {\r\n return this.clock.getRate() / this.tatums * 60;\r\n };\r\n\r\n p5.Metro.prototype._init = function() {\r\n this.metroTicks = 0;\r\n // this.setBPM(120);\r\n };\r\n\r\n // clear existing synced parts, add only this one\r\n p5.Metro.prototype.resetSync = function(part) {\r\n this.syncedParts = [part];\r\n };\r\n\r\n // push a new synced part to the array\r\n p5.Metro.prototype.pushSync = function(part) {\r\n this.syncedParts.push(part);\r\n };\r\n\r\n p5.Metro.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.start(now + t);\r\n this.setBPM(this.bpm);\r\n };\r\n\r\n p5.Metro.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n this.clock.stop(now + t);\r\n };\r\n\r\n p5.Metro.prototype.beatLength = function(tatums) {\r\n this.tatums = 1/tatums / 4; // lowest possible division of a beat\r\n };\r\n\r\n});\r\n","define([\"Tone/core/Tone\", \"Tone/core/Timeline\", \"Tone/type/Type\"], function (Tone) {\n\n\t\"use strict\";\n\n\t/**\n\t * @class A Timeline State. Provides the methods: setStateAtTime(\"state\", time)\n\t * and getValueAtTime(time).\n\t *\n\t * @extends {Tone.Timeline}\n\t * @param {String} initial The initial state of the TimelineState. \n\t * Defaults to undefined\n\t */\n\tTone.TimelineState = function(initial){\n\n\t\tTone.Timeline.call(this);\n\n\t\t/**\n\t\t * The initial state\n\t\t * @private\n\t\t * @type {String}\n\t\t */\n\t\tthis._initial = initial;\n\t};\n\n\tTone.extend(Tone.TimelineState, Tone.Timeline);\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {Number} time The time to query.\n\t * @return {String} The name of the state input in setStateAtTime.\n\t */\n\tTone.TimelineState.prototype.getValueAtTime = function(time){\n\t\tvar event = this.get(time);\n\t\tif (event !== null){\n\t\t\treturn event.state;\n\t\t} else {\n\t\t\treturn this._initial;\n\t\t}\n\t};\n\n\t/**\n\t * Returns the scheduled state scheduled before or at\n\t * the given time.\n\t * @param {String} state The name of the state to set.\n\t * @param {Number} time The time to query.\n\t */\n\tTone.TimelineState.prototype.setStateAtTime = function(state, time){\n\t\tthis.add({\n\t\t\t\"state\" : state,\n\t\t\t\"time\" : time\n\t\t});\n\t};\n\n\treturn Tone.TimelineState;\n});","'use strict';\r\n\r\ndefine(function(require) {\r\n var p5sound = require('master');\r\n\r\n var BPM = 120;\r\n\r\n /**\r\n * Set the global tempo, in beats per minute, for all\r\n * p5.Parts. This method will impact all active p5.Parts.\r\n *\r\n * @method setBPM\r\n * @for p5\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.prototype.setBPM = function(bpm, rampTime) {\r\n BPM = bpm;\r\n for (var i in p5sound.parts) {\r\n if (p5sound.parts[i]) {\r\n p5sound.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n *
A phrase is a pattern of musical events over time, i.e.\r\n * a series of notes and rests.
\r\n *\r\n *
Phrases must be added to a p5.Part for playback, and\r\n * each part can play multiple phrases at the same time.\r\n * For example, one Phrase might be a kick drum, another\r\n * could be a snare, and another could be the bassline.
\r\n *\r\n *
The first parameter is a name so that the phrase can be\r\n * modified or deleted later. The callback is a a function that\r\n * this phrase will call at every step—for example it might be\r\n * called playNote(value){}. The array determines\r\n * which value is passed into the callback at each step of the\r\n * phrase. It can be numbers, an object with multiple numbers,\r\n * or a zero (0) indicates a rest so the callback won't be called).
\r\n *\r\n * @class p5.Phrase\r\n * @constructor\r\n * @param {String} name Name so that you can access the Phrase.\r\n * @param {Function} callback The name of a function that this phrase\r\n * will call. Typically it will play a sound,\r\n * and accept two parameters: a time at which\r\n * to play the sound (in seconds from now),\r\n * and a value from the sequence array. The\r\n * time should be passed into the play() or\r\n * start() method to ensure precision.\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n * @example\r\n *
\r\n */\r\n p5.Phrase = function(name, callback, sequence) {\r\n this.phraseStep = 0;\r\n this.name = name;\r\n this.callback = callback;\r\n /**\r\n * Array of values to pass into the callback\r\n * at each step of the phrase. Depending on the callback\r\n * function's requirements, these values may be numbers,\r\n * strings, or an object with multiple parameters.\r\n * Zero (0) indicates a rest.\r\n *\r\n * @property {Array} sequence\r\n */\r\n this.sequence = sequence;\r\n };\r\n\r\n /**\r\n *
A p5.Part plays back one or more p5.Phrases. Instantiate a part\r\n * with steps and tatums. By default, each step represents a 1/16th note.
\r\n *\r\n *
See p5.Phrase for more about musical timing.
\r\n *\r\n * @class p5.Part\r\n * @constructor\r\n * @param {Number} [steps] Steps in the part\r\n * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note)\r\n * @example\r\n *
\r\n * var box, drum, myPart;\r\n * var boxPat = [1,0,0,2,0,2,0,0];\r\n * var drumPat = [0,1,1,0,2,0,1,0];\r\n * var msg = 'click to play';\r\n *\r\n * function preload() {\r\n * box = loadSound('assets/beatbox.mp3');\r\n * drum = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * noStroke();\r\n * fill(255);\r\n * textAlign(CENTER);\r\n * masterVolume(0.1);\r\n *\r\n * var boxPhrase = new p5.Phrase('box', playBox, boxPat);\r\n * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\r\n * myPart = new p5.Part();\r\n * myPart.addPhrase(boxPhrase);\r\n * myPart.addPhrase(drumPhrase);\r\n * myPart.setBPM(60);\r\n * masterVolume(0.1);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * text(msg, width/2, height/2);\r\n * }\r\n *\r\n * function playBox(time, playbackRate) {\r\n * box.rate(playbackRate);\r\n * box.play(time);\r\n * }\r\n *\r\n * function playDrum(time, playbackRate) {\r\n * drum.rate(playbackRate);\r\n * drum.play(time);\r\n * }\r\n *\r\n * function mouseClicked() {\r\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\r\n * myPart.start();\r\n * msg = 'playing part';\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.Part = function(steps, bLength) {\r\n this.length = steps || 0; // how many beats\r\n this.partStep = 0;\r\n this.phrases = [];\r\n this.isPlaying = false;\r\n this.noLoop();\r\n this.tatums = bLength || 0.0625; // defaults to quarter note\r\n\r\n this.metro = new p5.Metro();\r\n this.metro._init();\r\n this.metro.beatLength(this.tatums);\r\n this.metro.setBPM(BPM);\r\n p5sound.parts.push(this);\r\n this.callback = function() {};\r\n };\r\n\r\n /**\r\n * Set the tempo of this part, in Beats Per Minute.\r\n *\r\n * @method setBPM\r\n * @for p5.Part\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} [rampTime] Seconds from now\r\n */\r\n p5.Part.prototype.setBPM = function(tempo, rampTime) {\r\n this.metro.setBPM(tempo, rampTime);\r\n };\r\n\r\n /**\r\n * Returns the tempo, in Beats Per Minute, of this part.\r\n *\r\n * @method getBPM\r\n * @for p5.Part\r\n * @return {Number}\r\n */\r\n p5.Part.prototype.getBPM = function() {\r\n return this.metro.getBPM();\r\n };\r\n\r\n /**\r\n * Start playback of this part. It will play\r\n * through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method start\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.start = function(time) {\r\n if (!this.isPlaying) {\r\n this.isPlaying = true;\r\n this.metro.resetSync(this);\r\n var t = time || 0;\r\n this.metro.start(t);\r\n }\r\n };\r\n\r\n /**\r\n * Loop playback of this part. It will begin\r\n * looping through all of its phrases at a speed\r\n * determined by setBPM.\r\n *\r\n * @method loop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.loop = function(time) {\r\n this.looping = true;\r\n // rest onended function\r\n this.onended = function() {\r\n this.partStep = 0;\r\n };\r\n var t = time || 0;\r\n this.start(t);\r\n };\r\n\r\n /**\r\n * Tell the part to stop looping.\r\n *\r\n * @method noLoop\r\n * @for p5.Part\r\n */\r\n p5.Part.prototype.noLoop = function() {\r\n this.looping = false;\r\n // rest onended function\r\n this.onended = function() {\r\n this.stop();\r\n };\r\n };\r\n\r\n /**\r\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\r\n *\r\n * @method stop\r\n * @for p5.Part\r\n * @param {Number} [time] seconds from now\r\n */\r\n p5.Part.prototype.stop = function(time) {\r\n this.partStep = 0;\r\n this.pause(time);\r\n };\r\n\r\n /**\r\n * Pause the part. Playback will resume\r\n * from the current step.\r\n *\r\n * @method pause\r\n * @for p5.Part\r\n * @param {Number} time seconds from now\r\n */\r\n p5.Part.prototype.pause = function(time) {\r\n this.isPlaying = false;\r\n var t = time || 0;\r\n this.metro.stop(t);\r\n };\r\n\r\n /**\r\n * Add a p5.Phrase to this Part.\r\n *\r\n * @method addPhrase\r\n * @for p5.Part\r\n * @param {p5.Phrase} phrase reference to a p5.Phrase\r\n */\r\n p5.Part.prototype.addPhrase = function(name, callback, array) {\r\n var p;\r\n if (arguments.length === 3) {\r\n p = new p5.Phrase(name, callback, array);\r\n } else if (arguments[0] instanceof p5.Phrase) {\r\n p = arguments[0];\r\n } else {\r\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\r\n }\r\n this.phrases.push(p);\r\n // reset the length if phrase is longer than part's existing length\r\n if (p.sequence.length > this.length) {\r\n this.length = p.sequence.length;\r\n }\r\n };\r\n\r\n /**\r\n * Remove a phrase from this part, based on the name it was\r\n * given when it was created.\r\n *\r\n * @method removePhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.removePhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases.splice(i, 1);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Get a phrase from this part, based on the name it was\r\n * given when it was created. Now you can modify its array.\r\n *\r\n * @method getPhrase\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n */\r\n p5.Part.prototype.getPhrase = function(name) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n return this.phrases[i];\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Find all sequences with the specified name, and replace their patterns with the specified array.\r\n *\r\n * @method replaceSequence\r\n * @for p5.Part\r\n * @param {String} phraseName\r\n * @param {Array} sequence Array of values to pass into the callback\r\n * at each step of the phrase.\r\n */\r\n p5.Part.prototype.replaceSequence = function(name, array) {\r\n for (var i in this.phrases) {\r\n if (this.phrases[i].name === name) {\r\n this.phrases[i].sequence = array;\r\n }\r\n }\r\n };\r\n\r\n p5.Part.prototype.incrementStep = function(time) {\r\n if (this.partStep < this.length - 1) {\r\n this.callback(time);\r\n this.partStep += 1;\r\n } else {\r\n if (!this.looping && this.partStep === this.length - 1) {\r\n console.log('done');\r\n // this.callback(time);\r\n this.onended();\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the function that will be called at every step. This will clear the previous function.\r\n *\r\n * @method onStep\r\n * @for p5.Part\r\n * @param {Function} callback The name of the callback\r\n * you want to fire\r\n * on every beat/tatum.\r\n */\r\n p5.Part.prototype.onStep = function(callback) {\r\n this.callback = callback;\r\n };\r\n\r\n\r\n // ===============\r\n // p5.Score\r\n // ===============\r\n\r\n /**\r\n * A Score consists of a series of Parts. The parts will\r\n * be played back in order. For example, you could have an\r\n * A part, a B part, and a C part, and play them back in this order\r\n * new p5.Score(a, a, b, a, c)\r\n *\r\n * @class p5.Score\r\n * @constructor\r\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\r\n */\r\n p5.Score = function() {\r\n // for all of the arguments\r\n this.parts = [];\r\n this.currentPart = 0;\r\n\r\n var thisScore = this;\r\n for (var i in arguments) {\r\n if (arguments[i] && this.parts[i]) {\r\n this.parts[i] = arguments[i];\r\n this.parts[i].nextPart = this.parts[i + 1];\r\n this.parts[i].onended = function() {\r\n thisScore.resetPart(i);\r\n playNextPart(thisScore);\r\n };\r\n }\r\n }\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.onended = function() {\r\n if (this.looping) {\r\n // this.resetParts();\r\n this.parts[0].start();\r\n } else {\r\n this.parts[this.parts.length - 1].onended = function() {\r\n this.stop();\r\n this.resetParts();\r\n };\r\n }\r\n this.currentPart = 0;\r\n };\r\n\r\n /**\r\n * Start playback of the score.\r\n *\r\n * @method start\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.start = function() {\r\n this.parts[this.currentPart].start();\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Stop playback of the score.\r\n *\r\n * @method stop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.stop = function() {\r\n this.parts[this.currentPart].stop();\r\n this.currentPart = 0;\r\n this.scoreStep = 0;\r\n };\r\n\r\n /**\r\n * Pause playback of the score.\r\n *\r\n * @method pause\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.pause = function() {\r\n this.parts[this.currentPart].stop();\r\n };\r\n\r\n /**\r\n * Loop playback of the score.\r\n *\r\n * @method loop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.loop = function() {\r\n this.looping = true;\r\n this.start();\r\n };\r\n\r\n /**\r\n * Stop looping playback of the score. If it\r\n * is currently playing, this will go into effect\r\n * after the current round of playback completes.\r\n *\r\n * @method noLoop\r\n * @for p5.Score\r\n */\r\n p5.Score.prototype.noLoop = function() {\r\n this.looping = false;\r\n };\r\n\r\n p5.Score.prototype.resetParts = function() {\r\n var self = this;\r\n this.parts.forEach(function(part) {\r\n self.resetParts[part];\r\n });\r\n };\r\n\r\n p5.Score.prototype.resetPart = function(i) {\r\n this.parts[i].stop();\r\n this.parts[i].partStep = 0;\r\n for (var p in this.parts[i].phrases) {\r\n if (this.parts[i]) {\r\n this.parts[i].phrases[p].phraseStep = 0;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Set the tempo for all parts in the score\r\n *\r\n * @method setBPM\r\n * @for p5.Score\r\n * @param {Number} BPM Beats Per Minute\r\n * @param {Number} rampTime Seconds from now\r\n */\r\n p5.Score.prototype.setBPM = function(bpm, rampTime) {\r\n for (var i in this.parts) {\r\n if (this.parts[i]) {\r\n this.parts[i].setBPM(bpm, rampTime);\r\n }\r\n }\r\n };\r\n\r\n function playNextPart(aScore) {\r\n aScore.currentPart++;\r\n if (aScore.currentPart >= aScore.parts.length) {\r\n aScore.scoreStep = 0;\r\n aScore.onended();\r\n } else {\r\n aScore.scoreStep = 0;\r\n aScore.parts[aScore.currentPart - 1].stop();\r\n aScore.parts[aScore.currentPart].start();\r\n }\r\n }\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n var Clock = require('Tone/core/Clock');\r\n\r\n /**\r\n * SoundLoop\r\n *\r\n * @class p5.SoundLoop\r\n * @constructor\r\n *\r\n * @param {Function} callback this function will be called on each iteration of theloop\r\n * @param {Number|String} [interval] amount of time or beats for each iteration of the loop\r\n * defaults to 1\r\n *\r\n * @example\r\n *
\r\n * var click;\r\n * var looper1;\r\n *\r\n * function preload() {\r\n * click = loadSound('assets/drum.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * //the looper's callback is passed the timeFromNow\r\n * //this value should be used as a reference point from\r\n * //which to schedule sounds\r\n * looper1 = new p5.SoundLoop(function(timeFromNow){\r\n * click.play(timeFromNow);\r\n * background(255 * (looper1.iterations % 2));\r\n * }, 2);\r\n *\r\n * //stop after 10 iteratios;\r\n * looper1.maxIterations = 10;\r\n * //start the loop\r\n * looper1.start();\r\n * }\r\n *
\r\n */\r\n p5.SoundLoop = function(callback, interval) {\r\n this.callback = callback;\r\n /**\r\n * musicalTimeMode uses Tone.Time convention\r\n\t * true if string, false if number\r\n * @property {Boolean} musicalTimeMode\r\n */\r\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\r\n\r\n this._interval = interval || 1;\r\n\r\n /**\r\n * musicalTimeMode variables\r\n * modify these only when the interval is specified in musicalTime format as a string\r\n */\r\n this._timeSignature = 4;\r\n this._bpm = 60;\r\n\r\n this.isPlaying = false;\r\n\r\n /**\r\n * Set a limit to the number of loops to play. defaults to Infinity\r\n * @property {Number} maxIterations\r\n */\r\n this.maxIterations = Infinity;\r\n var self = this;\r\n\r\n this.clock = new Clock({\r\n 'callback' : function(time) {\r\n var timeFromNow = time - p5sound.audiocontext.currentTime;\r\n /**\r\n * Do not initiate the callback if timeFromNow is < 0\r\n * This ususually occurs for a few milliseconds when the page\r\n * is not fully loaded\r\n *\r\n * The callback should only be called until maxIterations is reached\r\n */\r\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\r\n self.callback(timeFromNow);}\r\n },\r\n 'frequency' : this._calcFreq()\r\n });\r\n };\r\n\r\n /**\r\n * Start the loop\r\n * @method start\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a starting time\r\n */\r\n p5.SoundLoop.prototype.start = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (!this.isPlaying) {\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n /**\r\n * Stop the loop\r\n * @method stop\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a stopping time\r\n */\r\n p5.SoundLoop.prototype.stop = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.stop(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n /**\r\n * Pause the loop\r\n * @method pause\r\n * @for p5.SoundLoop\r\n * @param {Number} [timeFromNow] schedule a pausing time\r\n */\r\n p5.SoundLoop.prototype.pause = function(timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n if (this.isPlaying) {\r\n this.clock.pause(now + t);\r\n this.isPlaying = false;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Synchronize loops. Use this method to start two more more loops in synchronization\r\n * or to start a loop in synchronization with a loop that is already playing\r\n * This method will schedule the implicit loop in sync with the explicit master loop\r\n * i.e. loopToStart.syncedStart(loopToSyncWith)\r\n *\r\n * @method syncedStart\r\n * @for p5.SoundLoop\r\n * @param {Object} otherLoop a p5.SoundLoop to sync with\r\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\r\n */\r\n p5.SoundLoop.prototype.syncedStart = function(otherLoop, timeFromNow) {\r\n var t = timeFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n\r\n if (!otherLoop.isPlaying) {\r\n otherLoop.clock.start(now + t);\r\n otherLoop.isPlaying = true;\r\n this.clock.start(now + t);\r\n this.isPlaying = true;\r\n } else if (otherLoop.isPlaying) {\r\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\r\n this.clock.start(now + time);\r\n this.isPlaying = true;\r\n }\r\n };\r\n\r\n\r\n /**\r\n * Updates frequency value, reflected in next callback\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _update\r\n */\r\n p5.SoundLoop.prototype._update = function() {\r\n this.clock.frequency.value = this._calcFreq();\r\n };\r\n\r\n /**\r\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _calcFreq\r\n * @return {Number} new clock frequency value\r\n */\r\n p5.SoundLoop.prototype._calcFreq = function() {\r\n //Seconds mode, bpm / timesignature has no effect\r\n if (typeof this._interval === 'number') {\r\n this.musicalTimeMode = false;\r\n return 1 / this._interval;\r\n }\r\n //Musical timing mode, calculate interval based bpm, interval,and time signature\r\n else if (typeof this._interval === 'string') {\r\n this.musicalTimeMode = true;\r\n return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4);\r\n }\r\n };\r\n\r\n /**\r\n * Convert notation from musical time format to seconds\r\n * Uses Tone.Time convention\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _convertNotation\r\n * @param {String} value value to be converted\r\n * @return {Number} converted value in seconds\r\n */\r\n p5.SoundLoop.prototype._convertNotation = function(value) {\r\n var type = value.slice(-1);\r\n value = Number(value.slice(0,-1));\r\n switch (type) {\r\n case 'm':\r\n return this._measure(value);\r\n case 'n':\r\n return this._note(value);\r\n default:\r\n console.warn('Specified interval is not formatted correctly. See Tone.js '+\r\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time');\r\n }\r\n };\r\n\r\n /**\r\n * Helper conversion methods of measure and note\r\n * @private\r\n * @for p5.SoundLoop\r\n * @method _measure\r\n */\r\n p5.SoundLoop.prototype._measure = function(value) {\r\n return value * this._timeSignature;\r\n };\r\n\r\n /**\r\n * @private\r\n * @method _note\r\n * @for p5.SoundLoop\r\n */\r\n p5.SoundLoop.prototype._note = function(value) {\r\n return this._timeSignature / value ;\r\n };\r\n\r\n\r\n /**\r\n * Getters and Setters, setting any paramter will result in a change in the clock's\r\n * frequency, that will be reflected after the next callback\r\n * beats per minute (defaults to 60)\r\n * @property {Number} bpm\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'bpm', {\r\n get : function() {\r\n return this._bpm;\r\n },\r\n set : function(bpm) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the BPM in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._bpm = bpm;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * number of quarter notes in a measure (defaults to 4)\r\n * @property {Number} timeSignature\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {\r\n get : function() {\r\n return this._timeSignature;\r\n },\r\n set : function(timeSig) {\r\n if (!this.musicalTimeMode) {\r\n console.warn('Changing the timeSignature in \"seconds\" mode has no effect. '+\r\n 'BPM is only relevant in musicalTimeMode '+\r\n 'when the interval is specified as a string '+\r\n '(\"2n\", \"4n\", \"1m\"...etc)');\r\n }\r\n this._timeSignature = timeSig;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * length of the loops interval\r\n * @property {Number|String} interval\r\n * @for p5.SoundLoop\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'interval', {\r\n get : function() {\r\n return this._interval;\r\n },\r\n set : function(interval) {\r\n this.musicalTimeMode = typeof interval === 'Number'? false : true;\r\n this._interval = interval;\r\n this._update();\r\n }\r\n });\r\n\r\n /**\r\n * how many times the callback has been called so far\r\n * @property {Number} iterations\r\n * @for p5.SoundLoop\r\n * @readonly\r\n */\r\n Object.defineProperty(p5.SoundLoop.prototype, 'iterations', {\r\n get : function() {\r\n return this.clock.ticks;\r\n }\r\n });\r\n\r\n return p5.SoundLoop;\r\n});\r\n","define(function (require) {\r\n\t'use strict';\r\n\r\n\tvar p5sound = require('master');\r\n\tvar Effect = require('effect');\r\n var CustomError = require('errorHandler');\r\n\r\n /**\r\n * Compressor is an audio effect class that performs dynamics compression\r\n * on an audio input source. This is a very commonly used technique in music\r\n * and sound production. Compression creates an overall louder, richer,\r\n * and fuller sound by lowering the volume of louds and raising that of softs.\r\n * Compression can be used to avoid clipping (sound distortion due to\r\n * peaks in volume) and is especially useful when many sounds are played\r\n * at once. Compression can be used on indivudal sound sources in addition\r\n * to the master output.\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Compressor\r\n * @constructor\r\n * @extends p5.Effect\r\n *\r\n *\r\n */\r\n\tp5.Compressor = function() {\r\n\t\tEffect.call(this);\r\n\r\n /**\r\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\r\n * \r\n * @property {AudioNode} compressor\r\n */\r\n\r\n\r\n\t\tthis.compressor = this.ac.createDynamicsCompressor();\r\n\r\n this.input.connect(this.compressor);\r\n this.compressor.connect(this.wet);\r\n\t};\r\n\r\n\tp5.Compressor.prototype = Object.create(Effect.prototype);\r\n\r\n /**\r\n * Performs the same function as .connect, but also accepts\r\n * optional parameters to set compressor's audioParams\r\n * @method process\r\n * @for p5.Compressor\r\n *\r\n * @param {Object} src Sound source to be connected\r\n *\r\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n\tp5.Compressor.prototype.process = function(src, attack, knee,\r\n ratio, threshold, release) {\r\n\t\tsrc.connect(this.input);\r\n\t\tthis.set(attack, knee, ratio, threshold, release);\r\n\t};\r\n\r\n /**\r\n * Set the paramters of a compressor.\r\n * @method set\r\n * @for p5.Compressor\r\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} knee A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n */\r\n p5.Compressor.prototype.set = function (attack, knee,\r\n ratio, threshold, release) {\r\n\r\n if (typeof attack !== 'undefined') {this.attack(attack);}\r\n if (typeof knee !== 'undefined') {this.knee(knee);}\r\n if (typeof ratio !== 'undefined') {this.ratio(ratio);}\r\n if (typeof threshold !== 'undefined') {this.threshold(threshold);}\r\n if (typeof release !== 'undefined') {this.release(release);}\r\n };\r\n\r\n\r\n /**\r\n * Get current attack or set value w/ time ramp\r\n *\r\n *\r\n * @method attack\r\n * @for p5.Compressor\r\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\r\n * default = .003, range 0 - 1\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.attack = function (attack, time){\r\n var t = time || 0;\r\n if (typeof attack == 'number'){\r\n this.compressor.attack.value = attack;\r\n this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof attack !== 'undefined') {\r\n attack.connect(this.compressor.attack);\r\n }\r\n return this.compressor.attack.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current knee or set value w/ time ramp\r\n *\r\n * @method knee\r\n * @for p5.Compressor\r\n * @param {Number} [knee] A decibel value representing the range above the\r\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\r\n * default = 30, range 0 - 40\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.knee = function (knee, time){\r\n var t = time || 0;\r\n if (typeof knee == 'number'){\r\n this.compressor.knee.value = knee;\r\n this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof knee !== 'undefined') {\r\n knee.connect(this.compressor.knee);\r\n }\r\n return this.compressor.knee.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current ratio or set value w/ time ramp\r\n * @method ratio\r\n * @for p5.Compressor\r\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\r\n * default = 12, range 1 - 20\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.ratio = function (ratio, time){\r\n var t = time || 0;\r\n if (typeof ratio == 'number'){\r\n this.compressor.ratio.value = ratio;\r\n this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof ratio !== 'undefined') {\r\n ratio.connect(this.compressor.ratio);\r\n }\r\n return this.compressor.ratio.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current threshold or set value w/ time ramp\r\n * @method threshold\r\n * @for p5.Compressor\r\n * @param {Number} threshold The decibel value above which the compression will start taking effect\r\n * default = -24, range -100 - 0\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.threshold = function (threshold, time){\r\n var t = time || 0;\r\n if (typeof threshold == 'number'){\r\n this.compressor.threshold.value = threshold;\r\n this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof threshold !== 'undefined') {\r\n threshold.connect(this.compressor.threshold);\r\n }\r\n return this.compressor.threshold.value;\r\n };\r\n\r\n\r\n /**\r\n * Get current release or set value w/ time ramp\r\n * @method release\r\n * @for p5.Compressor\r\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\r\n * default = .25, range 0 - 1\r\n *\r\n * @param {Number} [time] Assign time value to schedule the change in value\r\n */\r\n p5.Compressor.prototype.release = function (release, time){\r\n var t = time || 0;\r\n if (typeof release == 'number'){\r\n this.compressor.release.value = release;\r\n this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\r\n this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t);\r\n } else if (typeof number !== 'undefined') {\r\n release.connect(this.compressor.release);\r\n }\r\n return this.compressor.release.value;\r\n };\r\n\r\n /**\r\n * Return the current reduction value\r\n *\r\n * @method reduction\r\n * @for p5.Compressor\r\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\r\n */\r\n p5.Compressor.prototype.reduction =function() {\r\n return this.compressor.reduction.value;\r\n };\r\n\r\n\r\n\tp5.Compressor.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.compressor) {\r\n this.compressor.disconnect();\r\n delete this.compressor;\r\n }\r\n\t};\r\n\r\n return p5.Compressor;\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n // inspiration: recorder.js, Tone.js & typedarray.org\r\n\r\n var p5sound = require('master');\r\n var convertToWav = require('helpers').convertToWav;\r\n var processorNames = require('./audioWorklet/processorNames');\r\n var ac = p5sound.audiocontext;\r\n\r\n /**\r\n *
Record sounds for playback and/or to save as a .wav file.\r\n * The p5.SoundRecorder records all sound output from your sketch,\r\n * or can be assigned a specific source with setInput().
\r\n *
The record() method accepts a p5.SoundFile as a parameter.\r\n * When playback is stopped (either after the given amount of time,\r\n * or with the stop() method), the p5.SoundRecorder will send its\r\n * recording to that p5.SoundFile for playback.
\r\n * var mic, recorder, soundFile;\r\n * var state = 0;\r\n *\r\n * function setup() {\r\n * background(200);\r\n * // create an audio in\r\n * mic = new p5.AudioIn();\r\n *\r\n * // prompts user to enable their browser mic\r\n * mic.start();\r\n *\r\n * // create a sound recorder\r\n * recorder = new p5.SoundRecorder();\r\n *\r\n * // connect the mic to the recorder\r\n * recorder.setInput(mic);\r\n *\r\n * // this sound file will be used to\r\n * // playback & save the recording\r\n * soundFile = new p5.SoundFile();\r\n *\r\n * text('keyPress to record', 20, 20);\r\n * }\r\n *\r\n * function keyPressed() {\r\n * // make sure user enabled the mic\r\n * if (state === 0 && mic.enabled) {\r\n *\r\n * // record to our p5.SoundFile\r\n * recorder.record(soundFile);\r\n *\r\n * background(255,0,0);\r\n * text('Recording!', 20, 20);\r\n * state++;\r\n * }\r\n * else if (state === 1) {\r\n * background(0,255,0);\r\n *\r\n * // stop recorder and\r\n * // send result to soundFile\r\n * recorder.stop();\r\n *\r\n * text('Stopped', 20, 20);\r\n * state++;\r\n * }\r\n *\r\n * else if (state === 2) {\r\n * soundFile.play(); // play the result!\r\n * save(soundFile, 'mySound.wav');\r\n * state++;\r\n * }\r\n * }\r\n *
\r\n */\r\n p5.SoundRecorder = function() {\r\n this.input = ac.createGain();\r\n this.output = ac.createGain();\r\n\r\n this._inputChannels = 2;\r\n this._outputChannels = 2; // stereo output, even if input is mono\r\n\r\n this._workletNode = new AudioWorkletNode(ac, processorNames.recorderProcessor, {\r\n outputChannelCount: [this._outputChannels],\r\n processorOptions: { numInputChannels: this._inputChannels }\r\n });\r\n\r\n this._workletNode.port.onmessage = function(event) {\r\n if (event.data.name === 'buffers') {\r\n const buffers = [\r\n new Float32Array(event.data.leftBuffer),\r\n new Float32Array(event.data.rightBuffer)\r\n ];\r\n this._callback(buffers);\r\n }\r\n }.bind(this);\r\n\r\n /**\r\n * callback invoked when the recording is over\r\n * @private\r\n * @type Function(Float32Array)\r\n */\r\n this._callback = function() {};\r\n\r\n // connections\r\n this._workletNode.connect(p5.soundOut._silentNode);\r\n this.setInput();\r\n\r\n // add this p5.SoundFile to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a specific device to the p5.SoundRecorder.\r\n * If no parameter is given, p5.SoundRecorer will record\r\n * all audible p5.sound from your sketch.\r\n *\r\n * @method setInput\r\n * @for p5.SoundRecorder\r\n * @param {Object} [unit] p5.sound object or a web audio unit\r\n * that outputs sound\r\n */\r\n p5.SoundRecorder.prototype.setInput = function(unit) {\r\n this.input.disconnect();\r\n this.input = null;\r\n this.input = ac.createGain();\r\n this.input.connect(this._workletNode);\r\n this.input.connect(this.output);\r\n if (unit) {\r\n unit.connect(this.input);\r\n } else {\r\n p5.soundOut.output.connect(this.input);\r\n }\r\n };\r\n\r\n /**\r\n * Start recording. To access the recording, provide\r\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\r\n * will send its recording to that p5.SoundFile for playback once\r\n * recording is complete. Optional parameters include duration\r\n * (in seconds) of the recording, and a callback function that\r\n * will be called once the complete recording has been\r\n * transfered to the p5.SoundFile.\r\n *\r\n * @method record\r\n * @for p5.SoundRecorder\r\n * @param {p5.SoundFile} soundFile p5.SoundFile\r\n * @param {Number} [duration] Time (in seconds)\r\n * @param {Function} [callback] The name of a function that will be\r\n * called once the recording completes\r\n */\r\n p5.SoundRecorder.prototype.record = function(sFile, duration, callback) {\r\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\r\n\r\n if (sFile && callback) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n callback();\r\n };\r\n }\r\n else if (sFile) {\r\n this._callback = function(buffer) {\r\n sFile.setBuffer(buffer);\r\n };\r\n }\r\n };\r\n\r\n /**\r\n * Stop the recording. Once the recording is stopped,\r\n * the results will be sent to the p5.SoundFile that\r\n * was given on .record(), and if a callback function\r\n * was provided on record, that function will be called.\r\n *\r\n * @method stop\r\n * @for p5.SoundRecorder\r\n */\r\n p5.SoundRecorder.prototype.stop = function() {\r\n this._workletNode.port.postMessage({ name: 'stop' });\r\n };\r\n\r\n p5.SoundRecorder.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n\r\n this._callback = function() {};\r\n if (this.input) {\r\n this.input.disconnect();\r\n }\r\n this.input = null;\r\n this._workletNode = null;\r\n };\r\n\r\n\r\n /**\r\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\r\n * to download the file to their device.\r\n * For uploading audio to a server, use\r\n * `p5.SoundFile.saveBlob`.\r\n *\r\n * @for p5\r\n * @method saveSound\r\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\r\n * @param {String} fileName name of the resulting .wav file.\r\n */\r\n // add to p5.prototype as this is used by the p5 `save()` method.\r\n p5.prototype.saveSound = function (soundFile, fileName) {\r\n const dataView = convertToWav(soundFile.buffer);\r\n p5.prototype.writeFile([dataView], fileName, 'wav');\r\n };\r\n});\r\n","'use strict';\r\n\r\ndefine(function () {\r\n /**\r\n *
PeakDetect works in conjunction with p5.FFT to\r\n * look for onsets in some or all of the frequency spectrum.\r\n *
\r\n *
\r\n * To use p5.PeakDetect, call update in the draw loop\r\n * and pass in a p5.FFT object.\r\n *
\r\n *
\r\n * You can listen for a specific part of the frequency spectrum by\r\n * setting the range between freq1 and freq2.\r\n *
\r\n *\r\n *
threshold is the threshold for detecting a peak,\r\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\r\n * as 1.0.
\r\n *\r\n *
\r\n * The update method is meant to be run in the draw loop, and\r\n * frames determines how many loops must pass before\r\n * another peak can be detected.\r\n * For example, if the frameRate() = 60, you could detect the beat of a\r\n * 120 beat-per-minute song with this equation:\r\n * framesPerPeak = 60 / (estimatedBPM / 60 );\r\n *
\r\n *\r\n *
\r\n * Based on example contribtued by @b2renger, and a simple beat detection\r\n * explanation by Felix Turner.\r\n *
\r\n *\r\n * @class p5.PeakDetect\r\n * @constructor\r\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\r\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\r\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\r\n * scaled logarithmically where 0.1 is 1/2 the loudness\r\n * of 1.0. Defaults to 0.35.\r\n * @param {Number} [framesPerPeak] Defaults to 20.\r\n * @example\r\n *
\r\n */\r\n p5.PeakDetect = function(freq1, freq2, threshold, _framesPerPeak) {\r\n // framesPerPeak determines how often to look for a beat.\r\n // If a beat is provided, try to look for a beat based on bpm\r\n this.framesPerPeak = _framesPerPeak || 20;\r\n this.framesSinceLastPeak = 0;\r\n this.decayRate = 0.95;\r\n\r\n this.threshold = threshold || 0.35;\r\n this.cutoff = 0;\r\n\r\n // how much to increase the cutoff\r\n // TO DO: document this / figure out how to make it accessible\r\n this.cutoffMult = 1.5;\r\n\r\n this.energy = 0;\r\n this.penergy = 0;\r\n\r\n // TO DO: document this property / figure out how to make it accessible\r\n this.currentValue = 0;\r\n\r\n /**\r\n * isDetected is set to true when a peak is detected.\r\n *\r\n * @attribute isDetected {Boolean}\r\n * @default false\r\n */\r\n this.isDetected = false;\r\n\r\n this.f1 = freq1 || 40;\r\n this.f2 = freq2 || 20000;\r\n\r\n // function to call when a peak is detected\r\n this._onPeak = function() {};\r\n };\r\n\r\n\r\n /**\r\n * The update method is run in the draw loop.\r\n *\r\n * Accepts an FFT object. You must call .analyze()\r\n * on the FFT object prior to updating the peakDetect\r\n * because it relies on a completed FFT analysis.\r\n *\r\n * @method update\r\n * @param {p5.FFT} fftObject A p5.FFT object\r\n */\r\n p5.PeakDetect.prototype.update = function(fftObject) {\r\n var nrg = this.energy = fftObject.getEnergy(this.f1,this.f2)/255;\r\n if (nrg > this.cutoff && nrg > this.threshold && nrg-this.penergy > 0) {\r\n\r\n // trigger callback\r\n this._onPeak();\r\n this.isDetected = true;\r\n\r\n // debounce\r\n this.cutoff = nrg * this.cutoffMult;\r\n this.framesSinceLastPeak = 0;\r\n } else {\r\n this.isDetected = false;\r\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\r\n this.framesSinceLastPeak++;\r\n } else {\r\n this.cutoff *= this.decayRate;\r\n this.cutoff = Math.max(this.cutoff, this.threshold);\r\n }\r\n }\r\n\r\n this.currentValue = nrg;\r\n this.penergy = nrg;\r\n };\r\n\r\n /**\r\n * onPeak accepts two arguments: a function to call when\r\n * a peak is detected. The value of the peak,\r\n * between 0.0 and 1.0, is passed to the callback.\r\n *\r\n * @method onPeak\r\n * @param {Function} callback Name of a function that will\r\n * be called when a peak is\r\n * detected.\r\n * @param {Object} [val] Optional value to pass\r\n * into the function when\r\n * a peak is detected.\r\n * @example\r\n *
\r\n * var cnv, soundFile, fft, peakDetect;\r\n * var ellipseWidth = 0;\r\n *\r\n * function preload() {\r\n * soundFile = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * cnv = createCanvas(100,100);\r\n * textAlign(CENTER);\r\n *\r\n * fft = new p5.FFT();\r\n * peakDetect = new p5.PeakDetect();\r\n *\r\n * setupSound();\r\n *\r\n * // when a beat is detected, call triggerBeat()\r\n * peakDetect.onPeak(triggerBeat);\r\n * }\r\n *\r\n * function draw() {\r\n * background(0);\r\n * fill(255);\r\n * text('click to play', width/2, height/2);\r\n *\r\n * fft.analyze();\r\n * peakDetect.update(fft);\r\n *\r\n * ellipseWidth *= 0.95;\r\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\r\n * }\r\n *\r\n * // this function is called by peakDetect.onPeak\r\n * function triggerBeat() {\r\n * ellipseWidth = 50;\r\n * }\r\n *\r\n * // mouseclick starts/stops sound\r\n * function setupSound() {\r\n * cnv.mouseClicked( function() {\r\n * if (soundFile.isPlaying() ) {\r\n * soundFile.stop();\r\n * } else {\r\n * soundFile.play();\r\n * }\r\n * });\r\n * }\r\n *
\r\n */\r\n p5.PeakDetect.prototype.onPeak = function(callback, val) {\r\n var self = this;\r\n\r\n self._onPeak = function() {\r\n callback(self.energy, val);\r\n };\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n var p5sound = require('master');\r\n\r\n /**\r\n * A gain node is usefull to set the relative volume of sound.\r\n * It's typically used to build mixers.\r\n *\r\n * @class p5.Gain\r\n * @constructor\r\n * @example\r\n *
\r\n *\r\n * // load two soundfile and crossfade beetween them\r\n * var sound1,sound2;\r\n * var gain1, gain2, gain3;\r\n *\r\n * function preload(){\r\n * soundFormats('ogg', 'mp3');\r\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\r\n * sound2 = loadSound('assets/beat.mp3');\r\n * }\r\n *\r\n * function setup() {\r\n * createCanvas(400,200);\r\n *\r\n * // create a 'master' gain to which we will connect both soundfiles\r\n * gain3 = new p5.Gain();\r\n * gain3.connect();\r\n *\r\n * // setup first sound for playing\r\n * sound1.rate(1);\r\n * sound1.loop();\r\n * sound1.disconnect(); // diconnect from p5 output\r\n *\r\n * gain1 = new p5.Gain(); // setup a gain node\r\n * gain1.setInput(sound1); // connect the first sound to its input\r\n * gain1.connect(gain3); // connect its output to the 'master'\r\n *\r\n * sound2.rate(1);\r\n * sound2.disconnect();\r\n * sound2.loop();\r\n *\r\n * gain2 = new p5.Gain();\r\n * gain2.setInput(sound2);\r\n * gain2.connect(gain3);\r\n *\r\n * }\r\n *\r\n * function draw(){\r\n * background(180);\r\n *\r\n * // calculate the horizontal distance beetween the mouse and the right of the screen\r\n * var d = dist(mouseX,0,width,0);\r\n *\r\n * // map the horizontal position of the mouse to values useable for volume control of sound1\r\n * var vol1 = map(mouseX,0,width,0,1);\r\n * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa\r\n *\r\n * gain1.amp(vol1,0.5,0);\r\n * gain2.amp(vol2,0.5,0);\r\n *\r\n * // map the vertical position of the mouse to values useable for 'master volume control'\r\n * var vol3 = map(mouseY,0,height,0,1);\r\n * gain3.amp(vol3,0.5,0);\r\n * }\r\n *
\r\n *\r\n */\r\n\r\n p5.Gain = function() {\r\n this.ac = p5sound.audiocontext;\r\n\r\n this.input = this.ac.createGain();\r\n this.output = this.ac.createGain();\r\n\r\n // otherwise, Safari distorts\r\n this.input.gain.value = 0.5;\r\n this.input.connect(this.output);\r\n\r\n // add to the soundArray\r\n p5sound.soundArray.push(this);\r\n };\r\n\r\n /**\r\n * Connect a source to the gain node.\r\n *\r\n * @method setInput\r\n * @for p5.Gain\r\n * @param {Object} src p5.sound / Web Audio object with a sound\r\n * output.\r\n */\r\n\r\n\r\n p5.Gain.prototype.setInput = function(src) {\r\n src.connect(this.input);\r\n };\r\n\r\n /**\r\n * Send output to a p5.sound or web audio object\r\n *\r\n * @method connect\r\n * @for p5.Gain\r\n * @param {Object} unit\r\n */\r\n p5.Gain.prototype.connect = function(unit) {\r\n var u = unit || p5.soundOut.input;\r\n this.output.connect(u.input ? u.input : u);\r\n };\r\n\r\n /**\r\n * Disconnect all output.\r\n *\r\n * @method disconnect\r\n * @for p5.Gain\r\n */\r\n p5.Gain.prototype.disconnect = function() {\r\n if (this.output) {\r\n this.output.disconnect();\r\n }\r\n };\r\n\r\n /**\r\n * Set the output level of the gain node.\r\n *\r\n * @method amp\r\n * @for p5.Gain\r\n * @param {Number} volume amplitude between 0 and 1.0\r\n * @param {Number} [rampTime] create a fade that lasts rampTime\r\n * @param {Number} [timeFromNow] schedule this event to happen\r\n * seconds from now\r\n */\r\n p5.Gain.prototype.amp = function(vol, rampTime, tFromNow) {\r\n var rampTime = rampTime || 0;\r\n var tFromNow = tFromNow || 0;\r\n var now = p5sound.audiocontext.currentTime;\r\n var currentVol = this.output.gain.value;\r\n this.output.gain.cancelScheduledValues(now);\r\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\r\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\r\n };\r\n\r\n p5.Gain.prototype.dispose = function() {\r\n // remove reference from soundArray\r\n var index = p5sound.soundArray.indexOf(this);\r\n p5sound.soundArray.splice(index, 1);\r\n if (this.output) {\r\n this.output.disconnect();\r\n delete this.output;\r\n }\r\n if (this.input) {\r\n this.input.disconnect();\r\n delete this.input;\r\n }\r\n };\r\n\r\n});\r\n","'use strict';\r\n\r\ndefine(function (require) {\r\n\r\n var Effect = require('effect');\r\n\r\n /*\r\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n */\r\n function makeDistortionCurve(amount) {\r\n var k = typeof amount === 'number' ? amount : 50;\r\n var numSamples = 44100;\r\n var curve = new Float32Array(numSamples);\r\n var deg = Math.PI / 180;\r\n var i = 0;\r\n var x;\r\n for ( ; i < numSamples; ++i ) {\r\n x = i * 2 / numSamples - 1;\r\n curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );\r\n }\r\n return curve;\r\n }\r\n\r\n /**\r\n * A Distortion effect created with a Waveshaper Node,\r\n * with an approach adapted from\r\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\r\n *\r\n * This class extends p5.Effect.\r\n * Methods amp(), chain(),\r\n * drywet(), connect(), and\r\n * disconnect() are available.\r\n *\r\n * @class p5.Distortion\r\n * @extends p5.Effect\r\n * @constructor\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n *\r\n */\r\n p5.Distortion = function(amount, oversample) {\r\n Effect.call(this);\r\n\r\n if (typeof amount === 'undefined') {\r\n amount = 0.25;\r\n } if (typeof amount !== 'number') {\r\n throw new Error('amount must be a number');\r\n } if (typeof oversample === 'undefined') {\r\n oversample = '2x';\r\n } if (typeof oversample !== 'string') {\r\n throw new Error('oversample must be a String');\r\n }\r\n\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n\r\n /**\r\n * The p5.Distortion is built with a\r\n * \r\n * Web Audio WaveShaper Node.\r\n *\r\n * @property {AudioNode} WaveShaperNode\r\n */\r\n this.waveShaperNode = this.ac.createWaveShaper();\r\n\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n this.waveShaperNode.oversample = oversample;\r\n\r\n this.input.connect(this.waveShaperNode);\r\n\r\n this.waveShaperNode.connect(this.wet);\r\n };\r\n\r\n p5.Distortion.prototype = Object.create(Effect.prototype);\r\n\r\n\r\n /**\r\n * Process a sound source, optionally specify amount and oversample values.\r\n *\r\n * @method process\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.process = function(src, amount, oversample) {\r\n src.connect(this.input);\r\n this.set(amount, oversample);\r\n };\r\n\r\n /**\r\n * Set the amount and oversample of the waveshaper distortion.\r\n *\r\n * @method set\r\n * @for p5.Distortion\r\n * @param {Number} [amount=0.25] Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.set = function(amount, oversample) {\r\n if (amount) {\r\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\r\n this.amount = curveAmount;\r\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\r\n }\r\n if (oversample) {\r\n this.waveShaperNode.oversample = oversample;\r\n }\r\n };\r\n\r\n /**\r\n * Return the distortion amount, typically between 0-1.\r\n *\r\n * @method getAmount\r\n * @for p5.Distortion\r\n * @return {Number} Unbounded distortion amount.\r\n * Normal values range from 0-1.\r\n */\r\n p5.Distortion.prototype.getAmount = function() {\r\n return this.amount;\r\n };\r\n\r\n /**\r\n * Return the oversampling.\r\n *\r\n * @method getOversample\r\n * @for p5.Distortion\r\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\r\n */\r\n p5.Distortion.prototype.getOversample = function() {\r\n return this.waveShaperNode.oversample;\r\n };\r\n\r\n\r\n p5.Distortion.prototype.dispose = function() {\r\n Effect.prototype.dispose.apply(this);\r\n if (this.waveShaperNode) {\r\n this.waveShaperNode.disconnect();\r\n this.waveShaperNode = null;\r\n }\r\n };\r\n});\r\n","export default \"function _typeof(obj) { if (typeof Symbol === \\\"function\\\" && typeof Symbol.iterator === \\\"symbol\\\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \\\"function\\\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \\\"symbol\\\" : typeof obj; }; } return _typeof(obj); }\\n\\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\\"Cannot call a class as a function\\\"); } }\\n\\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \\\"object\\\" || typeof call === \\\"function\\\")) { return call; } return _assertThisInitialized(self); }\\n\\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\\\"this hasn't been initialised - super() hasn't been called\\\"); } return self; }\\n\\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\\\"value\\\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\\n\\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\\n\\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \\\"function\\\" && superClass !== null) { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\\n\\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \\\"function\\\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \\\"function\\\") { throw new TypeError(\\\"Super expression must either be null or a function\\\"); } if (typeof _cache !== \\\"undefined\\\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\\n\\nfunction isNativeReflectConstruct() { if (typeof Reflect === \\\"undefined\\\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \\\"function\\\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\\n\\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\\n\\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\\\"[native code]\\\") !== -1; }\\n\\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\\n\\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\\n\\n// import processor name via preval.require so that it's available as a value at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n}; // TO DO make this stereo / dependent on # of audio channels\\n\\nvar AmplitudeProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\\n\\n _createClass(AmplitudeProcessor, null, [{\\n key: \\\"parameterDescriptors\\\",\\n get: function get() {\\n return [{\\n name: 'smoothing',\\n defaultValue: 0,\\n minValue: 0,\\n maxValue: 1,\\n automationRate: 'k-rate'\\n }];\\n }\\n }]);\\n\\n function AmplitudeProcessor(options) {\\n var _this;\\n\\n _classCallCheck(this, AmplitudeProcessor);\\n\\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\\n var processorOptions = options.processorOptions || {};\\n _this.normalize = processorOptions.normalize || false;\\n _this.stereoVol = [0, 0];\\n _this.stereoVolNorm = [0, 0];\\n _this.volMax = 0.001;\\n\\n _this.port.onmessage = function (event) {\\n var data = event.data;\\n\\n if (data.name === 'toggleNormalize') {\\n _this.normalize = data.normalize;\\n }\\n };\\n\\n return _this;\\n }\\n\\n _createClass(AmplitudeProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs, outputs, parameters) {\\n var input = inputs[0];\\n var output = outputs[0];\\n var smoothing = parameters.smoothing;\\n\\n for (var channel = 0; channel < input.length; ++channel) {\\n var inputBuffer = input[channel];\\n var bufLength = inputBuffer.length;\\n var sum = 0;\\n\\n for (var i = 0; i < bufLength; i++) {\\n var x = inputBuffer[i];\\n\\n if (this.normalize) {\\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\\n } else {\\n sum += x * x;\\n }\\n } // ... then take the square root of the sum.\\n\\n\\n var rms = Math.sqrt(sum / bufLength);\\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\\n } // calculate stero normalized volume and add volume from all channels together\\n\\n\\n var volSum = 0;\\n\\n for (var index = 0; index < this.stereoVol.length; index++) {\\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\\n volSum += this.stereoVol[index];\\n } // volume is average of channels\\n\\n\\n var volume = volSum / this.stereoVol.length; // normalized value\\n\\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\\n this.port.postMessage({\\n name: 'amplitude',\\n volume: volume,\\n volNorm: volNorm,\\n stereoVol: this.stereoVol,\\n stereoVolNorm: this.stereoVolNorm\\n }); // pass input through to output\\n\\n for (var _channel = 0; _channel < output.length; ++_channel) {\\n output[_channel].set(input[_channel]);\\n }\\n\\n return true;\\n }\\n }]);\\n\\n return AmplitudeProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);\""],"sourceRoot":""}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index b00f4313..11649022 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3387,13 +3387,15 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -3410,19 +3412,22 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -3553,7 +3558,8 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -3567,6 +3573,7 @@
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3583,6 +3590,7 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -3591,13 +3599,15 @@
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -3618,6 +3628,7 @@
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -3706,7 +3717,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -3720,6 +3732,7 @@
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3857,6 +3870,7 @@
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
diff --git a/src/amplitude.js b/src/amplitude.js
index 5a9ef5aa..1a0708ed 100644
--- a/src/amplitude.js
+++ b/src/amplitude.js
@@ -2,6 +2,7 @@
define(function (require) {
var p5sound = require('master');
+ var processorNames = require('./audioWorklet/processorNames');
/**
* Amplitude measures volume between 0.0 and 1.0.
@@ -50,38 +51,42 @@ define(function (require) {
// set audio context
this.audiocontext = p5sound.audiocontext;
- this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1);
+ this._workletNode = new AudioWorkletNode(this.audiocontext, processorNames.amplitudeProcessor, {
+ outputChannelCount: [1],
+ parameterData: { smoothing: smoothing || 0 },
+ processorOptions: { normalize: false }
+ });
+
+ this._workletNode.port.onmessage = function(event) {
+ if (event.data.name === 'amplitude') {
+ this.volume = event.data.volume;
+ this.volNorm = event.data.volNorm;
+ this.stereoVol = event.data.stereoVol;
+ this.stereoVolNorm = event.data.stereoVolNorm;
+ }
+ }.bind(this);
// for connections
- this.input = this.processor;
+ this.input = this._workletNode;
this.output = this.audiocontext.createGain();
- // smoothing defaults to 0
- this.smoothing = smoothing || 0;
-
// the variables to return
this.volume = 0;
- this.average = 0;
-
+ this.volNorm = 0;
this.stereoVol = [0, 0];
- this.stereoAvg = [0, 0];
this.stereoVolNorm = [0, 0];
- this.volMax = 0.001;
this.normalize = false;
- this.processor.onaudioprocess = this._audioProcess.bind(this);
-
-
- this.processor.connect(this.output);
+ this._workletNode.connect(this.output);
this.output.gain.value = 0;
// this may only be necessary because of a Chrome bug
this.output.connect(this.audiocontext.destination);
// connect to p5sound master output by default, unless set by input()
- p5sound.meter.connect(this.processor);
+ p5sound.meter.connect(this._workletNode);
// add this p5.SoundFile to the soundArray
p5sound.soundArray.push(this);
@@ -128,29 +133,29 @@ define(function (require) {
p5sound.meter.disconnect();
if (smoothing) {
- this.smoothing = smoothing;
+ this._workletNode.parameters.get('smoothing').value = smoothing;
}
// connect to the master out of p5s instance if no snd is provided
if (source == null) {
console.log('Amplitude input source is not ready! Connecting to master output instead');
- p5sound.meter.connect(this.processor);
+ p5sound.meter.connect(this._workletNode);
}
// if it is a p5.Signal
else if (source instanceof p5.Signal) {
- source.output.connect(this.processor);
+ source.output.connect(this._workletNode);
}
// connect to the sound if it is available
else if (source) {
- source.connect(this.processor);
- this.processor.disconnect();
- this.processor.connect(this.output);
+ source.connect(this._workletNode);
+ this._workletNode.disconnect();
+ this._workletNode.connect(this.output);
}
// otherwise, connect to the master out of p5s instance (default)
else {
- p5sound.meter.connect(this.processor);
+ p5sound.meter.connect(this._workletNode);
}
};
@@ -172,56 +177,6 @@ define(function (require) {
}
};
- // TO DO make this stereo / dependent on # of audio channels
- p5.Amplitude.prototype._audioProcess = function(event) {
-
- for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) {
- var inputBuffer = event.inputBuffer.getChannelData(channel);
- var bufLength = inputBuffer.length;
-
- var total = 0;
- var sum = 0;
- var x;
-
- for (var i = 0; i < bufLength; i++) {
- x = inputBuffer[i];
- if (this.normalize) {
- total += Math.max(Math.min(x/this.volMax, 1), -1);
- sum += Math.max(Math.min(x/this.volMax, 1), -1) * Math.max(Math.min(x/this.volMax, 1), -1);
- }
- else {
- total += x;
- sum += x * x;
- }
- }
- var average = total/ bufLength;
-
- // ... then take the square root of the sum.
- var rms = Math.sqrt(sum / bufLength);
-
- this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing);
- this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing);
- this.volMax = Math.max(this.stereoVol[channel], this.volMax);
- }
-
- // add volume from all channels together
- var self = this;
- var volSum = this.stereoVol.reduce(function(previousValue, currentValue, index) {
- self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1]/self.volMax, 1), 0);
- self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index]/self.volMax, 1), 0);
-
- return previousValue + currentValue;
- });
-
- // volume is average of channels
- this.volume = volSum / this.stereoVol.length;
-
- // normalized value
- this.volNorm = Math.max(Math.min(this.volume/this.volMax, 1), 0);
-
-
- };
-
/**
* Returns a single Amplitude reading at the moment it is called.
* For continuous readings, run in the draw loop.
@@ -288,6 +243,7 @@ define(function (require) {
else {
this.normalize = !this.normalize;
}
+ this._workletNode.port.postMessage({ name: 'toggleNormalize', normalize: this.normalize });
};
/**
@@ -300,7 +256,7 @@ define(function (require) {
*/
p5.Amplitude.prototype.smooth = function(s) {
if (s >= 0 && s < 1) {
- this.smoothing = s;
+ this._workletNode.parameters.get('smoothing').value = s;
} else {
console.log('Error: smoothing must be between 0 and 1');
}
@@ -320,7 +276,8 @@ define(function (require) {
delete this.output;
}
- delete this.processor;
+ this._workletNode.disconnect();
+ delete this._workletNode;
};
});
diff --git a/src/audioWorklet/amplitudeProcessor.js b/src/audioWorklet/amplitudeProcessor.js
new file mode 100644
index 00000000..5aa1dfd3
--- /dev/null
+++ b/src/audioWorklet/amplitudeProcessor.js
@@ -0,0 +1,93 @@
+// import processor name via preval.require so that it's available as a value at compile time
+const processorNames = preval.require('./processorNames');
+
+class AmplitudeProcessor extends AudioWorkletProcessor {
+ static get parameterDescriptors() {
+ return [
+ {
+ name: 'smoothing',
+ defaultValue: 0,
+ minValue: 0,
+ maxValue: 1,
+ automationRate: 'k-rate'
+ }
+ ];
+ }
+
+ constructor(options) {
+ super();
+
+ const processorOptions = options.processorOptions || {};
+ this.normalize = processorOptions.normalize || false;
+
+ this.stereoVol = [0, 0];
+ this.stereoVolNorm = [0, 0];
+
+ this.volMax = 0.001;
+
+ this.port.onmessage = (event) => {
+ const data = event.data;
+ if (data.name === 'toggleNormalize') {
+ this.normalize = data.normalize;
+ }
+ };
+ }
+
+ // TO DO make this stereo / dependent on # of audio channels
+ process(inputs, outputs, parameters) {
+ const input = inputs[0];
+ const output = outputs[0];
+ const smoothing = parameters.smoothing;
+
+ for (let channel = 0; channel < input.length; ++channel) {
+ const inputBuffer = input[channel];
+ const bufLength = inputBuffer.length;
+
+ let sum = 0;
+ for (var i = 0; i < bufLength; i++) {
+ const x = inputBuffer[i];
+ if (this.normalize) {
+ sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);
+ } else {
+ sum += x * x;
+ }
+ }
+
+ // ... then take the square root of the sum.
+ const rms = Math.sqrt(sum / bufLength);
+
+ this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);
+ this.volMax = Math.max(this.stereoVol[channel], this.volMax);
+ }
+
+ // calculate stero normalized volume and add volume from all channels together
+ let volSum = 0;
+ for (let index = 0; index < this.stereoVol.length; index++) {
+ this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);
+ volSum += this.stereoVol[index];
+ }
+
+ // volume is average of channels
+ const volume = volSum / this.stereoVol.length;
+
+ // normalized value
+ const volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);
+
+ this.port.postMessage({
+ name: 'amplitude',
+ volume: volume,
+ volNorm: volNorm,
+ stereoVol: this.stereoVol,
+ stereoVolNorm: this.stereoVolNorm
+ });
+
+ // pass input through to output
+ for (let channel = 0; channel < output.length; ++channel) {
+ output[channel].set(input[channel]);
+ }
+
+ return true;
+ }
+}
+
+registerProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);
diff --git a/src/audioWorklet/index.js b/src/audioWorklet/index.js
index d14d27c3..e503fbac 100644
--- a/src/audioWorklet/index.js
+++ b/src/audioWorklet/index.js
@@ -1,6 +1,8 @@
const p5sound = require('master');
const moduleSources = [
- require('raw-loader!./recorderProcessor').default
+ require('raw-loader!./recorderProcessor').default,
+ require('raw-loader!./soundFileProcessor').default,
+ require('raw-loader!./amplitudeProcessor').default
];
const ac = p5sound.audiocontext;
diff --git a/src/audioWorklet/processorNames.js b/src/audioWorklet/processorNames.js
index a82bd086..c8402b89 100644
--- a/src/audioWorklet/processorNames.js
+++ b/src/audioWorklet/processorNames.js
@@ -1,3 +1,5 @@
module.exports = {
- recorderProcessor: 'recorder-processor'
+ recorderProcessor: 'recorder-processor',
+ soundFileProcessor: 'sound-file-processor',
+ amplitudeProcessor: 'amplitude-processor'
};
diff --git a/src/audioWorklet/soundFileProcessor.js b/src/audioWorklet/soundFileProcessor.js
new file mode 100644
index 00000000..b9abaffd
--- /dev/null
+++ b/src/audioWorklet/soundFileProcessor.js
@@ -0,0 +1,16 @@
+// import processor name via preval.require so that it's available as a value at compile time
+const processorNames = preval.require('./processorNames');
+
+class SoundFileProcessor extends AudioWorkletProcessor {
+ process(inputs) {
+ const input = inputs[0];
+ const inputChannel = input[0];
+ const position = inputChannel[inputChannel.length - 1] || 0;
+
+ this.port.postMessage({ name: 'position', position: position });
+
+ return true;
+ }
+}
+
+registerProcessor(processorNames.soundFileProcessor, SoundFileProcessor);
diff --git a/src/soundfile.js b/src/soundfile.js
index 7f6dd69b..8924b179 100644
--- a/src/soundfile.js
+++ b/src/soundfile.js
@@ -7,6 +7,7 @@ define(function (require) {
var ac = p5sound.audiocontext;
var midiToFreq = require('helpers').midiToFreq;
var convertToWav = require('helpers').convertToWav;
+ var processorNames = require('./audioWorklet/processorNames');
/**
*
SoundFile object with a path to a file.
@@ -94,7 +95,7 @@ define(function (require) {
// position of the most recently played sample
this._lastPos = 0;
this._counterNode = null;
- this._scopeNode = null;
+ this._workletNode = null;
// array of sources so that they can all be stopped!
this.bufferSourceNodes = [];
@@ -1238,23 +1239,28 @@ define(function (require) {
var now = ac.currentTime;
var cNode = ac.createBufferSource();
- // dispose of scope node if it already exists
- if (self._scopeNode) {
- self._scopeNode.disconnect();
- self._scopeNode.removeEventListener('audioprocess', self._onAudioProcess);
- delete self._scopeNode;
+ // dispose of worklet node if it already exists
+ if (self._workletNode) {
+ self._workletNode.disconnect();
+ delete self._workletNode;
}
- self._scopeNode = ac.createScriptProcessor( 256, 1, 1 );
+ self._workletNode = new AudioWorkletNode(ac, processorNames.soundFileProcessor);
+ self._workletNode.port.onmessage = function(event) {
+ if (event.data.name === 'position') {
+ this._lastPos = event.data.position;
+
+ // do any callbacks that have been scheduled
+ this._onTimeUpdate(self._lastPos);
+ }
+ }.bind(self);
// create counter buffer of the same length as self.buffer
cNode.buffer = _createCounterBuffer( self.buffer );
cNode.playbackRate.setValueAtTime(self.playbackRate, now);
- cNode.connect( self._scopeNode );
- self._scopeNode.connect( p5.soundOut._silentNode );
-
- self._scopeNode.addEventListener('audioprocess', self._onAudioProcess);
+ cNode.connect(self._workletNode);
+ self._workletNode.connect(p5.soundOut._silentNode);
return cNode;
};
diff --git a/test/index.html b/test/index.html
index e62b3024..52a3b146 100644
--- a/test/index.html
+++ b/test/index.html
@@ -2,17 +2,20 @@
TESTS
-
-
-
+
+
+
-
-
-
+