diff --git a/lib/p5.sound.js b/lib/p5.sound.js index f2a92764..5ebec323 100644 --- a/lib/p5.sound.js +++ b/lib/p5.sound.js @@ -1,4 +1,4 @@ -/** [p5.sound] Version: 0.3.12 - 2020-06-26 */ +/** [p5.sound] Version: 1.0.0 - 2021-02-24 */ /** *

p5.sound extends p5 with Web Audio functionality including audio input, @@ -117,54 +117,35 @@ }; __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; __webpack_require__.p = ""; - return __webpack_require__(__webpack_require__.s = 41); + return __webpack_require__(__webpack_require__.s = 40); }) ([ (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(7),__webpack_require__(9),__webpack_require__(18),__webpack_require__(10)], __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__)); - - }), - (function(module, exports, __webpack_require__) { - var __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_RESULT__ = (function(){"use strict";function a(t,e){this.isUndef(t)||1===t?this.input=this.context.createGain():1 */ -p5.prototype.getAudioContext = function () { +function getAudioContext() { return audiocontext; -}; +} /** *

It is not only a good practice to give users control over starting * audio. This policy is enforced by many web browsers, including iOS and @@ -268,8 +249,7 @@ p5.prototype.getAudioContext = function () { * */ - -p5.prototype.userStartAudio = function (elements, callback) { +function userStartAudio(elements, callback) { var elt = elements; if (elements instanceof p5.Element) { @@ -281,99 +261,119 @@ p5.prototype.userStartAudio = function (elements, callback) { } return startaudiocontext__WEBPACK_IMPORTED_MODULE_0___default()(audiocontext, elt, callback); -}; - +} __webpack_exports__["a"] = (audiocontext); }.call(this, __webpack_require__(26))) }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(15)], __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__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(0),__webpack_require__(19)], __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__), +var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(4),__webpack_require__(1),__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.Scale=function(t,e){this._outputMin=this.defaultArg(t,0),this._outputMax=this.defaultArg(e,1),this._scale=this.input=new i.Multiply(1),this._add=this.output=new i.Add(0),this._scale.connect(this._add),this._setRange()},i.extend(i.Scale,i.SignalBase),Object.defineProperty(i.Scale.prototype,"min",{get:function(){return this._outputMin},set:function(t){this._outputMin=t,this._setRange()}}),Object.defineProperty(i.Scale.prototype,"max",{get:function(){return this._outputMax},set:function(t){this._outputMax=t,this._setRange()}}),i.Scale.prototype._setRange=function(){this._add.value=this._outputMin,this._scale.value=this._outputMax-this._outputMin},i.Scale.prototype.dispose=function(){return i.prototype.dispose.call(this),this._add.dispose(),this._add=null,this._scale.dispose(),this._scale=null,this},i.Scale}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(16),__webpack_require__(30),__webpack_require__(31),__webpack_require__(12)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(t){return t.Type={Default:"number",Time:"time",Frequency:"frequency",TransportTime:"transportTime",Ticks:"ticks",NormalRange:"normalRange",AudioRange:"audioRange",Decibels:"db",Interval:"interval",BPM:"bpm",Positive:"positive",Cents:"cents",Degrees:"degrees",MIDI:"midi",BarsBeatsSixteenths:"barsBeatsSixteenths",Samples:"samples",Hertz:"hertz",Note:"note",Milliseconds:"milliseconds",Seconds:"seconds",Notation:"notation"},t.prototype.toSeconds=function(e){return this.isNumber(e)?e:this.isUndef(e)?this.now():this.isString(e)?new t.Time(e).toSeconds():e instanceof t.TimeBase?e.toSeconds():void 0},t.prototype.toFrequency=function(e){return this.isNumber(e)?e:this.isString(e)||this.isUndef(e)?new t.Frequency(e).valueOf():e instanceof t.TimeBase?e.toFrequency():void 0},t.prototype.toTicks=function(e){return this.isNumber(e)||this.isString(e)?new t.TransportTime(e).toTicks():this.isUndef(e)?t.Transport.ticks:e instanceof t.TimeBase?e.toTicks():void 0},t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), +var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(16),__webpack_require__(30),__webpack_require__(31),__webpack_require__(12)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(t){return t.Type={Default:"number",Time:"time",Frequency:"frequency",TransportTime:"transportTime",Ticks:"ticks",NormalRange:"normalRange",AudioRange:"audioRange",Decibels:"db",Interval:"interval",BPM:"bpm",Positive:"positive",Cents:"cents",Degrees:"degrees",MIDI:"midi",BarsBeatsSixteenths:"barsBeatsSixteenths",Samples:"samples",Hertz:"hertz",Note:"note",Milliseconds:"milliseconds",Seconds:"seconds",Notation:"notation"},t.prototype.toSeconds=function(e){return this.isNumber(e)?e:this.isUndef(e)?this.now():this.isString(e)?new t.Time(e).toSeconds():e instanceof t.TimeBase?e.toSeconds():void 0},t.prototype.toFrequency=function(e){return this.isNumber(e)?e:this.isString(e)||this.isUndef(e)?new t.Frequency(e).valueOf():e instanceof t.TimeBase?e.toFrequency():void 0},t.prototype.toTicks=function(e){return this.isNumber(e)||this.isString(e)?new t.TransportTime(e).toTicks():this.isUndef(e)?t.Transport.ticks:e instanceof t.TimeBase?e.toTicks():void 0},t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(18),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return window.GainNode&&!AudioContext.prototype.createGain&&(AudioContext.prototype.createGain=AudioContext.prototype.createGainNode),i.Gain=function(){var t=this.optionsObject(arguments,["gain","units"],i.Gain.defaults);this.input=this.output=this._gainNode=this.context.createGain(),this.gain=new i.Param({param:this._gainNode.gain,units:t.units,value:t.gain,convert:t.convert}),this._readOnly("gain")},i.extend(i.Gain),i.Gain.defaults={gain:1,convert:!0},i.Gain.prototype.dispose=function(){i.Param.prototype.dispose.call(this),this._gainNode.disconnect(),this._gainNode=null,this._writable("gain"),this.gain.dispose(),this.gain=null},i.prototype.createInsOuts=function(t,n){1===t?this.input=new i.Gain:1this._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__(7),__webpack_require__(39),__webpack_require__(14),__webpack_require__(12)], __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__)); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(14)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){function t(e,t,n){if(e.input)Array.isArray(e.input)?(o.prototype.isUndef(n)&&(n=0),this.connect(e.input[n])):this.connect(e.input,t,n);else try{e instanceof AudioNode?i.call(this,e,t,n):i.call(this,e,t)}catch(t){throw new Error("error connecting to node: "+e+"\n"+t)}}var i,r;return!window.hasOwnProperty("AudioContext")&&window.hasOwnProperty("webkitAudioContext")&&(window.AudioContext=window.webkitAudioContext),o.Context=function(t){for(var e in o.Emitter.call(this),t=t||new window.AudioContext,this._context=t,this._context)this._defineProperty(this._context,e);this._latencyHint="interactive",this._lookAhead=.1,this._updateInterval=this._lookAhead/3,this._computedUpdateInterval=0,this._worker=this._createWorker(),this._constants={}},o.extend(o.Context,o.Emitter),o.Emitter.mixin(o.Context),o.Context.prototype._defineProperty=function(e,n){this.isUndef(this[n])&&Object.defineProperty(this,n,{get:function(){return"function"==typeof e[n]?e[n].bind(e):e[n]},set:function(t){e[n]=t}})},o.Context.prototype.now=function(){return this._context.currentTime},o.Context.prototype._createWorker=function(){window.URL=window.URL||window.webkitURL;var t=new Blob(["var timeoutTime = "+(1e3*this._updateInterval).toFixed(1)+";self.onmessage = function(msg){\ttimeoutTime = parseInt(msg.data);};function tick(){\tsetTimeout(tick, timeoutTime);\tself.postMessage('tick');}tick();"]),e=URL.createObjectURL(t),n=new Worker(e);return n.addEventListener("message",function(){this.emit("tick")}.bind(this)),n.addEventListener("message",function(){var t=this.now();if(this.isNumber(this._lastUpdate)){var e=t-this._lastUpdate;this._computedUpdateInterval=Math.max(e,.97*this._computedUpdateInterval)}this._lastUpdate=t}.bind(this)),n},o.Context.prototype.getConstant=function(t){if(this._constants[t])return this._constants[t];for(var e=this._context.createBuffer(1,128,this._context.sampleRate),n=e.getChannelData(0),o=0;othis.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__), +var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.Timeline=function(){var e=this.optionsObject(arguments,["memory"],i.Timeline.defaults);this._timeline=[],this._toRemove=[],this._iterating=!1,this.memory=e.memory},i.extend(i.Timeline),i.Timeline.defaults={memory:1/0},Object.defineProperty(i.Timeline.prototype,"length",{get:function(){return this._timeline.length}}),i.Timeline.prototype.add=function(e){if(this.isUndef(e.time))throw new Error("Tone.Timeline: events must have a time attribute");if(this._timeline.length){var i=this._search(e.time);this._timeline.splice(i+1,0,e)}else this._timeline.push(e);if(this.length>this.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__)); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(2),__webpack_require__(0)], __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__), +var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(1),__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__)); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(0),__webpack_require__(2),__webpack_require__(7)], __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__), +var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(2),__webpack_require__(1),__webpack_require__(6)], __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__)); }), @@ -387,7 +387,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(0),__webpack_require__(32),__webpack_require__(38),__webpack_require__(10)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.CrossFade=function(e){this.createInsOuts(2,1),this.a=this.input[0]=new i.Gain,this.b=this.input[1]=new i.Gain,this.fade=new i.Signal(this.defaultArg(e,.5),i.Type.NormalRange),this._equalPowerA=new i.EqualPowerGain,this._equalPowerB=new i.EqualPowerGain,this._invert=new i.Expr("1 - $0"),this.a.connect(this.output),this.b.connect(this.output),this.fade.chain(this._equalPowerB,this.b.gain),this.fade.chain(this._invert,this._equalPowerA,this.a.gain),this._readOnly("fade")},i.extend(i.CrossFade),i.CrossFade.prototype.dispose=function(){return i.prototype.dispose.call(this),this._writable("fade"),this._equalPowerA.dispose(),this._equalPowerA=null,this._equalPowerB.dispose(),this._equalPowerB=null,this.fade.dispose(),this.fade=null,this._invert.dispose(),this._invert=null,this.a.dispose(),this.a=null,this.b.dispose(),this.b=null,this},i.CrossFade}).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__(32),__webpack_require__(38),__webpack_require__(10)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.CrossFade=function(e){this.createInsOuts(2,1),this.a=this.input[0]=new i.Gain,this.b=this.input[1]=new i.Gain,this.fade=new i.Signal(this.defaultArg(e,.5),i.Type.NormalRange),this._equalPowerA=new i.EqualPowerGain,this._equalPowerB=new i.EqualPowerGain,this._invert=new i.Expr("1 - $0"),this.a.connect(this.output),this.b.connect(this.output),this.fade.chain(this._equalPowerB,this.b.gain),this.fade.chain(this._invert,this._equalPowerA,this.a.gain),this._readOnly("fade")},i.extend(i.CrossFade),i.CrossFade.prototype.dispose=function(){return i.prototype.dispose.call(this),this._writable("fade"),this._equalPowerA.dispose(),this._equalPowerA=null,this._equalPowerB.dispose(),this._equalPowerB=null,this.fade.dispose(),this.fade=null,this._invert.dispose(),this._invert=null,this.a.dispose(),this.a=null,this.b.dispose(),this.b=null,this},i.CrossFade}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); }), @@ -599,310 +599,82 @@ var g;g=function(){return this}();try{g=g||new Function("return this")()}catch(t "use strict"; __webpack_require__.r(__webpack_exports__); - __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 _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\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\n// import dependencies via preval.require so that they're available as values at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\nvar RingBuffer = {\n \"default\":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: \"push\",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: \"pull\",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: \"framesAvailable\",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}[\"default\"];\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.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\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) {\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 this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\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 var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);"); + __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 _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\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\n// import dependencies via preval.require so that they're available as values at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\nvar RingBuffer = {\n \"default\":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: \"push\",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: \"pull\",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: \"framesAvailable\",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}[\"default\"];\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.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\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) {\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 this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\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 var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);"); }), (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); - __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 _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\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\n// import dependencies via preval.require so that they're available as values at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\nvar RingBuffer = {\n \"default\":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: \"push\",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: \"pull\",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: \"framesAvailable\",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}[\"default\"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: \"process\",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: 'position',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);"); + __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 _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\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\n// import dependencies via preval.require so that they're available as values at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\nvar RingBuffer = {\n \"default\":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: \"push\",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: \"pull\",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: \"framesAvailable\",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}[\"default\"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: \"process\",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: 'position',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);"); }), (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); - __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 _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\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\n// import dependencies via preval.require so that they're available as values at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\nvar RingBuffer = {\n \"default\":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: \"push\",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: \"pull\",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: \"framesAvailable\",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}[\"default\"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\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.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\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 } else if (data.name === 'smoothing') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: \"process\",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);"); + __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 _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\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\n// import dependencies via preval.require so that they're available as values at compile time\nvar processorNames = {\n \"recorderProcessor\": \"recorder-processor\",\n \"soundFileProcessor\": \"sound-file-processor\",\n \"amplitudeProcessor\": \"amplitude-processor\"\n};\nvar RingBuffer = {\n \"default\":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: \"push\",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: \"pull\",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: \"framesAvailable\",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}[\"default\"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\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.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\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 } else if (data.name === 'smoothing') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: \"process\",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);"); }), (function(module, exports, __webpack_require__) { -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1),__webpack_require__(17)], __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;oPeakDetect works in conjunction with p5.FFT to - * look for onsets in some or all of the frequency spectrum. - *

- *

- * To use p5.PeakDetect, call update in the draw loop - * and pass in a p5.FFT object. - *

- *

- * You can listen for a specific part of the frequency spectrum by - * setting the range between freq1 and freq2. - *

- * - *

threshold is the threshold for detecting a peak, - * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud - * as 1.0.

- * - *

- * The update method is meant to be run in the draw loop, and - * frames determines how many loops must pass before - * another peak can be detected. - * For example, if the frameRate() = 60, you could detect the beat of a - * 120 beat-per-minute song with this equation: - * framesPerPeak = 60 / (estimatedBPM / 60 ); - *

- * - *

- * Based on example contribtued by @b2renger, and a simple beat detection - * explanation by Felix Turner. - *

- * - * @class p5.PeakDetect - * @constructor - * @param {Number} [freq1] lowFrequency - defaults to 20Hz - * @param {Number} [freq2] highFrequency - defaults to 20000 Hz - * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1 - * scaled logarithmically where 0.1 is 1/2 the loudness - * of 1.0. Defaults to 0.35. - * @param {Number} [framesPerPeak] Defaults to 20. - * @example - *
- * - * var cnv, soundFile, fft, peakDetect; - * var ellipseWidth = 10; - * - * function preload() { - * soundFile = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * - * // p5.PeakDetect requires a p5.FFT - * fft = new p5.FFT(); - * peakDetect = new p5.PeakDetect(); - * } - * - * function draw() { - * background(0); - * text('click to play/pause', width/2, height/2); - * - * // peakDetect accepts an fft post-analysis - * fft.analyze(); - * peakDetect.update(fft); - * - * if ( peakDetect.isDetected ) { - * ellipseWidth = 50; - * } else { - * ellipseWidth *= 0.95; - * } - * - * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); - * } - * - * // toggle play/stop when canvas is clicked - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * if (soundFile.isPlaying() ) { - * soundFile.stop(); - * } else { - * soundFile.play(); - * } - * } - * } - *
- */ -p5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) { - this.framesPerPeak = _framesPerPeak || 20; - this.framesSinceLastPeak = 0; - this.decayRate = 0.95; - this.threshold = threshold || 0.35; - this.cutoff = 0; - - this.cutoffMult = 1.5; - this.energy = 0; - this.penergy = 0; - - this.currentValue = 0; - /** - * isDetected is set to true when a peak is detected. - * - * @attribute isDetected {Boolean} - * @default false - */ - - this.isDetected = false; - this.f1 = freq1 || 40; - this.f2 = freq2 || 20000; - - this._onPeak = function () {}; -}; -/** - * The update method is run in the draw loop. - * - * Accepts an FFT object. You must call .analyze() - * on the FFT object prior to updating the peakDetect - * because it relies on a completed FFT analysis. - * - * @method update - * @param {p5.FFT} fftObject A p5.FFT object - */ - - -p5.PeakDetect.prototype.update = function (fftObject) { - var nrg = this.energy = fftObject.getEnergy(this.f1, this.f2) / 255; - - if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) { - this._onPeak(); - - this.isDetected = true; - - this.cutoff = nrg * this.cutoffMult; - this.framesSinceLastPeak = 0; - } else { - this.isDetected = false; - - if (this.framesSinceLastPeak <= this.framesPerPeak) { - this.framesSinceLastPeak++; - } else { - this.cutoff *= this.decayRate; - this.cutoff = Math.max(this.cutoff, this.threshold); - } - } - - this.currentValue = nrg; - this.penergy = nrg; -}; -/** - * onPeak accepts two arguments: a function to call when - * a peak is detected. The value of the peak, - * between 0.0 and 1.0, is passed to the callback. - * - * @method onPeak - * @param {Function} callback Name of a function that will - * be called when a peak is - * detected. - * @param {Object} [val] Optional value to pass - * into the function when - * a peak is detected. - * @example - *
- * var cnv, soundFile, fft, peakDetect; - * var ellipseWidth = 0; - * - * function preload() { - * soundFile = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * cnv = createCanvas(100,100); - * textAlign(CENTER); - * - * fft = new p5.FFT(); - * peakDetect = new p5.PeakDetect(); - * - * setupSound(); - * - * // when a beat is detected, call triggerBeat() - * peakDetect.onPeak(triggerBeat); - * } - * - * function draw() { - * background(0); - * fill(255); - * text('click to play', width/2, height/2); - * - * fft.analyze(); - * peakDetect.update(fft); - * - * ellipseWidth *= 0.95; - * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); - * } - * - * // this function is called by peakDetect.onPeak - * function triggerBeat() { - * ellipseWidth = 50; - * } - * - * // mouseclick starts/stops sound - * function setupSound() { - * cnv.mouseClicked( function() { - * if (soundFile.isPlaying() ) { - * soundFile.stop(); - * } else { - * soundFile.play(); - * } - * }); - * } - *
- */ - - -p5.PeakDetect.prototype.onPeak = function (callback, val) { - var self = this; - - self._onPeak = function () { - callback(self.energy, val); - }; -}; - }), (function(module, __webpack_exports__, __webpack_require__) { @@ -913,10 +685,14 @@ var audioworklet_polyfill = __webpack_require__(24); var shims = __webpack_require__(25); -var audiocontext = __webpack_require__(6); +var audiocontext = __webpack_require__(3); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var master_Master = function Master() { + _classCallCheck(this, Master); + this.input = audiocontext["a" ].createGain(); this.output = audiocontext["a" ].createGain(); @@ -946,8 +722,7 @@ var master_Master = function Master() { }; -var p5sound = new master_Master(); - +var p5sound = new master_Master(); /** * Returns a number representing the master amplitude (volume) for sound * in this sketch. @@ -1044,9 +819,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat * @return {Number} samplerate samples per second */ -p5.prototype.sampleRate = function () { +function sampleRate() { return master.audiocontext.sampleRate; -}; +} /** * Returns the closest MIDI note value for * a given frequency. @@ -1058,11 +833,11 @@ p5.prototype.sampleRate = function () { */ -p5.prototype.freqToMidi = function (f) { +function freqToMidi(f) { var mathlog2 = Math.log(f / 440) / Math.log(2); var m = Math.round(12 * mathlog2) + 69; return m; -}; +} /** * Returns the frequency value of a MIDI note value. * General MIDI treats notes as integers where middle C @@ -1109,11 +884,12 @@ p5.prototype.freqToMidi = function (f) { */ -var midiToFreq = p5.prototype.midiToFreq = function (m) { +function midiToFreq(m) { return 440 * Math.pow(2, (m - 69) / 12.0); -}; +} -var noteToFreq = function noteToFreq(note) { + +function noteToFreq(note) { if (typeof note !== 'string') { return note; } @@ -1145,7 +921,7 @@ var noteToFreq = function noteToFreq(note) { } return midiToFreq(value); -}; +} /** * List the SoundFile formats that you will include. LoadSound * will search your directory for these extensions, and will pick @@ -1176,7 +952,8 @@ var noteToFreq = function noteToFreq(note) { * */ -p5.prototype.soundFormats = function () { + +function soundFormats() { master.extensions = []; for (var i = 0; i < arguments.length; i++) { @@ -1188,18 +965,15 @@ p5.prototype.soundFormats = function () { throw arguments[i] + ' is not a valid sound format!'; } } -}; +} -p5.prototype.disposeSound = function () { +function disposeSound() { for (var i = 0; i < master.soundArray.length; i++) { master.soundArray[i].dispose(); } -}; - - -p5.prototype.registerMethod('remove', p5.prototype.disposeSound); +} -p5.prototype._checkFileFormats = function (paths) { +function _checkFileFormats(paths) { var path; if (typeof paths === 'string') { @@ -1262,13 +1036,13 @@ p5.prototype._checkFileFormats = function (paths) { } return path; -}; +} /** * Used by Osc and Envelope to chain signal math */ -p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) { +function _mathChain(o, math, thisChain, nextChain, type) { for (var i in o.mathOps) { if (o.mathOps[i] instanceof type) { o.mathOps[i].dispose(); @@ -1285,7 +1059,7 @@ p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) { math.connect(nextChain); o.mathOps[thisChain] = math; return o; -}; +} function convertToWav(audioBuffer) { @@ -1332,6 +1106,7 @@ function convertToWav(audioBuffer) { return view; } + function interleave(leftChannel, rightChannel) { var length = leftChannel.length + rightChannel.length; var result = new Float32Array(length); @@ -1366,7 +1141,26 @@ function safeBufferSize(idealBufferSize) { tempAudioWorkletNode.disconnect(); tempAudioWorkletNode = null; return bufferSize; -} +} +/** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. + * For uploading audio to a server, use + * `p5.SoundFile.saveBlob`. + * + * @for p5 + * @method saveSound + * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save + * @param {String} fileName name of the resulting .wav file. + */ + + +function saveSound(soundFile, fileName) { + var dataView = convertToWav(soundFile.buffer); + p5.prototype.writeFile([dataView], fileName, 'wav'); +} + + var CustomError = function CustomError(name, errorTrace, failedPath) { var err = new Error(); var tempStack, splitStack; @@ -1386,7 +1180,6 @@ var CustomError = function CustomError(name, errorTrace, failedPath) { var moduleSources = [__webpack_require__(27)["default"], __webpack_require__(28)["default"], __webpack_require__(29)["default"]]; var audioWorklet_ac = master.audiocontext; -var initializedAudioWorklets = false; function loadAudioWorkletModules() { return Promise.all(moduleSources.map(function (moduleSrc) { @@ -1399,8 +1192,6 @@ function loadAudioWorkletModules() { } p5.prototype.registerMethod('init', function () { - if (initializedAudioWorklets) return; - if (!this.preload && !window.preload) { this.preload = function () {}; } @@ -1409,111 +1200,349 @@ p5.prototype.registerMethod('init', function () { this._incrementPreload(); var onWorkletModulesLoad = function () { - initializedAudioWorklets = true; - this._decrementPreload(); }.bind(this); loadAudioWorkletModules().then(onWorkletModulesLoad); }); +function panner_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var panner_ac = master.audiocontext; +function _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); } } -if (typeof panner_ac.createStereoPanner !== 'undefined') { - p5.Panner = function (input, output) { - this.stereoPanner = this.input = panner_ac.createStereoPanner(); - input.connect(this.stereoPanner); - this.stereoPanner.connect(output); - }; +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } - p5.Panner.prototype.pan = function (val, tFromNow) { - var time = tFromNow || 0; - var t = panner_ac.currentTime + time; - this.stereoPanner.pan.linearRampToValueAtTime(val, t); - }; +var panner_ac = master.audiocontext; +var panner; - p5.Panner.prototype.inputChannels = function () {}; +if (typeof panner_ac.createStereoPanner !== 'undefined') { + var Panner = + function () { + function Panner(input, output) { + panner_classCallCheck(this, Panner); + + this.stereoPanner = this.input = panner_ac.createStereoPanner(); + input.connect(this.stereoPanner); + this.stereoPanner.connect(output); + } - p5.Panner.prototype.connect = function (obj) { - this.stereoPanner.connect(obj); - }; + _createClass(Panner, [{ + key: "pan", + value: function pan(val, tFromNow) { + var time = tFromNow || 0; + var t = panner_ac.currentTime + time; + this.stereoPanner.pan.linearRampToValueAtTime(val, t); + } - p5.Panner.prototype.disconnect = function () { - if (this.stereoPanner) { - this.stereoPanner.disconnect(); - } - }; + }, { + key: "inputChannels", + value: function inputChannels() {} + }, { + key: "connect", + value: function connect(obj) { + this.stereoPanner.connect(obj); + } + }, { + key: "disconnect", + value: function disconnect() { + if (this.stereoPanner) { + this.stereoPanner.disconnect(); + } + } + }]); + + return Panner; + }(); + + panner = Panner; } else { - p5.Panner = function (input, output, numInputChannels) { - this.input = panner_ac.createGain(); - input.connect(this.input); - this.left = panner_ac.createGain(); - this.right = panner_ac.createGain(); - this.left.channelInterpretation = 'discrete'; - this.right.channelInterpretation = 'discrete'; - - if (numInputChannels > 1) { - this.splitter = panner_ac.createChannelSplitter(2); - this.input.connect(this.splitter); - this.splitter.connect(this.left, 1); - this.splitter.connect(this.right, 0); - } else { - this.input.connect(this.left); - this.input.connect(this.right); + var _Panner = + function () { + function _Panner(input, output, numInputChannels) { + panner_classCallCheck(this, _Panner); + + this.input = panner_ac.createGain(); + input.connect(this.input); + this.left = panner_ac.createGain(); + this.right = panner_ac.createGain(); + this.left.channelInterpretation = 'discrete'; + this.right.channelInterpretation = 'discrete'; + + if (numInputChannels > 1) { + this.splitter = panner_ac.createChannelSplitter(2); + this.input.connect(this.splitter); + this.splitter.connect(this.left, 1); + this.splitter.connect(this.right, 0); + } else { + this.input.connect(this.left); + this.input.connect(this.right); + } + + this.output = panner_ac.createChannelMerger(2); + this.left.connect(this.output, 0, 1); + this.right.connect(this.output, 0, 0); + this.output.connect(output); + } + + + _createClass(_Panner, [{ + key: "pan", + value: function pan(val, tFromNow) { + var time = tFromNow || 0; + var t = panner_ac.currentTime + time; + var v = (val + 1) / 2; + var rightVal = Math.cos(v * Math.PI / 2); + var leftVal = Math.sin(v * Math.PI / 2); + this.left.gain.linearRampToValueAtTime(leftVal, t); + this.right.gain.linearRampToValueAtTime(rightVal, t); + } + }, { + key: "inputChannels", + value: function inputChannels(numChannels) { + if (numChannels === 1) { + this.input.disconnect(); + this.input.connect(this.left); + this.input.connect(this.right); + } else if (numChannels === 2) { + if (typeof this.splitter === 'undefined') { + this.splitter = panner_ac.createChannelSplitter(2); + } + + this.input.disconnect(); + this.input.connect(this.splitter); + this.splitter.connect(this.left, 1); + this.splitter.connect(this.right, 0); + } + } + }, { + key: "connect", + value: function connect(obj) { + this.output.connect(obj); + } + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + } + }]); + + return _Panner; + }(); + + panner = _Panner; +} + + var panner_0 = (panner); +function soundfile_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { soundfile_typeof = function _typeof(obj) { return typeof obj; }; } else { soundfile_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return soundfile_typeof(obj); } + +function soundfile_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); } } + +function soundfile_createClass(Constructor, protoProps, staticProps) { if (protoProps) soundfile_defineProperties(Constructor.prototype, protoProps); if (staticProps) soundfile_defineProperties(Constructor, staticProps); return Constructor; } + +function soundfile_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + + + + +var soundfile_ac = master.audiocontext; + +var _createCounterBuffer = function _createCounterBuffer(buffer) { + var len = buffer.length; + var audioBuf = soundfile_ac.createBuffer(1, buffer.length, soundfile_ac.sampleRate); + var arrayBuffer = audioBuf.getChannelData(0); + + for (var index = 0; index < len; index++) { + arrayBuffer[index] = index; + } + + return audioBuf; +}; + + +var Peak = function Peak(amp, i) { + soundfile_classCallCheck(this, Peak); + + this.sampleIndex = i; + this.amplitude = amp; + this.tempos = []; + this.intervals = []; +}; + + +function getPeaksAtThreshold(data, threshold) { + var peaksObj = {}; + var length = data.length; + + for (var i = 0; i < length; i++) { + if (data[i] > threshold) { + var amp = data[i]; + var peak = new Peak(amp, i); + peaksObj[i] = peak; + + i += 6000; } - this.output = panner_ac.createChannelMerger(2); - this.left.connect(this.output, 0, 1); - this.right.connect(this.output, 0, 0); - this.output.connect(output); - }; + i++; + } + + return peaksObj; +} + +function countIntervalsBetweenNearbyPeaks(peaksObj) { + var intervalCounts = []; + var peaksArray = Object.keys(peaksObj).sort(); - p5.Panner.prototype.pan = function (val, tFromNow) { - var time = tFromNow || 0; - var t = panner_ac.currentTime + time; - var v = (val + 1) / 2; - var rightVal = Math.cos(v * Math.PI / 2); - var leftVal = Math.sin(v * Math.PI / 2); - this.left.gain.linearRampToValueAtTime(leftVal, t); - this.right.gain.linearRampToValueAtTime(rightVal, t); - }; + for (var index = 0; index < peaksArray.length; index++) { + for (var i = 0; i < 10; i++) { + var startPeak = peaksObj[peaksArray[index]]; + var endPeak = peaksObj[peaksArray[index + i]]; - p5.Panner.prototype.inputChannels = function (numChannels) { - if (numChannels === 1) { - this.input.disconnect(); - this.input.connect(this.left); - this.input.connect(this.right); - } else if (numChannels === 2) { - if (typeof this.splitter === 'undefined') { - this.splitter = panner_ac.createChannelSplitter(2); + if (startPeak && endPeak) { + var startPos = startPeak.sampleIndex; + var endPos = endPeak.sampleIndex; + var interval = endPos - startPos; + + if (interval > 0) { + startPeak.intervals.push(interval); + } + + + var foundInterval = intervalCounts.some(function (intervalCount) { + if (intervalCount.interval === interval) { + intervalCount.count++; + return intervalCount; + } + }); + + if (!foundInterval) { + intervalCounts.push({ + interval: interval, + count: 1 + }); + } } + } + } - this.input.disconnect(); - this.input.connect(this.splitter); - this.splitter.connect(this.left, 1); - this.splitter.connect(this.right, 0); + return intervalCounts; +} + + +function groupNeighborsByTempo(intervalCounts, sampleRate) { + var tempoCounts = []; + intervalCounts.forEach(function (intervalCount) { + try { + var theoreticalTempo = Math.abs(60 / (intervalCount.interval / sampleRate)); + theoreticalTempo = mapTempo(theoreticalTempo); + var foundTempo = tempoCounts.some(function (tempoCount) { + if (tempoCount.tempo === theoreticalTempo) return tempoCount.count += intervalCount.count; + }); + + if (!foundTempo) { + if (isNaN(theoreticalTempo)) { + return; + } + + tempoCounts.push({ + tempo: Math.round(theoreticalTempo), + count: intervalCount.count + }); + } + } catch (e) { + throw e; } - }; + }); + return tempoCounts; +} - p5.Panner.prototype.connect = function (obj) { - this.output.connect(obj); - }; - p5.Panner.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); +function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { + var peaksAtTopTempo = []; + var peaksArray = Object.keys(peaksObj).sort(); + + for (var i = 0; i < peaksArray.length; i++) { + var key = peaksArray[i]; + var peak = peaksObj[key]; + + for (var j = 0; j < peak.intervals.length; j++) { + var intervalBPM = Math.round(Math.abs(60 / (peak.intervals[j] / sampleRate))); + intervalBPM = mapTempo(intervalBPM); + + if (Math.abs(intervalBPM - tempo) < bpmVariance) { + peaksAtTopTempo.push(peak.sampleIndex / sampleRate); + } } - }; + } + + + peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { + var dif = arr[index + 1] - peakTime; + + if (dif > 0.01) { + return true; + } + }); + return peaksAtTopTempo; +} + + +function mapTempo(theoreticalTempo) { + if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { + return; + } + + + while (theoreticalTempo < 90) { + theoreticalTempo *= 2; + } + + while (theoreticalTempo > 180 && theoreticalTempo > 90) { + theoreticalTempo /= 2; + } + + return theoreticalTempo; } -function soundfile_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { soundfile_typeof = function _typeof(obj) { return typeof obj; }; } else { soundfile_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return soundfile_typeof(obj); } +var Cue = function Cue(callback, time, id, val) { + soundfile_classCallCheck(this, Cue); + + this.callback = callback; + this.time = time; + this.id = id; + this.val = val; +}; +function _clearOnEnd(e) { + var thisBufferSourceNode = e.target; + var soundFile = this; -var soundfile_ac = master.audiocontext; + thisBufferSourceNode._playing = false; + thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd); + + soundFile._onended(soundFile); + + + soundFile.bufferSourceNodes.map(function (_, i) { + return i; + }).reverse().forEach(function (i) { + var n = soundFile.bufferSourceNodes[i]; + + if (n._playing === false) { + soundFile.bufferSourceNodes.splice(i, 1); + } + }); + + if (soundFile.bufferSourceNodes.length === 0) { + soundFile._playing = false; + } +} /** *

SoundFile object with a path to a file.

* @@ -1572,196 +1601,155 @@ var soundfile_ac = master.audiocontext; * */ -p5.SoundFile = function (paths, onload, onerror, whileLoading) { - if (typeof paths !== 'undefined') { - if (typeof paths === 'string' || typeof paths[0] === 'string') { - var path = p5.prototype._checkFileFormats(paths); - this.url = path; - } else if (soundfile_typeof(paths) === 'object') { - if (!(window.File && window.FileReader && window.FileList && window.Blob)) { - throw 'Unable to load file because the File API is not supported'; +var soundfile_SoundFile = +function () { + function SoundFile(paths, onload, onerror, whileLoading) { + soundfile_classCallCheck(this, SoundFile); + + if (typeof paths !== 'undefined') { + if (typeof paths === 'string' || typeof paths[0] === 'string') { + var path = p5.prototype._checkFileFormats(paths); + + this.url = path; + } else if (soundfile_typeof(paths) === 'object') { + if (!(window.File && window.FileReader && window.FileList && window.Blob)) { + throw 'Unable to load file because the File API is not supported'; + } + } + + + if (paths.file) { + paths = paths.file; } + + this.file = paths; } - if (paths.file) { - paths = paths.file; - } + this._onended = function () {}; - this.file = paths; - } + this._looping = false; + this._playing = false; + this._paused = false; + this._pauseTime = 0; + this._cues = []; + this._cueIDCounter = 0; - this._onended = function () {}; + this._lastPos = 0; + this._counterNode = null; + this._workletNode = null; - this._looping = false; - this._playing = false; - this._paused = false; - this._pauseTime = 0; + this.bufferSourceNodes = []; - this._cues = []; - this._cueIDCounter = 0; + this.bufferSourceNode = null; + this.buffer = null; + this.playbackRate = 1; + this.input = master.audiocontext.createGain(); + this.output = master.audiocontext.createGain(); + this.reversed = false; - this._lastPos = 0; - this._counterNode = null; - this._workletNode = null; + this.startTime = 0; + this.endTime = null; + this.pauseTime = 0; - this.bufferSourceNodes = []; + this.mode = 'sustain'; - this.bufferSourceNode = null; - this.buffer = null; - this.playbackRate = 1; - this.input = master.audiocontext.createGain(); - this.output = master.audiocontext.createGain(); - this.reversed = false; + this.startMillis = null; - this.startTime = 0; - this.endTime = null; - this.pauseTime = 0; + this.panPosition = 0.0; + this.panner = new panner_0(this.output, master.input, 2); - this.mode = 'sustain'; + if (this.url || this.file) { + this.load(onload, onerror); + } - this.startMillis = null; - this.panPosition = 0.0; - this.panner = new p5.Panner(this.output, master.input, 2); + master.soundArray.push(this); - if (this.url || this.file) { - this.load(onload, onerror); - } + if (typeof whileLoading === 'function') { + this._whileLoading = whileLoading; + } else { + this._whileLoading = function () {}; + } + this._clearOnEnd = _clearOnEnd.bind(this); - master.soundArray.push(this); + this.amp = this.setVolume; - if (typeof whileLoading === 'function') { - this._whileLoading = whileLoading; - } else { - this._whileLoading = function () {}; + this.fade = this.setVolume; } + /** + * This is a helper function that the p5.SoundFile calls to load + * itself. Accepts a callback (the name of another function) + * as an optional parameter. + * + * @private + * @for p5.SoundFile + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if there is an error + */ - this._clearOnEnd = _clearOnEnd.bind(this); -}; + soundfile_createClass(SoundFile, [{ + key: "load", + value: function load(callback, errorCallback) { + var self = this; + var errorTrace = new Error().stack; + + if (this.url !== undefined && this.url !== '') { + var request = new XMLHttpRequest(); + request.addEventListener('progress', function (evt) { + self._updateProgress(evt); + }, false); + request.open('GET', this.url, true); + request.responseType = 'arraybuffer'; + + request.onload = function () { + if (request.status === 200) { + if (!self.panner) return; + soundfile_ac.decodeAudioData(request.response, + function (buff) { + if (!self.panner) return; + self.buffer = buff; + self.panner.inputChannels(buff.numberOfChannels); + + if (callback) { + callback(self); + } + }, + function () { + if (!self.panner) return; + var err = new errorHandler('decodeAudioData', errorTrace, self.url); + var msg = 'AudioContext error at decodeAudioData for ' + self.url; + + if (errorCallback) { + err.msg = msg; + errorCallback(err); + } else { + console.error(msg + '\n The error stack trace includes: \n' + err.stack); + } + }); + } + else { + if (!self.panner) return; + var err = new errorHandler('loadSound', errorTrace, self.url); + var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; + + if (errorCallback) { + err.message = msg; + errorCallback(err); + } else { + console.error(msg + '\n The error stack trace includes: \n' + err.stack); + } + } + }; -p5.prototype.registerPreloadMethod('loadSound', p5.prototype); -/** - * loadSound() returns a new p5.SoundFile from a specified - * path. If called during preload(), the p5.SoundFile will be ready - * to play in time for setup() and draw(). If called outside of - * preload, the p5.SoundFile will not be ready immediately, so - * loadSound accepts a callback as the second parameter. Using a - * - * local server is recommended when loading external files. - * - * @method loadSound - * @for p5 - * @param {String|Array} path Path to the sound file, or an array with - * paths to soundfiles in multiple formats - * i.e. ['sound.ogg', 'sound.mp3']. - * Alternately, accepts an object: either - * from the HTML5 File API, or a p5.File. - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if there is - * an error loading the file. - * @param {Function} [whileLoading] Name of a function to call while file is loading. - * This function will receive the percentage loaded - * so far, from 0.0 to 1.0. - * @return {SoundFile} Returns a p5.SoundFile - * @example - *
- * let mySound; - * function preload() { - * soundFormats('mp3', 'ogg'); - * mySound = loadSound('assets/doorbell'); - * } - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * text('tap here to play', 10, 20); - * } - * - * function canvasPressed() { - * // playing a sound file on a user gesture - * // is equivalent to `userStartAudio()` - * mySound.play(); - * } - *
- */ - -p5.prototype.loadSound = function (path, callback, onerror, whileLoading) { - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - - var self = this; - var s = new p5.SoundFile(path, function () { - if (typeof callback === 'function') { - callback.apply(self, arguments); - } - - if (typeof self._decrementPreload === 'function') { - self._decrementPreload(); - } - }, onerror, whileLoading); - return s; -}; -/** - * This is a helper function that the p5.SoundFile calls to load - * itself. Accepts a callback (the name of another function) - * as an optional parameter. - * - * @private - * @for p5.SoundFile - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if there is an error - */ - - -p5.SoundFile.prototype.load = function (callback, errorCallback) { - var self = this; - var errorTrace = new Error().stack; - - if (this.url !== undefined && this.url !== '') { - var request = new XMLHttpRequest(); - request.addEventListener('progress', function (evt) { - self._updateProgress(evt); - }, false); - request.open('GET', this.url, true); - request.responseType = 'arraybuffer'; - - request.onload = function () { - if (request.status === 200) { - if (!self.panner) return; - soundfile_ac.decodeAudioData(request.response, - function (buff) { - if (!self.panner) return; - self.buffer = buff; - self.panner.inputChannels(buff.numberOfChannels); - - if (callback) { - callback(self); - } - }, - function () { - if (!self.panner) return; - var err = new errorHandler('decodeAudioData', errorTrace, self.url); - var msg = 'AudioContext error at decodeAudioData for ' + self.url; - if (errorCallback) { - err.msg = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - }); - } - else { - if (!self.panner) return; + request.onerror = function () { var err = new errorHandler('loadSound', errorTrace, self.url); - var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; + var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; if (errorCallback) { err.message = msg; @@ -1769,3642 +1757,3491 @@ p5.SoundFile.prototype.load = function (callback, errorCallback) { } else { console.error(msg + '\n The error stack trace includes: \n' + err.stack); } - } - }; + }; + request.send(); + } else if (this.file !== undefined) { + var reader = new FileReader(); - request.onerror = function () { - var err = new errorHandler('loadSound', errorTrace, self.url); - var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; + reader.onload = function () { + if (!self.panner) return; + soundfile_ac.decodeAudioData(reader.result, function (buff) { + if (!self.panner) return; + self.buffer = buff; + self.panner.inputChannels(buff.numberOfChannels); - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); + if (callback) { + callback(self); + } + }); + }; + + reader.onerror = function (e) { + if (!self.panner) return; + + if (onerror) { + onerror(e); + } + }; + + reader.readAsArrayBuffer(this.file); } - }; + } - request.send(); - } else if (this.file !== undefined) { - var reader = new FileReader(); + }, { + key: "_updateProgress", + value: function _updateProgress(evt) { + if (evt.lengthComputable) { + var percentComplete = evt.loaded / evt.total * 0.99; - reader.onload = function () { - if (!self.panner) return; - soundfile_ac.decodeAudioData(reader.result, function (buff) { - if (!self.panner) return; - self.buffer = buff; - self.panner.inputChannels(buff.numberOfChannels); + this._whileLoading(percentComplete, evt); - if (callback) { - callback(self); - } - }); - }; + } else { + this._whileLoading('size unknown'); + } + } + /** + * Returns true if the sound file finished loading successfully. + * + * @method isLoaded + * @for p5.SoundFile + * @return {Boolean} + */ + + }, { + key: "isLoaded", + value: function isLoaded() { + if (this.buffer) { + return true; + } else { + return false; + } + } + /** + * Play the p5.SoundFile + * + * @method play + * @for p5.SoundFile + * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now). + * @param {Number} [rate] (optional) playback rate + * @param {Number} [amp] (optional) amplitude (volume) + * of playback + * @param {Number} [cueStart] (optional) cue start time in seconds + * @param {Number} [duration] (optional) duration of playback in seconds + */ + + }, { + key: "play", + value: function play(startTime, rate, amp, _cueStart, duration) { + if (!this.output) { + console.warn('SoundFile.play() called after dispose'); + return; + } - reader.onerror = function (e) { - if (!self.panner) return; + var now = master.audiocontext.currentTime; + var cueStart, cueEnd; + var time = startTime || 0; - if (onerror) { - onerror(e); + if (time < 0) { + time = 0; } - }; - reader.readAsArrayBuffer(this.file); - } -}; + time = time + now; + if (typeof rate !== 'undefined') { + this.rate(rate); + } -p5.SoundFile.prototype._updateProgress = function (evt) { - if (evt.lengthComputable) { - var percentComplete = evt.loaded / evt.total * 0.99; + if (typeof amp !== 'undefined') { + this.setVolume(amp); + } - this._whileLoading(percentComplete, evt); - } else { - this._whileLoading('size unknown'); - } -}; -/** - * Returns true if the sound file finished loading successfully. - * - * @method isLoaded - * @for p5.SoundFile - * @return {Boolean} - */ + if (this.buffer) { + this._pauseTime = 0; + if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) { + this.bufferSourceNode.stop(time); -p5.SoundFile.prototype.isLoaded = function () { - if (this.buffer) { - return true; - } else { - return false; - } -}; -/** - * Play the p5.SoundFile - * - * @method play - * @for p5.SoundFile - * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now). - * @param {Number} [rate] (optional) playback rate - * @param {Number} [amp] (optional) amplitude (volume) - * of playback - * @param {Number} [cueStart] (optional) cue start time in seconds - * @param {Number} [duration] (optional) duration of playback in seconds - */ + this._counterNode.stop(time); + } -p5.SoundFile.prototype.play = function (startTime, rate, amp, _cueStart, duration) { - if (!this.output) { - console.warn('SoundFile.play() called after dispose'); - return; - } + if (this.mode === 'untildone' && this.isPlaying()) { + return; + } - var now = master.audiocontext.currentTime; - var cueStart, cueEnd; - var time = startTime || 0; - if (time < 0) { - time = 0; - } + this.bufferSourceNode = this._initSourceNode(); - time = time + now; + delete this._counterNode; + this._counterNode = this._initCounterNode(); - if (typeof rate !== 'undefined') { - this.rate(rate); - } + if (_cueStart) { + if (_cueStart >= 0 && _cueStart < this.buffer.duration) { + cueStart = _cueStart; + } else { + throw 'start time out of range'; + } + } else { + cueStart = 0; + } - if (typeof amp !== 'undefined') { - this.setVolume(amp); - } + if (duration) { + duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration; + } - if (this.buffer) { - this._pauseTime = 0; + if (this._paused) { + this.bufferSourceNode.start(time, this.pauseTime, duration); - if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) { - this.bufferSourceNode.stop(time); + this._counterNode.start(time, this.pauseTime, duration); + } else { + this.bufferSourceNode.start(time, cueStart, duration); - this._counterNode.stop(time); - } + this._counterNode.start(time, cueStart, duration); + } + this._playing = true; + this._paused = false; - if (this.mode === 'untildone' && this.isPlaying()) { - return; - } + this.bufferSourceNodes.push(this.bufferSourceNode); + this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1; + this.bufferSourceNode.addEventListener('ended', this._clearOnEnd); + } + else { + throw 'not ready to play file, buffer has yet to load. Try preload()'; + } - this.bufferSourceNode = this._initSourceNode(); + this.bufferSourceNode.loop = this._looping; + this._counterNode.loop = this._looping; + + if (this._looping === true) { + cueEnd = duration ? duration : cueStart - 0.000000000000001; + this.bufferSourceNode.loopStart = cueStart; + this.bufferSourceNode.loopEnd = cueEnd; + this._counterNode.loopStart = cueStart; + this._counterNode.loopEnd = cueEnd; + } + } + /** + * p5.SoundFile has two play modes: restart and + * sustain. Play Mode determines what happens to a + * p5.SoundFile if it is triggered while in the middle of playback. + * In sustain mode, playback will continue simultaneous to the + * new playback. In restart mode, play() will stop playback + * and start over. With untilDone, a sound will play only if it's + * not already playing. Sustain is the default mode. + * + * @method playMode + * @for p5.SoundFile + * @param {String} str 'restart' or 'sustain' or 'untilDone' + * @example + *
+ * let mySound; + * function preload(){ + * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * noFill(); + * rect(0, height/2, width - 1, height/2 - 1); + * rect(0, 0, width - 1, height/2); + * textAlign(CENTER, CENTER); + * fill(20); + * text('restart', width/2, 1 * height/4); + * text('sustain', width/2, 3 * height/4); + * } + * function canvasPressed() { + * if (mouseX < height/2) { + * mySound.playMode('restart'); + * } else { + * mySound.playMode('sustain'); + * } + * mySound.play(); + * } + * + *
+ */ + + }, { + key: "playMode", + value: function playMode(str) { + var s = str.toLowerCase(); + + if (s === 'restart' && this.buffer && this.bufferSourceNode) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + var now = master.audiocontext.currentTime; + this.bufferSourceNodes[i].stop(now); + } + } - delete this._counterNode; - this._counterNode = this._initCounterNode(); - if (_cueStart) { - if (_cueStart >= 0 && _cueStart < this.buffer.duration) { - cueStart = _cueStart; + if (s === 'restart' || s === 'sustain' || s === 'untildone') { + this.mode = s; } else { - throw 'start time out of range'; + throw 'Invalid play mode. Must be either "restart" or "sustain"'; } - } else { - cueStart = 0; } + /** + * Pauses a file that is currently playing. If the file is not + * playing, then nothing will happen. + * + * After pausing, .play() will resume from the paused + * position. + * If p5.SoundFile had been set to loop before it was paused, + * it will continue to loop after it is unpaused with .play(). + * + * @method pause + * @for p5.SoundFile + * @param {Number} [startTime] (optional) schedule event to occur + * seconds from now + * @example + *
+ * let soundFile; + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); + * } + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * background(220); + * text('tap to play, release to pause', 10, 20, width - 20); + * } + * function canvasPressed() { + * soundFile.loop(); + * background(0, 200, 50); + * } + * function mouseReleased() { + * soundFile.pause(); + * background(220); + * } + * + *
+ */ + + }, { + key: "pause", + value: function pause(startTime) { + var now = master.audiocontext.currentTime; + var time = startTime || 0; + var pTime = time + now; - if (duration) { - duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration; - } + if (this.isPlaying() && this.buffer && this.bufferSourceNode) { + this._paused = true; + this._playing = false; + this.pauseTime = this.currentTime(); + this.bufferSourceNode.stop(pTime); + + this._counterNode.stop(pTime); + this._pauseTime = this.currentTime(); + } else { + this._pauseTime = 0; + } + } + /** + * Loop the p5.SoundFile. Accepts optional parameters to set the + * playback rate, playback volume, loopStart, loopEnd. + * + * @method loop + * @for p5.SoundFile + * @param {Number} [startTime] (optional) schedule event to occur + * seconds from now + * @param {Number} [rate] (optional) playback rate + * @param {Number} [amp] (optional) playback volume + * @param {Number} [cueLoopStart] (optional) startTime in seconds + * @param {Number} [duration] (optional) loop duration in seconds + * @example + *
+ * let soundFile; + * let loopStart = 0.5; + * let loopDuration = 0.2; + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); + * } + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * background(220); + * text('tap to play, release to pause', 10, 20, width - 20); + * } + * function canvasPressed() { + * soundFile.loop(); + * background(0, 200, 50); + * } + * function mouseReleased() { + * soundFile.pause(); + * background(220); + * } + * + *
+ */ + + }, { + key: "loop", + value: function loop(startTime, rate, amp, loopStart, duration) { + this._looping = true; + this.play(startTime, rate, amp, loopStart, duration); + } + /** + * Set a p5.SoundFile's looping flag to true or false. If the sound + * is currently playing, this change will take effect when it + * reaches the end of the current playback. + * + * @method setLoop + * @for p5.SoundFile + * @param {Boolean} Boolean set looping to true or false + */ + + }, { + key: "setLoop", + value: function setLoop(bool) { + if (bool === true) { + this._looping = true; + } else if (bool === false) { + this._looping = false; + } else { + throw 'Error: setLoop accepts either true or false'; + } - if (this._paused) { - this.bufferSourceNode.start(time, this.pauseTime, duration); + if (this.bufferSourceNode) { + this.bufferSourceNode.loop = this._looping; + this._counterNode.loop = this._looping; + } + } + /** + * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not. + * + * @method isLooping + * @for p5.SoundFile + * @return {Boolean} + */ + + }, { + key: "isLooping", + value: function isLooping() { + if (!this.bufferSourceNode) { + return false; + } - this._counterNode.start(time, this.pauseTime, duration); - } else { - this.bufferSourceNode.start(time, cueStart, duration); + if (this._looping === true && this.isPlaying() === true) { + return true; + } - this._counterNode.start(time, cueStart, duration); + return false; } + /** + * Returns true if a p5.SoundFile is playing, false if not (i.e. + * paused or stopped). + * + * @method isPlaying + * @for p5.SoundFile + * @return {Boolean} + */ + + }, { + key: "isPlaying", + value: function isPlaying() { + return this._playing; + } + /** + * Returns true if a p5.SoundFile is paused, false if not (i.e. + * playing or stopped). + * + * @method isPaused + * @for p5.SoundFile + * @return {Boolean} + */ + + }, { + key: "isPaused", + value: function isPaused() { + return this._paused; + } + /** + * Stop soundfile playback. + * + * @method stop + * @for p5.SoundFile + * @param {Number} [startTime] (optional) schedule event to occur + * in seconds from now + */ + + }, { + key: "stop", + value: function stop(timeFromNow) { + var time = timeFromNow || 0; + + if (this.mode === 'sustain' || this.mode === 'untildone') { + this.stopAll(time); + this._playing = false; + this.pauseTime = 0; + this._paused = false; + } else if (this.buffer && this.bufferSourceNode) { + var now = master.audiocontext.currentTime; + var t = time || 0; + this.pauseTime = 0; + this.bufferSourceNode.stop(now + t); + + this._counterNode.stop(now + t); + + this._playing = false; + this._paused = false; + } + } + /** + * Stop playback on all of this soundfile's sources. + * @private + */ + + }, { + key: "stopAll", + value: function stopAll(_time) { + var now = master.audiocontext.currentTime; + var time = _time || 0; - this._playing = true; - this._paused = false; + if (this.buffer && this.bufferSourceNode) { + for (var i in this.bufferSourceNodes) { + var bufferSourceNode = this.bufferSourceNodes[i]; - this.bufferSourceNodes.push(this.bufferSourceNode); - this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1; - this.bufferSourceNode.addEventListener('ended', this._clearOnEnd); - } - else { - throw 'not ready to play file, buffer has yet to load. Try preload()'; - } + if (bufferSourceNode) { + try { + bufferSourceNode.stop(now + time); + } catch (e) { + } + } + } + this._counterNode.stop(now + time); - this.bufferSourceNode.loop = this._looping; - this._counterNode.loop = this._looping; + this._onended(this); + } + } + }, { + key: "getVolume", + value: function getVolume() { + return this.output.gain.value; + } + /** + * Set the stereo panning of a p5.sound object to + * a floating point number between -1.0 (left) and 1.0 (right). + * Default is 0.0 (center). + * + * @method pan + * @for p5.SoundFile + * @param {Number} [panValue] Set the stereo panner + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @example + *
+ * let ballX = 0; + * let soundFile; + * + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/beatbox.mp3'); + * } + * + * function draw() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * background(220); + * ballX = constrain(mouseX, 0, width); + * ellipse(ballX, height/2, 20, 20); + * } + * + * function canvasPressed(){ + * // map the ball's x location to a panning degree + * // between -1.0 (left) and 1.0 (right) + * let panning = map(ballX, 0., width,-1.0, 1.0); + * soundFile.pan(panning); + * soundFile.play(); + * } + *
+ */ + + }, { + key: "pan", + value: function pan(pval, tFromNow) { + this.panPosition = pval; + this.panner.pan(pval, tFromNow); + } + /** + * Returns the current stereo pan position (-1.0 to 1.0) + * + * @method getPan + * @for p5.SoundFile + * @return {Number} Returns the stereo pan setting of the Oscillator + * as a number between -1.0 (left) and 1.0 (right). + * 0.0 is center and default. + */ + + }, { + key: "getPan", + value: function getPan() { + return this.panPosition; + } + /** + * Set the playback rate of a sound file. Will change the speed and the pitch. + * Values less than zero will reverse the audio buffer. + * + * @method rate + * @for p5.SoundFile + * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal, + * .5 is half-speed, 2.0 is twice as fast. + * Values less than zero play backwards. + * @example + *
+ * let mySound; + * + * function preload() { + * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * } + * function canvasPressed() { + * mySound.loop(); + * } + * function mouseReleased() { + * mySound.pause(); + * } + * function draw() { + * background(220); + * + * // Set the rate to a range between 0.1 and 4 + * // Changing the rate also alters the pitch + * let playbackRate = map(mouseY, 0.1, height, 2, 0); + * playbackRate = constrain(playbackRate, 0.01, 4); + * mySound.rate(playbackRate); + * + * line(0, mouseY, width, mouseY); + * text('rate: ' + round(playbackRate * 100) + '%', 10, 20); + * } + * + * + *
+ * + */ + + }, { + key: "rate", + value: function rate(playbackRate) { + var reverse = false; + + if (typeof playbackRate === 'undefined') { + return this.playbackRate; + } - if (this._looping === true) { - cueEnd = duration ? duration : cueStart - 0.000000000000001; - this.bufferSourceNode.loopStart = cueStart; - this.bufferSourceNode.loopEnd = cueEnd; - this._counterNode.loopStart = cueStart; - this._counterNode.loopEnd = cueEnd; - } -}; -/** - * p5.SoundFile has two play modes: restart and - * sustain. Play Mode determines what happens to a - * p5.SoundFile if it is triggered while in the middle of playback. - * In sustain mode, playback will continue simultaneous to the - * new playback. In restart mode, play() will stop playback - * and start over. With untilDone, a sound will play only if it's - * not already playing. Sustain is the default mode. - * - * @method playMode - * @for p5.SoundFile - * @param {String} str 'restart' or 'sustain' or 'untilDone' - * @example - *
- * let mySound; - * function preload(){ - * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * noFill(); - * rect(0, height/2, width - 1, height/2 - 1); - * rect(0, 0, width - 1, height/2); - * textAlign(CENTER, CENTER); - * fill(20); - * text('restart', width/2, 1 * height/4); - * text('sustain', width/2, 3 * height/4); - * } - * function canvasPressed() { - * if (mouseX < height/2) { - * mySound.playMode('restart'); - * } else { - * mySound.playMode('sustain'); - * } - * mySound.play(); - * } - * - *
- */ + this.playbackRate = playbackRate; + if (playbackRate === 0) { + playbackRate = 0.0000000000001; + } else if (playbackRate < 0 && !this.reversed) { + playbackRate = Math.abs(playbackRate); + reverse = true; + } else if (playbackRate > 0 && this.reversed) { + reverse = true; + } -p5.SoundFile.prototype.playMode = function (str) { - var s = str.toLowerCase(); + if (this.bufferSourceNode) { + var now = master.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(now); + this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); - if (s === 'restart' && this.buffer && this.bufferSourceNode) { - for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { - var now = master.audiocontext.currentTime; - this.bufferSourceNodes[i].stop(now); - } - } + this._counterNode.playbackRate.cancelScheduledValues(now); + this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); + } - if (s === 'restart' || s === 'sustain' || s === 'untildone') { - this.mode = s; - } else { - throw 'Invalid play mode. Must be either "restart" or "sustain"'; - } -}; -/** - * Pauses a file that is currently playing. If the file is not - * playing, then nothing will happen. - * - * After pausing, .play() will resume from the paused - * position. - * If p5.SoundFile had been set to loop before it was paused, - * it will continue to loop after it is unpaused with .play(). - * - * @method pause - * @for p5.SoundFile - * @param {Number} [startTime] (optional) schedule event to occur - * seconds from now - * @example - *
- * let soundFile; - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); - * } - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * text('tap to play, release to pause', 10, 20, width - 20); - * } - * function canvasPressed() { - * soundFile.loop(); - * background(0, 200, 50); - * } - * function mouseReleased() { - * soundFile.pause(); - * background(220); - * } - * - *
- */ + if (reverse) { + this.reverseBuffer(); + } + return this.playbackRate; + } -p5.SoundFile.prototype.pause = function (startTime) { - var now = master.audiocontext.currentTime; - var time = startTime || 0; - var pTime = time + now; + }, { + key: "setPitch", + value: function setPitch(num) { + var newPlaybackRate = midiToFreq(num) / midiToFreq(60); + this.rate(newPlaybackRate); + } + }, { + key: "getPlaybackRate", + value: function getPlaybackRate() { + return this.playbackRate; + } + /** + * Multiply the output volume (amplitude) of a sound file + * between 0.0 (silence) and 1.0 (full volume). + * 1.0 is the maximum amplitude of a digital sound, so multiplying + * by greater than 1.0 may cause digital distortion. To + * fade, provide a rampTime parameter. For more + * complex fades, see the Envelope class. + * + * Alternately, you can pass in a signal source such as an + * oscillator to modulate the amplitude with an audio signal. + * + * @method setVolume + * @for p5.SoundFile + * @param {Number|Object} volume Volume (amplitude) between 0.0 + * and 1.0 or modulating signal/oscillator + * @param {Number} [rampTime] Fade for t seconds + * @param {Number} [timeFromNow] Schedule this event to happen at + * t seconds in the future + */ + + }, { + key: "setVolume", + value: function setVolume(vol, _rampTime, _tFromNow) { + if (typeof vol === 'number') { + var rampTime = _rampTime || 0; + var tFromNow = _tFromNow || 0; + var now = master.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now + tFromNow); + this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); + } else if (vol) { + vol.connect(this.output.gain); + } else { + return this.output.gain; + } + } + /** + * Returns the duration of a sound file in seconds. + * + * @method duration + * @for p5.SoundFile + * @return {Number} The duration of the soundFile in seconds. + */ + + }, { + key: "duration", + value: function duration() { + if (this.buffer) { + return this.buffer.duration; + } else { + return 0; + } + } + /** + * Return the current position of the p5.SoundFile playhead, in seconds. + * Time is relative to the normal buffer direction, so if `reverseBuffer` + * has been called, currentTime will count backwards. + * + * @method currentTime + * @for p5.SoundFile + * @return {Number} currentTime of the soundFile in seconds. + */ + + }, { + key: "currentTime", + value: function currentTime() { + return this.reversed ? Math.abs(this._lastPos - this.buffer.length) / soundfile_ac.sampleRate : this._lastPos / soundfile_ac.sampleRate; + } + /** + * Move the playhead of a soundfile that is currently playing to a + * new position and a new duration, in seconds. + * If none are given, will reset the file to play entire duration + * from start to finish. To set the position of a soundfile that is + * not currently playing, use the `play` or `loop` methods. + * + * @method jump + * @for p5.SoundFile + * @param {Number} cueTime cueTime of the soundFile in seconds. + * @param {Number} duration duration in seconds. + */ + + }, { + key: "jump", + value: function jump(cueTime, duration) { + if (cueTime < 0 || cueTime > this.buffer.duration) { + throw 'jump time out of range'; + } - if (this.isPlaying() && this.buffer && this.bufferSourceNode) { - this._paused = true; - this._playing = false; - this.pauseTime = this.currentTime(); - this.bufferSourceNode.stop(pTime); + if (duration > this.buffer.duration - cueTime) { + throw 'end time out of range'; + } - this._counterNode.stop(pTime); + var cTime = cueTime || 0; + var dur = duration || undefined; - this._pauseTime = this.currentTime(); - } else { - this._pauseTime = 0; - } -}; -/** - * Loop the p5.SoundFile. Accepts optional parameters to set the - * playback rate, playback volume, loopStart, loopEnd. - * - * @method loop - * @for p5.SoundFile - * @param {Number} [startTime] (optional) schedule event to occur - * seconds from now - * @param {Number} [rate] (optional) playback rate - * @param {Number} [amp] (optional) playback volume - * @param {Number} [cueLoopStart] (optional) startTime in seconds - * @param {Number} [duration] (optional) loop duration in seconds - * @example - *
- * let soundFile; - * let loopStart = 0.5; - * let loopDuration = 0.2; - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); - * } - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * text('tap to play, release to pause', 10, 20, width - 20); - * } - * function canvasPressed() { - * soundFile.loop(); - * background(0, 200, 50); - * } - * function mouseReleased() { - * soundFile.pause(); - * background(220); - * } - * - *
- */ + if (this.isPlaying()) { + this.stop(0); + this.play(0, this.playbackRate, this.output.gain.value, cTime, dur); + } + } + /** + * Return the number of channels in a sound file. + * For example, Mono = 1, Stereo = 2. + * + * @method channels + * @for p5.SoundFile + * @return {Number} [channels] + */ + + }, { + key: "channels", + value: function channels() { + return this.buffer.numberOfChannels; + } + /** + * Return the sample rate of the sound file. + * + * @method sampleRate + * @for p5.SoundFile + * @return {Number} [sampleRate] + */ + + }, { + key: "sampleRate", + value: function sampleRate() { + return this.buffer.sampleRate; + } + /** + * Return the number of samples in a sound file. + * Equal to sampleRate * duration. + * + * @method frames + * @for p5.SoundFile + * @return {Number} [sampleCount] + */ + + }, { + key: "frames", + value: function frames() { + return this.buffer.length; + } + /** + * Returns an array of amplitude peaks in a p5.SoundFile that can be + * used to draw a static waveform. Scans through the p5.SoundFile's + * audio buffer to find the greatest amplitudes. Accepts one + * parameter, 'length', which determines size of the array. + * Larger arrays result in more precise waveform visualizations. + * + * Inspired by Wavesurfer.js. + * + * @method getPeaks + * @for p5.SoundFile + * @params {Number} [length] length is the size of the returned array. + * Larger length results in more precision. + * Defaults to 5*width of the browser window. + * @returns {Float32Array} Array of peaks. + */ + + }, { + key: "getPeaks", + value: function getPeaks(length) { + if (this.buffer) { + if (!length) { + length = window.width * 5; + } + if (this.buffer) { + var buffer = this.buffer; + var sampleSize = buffer.length / length; + var sampleStep = ~~(sampleSize / 10) || 1; + var channels = buffer.numberOfChannels; + var peaks = new Float32Array(Math.round(length)); + + for (var c = 0; c < channels; c++) { + var chan = buffer.getChannelData(c); + + for (var i = 0; i < length; i++) { + var start = ~~(i * sampleSize); + var end = ~~(start + sampleSize); + var max = 0; + + for (var j = start; j < end; j += sampleStep) { + var value = chan[j]; + + if (value > max) { + max = value; + } else if (-value > max) { + max = value; + } + } + + if (c === 0 || Math.abs(max) > peaks[i]) { + peaks[i] = max; + } + } + } -p5.SoundFile.prototype.loop = function (startTime, rate, amp, loopStart, duration) { - this._looping = true; - this.play(startTime, rate, amp, loopStart, duration); -}; -/** - * Set a p5.SoundFile's looping flag to true or false. If the sound - * is currently playing, this change will take effect when it - * reaches the end of the current playback. - * - * @method setLoop - * @for p5.SoundFile - * @param {Boolean} Boolean set looping to true or false - */ + return peaks; + } + } else { + throw 'Cannot load peaks yet, buffer is not loaded'; + } + } + /** + * Reverses the p5.SoundFile's buffer source. + * Playback must be handled separately (see example). + * + * @method reverseBuffer + * @for p5.SoundFile + * @example + *
+ * let drum; + * function preload() { + * drum = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * background(220); + * text('tap to play', 20, 20); + * } + * + * function canvasPressed() { + * drum.stop(); + * drum.reverseBuffer(); + * drum.play(); + * } + * + *
+ */ + + }, { + key: "reverseBuffer", + value: function reverseBuffer() { + if (this.buffer) { + var currentPos = this._lastPos / soundfile_ac.sampleRate; + var curVol = this.getVolume(); + this.setVolume(0, 0.001); + var numChannels = this.buffer.numberOfChannels; + + for (var i = 0; i < numChannels; i++) { + this.buffer.getChannelData(i).reverse(); + } -p5.SoundFile.prototype.setLoop = function (bool) { - if (bool === true) { - this._looping = true; - } else if (bool === false) { - this._looping = false; - } else { - throw 'Error: setLoop accepts either true or false'; - } + this.reversed = !this.reversed; - if (this.bufferSourceNode) { - this.bufferSourceNode.loop = this._looping; - this._counterNode.loop = this._looping; - } -}; -/** - * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not. - * - * @method isLooping - * @for p5.SoundFile - * @return {Boolean} - */ + if (this.isPlaying() && currentPos) { + this.jump(this.duration() - currentPos); + } + this.setVolume(curVol, 0.001); + } else { + throw 'SoundFile is not done loading'; + } + } + /** + * Schedule an event to be called when the soundfile + * reaches the end of a buffer. If the soundfile is + * playing through once, this will be called when it + * ends. If it is looping, it will be called when + * stop is called. + * + * @method onended + * @for p5.SoundFile + * @param {Function} callback function to call when the + * soundfile has ended. + */ + + }, { + key: "onended", + value: function onended(callback) { + this._onended = callback; + return this; + } + }, { + key: "add", + value: function add() { + } + }, { + key: "dispose", + value: function dispose() { + var now = master.audiocontext.currentTime; + + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + this.stop(now); + + if (this.buffer && this.bufferSourceNode) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + if (this.bufferSourceNodes[i] !== null) { + this.bufferSourceNodes[i].disconnect(); + + try { + this.bufferSourceNodes[i].stop(now); + } catch (e) { + console.warn('no buffer source node to dispose'); + } -p5.SoundFile.prototype.isLooping = function () { - if (!this.bufferSourceNode) { - return false; - } + this.bufferSourceNodes[i] = null; + } + } - if (this._looping === true && this.isPlaying() === true) { - return true; - } + if (this.isPlaying()) { + try { + this._counterNode.stop(now); + } catch (e) { + console.log(e); + } - return false; -}; -/** - * Returns true if a p5.SoundFile is playing, false if not (i.e. - * paused or stopped). - * - * @method isPlaying - * @for p5.SoundFile - * @return {Boolean} - */ + this._counterNode = null; + } + } + if (this.output) { + this.output.disconnect(); + this.output = null; + } -p5.SoundFile.prototype.isPlaying = function () { - return this._playing; -}; -/** - * Returns true if a p5.SoundFile is paused, false if not (i.e. - * playing or stopped). - * - * @method isPaused - * @for p5.SoundFile - * @return {Boolean} - */ + if (this.panner) { + this.panner.disconnect(); + this.panner = null; + } + } + /** + * Connects the output of a p5sound object to input of another + * p5.sound object. For example, you may connect a p5.SoundFile to an + * FFT or an Effect. If no parameter is given, it will connect to + * the master output. Most p5sound objects connect to the master + * output when they are created. + * + * @method connect + * @for p5.SoundFile + * @param {Object} [object] Audio object that accepts an input + */ + + }, { + key: "connect", + value: function connect(unit) { + if (!unit) { + this.panner.connect(master.input); + } else { + if (unit.hasOwnProperty('input')) { + this.panner.connect(unit.input); + } else { + this.panner.connect(unit); + } + } + } + /** + * Disconnects the output of this p5sound object. + * + * @method disconnect + * @for p5.SoundFile + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.panner) { + this.panner.disconnect(); + } + } + /** + */ + }, { + key: "getLevel", + value: function getLevel() { + console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'); + } + /** + * Reset the source for this SoundFile to a + * new path (URL). + * + * @method setPath + * @for p5.SoundFile + * @param {String} path path to audio file + * @param {Function} callback Callback + */ + + }, { + key: "setPath", + value: function setPath(p, callback) { + var path = p5.prototype._checkFileFormats(p); -p5.SoundFile.prototype.isPaused = function () { - return this._paused; -}; -/** - * Stop soundfile playback. - * - * @method stop - * @for p5.SoundFile - * @param {Number} [startTime] (optional) schedule event to occur - * in seconds from now - */ + this.url = path; + this.load(callback); + } + /** + * Replace the current Audio Buffer with a new Buffer. + * + * @method setBuffer + * @for p5.SoundFile + * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays + * will create a stereo source. 1 will create + * a mono source. + */ + + }, { + key: "setBuffer", + value: function setBuffer(buf) { + var numChannels = buf.length; + var size = buf[0].length; + var newBuffer = soundfile_ac.createBuffer(numChannels, size, soundfile_ac.sampleRate); + + if (!(buf[0] instanceof Float32Array)) { + buf[0] = new Float32Array(buf[0]); + } + for (var channelNum = 0; channelNum < numChannels; channelNum++) { + var channel = newBuffer.getChannelData(channelNum); + channel.set(buf[channelNum]); + } -p5.SoundFile.prototype.stop = function (timeFromNow) { - var time = timeFromNow || 0; + this.buffer = newBuffer; - if (this.mode === 'sustain' || this.mode === 'untildone') { - this.stopAll(time); - this._playing = false; - this.pauseTime = 0; - this._paused = false; - } else if (this.buffer && this.bufferSourceNode) { - var now = master.audiocontext.currentTime; - var t = time || 0; - this.pauseTime = 0; - this.bufferSourceNode.stop(now + t); + this.panner.inputChannels(numChannels); + } - this._counterNode.stop(now + t); + }, { + key: "_initCounterNode", + value: function _initCounterNode() { + var _this = this; - this._playing = false; - this._paused = false; - } -}; -/** - * Stop playback on all of this soundfile's sources. - * @private - */ + var self = this; + var now = soundfile_ac.currentTime; + var cNode = soundfile_ac.createBufferSource(); + var workletBufferSize = safeBufferSize(256); + if (self._workletNode) { + self._workletNode.disconnect(); -p5.SoundFile.prototype.stopAll = function (_time) { - var now = master.audiocontext.currentTime; - var time = _time || 0; + delete self._workletNode; + } - if (this.buffer && this.bufferSourceNode) { - for (var i in this.bufferSourceNodes) { - var bufferSourceNode = this.bufferSourceNodes[i]; + self._workletNode = new AudioWorkletNode(soundfile_ac, processorNames_default.a.soundFileProcessor, { + processorOptions: { + bufferSize: workletBufferSize + } + }); + + self._workletNode.port.onmessage = function (event) { + if (event.data.name === 'position') { + if (event.data.position === 0) { + return; + } - if (bufferSourceNode) { - try { - bufferSourceNode.stop(now + time); - } catch (e) { + _this._lastPos = event.data.position; + + _this._onTimeUpdate(self._lastPos); } - } + }; + + + cNode.buffer = _createCounterBuffer(self.buffer); + cNode.playbackRate.setValueAtTime(self.playbackRate, now); + cNode.connect(self._workletNode); + + self._workletNode.connect(p5.soundOut._silentNode); + + return cNode; + } + + }, { + key: "_initSourceNode", + value: function _initSourceNode() { + var bufferSourceNode = soundfile_ac.createBufferSource(); + bufferSourceNode.buffer = this.buffer; + bufferSourceNode.playbackRate.value = this.playbackRate; + bufferSourceNode.connect(this.output); + return bufferSourceNode; } + /** + * processPeaks returns an array of timestamps where it thinks there is a beat. + * + * This is an asynchronous function that processes the soundfile in an offline audio context, + * and sends the results to your callback function. + * + * The process involves running the soundfile through a lowpass filter, and finding all of the + * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, + * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. + * + * @method processPeaks + * @for p5.SoundFile + * @param {Function} callback a function to call once this data is returned + * @param {Number} [initThreshold] initial threshold defaults to 0.9 + * @param {Number} [minThreshold] minimum threshold defaults to 0.22 + * @param {Number} [minPeaks] minimum number of peaks defaults to 200 + * @return {Array} Array of timestamped peaks + */ + + }, { + key: "processPeaks", + value: function processPeaks(callback, _initThreshold, _minThreshold, _minPeaks) { + var bufLen = this.buffer.length; + var sampleRate = this.buffer.sampleRate; + var buffer = this.buffer; + var allPeaks = []; + var initialThreshold = _initThreshold || 0.9, + threshold = initialThreshold, + minThreshold = _minThreshold || 0.22, + minPeaks = _minPeaks || 200; - this._counterNode.stop(now + time); + var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate); - this._onended(this); - } -}; -/** - * Multiply the output volume (amplitude) of a sound file - * between 0.0 (silence) and 1.0 (full volume). - * 1.0 is the maximum amplitude of a digital sound, so multiplying - * by greater than 1.0 may cause digital distortion. To - * fade, provide a rampTime parameter. For more - * complex fades, see the Envelope class. - * - * Alternately, you can pass in a signal source such as an - * oscillator to modulate the amplitude with an audio signal. - * - * @method setVolume - * @for p5.SoundFile - * @param {Number|Object} volume Volume (amplitude) between 0.0 - * and 1.0 or modulating signal/oscillator - * @param {Number} [rampTime] Fade for t seconds - * @param {Number} [timeFromNow] Schedule this event to happen at - * t seconds in the future - */ + var source = offlineContext.createBufferSource(); + source.buffer = buffer; + var filter = offlineContext.createBiquadFilter(); + filter.type = 'lowpass'; + source.connect(filter); + filter.connect(offlineContext.destination); -p5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) { - if (typeof vol === 'number') { - var rampTime = _rampTime || 0; - var tFromNow = _tFromNow || 0; - var now = master.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now + tFromNow); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(this.output.gain); - } else { - return this.output.gain; - } -}; + source.start(0); + offlineContext.startRendering(); + offlineContext.oncomplete = function (e) { + if (!self.panner) return; + var filteredBuffer = e.renderedBuffer; + var bufferData = filteredBuffer.getChannelData(0); -p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume; + do { + allPeaks = getPeaksAtThreshold(bufferData, threshold); + threshold -= 0.005; + } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold); -p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume; -p5.SoundFile.prototype.getVolume = function () { - return this.output.gain.value; -}; -/** - * Set the stereo panning of a p5.sound object to - * a floating point number between -1.0 (left) and 1.0 (right). - * Default is 0.0 (center). - * - * @method pan - * @for p5.SoundFile - * @param {Number} [panValue] Set the stereo panner - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @example - *
- * let ballX = 0; - * let soundFile; - * - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/beatbox.mp3'); - * } - * - * function draw() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * ballX = constrain(mouseX, 0, width); - * ellipse(ballX, height/2, 20, 20); - * } - * - * function canvasPressed(){ - * // map the ball's x location to a panning degree - * // between -1.0 (left) and 1.0 (right) - * let panning = map(ballX, 0., width,-1.0, 1.0); - * soundFile.pan(panning); - * soundFile.play(); - * } - *
- */ + var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); + var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate); -p5.SoundFile.prototype.pan = function (pval, tFromNow) { - this.panPosition = pval; - this.panner.pan(pval, tFromNow); -}; -/** - * Returns the current stereo pan position (-1.0 to 1.0) - * - * @method getPan - * @for p5.SoundFile - * @return {Number} Returns the stereo pan setting of the Oscillator - * as a number between -1.0 (left) and 1.0 (right). - * 0.0 is center and default. - */ + var topTempos = groups.sort(function (intA, intB) { + return intB.count - intA.count; + }).splice(0, 5); + this.tempo = topTempos[0].tempo; -p5.SoundFile.prototype.getPan = function () { - return this.panPosition; -}; + var bpmVariance = 5; + var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance); + callback(tempoPeaks); + }; + } + /** + * Schedule events to trigger every time a MediaElement + * (audio/video) reaches a playback cue point. + * + * Accepts a callback function, a time (in seconds) at which to trigger + * the callback, and an optional parameter for the callback. + * + * Time will be passed as the first parameter to the callback function, + * and param will be the second parameter. + * + * + * @method addCue + * @for p5.SoundFile + * @param {Number} time Time in seconds, relative to this media + * element's playback. For example, to trigger + * an event every time playback reaches two + * seconds, pass in the number 2. This will be + * passed as the first parameter to + * the callback function. + * @param {Function} callback Name of a function that will be + * called at the given time. The callback will + * receive time and (optionally) param as its + * two parameters. + * @param {Object} [value] An object to be passed as the + * second parameter to the + * callback function. + * @return {Number} id ID of this cue, + * useful for removeCue(id) + * @example + *
+ * let mySound; + * function preload() { + * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * background(220); + * text('tap to play', 10, 20); + * + * // schedule calls to changeText + * mySound.addCue(0, changeText, "hello" ); + * mySound.addCue(0.5, changeText, "hello," ); + * mySound.addCue(1, changeText, "hello, p5!"); + * mySound.addCue(1.5, changeText, "hello, p5!!"); + * mySound.addCue(2, changeText, "hello, p5!!!!!"); + * } + * + * function changeText(val) { + * background(220); + * text(val, 10, 20); + * } + * + * function canvasPressed() { + * mySound.play(); + * } + *
+ */ + + }, { + key: "addCue", + value: function addCue(time, callback, val) { + var id = this._cueIDCounter++; + var cue = new Cue(callback, time, id, val); + + this._cues.push(cue); + + + return id; + } + /** + * Remove a callback based on its ID. The ID is returned by the + * addCue method. + * + * @method removeCue + * @for p5.SoundFile + * @param {Number} id ID of the cue, as returned by addCue + */ + + }, { + key: "removeCue", + value: function removeCue(id) { + var cueLength = this._cues.length; + + for (var i = 0; i < cueLength; i++) { + var cue = this._cues[i]; + + if (cue.id === id) { + this._cues.splice(i, 1); + + break; + } + } + + if (this._cues.length === 0) { + } + } + /** + * Remove all of the callbacks that had originally been scheduled + * via the addCue method. + * + * @method clearCues + */ + + }, { + key: "clearCues", + value: function clearCues() { + this._cues = []; + } + + }, { + key: "_onTimeUpdate", + value: function _onTimeUpdate(position) { + var playbackTime = position / this.buffer.sampleRate; + var cueLength = this._cues.length; + + for (var i = 0; i < cueLength; i++) { + var cue = this._cues[i]; + var callbackTime = cue.time; + var val = cue.val; + var leftLimit = this._prevUpdateTime || 0; + var rightLimit = playbackTime; + + if (leftLimit <= callbackTime && callbackTime <= rightLimit) { + cue.callback(val); + } + } + + this._prevUpdateTime = playbackTime; + } + /** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. To upload a file to a server, see + * getBlob + * + * @method save + * @for p5.SoundFile + * @param {String} [fileName] name of the resulting .wav file. + * @example + *
+ * let mySound; + * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(canvasPressed); + * background(220); + * text('tap to download', 10, 20); + * } + * + * function canvasPressed() { + * mySound.save('my cool filename'); + * } + *
+ */ + + }, { + key: "save", + value: function save(fileName) { + p5.prototype.saveSound(this, fileName, 'wav'); + } + /** + * This method is useful for sending a SoundFile to a server. It returns the + * .wav-encoded audio data as a "Blob". + * A Blob is a file-like data object that can be uploaded to a server + * with an http request. We'll + * use the `httpDo` options object to send a POST request with some + * specific options: we encode the request as `multipart/form-data`, + * and attach the blob as one of the form values using `FormData`. + * + * + * @method getBlob + * @for p5.SoundFile + * @returns {Blob} A file-like data object + * @example + *
+ * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } + * + * function setup() { + * noCanvas(); + * let soundBlob = mySound.getBlob(); + * + * // Now we can send the blob to a server... + * let serverUrl = 'https://jsonplaceholder.typicode.com/posts'; + * let httpRequestOptions = { + * method: 'POST', + * body: new FormData().append('soundBlob', soundBlob), + * headers: new Headers({ + * 'Content-Type': 'multipart/form-data' + * }) + * }; + * httpDo(serverUrl, httpRequestOptions); + * + * // We can also create an `ObjectURL` pointing to the Blob + * let blobUrl = URL.createObjectURL(soundBlob); + * + * // The `
+ */ + + }, { + key: "getBlob", + value: function getBlob() { + var dataView = convertToWav(this.buffer); + return new Blob([dataView], { + type: 'audio/wav' + }); + } + }]); + + return SoundFile; +}(); /** - * Set the playback rate of a sound file. Will change the speed and the pitch. - * Values less than zero will reverse the audio buffer. - * - * @method rate - * @for p5.SoundFile - * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal, - * .5 is half-speed, 2.0 is twice as fast. - * Values less than zero play backwards. + * loadSound() returns a new p5.SoundFile from a specified + * path. If called during preload(), the p5.SoundFile will be ready + * to play in time for setup() and draw(). If called outside of + * preload, the p5.SoundFile will not be ready immediately, so + * loadSound accepts a callback as the second parameter. Using a + * + * local server is recommended when loading external files. + * + * @method loadSound + * @for p5 + * @param {String|Array} path Path to the sound file, or an array with + * paths to soundfiles in multiple formats + * i.e. ['sound.ogg', 'sound.mp3']. + * Alternately, accepts an object: either + * from the HTML5 File API, or a p5.File. + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if there is + * an error loading the file. + * @param {Function} [whileLoading] Name of a function to call while file is loading. + * This function will receive the percentage loaded + * so far, from 0.0 to 1.0. + * @return {SoundFile} Returns a p5.SoundFile * @example *
* let mySound; - * * function preload() { - * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); + * soundFormats('mp3', 'ogg'); + * mySound = loadSound('assets/doorbell'); * } * * function setup() { * let cnv = createCanvas(100, 100); * cnv.mousePressed(canvasPressed); - * } - * function canvasPressed() { - * mySound.loop(); - * } - * function mouseReleased() { - * mySound.pause(); - * } - * function draw() { * background(220); - * - * // Set the rate to a range between 0.1 and 4 - * // Changing the rate also alters the pitch - * let playbackRate = map(mouseY, 0.1, height, 2, 0); - * playbackRate = constrain(playbackRate, 0.01, 4); - * mySound.rate(playbackRate); - * - * line(0, mouseY, width, mouseY); - * text('rate: ' + round(playbackRate * 100) + '%', 10, 20); + * text('tap here to play', 10, 20); * } * - * - *
- * + * function canvasPressed() { + * // playing a sound file on a user gesture + * // is equivalent to `userStartAudio()` + * mySound.play(); + * } + * */ -p5.SoundFile.prototype.rate = function (playbackRate) { - var reverse = false; - - if (typeof playbackRate === 'undefined') { - return this.playbackRate; +function loadSound(path, callback, onerror, whileLoading) { + if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { + window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); } - this.playbackRate = playbackRate; + var self = this; + var s = new soundfile_SoundFile(path, function () { + if (typeof callback === 'function') { + callback.apply(self, arguments); + } - if (playbackRate === 0) { - playbackRate = 0.0000000000001; - } else if (playbackRate < 0 && !this.reversed) { - playbackRate = Math.abs(playbackRate); - reverse = true; - } else if (playbackRate > 0 && this.reversed) { - reverse = true; - } + if (typeof self._decrementPreload === 'function') { + self._decrementPreload(); + } + }, onerror, whileLoading); + return s; +} - if (this.bufferSourceNode) { - var now = master.audiocontext.currentTime; - this.bufferSourceNode.playbackRate.cancelScheduledValues(now); - this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); + var soundfile = (soundfile_SoundFile); - this._counterNode.playbackRate.cancelScheduledValues(now); +function amplitude_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); - } +function amplitude_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); } } - if (reverse) { - this.reverseBuffer(); - } +function amplitude_createClass(Constructor, protoProps, staticProps) { if (protoProps) amplitude_defineProperties(Constructor.prototype, protoProps); if (staticProps) amplitude_defineProperties(Constructor, staticProps); return Constructor; } - return this.playbackRate; -}; -p5.SoundFile.prototype.setPitch = function (num) { - var newPlaybackRate = midiToFreq(num) / midiToFreq(60); - this.rate(newPlaybackRate); -}; -p5.SoundFile.prototype.getPlaybackRate = function () { - return this.playbackRate; -}; /** - * Returns the duration of a sound file in seconds. + * Amplitude measures volume between 0.0 and 1.0. + * Listens to all p5sound by default, or use setInput() + * to listen to a specific sound source. Accepts an optional + * smoothing value, which defaults to 0. * - * @method duration - * @for p5.SoundFile - * @return {Number} The duration of the soundFile in seconds. - */ - - -p5.SoundFile.prototype.duration = function () { - if (this.buffer) { - return this.buffer.duration; - } else { - return 0; - } -}; -/** - * Return the current position of the p5.SoundFile playhead, in seconds. - * Time is relative to the normal buffer direction, so if `reverseBuffer` - * has been called, currentTime will count backwards. + * @class p5.Amplitude + * @constructor + * @param {Number} [smoothing] between 0.0 and .999 to smooth + * amplitude readings (defaults to 0) + * @example + *
+ * let sound, amplitude; * - * @method currentTime - * @for p5.SoundFile - * @return {Number} currentTime of the soundFile in seconds. - */ - - -p5.SoundFile.prototype.currentTime = function () { - return this.reversed ? Math.abs(this._lastPos - this.buffer.length) / soundfile_ac.sampleRate : this._lastPos / soundfile_ac.sampleRate; -}; -/** - * Move the playhead of a soundfile that is currently playing to a - * new position and a new duration, in seconds. - * If none are given, will reset the file to play entire duration - * from start to finish. To set the position of a soundfile that is - * not currently playing, use the `play` or `loop` methods. - * - * @method jump - * @for p5.SoundFile - * @param {Number} cueTime cueTime of the soundFile in seconds. - * @param {Number} duration duration in seconds. - */ - - -p5.SoundFile.prototype.jump = function (cueTime, duration) { - if (cueTime < 0 || cueTime > this.buffer.duration) { - throw 'jump time out of range'; - } + * function preload(){ + * sound = loadSound('assets/beat.mp3'); + * } + * function setup() { + * let cnv = createCanvas(100,100); + * cnv.mouseClicked(toggleSound); + * amplitude = new p5.Amplitude(); + * } + * + * function draw() { + * background(220); + * text('tap to play', 20, 20); + * + * let level = amplitude.getLevel(); + * let size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * + * function togglePlay() { + * if (sound.isPlaying() ){ + * sound.pause(); + * } else { + * sound.loop(); + * amplitude = new p5.Amplitude(); + * amplitude.setInput(sound); + * } + * } + * + *
+ */ - if (duration > this.buffer.duration - cueTime) { - throw 'end time out of range'; - } +var amplitude_Amplitude = +function () { + function Amplitude(smoothing) { + amplitude_classCallCheck(this, Amplitude); - var cTime = cueTime || 0; - var dur = duration || undefined; + this.bufferSize = safeBufferSize(2048); - if (this.isPlaying()) { - this.stop(0); - this.play(0, this.playbackRate, this.output.gain.value, cTime, dur); - } -}; -/** - * Return the number of channels in a sound file. - * For example, Mono = 1, Stereo = 2. - * - * @method channels - * @for p5.SoundFile - * @return {Number} [channels] - */ + this.audiocontext = master.audiocontext; + this._workletNode = new AudioWorkletNode(this.audiocontext, processorNames_default.a.amplitudeProcessor, { + outputChannelCount: [1], + parameterData: { + smoothing: smoothing || 0 + }, + processorOptions: { + normalize: false, + smoothing: smoothing || 0, + numInputChannels: 2, + bufferSize: this.bufferSize + } + }); + 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); -p5.SoundFile.prototype.channels = function () { - return this.buffer.numberOfChannels; -}; -/** - * Return the sample rate of the sound file. - * - * @method sampleRate - * @for p5.SoundFile - * @return {Number} [sampleRate] - */ + this.input = this._workletNode; + this.output = this.audiocontext.createGain(); -p5.SoundFile.prototype.sampleRate = function () { - return this.buffer.sampleRate; -}; -/** - * Return the number of samples in a sound file. - * Equal to sampleRate * duration. - * - * @method frames - * @for p5.SoundFile - * @return {Number} [sampleCount] - */ + this.volume = 0; + this.volNorm = 0; + this.stereoVol = [0, 0]; + this.stereoVolNorm = [0, 0]; + this.normalize = false; + this._workletNode.connect(this.output); -p5.SoundFile.prototype.frames = function () { - return this.buffer.length; -}; -/** - * Returns an array of amplitude peaks in a p5.SoundFile that can be - * used to draw a static waveform. Scans through the p5.SoundFile's - * audio buffer to find the greatest amplitudes. Accepts one - * parameter, 'length', which determines size of the array. - * Larger arrays result in more precise waveform visualizations. - * - * Inspired by Wavesurfer.js. - * - * @method getPeaks - * @for p5.SoundFile - * @params {Number} [length] length is the size of the returned array. - * Larger length results in more precision. - * Defaults to 5*width of the browser window. - * @returns {Float32Array} Array of peaks. - */ + this.output.gain.value = 0; + this.output.connect(this.audiocontext.destination); -p5.SoundFile.prototype.getPeaks = function (length) { - if (this.buffer) { - if (!length) { - length = window.width * 5; - } + master.meter.connect(this._workletNode); + + master.soundArray.push(this); + } + /** + * Connects to the p5sound instance (master output) by default. + * Optionally, you can pass in a specific source (i.e. a soundfile). + * + * @method setInput + * @for p5.Amplitude + * @param {soundObject|undefined} [snd] set the sound source + * (optional, defaults to + * master output) + * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0 + * to smooth amplitude readings + * @example + *
+ * function preload(){ + * sound1 = loadSound('assets/beat.mp3'); + * sound2 = loadSound('assets/drum.mp3'); + * } + * function setup(){ + * cnv = createCanvas(100, 100); + * cnv.mouseClicked(toggleSound); + * + * amplitude = new p5.Amplitude(); + * amplitude.setInput(sound2); + * } + * + * function draw() { + * background(220); + * text('tap to play', 20, 20); + * + * let level = amplitude.getLevel(); + * let size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * + * function toggleSound(){ + * if (sound1.isPlaying() && sound2.isPlaying()) { + * sound1.stop(); + * sound2.stop(); + * } else { + * sound1.play(); + * sound2.play(); + * } + * } + *
+ */ - if (this.buffer) { - var buffer = this.buffer; - var sampleSize = buffer.length / length; - var sampleStep = ~~(sampleSize / 10) || 1; - var channels = buffer.numberOfChannels; - var peaks = new Float32Array(Math.round(length)); - - for (var c = 0; c < channels; c++) { - var chan = buffer.getChannelData(c); - - for (var i = 0; i < length; i++) { - var start = ~~(i * sampleSize); - var end = ~~(start + sampleSize); - var max = 0; - - for (var j = start; j < end; j += sampleStep) { - var value = chan[j]; - - if (value > max) { - max = value; - } else if (-value > max) { - max = value; - } - } - if (c === 0 || Math.abs(max) > peaks[i]) { - peaks[i] = max; + amplitude_createClass(Amplitude, [{ + key: "setInput", + value: function setInput(source, smoothing) { + master.meter.disconnect(); + + if (smoothing) { + this._workletNode.parameters.get('smoothing').value = smoothing; + } + + + if (source == null) { + console.log('Amplitude input source is not ready! Connecting to master output instead'); + master.meter.connect(this._workletNode); + } + else if (source) { + source.connect(this._workletNode); + + this._workletNode.disconnect(); + + this._workletNode.connect(this.output); + } + else { + master.meter.connect(this._workletNode); } + } + }, { + key: "connect", + value: function connect(unit) { + if (unit) { + if (unit.hasOwnProperty('input')) { + this.output.connect(unit.input); + } else { + this.output.connect(unit); + } + } else { + this.output.connect(this.panner.connect(master.input)); + } + } + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + } + /** + * Returns a single Amplitude reading at the moment it is called. + * For continuous readings, run in the draw loop. + * + * @method getLevel + * @for p5.Amplitude + * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right) + * @return {Number} Amplitude as a number between 0.0 and 1.0 + * @example + *
+ * function preload(){ + * sound = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mouseClicked(toggleSound); + * amplitude = new p5.Amplitude(); + * } + * + * function draw() { + * background(220, 150); + * textAlign(CENTER); + * text('tap to play', width/2, 20); + * + * let level = amplitude.getLevel(); + * let size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * + * function toggleSound(){ + * if (sound.isPlaying()) { + * sound.stop(); + * } else { + * sound.play(); + * } + * } + *
+ */ + + }, { + key: "getLevel", + value: function getLevel(channel) { + if (typeof channel !== 'undefined') { + if (this.normalize) { + return this.stereoVolNorm[channel]; + } else { + return this.stereoVol[channel]; } + } else if (this.normalize) { + return this.volNorm; + } else { + return this.volume; + } + } + /** + * Determines whether the results of Amplitude.process() will be + * Normalized. To normalize, Amplitude finds the difference the + * loudest reading it has processed and the maximum amplitude of + * 1.0. Amplitude adds this difference to all values to produce + * results that will reliably map between 0.0 and 1.0. However, + * if a louder moment occurs, the amount that Normalize adds to + * all the values will change. Accepts an optional boolean parameter + * (true or false). Normalizing is off by default. + * + * @method toggleNormalize + * @for p5.Amplitude + * @param {boolean} [boolean] set normalize to true (1) or false (0) + */ + + }, { + key: "toggleNormalize", + value: function toggleNormalize(bool) { + if (typeof bool === 'boolean') { + this.normalize = bool; + } else { + this.normalize = !this.normalize; } - return peaks; + this._workletNode.port.postMessage({ + name: 'toggleNormalize', + normalize: this.normalize + }); } - } else { - throw 'Cannot load peaks yet, buffer is not loaded'; - } -}; + /** + * Smooth Amplitude analysis by averaging with the last analysis + * frame. Off by default. + * + * @method smooth + * @for p5.Amplitude + * @param {Number} set smoothing from 0.0 <= 1 + */ + + }, { + key: "smooth", + value: function smooth(s) { + if (s >= 0 && s < 1) { + this._workletNode.port.postMessage({ + name: 'smoothing', + smoothing: s + }); + } else { + console.log('Error: smoothing must be between 0 and 1'); + } + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + + if (this.input) { + this.input.disconnect(); + delete this.input; + } + + if (this.output) { + this.output.disconnect(); + delete this.output; + } + + this._workletNode.disconnect(); + + delete this._workletNode; + } + }]); + + return Amplitude; +}(); + + var amplitude = (amplitude_Amplitude); +function fft_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function fft_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); } } + +function fft_createClass(Constructor, protoProps, staticProps) { if (protoProps) fft_defineProperties(Constructor.prototype, protoProps); if (staticProps) fft_defineProperties(Constructor, staticProps); return Constructor; } + + /** - * Reverses the p5.SoundFile's buffer source. - * Playback must be handled separately (see example). + *

FFT (Fast Fourier Transform) is an analysis algorithm that + * isolates individual + * + * audio frequencies within a waveform.

+ * + *

Once instantiated, a p5.FFT object can return an array based on + * two types of analyses:
• FFT.waveform() computes + * amplitude values along the time domain. The array indices correspond + * to samples across a brief moment in time. Each value represents + * amplitude of the waveform at that sample of time.
+ * • FFT.analyze() computes amplitude values along the + * frequency domain. The array indices correspond to frequencies (i.e. + * pitches), from the lowest to the highest that humans can hear. Each + * value represents amplitude at that slice of the frequency spectrum. + * Use with getEnergy() to measure amplitude at specific + * frequencies, or within a range of frequencies.

+ * + *

FFT analyzes a very short snapshot of sound called a sample + * buffer. It returns an array of amplitude measurements, referred + * to as bins. The array is 1024 bins long by default. + * You can change the bin array length, but it must be a power of 2 + * between 16 and 1024 in order for the FFT algorithm to function + * correctly. The actual size of the FFT buffer is twice the + * number of bins, so given a standard sample rate, the buffer is + * 2048/44100 seconds long.

+ * * - * @method reverseBuffer - * @for p5.SoundFile + * @class p5.FFT + * @constructor + * @param {Number} [smoothing] Smooth results of Freq Spectrum. + * 0.0 < smoothing < 1.0. + * Defaults to 0.8. + * @param {Number} [bins] Length of resulting array. + * Must be a power of two between + * 16 and 1024. Defaults to 1024. * @example *
- * let drum; - * function preload() { - * drum = loadSound('assets/drum.mp3'); + * function preload(){ + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); * } * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); + * function setup(){ + * let cnv = createCanvas(100,100); + * cnv.mouseClicked(togglePlay); + * fft = new p5.FFT(); + * sound.amp(0.2); + * } + * + * function draw(){ * background(220); + * + * let spectrum = fft.analyze(); + * noStroke(); + * fill(255, 0, 255); + * for (let i = 0; i< spectrum.length; i++){ + * let x = map(i, 0, spectrum.length, 0, width); + * let h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width / spectrum.length, h ) + * } + * + * let waveform = fft.waveform(); + * noFill(); + * beginShape(); + * stroke(20); + * for (let i = 0; i < waveform.length; i++){ + * let x = map(i, 0, waveform.length, 0, width); + * let y = map( waveform[i], -1, 1, 0, height); + * vertex(x,y); + * } + * endShape(); + * * text('tap to play', 20, 20); * } * - * function canvasPressed() { - * drum.stop(); - * drum.reverseBuffer(); - * drum.play(); + * function togglePlay() { + * if (sound.isPlaying()) { + * sound.pause(); + * } else { + * sound.loop(); + * } * } - * - *
+ * */ +var fft_FFT = +function () { + function FFT(smoothing, bins) { + fft_classCallCheck(this, FFT); + + this.input = this.analyser = master.audiocontext.createAnalyser(); + Object.defineProperties(this, { + bins: { + get: function get() { + return this.analyser.fftSize / 2; + }, + set: function set(b) { + this.analyser.fftSize = b * 2; + }, + configurable: true, + enumerable: true + }, + smoothing: { + get: function get() { + return this.analyser.smoothingTimeConstant; + }, + set: function set(s) { + this.analyser.smoothingTimeConstant = s; + }, + configurable: true, + enumerable: true + } + }); -p5.SoundFile.prototype.reverseBuffer = function () { - if (this.buffer) { - var currentPos = this._lastPos / soundfile_ac.sampleRate; - var curVol = this.getVolume(); - this.setVolume(0, 0.001); - var numChannels = this.buffer.numberOfChannels; - - for (var i = 0; i < numChannels; i++) { - this.buffer.getChannelData(i).reverse(); - } - + this.smooth(smoothing); + this.bins = bins || 1024; - this.reversed = !this.reversed; + master.fftMeter.connect(this.analyser); + this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount); + this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount); - if (this.isPlaying() && currentPos) { - this.jump(this.duration() - currentPos); - } + this.bass = [20, 140]; + this.lowMid = [140, 400]; + this.mid = [400, 2600]; + this.highMid = [2600, 5200]; + this.treble = [5200, 14000]; - this.setVolume(curVol, 0.001); - } else { - throw 'SoundFile is not done loading'; + master.soundArray.push(this); } -}; -/** - * Schedule an event to be called when the soundfile - * reaches the end of a buffer. If the soundfile is - * playing through once, this will be called when it - * ends. If it is looping, it will be called when - * stop is called. - * - * @method onended - * @for p5.SoundFile - * @param {Function} callback function to call when the - * soundfile has ended. - */ + /** + * Set the input source for the FFT analysis. If no source is + * provided, FFT will analyze all sound in the sketch. + * + * @method setInput + * @for p5.FFT + * @param {Object} [source] p5.sound object (or web audio API source node) + */ -p5.SoundFile.prototype.onended = function (callback) { - this._onended = callback; - return this; -}; + fft_createClass(FFT, [{ + key: "setInput", + value: function setInput(source) { + if (!source) { + master.fftMeter.connect(this.analyser); + } else { + if (source.output) { + source.output.connect(this.analyser); + } else if (source.connect) { + source.connect(this.analyser); + } -p5.SoundFile.prototype.add = function () { -}; + master.fftMeter.disconnect(); + } + } + /** + * Returns an array of amplitude values (between -1.0 and +1.0) that represent + * a snapshot of amplitude readings in a single buffer. Length will be + * equal to bins (defaults to 1024). Can be used to draw the waveform + * of a sound. + * + * @method waveform + * @for p5.FFT + * @param {Number} [bins] Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @param {String} [precision] If any value is provided, will return results + * in a Float32 Array which is more precise + * than a regular array. + * @return {Array} Array Array of amplitude values (-1 to 1) + * over time. Array length = bins. + * + */ + + }, { + key: "waveform", + value: function waveform() { + var bins, mode; + var normalArray = new Array(); + + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === 'number') { + bins = arguments[i]; + this.analyser.fftSize = bins * 2; + } -p5.SoundFile.prototype.dispose = function () { - var now = master.audiocontext.currentTime; + if (typeof arguments[i] === 'string') { + mode = arguments[i]; + } + } - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - this.stop(now); - if (this.buffer && this.bufferSourceNode) { - for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { - if (this.bufferSourceNodes[i] !== null) { - this.bufferSourceNodes[i].disconnect(); + if (mode && !p5.prototype._isSafari()) { + timeToFloat(this, this.timeDomain); + this.analyser.getFloatTimeDomainData(this.timeDomain); + return this.timeDomain; + } else { + timeToInt(this, this.timeDomain); + this.analyser.getByteTimeDomainData(this.timeDomain); - try { - this.bufferSourceNodes[i].stop(now); - } catch (e) { - console.warn('no buffer source node to dispose'); + for (var j = 0; j < this.timeDomain.length; j++) { + var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1); + normalArray.push(scaled); } - this.bufferSourceNodes[i] = null; + return normalArray; } } + /** + * Returns an array of amplitude values (between 0 and 255) + * across the frequency spectrum. Length is equal to FFT bins + * (1024 by default). The array indices correspond to frequencies + * (i.e. pitches), from the lowest to the highest that humans can + * hear. Each value represents amplitude at that slice of the + * frequency spectrum. Must be called prior to using + * getEnergy(). + * + * @method analyze + * @for p5.FFT + * @param {Number} [bins] Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @param {Number} [scale] If "dB," returns decibel + * float measurements between + * -140 and 0 (max). + * Otherwise returns integers from 0-255. + * @return {Array} spectrum Array of energy (amplitude/volume) + * values across the frequency spectrum. + * Lowest energy (silence) = 0, highest + * possible is 255. + * @example + *
+ * let osc, fft; + * + * function setup(){ + * let cnv = createCanvas(100,100); + * cnv.mousePressed(startSound); + * osc = new p5.Oscillator(); + * osc.amp(0); + * fft = new p5.FFT(); + * } + * + * function draw(){ + * background(220); + * + * let freq = map(mouseX, 0, windowWidth, 20, 10000); + * freq = constrain(freq, 1, 20000); + * osc.freq(freq); + * + * let spectrum = fft.analyze(); + * noStroke(); + * fill(255, 0, 255); + * for (let i = 0; i< spectrum.length; i++){ + * let x = map(i, 0, spectrum.length, 0, width); + * let h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width / spectrum.length, h ); + * } + * + * stroke(255); + * if (!osc.started) { + * text('tap here and drag to change frequency', 10, 20, width - 20); + * } else { + * text(round(freq)+'Hz', 10, 20); + * } + * } + * + * function startSound() { + * osc.start(); + * osc.amp(0.5, 0.2); + * } + * + * function mouseReleased() { + * osc.amp(0, 0.2); + * } + *
+ * + * + */ + + }, { + key: "analyze", + value: function analyze() { + var mode; + + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === 'number') { + this.bins = arguments[i]; + this.analyser.fftSize = this.bins * 2; + } - if (this.isPlaying()) { - try { - this._counterNode.stop(now); - } catch (e) { - console.log(e); + if (typeof arguments[i] === 'string') { + mode = arguments[i]; + } } - this._counterNode = null; + if (mode && mode.toLowerCase() === 'db') { + freqToFloat(this); + this.analyser.getFloatFrequencyData(this.freqDomain); + return this.freqDomain; + } else { + freqToInt(this, this.freqDomain); + this.analyser.getByteFrequencyData(this.freqDomain); + var normalArray = Array.apply([], this.freqDomain); + return normalArray; + } } - } + /** + * Returns the amount of energy (volume) at a specific + * + * frequency, or the average amount of energy between two + * frequencies. Accepts Number(s) corresponding + * to frequency (in Hz), or a "string" corresponding to predefined + * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble"). + * Returns a range between 0 (no energy/volume at that frequency) and + * 255 (maximum energy). + * NOTE: analyze() must be called prior to getEnergy(). analyze() + * tells the FFT to analyze frequency data, and getEnergy() uses + * the results to determine the value at a specific frequency or + * range of frequencies.

+ * + * @method getEnergy + * @for p5.FFT + * @param {Number|String} frequency1 Will return a value representing + * energy at this frequency. Alternately, + * the strings "bass", "lowMid" "mid", + * "highMid", and "treble" will return + * predefined frequency ranges. + * @param {Number} [frequency2] If a second frequency is given, + * will return average amount of + * energy that exists between the + * two frequencies. + * @return {Number} Energy Energy (volume/amplitude) from + * 0 and 255. + * + */ + + }, { + key: "getEnergy", + value: function getEnergy(frequency1, frequency2) { + var nyquist = master.audiocontext.sampleRate / 2; + + if (frequency1 === 'bass') { + frequency1 = this.bass[0]; + frequency2 = this.bass[1]; + } else if (frequency1 === 'lowMid') { + frequency1 = this.lowMid[0]; + frequency2 = this.lowMid[1]; + } else if (frequency1 === 'mid') { + frequency1 = this.mid[0]; + frequency2 = this.mid[1]; + } else if (frequency1 === 'highMid') { + frequency1 = this.highMid[0]; + frequency2 = this.highMid[1]; + } else if (frequency1 === 'treble') { + frequency1 = this.treble[0]; + frequency2 = this.treble[1]; + } - if (this.output) { - this.output.disconnect(); - this.output = null; - } + if (typeof frequency1 !== 'number') { + throw 'invalid input for getEnergy()'; + } else if (!frequency2) { + var index = Math.round(frequency1 / nyquist * this.freqDomain.length); + return this.freqDomain[index]; + } else if (frequency1 && frequency2) { + if (frequency1 > frequency2) { + var swap = frequency2; + frequency2 = frequency1; + frequency1 = swap; + } - if (this.panner) { - this.panner.disconnect(); - this.panner = null; - } -}; -/** - * Connects the output of a p5sound object to input of another - * p5.sound object. For example, you may connect a p5.SoundFile to an - * FFT or an Effect. If no parameter is given, it will connect to - * the master output. Most p5sound objects connect to the master - * output when they are created. - * - * @method connect - * @for p5.SoundFile - * @param {Object} [object] Audio object that accepts an input - */ + var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length); + var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length); + var total = 0; + var numFrequencies = 0; + for (var i = lowIndex; i <= highIndex; i++) { + total += this.freqDomain[i]; + numFrequencies += 1; + } -p5.SoundFile.prototype.connect = function (unit) { - if (!unit) { - this.panner.connect(master.input); - } else { - if (unit.hasOwnProperty('input')) { - this.panner.connect(unit.input); - } else { - this.panner.connect(unit); - } - } -}; -/** - * Disconnects the output of this p5sound object. - * - * @method disconnect - * @for p5.SoundFile - */ + var toReturn = total / numFrequencies; + return toReturn; + } else { + throw 'invalid input for getEnergy()'; + } + } -p5.SoundFile.prototype.disconnect = function () { - if (this.panner) { - this.panner.disconnect(); - } -}; -/** - */ + }, { + key: "getFreq", + value: function getFreq(freq1, freq2) { + console.log('getFreq() is deprecated. Please use getEnergy() instead.'); + var x = this.getEnergy(freq1, freq2); + return x; + } + /** + * Returns the + * + * spectral centroid of the input signal. + * NOTE: analyze() must be called prior to getCentroid(). Analyze() + * tells the FFT to analyze frequency data, and getCentroid() uses + * the results determine the spectral centroid.

+ * + * @method getCentroid + * @for p5.FFT + * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz. + * + * + * @example + *
+ * function setup(){ + * cnv = createCanvas(100,100); + * cnv.mousePressed(userStartAudio); + * sound = new p5.AudioIn(); + * sound.start(); + * fft = new p5.FFT(); + * sound.connect(fft); + *} + * + *function draw() { + * if (getAudioContext().state !== 'running') { + * background(220); + * text('tap here and enable mic to begin', 10, 20, width - 20); + * return; + * } + * let centroidplot = 0.0; + * let spectralCentroid = 0; + * + * background(0); + * stroke(0,255,0); + * let spectrum = fft.analyze(); + * fill(0,255,0); // spectrum is green + * + * //draw the spectrum + * for (let i = 0; i < spectrum.length; i++){ + * let x = map(log(i), 0, log(spectrum.length), 0, width); + * let h = map(spectrum[i], 0, 255, 0, height); + * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length)); + * rect(x, height, rectangle_width, -h ) + * } + * let nyquist = 22050; + * + * // get the centroid + * spectralCentroid = fft.getCentroid(); + * + * // the mean_freq_index calculation is for the display. + * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length); + * + * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width); + * + * stroke(255,0,0); // the line showing where the centroid is will be red + * + * rect(centroidplot, 0, width / spectrum.length, height) + * noStroke(); + * fill(255,255,255); // text is white + * text('centroid: ', 10, 20); + * text(round(spectralCentroid)+' Hz', 10, 40); + *} + *
+ */ + + }, { + key: "getCentroid", + value: function getCentroid() { + var nyquist = master.audiocontext.sampleRate / 2; + var cumulative_sum = 0; + var centroid_normalization = 0; + + for (var i = 0; i < this.freqDomain.length; i++) { + cumulative_sum += i * this.freqDomain[i]; + centroid_normalization += this.freqDomain[i]; + } + var mean_freq_index = 0; -p5.SoundFile.prototype.getLevel = function () { - console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'); -}; -/** - * Reset the source for this SoundFile to a - * new path (URL). - * - * @method setPath - * @for p5.SoundFile - * @param {String} path path to audio file - * @param {Function} callback Callback - */ + if (centroid_normalization !== 0) { + mean_freq_index = cumulative_sum / centroid_normalization; + } + var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length); + return spec_centroid_freq; + } + /** + * Smooth FFT analysis by averaging with the last analysis frame. + * + * @method smooth + * @param {Number} smoothing 0.0 < smoothing < 1.0. + * Defaults to 0.8. + */ + + }, { + key: "smooth", + value: function smooth(s) { + if (typeof s !== 'undefined') { + this.smoothing = s; + } -p5.SoundFile.prototype.setPath = function (p, callback) { - var path = p5.prototype._checkFileFormats(p); + return this.smoothing; + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + + if (this.analyser) { + this.analyser.disconnect(); + delete this.analyser; + } + } + /** + * Returns an array of average amplitude values for a given number + * of frequency bands split equally. N defaults to 16. + * NOTE: analyze() must be called prior to linAverages(). Analyze() + * tells the FFT to analyze frequency data, and linAverages() uses + * the results to group them into a smaller set of averages.

+ * + * @method linAverages + * @for p5.FFT + * @param {Number} N Number of returned frequency groups + * @return {Array} linearAverages Array of average amplitude values for each group + */ + + }, { + key: "linAverages", + value: function linAverages(_N) { + var N = _N || 16; + + var spectrum = this.freqDomain; + var spectrumLength = spectrum.length; + var spectrumStep = Math.floor(spectrumLength / N); + var linearAverages = new Array(N); + + var groupIndex = 0; + + for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { + linearAverages[groupIndex] = linearAverages[groupIndex] !== undefined ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; + + if (specIndex % spectrumStep === spectrumStep - 1) { + groupIndex++; + } + } - this.url = path; - this.load(callback); -}; -/** - * Replace the current Audio Buffer with a new Buffer. - * - * @method setBuffer - * @for p5.SoundFile - * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays - * will create a stereo source. 1 will create - * a mono source. - */ + return linearAverages; + } + /** + * Returns an array of average amplitude values of the spectrum, for a given + * set of + * Octave Bands + * NOTE: analyze() must be called prior to logAverages(). Analyze() + * tells the FFT to analyze frequency data, and logAverages() uses + * the results to group them into a smaller set of averages.

+ * + * @method logAverages + * @for p5.FFT + * @param {Array} octaveBands Array of Octave Bands objects for grouping + * @return {Array} logAverages Array of average amplitude values for each group + */ + + }, { + key: "logAverages", + value: function logAverages(octaveBands) { + var nyquist = master.audiocontext.sampleRate / 2; + var spectrum = this.freqDomain; + var spectrumLength = spectrum.length; + var logAverages = new Array(octaveBands.length); + + var octaveIndex = 0; + + for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { + var specIndexFrequency = Math.round(specIndex * nyquist / this.freqDomain.length); + + if (specIndexFrequency > octaveBands[octaveIndex].hi) { + octaveIndex++; + } + logAverages[octaveIndex] = logAverages[octaveIndex] !== undefined ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; + } -p5.SoundFile.prototype.setBuffer = function (buf) { - var numChannels = buf.length; - var size = buf[0].length; - var newBuffer = soundfile_ac.createBuffer(numChannels, size, soundfile_ac.sampleRate); + return logAverages; + } + /** + * Calculates and Returns the 1/N + * Octave Bands + * N defaults to 3 and minimum central frequency to 15.625Hz. + * (1/3 Octave Bands ~= 31 Frequency Bands) + * Setting fCtr0 to a central value of a higher octave will ignore the lower bands + * and produce less frequency groups. + * + * @method getOctaveBands + * @for p5.FFT + * @param {Number} N Specifies the 1/N type of generated octave bands + * @param {Number} fCtr0 Minimum central frequency for the lowest band + * @return {Array} octaveBands Array of octave band objects with their bounds + */ + + }, { + key: "getOctaveBands", + value: function getOctaveBands(_N, _fCtr0) { + var N = _N || 3; + + var fCtr0 = _fCtr0 || 15.625; + + var octaveBands = []; + var lastFrequencyBand = { + lo: fCtr0 / Math.pow(2, 1 / (2 * N)), + ctr: fCtr0, + hi: fCtr0 * Math.pow(2, 1 / (2 * N)) + }; + octaveBands.push(lastFrequencyBand); + var nyquist = master.audiocontext.sampleRate / 2; + + while (lastFrequencyBand.hi < nyquist) { + var newFrequencyBand = {}; + newFrequencyBand.lo = lastFrequencyBand.hi; + newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N); + newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N)); + octaveBands.push(newFrequencyBand); + lastFrequencyBand = newFrequencyBand; + } - if (!(buf[0] instanceof Float32Array)) { - buf[0] = new Float32Array(buf[0]); - } + return octaveBands; + } + }]); - for (var channelNum = 0; channelNum < numChannels; channelNum++) { - var channel = newBuffer.getChannelData(channelNum); - channel.set(buf[channelNum]); - } + return FFT; +}(); - this.buffer = newBuffer; - this.panner.inputChannels(numChannels); -}; +function freqToFloat(fft) { + if (fft.freqDomain instanceof Float32Array === false) { + fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount); + } +} +function freqToInt(fft) { + if (fft.freqDomain instanceof Uint8Array === false) { + fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount); + } +} -var _createCounterBuffer = function _createCounterBuffer(buffer) { - var len = buffer.length; - var audioBuf = soundfile_ac.createBuffer(1, buffer.length, soundfile_ac.sampleRate); - var arrayBuffer = audioBuf.getChannelData(0); +function timeToFloat(fft) { + if (fft.timeDomain instanceof Float32Array === false) { + fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount); + } +} - for (var index = 0; index < len; index++) { - arrayBuffer[index] = index; +function timeToInt(fft) { + if (fft.timeDomain instanceof Uint8Array === false) { + fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount); } +} - return audioBuf; -}; + var fft = (fft_FFT); +var Add = __webpack_require__(4); +var Add_default = __webpack_require__.n(Add); +var Multiply = __webpack_require__(1); +var Multiply_default = __webpack_require__.n(Multiply); -p5.SoundFile.prototype._initCounterNode = function () { - var _this = this; +var Scale = __webpack_require__(8); +var Scale_default = __webpack_require__.n(Scale); - var self = this; - var now = soundfile_ac.currentTime; - var cNode = soundfile_ac.createBufferSource(); - var workletBufferSize = safeBufferSize(256); +function oscillator_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { oscillator_typeof = function _typeof(obj) { return typeof obj; }; } else { oscillator_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return oscillator_typeof(obj); } - if (self._workletNode) { - self._workletNode.disconnect(); +function _possibleConstructorReturn(self, call) { if (call && (oscillator_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } - delete self._workletNode; - } +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } - self._workletNode = new AudioWorkletNode(soundfile_ac, processorNames_default.a.soundFileProcessor, { - processorOptions: { - bufferSize: workletBufferSize - } - }); +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } - self._workletNode.port.onmessage = function (event) { - if (event.data.name === 'position') { - if (event.data.position === 0) { - return; - } +function _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); } - _this._lastPos = event.data.position; +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } - _this._onTimeUpdate(self._lastPos); - } - }; +function oscillator_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function oscillator_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); } } - cNode.buffer = _createCounterBuffer(self.buffer); - cNode.playbackRate.setValueAtTime(self.playbackRate, now); - cNode.connect(self._workletNode); +function oscillator_createClass(Constructor, protoProps, staticProps) { if (protoProps) oscillator_defineProperties(Constructor.prototype, protoProps); if (staticProps) oscillator_defineProperties(Constructor, staticProps); return Constructor; } - self._workletNode.connect(p5.soundOut._silentNode); - return cNode; -}; -p5.SoundFile.prototype._initSourceNode = function () { - var bufferSourceNode = soundfile_ac.createBufferSource(); - bufferSourceNode.buffer = this.buffer; - bufferSourceNode.playbackRate.value = this.playbackRate; - bufferSourceNode.connect(this.output); - return bufferSourceNode; -}; -/** - * processPeaks returns an array of timestamps where it thinks there is a beat. - * - * This is an asynchronous function that processes the soundfile in an offline audio context, - * and sends the results to your callback function. - * - * The process involves running the soundfile through a lowpass filter, and finding all of the - * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, - * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. - * - * @method processPeaks - * @for p5.SoundFile - * @param {Function} callback a function to call once this data is returned - * @param {Number} [initThreshold] initial threshold defaults to 0.9 - * @param {Number} [minThreshold] minimum threshold defaults to 0.22 - * @param {Number} [minPeaks] minimum number of peaks defaults to 200 - * @return {Array} Array of timestamped peaks - */ -p5.SoundFile.prototype.processPeaks = function (callback, _initThreshold, _minThreshold, _minPeaks) { - var bufLen = this.buffer.length; - var sampleRate = this.buffer.sampleRate; - var buffer = this.buffer; - var allPeaks = []; - var initialThreshold = _initThreshold || 0.9, - threshold = initialThreshold, - minThreshold = _minThreshold || 0.22, - minPeaks = _minPeaks || 200; +function sigChain(o, mathObj, thisChain, nextChain, type) { + var chainSource = o.oscillator; + + for (var i in o.mathOps) { + if (o.mathOps[i] instanceof type) { + chainSource.disconnect(); + o.mathOps[i].dispose(); + thisChain = i; - var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate); + if (thisChain < o.mathOps.length - 2) { + nextChain = o.mathOps[i + 1]; + } + } + } - var source = offlineContext.createBufferSource(); - source.buffer = buffer; + if (thisChain === o.mathOps.length - 1) { + o.mathOps.push(nextChain); + } - var filter = offlineContext.createBiquadFilter(); - filter.type = 'lowpass'; - source.connect(filter); - filter.connect(offlineContext.destination); - source.start(0); - offlineContext.startRendering(); + if (i > 0) { + chainSource = o.mathOps[i - 1]; + } - offlineContext.oncomplete = function (e) { - if (!self.panner) return; - var filteredBuffer = e.renderedBuffer; - var bufferData = filteredBuffer.getChannelData(0); + chainSource.disconnect(); + chainSource.connect(mathObj); + mathObj.connect(nextChain); + o.mathOps[thisChain] = mathObj; + return o; +} +/** + *

Creates a signal that oscillates between -1.0 and 1.0. + * By default, the oscillation takes the form of a sinusoidal + * shape ('sine'). Additional types include 'triangle', + * 'sawtooth' and 'square'. The frequency defaults to + * 440 oscillations per second (440Hz, equal to the pitch of an + * 'A' note).

+ * + *

Set the type of oscillation with setType(), or by instantiating a + * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc. + *

+ * + * @class p5.Oscillator + * @constructor + * @param {Number} [freq] frequency defaults to 440Hz + * @param {String} [type] type of oscillator. Options: + * 'sine' (default), 'triangle', + * 'sawtooth', 'square' + * @example + *
+ * let osc, playing, freq, amp; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playOscillator); + * osc = new p5.Oscillator('sine'); + * } + * + * function draw() { + * background(220) + * freq = constrain(map(mouseX, 0, width, 100, 500), 100, 500); + * amp = constrain(map(mouseY, height, 0, 0, 1), 0, 1); + * + * text('tap to play', 20, 20); + * text('freq: ' + freq, 20, 40); + * text('amp: ' + amp, 20, 60); + * + * if (playing) { + * // smooth the transitions by 0.1 seconds + * osc.freq(freq, 0.1); + * osc.amp(amp, 0.1); + * } + * } + * + * function playOscillator() { + * // starting an oscillator on a user gesture will enable audio + * // in browsers that have a strict autoplay policy. + * // See also: userStartAudio(); + * osc.start(); + * playing = true; + * } + * + * function mouseReleased() { + * // ramp amplitude to 0 over 0.5 seconds + * osc.amp(0, 0.5); + * playing = false; + * } + *
+ */ - do { - allPeaks = getPeaksAtThreshold(bufferData, threshold); - threshold -= 0.005; - } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold); +var oscillator_Oscillator = +function () { + function Oscillator(freq, type) { + oscillator_classCallCheck(this, Oscillator); - var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); + if (typeof freq === 'string') { + var f = type; + type = freq; + freq = f; + } - var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate); + if (typeof type === 'number') { + var _f = type; + type = freq; + freq = _f; + } - var topTempos = groups.sort(function (intA, intB) { - return intB.count - intA.count; - }).splice(0, 5); + this.started = false; - this.tempo = topTempos[0].tempo; + this.phaseAmount = undefined; + this.oscillator = master.audiocontext.createOscillator(); + this.f = freq || 440.0; - var bpmVariance = 5; - var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance); - callback(tempoPeaks); - }; -}; + this.oscillator.type = type || 'sine'; + this.oscillator.frequency.setValueAtTime(this.f, master.audiocontext.currentTime); + this.output = master.audiocontext.createGain(); + this._freqMods = []; -var Peak = function Peak(amp, i) { - this.sampleIndex = i; - this.amplitude = amp; - this.tempos = []; - this.intervals = []; -}; + this.output.gain.value = 0.5; + this.output.gain.setValueAtTime(0.5, master.audiocontext.currentTime); + this.oscillator.connect(this.output); + this.panPosition = 0.0; + this.connection = master.input; -function getPeaksAtThreshold(data, threshold) { - var peaksObj = {}; - var length = data.length; + this.panner = new panner_0(this.output, this.connection, 1); - for (var i = 0; i < length; i++) { - if (data[i] > threshold) { - var amp = data[i]; - var peak = new Peak(amp, i); - peaksObj[i] = peak; + this.mathOps = [this.output]; - i += 6000; - } + master.soundArray.push(this); - i++; + this.fade = this.amp; } + /** + * Start an oscillator. + * + * Starting an oscillator on a user gesture will enable audio in browsers + * that have a strict autoplay policy, including Chrome and most mobile + * devices. See also: `userStartAudio()`. + * + * @method start + * @for p5.Oscillator + * @param {Number} [time] startTime in seconds from now. + * @param {Number} [frequency] frequency in Hz. + */ - return peaksObj; -} + oscillator_createClass(Oscillator, [{ + key: "start", + value: function start(time, f) { + if (this.started) { + var now = master.audiocontext.currentTime; + this.stop(now); + } -function countIntervalsBetweenNearbyPeaks(peaksObj) { - var intervalCounts = []; - var peaksArray = Object.keys(peaksObj).sort(); + if (!this.started) { + var freq = f || this.f; + var type = this.oscillator.type; - for (var index = 0; index < peaksArray.length; index++) { - for (var i = 0; i < 10; i++) { - var startPeak = peaksObj[peaksArray[index]]; - var endPeak = peaksObj[peaksArray[index + i]]; + if (this.oscillator) { + this.oscillator.disconnect(); + delete this.oscillator; + } - if (startPeak && endPeak) { - var startPos = startPeak.sampleIndex; - var endPos = endPeak.sampleIndex; - var interval = endPos - startPos; - if (interval > 0) { - startPeak.intervals.push(interval); - } + this.oscillator = master.audiocontext.createOscillator(); + this.oscillator.frequency.value = Math.abs(freq); + this.oscillator.type = type; + this.oscillator.connect(this.output); + time = time || 0; + this.oscillator.start(time + master.audiocontext.currentTime); + this.freqNode = this.oscillator.frequency; - var foundInterval = intervalCounts.some(function (intervalCount) { - if (intervalCount.interval === interval) { - intervalCount.count++; - return intervalCount; + for (var i in this._freqMods) { + if (typeof this._freqMods[i].connect !== 'undefined') { + this._freqMods[i].connect(this.oscillator.frequency); } - }); - - if (!foundInterval) { - intervalCounts.push({ - interval: interval, - count: 1 - }); } + + this.started = true; } } - } - - return intervalCounts; -} - + /** + * Stop an oscillator. Accepts an optional parameter + * to determine how long (in seconds from now) until the + * oscillator stops. + * + * @method stop + * @for p5.Oscillator + * @param {Number} secondsFromNow Time, in seconds from now. + */ + + }, { + key: "stop", + value: function stop(time) { + if (this.started) { + var t = time || 0; + var now = master.audiocontext.currentTime; + this.oscillator.stop(t + now); + this.started = false; + } + } + /** + * Set the amplitude between 0 and 1.0. Or, pass in an object + * such as an oscillator to modulate amplitude with an audio signal. + * + * @method amp + * @for p5.Oscillator + * @param {Number|Object} vol between 0 and 1.0 + * or a modulating signal/oscillator + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {AudioParam} gain If no value is provided, + * returns the Web Audio API + * AudioParam that controls + * this oscillator's + * gain/amplitude/volume) + */ + + }, { + key: "amp", + value: function amp(vol) { + var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + + if (typeof vol === 'number') { + var now = master.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); + } else if (vol) { + vol.connect(this.output.gain); + } else { + return this.output.gain; + } + } + /** + * Returns the value of output gain + * + * @method getAmp + * @for p5.Oscillator + * + * @returns {number} Amplitude value between 0.0 and 1.0 + */ + + }, { + key: "getAmp", + value: function getAmp() { + return this.output.gain.value; + } + /** + * Set frequency of an oscillator to a value. Or, pass in an object + * such as an oscillator to modulate the frequency with an audio signal. + * + * @method freq + * @for p5.Oscillator + * @param {Number|Object} Frequency Frequency in Hz + * or modulating signal/oscillator + * @param {Number} [rampTime] Ramp time (in seconds) + * @param {Number} [timeFromNow] Schedule this event to happen + * at x seconds from now + * @return {AudioParam} Frequency If no value is provided, + * returns the Web Audio API + * AudioParam that controls + * this oscillator's frequency + * @example + *
+ * let osc; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playOscillator); + * osc = new p5.Oscillator(300); + * background(220); + * text('tap to play', 20, 20); + * } + * + * function playOscillator() { + * osc.start(); + * osc.amp(0.5); + * // start at 700Hz + * osc.freq(700); + * // ramp to 60Hz over 0.7 seconds + * osc.freq(60, 0.7); + * osc.amp(0, 0.1, 0.7); + * } + *
+ */ + + }, { + key: "freq", + value: function freq(val) { + var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + + if (typeof val === 'number' && !isNaN(val)) { + this.f = val; + var now = master.audiocontext.currentTime; + + if (rampTime === 0) { + this.oscillator.frequency.setValueAtTime(val, tFromNow + now); + } else { + if (val > 0) { + this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); + } else { + this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now); + } + } -function groupNeighborsByTempo(intervalCounts, sampleRate) { - var tempoCounts = []; - intervalCounts.forEach(function (intervalCount) { - try { - var theoreticalTempo = Math.abs(60 / (intervalCount.interval / sampleRate)); - theoreticalTempo = mapTempo(theoreticalTempo); - var foundTempo = tempoCounts.some(function (tempoCount) { - if (tempoCount.tempo === theoreticalTempo) return tempoCount.count += intervalCount.count; - }); - if (!foundTempo) { - if (isNaN(theoreticalTempo)) { - return; + if (this.phaseAmount) { + this.phase(this.phaseAmount); + } + } else if (val) { + if (val.output) { + val = val.output; } - tempoCounts.push({ - tempo: Math.round(theoreticalTempo), - count: intervalCount.count - }); + val.connect(this.oscillator.frequency); + + this._freqMods.push(val); + } else { + return this.oscillator.frequency; } - } catch (e) { - throw e; } - }); - return tempoCounts; -} + /** + * Returns the value of frequency of oscillator + * + * @method getFreq + * @for p5.Oscillator + * @returns {number} Frequency of oscillator in Hertz + */ + + }, { + key: "getFreq", + value: function getFreq() { + return this.oscillator.frequency.value; + } + /** + * Set type to 'sine', 'triangle', 'sawtooth' or 'square'. + * + * @method setType + * @for p5.Oscillator + * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'. + */ + + }, { + key: "setType", + value: function setType(type) { + this.oscillator.type = type; + } + /** + * Returns current type of oscillator eg. 'sine', 'triangle', 'sawtooth' or 'square'. + * + * @method getType + * @for p5.Oscillator + * @returns {String} type of oscillator eg . 'sine', 'triangle', 'sawtooth' or 'square'. + */ + + }, { + key: "getType", + value: function getType() { + return this.oscillator.type; + } + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @for p5.Oscillator + * @param {Object} unit A p5.sound or Web Audio object + */ + + }, { + key: "connect", + value: function connect(unit) { + if (!unit) { + this.panner.connect(master.input); + } else if (unit.hasOwnProperty('input')) { + this.panner.connect(unit.input); + this.connection = unit.input; + } else { + this.panner.connect(unit); + this.connection = unit; + } + } + /** + * Disconnect all outputs + * + * @method disconnect + * @for p5.Oscillator + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + if (this.panner) { + this.panner.disconnect(); -function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { - var peaksAtTopTempo = []; - var peaksArray = Object.keys(peaksObj).sort(); + if (this.output) { + this.output.connect(this.panner); + } + } - for (var i = 0; i < peaksArray.length; i++) { - var key = peaksArray[i]; - var peak = peaksObj[key]; - - for (var j = 0; j < peak.intervals.length; j++) { - var intervalBPM = Math.round(Math.abs(60 / (peak.intervals[j] / sampleRate))); - intervalBPM = mapTempo(intervalBPM); - - if (Math.abs(intervalBPM - tempo) < bpmVariance) { - peaksAtTopTempo.push(peak.sampleIndex / sampleRate); - } - } - } + this.oscMods = []; + } + /** + * Pan between Left (-1) and Right (1) + * + * @method pan + * @for p5.Oscillator + * @param {Number} panning Number between -1 and 1 + * @param {Number} timeFromNow schedule this event to happen + * seconds from now + */ + + }, { + key: "pan", + value: function pan(pval, tFromNow) { + this.panPosition = pval; + this.panner.pan(pval, tFromNow); + } + /** + * Returns the current value of panPosition , between Left (-1) and Right (1) + * + * @method getPan + * @for p5.Oscillator + * + * @returns {number} panPosition of oscillator , between Left (-1) and Right (1) + */ + + }, { + key: "getPan", + value: function getPan() { + return this.panPosition; + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + + if (this.oscillator) { + var now = master.audiocontext.currentTime; + this.stop(now); + this.disconnect(); + this.panner = null; + this.oscillator = null; + } - peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { - var dif = arr[index + 1] - peakTime; - if (dif > 0.01) { - return true; + if (this.osc2) { + this.osc2.dispose(); + } } - }); - return peaksAtTopTempo; -} - + /** + * Set the phase of an oscillator between 0.0 and 1.0. + * In this implementation, phase is a delay time + * based on the oscillator's current frequency. + * + * @method phase + * @for p5.Oscillator + * @param {Number} phase float between 0.0 and 1.0 + */ + + }, { + key: "phase", + value: function phase(p) { + var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f); + var now = master.audiocontext.currentTime; + this.phaseAmount = p; -function mapTempo(theoreticalTempo) { - if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { - return; - } + if (!this.dNode) { + this.dNode = master.audiocontext.createDelay(); + this.oscillator.disconnect(); + this.oscillator.connect(this.dNode); + this.dNode.connect(this.output); + } - while (theoreticalTempo < 90) { - theoreticalTempo *= 2; - } - while (theoreticalTempo > 180 && theoreticalTempo > 90) { - theoreticalTempo /= 2; - } + this.dNode.delayTime.setValueAtTime(delayAmt, now); + } + /** + * Add a value to the p5.Oscillator's output amplitude, + * and return the oscillator. Calling this method again + * will override the initial add() with a new value. + * + * @method add + * @for p5.Oscillator + * @param {Number} number Constant number to add + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with scaled output + * + */ + + }, { + key: "add", + value: function add(num) { + var add = new Add_default.a(num); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, add, thisChain, nextChain, Add_default.a); + } + /** + * Multiply the p5.Oscillator's output amplitude + * by a fixed value (i.e. turn it up!). Calling this method + * again will override the initial mult() with a new value. + * + * @method mult + * @for p5.Oscillator + * @param {Number} number Constant number to multiply + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with multiplied output + */ + + }, { + key: "mult", + value: function mult(num) { + var mult = new Multiply_default.a(num); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, mult, thisChain, nextChain, Multiply_default.a); + } + /** + * Scale this oscillator's amplitude values to a given + * range, and return the oscillator. Calling this method + * again will override the initial scale() with new values. + * + * @method scale + * @for p5.Oscillator + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with scaled output + */ + + }, { + key: "scale", + value: function scale(inMin, inMax, outMin, outMax) { + var mapOutMin, mapOutMax; + + if (arguments.length === 4) { + mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; + + mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; + } else { + mapOutMin = arguments[0]; + mapOutMax = arguments[1]; + } - return theoreticalTempo; -} + var scale = new Scale_default.a(mapOutMin, mapOutMax); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, scale, thisChain, nextChain, Scale_default.a); + } + }]); + return Oscillator; +}(); -var Cue = function Cue(callback, time, id, val) { - this.callback = callback; - this.time = time; - this.id = id; - this.val = val; -}; /** - * Schedule events to trigger every time a MediaElement - * (audio/video) reaches a playback cue point. - * - * Accepts a callback function, a time (in seconds) at which to trigger - * the callback, and an optional parameter for the callback. - * - * Time will be passed as the first parameter to the callback function, - * and param will be the second parameter. - * - * - * @method addCue - * @for p5.SoundFile - * @param {Number} time Time in seconds, relative to this media - * element's playback. For example, to trigger - * an event every time playback reaches two - * seconds, pass in the number 2. This will be - * passed as the first parameter to - * the callback function. - * @param {Function} callback Name of a function that will be - * called at the given time. The callback will - * receive time and (optionally) param as its - * two parameters. - * @param {Object} [value] An object to be passed as the - * second parameter to the - * callback function. - * @return {Number} id ID of this cue, - * useful for removeCue(id) - * @example - *
- * let mySound; - * function preload() { - * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * text('tap to play', 10, 20); - * - * // schedule calls to changeText - * mySound.addCue(0, changeText, "hello" ); - * mySound.addCue(0.5, changeText, "hello," ); - * mySound.addCue(1, changeText, "hello, p5!"); - * mySound.addCue(1.5, changeText, "hello, p5!!"); - * mySound.addCue(2, changeText, "hello, p5!!!!!"); - * } - * - * function changeText(val) { - * background(220); - * text(val, 10, 20); - * } + * Constructor: new p5.SinOsc(). + * This creates a Sine Wave Oscillator and is + * equivalent to new p5.Oscillator('sine') + * or creating a p5.Oscillator and then calling + * its method setType('sine'). + * See p5.Oscillator for methods. * - * function canvasPressed() { - * mySound.play(); - * } - *
+ * @class p5.SinOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency */ -p5.SoundFile.prototype.addCue = function (time, callback, val) { - var id = this._cueIDCounter++; - var cue = new Cue(callback, time, id, val); +var SinOsc = +function (_Oscillator) { + _inherits(SinOsc, _Oscillator); - this._cues.push(cue); + function SinOsc(freq) { + oscillator_classCallCheck(this, SinOsc); + return _possibleConstructorReturn(this, _getPrototypeOf(SinOsc).call(this, freq, 'sine')); + } - return id; -}; + return SinOsc; +}(oscillator_Oscillator); /** - * Remove a callback based on its ID. The ID is returned by the - * addCue method. + * Constructor: new p5.TriOsc(). + * This creates a Triangle Wave Oscillator and is + * equivalent to new p5.Oscillator('triangle') + * or creating a p5.Oscillator and then calling + * its method setType('triangle'). + * See p5.Oscillator for methods. * - * @method removeCue - * @for p5.SoundFile - * @param {Number} id ID of the cue, as returned by addCue + * @class p5.TriOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency */ -p5.SoundFile.prototype.removeCue = function (id) { - var cueLength = this._cues.length; - - for (var i = 0; i < cueLength; i++) { - var cue = this._cues[i]; +var TriOsc = +function (_Oscillator2) { + _inherits(TriOsc, _Oscillator2); - if (cue.id === id) { - this._cues.splice(i, 1); + function TriOsc(freq) { + oscillator_classCallCheck(this, TriOsc); - break; - } + return _possibleConstructorReturn(this, _getPrototypeOf(TriOsc).call(this, freq, 'triangle')); } - if (this._cues.length === 0) { - } -}; + return TriOsc; +}(oscillator_Oscillator); /** - * Remove all of the callbacks that had originally been scheduled - * via the addCue method. + * Constructor: new p5.SawOsc(). + * This creates a SawTooth Wave Oscillator and is + * equivalent to new p5.Oscillator('sawtooth') + * or creating a p5.Oscillator and then calling + * its method setType('sawtooth'). + * See p5.Oscillator for methods. * - * @method clearCues + * @class p5.SawOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency */ -p5.SoundFile.prototype.clearCues = function () { - this._cues = []; -}; - +var SawOsc = +function (_Oscillator3) { + _inherits(SawOsc, _Oscillator3); -p5.SoundFile.prototype._onTimeUpdate = function (position) { - var playbackTime = position / this.buffer.sampleRate; - var cueLength = this._cues.length; + function SawOsc(freq) { + oscillator_classCallCheck(this, SawOsc); - for (var i = 0; i < cueLength; i++) { - var cue = this._cues[i]; - var callbackTime = cue.time; - var val = cue.val; - var leftLimit = this._prevUpdateTime || 0; - var rightLimit = playbackTime; - - if (leftLimit <= callbackTime && callbackTime <= rightLimit) { - cue.callback(val); - } + return _possibleConstructorReturn(this, _getPrototypeOf(SawOsc).call(this, freq, 'sawtooth')); } - this._prevUpdateTime = playbackTime; -}; -/** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. To upload a file to a server, see - * getBlob - * - * @method save - * @for p5.SoundFile - * @param {String} [fileName] name of the resulting .wav file. - * @example - *
- * let mySound; - * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * text('tap to download', 10, 20); - * } - * - * function canvasPressed() { - * mySound.save('my cool filename'); - * } - *
- */ - - -p5.SoundFile.prototype.save = function (fileName) { - p5.prototype.saveSound(this, fileName, 'wav'); -}; + return SawOsc; +}(oscillator_Oscillator); /** - * This method is useful for sending a SoundFile to a server. It returns the - * .wav-encoded audio data as a "Blob". - * A Blob is a file-like data object that can be uploaded to a server - * with an http request. We'll - * use the `httpDo` options object to send a POST request with some - * specific options: we encode the request as `multipart/form-data`, - * and attach the blob as one of the form values using `FormData`. - * - * - * @method getBlob - * @for p5.SoundFile - * @returns {Blob} A file-like data object - * @example - *
- * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * noCanvas(); - * let soundBlob = mySound.getBlob(); - * - * // Now we can send the blob to a server... - * let serverUrl = 'https://jsonplaceholder.typicode.com/posts'; - * let httpRequestOptions = { - * method: 'POST', - * body: new FormData().append('soundBlob', soundBlob), - * headers: new Headers({ - * 'Content-Type': 'multipart/form-data' - * }) - * }; - * httpDo(serverUrl, httpRequestOptions); - * - * // We can also create an `ObjectURL` pointing to the Blob - * let blobUrl = URL.createObjectURL(soundBlob); - * - * // The `
+ * @class p5.SqrOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency */ -p5.SoundFile.prototype.getBlob = function () { - var dataView = convertToWav(this.buffer); - return new Blob([dataView], { - type: 'audio/wav' - }); -}; +var SqrOsc = +function (_Oscillator4) { + _inherits(SqrOsc, _Oscillator4); + function SqrOsc(freq) { + oscillator_classCallCheck(this, SqrOsc); -function _clearOnEnd(e) { - var thisBufferSourceNode = e.target; - var soundFile = this; + return _possibleConstructorReturn(this, _getPrototypeOf(SqrOsc).call(this, freq, 'square')); + } - thisBufferSourceNode._playing = false; - thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd); + return SqrOsc; +}(oscillator_Oscillator); - soundFile._onended(soundFile); + var oscillator = (oscillator_Oscillator); +var TimelineSignal = __webpack_require__(7); +var TimelineSignal_default = __webpack_require__.n(TimelineSignal); - soundFile.bufferSourceNodes.map(function (_, i) { - return i; - }).reverse().forEach(function (i) { - var n = soundFile.bufferSourceNodes[i]; - if (n._playing === false) { - soundFile.bufferSourceNodes.splice(i, 1); - } - }); - if (soundFile.bufferSourceNodes.length === 0) { - soundFile._playing = false; - } -} /** - * Amplitude measures volume between 0.0 and 1.0. - * Listens to all p5sound by default, or use setInput() - * to listen to a specific sound source. Accepts an optional - * smoothing value, which defaults to 0. + *

Envelopes are pre-defined amplitude distribution over time. + * Typically, envelopes are used to control the output volume + * of an object, a series of fades referred to as Attack, Decay, + * Sustain and Release ( + * ADSR + * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can + * control an Oscillator's frequency like this: osc.freq(env).

+ *

Use setRange to change the attack/release level. + * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

+ *

Use the play method to play the entire envelope, + * the ramp method for a pingable trigger, + * or triggerAttack/ + * triggerRelease to trigger noteOn/noteOff.

* - * @class p5.Amplitude + * @class p5.Envelope * @constructor - * @param {Number} [smoothing] between 0.0 and .999 to smooth - * amplitude readings (defaults to 0) * @example *
- * let sound, amplitude; + * let t1 = 0.1; // attack time in seconds + * let l1 = 0.7; // attack level 0.0 to 1.0 + * let t2 = 0.3; // decay time in seconds + * let l2 = 0.1; // decay level 0.0 to 1.0 * - * function preload(){ - * sound = loadSound('assets/beat.mp3'); - * } - * function setup() { - * let cnv = createCanvas(100,100); - * cnv.mouseClicked(toggleSound); - * amplitude = new p5.Amplitude(); - * } + * let env; + * let triOsc; * - * function draw() { + * function setup() { + * let cnv = createCanvas(100, 100); * background(220); * text('tap to play', 20, 20); + * cnv.mousePressed(playSound); * - * let level = amplitude.getLevel(); - * let size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); + * env = new p5.Envelope(t1, l1, t2, l2); + * triOsc = new p5.Oscillator('triangle'); * } * - * function toggleSound() { - * if (sound.isPlaying() ){ - * sound.stop(); - * } else { - * sound.play(); - * } + * function playSound() { + * // starting the oscillator ensures that audio is enabled. + * triOsc.start(); + * env.play(triOsc); * } - * *
*/ -p5.Amplitude = function (smoothing) { - this.bufferSize = safeBufferSize(2048); - - this.audiocontext = master.audiocontext; - this._workletNode = new AudioWorkletNode(this.audiocontext, processorNames_default.a.amplitudeProcessor, { - outputChannelCount: [1], - parameterData: { - smoothing: smoothing || 0 - }, - processorOptions: { - normalize: false, - smoothing: smoothing || 0, - numInputChannels: 2, - bufferSize: this.bufferSize - } - }); - - 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); - - - this.input = this._workletNode; - this.output = this.audiocontext.createGain(); +p5.Envelope = function (t1, l1, t2, l2, t3, l3) { + /** + * Time until envelope reaches attackLevel + * @property attackTime + */ + this.aTime = t1 || 0.1; + /** + * Level once attack is complete. + * @property attackLevel + */ - this.volume = 0; - this.volNorm = 0; - this.stereoVol = [0, 0]; - this.stereoVolNorm = [0, 0]; - this.normalize = false; + this.aLevel = l1 || 1; + /** + * Time until envelope reaches decayLevel. + * @property decayTime + */ - this._workletNode.connect(this.output); + this.dTime = t2 || 0.5; + /** + * Level after decay. The envelope will sustain here until it is released. + * @property decayLevel + */ - this.output.gain.value = 0; + this.dLevel = l2 || 0; + /** + * Duration of the release portion of the envelope. + * @property releaseTime + */ - this.output.connect(this.audiocontext.destination); + this.rTime = t3 || 0; + /** + * Level at the end of the release. + * @property releaseLevel + */ - master.meter.connect(this._workletNode); + this.rLevel = l3 || 0; + this._rampHighPercentage = 0.98; + this._rampLowPercentage = 0.02; + this.output = master.audiocontext.createGain(); + this.control = new TimelineSignal_default.a(); + + this._init(); + + + this.control.connect(this.output); + + this.connection = null; + + this.mathOps = [this.control]; + + this.isExponential = false; + + this.sourceToClear = null; + + this.wasTriggered = false; master.soundArray.push(this); +}; + + +p5.Envelope.prototype._init = function () { + var now = master.audiocontext.currentTime; + var t = now; + this.control.setTargetAtTime(0.00001, t, 0.001); + + this._setRampAD(this.aTime, this.dTime); }; /** - * Connects to the p5sound instance (master output) by default. - * Optionally, you can pass in a specific source (i.e. a soundfile). - * - * @method setInput - * @for p5.Amplitude - * @param {soundObject|undefined} [snd] set the sound source - * (optional, defaults to - * master output) - * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0 - * to smooth amplitude readings + * Reset the envelope with a series of time/value pairs. + * + * @method set + * @for p5.Envelope + * @param {Number} attackTime Time (in seconds) before level + * reaches attackLevel + * @param {Number} attackLevel Typically an amplitude between + * 0.0 and 1.0 + * @param {Number} decayTime Time + * @param {Number} decayLevel Amplitude (In a standard ADSR envelope, + * decayLevel = sustainLevel) + * @param {Number} releaseTime Release Time (in seconds) + * @param {Number} releaseLevel Amplitude * @example *
- * function preload(){ - * sound1 = loadSound('assets/beat.mp3'); - * sound2 = loadSound('assets/drum.mp3'); - * } - * function setup(){ - * cnv = createCanvas(100, 100); - * cnv.mouseClicked(toggleSound); + * let attackTime; + * let l1 = 0.7; // attack level 0.0 to 1.0 + * let t2 = 0.3; // decay time in seconds + * let l2 = 0.1; // decay level 0.0 to 1.0 + * let l3 = 0.2; // release time in seconds * - * amplitude = new p5.Amplitude(); - * amplitude.setInput(sound2); + * let env, triOsc; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playSound); + * + * env = new p5.Envelope(); + * triOsc = new p5.Oscillator('triangle'); * } * * function draw() { * background(220); - * text('tap to play', 20, 20); + * text('tap here to play', 5, 20); * - * let level = amplitude.getLevel(); - * let size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); + * attackTime = map(mouseX, 0, width, 0.0, 1.0); + * text('attack time: ' + attackTime, 5, height - 20); * } * - * function toggleSound(){ - * if (sound1.isPlaying() && sound2.isPlaying()) { - * sound1.stop(); - * sound2.stop(); - * } else { - * sound1.play(); - * sound2.play(); - * } + * // mouseClick triggers envelope if over canvas + * function playSound() { + * env.set(attackTime, l1, t2, l2, l3); + * + * triOsc.start(); + * env.play(triOsc); * } *
+ * */ -p5.Amplitude.prototype.setInput = function (source, smoothing) { - master.meter.disconnect(); - - if (smoothing) { - this._workletNode.parameters.get('smoothing').value = smoothing; - } - - - if (source == null) { - console.log('Amplitude input source is not ready! Connecting to master output instead'); - master.meter.connect(this._workletNode); - } - else if (source instanceof p5.Signal) { - source.output.connect(this._workletNode); - } - else if (source) { - source.connect(this._workletNode); - - this._workletNode.disconnect(); - - this._workletNode.connect(this.output); - } - else { - master.meter.connect(this._workletNode); - } -}; - -p5.Amplitude.prototype.connect = function (unit) { - if (unit) { - if (unit.hasOwnProperty('input')) { - this.output.connect(unit.input); - } else { - this.output.connect(unit); - } - } else { - this.output.connect(this.panner.connect(master.input)); - } -}; +p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) { + this.aTime = t1; + this.aLevel = l1; + this.dTime = t2 || 0; + this.dLevel = l2 || 0; + this.rTime = t3 || 0; + this.rLevel = l3 || 0; -p5.Amplitude.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } + this._setRampAD(t1, t2); }; /** - * Returns a single Amplitude reading at the moment it is called. - * For continuous readings, run in the draw loop. + * Set values like a traditional + * + * ADSR envelope + * . * - * @method getLevel - * @for p5.Amplitude - * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right) - * @return {Number} Amplitude as a number between 0.0 and 1.0 + * @method setADSR + * @for p5.Envelope + * @param {Number} attackTime Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) * @example *
- * function preload(){ - * sound = loadSound('assets/beat.mp3'); - * } + * let attackLevel = 1.0; + * let releaseLevel = 0; + * + * let attackTime = 0.001; + * let decayTime = 0.2; + * let susPercent = 0.2; + * let releaseTime = 0.5; + * + * let env, triOsc; * * function setup() { * let cnv = createCanvas(100, 100); - * cnv.mouseClicked(toggleSound); - * amplitude = new p5.Amplitude(); + * cnv.mousePressed(playEnv); + * + * env = new p5.Envelope(); + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.freq(220); * } * * function draw() { - * background(220, 150); - * textAlign(CENTER); - * text('tap to play', width/2, 20); - * - * let level = amplitude.getLevel(); - * let size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); + * background(220); + * text('tap here to play', 5, 20); + * attackTime = map(mouseX, 0, width, 0, 1.0); + * text('attack time: ' + attackTime, 5, height - 40); * } * - * function toggleSound(){ - * if (sound.isPlaying()) { - * sound.stop(); - * } else { - * sound.play(); - * } + * function playEnv() { + * triOsc.start(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.play(); * } *
*/ -p5.Amplitude.prototype.getLevel = function (channel) { - if (typeof channel !== 'undefined') { - if (this.normalize) { - return this.stereoVolNorm[channel]; - } else { - return this.stereoVol[channel]; - } - } else if (this.normalize) { - return this.volNorm; - } else { - return this.volume; - } -}; -/** - * Determines whether the results of Amplitude.process() will be - * Normalized. To normalize, Amplitude finds the difference the - * loudest reading it has processed and the maximum amplitude of - * 1.0. Amplitude adds this difference to all values to produce - * results that will reliably map between 0.0 and 1.0. However, - * if a louder moment occurs, the amount that Normalize adds to - * all the values will change. Accepts an optional boolean parameter - * (true or false). Normalizing is off by default. - * - * @method toggleNormalize - * @for p5.Amplitude - * @param {boolean} [boolean] set normalize to true (1) or false (0) - */ - +p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) { + this.aTime = aTime; + this.dTime = dTime || 0; -p5.Amplitude.prototype.toggleNormalize = function (bool) { - if (typeof bool === 'boolean') { - this.normalize = bool; - } else { - this.normalize = !this.normalize; - } + this.sPercent = sPercent || 0; + this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0; + this.rTime = rTime || 0; - this._workletNode.port.postMessage({ - name: 'toggleNormalize', - normalize: this.normalize - }); + this._setRampAD(aTime, dTime); }; /** - * Smooth Amplitude analysis by averaging with the last analysis - * frame. Off by default. + * Set max (attackLevel) and min (releaseLevel) of envelope. + * + * @method setRange + * @for p5.Envelope + * @param {Number} aLevel attack level (defaults to 1) + * @param {Number} rLevel release level (defaults to 0) + * @example + *
+ * let attackLevel = 1.0; + * let releaseLevel = 0; + * + * let attackTime = 0.001; + * let decayTime = 0.2; + * let susPercent = 0.2; + * let releaseTime = 0.5; + * + * let env, triOsc; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playEnv); + * + * env = new p5.Envelope(); + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.freq(220); + * } + * + * function draw() { + * background(220); + * text('tap here to play', 5, 20); + * attackLevel = map(mouseY, height, 0, 0, 1.0); + * text('attack level: ' + attackLevel, 5, height - 20); + * } * - * @method smooth - * @for p5.Amplitude - * @param {Number} set smoothing from 0.0 <= 1 + * function playEnv() { + * triOsc.start(); + * env.setRange(attackLevel, releaseLevel); + * env.play(); + * } + *
*/ -p5.Amplitude.prototype.smooth = function (s) { - if (s >= 0 && s < 1) { - this._workletNode.port.postMessage({ - name: 'smoothing', - smoothing: s - }); - } else { - console.log('Error: smoothing must be between 0 and 1'); - } -}; +p5.Envelope.prototype.setRange = function (aLevel, rLevel) { + this.aLevel = aLevel || 1; + this.rLevel = rLevel || 0; +}; -p5.Amplitude.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - if (this.input) { - this.input.disconnect(); - delete this.input; - } +p5.Envelope.prototype._setRampAD = function (t1, t2) { + this._rampAttackTime = this.checkExpInput(t1); + this._rampDecayTime = this.checkExpInput(t2); + var TCDenominator = 1.0; - if (this.output) { - this.output.disconnect(); - delete this.output; - } + TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)); + this._rampAttackTC = t1 / this.checkExpInput(TCDenominator); + TCDenominator = Math.log(1.0 / this._rampLowPercentage); + this._rampDecayTC = t2 / this.checkExpInput(TCDenominator); +}; - this._workletNode.disconnect(); - delete this._workletNode; -}; +p5.Envelope.prototype.setRampPercentages = function (p1, p2) { + this._rampHighPercentage = this.checkExpInput(p1); + this._rampLowPercentage = this.checkExpInput(p2); + var TCDenominator = 1.0; -/** - *

FFT (Fast Fourier Transform) is an analysis algorithm that - * isolates individual - * - * audio frequencies within a waveform.

- * - *

Once instantiated, a p5.FFT object can return an array based on - * two types of analyses:
• FFT.waveform() computes - * amplitude values along the time domain. The array indices correspond - * to samples across a brief moment in time. Each value represents - * amplitude of the waveform at that sample of time.
- * • FFT.analyze() computes amplitude values along the - * frequency domain. The array indices correspond to frequencies (i.e. - * pitches), from the lowest to the highest that humans can hear. Each - * value represents amplitude at that slice of the frequency spectrum. - * Use with getEnergy() to measure amplitude at specific - * frequencies, or within a range of frequencies.

- * - *

FFT analyzes a very short snapshot of sound called a sample - * buffer. It returns an array of amplitude measurements, referred - * to as bins. The array is 1024 bins long by default. - * You can change the bin array length, but it must be a power of 2 - * between 16 and 1024 in order for the FFT algorithm to function - * correctly. The actual size of the FFT buffer is twice the - * number of bins, so given a standard sample rate, the buffer is - * 2048/44100 seconds long.

- * - * - * @class p5.FFT - * @constructor - * @param {Number} [smoothing] Smooth results of Freq Spectrum. - * 0.0 < smoothing < 1.0. - * Defaults to 0.8. - * @param {Number} [bins] Length of resulting array. - * Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @example - *
- * function preload(){ - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup(){ - * let cnv = createCanvas(100,100); - * cnv.mouseClicked(togglePlay); - * fft = new p5.FFT(); - * sound.amp(0.2); - * } - * - * function draw(){ - * background(220); - * - * let spectrum = fft.analyze(); - * noStroke(); - * fill(255, 0, 255); - * for (let i = 0; i< spectrum.length; i++){ - * let x = map(i, 0, spectrum.length, 0, width); - * let h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width / spectrum.length, h ) - * } - * - * let waveform = fft.waveform(); - * noFill(); - * beginShape(); - * stroke(20); - * for (let i = 0; i < waveform.length; i++){ - * let x = map(i, 0, waveform.length, 0, width); - * let y = map( waveform[i], -1, 1, 0, height); - * vertex(x,y); - * } - * endShape(); - * - * text('tap to play', 20, 20); - * } - * - * function togglePlay() { - * if (sound.isPlaying()) { - * sound.pause(); - * } else { - * sound.loop(); - * } - * } - *
- */ - -p5.FFT = function (smoothing, bins) { - this.input = this.analyser = master.audiocontext.createAnalyser(); - Object.defineProperties(this, { - bins: { - get: function get() { - return this.analyser.fftSize / 2; - }, - set: function set(b) { - this.analyser.fftSize = b * 2; - }, - configurable: true, - enumerable: true - }, - smoothing: { - get: function get() { - return this.analyser.smoothingTimeConstant; - }, - set: function set(s) { - this.analyser.smoothingTimeConstant = s; - }, - configurable: true, - enumerable: true - } - }); - - this.smooth(smoothing); - this.bins = bins || 1024; - - master.fftMeter.connect(this.analyser); - this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount); - this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount); - - this.bass = [20, 140]; - this.lowMid = [140, 400]; - this.mid = [400, 2600]; - this.highMid = [2600, 5200]; - this.treble = [5200, 14000]; - - master.soundArray.push(this); -}; -/** - * Set the input source for the FFT analysis. If no source is - * provided, FFT will analyze all sound in the sketch. - * - * @method setInput - * @for p5.FFT - * @param {Object} [source] p5.sound object (or web audio API source node) - */ - - -p5.FFT.prototype.setInput = function (source) { - if (!source) { - master.fftMeter.connect(this.analyser); - } else { - if (source.output) { - source.output.connect(this.analyser); - } else if (source.connect) { - source.connect(this.analyser); - } - - master.fftMeter.disconnect(); - } -}; -/** - * Returns an array of amplitude values (between -1.0 and +1.0) that represent - * a snapshot of amplitude readings in a single buffer. Length will be - * equal to bins (defaults to 1024). Can be used to draw the waveform - * of a sound. - * - * @method waveform - * @for p5.FFT - * @param {Number} [bins] Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @param {String} [precision] If any value is provided, will return results - * in a Float32 Array which is more precise - * than a regular array. - * @return {Array} Array Array of amplitude values (-1 to 1) - * over time. Array length = bins. - * - */ - - -p5.FFT.prototype.waveform = function () { - var bins, mode; - var normalArray = new Array(); - - for (var i = 0; i < arguments.length; i++) { - if (typeof arguments[i] === 'number') { - bins = arguments[i]; - this.analyser.fftSize = bins * 2; - } - - if (typeof arguments[i] === 'string') { - mode = arguments[i]; - } - } - - - if (mode && !p5.prototype._isSafari()) { - timeToFloat(this, this.timeDomain); - this.analyser.getFloatTimeDomainData(this.timeDomain); - return this.timeDomain; - } else { - timeToInt(this, this.timeDomain); - this.analyser.getByteTimeDomainData(this.timeDomain); - - for (var j = 0; j < this.timeDomain.length; j++) { - var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1); - normalArray.push(scaled); - } - - return normalArray; - } -}; -/** - * Returns an array of amplitude values (between 0 and 255) - * across the frequency spectrum. Length is equal to FFT bins - * (1024 by default). The array indices correspond to frequencies - * (i.e. pitches), from the lowest to the highest that humans can - * hear. Each value represents amplitude at that slice of the - * frequency spectrum. Must be called prior to using - * getEnergy(). - * - * @method analyze - * @for p5.FFT - * @param {Number} [bins] Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @param {Number} [scale] If "dB," returns decibel - * float measurements between - * -140 and 0 (max). - * Otherwise returns integers from 0-255. - * @return {Array} spectrum Array of energy (amplitude/volume) - * values across the frequency spectrum. - * Lowest energy (silence) = 0, highest - * possible is 255. - * @example - *
- * let osc, fft; - * - * function setup(){ - * let cnv = createCanvas(100,100); - * cnv.mousePressed(startSound); - * osc = new p5.Oscillator(); - * osc.amp(0); - * fft = new p5.FFT(); - * } - * - * function draw(){ - * background(220); - * - * let freq = map(mouseX, 0, windowWidth, 20, 10000); - * freq = constrain(freq, 1, 20000); - * osc.freq(freq); - * - * let spectrum = fft.analyze(); - * noStroke(); - * fill(255, 0, 255); - * for (let i = 0; i< spectrum.length; i++){ - * let x = map(i, 0, spectrum.length, 0, width); - * let h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width / spectrum.length, h ); - * } - * - * stroke(255); - * if (!osc.started) { - * text('tap here and drag to change frequency', 10, 20, width - 20); - * } else { - * text(round(freq)+'Hz', 10, 20); - * } - * } - * - * function startSound() { - * osc.start(); - * osc.amp(0.5, 0.2); - * } - * - * function mouseReleased() { - * osc.amp(0, 0.2); - * } - *
- * - * - */ - - -p5.FFT.prototype.analyze = function () { - var mode; - - for (var i = 0; i < arguments.length; i++) { - if (typeof arguments[i] === 'number') { - this.bins = arguments[i]; - this.analyser.fftSize = this.bins * 2; - } - - if (typeof arguments[i] === 'string') { - mode = arguments[i]; - } - } - - if (mode && mode.toLowerCase() === 'db') { - freqToFloat(this); - this.analyser.getFloatFrequencyData(this.freqDomain); - return this.freqDomain; - } else { - freqToInt(this, this.freqDomain); - this.analyser.getByteFrequencyData(this.freqDomain); - var normalArray = Array.apply([], this.freqDomain); - return normalArray; - } -}; -/** - * Returns the amount of energy (volume) at a specific - * - * frequency, or the average amount of energy between two - * frequencies. Accepts Number(s) corresponding - * to frequency (in Hz), or a String corresponding to predefined - * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble"). - * Returns a range between 0 (no energy/volume at that frequency) and - * 255 (maximum energy). - * NOTE: analyze() must be called prior to getEnergy(). Analyze() - * tells the FFT to analyze frequency data, and getEnergy() uses - * the results determine the value at a specific frequency or - * range of frequencies.

- * - * @method getEnergy - * @for p5.FFT - * @param {Number|String} frequency1 Will return a value representing - * energy at this frequency. Alternately, - * the strings "bass", "lowMid" "mid", - * "highMid", and "treble" will return - * predefined frequency ranges. - * @param {Number} [frequency2] If a second frequency is given, - * will return average amount of - * energy that exists between the - * two frequencies. - * @return {Number} Energy Energy (volume/amplitude) from - * 0 and 255. - * - */ - - -p5.FFT.prototype.getEnergy = function (frequency1, frequency2) { - var nyquist = master.audiocontext.sampleRate / 2; - - if (frequency1 === 'bass') { - frequency1 = this.bass[0]; - frequency2 = this.bass[1]; - } else if (frequency1 === 'lowMid') { - frequency1 = this.lowMid[0]; - frequency2 = this.lowMid[1]; - } else if (frequency1 === 'mid') { - frequency1 = this.mid[0]; - frequency2 = this.mid[1]; - } else if (frequency1 === 'highMid') { - frequency1 = this.highMid[0]; - frequency2 = this.highMid[1]; - } else if (frequency1 === 'treble') { - frequency1 = this.treble[0]; - frequency2 = this.treble[1]; - } - - if (typeof frequency1 !== 'number') { - throw 'invalid input for getEnergy()'; - } else if (!frequency2) { - var index = Math.round(frequency1 / nyquist * this.freqDomain.length); - return this.freqDomain[index]; - } else if (frequency1 && frequency2) { - if (frequency1 > frequency2) { - var swap = frequency2; - frequency2 = frequency1; - frequency1 = swap; - } - - var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length); - var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length); - var total = 0; - var numFrequencies = 0; - - for (var i = lowIndex; i <= highIndex; i++) { - total += this.freqDomain[i]; - numFrequencies += 1; - } - - - var toReturn = total / numFrequencies; - return toReturn; - } else { - throw 'invalid input for getEnergy()'; - } -}; - - -p5.FFT.prototype.getFreq = function (freq1, freq2) { - console.log('getFreq() is deprecated. Please use getEnergy() instead.'); - var x = this.getEnergy(freq1, freq2); - return x; -}; -/** - * Returns the - * - * spectral centroid of the input signal. - * NOTE: analyze() must be called prior to getCentroid(). Analyze() - * tells the FFT to analyze frequency data, and getCentroid() uses - * the results determine the spectral centroid.

- * - * @method getCentroid - * @for p5.FFT - * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz. - * - * - * @example - *
- * function setup(){ - * cnv = createCanvas(100,100); - * cnv.mousePressed(userStartAudio); - * sound = new p5.AudioIn(); - * sound.start(); - * fft = new p5.FFT(); - * sound.connect(fft); - *} - * - *function draw() { - * if (getAudioContext().state !== 'running') { - * background(220); - * text('tap here and enable mic to begin', 10, 20, width - 20); - * return; - * } - * let centroidplot = 0.0; - * let spectralCentroid = 0; - * - * background(0); - * stroke(0,255,0); - * let spectrum = fft.analyze(); - * fill(0,255,0); // spectrum is green - * - * //draw the spectrum - * for (let i = 0; i < spectrum.length; i++){ - * let x = map(log(i), 0, log(spectrum.length), 0, width); - * let h = map(spectrum[i], 0, 255, 0, height); - * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length)); - * rect(x, height, rectangle_width, -h ) - * } - * let nyquist = 22050; - * - * // get the centroid - * spectralCentroid = fft.getCentroid(); - * - * // the mean_freq_index calculation is for the display. - * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length); - * - * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width); - * - * stroke(255,0,0); // the line showing where the centroid is will be red - * - * rect(centroidplot, 0, width / spectrum.length, height) - * noStroke(); - * fill(255,255,255); // text is white - * text('centroid: ', 10, 20); - * text(round(spectralCentroid)+' Hz', 10, 40); - *} - *
- */ - - -p5.FFT.prototype.getCentroid = function () { - var nyquist = master.audiocontext.sampleRate / 2; - var cumulative_sum = 0; - var centroid_normalization = 0; - - for (var i = 0; i < this.freqDomain.length; i++) { - cumulative_sum += i * this.freqDomain[i]; - centroid_normalization += this.freqDomain[i]; - } - - var mean_freq_index = 0; - - if (centroid_normalization !== 0) { - mean_freq_index = cumulative_sum / centroid_normalization; - } - - var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length); - return spec_centroid_freq; -}; -/** - * Smooth FFT analysis by averaging with the last analysis frame. - * - * @method smooth - * @param {Number} smoothing 0.0 < smoothing < 1.0. - * Defaults to 0.8. - */ - - -p5.FFT.prototype.smooth = function (s) { - if (typeof s !== 'undefined') { - this.smoothing = s; - } - - return this.smoothing; -}; - -p5.FFT.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - - if (this.analyser) { - this.analyser.disconnect(); - delete this.analyser; - } -}; -/** - * Returns an array of average amplitude values for a given number - * of frequency bands split equally. N defaults to 16. - * NOTE: analyze() must be called prior to linAverages(). Analyze() - * tells the FFT to analyze frequency data, and linAverages() uses - * the results to group them into a smaller set of averages.

- * - * @method linAverages - * @for p5.FFT - * @param {Number} N Number of returned frequency groups - * @return {Array} linearAverages Array of average amplitude values for each group - */ - - -p5.FFT.prototype.linAverages = function (_N) { - var N = _N || 16; - - var spectrum = this.freqDomain; - var spectrumLength = spectrum.length; - var spectrumStep = Math.floor(spectrumLength / N); - var linearAverages = new Array(N); - - var groupIndex = 0; - - for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { - linearAverages[groupIndex] = linearAverages[groupIndex] !== undefined ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; - - if (specIndex % spectrumStep === spectrumStep - 1) { - groupIndex++; - } - } - - return linearAverages; -}; -/** - * Returns an array of average amplitude values of the spectrum, for a given - * set of - * Octave Bands - * NOTE: analyze() must be called prior to logAverages(). Analyze() - * tells the FFT to analyze frequency data, and logAverages() uses - * the results to group them into a smaller set of averages.

- * - * @method logAverages - * @for p5.FFT - * @param {Array} octaveBands Array of Octave Bands objects for grouping - * @return {Array} logAverages Array of average amplitude values for each group - */ - - -p5.FFT.prototype.logAverages = function (octaveBands) { - var nyquist = master.audiocontext.sampleRate / 2; - var spectrum = this.freqDomain; - var spectrumLength = spectrum.length; - var logAverages = new Array(octaveBands.length); - - var octaveIndex = 0; - - for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { - var specIndexFrequency = Math.round(specIndex * nyquist / this.freqDomain.length); - - if (specIndexFrequency > octaveBands[octaveIndex].hi) { - octaveIndex++; - } - - logAverages[octaveIndex] = logAverages[octaveIndex] !== undefined ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; - } - - return logAverages; -}; -/** - * Calculates and Returns the 1/N - * Octave Bands - * N defaults to 3 and minimum central frequency to 15.625Hz. - * (1/3 Octave Bands ~= 31 Frequency Bands) - * Setting fCtr0 to a central value of a higher octave will ignore the lower bands - * and produce less frequency groups. - * - * @method getOctaveBands - * @for p5.FFT - * @param {Number} N Specifies the 1/N type of generated octave bands - * @param {Number} fCtr0 Minimum central frequency for the lowest band - * @return {Array} octaveBands Array of octave band objects with their bounds - */ - - -p5.FFT.prototype.getOctaveBands = function (_N, _fCtr0) { - var N = _N || 3; - - var fCtr0 = _fCtr0 || 15.625; - - var octaveBands = []; - var lastFrequencyBand = { - lo: fCtr0 / Math.pow(2, 1 / (2 * N)), - ctr: fCtr0, - hi: fCtr0 * Math.pow(2, 1 / (2 * N)) - }; - octaveBands.push(lastFrequencyBand); - var nyquist = master.audiocontext.sampleRate / 2; - - while (lastFrequencyBand.hi < nyquist) { - var newFrequencyBand = {}; - newFrequencyBand.lo = lastFrequencyBand.hi; - newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N); - newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N)); - octaveBands.push(newFrequencyBand); - lastFrequencyBand = newFrequencyBand; - } - - return octaveBands; -}; - - -function freqToFloat(fft) { - if (fft.freqDomain instanceof Float32Array === false) { - fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount); - } -} - -function freqToInt(fft) { - if (fft.freqDomain instanceof Uint8Array === false) { - fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount); - } -} - -function timeToFloat(fft) { - if (fft.timeDomain instanceof Float32Array === false) { - fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount); - } -} - -function timeToInt(fft) { - if (fft.timeDomain instanceof Uint8Array === false) { - fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount); - } -} - - var fft = (p5.FFT); -var Signal = __webpack_require__(0); -var Signal_default = __webpack_require__.n(Signal); - -var Add = __webpack_require__(3); -var Add_default = __webpack_require__.n(Add); - -var Multiply = __webpack_require__(2); -var Multiply_default = __webpack_require__.n(Multiply); - -var Scale = __webpack_require__(4); -var Scale_default = __webpack_require__.n(Scale); - - - - - -/** - *

p5.Signal is a constant audio-rate signal used by p5.Oscillator - * and p5.Envelope for modulation math.

- * - *

This is necessary because Web Audio is processed on a separate clock. - * For example, the p5 draw loop runs about 60 times per second. But - * the audio clock must process samples 44100 times per second. If we - * want to add a value to each of those samples, we can't do it in the - * 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 - * a Tone.Signal from the Tone.js library by Yotam Mann. - * If you want to work directly with audio signals for modular - * synthesis, check out - * tone.js.

- * - * @class p5.Signal - * @constructor - * @return {Tone.Signal} A Signal object from the Tone.js library - * @example - *
- * let carrier, modulator; - * let hasStarted = false; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(canvasPressed); - * background(220); - * text('tap to play', 20, 20); - * - * carrier = new p5.Oscillator('sine'); - * carrier.amp(1); // set amplitude - * carrier.freq(220); // set frequency - * - * modulator = new p5.Oscillator('sawtooth'); - * modulator.disconnect(); - * modulator.start(); - * modulator.amp(1); - * modulator.freq(4); - * - * // Modulator's default amplitude range is -1 to 1. - * // Multiply it by -200, so the range is -200 to 200 - * // then add 220 so the range is 20 to 420 - * carrier.freq( modulator.mult(-400).add(220) ); - * } - * - * function canvasPressed() { - * userStartAudio(); - * carrier.amp(1.0); - * if(!hasStarted){ - * carrier.start(); - * hasStarted = true; - * } - * } - * - * function mouseReleased() { - * carrier.amp(0); - * } - *
- */ - -p5.Signal = function (value) { - var s = new Signal_default.a(value); - - return s; -}; -/** - * Fade to value, for smooth transitions - * - * @method fade - * @for p5.Signal - * @param {Number} value Value to set this signal - * @param {Number} [secondsFromNow] Length of fade, in seconds from now - */ - - -Signal_default.a.prototype.fade = Signal_default.a.prototype.linearRampToValueAtTime; -Multiply_default.a.prototype.fade = Signal_default.a.prototype.fade; -Add_default.a.prototype.fade = Signal_default.a.prototype.fade; -Scale_default.a.prototype.fade = Signal_default.a.prototype.fade; -/** - * Connect a p5.sound object or Web Audio node to this - * p5.Signal so that its amplitude values can be scaled. - * - * @method setInput - * @for p5.Signal - * @param {Object} input - */ - -Signal_default.a.prototype.setInput = function (_input) { - _input.connect(this); -}; - -Multiply_default.a.prototype.setInput = Signal_default.a.prototype.setInput; -Add_default.a.prototype.setInput = Signal_default.a.prototype.setInput; -Scale_default.a.prototype.setInput = Signal_default.a.prototype.setInput; - -/** - * Add a constant value to this audio signal, - * and return the resulting audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalAdd. - * - * @method add - * @for p5.Signal - * @param {Number} number - * @return {p5.Signal} object - */ - -Signal_default.a.prototype.add = function (num) { - var add = new Add_default.a(num); - - this.connect(add); - return add; -}; - -Multiply_default.a.prototype.add = Signal_default.a.prototype.add; -Add_default.a.prototype.add = Signal_default.a.prototype.add; -Scale_default.a.prototype.add = Signal_default.a.prototype.add; -/** - * Multiply this signal by a constant value, - * and return the resulting audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalMult. - * - * @method mult - * @for p5.Signal - * @param {Number} number to multiply - * @return {p5.Signal} object - */ - -Signal_default.a.prototype.mult = function (num) { - var mult = new Multiply_default.a(num); - - this.connect(mult); - return mult; -}; - -Multiply_default.a.prototype.mult = Signal_default.a.prototype.mult; -Add_default.a.prototype.mult = Signal_default.a.prototype.mult; -Scale_default.a.prototype.mult = Signal_default.a.prototype.mult; -/** - * Scale this signal value to a given range, - * and return the result as an audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalScale. - * - * @method scale - * @for p5.Signal - * @param {Number} number to multiply - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Signal} object - */ - -Signal_default.a.prototype.scale = function (inMin, inMax, outMin, outMax) { - var mapOutMin, mapOutMax; - - if (arguments.length === 4) { - mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; - mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; - } else { - mapOutMin = arguments[0]; - mapOutMax = arguments[1]; - } - - var scale = new Scale_default.a(mapOutMin, mapOutMax); - this.connect(scale); - return scale; -}; - -Multiply_default.a.prototype.scale = Signal_default.a.prototype.scale; -Add_default.a.prototype.scale = Signal_default.a.prototype.scale; -Scale_default.a.prototype.scale = Signal_default.a.prototype.scale; - - - - -/** - *

Creates a signal that oscillates between -1.0 and 1.0. - * By default, the oscillation takes the form of a sinusoidal - * shape ('sine'). Additional types include 'triangle', - * 'sawtooth' and 'square'. The frequency defaults to - * 440 oscillations per second (440Hz, equal to the pitch of an - * 'A' note).

- * - *

Set the type of oscillation with setType(), or by instantiating a - * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc. - *

- * - * @class p5.Oscillator - * @constructor - * @param {Number} [freq] frequency defaults to 440Hz - * @param {String} [type] type of oscillator. Options: - * 'sine' (default), 'triangle', - * 'sawtooth', 'square' - * @example - *
- * let osc, playing, freq, amp; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playOscillator); - * osc = new p5.Oscillator('sine'); - * } - * - * function draw() { - * background(220) - * freq = constrain(map(mouseX, 0, width, 100, 500), 100, 500); - * amp = constrain(map(mouseY, height, 0, 0, 1), 0, 1); - * - * text('tap to play', 20, 20); - * text('freq: ' + freq, 20, 40); - * text('amp: ' + amp, 20, 60); - * - * if (playing) { - * // smooth the transitions by 0.1 seconds - * osc.freq(freq, 0.1); - * osc.amp(amp, 0.1); - * } - * } - * - * function playOscillator() { - * // starting an oscillator on a user gesture will enable audio - * // in browsers that have a strict autoplay policy. - * // See also: userStartAudio(); - * osc.start(); - * playing = true; - * } - * - * function mouseReleased() { - * // ramp amplitude to 0 over 0.5 seconds - * osc.amp(0, 0.5); - * playing = false; - * } - *
- */ - -p5.Oscillator = function (freq, type) { - if (typeof freq === 'string') { - var f = type; - type = freq; - freq = f; - } - - if (typeof type === 'number') { - var _f = type; - type = freq; - freq = _f; - } - - this.started = false; - - this.phaseAmount = undefined; - this.oscillator = master.audiocontext.createOscillator(); - this.f = freq || 440.0; - - this.oscillator.type = type || 'sine'; - this.oscillator.frequency.setValueAtTime(this.f, master.audiocontext.currentTime); - - this.output = master.audiocontext.createGain(); - this._freqMods = []; - - this.output.gain.value = 0.5; - this.output.gain.setValueAtTime(0.5, master.audiocontext.currentTime); - this.oscillator.connect(this.output); - - this.panPosition = 0.0; - this.connection = master.input; - - this.panner = new p5.Panner(this.output, this.connection, 1); - - this.mathOps = [this.output]; - - master.soundArray.push(this); -}; -/** - * Start an oscillator. - * - * Starting an oscillator on a user gesture will enable audio in browsers - * that have a strict autoplay policy, including Chrome and most mobile - * devices. See also: `userStartAudio()`. - * - * @method start - * @for p5.Oscillator - * @param {Number} [time] startTime in seconds from now. - * @param {Number} [frequency] frequency in Hz. - */ - - -p5.Oscillator.prototype.start = function (time, f) { - if (this.started) { - var now = master.audiocontext.currentTime; - this.stop(now); - } - - if (!this.started) { - var freq = f || this.f; - var type = this.oscillator.type; - - if (this.oscillator) { - this.oscillator.disconnect(); - delete this.oscillator; - } - - - this.oscillator = master.audiocontext.createOscillator(); - this.oscillator.frequency.value = Math.abs(freq); - this.oscillator.type = type; - - this.oscillator.connect(this.output); - time = time || 0; - this.oscillator.start(time + master.audiocontext.currentTime); - this.freqNode = this.oscillator.frequency; - - for (var i in this._freqMods) { - if (typeof this._freqMods[i].connect !== 'undefined') { - this._freqMods[i].connect(this.oscillator.frequency); - } - } - - this.started = true; - } -}; -/** - * Stop an oscillator. Accepts an optional parameter - * to determine how long (in seconds from now) until the - * oscillator stops. - * - * @method stop - * @for p5.Oscillator - * @param {Number} secondsFromNow Time, in seconds from now. - */ - - -p5.Oscillator.prototype.stop = function (time) { - if (this.started) { - var t = time || 0; - var now = master.audiocontext.currentTime; - this.oscillator.stop(t + now); - this.started = false; - } -}; -/** - * Set the amplitude between 0 and 1.0. Or, pass in an object - * such as an oscillator to modulate amplitude with an audio signal. - * - * @method amp - * @for p5.Oscillator - * @param {Number|Object} vol between 0 and 1.0 - * or a modulating signal/oscillator - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {AudioParam} gain If no value is provided, - * returns the Web Audio API - * AudioParam that controls - * this oscillator's - * gain/amplitude/volume) - */ - - -p5.Oscillator.prototype.amp = function (vol) { - var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - - if (typeof vol === 'number') { - var now = master.audiocontext.currentTime; - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(this.output.gain); - } else { - return this.output.gain; - } -}; - - -p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp; -/** - * Returns the value of output gain - * - * @method getAmp - * @for p5.Oscillator - * - * @returns {number} Amplitude value between 0.0 and 1.0 - */ - -p5.Oscillator.prototype.getAmp = function () { - return this.output.gain.value; -}; -/** - * Set frequency of an oscillator to a value. Or, pass in an object - * such as an oscillator to modulate the frequency with an audio signal. - * - * @method freq - * @for p5.Oscillator - * @param {Number|Object} Frequency Frequency in Hz - * or modulating signal/oscillator - * @param {Number} [rampTime] Ramp time (in seconds) - * @param {Number} [timeFromNow] Schedule this event to happen - * at x seconds from now - * @return {AudioParam} Frequency If no value is provided, - * returns the Web Audio API - * AudioParam that controls - * this oscillator's frequency - * @example - *
- * let osc; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playOscillator); - * osc = new p5.Oscillator(300); - * background(220); - * text('tap to play', 20, 20); - * } - * - * function playOscillator() { - * osc.start(); - * osc.amp(0.5); - * // start at 700Hz - * osc.freq(700); - * // ramp to 60Hz over 0.7 seconds - * osc.freq(60, 0.7); - * osc.amp(0, 0.1, 0.7); - * } - *
- */ - - -p5.Oscillator.prototype.freq = function (val) { - var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - - if (typeof val === 'number' && !isNaN(val)) { - this.f = val; - var now = master.audiocontext.currentTime; - - if (rampTime === 0) { - this.oscillator.frequency.setValueAtTime(val, tFromNow + now); - } else { - if (val > 0) { - this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - } else { - this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now); - } - } - - - if (this.phaseAmount) { - this.phase(this.phaseAmount); - } - } else if (val) { - if (val.output) { - val = val.output; - } - - val.connect(this.oscillator.frequency); - - this._freqMods.push(val); - } else { - return this.oscillator.frequency; - } -}; -/** - * Returns the value of frequency of oscillator - * - * @method getFreq - * @for p5.Oscillator - * @returns {number} Frequency of oscillator in Hertz - */ - - -p5.Oscillator.prototype.getFreq = function () { - return this.oscillator.frequency.value; -}; -/** - * Set type to 'sine', 'triangle', 'sawtooth' or 'square'. - * - * @method setType - * @for p5.Oscillator - * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'. - */ - - -p5.Oscillator.prototype.setType = function (type) { - this.oscillator.type = type; -}; -/** - * Returns current type of oscillator eg. 'sine', 'triangle', 'sawtooth' or 'square'. - * - * @method getType - * @for p5.Oscillator - * @returns {String} type of oscillator eg . 'sine', 'triangle', 'sawtooth' or 'square'. - */ - - -p5.Oscillator.prototype.getType = function () { - return this.oscillator.type; -}; -/** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @for p5.Oscillator - * @param {Object} unit A p5.sound or Web Audio object - */ - - -p5.Oscillator.prototype.connect = function (unit) { - if (!unit) { - this.panner.connect(master.input); - } else if (unit.hasOwnProperty('input')) { - this.panner.connect(unit.input); - this.connection = unit.input; - } else { - this.panner.connect(unit); - this.connection = unit; - } -}; -/** - * Disconnect all outputs - * - * @method disconnect - * @for p5.Oscillator - */ - - -p5.Oscillator.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - - if (this.panner) { - this.panner.disconnect(); - - if (this.output) { - this.output.connect(this.panner); - } - } - - this.oscMods = []; -}; -/** - * Pan between Left (-1) and Right (1) - * - * @method pan - * @for p5.Oscillator - * @param {Number} panning Number between -1 and 1 - * @param {Number} timeFromNow schedule this event to happen - * seconds from now - */ - - -p5.Oscillator.prototype.pan = function (pval, tFromNow) { - this.panPosition = pval; - this.panner.pan(pval, tFromNow); -}; -/** - * Returns the current value of panPosition , between Left (-1) and Right (1) - * - * @method getPan - * @for p5.Oscillator - * - * @returns {number} panPosition of oscillator , between Left (-1) and Right (1) - */ - - -p5.Oscillator.prototype.getPan = function () { - return this.panPosition; -}; - - -p5.Oscillator.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - - if (this.oscillator) { - var now = master.audiocontext.currentTime; - this.stop(now); - this.disconnect(); - this.panner = null; - this.oscillator = null; - } - - - if (this.osc2) { - this.osc2.dispose(); - } -}; -/** - * Set the phase of an oscillator between 0.0 and 1.0. - * In this implementation, phase is a delay time - * based on the oscillator's current frequency. - * - * @method phase - * @for p5.Oscillator - * @param {Number} phase float between 0.0 and 1.0 - */ - - -p5.Oscillator.prototype.phase = function (p) { - var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f); - var now = master.audiocontext.currentTime; - this.phaseAmount = p; - - if (!this.dNode) { - this.dNode = master.audiocontext.createDelay(); - - this.oscillator.disconnect(); - this.oscillator.connect(this.dNode); - this.dNode.connect(this.output); - } - - - this.dNode.delayTime.setValueAtTime(delayAmt, now); -}; - - -var sigChain = function sigChain(o, mathObj, thisChain, nextChain, type) { - var chainSource = o.oscillator; - - for (var i in o.mathOps) { - if (o.mathOps[i] instanceof type) { - chainSource.disconnect(); - o.mathOps[i].dispose(); - thisChain = i; - - if (thisChain < o.mathOps.length - 2) { - nextChain = o.mathOps[i + 1]; - } - } - } - - if (thisChain === o.mathOps.length - 1) { - o.mathOps.push(nextChain); - } - - - if (i > 0) { - chainSource = o.mathOps[i - 1]; - } - - chainSource.disconnect(); - chainSource.connect(mathObj); - mathObj.connect(nextChain); - o.mathOps[thisChain] = mathObj; - return o; -}; -/** - * Add a value to the p5.Oscillator's output amplitude, - * and return the oscillator. Calling this method again - * will override the initial add() with a new value. - * - * @method add - * @for p5.Oscillator - * @param {Number} number Constant number to add - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with scaled output - * - */ - - -p5.Oscillator.prototype.add = function (num) { - var add = new Add_default.a(num); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, add, thisChain, nextChain, Add_default.a); -}; -/** - * Multiply the p5.Oscillator's output amplitude - * by a fixed value (i.e. turn it up!). Calling this method - * again will override the initial mult() with a new value. - * - * @method mult - * @for p5.Oscillator - * @param {Number} number Constant number to multiply - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with multiplied output - */ - - -p5.Oscillator.prototype.mult = function (num) { - var mult = new Multiply_default.a(num); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, mult, thisChain, nextChain, Multiply_default.a); -}; -/** - * Scale this oscillator's amplitude values to a given - * range, and return the oscillator. Calling this method - * again will override the initial scale() with new values. - * - * @method scale - * @for p5.Oscillator - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with scaled output - */ - - -p5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) { - var mapOutMin, mapOutMax; - - if (arguments.length === 4) { - mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; - mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; - } else { - mapOutMin = arguments[0]; - mapOutMax = arguments[1]; - } - - var scale = new Scale_default.a(mapOutMin, mapOutMax); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, scale, thisChain, nextChain, Scale_default.a); -}; - -/** - * Constructor: new p5.SinOsc(). - * This creates a Sine Wave Oscillator and is - * equivalent to new p5.Oscillator('sine') - * or creating a p5.Oscillator and then calling - * its method setType('sine'). - * See p5.Oscillator for methods. - * - * @class p5.SinOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - - -p5.SinOsc = function (freq) { - p5.Oscillator.call(this, freq, 'sine'); -}; - -p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype); -/** - * Constructor: new p5.TriOsc(). - * This creates a Triangle Wave Oscillator and is - * equivalent to new p5.Oscillator('triangle') - * or creating a p5.Oscillator and then calling - * its method setType('triangle'). - * See p5.Oscillator for methods. - * - * @class p5.TriOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - -p5.TriOsc = function (freq) { - p5.Oscillator.call(this, freq, 'triangle'); -}; - -p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype); -/** - * Constructor: new p5.SawOsc(). - * This creates a SawTooth Wave Oscillator and is - * equivalent to new p5.Oscillator('sawtooth') - * or creating a p5.Oscillator and then calling - * its method setType('sawtooth'). - * See p5.Oscillator for methods. - * - * @class p5.SawOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - -p5.SawOsc = function (freq) { - p5.Oscillator.call(this, freq, 'sawtooth'); -}; - -p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype); -/** - * Constructor: new p5.SqrOsc(). - * This creates a Square Wave Oscillator and is - * equivalent to new p5.Oscillator('square') - * or creating a p5.Oscillator and then calling - * its method setType('square'). - * See p5.Oscillator for methods. - * - * @class p5.SqrOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - -p5.SqrOsc = function (freq) { - p5.Oscillator.call(this, freq, 'square'); -}; - -p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype); -var Oscillator = p5.Oscillator; -var TimelineSignal = __webpack_require__(8); -var TimelineSignal_default = __webpack_require__.n(TimelineSignal); - - - - - - -/** - *

Envelopes are pre-defined amplitude distribution over time. - * Typically, envelopes are used to control the output volume - * of an object, a series of fades referred to as Attack, Decay, - * Sustain and Release ( - * ADSR - * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can - * control an Oscillator's frequency like this: osc.freq(env).

- *

Use setRange to change the attack/release level. - * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

- *

Use the play method to play the entire envelope, - * the ramp method for a pingable trigger, - * or triggerAttack/ - * triggerRelease to trigger noteOn/noteOff.

- * - * @class p5.Envelope - * @constructor - * @example - *
- * let t1 = 0.1; // attack time in seconds - * let l1 = 0.7; // attack level 0.0 to 1.0 - * let t2 = 0.3; // decay time in seconds - * let l2 = 0.1; // decay level 0.0 to 1.0 - * - * let env; - * let triOsc; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * background(220); - * text('tap to play', 20, 20); - * cnv.mousePressed(playSound); - * - * env = new p5.Envelope(t1, l1, t2, l2); - * triOsc = new p5.Oscillator('triangle'); - * } - * - * function playSound() { - * // starting the oscillator ensures that audio is enabled. - * triOsc.start(); - * env.play(triOsc); - * } - *
- */ - -p5.Envelope = function (t1, l1, t2, l2, t3, l3) { - /** - * Time until envelope reaches attackLevel - * @property attackTime - */ - this.aTime = t1 || 0.1; - /** - * Level once attack is complete. - * @property attackLevel - */ - - this.aLevel = l1 || 1; - /** - * Time until envelope reaches decayLevel. - * @property decayTime - */ - - this.dTime = t2 || 0.5; - /** - * Level after decay. The envelope will sustain here until it is released. - * @property decayLevel - */ - - this.dLevel = l2 || 0; - /** - * Duration of the release portion of the envelope. - * @property releaseTime - */ - - this.rTime = t3 || 0; - /** - * Level at the end of the release. - * @property releaseLevel - */ - - this.rLevel = l3 || 0; - this._rampHighPercentage = 0.98; - this._rampLowPercentage = 0.02; - this.output = master.audiocontext.createGain(); - this.control = new TimelineSignal_default.a(); - - this._init(); - - - this.control.connect(this.output); - - this.connection = null; - - this.mathOps = [this.control]; - - this.isExponential = false; - - this.sourceToClear = null; - - this.wasTriggered = false; - - master.soundArray.push(this); -}; - - -p5.Envelope.prototype._init = function () { - var now = master.audiocontext.currentTime; - var t = now; - this.control.setTargetAtTime(0.00001, t, 0.001); - - this._setRampAD(this.aTime, this.dTime); -}; -/** - * Reset the envelope with a series of time/value pairs. - * - * @method set - * @for p5.Envelope - * @param {Number} attackTime Time (in seconds) before level - * reaches attackLevel - * @param {Number} attackLevel Typically an amplitude between - * 0.0 and 1.0 - * @param {Number} decayTime Time - * @param {Number} decayLevel Amplitude (In a standard ADSR envelope, - * decayLevel = sustainLevel) - * @param {Number} releaseTime Release Time (in seconds) - * @param {Number} releaseLevel Amplitude - * @example - *
- * let attackTime; - * let l1 = 0.7; // attack level 0.0 to 1.0 - * let t2 = 0.3; // decay time in seconds - * let l2 = 0.1; // decay level 0.0 to 1.0 - * let l3 = 0.2; // release time in seconds - * - * let env, triOsc; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playSound); - * - * env = new p5.Envelope(); - * triOsc = new p5.Oscillator('triangle'); - * } - * - * function draw() { - * background(220); - * text('tap here to play', 5, 20); - * - * attackTime = map(mouseX, 0, width, 0.0, 1.0); - * text('attack time: ' + attackTime, 5, height - 20); - * } - * - * // mouseClick triggers envelope if over canvas - * function playSound() { - * env.set(attackTime, l1, t2, l2, l3); - * - * triOsc.start(); - * env.play(triOsc); - * } - *
- * - */ - - -p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) { - this.aTime = t1; - this.aLevel = l1; - this.dTime = t2 || 0; - this.dLevel = l2 || 0; - this.rTime = t3 || 0; - this.rLevel = l3 || 0; - - this._setRampAD(t1, t2); -}; -/** - * Set values like a traditional - * - * ADSR envelope - * . - * - * @method setADSR - * @for p5.Envelope - * @param {Number} attackTime Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - * @example - *
- * let attackLevel = 1.0; - * let releaseLevel = 0; - * - * let attackTime = 0.001; - * let decayTime = 0.2; - * let susPercent = 0.2; - * let releaseTime = 0.5; - * - * let env, triOsc; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playEnv); - * - * env = new p5.Envelope(); - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.freq(220); - * } - * - * function draw() { - * background(220); - * text('tap here to play', 5, 20); - * attackTime = map(mouseX, 0, width, 0, 1.0); - * text('attack time: ' + attackTime, 5, height - 40); - * } - * - * function playEnv() { - * triOsc.start(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.play(); - * } - *
- */ - - -p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) { - this.aTime = aTime; - this.dTime = dTime || 0; - - this.sPercent = sPercent || 0; - this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0; - this.rTime = rTime || 0; - - this._setRampAD(aTime, dTime); -}; -/** - * Set max (attackLevel) and min (releaseLevel) of envelope. - * - * @method setRange - * @for p5.Envelope - * @param {Number} aLevel attack level (defaults to 1) - * @param {Number} rLevel release level (defaults to 0) - * @example - *
- * let attackLevel = 1.0; - * let releaseLevel = 0; - * - * let attackTime = 0.001; - * let decayTime = 0.2; - * let susPercent = 0.2; - * let releaseTime = 0.5; - * - * let env, triOsc; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playEnv); - * - * env = new p5.Envelope(); - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.freq(220); - * } - * - * function draw() { - * background(220); - * text('tap here to play', 5, 20); - * attackLevel = map(mouseY, height, 0, 0, 1.0); - * text('attack level: ' + attackLevel, 5, height - 20); - * } - * - * function playEnv() { - * triOsc.start(); - * env.setRange(attackLevel, releaseLevel); - * env.play(); - * } - *
- */ - - -p5.Envelope.prototype.setRange = function (aLevel, rLevel) { - this.aLevel = aLevel || 1; - this.rLevel = rLevel || 0; -}; - - -p5.Envelope.prototype._setRampAD = function (t1, t2) { - this._rampAttackTime = this.checkExpInput(t1); - this._rampDecayTime = this.checkExpInput(t2); - var TCDenominator = 1.0; - - TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)); - this._rampAttackTC = t1 / this.checkExpInput(TCDenominator); - TCDenominator = Math.log(1.0 / this._rampLowPercentage); - this._rampDecayTC = t2 / this.checkExpInput(TCDenominator); -}; - - -p5.Envelope.prototype.setRampPercentages = function (p1, p2) { - this._rampHighPercentage = this.checkExpInput(p1); - this._rampLowPercentage = this.checkExpInput(p2); - var TCDenominator = 1.0; - - TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)); - this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator); - TCDenominator = Math.log(1.0 / this._rampLowPercentage); - this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator); -}; + TCDenominator = Math.log(1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)); + this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator); + TCDenominator = Math.log(1.0 / this._rampLowPercentage); + this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator); +}; /** * Assign a parameter to be controlled by this envelope. * If a p5.Sound object is given, then the p5.Envelope will control its @@ -5819,10 +5656,6 @@ p5.Envelope.prototype.connect = function (unit) { unit.setValueAtTime(0, master.audiocontext.currentTime); } - if (unit instanceof p5.Signal) { - unit.setValue(0); - } - this.output.connect(unit); }; @@ -5840,281 +5673,103 @@ p5.Envelope.prototype.disconnect = function () { * @method add * @for p5.Envelope * @param {Number} number Constant number to add - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - - -p5.Envelope.prototype.add = function (num) { - var add = new Add_default.a(num); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, add, thisChain, nextChain, Add_default.a); -}; -/** - * Multiply the p5.Envelope's output amplitude - * by a fixed value. Calling this method - * again will override the initial mult() with new values. - * - * @method mult - * @for p5.Envelope - * @param {Number} number Constant number to multiply - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - - -p5.Envelope.prototype.mult = function (num) { - var mult = new Multiply_default.a(num); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, mult, thisChain, nextChain, Multiply_default.a); -}; -/** - * Scale this envelope's amplitude values to a given - * range, and return the envelope. Calling this method - * again will override the initial scale() with new values. - * - * @method scale - * @for p5.Envelope - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - - -p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) { - var scale = new Scale_default.a(inMin, inMax, outMin, outMax); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale_default.a); -}; - - -p5.Envelope.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - this.disconnect(); - - if (this.control) { - this.control.dispose(); - this.control = null; - } - - for (var i = 1; i < this.mathOps.length; i++) { - this.mathOps[i].dispose(); - } -}; - - -p5.Env = function (t1, l1, t2, l2, t3, l3) { - console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' + 'Please use the new p5.Envelope instead.'); - p5.Envelope.call(this, t1, l1, t2, l2, t3, l3); -}; - -p5.Env.prototype = Object.create(p5.Envelope.prototype); - var envelope = (p5.Envelope); - - -/** - * Creates a Pulse object, an oscillator that implements - * Pulse Width Modulation. - * The pulse is created with two oscillators. - * Accepts a parameter for frequency, and to set the - * width between the pulses. See - * p5.Oscillator for a full list of methods. - * - * @class p5.Pulse - * @extends p5.Oscillator - * @constructor - * @param {Number} [freq] Frequency in oscillations per second (Hz) - * @param {Number} [w] Width between the pulses (0 to 1.0, - * defaults to 0) - * @example - *
- * let pulse; - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(startPulse); - * background(220); - * - * pulse = new p5.Pulse(); - * pulse.amp(0.5); - * pulse.freq(220); - * } - * function startPulse() { - * pulse.start(); - * pulse.amp(0.5, 0.02); - * } - * function mouseReleased() { - * pulse.amp(0, 0.2); - * } - * function draw() { - * background(220); - * text('tap to play', 5, 20, width - 20); - * let w = map(mouseX, 0, width, 0, 1); - * w = constrain(w, 0, 1); - * pulse.width(w); - * text('pulse width: ' + w, 5, height - 20); - * } - *
+ * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output */ -p5.Pulse = function (freq, w) { - p5.Oscillator.call(this, freq, 'sawtooth'); - - this.w = w || 0; - - this.osc2 = new p5.SawOsc(freq); - - this.dNode = master.audiocontext.createDelay(); - - this.dcOffset = createDCOffset(); - this.dcGain = master.audiocontext.createGain(); - this.dcOffset.connect(this.dcGain); - this.dcGain.connect(this.output); - - this.f = freq || 440; - var mW = this.w / this.oscillator.frequency.value; - this.dNode.delayTime.value = mW; - this.dcGain.gain.value = 1.7 * (0.5 - this.w); - - this.osc2.disconnect(); - this.osc2.panner.disconnect(); - this.osc2.amp(-1); - this.osc2.output.connect(this.dNode); - this.dNode.connect(this.output); - this.output.gain.value = 1; - this.output.connect(this.panner); +p5.Envelope.prototype.add = function (num) { + var add = new Add_default.a(num); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, add, thisChain, nextChain, Add_default.a); }; - -p5.Pulse.prototype = Object.create(p5.Oscillator.prototype); /** - * Set the width of a Pulse object (an oscillator that implements - * Pulse Width Modulation). + * Multiply the p5.Envelope's output amplitude + * by a fixed value. Calling this method + * again will override the initial mult() with new values. * - * @method width - * @param {Number} [width] Width between the pulses (0 to 1.0, - * defaults to 0) + * @method mult + * @for p5.Envelope + * @param {Number} number Constant number to multiply + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output */ -p5.Pulse.prototype.width = function (w) { - if (typeof w === 'number') { - if (w <= 1.0 && w >= 0.0) { - this.w = w; - - var mW = this.w / this.oscillator.frequency.value; - this.dNode.delayTime.value = mW; - } - this.dcGain.gain.value = 1.7 * (0.5 - this.w); - } else { - w.connect(this.dNode.delayTime); - var sig = new p5.SignalAdd(-0.5); - sig.setInput(w); - sig = sig.mult(-1); - sig = sig.mult(1.7); - sig.connect(this.dcGain.gain); - } +p5.Envelope.prototype.mult = function (num) { + var mult = new Multiply_default.a(num); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, mult, thisChain, nextChain, Multiply_default.a); }; +/** + * Scale this envelope's amplitude values to a given + * range, and return the envelope. Calling this method + * again will override the initial scale() with new values. + * + * @method scale + * @for p5.Envelope + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output + */ -p5.Pulse.prototype.start = function (f, time) { - var now = master.audiocontext.currentTime; - var t = time || 0; - if (!this.started) { - var freq = f || this.f; - var type = this.oscillator.type; - this.oscillator = master.audiocontext.createOscillator(); - this.oscillator.frequency.setValueAtTime(freq, now); - this.oscillator.type = type; - this.oscillator.connect(this.output); - this.oscillator.start(t + now); +p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) { + var scale = new Scale_default.a(inMin, inMax, outMin, outMax); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale_default.a); +}; - this.osc2.oscillator = master.audiocontext.createOscillator(); - this.osc2.oscillator.frequency.setValueAtTime(freq, t + now); - this.osc2.oscillator.type = type; - this.osc2.oscillator.connect(this.osc2.output); - this.osc2.start(t + now); - this.freqNode = [this.oscillator.frequency, this.osc2.oscillator.frequency]; - this.dcOffset = createDCOffset(); - this.dcOffset.connect(this.dcGain); - this.dcOffset.start(t + now); +p5.Envelope.prototype.dispose = function () { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + this.disconnect(); - if (this.mods !== undefined && this.mods.frequency !== undefined) { - this.mods.frequency.connect(this.freqNode[0]); - this.mods.frequency.connect(this.freqNode[1]); - } + if (this.control) { + this.control.dispose(); + this.control = null; + } - this.started = true; - this.osc2.started = true; + for (var i = 1; i < this.mathOps.length; i++) { + this.mathOps[i].dispose(); } +}; + + +p5.Env = function (t1, l1, t2, l2, t3, l3) { + console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' + 'Please use the new p5.Envelope instead.'); + p5.Envelope.call(this, t1, l1, t2, l2, t3, l3); }; -p5.Pulse.prototype.stop = function (time) { - if (this.started) { - var t = time || 0; - var now = master.audiocontext.currentTime; - this.oscillator.stop(t + now); +p5.Env.prototype = Object.create(p5.Envelope.prototype); +var Envelope = p5.Envelope; + var envelope = (Envelope); +function noise_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { noise_typeof = function _typeof(obj) { return typeof obj; }; } else { noise_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return noise_typeof(obj); } - if (this.osc2.oscillator) { - this.osc2.oscillator.stop(t + now); - } +function noise_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - this.dcOffset.stop(t + now); - this.started = false; - this.osc2.started = false; - } -}; +function noise_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); } } -p5.Pulse.prototype.freq = function (val) { - var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; +function noise_createClass(Constructor, protoProps, staticProps) { if (protoProps) noise_defineProperties(Constructor.prototype, protoProps); if (staticProps) noise_defineProperties(Constructor, staticProps); return Constructor; } - if (typeof val === 'number') { - this.f = val; - var now = master.audiocontext.currentTime; - var currentFreq = this.oscillator.frequency.value; - this.oscillator.frequency.cancelScheduledValues(now); - this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); - this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - this.osc2.oscillator.frequency.cancelScheduledValues(now); - this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); - this.osc2.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - - if (this.freqMod) { - this.freqMod.output.disconnect(); - this.freqMod = null; - } - } else if (val.output) { - val.output.disconnect(); - val.output.connect(this.oscillator.frequency); - val.output.connect(this.osc2.oscillator.frequency); - this.freqMod = val; - } -}; +function noise_possibleConstructorReturn(self, call) { if (call && (noise_typeof(call) === "object" || typeof call === "function")) { return call; } return noise_assertThisInitialized(self); } +function noise_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } -function createDCOffset() { - var ac = master.audiocontext; - var buffer = ac.createBuffer(1, 2048, ac.sampleRate); - var data = buffer.getChannelData(0); +function noise_getPrototypeOf(o) { noise_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return noise_getPrototypeOf(o); } + +function noise_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) noise_setPrototypeOf(subClass, superClass); } + +function noise_setPrototypeOf(o, p) { noise_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return noise_setPrototypeOf(o, p); } - for (var i = 0; i < 2048; i++) { - data[i] = 1.0; - } - var bufferSource = ac.createBufferSource(); - bufferSource.buffer = buffer; - bufferSource.loop = true; - return bufferSource; -} var _whiteNoiseBuffer = function () { var bufferSize = 2 * master.audiocontext.sampleRate; @@ -6181,109 +5836,388 @@ var _brownNoiseBuffer = function () { */ -p5.Noise = function (type) { - var assignType; - p5.Oscillator.call(this); - delete this.f; - delete this.freq; - delete this.oscillator; +var noise_Noise = +function (_Oscillator) { + noise_inherits(Noise, _Oscillator); - if (type === 'brown') { - assignType = _brownNoiseBuffer; - } else if (type === 'pink') { - assignType = _pinkNoiseBuffer; - } else { - assignType = _whiteNoiseBuffer; + function Noise(type) { + var _this; + + noise_classCallCheck(this, Noise); + + _this = noise_possibleConstructorReturn(this, noise_getPrototypeOf(Noise).call(this)); + var assignType; + delete _this.f; + delete _this.freq; + delete _this.oscillator; + + if (type === 'brown') { + assignType = _brownNoiseBuffer; + } else if (type === 'pink') { + assignType = _pinkNoiseBuffer; + } else { + assignType = _whiteNoiseBuffer; + } + + _this.buffer = assignType; + return _this; } + /** + * Set type of noise to 'white', 'pink' or 'brown'. + * White is the default. + * + * @method setType + * @param {String} [type] 'white', 'pink' or 'brown' + */ + + + noise_createClass(Noise, [{ + key: "setType", + value: function setType(type) { + switch (type) { + case 'white': + this.buffer = _whiteNoiseBuffer; + break; + + case 'pink': + this.buffer = _pinkNoiseBuffer; + break; + + case 'brown': + this.buffer = _brownNoiseBuffer; + break; + + default: + this.buffer = _whiteNoiseBuffer; + } + + if (this.started) { + var now = master.audiocontext.currentTime; + this.stop(now); + this.start(now + 0.01); + } + } + }, { + key: "getType", + value: function getType() { + return this.buffer.type; + } + }, { + key: "start", + value: function start() { + if (this.started) { + this.stop(); + } + + this.noise = master.audiocontext.createBufferSource(); + this.noise.buffer = this.buffer; + this.noise.loop = true; + this.noise.connect(this.output); + var now = master.audiocontext.currentTime; + this.noise.start(now); + this.started = true; + } + }, { + key: "stop", + value: function stop() { + var now = master.audiocontext.currentTime; + + if (this.noise) { + this.noise.stop(now); + this.started = false; + } + } + }, { + key: "dispose", + value: function dispose() { + var now = master.audiocontext.currentTime; + + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + + if (this.noise) { + this.noise.disconnect(); + this.stop(now); + } + + if (this.output) { + this.output.disconnect(); + } + + if (this.panner) { + this.panner.disconnect(); + } + + this.output = null; + this.panner = null; + this.buffer = null; + this.noise = null; + } + }]); + + return Noise; +}(oscillator); + + var noise = (noise_Noise); +var Signal = __webpack_require__(2); +var Signal_default = __webpack_require__.n(Signal); + +function pulse_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { pulse_typeof = function _typeof(obj) { return typeof obj; }; } else { pulse_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return pulse_typeof(obj); } + +function pulse_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function pulse_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); } } + +function pulse_createClass(Constructor, protoProps, staticProps) { if (protoProps) pulse_defineProperties(Constructor.prototype, protoProps); if (staticProps) pulse_defineProperties(Constructor, staticProps); return Constructor; } + +function pulse_possibleConstructorReturn(self, call) { if (call && (pulse_typeof(call) === "object" || typeof call === "function")) { return call; } return pulse_assertThisInitialized(self); } + +function pulse_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function pulse_getPrototypeOf(o) { pulse_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return pulse_getPrototypeOf(o); } + +function pulse_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) pulse_setPrototypeOf(subClass, superClass); } + +function pulse_setPrototypeOf(o, p) { pulse_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return pulse_setPrototypeOf(o, p); } + + + - this.buffer = assignType; -}; -p5.Noise.prototype = Object.create(p5.Oscillator.prototype); /** - * Set type of noise to 'white', 'pink' or 'brown'. - * White is the default. + * Creates a Pulse object, an oscillator that implements + * Pulse Width Modulation. + * The pulse is created with two oscillators. + * Accepts a parameter for frequency, and to set the + * width between the pulses. See
+ * p5.Oscillator for a full list of methods. + * + * @class p5.Pulse + * @extends p5.Oscillator + * @constructor + * @param {Number} [freq] Frequency in oscillations per second (Hz) + * @param {Number} [w] Width between the pulses (0 to 1.0, + * defaults to 0) + * @example + *
+ * let pulse; + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(startPulse); + * background(220); * - * @method setType - * @param {String} [type] 'white', 'pink' or 'brown' + * pulse = new p5.Pulse(); + * pulse.amp(0.5); + * pulse.freq(220); + * } + * function startPulse() { + * pulse.start(); + * pulse.amp(0.5, 0.02); + * } + * function mouseReleased() { + * pulse.amp(0, 0.2); + * } + * function draw() { + * background(220); + * text('tap to play', 5, 20, width - 20); + * let w = map(mouseX, 0, width, 0, 1); + * w = constrain(w, 0, 1); + * pulse.width(w); + * text('pulse width: ' + w, 5, height - 20); + * } + *
*/ -p5.Noise.prototype.setType = function (type) { - switch (type) { - case 'white': - this.buffer = _whiteNoiseBuffer; - break; +var pulse_Pulse = +function (_Oscillator) { + pulse_inherits(Pulse, _Oscillator); - case 'pink': - this.buffer = _pinkNoiseBuffer; - break; + function Pulse(freq, w) { + var _this; - case 'brown': - this.buffer = _brownNoiseBuffer; - break; + pulse_classCallCheck(this, Pulse); - default: - this.buffer = _whiteNoiseBuffer; - } + _this = pulse_possibleConstructorReturn(this, pulse_getPrototypeOf(Pulse).call(this, freq, 'sawtooth')); - if (this.started) { - var now = master.audiocontext.currentTime; - this.stop(now); - this.start(now + 0.01); - } -}; + _this.w = w || 0; -p5.Noise.prototype.getType = function () { - return this.buffer.type; -}; + _this.osc2 = new SawOsc(freq); -p5.Noise.prototype.start = function () { - if (this.started) { - this.stop(); - } + _this.dNode = master.audiocontext.createDelay(); - this.noise = master.audiocontext.createBufferSource(); - this.noise.buffer = this.buffer; - this.noise.loop = true; - this.noise.connect(this.output); - var now = master.audiocontext.currentTime; - this.noise.start(now); - this.started = true; -}; + _this.dcOffset = createDCOffset(); + _this.dcGain = master.audiocontext.createGain(); -p5.Noise.prototype.stop = function () { - var now = master.audiocontext.currentTime; + _this.dcOffset.connect(_this.dcGain); + + _this.dcGain.connect(_this.output); + + + _this.f = freq || 440; + var mW = _this.w / _this.oscillator.frequency.value; + _this.dNode.delayTime.value = mW; + _this.dcGain.gain.value = 1.7 * (0.5 - _this.w); + + _this.osc2.disconnect(); + + _this.osc2.panner.disconnect(); + + _this.osc2.amp(-1); - if (this.noise) { - this.noise.stop(now); - this.started = false; + + _this.osc2.output.connect(_this.dNode); + + _this.dNode.connect(_this.output); + + _this.output.gain.value = 1; + + _this.output.connect(_this.panner); + + return _this; } -}; + /** + * Set the width of a Pulse object (an oscillator that implements + * Pulse Width Modulation). + * + * @method width + * @param {Number} [width] Width between the pulses (0 to 1.0, + * defaults to 0) + */ -p5.Noise.prototype.dispose = function () { - var now = master.audiocontext.currentTime; - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); + pulse_createClass(Pulse, [{ + key: "width", + value: function width(w) { + if (typeof w === 'number') { + if (w <= 1.0 && w >= 0.0) { + this.w = w; + + var mW = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = mW; + } + + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + w.connect(this.dNode.delayTime); + var sig = new Signal_default.a(-0.5); + + w.connect(sig); + var mult1 = new Multiply_default.a(-1); + var mult2 = new Multiply_default.a(1.7); + sig = sig.connect(mult1).connect(mult2); + sig.connect(this.dcGain.gain); + } + } + }, { + key: "start", + value: function start(f, time) { + var now = master.audiocontext.currentTime; + var t = time || 0; + + if (!this.started) { + var freq = f || this.f; + var type = this.oscillator.type; + this.oscillator = master.audiocontext.createOscillator(); + this.oscillator.frequency.setValueAtTime(freq, now); + this.oscillator.type = type; + this.oscillator.connect(this.output); + this.oscillator.start(t + now); + + this.osc2.oscillator = master.audiocontext.createOscillator(); + this.osc2.oscillator.frequency.setValueAtTime(freq, t + now); + this.osc2.oscillator.type = type; + this.osc2.oscillator.connect(this.osc2.output); + this.osc2.start(t + now); + this.freqNode = [this.oscillator.frequency, this.osc2.oscillator.frequency]; + + this.dcOffset = createDCOffset(); + this.dcOffset.connect(this.dcGain); + this.dcOffset.start(t + now); + + if (this.mods !== undefined && this.mods.frequency !== undefined) { + this.mods.frequency.connect(this.freqNode[0]); + this.mods.frequency.connect(this.freqNode[1]); + } + + this.started = true; + this.osc2.started = true; + } + } + }, { + key: "stop", + value: function stop(time) { + if (this.started) { + var t = time || 0; + var now = master.audiocontext.currentTime; + this.oscillator.stop(t + now); + + if (this.osc2.oscillator) { + this.osc2.oscillator.stop(t + now); + } + + this.dcOffset.stop(t + now); + this.started = false; + this.osc2.started = false; + } + } + }, { + key: "freq", + value: function freq(val) { + var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + + if (typeof val === 'number') { + this.f = val; + var now = master.audiocontext.currentTime; + var currentFreq = this.oscillator.frequency.value; + this.oscillator.frequency.cancelScheduledValues(now); + this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); + this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); + this.osc2.oscillator.frequency.cancelScheduledValues(now); + this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); + this.osc2.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); + + if (this.freqMod) { + this.freqMod.output.disconnect(); + this.freqMod = null; + } + } else if (val.output) { + val.output.disconnect(); + val.output.connect(this.oscillator.frequency); + val.output.connect(this.osc2.oscillator.frequency); + this.freqMod = val; + } + } + }]); + + return Pulse; +}(oscillator); + + +function createDCOffset() { + var ac = master.audiocontext; + var buffer = ac.createBuffer(1, 2048, ac.sampleRate); + var data = buffer.getChannelData(0); + + for (var i = 0; i < 2048; i++) { + data[i] = 1.0; + } + + var bufferSource = ac.createBufferSource(); + bufferSource.buffer = buffer; + bufferSource.loop = true; + return bufferSource; +} - if (this.noise) { - this.noise.disconnect(); - this.stop(now); - } + var pulse = (pulse_Pulse); +function audioin_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - if (this.output) { - this.output.disconnect(); - } +function audioin_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); } } + +function audioin_createClass(Constructor, protoProps, staticProps) { if (protoProps) audioin_defineProperties(Constructor.prototype, protoProps); if (staticProps) audioin_defineProperties(Constructor, staticProps); return Constructor; } - if (this.panner) { - this.panner.disconnect(); - } - this.output = null; - this.panner = null; - this.buffer = null; - this.noise = null; -}; master.inputSources = []; /** @@ -6313,7 +6247,7 @@ master.inputSources = []; * * function setup(){ * let cnv = createCanvas(100, 100); - * cnv.mousePressed(userStartAudio); + * cnv.mousePressed(useraudiocontextStartAudio); * textAlign(CENTER); * mic = new p5.AudioIn(); * mic.start(); @@ -6331,340 +6265,366 @@ master.inputSources = []; * */ -p5.AudioIn = function (errorCallback) { - - /** - * @property {GainNode} input - */ - this.input = master.audiocontext.createGain(); - /** - * @property {GainNode} output - */ - - this.output = master.audiocontext.createGain(); - /** - * @property {MediaStream|null} stream - */ +var audioin_AudioIn = +function () { + function AudioIn(errorCallback) { + audioin_classCallCheck(this, AudioIn); + + + /** + * @property {GainNode} input + */ + this.input = master.audiocontext.createGain(); + /** + * @property {GainNode} output + */ + + this.output = master.audiocontext.createGain(); + /** + * @property {MediaStream|null} stream + */ + + this.stream = null; + /** + * @property {MediaStreamAudioSourceNode|null} mediaStream + */ + + this.mediaStream = null; + /** + * @property {Number|null} currentSource + */ + + this.currentSource = null; + /** + * Client must allow browser to access their microphone / audioin source. + * Default: false. Will become true when the client enables access. + * + * @property {Boolean} enabled + */ + + this.enabled = false; + /** + * Input amplitude, connect to it by default but not to master out + * + * @property {p5.Amplitude} amplitude + */ + + this.amplitude = new amplitude(); + this.output.connect(this.amplitude.input); - this.stream = null; - /** - * @property {MediaStreamAudioSourceNode|null} mediaStream - */ + if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) { + errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices'); + } - this.mediaStream = null; - /** - * @property {Number|null} currentSource - */ - this.currentSource = null; + master.soundArray.push(this); + } /** - * Client must allow browser to access their microphone / audioin source. - * Default: false. Will become true when the client enables access. + * Start processing audio input. This enables the use of other + * AudioIn methods like getLevel(). Note that by default, AudioIn + * is not connected to p5.sound's output. So you won't hear + * anything unless you use the connect() method.
* - * @property {Boolean} enabled - */ - - this.enabled = false; - /** - * Input amplitude, connect to it by default but not to master out + * Certain browsers limit access to the user's microphone. For example, + * Chrome only allows access from localhost and over https. For this reason, + * you may want to include an errorCallback—a function that is called in case + * the browser won't provide mic access. * - * @property {p5.Amplitude} amplitude + * @method start + * @for p5.AudioIn + * @param {Function} [successCallback] Name of a function to call on + * success. + * @param {Function} [errorCallback] Name of a function to call if + * there was an error. For example, + * some browsers do not support + * getUserMedia. */ - this.amplitude = new p5.Amplitude(); - this.output.connect(this.amplitude.input); - if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) { - errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices'); - } + audioin_createClass(AudioIn, [{ + key: "start", + value: function start(successCallback, errorCallback) { + var self = this; + if (this.stream) { + this.stop(); + } - master.soundArray.push(this); -}; -/** - * Start processing audio input. This enables the use of other - * AudioIn methods like getLevel(). Note that by default, AudioIn - * is not connected to p5.sound's output. So you won't hear - * anything unless you use the connect() method.
- * - * Certain browsers limit access to the user's microphone. For example, - * Chrome only allows access from localhost and over https. For this reason, - * you may want to include an errorCallback—a function that is called in case - * the browser won't provide mic access. - * - * @method start - * @for p5.AudioIn - * @param {Function} [successCallback] Name of a function to call on - * success. - * @param {Function} [errorCallback] Name of a function to call if - * there was an error. For example, - * some browsers do not support - * getUserMedia. - */ + var audioSource = master.inputSources[self.currentSource]; + var constraints = { + audio: { + sampleRate: master.audiocontext.sampleRate, + echoCancellation: false + } + }; -p5.AudioIn.prototype.start = function (successCallback, errorCallback) { - var self = this; + if (master.inputSources[this.currentSource]) { + constraints.audio.deviceId = audioSource.deviceId; + } - if (this.stream) { - this.stop(); - } + window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { + self.stream = stream; + self.enabled = true; + self.mediaStream = master.audiocontext.createMediaStreamSource(stream); + self.mediaStream.connect(self.output); - var audioSource = master.inputSources[self.currentSource]; - var constraints = { - audio: { - sampleRate: master.audiocontext.sampleRate, - echoCancellation: false + self.amplitude.setInput(self.output); + if (successCallback) successCallback(); + })["catch"](function (err) { + if (errorCallback) errorCallback(err);else console.error(err); + }); } - }; - - if (master.inputSources[this.currentSource]) { - constraints.audio.deviceId = audioSource.deviceId; - } - - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - self.stream = stream; - self.enabled = true; - - self.mediaStream = master.audiocontext.createMediaStreamSource(stream); - self.mediaStream.connect(self.output); - - self.amplitude.setInput(self.output); - if (successCallback) successCallback(); - })["catch"](function (err) { - if (errorCallback) errorCallback(err);else console.error(err); - }); -}; -/** - * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel(). - * If re-starting, the user may be prompted for permission access. - * - * @method stop - * @for p5.AudioIn - */ - - -p5.AudioIn.prototype.stop = function () { - if (this.stream) { - this.stream.getTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.disconnect(); - delete this.mediaStream; - delete this.stream; - } -}; -/** - * Connect to an audio unit. If no parameter is provided, will - * connect to the master output (i.e. your speakers).
- * - * @method connect - * @for p5.AudioIn - * @param {Object} [unit] An object that accepts audio input, - * such as an FFT - */ - - -p5.AudioIn.prototype.connect = function (unit) { - if (unit) { - if (unit.hasOwnProperty('input')) { - this.output.connect(unit.input); - } else if (unit.hasOwnProperty('analyser')) { - this.output.connect(unit.analyser); - } else { - this.output.connect(unit); + /** + * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel(). + * If re-starting, the user may be prompted for permission access. + * + * @method stop + * @for p5.AudioIn + */ + + }, { + key: "stop", + value: function stop() { + if (this.stream) { + this.stream.getTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.disconnect(); + delete this.mediaStream; + delete this.stream; + } } - } else { - this.output.connect(master.input); - } -}; -/** - * Disconnect the AudioIn from all audio units. For example, if - * connect() had been called, disconnect() will stop sending - * signal to your speakers.
- * - * @method disconnect - * @for p5.AudioIn - */ - - -p5.AudioIn.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - - this.output.connect(this.amplitude.input); - } -}; -/** - * Read the Amplitude (volume level) of an AudioIn. The AudioIn - * class contains its own instance of the Amplitude class to help - * make it easy to get a microphone's volume level. Accepts an - * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must - * .start() before using .getLevel().
- * - * @method getLevel - * @for p5.AudioIn - * @param {Number} [smoothing] Smoothing is 0.0 by default. - * Smooths values based on previous values. - * @return {Number} Volume level (between 0.0 and 1.0) - */ - - -p5.AudioIn.prototype.getLevel = function (smoothing) { - if (smoothing) { - this.amplitude.smoothing = smoothing; - } - - return this.amplitude.getLevel(); -}; -/** - * Set amplitude (volume) of a mic input between 0 and 1.0.
- * - * @method amp - * @for p5.AudioIn - * @param {Number} vol between 0 and 1.0 - * @param {Number} [time] ramp time (optional) - */ - + /** + * Connect to an audio unit. If no parameter is provided, will + * connect to the master output (i.e. your speakers).
+ * + * @method connect + * @for p5.AudioIn + * @param {Object} [unit] An object that accepts audio input, + * such as an FFT + */ + + }, { + key: "connect", + value: function connect(unit) { + if (unit) { + if (unit.hasOwnProperty('input')) { + this.output.connect(unit.input); + } else if (unit.hasOwnProperty('analyser')) { + this.output.connect(unit.analyser); + } else { + this.output.connect(unit); + } + } else { + this.output.connect(master.input); + } + } + /** + * Disconnect the AudioIn from all audio units. For example, if + * connect() had been called, disconnect() will stop sending + * signal to your speakers.
+ * + * @method disconnect + * @for p5.AudioIn + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + + this.output.connect(this.amplitude.input); + } + } + /** + * Read the Amplitude (volume level) of an AudioIn. The AudioIn + * class contains its own instance of the Amplitude class to help + * make it easy to get a microphone's volume level. Accepts an + * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must + * .start() before using .getLevel().
+ * + * @method getLevel + * @for p5.AudioIn + * @param {Number} [smoothing] Smoothing is 0.0 by default. + * Smooths values based on previous values. + * @return {Number} Volume level (between 0.0 and 1.0) + */ + + }, { + key: "getLevel", + value: function getLevel(smoothing) { + if (smoothing) { + this.amplitude.smoothing = smoothing; + } -p5.AudioIn.prototype.amp = function (vol, t) { - if (t) { - var rampTime = t || 0; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(master.audiocontext.currentTime); - this.output.gain.setValueAtTime(currentVol, master.audiocontext.currentTime); - this.output.gain.linearRampToValueAtTime(vol, rampTime + master.audiocontext.currentTime); - } else { - this.output.gain.cancelScheduledValues(master.audiocontext.currentTime); - this.output.gain.setValueAtTime(vol, master.audiocontext.currentTime); - } -}; -/** - * Returns a list of available input sources. This is a wrapper - * for
- * MediaDevices.enumerateDevices() - Web APIs | MDN - * and it returns a Promise. - * @method getSources - * @for p5.AudioIn - * @param {Function} [successCallback] This callback function handles the sources when they - * have been enumerated. The callback function - * receives the deviceList array as its only argument - * @param {Function} [errorCallback] This optional callback receives the error - * message as its argument. - * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar - * to the enumerateDevices() method - * @example - *
- * let audioIn; - * - * function setup(){ - * text('getting sources...', 0, 20); - * audioIn = new p5.AudioIn(); - * audioIn.getSources(gotSources); - * } - * - * function gotSources(deviceList) { - * if (deviceList.length > 0) { - * //set the source to the first item in the deviceList array - * audioIn.setSource(0); - * let currentSource = deviceList[audioIn.currentSource]; - * text('set source to: ' + currentSource.deviceId, 5, 20, width); - * } - * } - *
- */ + return this.amplitude.getLevel(); + } + /** + * Set amplitude (volume) of a mic input between 0 and 1.0.
+ * + * @method amp + * @for p5.AudioIn + * @param {Number} vol between 0 and 1.0 + * @param {Number} [time] ramp time (optional) + */ + + }, { + key: "amp", + value: function amp(vol, t) { + if (t) { + var rampTime = t || 0; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(master.audiocontext.currentTime); + this.output.gain.setValueAtTime(currentVol, master.audiocontext.currentTime); + this.output.gain.linearRampToValueAtTime(vol, rampTime + master.audiocontext.currentTime); + } else { + this.output.gain.cancelScheduledValues(master.audiocontext.currentTime); + this.output.gain.setValueAtTime(vol, master.audiocontext.currentTime); + } + } + /** + * Returns a list of available input sources. This is a wrapper + * for + * MediaDevices.enumerateDevices() - Web APIs | MDN + * and it returns a Promise. + * @method getSources + * @for p5.AudioIn + * @param {Function} [successCallback] This callback function handles the sources when they + * have been enumerated. The callback function + * receives the deviceList array as its only argument + * @param {Function} [errorCallback] This optional callback receives the error + * message as its argument. + * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar + * to the enumerateDevices() method + * @example + *
+ * let audioIn; + * + * function setup(){ + * text('getting sources...', 0, 20); + * audioIn = new p5.AudioIn(); + * audioIn.getSources(gotSources); + * } + * + * function gotSources(deviceList) { + * if (deviceList.length > 0) { + * //set the source to the first item in the deviceList array + * audioIn.setSource(0); + * let currentSource = deviceList[audioIn.currentSource]; + * text('set source to: ' + currentSource.deviceId, 5, 20, width); + * } + * } + *
+ */ + + }, { + key: "getSources", + value: function getSources(onSuccess, onError) { + return new Promise(function (resolve, reject) { + window.navigator.mediaDevices.enumerateDevices().then(function (devices) { + master.inputSources = devices.filter(function (device) { + return device.kind === 'audioinput'; + }); + resolve(master.inputSources); + if (onSuccess) { + onSuccess(master.inputSources); + } + })["catch"](function (error) { + reject(error); -p5.AudioIn.prototype.getSources = function (onSuccess, onError) { - return new Promise(function (resolve, reject) { - window.navigator.mediaDevices.enumerateDevices().then(function (devices) { - master.inputSources = devices.filter(function (device) { - return device.kind === 'audioinput'; + if (onError) { + onError(error); + } else { + console.error('This browser does not support MediaStreamTrack.getSources()'); + } + }); }); - resolve(master.inputSources); + } + /** + * Set the input source. Accepts a number representing a + * position in the array returned by getSources(). + * This is only available in browsers that support + * + * navigator.mediaDevices.enumerateDevices() + * + * @method setSource + * @for p5.AudioIn + * @param {number} num position of input source in the array + * @example + *
+ * let audioIn; + * + * function setup(){ + * text('getting sources...', 0, 20); + * audioIn = new p5.AudioIn(); + * audioIn.getSources(gotSources); + * } + * + * function gotSources(deviceList) { + * if (deviceList.length > 0) { + * //set the source to the first item in the deviceList array + * audioIn.setSource(0); + * let currentSource = deviceList[audioIn.currentSource]; + * text('set source to: ' + currentSource.deviceId, 5, 20, width); + * } + * } + *
+ */ + + }, { + key: "setSource", + value: function setSource(num) { + if (master.inputSources.length > 0 && num < master.inputSources.length) { + this.currentSource = num; + console.log('set source to ', master.inputSources[this.currentSource]); + } else { + console.log('unable to set input source'); + } - if (onSuccess) { - onSuccess(master.inputSources); - } - })["catch"](function (error) { - reject(error); - if (onError) { - onError(error); - } else { - console.error('This browser does not support MediaStreamTrack.getSources()'); + if (this.stream && this.stream.active) { + this.start(); } - }); - }); -}; -/** - * Set the input source. Accepts a number representing a - * position in the array returned by getSources(). - * This is only available in browsers that support - * - * navigator.mediaDevices.enumerateDevices() - * - * @method setSource - * @for p5.AudioIn - * @param {number} num position of input source in the array - * @example - *
- * let audioIn; - * - * function setup(){ - * text('getting sources...', 0, 20); - * audioIn = new p5.AudioIn(); - * audioIn.getSources(gotSources); - * } - * - * function gotSources(deviceList) { - * if (deviceList.length > 0) { - * //set the source to the first item in the deviceList array - * audioIn.setSource(0); - * let currentSource = deviceList[audioIn.currentSource]; - * text('set source to: ' + currentSource.deviceId, 5, 20, width); - * } - * } - *
- */ + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + this.stop(); -p5.AudioIn.prototype.setSource = function (num) { - if (master.inputSources.length > 0 && num < master.inputSources.length) { - this.currentSource = num; - console.log('set source to ', master.inputSources[this.currentSource]); - } else { - console.log('unable to set input source'); - } + if (this.output) { + this.output.disconnect(); + } + if (this.amplitude) { + this.amplitude.disconnect(); + } - if (this.stream && this.stream.active) { - this.start(); - } -}; + delete this.amplitude; + delete this.output; + } + }]); + return AudioIn; +}(); -p5.AudioIn.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - this.stop(); + var audioin = (audioin_AudioIn); +var CrossFade = __webpack_require__(23); +var CrossFade_default = __webpack_require__.n(CrossFade); - if (this.output) { - this.output.disconnect(); - } +function effect_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - if (this.amplitude) { - this.amplitude.disconnect(); - } +function effect_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); } } - delete this.amplitude; - delete this.output; -}; -var CrossFade = __webpack_require__(23); -var CrossFade_default = __webpack_require__.n(CrossFade); +function effect_createClass(Constructor, protoProps, staticProps) { if (protoProps) effect_defineProperties(Constructor.prototype, protoProps); if (staticProps) effect_defineProperties(Constructor, staticProps); return Constructor; } @@ -6692,150 +6652,186 @@ var CrossFade_default = __webpack_require__.n(CrossFade); * signals are mixed properly. */ -p5.Effect = function () { - this.ac = master.audiocontext; - this.input = this.ac.createGain(); - this.output = this.ac.createGain(); - /** - * The p5.Effect class is built - * using Tone.js CrossFade - * @private - */ +var effect_Effect = +function () { + function Effect() { + effect_classCallCheck(this, Effect); - this._drywet = new CrossFade_default.a(1); - /** - * In classes that extend - * p5.Effect, connect effect nodes - * to the wet parameter - */ + this.ac = master.audiocontext; + this.input = this.ac.createGain(); + this.output = this.ac.createGain(); + /** + * The p5.Effect class is built + * using Tone.js CrossFade + * @private + */ - this.wet = this.ac.createGain(); - this.input.connect(this._drywet.a); - this.wet.connect(this._drywet.b); + this._drywet = new CrossFade_default.a(1); + /** + * In classes that extend + * p5.Effect, connect effect nodes + * to the wet parameter + */ - this._drywet.connect(this.output); + this.wet = this.ac.createGain(); + this.input.connect(this._drywet.a); + this.wet.connect(this._drywet.b); - this.connect(); + this._drywet.connect(this.output); - master.soundArray.push(this); -}; -/** - * Set the output volume of the filter. - * - * @method amp - * @for p5.Effect - * @param {Number} [vol] amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts until rampTime - * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds - */ + this.connect(); + master.soundArray.push(this); + } + /** + * Set the output volume of the filter. + * + * @method amp + * @for p5.Effect + * @param {Number} [vol] amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts until rampTime + * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds + */ -p5.Effect.prototype.amp = function (vol) { - var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var now = master.audiocontext.currentTime; - var startTime = now + tFromNow; - var endTime = startTime + rampTime + 0.001; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now); - this.output.gain.linearRampToValueAtTime(currentVol, startTime + 0.001); - this.output.gain.linearRampToValueAtTime(vol, endTime); -}; -/** - * Link effects together in a chain - * Example usage: filter.chain(reverb, delay, panner); - * May be used with an open-ended number of arguments - * - * @method chain - * @for p5.Effect - * @param {Object} [arguments] Chain together multiple sound objects - */ + effect_createClass(Effect, [{ + key: "amp", + value: function amp(vol) { + var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var now = master.audiocontext.currentTime; + var startTime = now + tFromNow; + var endTime = startTime + rampTime + 0.001; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now); + this.output.gain.linearRampToValueAtTime(currentVol, startTime + 0.001); + this.output.gain.linearRampToValueAtTime(vol, endTime); + } + /** + * Link effects together in a chain + * Example usage: filter.chain(reverb, delay, panner); + * May be used with an open-ended number of arguments + * + * @method chain + * @for p5.Effect + * @param {Object} [arguments] Chain together multiple sound objects + */ + + }, { + key: "chain", + value: function chain() { + if (arguments.length > 0) { + this.connect(arguments[0]); + + for (var i = 1; i < arguments.length; i += 1) { + arguments[i - 1].connect(arguments[i]); + } + } -p5.Effect.prototype.chain = function () { - if (arguments.length > 0) { - this.connect(arguments[0]); + return this; + } + /** + * Adjust the dry/wet value. + * + * @method drywet + * @for p5.Effect + * @param {Number} [fade] The desired drywet value (0 - 1.0) + */ + + }, { + key: "drywet", + value: function drywet() { + if (typeof fade !== 'undefined') { + this._drywet.fade.value = fade; + } - for (var i = 1; i < arguments.length; i += 1) { - arguments[i - 1].connect(arguments[i]); + return this._drywet.fade.value; } - } + /** + * Send output to a p5.js-sound, Web Audio Node, or use signal to + * control an AudioParam + * + * @method connect + * @for p5.Effect + * @param {Object} unit + */ + + }, { + key: "connect", + value: function connect(unit) { + var u = unit || p5.soundOut.input; + this.output.connect(u.input ? u.input : u); + } + /** + * Disconnect all output. + * @method disconnect + * @for p5.Effect + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + + if (this.input) { + this.input.disconnect(); + delete this.input; + } - return this; -}; -/** - * Adjust the dry/wet value. - * - * @method drywet - * @for p5.Effect - * @param {Number} [fade] The desired drywet value (0 - 1.0) - */ + if (this.output) { + this.output.disconnect(); + delete this.output; + } + if (this._drywet) { + this._drywet.disconnect(); -p5.Effect.prototype.drywet = function (fade) { - if (typeof fade !== 'undefined') { - this._drywet.fade.value = fade; - } + delete this._drywet; + } - return this._drywet.fade.value; -}; -/** - * Send output to a p5.js-sound, Web Audio Node, or use signal to - * control an AudioParam - * - * @method connect - * @for p5.Effect - * @param {Object} unit - */ + if (this.wet) { + this.wet.disconnect(); + delete this.wet; + } + this.ac = undefined; + } + }]); -p5.Effect.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - this.output.connect(u.input ? u.input : u); -}; -/** - * Disconnect all output. - * @method disconnect - * @for p5.Effect - */ + return Effect; +}(); + var effect = (effect_Effect); +function filter_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { filter_typeof = function _typeof(obj) { return typeof obj; }; } else { filter_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return filter_typeof(obj); } -p5.Effect.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } -}; +function filter_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -p5.Effect.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); +function filter_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); } } - if (this.input) { - this.input.disconnect(); - delete this.input; - } +function filter_createClass(Constructor, protoProps, staticProps) { if (protoProps) filter_defineProperties(Constructor.prototype, protoProps); if (staticProps) filter_defineProperties(Constructor, staticProps); return Constructor; } - if (this.output) { - this.output.disconnect(); - delete this.output; - } +function filter_possibleConstructorReturn(self, call) { if (call && (filter_typeof(call) === "object" || typeof call === "function")) { return call; } return filter_assertThisInitialized(self); } - if (this._drywet) { - this._drywet.disconnect(); +function filter_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } - delete this._drywet; - } +function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } - if (this.wet) { - this.wet.disconnect(); - delete this.wet; - } +function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = filter_getPrototypeOf(object); if (object === null) break; } return object; } - this.ac = undefined; -}; +function filter_getPrototypeOf(o) { filter_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return filter_getPrototypeOf(o); } + +function filter_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) filter_setPrototypeOf(subClass, superClass); } + +function filter_setPrototypeOf(o, p) { filter_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return filter_setPrototypeOf(o, p); } -var Effect = p5.Effect; - var effect = (Effect); /** *

A p5.Filter uses a Web Audio Biquad Filter to filter @@ -6896,210 +6892,233 @@ var Effect = p5.Effect; * let x = map(i, 0, spectrum.length, 0, width); * let h = -height + map(spectrum[i], 0, 255, height, 0); * rect(x, height, width/spectrum.length, h); - * } - * if (!noise.started) { - * text('tap here and drag to change frequency', 10, 20, width - 20); - * } else { - * text('Frequency: ' + round(freq)+'Hz', 20, 20, width - 20); - * } - * } - * - * function makeNoise() { - * // see also: `userStartAudio()` - * noise.start(); - * noise.amp(0.5, 0.2); - * } - * - * function mouseReleased() { - * noise.amp(0, 0.2); - * } - * - * - */ - -p5.Filter = function (type) { - effect.call(this); - - /** - * The p5.Filter is built with a - * - * Web Audio BiquadFilter Node. - * - * @property {DelayNode} biquadFilter - */ - - this.biquad = this.ac.createBiquadFilter(); - this.input.connect(this.biquad); - this.biquad.connect(this.wet); - - if (type) { - this.setType(type); - } - - - this._on = true; - this._untoggledType = this.biquad.type; -}; - -p5.Filter.prototype = Object.create(effect.prototype); -/** - * Filter an audio signal according to a set - * of filter parameters. - * - * @method process - * @param {Object} Signal An object that outputs audio - * @param {Number} [freq] Frequency in Hz, from 10 to 22050 - * @param {Number} [res] Resonance/Width of the filter frequency - * from 0.001 to 1000 - */ - -p5.Filter.prototype.process = function (src, freq, res, time) { - src.connect(this.input); - this.set(freq, res, time); -}; -/** - * Set the frequency and the resonance of the filter. + * } + * if (!noise.started) { + * text('tap here and drag to change frequency', 10, 20, width - 20); + * } else { + * text('Frequency: ' + round(freq)+'Hz', 20, 20, width - 20); + * } + * } * - * @method set - * @param {Number} [freq] Frequency in Hz, from 10 to 22050 - * @param {Number} [res] Resonance (Q) from 0.001 to 1000 - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - - -p5.Filter.prototype.set = function (freq, res, time) { - if (freq) { - this.freq(freq, time); - } - - if (res) { - this.res(res, time); - } -}; -/** - * Set the filter frequency, in Hz, from 10 to 22050 (the range of - * human hearing, although in reality most people hear in a narrower - * range). - * - * @method freq - * @param {Number} freq Filter Frequency - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {Number} value Returns the current frequency value + * function makeNoise() { + * // see also: `userStartAudio()` + * noise.start(); + * noise.amp(0.5, 0.2); + * } + * + * function mouseReleased() { + * noise.amp(0, 0.2); + * } + * + * */ +var Filter = +function (_Effect) { + filter_inherits(Filter, _Effect); -p5.Filter.prototype.freq = function (freq, time) { - var t = time || 0; - - if (freq <= 0) { - freq = 1; - } + function Filter(type) { + var _this; - if (typeof freq === 'number') { - this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t); - } else if (freq) { - freq.connect(this.biquad.frequency); - } + filter_classCallCheck(this, Filter); - return this.biquad.frequency.value; -}; -/** - * Controls either width of a bandpass frequency, - * or the resonance of a low/highpass cutoff frequency. - * - * @method res - * @param {Number} res Resonance/Width of filter freq - * from 0.001 to 1000 - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {Number} value Returns the current res value - */ + _this = filter_possibleConstructorReturn(this, filter_getPrototypeOf(Filter).call(this)); + /** + * The p5.Filter is built with a + * + * Web Audio BiquadFilter Node. + * + * @property {DelayNode} biquadFilter + */ -p5.Filter.prototype.res = function (res, time) { - var t = time || 0; + _this.biquad = _this.ac.createBiquadFilter(); - if (typeof res === 'number') { - this.biquad.Q.value = res; - this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t); - } else if (res) { - res.connect(this.biquad.Q); - } + _this.input.connect(_this.biquad); - return this.biquad.Q.value; -}; -/** - * Controls the gain attribute of a Biquad Filter. - * This is distinctly different from .amp() which is inherited from p5.Effect - * .amp() controls the volume via the output gain node - * p5.Filter.gain() controls the gain parameter of a Biquad Filter node. - * - * @method gain - * @param {Number} gain - * @return {Number} Returns the current or updated gain value - */ + _this.biquad.connect(_this.wet); + if (type) { + _this.setType(type); + } -p5.Filter.prototype.gain = function (gain, time) { - var t = time || 0; - if (typeof gain === 'number') { - this.biquad.gain.value = gain; - this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t); - } else if (gain) { - gain.connect(this.biquad.gain); + _this._on = true; + _this._untoggledType = _this.biquad.type; + return _this; } + /** + * Filter an audio signal according to a set + * of filter parameters. + * + * @method process + * @param {Object} Signal An object that outputs audio + * @param {Number} [freq] Frequency in Hz, from 10 to 22050 + * @param {Number} [res] Resonance/Width of the filter frequency + * from 0.001 to 1000 + */ - return this.biquad.gain.value; -}; -/** - * Toggle function. Switches between the specified type and allpass - * - * @method toggle - * @return {boolean} [Toggle value] - */ + filter_createClass(Filter, [{ + key: "process", + value: function process(src, freq, res, time) { + src.connect(this.input); + this.set(freq, res, time); + } + /** + * Set the frequency and the resonance of the filter. + * + * @method set + * @param {Number} [freq] Frequency in Hz, from 10 to 22050 + * @param {Number} [res] Resonance (Q) from 0.001 to 1000 + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + + }, { + key: "set", + value: function set(freq, res, time) { + if (freq) { + this.freq(freq, time); + } -p5.Filter.prototype.toggle = function () { - this._on = !this._on; + if (res) { + this.res(res, time); + } + } + /** + * Set the filter frequency, in Hz, from 10 to 22050 (the range of + * human hearing, although in reality most people hear in a narrower + * range). + * + * @method freq + * @param {Number} freq Filter Frequency + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {Number} value Returns the current frequency value + */ + + }, { + key: "freq", + value: function freq(_freq, time) { + var t = time || 0; + + if (_freq <= 0) { + _freq = 1; + } - if (this._on === true) { - this.biquad.type = this._untoggledType; - } else if (this._on === false) { - this.biquad.type = 'allpass'; - } + if (typeof _freq === 'number') { + this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.frequency.exponentialRampToValueAtTime(_freq, this.ac.currentTime + 0.02 + t); + } else if (_freq) { + _freq.connect(this.biquad.frequency); + } - return this._on; -}; -/** - * Set the type of a p5.Filter. Possible types include: - * "lowpass" (default), "highpass", "bandpass", - * "lowshelf", "highshelf", "peaking", "notch", - * "allpass". - * - * @method setType - * @param {String} t - */ + return this.biquad.frequency.value; + } + /** + * Controls either width of a bandpass frequency, + * or the resonance of a low/highpass cutoff frequency. + * + * @method res + * @param {Number} res Resonance/Width of filter freq + * from 0.001 to 1000 + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {Number} value Returns the current res value + */ + + }, { + key: "res", + value: function res(_res, time) { + var t = time || 0; + + if (typeof _res === 'number') { + this.biquad.Q.value = _res; + this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.Q.linearRampToValueAtTime(_res, this.ac.currentTime + 0.02 + t); + } else if (_res) { + _res.connect(this.biquad.Q); + } + return this.biquad.Q.value; + } + /** + * Controls the gain attribute of a Biquad Filter. + * This is distinctly different from .amp() which is inherited from p5.Effect + * .amp() controls the volume via the output gain node + * p5.Filter.gain() controls the gain parameter of a Biquad Filter node. + * + * @method gain + * @param {Number} gain + * @return {Number} Returns the current or updated gain value + */ + + }, { + key: "gain", + value: function gain(_gain, time) { + var t = time || 0; + + if (typeof _gain === 'number') { + this.biquad.gain.value = _gain; + this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.gain.linearRampToValueAtTime(_gain, this.ac.currentTime + 0.02 + t); + } else if (_gain) { + _gain.connect(this.biquad.gain); + } -p5.Filter.prototype.setType = function (t) { - this.biquad.type = t; - this._untoggledType = this.biquad.type; -}; + return this.biquad.gain.value; + } + /** + * Toggle function. Switches between the specified type and allpass + * + * @method toggle + * @return {boolean} [Toggle value] + */ + + }, { + key: "toggle", + value: function toggle() { + this._on = !this._on; + + if (this._on === true) { + this.biquad.type = this._untoggledType; + } else if (this._on === false) { + this.biquad.type = 'allpass'; + } -p5.Filter.prototype.dispose = function () { - effect.prototype.dispose.apply(this); + return this._on; + } + /** + * Set the type of a p5.Filter. Possible types include: + * "lowpass" (default), "highpass", "bandpass", + * "lowshelf", "highshelf", "peaking", "notch", + * "allpass". + * + * @method setType + * @param {String} t + */ + + }, { + key: "setType", + value: function setType(t) { + this.biquad.type = t; + this._untoggledType = this.biquad.type; + } + }, { + key: "dispose", + value: function dispose() { + _get(filter_getPrototypeOf(Filter.prototype), "dispose", this).call(this); + + if (this.biquad) { + this.biquad.disconnect(); + delete this.biquad; + } + } + }]); - if (this.biquad) { - this.biquad.disconnect(); - delete this.biquad; - } -}; + return Filter; +}(effect); /** * Constructor: new p5.LowPass() Filter. * This is the same as creating a p5.Filter and then calling @@ -7112,11 +7131,18 @@ p5.Filter.prototype.dispose = function () { */ -p5.LowPass = function () { - p5.Filter.call(this, 'lowpass'); -}; +var LowPass = +function (_Filter) { + filter_inherits(LowPass, _Filter); + + function LowPass() { + filter_classCallCheck(this, LowPass); + + return filter_possibleConstructorReturn(this, filter_getPrototypeOf(LowPass).call(this, 'lowpass')); + } -p5.LowPass.prototype = Object.create(p5.Filter.prototype); + return LowPass; +}(Filter); /** * Constructor: new p5.HighPass() Filter. * This is the same as creating a p5.Filter and then calling @@ -7128,11 +7154,19 @@ p5.LowPass.prototype = Object.create(p5.Filter.prototype); * @extends p5.Filter */ -p5.HighPass = function () { - p5.Filter.call(this, 'highpass'); -}; -p5.HighPass.prototype = Object.create(p5.Filter.prototype); +var HighPass = +function (_Filter2) { + filter_inherits(HighPass, _Filter2); + + function HighPass() { + filter_classCallCheck(this, HighPass); + + return filter_possibleConstructorReturn(this, filter_getPrototypeOf(HighPass).call(this, 'highpass')); + } + + return HighPass; +}(Filter); /** * Constructor: new p5.BandPass() Filter. * This is the same as creating a p5.Filter and then calling @@ -7144,540 +7178,362 @@ p5.HighPass.prototype = Object.create(p5.Filter.prototype); * @extends p5.Filter */ -p5.BandPass = function () { - p5.Filter.call(this, 'bandpass'); -}; - -p5.BandPass.prototype = Object.create(p5.Filter.prototype); - var filter = (p5.Filter); - - -/** - * EQFilter extends p5.Filter with constraints - * necessary for the p5.EQ - * - * @private - */ - -var eqFilter_EQFilter = function EQFilter(freq, res) { - filter.call(this, 'peaking'); - this.disconnect(); - this.set(freq, res); - this.biquad.gain.value = 0; - delete this.input; - delete this.output; - delete this._drywet; - delete this.wet; -}; - -eqFilter_EQFilter.prototype = Object.create(filter.prototype); - -eqFilter_EQFilter.prototype.amp = function () { - console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`'); -}; - -eqFilter_EQFilter.prototype.drywet = function () { - console.warn('`drywet()` is not available for p5.EQ bands.'); -}; - -eqFilter_EQFilter.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - - if (this.biquad) { - this.biquad.connect(u.input ? u.input : u); - } else { - this.output.connect(u.input ? u.input : u); - } -}; - -eqFilter_EQFilter.prototype.disconnect = function () { - if (this.biquad) { - this.biquad.disconnect(); - } -}; - -eqFilter_EQFilter.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - this.disconnect(); - delete this.biquad; -}; - - var eqFilter = (eqFilter_EQFilter); - - -/** - * p5.EQ is an audio effect that performs the function of a multiband - * audio equalizer. Equalization is used to adjust the balance of - * frequency compoenents of an audio signal. This process is commonly used - * in sound production and recording to change the waveform before it reaches - * a sound output device. EQ can also be used as an audio effect to create - * interesting distortions by filtering out parts of the spectrum. p5.EQ is - * built using a chain of Web Audio Biquad Filter Nodes and can be - * instantiated with 3 or 8 bands. Bands can be added or removed from - * the EQ by directly modifying p5.EQ.bands (the array that stores filters). - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.EQ - * @constructor - * @extends p5.Effect - * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3 - * @return {Object} p5.EQ object - * - * @example - *

- * let eq, soundFile - * let eqBandIndex = 0; - * let eqBandNames = ['lows', 'mids', 'highs']; - * - * function preload() { - * soundFormats('mp3', 'ogg'); - * soundFile = loadSound('assets/beat'); - * } - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(toggleSound); - * - * eq = new p5.EQ(eqBandNames.length); - * soundFile.disconnect(); - * eq.process(soundFile); - * } - * - * function draw() { - * background(30); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('filtering ', 50, 25); - * - * fill(255, 40, 255); - * textSize(26); - * text(eqBandNames[eqBandIndex], 50, 55); - * - * fill(255); - * textSize(9); - * - * if (!soundFile.isPlaying()) { - * text('tap to play', 50, 80); - * } else { - * text('tap to filter next band', 50, 80) - * } - * } - * - * function toggleSound() { - * if (!soundFile.isPlaying()) { - * soundFile.play(); - * } else { - * eqBandIndex = (eqBandIndex + 1) % eq.bands.length; - * } - * - * for (let i = 0; i < eq.bands.length; i++) { - * eq.bands[i].gain(0); - * } - * // filter the band we want to filter - * eq.bands[eqBandIndex].gain(-40); - * } - *
- */ - -p5.EQ = function (_eqsize) { - effect.call(this); - _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3; - var factor; - _eqsize === 3 ? factor = Math.pow(2, 3) : factor = 2; - /** - * The p5.EQ is built with abstracted p5.Filter objects. - * To modify any bands, use methods of the - * p5.Filter API, especially `gain` and `freq`. - * Bands are stored in an array, with indices 0 - 3, or 0 - 7 - * @property {Array} bands - * - */ - - this.bands = []; - var freq, res; - - for (var i = 0; i < _eqsize; i++) { - if (i === _eqsize - 1) { - freq = 21000; - res = 0.01; - } else if (i === 0) { - freq = 100; - res = 0.1; - } else if (i === 1) { - freq = _eqsize === 3 ? 360 * factor : 360; - res = 1; - } else { - freq = this.bands[i - 1].freq() * factor; - res = 1; - } +var BandPass = +function (_Filter3) { + filter_inherits(BandPass, _Filter3); - this.bands[i] = this._newBand(freq, res); + function BandPass() { + filter_classCallCheck(this, BandPass); - if (i > 0) { - this.bands[i - 1].connect(this.bands[i].biquad); - } else { - this.input.connect(this.bands[i].biquad); - } + return filter_possibleConstructorReturn(this, filter_getPrototypeOf(BandPass).call(this, 'bandpass')); } - this.bands[_eqsize - 1].connect(this.output); -}; - -p5.EQ.prototype = Object.create(effect.prototype); -/** - * Process an input by connecting it to the EQ - * @method process - * @param {Object} src Audio source - */ + return BandPass; +}(Filter); -p5.EQ.prototype.process = function (src) { - src.connect(this.input); -}; -// * Set the frequency and gain of each band in the EQ. This method should be -// * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ. -// * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2); -// * -// * @method set -// * @for p5.EQ -// * @param {Number} [freq0] Frequency value for band with index 0 -// * @param {Number} [gain0] Gain value for band with index 0 -// * @param {Number} [freq1] Frequency value for band with index 1 -// * @param {Number} [gain1] Gain value for band with index 1 -// * @param {Number} [freq2] Frequency value for band with index 2 -// * @param {Number} [gain2] Gain value for band with index 2 -// * @param {Number} [freq3] Frequency value for band with index 3 -// * @param {Number} [gain3] Gain value for band with index 3 -// * @param {Number} [freq4] Frequency value for band with index 4 -// * @param {Number} [gain4] Gain value for band with index 4 -// * @param {Number} [freq5] Frequency value for band with index 5 -// * @param {Number} [gain5] Gain value for band with index 5 -// * @param {Number} [freq6] Frequency value for band with index 6 -// * @param {Number} [gain6] Gain value for band with index 6 -// * @param {Number} [freq7] Frequency value for band with index 7 -// * @param {Number} [gain7] Gain value for band with index 7 -// */ + var filter = (Filter); +function eqFilter_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { eqFilter_typeof = function _typeof(obj) { return typeof obj; }; } else { eqFilter_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return eqFilter_typeof(obj); } -p5.EQ.prototype.set = function () { - if (arguments.length === this.bands.length * 2) { - for (var i = 0; i < arguments.length; i += 2) { - this.bands[i / 2].freq(arguments[i]); - this.bands[i / 2].gain(arguments[i + 1]); - } - } else { - console.error('Argument mismatch. .set() should be called with ' + this.bands.length * 2 + ' arguments. (one frequency and gain value pair for each band of the eq)'); - } -}; -/** - * Add a new band. Creates a p5.Filter and strips away everything but - * the raw biquad filter. This method returns an abstracted p5.Filter, - * which can be added to p5.EQ.bands, in order to create new EQ bands. - * @private - * @for p5.EQ - * @method _newBand - * @param {Number} freq - * @param {Number} res - * @return {Object} Abstracted Filter - */ +function eqFilter_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function eqFilter_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); } } -p5.EQ.prototype._newBand = function (freq, res) { - return new eqFilter(freq, res); -}; +function eqFilter_createClass(Constructor, protoProps, staticProps) { if (protoProps) eqFilter_defineProperties(Constructor.prototype, protoProps); if (staticProps) eqFilter_defineProperties(Constructor, staticProps); return Constructor; } -p5.EQ.prototype.dispose = function () { - effect.prototype.dispose.apply(this); +function eqFilter_possibleConstructorReturn(self, call) { if (call && (eqFilter_typeof(call) === "object" || typeof call === "function")) { return call; } return eqFilter_assertThisInitialized(self); } - if (this.bands) { - while (this.bands.length > 0) { - delete this.bands.pop().dispose(); - } +function eqFilter_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } - delete this.bands; - } -}; +function eqFilter_getPrototypeOf(o) { eqFilter_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return eqFilter_getPrototypeOf(o); } - var eq = (p5.EQ); +function eqFilter_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) eqFilter_setPrototypeOf(subClass, superClass); } -/** - * Panner3D is based on the - * Web Audio Spatial Panner Node. - * This panner is a spatial processing node that allows audio to be positioned - * and oriented in 3D space. - * - * The position is relative to an - * Audio Context Listener, which can be accessed - * by p5.soundOut.audiocontext.listener - * - * - * @class p5.Panner3D - * @constructor - */ +function eqFilter_setPrototypeOf(o, p) { eqFilter_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return eqFilter_setPrototypeOf(o, p); } -p5.Panner3D = function () { - effect.call(this); - /** - * - * Web Audio Spatial Panner Node - * - * Properties include
- * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType) - * : "equal power" or "HRTF"
- * [DistanceModel](https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType) - * : "linear", "inverse", or "exponential" - * - * @property {AudioNode} panner - * - */ - this.panner = this.ac.createPanner(); - this.panner.panningModel = 'HRTF'; - this.panner.distanceModel = 'linear'; - this.panner.connect(this.output); - this.input.connect(this.panner); -}; -p5.Panner3D.prototype = Object.create(effect.prototype); /** - * Connect an audio sorce + * EQFilter extends p5.Filter with constraints + * necessary for the p5.EQ * - * @method process - * @for p5.Panner3D - * @param {Object} src Input source - */ - -p5.Panner3D.prototype.process = function (src) { - src.connect(this.input); -}; -/** - * Set the X,Y,Z position of the Panner - * @method set - * @for p5.Panner3D - * @param {Number} xVal - * @param {Number} yVal - * @param {Number} zVal - * @param {Number} time - * @return {Array} Updated x, y, z values as an array - */ - - -p5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) { - this.positionX(xVal, time); - this.positionY(yVal, time); - this.positionZ(zVal, time); - return [this.panner.positionX.value, this.panner.positionY.value, this.panner.positionZ.value]; -}; -/** - * Getter and setter methods for position coordinates - * @method positionX - * @for p5.Panner3D - * @return {Number} updated coordinate value - */ - -/** - * Getter and setter methods for position coordinates - * @method positionY - * @for p5.Panner3D - * @return {Number} updated coordinate value + * @private */ -/** - * Getter and setter methods for position coordinates - * @method positionZ - * @for p5.Panner3D - * @return {Number} updated coordinate value - */ +var eqFilter_EQFilter = +function (_Filter) { + eqFilter_inherits(EQFilter, _Filter); + function EQFilter(freq, res) { + var _this; -p5.Panner3D.prototype.positionX = function (xVal, time) { - var t = time || 0; + eqFilter_classCallCheck(this, EQFilter); - if (typeof xVal === 'number') { - this.panner.positionX.value = xVal; - this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.panner.positionX); - } + _this = eqFilter_possibleConstructorReturn(this, eqFilter_getPrototypeOf(EQFilter).call(this, 'peaking')); - return this.panner.positionX.value; -}; + _this.disconnect(); -p5.Panner3D.prototype.positionY = function (yVal, time) { - var t = time || 0; + _this.set(freq, res); - if (typeof yVal === 'number') { - this.panner.positionY.value = yVal; - this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.panner.positionY); + _this.biquad.gain.value = 0; + delete _this.input; + delete _this.output; + delete _this._drywet; + delete _this.wet; + return _this; } - return this.panner.positionY.value; -}; - -p5.Panner3D.prototype.positionZ = function (zVal, time) { - var t = time || 0; + eqFilter_createClass(EQFilter, [{ + key: "amp", + value: function amp() { + console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`'); + } + }, { + key: "drywet", + value: function drywet() { + console.warn('`drywet()` is not available for p5.EQ bands.'); + } + }, { + key: "connect", + value: function connect(unit) { + var u = unit || p5.soundOut.input; - if (typeof zVal === 'number') { - this.panner.positionZ.value = zVal; - this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.panner.positionZ); - } + if (this.biquad) { + this.biquad.connect(u.input ? u.input : u); + } else { + this.output.connect(u.input ? u.input : u); + } + } + }, { + key: "disconnect", + value: function disconnect() { + if (this.biquad) { + this.biquad.disconnect(); + } + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + this.disconnect(); + delete this.biquad; + } + }]); - return this.panner.positionZ.value; -}; -/** - * Set the X,Y,Z position of the Panner - * @method orient - * @for p5.Panner3D - * @param {Number} xVal - * @param {Number} yVal - * @param {Number} zVal - * @param {Number} time - * @return {Array} Updated x, y, z values as an array - */ + return EQFilter; +}(filter); + var eqFilter = (eqFilter_EQFilter); +function eq_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { eq_typeof = function _typeof(obj) { return typeof obj; }; } else { eq_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return eq_typeof(obj); } -p5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) { - this.orientX(xVal, time); - this.orientY(yVal, time); - this.orientZ(zVal, time); - return [this.panner.orientationX.value, this.panner.orientationY.value, this.panner.orientationZ.value]; -}; -/** - * Getter and setter methods for orient coordinates - * @method orientX - * @for p5.Panner3D - * @return {Number} updated coordinate value - */ +function eq_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -/** - * Getter and setter methods for orient coordinates - * @method orientY - * @for p5.Panner3D - * @return {Number} updated coordinate value - */ +function eq_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); } } -/** - * Getter and setter methods for orient coordinates - * @method orientZ - * @for p5.Panner3D - * @return {Number} updated coordinate value - */ +function eq_createClass(Constructor, protoProps, staticProps) { if (protoProps) eq_defineProperties(Constructor.prototype, protoProps); if (staticProps) eq_defineProperties(Constructor, staticProps); return Constructor; } +function eq_possibleConstructorReturn(self, call) { if (call && (eq_typeof(call) === "object" || typeof call === "function")) { return call; } return eq_assertThisInitialized(self); } -p5.Panner3D.prototype.orientX = function (xVal, time) { - var t = time || 0; +function eq_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } - if (typeof xVal === 'number') { - this.panner.orientationX.value = xVal; - this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.panner.orientationX); - } +function eq_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { eq_get = Reflect.get; } else { eq_get = function _get(target, property, receiver) { var base = eq_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return eq_get(target, property, receiver || target); } - return this.panner.orientationX.value; -}; +function eq_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = eq_getPrototypeOf(object); if (object === null) break; } return object; } -p5.Panner3D.prototype.orientY = function (yVal, time) { - var t = time || 0; +function eq_getPrototypeOf(o) { eq_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return eq_getPrototypeOf(o); } - if (typeof yVal === 'number') { - this.panner.orientationY.value = yVal; - this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.panner.orientationY); - } +function eq_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) eq_setPrototypeOf(subClass, superClass); } - return this.panner.orientationY.value; -}; +function eq_setPrototypeOf(o, p) { eq_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return eq_setPrototypeOf(o, p); } -p5.Panner3D.prototype.orientZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.panner.orientationZ.value = zVal; - this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.panner.orientationZ); - } - return this.panner.orientationZ.value; -}; /** - * Set the rolloff factor and max distance - * @method setFalloff - * @for p5.Panner3D - * @param {Number} [maxDistance] - * @param {Number} [rolloffFactor] + * p5.EQ is an audio effect that performs the function of a multiband + * audio equalizer. Equalization is used to adjust the balance of + * frequency compoenents of an audio signal. This process is commonly used + * in sound production and recording to change the waveform before it reaches + * a sound output device. EQ can also be used as an audio effect to create + * interesting distortions by filtering out parts of the spectrum. p5.EQ is + * built using a chain of Web Audio Biquad Filter Nodes and can be + * instantiated with 3 or 8 bands. Bands can be added or removed from + * the EQ by directly modifying p5.EQ.bands (the array that stores filters). + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.EQ + * @constructor + * @extends p5.Effect + * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3 + * @return {Object} p5.EQ object + * + * @example + *
+ * let eq, soundFile + * let eqBandIndex = 0; + * let eqBandNames = ['lows', 'mids', 'highs']; + * + * function preload() { + * soundFormats('mp3', 'ogg'); + * soundFile = loadSound('assets/beat'); + * } + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(toggleSound); + * + * eq = new p5.EQ(eqBandNames.length); + * soundFile.disconnect(); + * eq.process(soundFile); + * } + * + * function draw() { + * background(30); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('filtering ', 50, 25); + * + * fill(255, 40, 255); + * textSize(26); + * text(eqBandNames[eqBandIndex], 50, 55); + * + * fill(255); + * textSize(9); + * + * if (!soundFile.isPlaying()) { + * text('tap to play', 50, 80); + * } else { + * text('tap to filter next band', 50, 80) + * } + * } + * + * function toggleSound() { + * if (!soundFile.isPlaying()) { + * soundFile.play(); + * } else { + * eqBandIndex = (eqBandIndex + 1) % eq.bands.length; + * } + * + * for (let i = 0; i < eq.bands.length; i++) { + * eq.bands[i].gain(0); + * } + * // filter the band we want to filter + * eq.bands[eqBandIndex].gain(-40); + * } + *
*/ +var eq_EQ = +function (_Effect) { + eq_inherits(EQ, _Effect); + + function EQ(_eqsize) { + var _this; + + eq_classCallCheck(this, EQ); + + _this = eq_possibleConstructorReturn(this, eq_getPrototypeOf(EQ).call(this)); + + _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3; + var factor; + _eqsize === 3 ? factor = Math.pow(2, 3) : factor = 2; + /** + * The p5.EQ is built with abstracted p5.Filter objects. + * To modify any bands, use methods of the + * p5.Filter API, especially `gain` and `freq`. + * Bands are stored in an array, with indices 0 - 3, or 0 - 7 + * @property {Array} bands + * + */ + + _this.bands = []; + var freq, res; + + for (var i = 0; i < _eqsize; i++) { + if (i === _eqsize - 1) { + freq = 21000; + res = 0.01; + } else if (i === 0) { + freq = 100; + res = 0.1; + } else if (i === 1) { + freq = _eqsize === 3 ? 360 * factor : 360; + res = 1; + } else { + freq = _this.bands[i - 1].freq() * factor; + res = 1; + } + + _this.bands[i] = _this._newBand(freq, res); -p5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) { - this.maxDist(maxDistance); - this.rolloff(rolloffFactor); -}; -/** - * Maxium distance between the source and the listener - * @method maxDist - * @for p5.Panner3D - * @param {Number} maxDistance - * @return {Number} updated value - */ + if (i > 0) { + _this.bands[i - 1].connect(_this.bands[i].biquad); + } else { + _this.input.connect(_this.bands[i].biquad); + } + } + _this.bands[_eqsize - 1].connect(_this.output); -p5.Panner3D.prototype.maxDist = function (maxDistance) { - if (typeof maxDistance === 'number') { - this.panner.maxDistance = maxDistance; + return _this; } + /** + * Process an input by connecting it to the EQ + * @method process + * @param {Object} src Audio source + */ - return this.panner.maxDistance; -}; -/** - * How quickly the volume is reduced as the source moves away from the listener - * @method rollof - * @for p5.Panner3D - * @param {Number} rolloffFactor - * @return {Number} updated value - */ + eq_createClass(EQ, [{ + key: "process", + value: function process(src) { + src.connect(this.input); + } + // * Set the frequency and gain of each band in the EQ. This method should be + // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ. + // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2); + // * + // * @method set + // * @for p5.EQ + // * @param {Number} [freq0] Frequency value for band with index 0 + // * @param {Number} [gain0] Gain value for band with index 0 + // * @param {Number} [freq1] Frequency value for band with index 1 + // * @param {Number} [gain1] Gain value for band with index 1 + // * @param {Number} [freq2] Frequency value for band with index 2 + // * @param {Number} [gain2] Gain value for band with index 2 + // * @param {Number} [freq3] Frequency value for band with index 3 + // * @param {Number} [gain3] Gain value for band with index 3 + // * @param {Number} [freq4] Frequency value for band with index 4 + // * @param {Number} [gain4] Gain value for band with index 4 + // * @param {Number} [freq5] Frequency value for band with index 5 + // * @param {Number} [gain5] Gain value for band with index 5 + // * @param {Number} [freq6] Frequency value for band with index 6 + // * @param {Number} [gain6] Gain value for band with index 6 + // * @param {Number} [freq7] Frequency value for band with index 7 + // * @param {Number} [gain7] Gain value for band with index 7 + // */ + + }, { + key: "set", + value: function set() { + if (arguments.length === this.bands.length * 2) { + for (var i = 0; i < arguments.length; i += 2) { + this.bands[i / 2].freq(arguments[i]); + this.bands[i / 2].gain(arguments[i + 1]); + } + } else { + console.error('Argument mismatch. .set() should be called with ' + this.bands.length * 2 + ' arguments. (one frequency and gain value pair for each band of the eq)'); + } + } + /** + * Add a new band. Creates a p5.Filter and strips away everything but + * the raw biquad filter. This method returns an abstracted p5.Filter, + * which can be added to p5.EQ.bands, in order to create new EQ bands. + * @private + * @for p5.EQ + * @method _newBand + * @param {Number} freq + * @param {Number} res + * @return {Object} Abstracted Filter + */ + + }, { + key: "_newBand", + value: function _newBand(freq, res) { + return new eqFilter(freq, res); + } + }, { + key: "dispose", + value: function dispose() { + eq_get(eq_getPrototypeOf(EQ.prototype), "dispose", this).call(this); + + if (this.bands) { + while (this.bands.length > 0) { + delete this.bands.pop().dispose(); + } -p5.Panner3D.prototype.rolloff = function (rolloffFactor) { - if (typeof rolloffFactor === 'number') { - this.panner.rolloffFactor = rolloffFactor; - } + delete this.bands; + } + } + }]); - return this.panner.rolloffFactor; -}; + return EQ; +}(effect); -p5.Panner3D.dispose = function () { - effect.prototype.dispose.apply(this); + var eq = (eq_EQ); +function listener3d_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - if (this.panner) { - this.panner.disconnect(); - delete this.panner; - } -}; +function listener3d_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); } } + +function listener3d_createClass(Constructor, protoProps, staticProps) { if (protoProps) listener3d_defineProperties(Constructor.prototype, protoProps); if (staticProps) listener3d_defineProperties(Constructor, staticProps); return Constructor; } - var panner3d = (p5.Panner3D); // * listener is a class that can construct both a Spatial Panner // * and a Spatial Listener. The panner is based on the // * Web Audio Spatial Panner Node @@ -7701,210 +7557,578 @@ p5.Panner3D.dispose = function () { // * @param {String} [type] [Specify construction of a spatial panner or listener] // */ -p5.Listener3D = function (type) { - this.ac = master.audiocontext; - this.listener = this.ac.listener; -}; -// * Connect an audio sorce -// * @param {Object} src Input source -// */ +var listener3d_Listener3D = +function () { + function Listener3D(type) { + listener3d_classCallCheck(this, Listener3D); + this.ac = master.audiocontext; + this.listener = this.ac.listener; + } + // * Connect an audio sorce + // * @param {Object} src Input source + // */ -p5.Listener3D.prototype.process = function (src) { - src.connect(this.input); -}; -// * Set the X,Y,Z position of the Panner -// * @param {[Number]} xVal -// * @param {[Number]} yVal -// * @param {[Number]} zVal -// * @param {[Number]} time -// * @return {[Array]} [Updated x, y, z values as an array] -// */ + listener3d_createClass(Listener3D, [{ + key: "process", + value: function process(src) { + src.connect(this.input); + } + // * Set the X,Y,Z position of the Panner + // * @param {[Number]} xVal + // * @param {[Number]} yVal + // * @param {[Number]} zVal + // * @param {[Number]} time + // * @return {[Array]} [Updated x, y, z values as an array] + // */ + + }, { + key: "position", + value: function position(xVal, yVal, zVal, time) { + this.positionX(xVal, time); + this.positionY(yVal, time); + this.positionZ(zVal, time); + return [this.listener.positionX.value, this.listener.positionY.value, this.listener.positionZ.value]; + } + // * Getter and setter methods for position coordinates + // * @return {Number} [updated coordinate value] + // */ + + }, { + key: "positionX", + value: function positionX(xVal, time) { + var t = time || 0; + + if (typeof xVal === 'number') { + this.listener.positionX.value = xVal; + this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); + } else if (xVal) { + xVal.connect(this.listener.positionX); + } -p5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) { - this.positionX(xVal, time); - this.positionY(yVal, time); - this.positionZ(zVal, time); - return [this.listener.positionX.value, this.listener.positionY.value, this.listener.positionZ.value]; -}; -// * Getter and setter methods for position coordinates -// * @return {Number} [updated coordinate value] -// */ + return this.listener.positionX.value; + } + }, { + key: "positionY", + value: function positionY(yVal, time) { + var t = time || 0; + + if (typeof yVal === 'number') { + this.listener.positionY.value = yVal; + this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); + } else if (yVal) { + yVal.connect(this.listener.positionY); + } + return this.listener.positionY.value; + } + }, { + key: "positionZ", + value: function positionZ(zVal, time) { + var t = time || 0; + + if (typeof zVal === 'number') { + this.listener.positionZ.value = zVal; + this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); + } else if (zVal) { + zVal.connect(this.listener.positionZ); + } -p5.Listener3D.prototype.positionX = function (xVal, time) { - var t = time || 0; + return this.listener.positionZ.value; + } + // * Overrides the listener orient() method because Listener has slightly + // * different params. In human terms, Forward vectors are the direction the + // * nose is pointing. Up vectors are the direction of the top of the head. + // * + // * @method orient + // * @param {Number} xValF Forward vector X direction + // * @param {Number} yValF Forward vector Y direction + // * @param {Number} zValF Forward vector Z direction + // * @param {Number} xValU Up vector X direction + // * @param {Number} yValU Up vector Y direction + // * @param {Number} zValU Up vector Z direction + // * @param {Number} time + // * @return {Array} All orienation params + // */ + + }, { + key: "orient", + value: function orient(xValF, yValF, zValF, xValU, yValU, zValU, time) { + if (arguments.length === 3 || arguments.length === 4) { + time = arguments[3]; + this.orientForward(xValF, yValF, zValF, time); + } else if (arguments.length === 6 || arguments === 7) { + this.orientForward(xValF, yValF, zValF); + this.orientUp(xValU, yValU, zValU, time); + } - if (typeof xVal === 'number') { - this.listener.positionX.value = xVal; - this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.positionX); - } + return [this.listener.forwardX.value, this.listener.forwardY.value, this.listener.forwardZ.value, this.listener.upX.value, this.listener.upY.value, this.listener.upZ.value]; + } + }, { + key: "orientForward", + value: function orientForward(xValF, yValF, zValF, time) { + this.forwardX(xValF, time); + this.forwardY(yValF, time); + this.forwardZ(zValF, time); + return [this.listener.forwardX, this.listener.forwardY, this.listener.forwardZ]; + } + }, { + key: "orientUp", + value: function orientUp(xValU, yValU, zValU, time) { + this.upX(xValU, time); + this.upY(yValU, time); + this.upZ(zValU, time); + return [this.listener.upX, this.listener.upY, this.listener.upZ]; + } + // * Getter and setter methods for orient coordinates + // * @return {Number} [updated coordinate value] + // */ + + }, { + key: "forwardX", + value: function forwardX(xVal, time) { + var t = time || 0; + + if (typeof xVal === 'number') { + this.listener.forwardX.value = xVal; + this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); + } else if (xVal) { + xVal.connect(this.listener.forwardX); + } - return this.listener.positionX.value; -}; + return this.listener.forwardX.value; + } + }, { + key: "forwardY", + value: function forwardY(yVal, time) { + var t = time || 0; + + if (typeof yVal === 'number') { + this.listener.forwardY.value = yVal; + this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); + } else if (yVal) { + yVal.connect(this.listener.forwardY); + } + + return this.listener.forwardY.value; + } + }, { + key: "forwardZ", + value: function forwardZ(zVal, time) { + var t = time || 0; + + if (typeof zVal === 'number') { + this.listener.forwardZ.value = zVal; + this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); + } else if (zVal) { + zVal.connect(this.listener.forwardZ); + } -p5.Listener3D.prototype.positionY = function (yVal, time) { - var t = time || 0; + return this.listener.forwardZ.value; + } + }, { + key: "upX", + value: function upX(xVal, time) { + var t = time || 0; + + if (typeof xVal === 'number') { + this.listener.upX.value = xVal; + this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); + } else if (xVal) { + xVal.connect(this.listener.upX); + } - if (typeof yVal === 'number') { - this.listener.positionY.value = yVal; - this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.positionY); - } + return this.listener.upX.value; + } + }, { + key: "upY", + value: function upY(yVal, time) { + var t = time || 0; + + if (typeof yVal === 'number') { + this.listener.upY.value = yVal; + this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); + } else if (yVal) { + yVal.connect(this.listener.upY); + } - return this.listener.positionY.value; -}; + return this.listener.upY.value; + } + }, { + key: "upZ", + value: function upZ(zVal, time) { + var t = time || 0; + + if (typeof zVal === 'number') { + this.listener.upZ.value = zVal; + this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); + } else if (zVal) { + zVal.connect(this.listener.upZ); + } -p5.Listener3D.prototype.positionZ = function (zVal, time) { - var t = time || 0; + return this.listener.upZ.value; + } + }]); - if (typeof zVal === 'number') { - this.listener.positionZ.value = zVal; - this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.positionZ); - } + return Listener3D; +}(); - return this.listener.positionZ.value; -}; -// * Overrides the listener orient() method because Listener has slightly -// * different params. In human terms, Forward vectors are the direction the -// * nose is pointing. Up vectors are the direction of the top of the head. -// * -// * @method orient -// * @param {Number} xValF Forward vector X direction -// * @param {Number} yValF Forward vector Y direction -// * @param {Number} zValF Forward vector Z direction -// * @param {Number} xValU Up vector X direction -// * @param {Number} yValU Up vector Y direction -// * @param {Number} zValU Up vector Z direction -// * @param {Number} time -// * @return {Array} All orienation params -// */ + var listener3d = (listener3d_Listener3D); +function panner3d_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { panner3d_typeof = function _typeof(obj) { return typeof obj; }; } else { panner3d_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return panner3d_typeof(obj); } +function panner3d_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -p5.Listener3D.prototype.orient = function (xValF, yValF, zValF, xValU, yValU, zValU, time) { - if (arguments.length === 3 || arguments.length === 4) { - time = arguments[3]; - this.orientForward(xValF, yValF, zValF, time); - } else if (arguments.length === 6 || arguments === 7) { - this.orientForward(xValF, yValF, zValF); - this.orientUp(xValU, yValU, zValU, time); - } +function panner3d_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); } } - return [this.listener.forwardX.value, this.listener.forwardY.value, this.listener.forwardZ.value, this.listener.upX.value, this.listener.upY.value, this.listener.upZ.value]; -}; +function panner3d_createClass(Constructor, protoProps, staticProps) { if (protoProps) panner3d_defineProperties(Constructor.prototype, protoProps); if (staticProps) panner3d_defineProperties(Constructor, staticProps); return Constructor; } -p5.Listener3D.prototype.orientForward = function (xValF, yValF, zValF, time) { - this.forwardX(xValF, time); - this.forwardY(yValF, time); - this.forwardZ(zValF, time); - return [this.listener.forwardX, this.listener.forwardY, this.listener.forwardZ]; -}; +function panner3d_possibleConstructorReturn(self, call) { if (call && (panner3d_typeof(call) === "object" || typeof call === "function")) { return call; } return panner3d_assertThisInitialized(self); } -p5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) { - this.upX(xValU, time); - this.upY(yValU, time); - this.upZ(zValU, time); - return [this.listener.upX, this.listener.upY, this.listener.upZ]; -}; -// * Getter and setter methods for orient coordinates -// * @return {Number} [updated coordinate value] -// */ +function panner3d_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +function panner3d_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { panner3d_get = Reflect.get; } else { panner3d_get = function _get(target, property, receiver) { var base = panner3d_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return panner3d_get(target, property, receiver || target); } -p5.Listener3D.prototype.forwardX = function (xVal, time) { - var t = time || 0; +function panner3d_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = panner3d_getPrototypeOf(object); if (object === null) break; } return object; } - if (typeof xVal === 'number') { - this.listener.forwardX.value = xVal; - this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.forwardX); - } +function panner3d_getPrototypeOf(o) { panner3d_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return panner3d_getPrototypeOf(o); } - return this.listener.forwardX.value; -}; +function panner3d_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) panner3d_setPrototypeOf(subClass, superClass); } -p5.Listener3D.prototype.forwardY = function (yVal, time) { - var t = time || 0; +function panner3d_setPrototypeOf(o, p) { panner3d_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return panner3d_setPrototypeOf(o, p); } - if (typeof yVal === 'number') { - this.listener.forwardY.value = yVal; - this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.forwardY); - } - return this.listener.forwardY.value; -}; +/** + * Panner3D is based on the + * Web Audio Spatial Panner Node. + * This panner is a spatial processing node that allows audio to be positioned + * and oriented in 3D space. + * + * The position is relative to an + * Audio Context Listener, which can be accessed + * by p5.soundOut.audiocontext.listener + * + * + * @class p5.Panner3D + * @constructor + */ -p5.Listener3D.prototype.forwardZ = function (zVal, time) { - var t = time || 0; +var Panner3D = +function (_Effect) { + panner3d_inherits(Panner3D, _Effect); - if (typeof zVal === 'number') { - this.listener.forwardZ.value = zVal; - this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.forwardZ); - } + function Panner3D() { + var _this; - return this.listener.forwardZ.value; -}; + panner3d_classCallCheck(this, Panner3D); -p5.Listener3D.prototype.upX = function (xVal, time) { - var t = time || 0; + _this = panner3d_possibleConstructorReturn(this, panner3d_getPrototypeOf(Panner3D).call(this)); + /** + * + * Web Audio Spatial Panner Node + * + * Properties include
+ * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType) + * : "equal power" or "HRTF"
+ * [DistanceModel](https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType) + * : "linear", "inverse", or "exponential" + * + * @property {AudioNode} panner + * + */ - if (typeof xVal === 'number') { - this.listener.upX.value = xVal; - this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.upX); - } + _this.panner = _this.ac.createPanner(); + _this.panner.panningModel = 'HRTF'; + _this.panner.distanceModel = 'linear'; - return this.listener.upX.value; -}; + _this.panner.connect(_this.output); -p5.Listener3D.prototype.upY = function (yVal, time) { - var t = time || 0; + _this.input.connect(_this.panner); - if (typeof yVal === 'number') { - this.listener.upY.value = yVal; - this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.upY); + return _this; } + /** + * Connect an audio sorce + * + * @method process + * @for p5.Panner3D + * @param {Object} src Input source + */ - return this.listener.upY.value; -}; -p5.Listener3D.prototype.upZ = function (zVal, time) { - var t = time || 0; + panner3d_createClass(Panner3D, [{ + key: "process", + value: function process(src) { + src.connect(this.input); + } + /** + * Set the X,Y,Z position of the Panner + * @method set + * @for p5.Panner3D + * @param {Number} xVal + * @param {Number} yVal + * @param {Number} zVal + * @param {Number} time + * @return {Array} Updated x, y, z values as an array + */ + + }, { + key: "set", + value: function set(xVal, yVal, zVal, time) { + this.positionX(xVal, time); + this.positionY(yVal, time); + this.positionZ(zVal, time); + return [this.panner.positionX.value, this.panner.positionY.value, this.panner.positionZ.value]; + } + /** + * Getter and setter methods for position coordinates + * @method positionX + * @for p5.Panner3D + * @return {Number} updated coordinate value + */ + + /** + * Getter and setter methods for position coordinates + * @method positionY + * @for p5.Panner3D + * @return {Number} updated coordinate value + */ + + /** + * Getter and setter methods for position coordinates + * @method positionZ + * @for p5.Panner3D + * @return {Number} updated coordinate value + */ + + }, { + key: "positionX", + value: function positionX(xVal, time) { + var t = time || 0; + + if (typeof xVal === 'number') { + this.panner.positionX.value = xVal; + this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); + } else if (xVal) { + xVal.connect(this.panner.positionX); + } - if (typeof zVal === 'number') { - this.listener.upZ.value = zVal; - this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.upZ); - } + return this.panner.positionX.value; + } + }, { + key: "positionY", + value: function positionY(yVal, time) { + var t = time || 0; + + if (typeof yVal === 'number') { + this.panner.positionY.value = yVal; + this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); + } else if (yVal) { + yVal.connect(this.panner.positionY); + } - return this.listener.upZ.value; -}; + return this.panner.positionY.value; + } + }, { + key: "positionZ", + value: function positionZ(zVal, time) { + var t = time || 0; + + if (typeof zVal === 'number') { + this.panner.positionZ.value = zVal; + this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); + } else if (zVal) { + zVal.connect(this.panner.positionZ); + } + + return this.panner.positionZ.value; + } + /** + * Set the X,Y,Z position of the Panner + * @method orient + * @for p5.Panner3D + * @param {Number} xVal + * @param {Number} yVal + * @param {Number} zVal + * @param {Number} time + * @return {Array} Updated x, y, z values as an array + */ + + }, { + key: "orient", + value: function orient(xVal, yVal, zVal, time) { + this.orientX(xVal, time); + this.orientY(yVal, time); + this.orientZ(zVal, time); + return [this.panner.orientationX.value, this.panner.orientationY.value, this.panner.orientationZ.value]; + } + /** + * Getter and setter methods for orient coordinates + * @method orientX + * @for p5.Panner3D + * @return {Number} updated coordinate value + */ + + /** + * Getter and setter methods for orient coordinates + * @method orientY + * @for p5.Panner3D + * @return {Number} updated coordinate value + */ + + /** + * Getter and setter methods for orient coordinates + * @method orientZ + * @for p5.Panner3D + * @return {Number} updated coordinate value + */ + + }, { + key: "orientX", + value: function orientX(xVal, time) { + var t = time || 0; + + if (typeof xVal === 'number') { + this.panner.orientationX.value = xVal; + this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); + } else if (xVal) { + xVal.connect(this.panner.orientationX); + } + + return this.panner.orientationX.value; + } + }, { + key: "orientY", + value: function orientY(yVal, time) { + var t = time || 0; + + if (typeof yVal === 'number') { + this.panner.orientationY.value = yVal; + this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); + } else if (yVal) { + yVal.connect(this.panner.orientationY); + } + + return this.panner.orientationY.value; + } + }, { + key: "orientZ", + value: function orientZ(zVal, time) { + var t = time || 0; + + if (typeof zVal === 'number') { + this.panner.orientationZ.value = zVal; + this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); + } else if (zVal) { + zVal.connect(this.panner.orientationZ); + } + + return this.panner.orientationZ.value; + } + /** + * Set the rolloff factor and max distance + * @method setFalloff + * @for p5.Panner3D + * @param {Number} [maxDistance] + * @param {Number} [rolloffFactor] + */ + + }, { + key: "setFalloff", + value: function setFalloff(maxDistance, rolloffFactor) { + this.maxDist(maxDistance); + this.rolloff(rolloffFactor); + } + /** + * Maxium distance between the source and the listener + * @method maxDist + * @for p5.Panner3D + * @param {Number} maxDistance + * @return {Number} updated value + */ + + }, { + key: "maxDist", + value: function maxDist(maxDistance) { + if (typeof maxDistance === 'number') { + this.panner.maxDistance = maxDistance; + } + + return this.panner.maxDistance; + } + /** + * How quickly the volume is reduced as the source moves away from the listener + * @method rollof + * @for p5.Panner3D + * @param {Number} rolloffFactor + * @return {Number} updated value + */ + + }, { + key: "rolloff", + value: function rolloff(rolloffFactor) { + if (typeof rolloffFactor === 'number') { + this.panner.rolloffFactor = rolloffFactor; + } + + return this.panner.rolloffFactor; + } + }, { + key: "dispose", + value: function dispose() { + panner3d_get(panner3d_getPrototypeOf(Panner3D.prototype), "dispose", this).call(this); + + if (this.panner) { + this.panner.disconnect(); + delete this.panner; + } + } + }]); + + return Panner3D; +}(effect); + + var panner3d = (Panner3D); +function delay_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { delay_typeof = function _typeof(obj) { return typeof obj; }; } else { delay_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return delay_typeof(obj); } + +function delay_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function delay_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); } } + +function delay_createClass(Constructor, protoProps, staticProps) { if (protoProps) delay_defineProperties(Constructor.prototype, protoProps); if (staticProps) delay_defineProperties(Constructor, staticProps); return Constructor; } + +function delay_possibleConstructorReturn(self, call) { if (call && (delay_typeof(call) === "object" || typeof call === "function")) { return call; } return delay_assertThisInitialized(self); } + +function delay_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function delay_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { delay_get = Reflect.get; } else { delay_get = function _get(target, property, receiver) { var base = delay_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return delay_get(target, property, receiver || target); } + +function delay_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = delay_getPrototypeOf(object); if (object === null) break; } return object; } + +function delay_getPrototypeOf(o) { delay_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return delay_getPrototypeOf(o); } + +function delay_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) delay_setPrototypeOf(subClass, superClass); } + +function delay_setPrototypeOf(o, p) { delay_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return delay_setPrototypeOf(o, p); } - var listener3d = (p5.Listener3D); /** @@ -7954,293 +8178,339 @@ p5.Listener3D.prototype.upZ = function (zVal, time) { * osc.stop(); * } * - */ - -p5.Delay = function () { - effect.call(this); - this._split = this.ac.createChannelSplitter(2); - this._merge = this.ac.createChannelMerger(2); - this._leftGain = this.ac.createGain(); - this._rightGain = this.ac.createGain(); - /** - * The p5.Delay is built with two - * - * Web Audio Delay Nodes, one for each stereo channel. - * - * @for p5.Delay - * @property {DelayNode} leftDelay - */ + */ - this.leftDelay = this.ac.createDelay(); - /** - * The p5.Delay is built with two - * - * Web Audio Delay Nodes, one for each stereo channel. - * @for p5.Delay - * @property {DelayNode} rightDelay - */ +var delay_Delay = +function (_Effect) { + delay_inherits(Delay, _Effect); - this.rightDelay = this.ac.createDelay(); - this._leftFilter = new filter(); - this._rightFilter = new filter(); + function Delay() { + var _this; - this._leftFilter.disconnect(); + delay_classCallCheck(this, Delay); - this._rightFilter.disconnect(); + _this = delay_possibleConstructorReturn(this, delay_getPrototypeOf(Delay).call(this)); + _this._split = _this.ac.createChannelSplitter(2); + _this._merge = _this.ac.createChannelMerger(2); + _this._leftGain = _this.ac.createGain(); + _this._rightGain = _this.ac.createGain(); + /** + * The p5.Delay is built with two + * + * Web Audio Delay Nodes, one for each stereo channel. + * + * @for p5.Delay + * @property {DelayNode} leftDelay + */ - this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime); + _this.leftDelay = _this.ac.createDelay(); + /** + * The p5.Delay is built with two + * + * Web Audio Delay Nodes, one for each stereo channel. + * @for p5.Delay + * @property {DelayNode} rightDelay + */ - this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime); + _this.rightDelay = _this.ac.createDelay(); + _this._leftFilter = new filter(); + _this._rightFilter = new filter(); - this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); + _this._leftFilter.disconnect(); - this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); + _this._rightFilter.disconnect(); + _this._leftFilter.biquad.frequency.setValueAtTime(1200, _this.ac.currentTime); - this.input.connect(this._split); - this.leftDelay.connect(this._leftGain); - this.rightDelay.connect(this._rightGain); + _this._rightFilter.biquad.frequency.setValueAtTime(1200, _this.ac.currentTime); - this._leftGain.connect(this._leftFilter.input); + _this._leftFilter.biquad.Q.setValueAtTime(0.3, _this.ac.currentTime); - this._rightGain.connect(this._rightFilter.input); + _this._rightFilter.biquad.Q.setValueAtTime(0.3, _this.ac.currentTime); - this._merge.connect(this.wet); - this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); + _this.input.connect(_this._split); - this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); + _this.leftDelay.connect(_this._leftGain); + _this.rightDelay.connect(_this._rightGain); - this.setType(0); - this._maxDelay = this.leftDelay.delayTime.maxValue; + _this._leftGain.connect(_this._leftFilter.input); - this.feedback(0.5); -}; + _this._rightGain.connect(_this._rightFilter.input); -p5.Delay.prototype = Object.create(effect.prototype); -/** - * Add delay to an audio signal according to a set - * of delay parameters. - * - * @method process - * @for p5.Delay - * @param {Object} Signal An object that outputs audio - * @param {Number} [delayTime] Time (in seconds) of the delay/echo. - * Some browsers limit delayTime to - * 1 second. - * @param {Number} [feedback] sends the delay back through itself - * in a loop that decreases in volume - * each time. - * @param {Number} [lowPass] Cutoff frequency. Only frequencies - * below the lowPass will be part of the - * delay. - */ + _this._merge.connect(_this.wet); -p5.Delay.prototype.process = function (src, _delayTime, _feedback, _filter) { - var feedback = _feedback || 0; - var delayTime = _delayTime || 0; + _this._leftFilter.biquad.gain.setValueAtTime(1, _this.ac.currentTime); - if (feedback >= 1.0) { - throw new Error('Feedback value will force a positive feedback loop.'); - } + _this._rightFilter.biquad.gain.setValueAtTime(1, _this.ac.currentTime); - if (delayTime >= this._maxDelay) { - throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.'); - } - src.connect(this.input); - this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); - this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); - this._leftGain.gain.value = feedback; - this._rightGain.gain.value = feedback; + _this.setType(0); + + _this._maxDelay = _this.leftDelay.delayTime.maxValue; - if (_filter) { - this._leftFilter.freq(_filter); + _this.feedback(0.5); - this._rightFilter.freq(_filter); + return _this; } -}; -/** - * Set the delay (echo) time, in seconds. Usually this value will be - * a floating point number between 0.0 and 1.0. - * - * @method delayTime - * @for p5.Delay - * @param {Number} delayTime Time (in seconds) of the delay - */ + /** + * Add delay to an audio signal according to a set + * of delay parameters. + * + * @method process + * @for p5.Delay + * @param {Object} Signal An object that outputs audio + * @param {Number} [delayTime] Time (in seconds) of the delay/echo. + * Some browsers limit delayTime to + * 1 second. + * @param {Number} [feedback] sends the delay back through itself + * in a loop that decreases in volume + * each time. + * @param {Number} [lowPass] Cutoff frequency. Only frequencies + * below the lowPass will be part of the + * delay. + */ -p5.Delay.prototype.delayTime = function (t) { - if (typeof t !== 'number') { - t.connect(this.leftDelay.delayTime); - t.connect(this.rightDelay.delayTime); - } else { - 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); - } -}; -/** - * Feedback occurs when Delay sends its signal back through its input - * in a loop. The feedback amount determines how much signal to send each - * time through the loop. A feedback greater than 1.0 is not desirable because - * it will increase the overall output each time through the loop, - * creating an infinite feedback loop. The default value is 0.5 - * - * @method feedback - * @for p5.Delay - * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an - * Oscillator that can be used to - * modulate this param - * @returns {Number} Feedback value - * - */ + delay_createClass(Delay, [{ + key: "process", + value: function process(src, _delayTime, _feedback, _filter) { + var feedback = _feedback || 0; + var delayTime = _delayTime || 0; + if (feedback >= 1.0) { + throw new Error('Feedback value will force a positive feedback loop.'); + } -p5.Delay.prototype.feedback = function (f) { - if (f && typeof f !== 'number') { - f.connect(this._leftGain.gain); - f.connect(this._rightGain.gain); - } else if (f >= 1.0) { - throw new Error('Feedback value will force a positive feedback loop.'); - } else if (typeof f === 'number') { - this._leftGain.gain.value = f; - this._rightGain.gain.value = f; - } + if (delayTime >= this._maxDelay) { + throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.'); + } + src.connect(this.input); + this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); + this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); + this._leftGain.gain.value = feedback; + this._rightGain.gain.value = feedback; - return this._leftGain.gain.value; -}; -/** - * Set a lowpass filter frequency for the delay. A lowpass filter - * will cut off any frequencies higher than the filter frequency. - * - * @method filter - * @for p5.Delay - * @param {Number|Object} cutoffFreq A lowpass filter will cut off any - * frequencies higher than the filter frequency. - * @param {Number|Object} res Resonance of the filter frequency - * cutoff, or an object (i.e. a p5.Oscillator) - * that can be used to modulate this parameter. - * High numbers (i.e. 15) will produce a resonance, - * low numbers (i.e. .2) will produce a slope. - */ + if (_filter) { + this._leftFilter.freq(_filter); + this._rightFilter.freq(_filter); + } + } + /** + * Set the delay (echo) time, in seconds. Usually this value will be + * a floating point number between 0.0 and 1.0. + * + * @method delayTime + * @for p5.Delay + * @param {Number} delayTime Time (in seconds) of the delay + */ + + }, { + key: "delayTime", + value: function delayTime(t) { + if (typeof t !== 'number') { + t.connect(this.leftDelay.delayTime); + t.connect(this.rightDelay.delayTime); + } else { + 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); + } + } + /** + * Feedback occurs when Delay sends its signal back through its input + * in a loop. The feedback amount determines how much signal to send each + * time through the loop. A feedback greater than 1.0 is not desirable because + * it will increase the overall output each time through the loop, + * creating an infinite feedback loop. The default value is 0.5 + * + * @method feedback + * @for p5.Delay + * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an + * Oscillator that can be used to + * modulate this param + * @returns {Number} Feedback value + * + */ + + }, { + key: "feedback", + value: function feedback(f) { + if (f && typeof f !== 'number') { + f.connect(this._leftGain.gain); + f.connect(this._rightGain.gain); + } else if (f >= 1.0) { + throw new Error('Feedback value will force a positive feedback loop.'); + } else if (typeof f === 'number') { + this._leftGain.gain.value = f; + this._rightGain.gain.value = f; + } -p5.Delay.prototype.filter = function (freq, q) { - this._leftFilter.set(freq, q); - this._rightFilter.set(freq, q); -}; -/** - * Choose a preset type of delay. 'pingPong' bounces the signal - * from the left to the right channel to produce a stereo effect. - * Any other parameter will revert to the default delay setting. - * - * @method setType - * @for p5.Delay - * @param {String|Number} type 'pingPong' (1) or 'default' (0) - */ + return this._leftGain.gain.value; + } + /** + * Set a lowpass filter frequency for the delay. A lowpass filter + * will cut off any frequencies higher than the filter frequency. + * + * @method filter + * @for p5.Delay + * @param {Number|Object} cutoffFreq A lowpass filter will cut off any + * frequencies higher than the filter frequency. + * @param {Number|Object} res Resonance of the filter frequency + * cutoff, or an object (i.e. a p5.Oscillator) + * that can be used to modulate this parameter. + * High numbers (i.e. 15) will produce a resonance, + * low numbers (i.e. .2) will produce a slope. + */ + + }, { + key: "filter", + value: function filter(freq, q) { + this._leftFilter.set(freq, q); + + this._rightFilter.set(freq, q); + } + /** + * Choose a preset type of delay. 'pingPong' bounces the signal + * from the left to the right channel to produce a stereo effect. + * Any other parameter will revert to the default delay setting. + * + * @method setType + * @for p5.Delay + * @param {String|Number} type 'pingPong' (1) or 'default' (0) + */ + + }, { + key: "setType", + value: function setType(t) { + if (t === 1) { + t = 'pingPong'; + } + this._split.disconnect(); -p5.Delay.prototype.setType = function (t) { - if (t === 1) { - t = 'pingPong'; - } + this._leftFilter.disconnect(); - this._split.disconnect(); + this._rightFilter.disconnect(); - this._leftFilter.disconnect(); + this._split.connect(this.leftDelay, 0); - this._rightFilter.disconnect(); + this._split.connect(this.rightDelay, 1); - this._split.connect(this.leftDelay, 0); + switch (t) { + case 'pingPong': + this._rightFilter.setType(this._leftFilter.biquad.type); - this._split.connect(this.rightDelay, 1); + this._leftFilter.output.connect(this._merge, 0, 0); - switch (t) { - case 'pingPong': - this._rightFilter.setType(this._leftFilter.biquad.type); + this._rightFilter.output.connect(this._merge, 0, 1); - this._leftFilter.output.connect(this._merge, 0, 0); + this._leftFilter.output.connect(this.rightDelay); - this._rightFilter.output.connect(this._merge, 0, 1); + this._rightFilter.output.connect(this.leftDelay); - this._leftFilter.output.connect(this.rightDelay); + break; - this._rightFilter.output.connect(this.leftDelay); + default: + this._leftFilter.output.connect(this._merge, 0, 0); - break; + this._rightFilter.output.connect(this._merge, 0, 1); - default: - this._leftFilter.output.connect(this._merge, 0, 0); + this._leftFilter.output.connect(this.leftDelay); - this._rightFilter.output.connect(this._merge, 0, 1); + this._rightFilter.output.connect(this.rightDelay); - this._leftFilter.output.connect(this.leftDelay); + } + } - this._rightFilter.output.connect(this.rightDelay); + /** + * Set the output level of the delay effect. + * + * @method amp + * @for p5.Delay + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @for p5.Delay + * @param {Object} unit + */ + + /** + * Disconnect all output. + * + * @method disconnect + * @for p5.Delay + */ + + }, { + key: "dispose", + value: function dispose() { + delay_get(delay_getPrototypeOf(Delay.prototype), "dispose", this).call(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 = undefined; + this._leftFilter = undefined; + this._rightFilter = undefined; + this._merge = undefined; + this._leftGain = undefined; + this._rightGain = undefined; + this.leftDelay = undefined; + this.rightDelay = undefined; + } + }]); - } -}; + return Delay; +}(effect); -/** - * Set the output level of the delay effect. - * - * @method amp - * @for p5.Delay - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ + var delay = (delay_Delay); +function reverb_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { reverb_typeof = function _typeof(obj) { return typeof obj; }; } else { reverb_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return reverb_typeof(obj); } -/** - * Send output to a p5.sound or web audio object - * - * @method connect - * @for p5.Delay - * @param {Object} unit - */ +function reverb_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -/** - * Disconnect all output. - * - * @method disconnect - * @for p5.Delay - */ +function reverb_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); } } +function reverb_createClass(Constructor, protoProps, staticProps) { if (protoProps) reverb_defineProperties(Constructor.prototype, protoProps); if (staticProps) reverb_defineProperties(Constructor, staticProps); return Constructor; } -p5.Delay.prototype.dispose = function () { - effect.prototype.dispose.apply(this); +function reverb_possibleConstructorReturn(self, call) { if (call && (reverb_typeof(call) === "object" || typeof call === "function")) { return call; } return reverb_assertThisInitialized(self); } - this._split.disconnect(); +function reverb_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } - this._leftFilter.dispose(); +function reverb_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { reverb_get = Reflect.get; } else { reverb_get = function _get(target, property, receiver) { var base = reverb_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return reverb_get(target, property, receiver || target); } - this._rightFilter.dispose(); +function reverb_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = reverb_getPrototypeOf(object); if (object === null) break; } return object; } - this._merge.disconnect(); +function reverb_getPrototypeOf(o) { reverb_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return reverb_getPrototypeOf(o); } - this._leftGain.disconnect(); +function reverb_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) reverb_setPrototypeOf(subClass, superClass); } - this._rightGain.disconnect(); +function reverb_setPrototypeOf(o, p) { reverb_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return reverb_setPrototypeOf(o, p); } - this.leftDelay.disconnect(); - this.rightDelay.disconnect(); - this._split = undefined; - this._leftFilter = undefined; - this._rightFilter = undefined; - this._merge = undefined; - this._leftGain = undefined; - this._rightGain = undefined; - this.leftDelay = undefined; - this.rightDelay = undefined; -}; - var delay = (p5.Delay); /** @@ -8295,174 +8565,194 @@ p5.Delay.prototype.dispose = function () { * */ -p5.Reverb = function () { - effect.call(this); - - this._initConvolverNode(); - - - this.input.gain.value = 0.5; +var Reverb = +function (_Effect) { + reverb_inherits(Reverb, _Effect); - this._seconds = 3; - this._decay = 2; - this._reverse = false; + function Reverb() { + var _this; - this._buildImpulse(); -}; - -p5.Reverb.prototype = Object.create(effect.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 () { - if (this.convolverNode) { - this.convolverNode.disconnect(); - delete this.convolverNode; - } -}; - -p5.Reverb.prototype._setBuffer = function (audioBuffer) { - this._teardownConvolverNode(); + reverb_classCallCheck(this, Reverb); - this._initConvolverNode(); - - this.convolverNode.buffer = audioBuffer; -}; -/** - * Connect a source to the reverb, and assign reverb parameters. - * - * @method process - * @for p5.Reverb - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - * @param {Number} [seconds] Duration of the reverb, in seconds. - * Min: 0, Max: 10. Defaults to 3. - * @param {Number} [decayRate] Percentage of decay with each echo. - * Min: 0, Max: 100. Defaults to 2. - * @param {Boolean} [reverse] Play the reverb backwards or forwards. - */ - - -p5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) { - src.connect(this.input); - var rebuild = false; - - if (seconds) { - this._seconds = seconds; - rebuild = true; - } + _this = reverb_possibleConstructorReturn(this, reverb_getPrototypeOf(Reverb).call(this)); - if (decayRate) { - this._decay = decayRate; - } + _this._initConvolverNode(); - if (reverse) { - this._reverse = reverse; - } - if (rebuild) { - this._buildImpulse(); - } -}; -/** - * Set the reverb settings. Similar to .process(), but without - * assigning a new input. - * - * @method set - * @for p5.Reverb - * @param {Number} [seconds] Duration of the reverb, in seconds. - * Min: 0, Max: 10. Defaults to 3. - * @param {Number} [decayRate] Percentage of decay with each echo. - * Min: 0, Max: 100. Defaults to 2. - * @param {Boolean} [reverse] Play the reverb backwards or forwards. - */ + _this.input.gain.value = 0.5; + _this._seconds = 3; + _this._decay = 2; + _this._reverse = false; -p5.Reverb.prototype.set = function (seconds, decayRate, reverse) { - var rebuild = false; + _this._buildImpulse(); - if (seconds) { - this._seconds = seconds; - rebuild = true; + return _this; } - if (decayRate) { - this._decay = decayRate; - } + reverb_createClass(Reverb, [{ + key: "_initConvolverNode", + value: function _initConvolverNode() { + this.convolverNode = this.ac.createConvolver(); + this.input.connect(this.convolverNode); + this.convolverNode.connect(this.wet); + } + }, { + key: "_teardownConvolverNode", + value: function _teardownConvolverNode() { + if (this.convolverNode) { + this.convolverNode.disconnect(); + delete this.convolverNode; + } + } + }, { + key: "_setBuffer", + value: function _setBuffer(audioBuffer) { + this._teardownConvolverNode(); - if (reverse) { - this._reverse = reverse; - } + this._initConvolverNode(); - if (rebuild) { - this._buildImpulse(); - } -}; + this.convolverNode.buffer = audioBuffer; + } + /** + * Connect a source to the reverb, and assign reverb parameters. + * + * @method process + * @for p5.Reverb + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + * @param {Number} [seconds] Duration of the reverb, in seconds. + * Min: 0, Max: 10. Defaults to 3. + * @param {Number} [decayRate] Percentage of decay with each echo. + * Min: 0, Max: 100. Defaults to 2. + * @param {Boolean} [reverse] Play the reverb backwards or forwards. + */ + + }, { + key: "process", + value: function process(src, seconds, decayRate, reverse) { + src.connect(this.input); + var rebuild = false; + + if (seconds) { + this._seconds = seconds; + rebuild = true; + } -/** - * Set the output level of the reverb effect. - * - * @method amp - * @for p5.Reverb - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ + if (decayRate) { + this._decay = decayRate; + } -/** - * Send output to a p5.sound or web audio object - * - * @method connect - * @for p5.Reverb - * @param {Object} unit - */ + if (reverse) { + this._reverse = reverse; + } -/** - * Disconnect all output. - * - * @method disconnect - * @for p5.Reverb - */ + if (rebuild) { + this._buildImpulse(); + } + } + /** + * Set the reverb settings. Similar to .process(), but without + * assigning a new input. + * + * @method set + * @for p5.Reverb + * @param {Number} [seconds] Duration of the reverb, in seconds. + * Min: 0, Max: 10. Defaults to 3. + * @param {Number} [decayRate] Percentage of decay with each echo. + * Min: 0, Max: 100. Defaults to 2. + * @param {Boolean} [reverse] Play the reverb backwards or forwards. + */ + + }, { + key: "set", + value: function set(seconds, decayRate, reverse) { + var rebuild = false; + + if (seconds) { + this._seconds = seconds; + rebuild = true; + } -/** - * Inspired by Simple Reverb by Jordan Santell - * https://github.com/web-audio-components/simple-reverb/blob/master/index.js - * - * Utility function for building an impulse response - * based on the module parameters. - * - * @private - */ + if (decayRate) { + this._decay = decayRate; + } + if (reverse) { + this._reverse = reverse; + } -p5.Reverb.prototype._buildImpulse = function () { - var rate = this.ac.sampleRate; - var length = rate * this._seconds; - var decay = this._decay; - var impulse = this.ac.createBuffer(2, length, rate); - var impulseL = impulse.getChannelData(0); - var impulseR = impulse.getChannelData(1); - var n, i; + if (rebuild) { + this._buildImpulse(); + } + } - for (i = 0; i < length; i++) { - n = this._reverse ? length - i : i; - impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); - impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); - } + /** + * Set the output level of the reverb effect. + * + * @method amp + * @for p5.Reverb + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @for p5.Reverb + * @param {Object} unit + */ + + /** + * Disconnect all output. + * + * @method disconnect + * @for p5.Reverb + */ + + /** + * Inspired by Simple Reverb by Jordan Santell + * https://github.com/web-audio-components/simple-reverb/blob/master/index.js + * + * Utility function for building an impulse response + * based on the module parameters. + * + * @private + */ + + }, { + key: "_buildImpulse", + value: function _buildImpulse() { + var rate = this.ac.sampleRate; + var length = rate * this._seconds; + var decay = this._decay; + var impulse = this.ac.createBuffer(2, length, rate); + var impulseL = impulse.getChannelData(0); + var impulseR = impulse.getChannelData(1); + var n, i; + + for (i = 0; i < length; i++) { + n = this._reverse ? length - i : i; + impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); + impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); + } - this._setBuffer(impulse); -}; + this._setBuffer(impulse); + } + }, { + key: "dispose", + value: function dispose() { + reverb_get(reverb_getPrototypeOf(Reverb.prototype), "dispose", this).call(this); -p5.Reverb.prototype.dispose = function () { - effect.prototype.dispose.apply(this); + this._teardownConvolverNode(); + } + }]); - this._teardownConvolverNode(); -}; + return Reverb; +}(effect); /** *

p5.Convolver extends p5.Reverb. It can emulate the sound of real @@ -8526,155 +8816,121 @@ p5.Reverb.prototype.dispose = function () { */ -p5.Convolver = function (path, callback, errorCallback) { - p5.Reverb.call(this); - /** - * Internally, the p5.Convolver uses the a - * - * Web Audio Convolver Node. - * - * @property {ConvolverNode} convolverNode - */ +var reverb_Convolver = +function (_Reverb) { + reverb_inherits(Convolver, _Reverb); - this._initConvolverNode(); + function Convolver(path, callback, errorCallback) { + var _this2; + reverb_classCallCheck(this, Convolver); - this.input.gain.value = 0.5; + _this2 = reverb_possibleConstructorReturn(this, reverb_getPrototypeOf(Convolver).call(this)); + /** + * Internally, the p5.Convolver uses the a + * + * Web Audio Convolver Node. + * + * @property {ConvolverNode} convolverNode + */ - if (path) { - this.impulses = []; + _this2._initConvolverNode(); - this._loadBuffer(path, callback, errorCallback); - } else { - this._seconds = 3; - this._decay = 2; - this._reverse = false; - this._buildImpulse(); - } -}; + _this2.input.gain.value = 0.5; -p5.Convolver.prototype = Object.create(p5.Reverb.prototype); -p5.prototype.registerPreloadMethod('createConvolver', p5.prototype); -/** - * Create a p5.Convolver. Accepts a path to a soundfile - * that will be used to generate an impulse response. - * - * @method createConvolver - * @for p5 - * @param {String} path path to a sound file - * @param {Function} [callback] function to call if loading is successful. - * The object will be passed in as the argument - * to the callback function. - * @param {Function} [errorCallback] function to call if loading is not successful. - * A custom error will be passed in as the argument - * to the callback function. - * @return {p5.Convolver} - * @example - *

- * let cVerb, sound; - * function preload() { - * // We have both MP3 and OGG versions of all sound assets - * soundFormats('ogg', 'mp3'); - * - * // Try replacing 'bx-spring' with other soundfiles like - * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' - * cVerb = createConvolver('assets/bx-spring.mp3'); - * - * // Try replacing 'Damscray_DancingTiger' with - * // 'beat', 'doorbell', lucky_dragons_-_power_melody' - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playSound); - * background(220); - * text('tap to play', 20, 20); - * - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * } - * - * function playSound() { - * sound.play(); - * } - *
- */ + if (path) { + _this2.impulses = []; -p5.prototype.createConvolver = function (path, callback, errorCallback) { - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } + _this2._loadBuffer(path, callback, errorCallback); + } else { + _this2._seconds = 3; + _this2._decay = 2; + _this2._reverse = false; - var self = this; - var cReverb = new p5.Convolver(path, function (buffer) { - if (typeof callback === 'function') { - callback(buffer); + _this2._buildImpulse(); } + /** + * If you load multiple impulse files using the .addImpulse method, + * they will be stored as Objects in this Array. Toggle between them + * with the toggleImpulse(id) method. + * + * @property {Array} impulses + * @for p5.Convolver + */ - if (typeof self._decrementPreload === 'function') { - self._decrementPreload(); - } - }, errorCallback); - cReverb.impulses = []; - return cReverb; -}; -/** - * Private method to load a buffer as an Impulse Response, - * assign it to the convolverNode, and add to the Array of .impulses. - * - * @param {String} path - * @param {Function} callback - * @param {Function} errorCallback - * @private - */ + _this2.impulses = []; + _this2.set = null; + return _this2; + } + /** + * Private method to load a buffer as an Impulse Response, + * assign it to the convolverNode, and add to the Array of .impulses. + * + * @param {String} path + * @param {Function} callback + * @param {Function} errorCallback + * @private + */ -p5.Convolver.prototype._loadBuffer = function (_path, callback, errorCallback) { - var path = p5.prototype._checkFileFormats(_path); - var self = this; - var errorTrace = new Error().stack; - var ac = p5.prototype.getAudioContext(); - var request = new XMLHttpRequest(); - request.open('GET', path, true); - request.responseType = 'arraybuffer'; - - request.onload = function () { - if (request.status === 200) { - ac.decodeAudioData(request.response, function (buff) { - var buffer = {}; - var chunks = path.split('/'); - buffer.name = chunks[chunks.length - 1]; - buffer.audioBuffer = buff; - self.impulses.push(buffer); - - self._setBuffer(buffer.audioBuffer); - - if (callback) { - callback(buffer); - } - }, - function () { - var err = new errorHandler('decodeAudioData', errorTrace, self.url); - var msg = 'AudioContext error at decodeAudioData for ' + self.url; + reverb_createClass(Convolver, [{ + key: "_loadBuffer", + value: function _loadBuffer(_path, callback, errorCallback) { + var path = p5.prototype._checkFileFormats(_path); - if (errorCallback) { - err.msg = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - }); - } - else { + var self = this; + var errorTrace = new Error().stack; + var ac = Object(audiocontext["b" ])(); + var request = new XMLHttpRequest(); + request.open('GET', path, true); + request.responseType = 'arraybuffer'; + + request.onload = function () { + if (request.status === 200) { + ac.decodeAudioData(request.response, function (buff) { + var buffer = {}; + var chunks = path.split('/'); + buffer.name = chunks[chunks.length - 1]; + buffer.audioBuffer = buff; + self.impulses.push(buffer); + + self._setBuffer(buffer.audioBuffer); + + if (callback) { + callback(buffer); + } + }, + function () { + var err = new errorHandler('decodeAudioData', errorTrace, self.url); + var msg = 'AudioContext error at decodeAudioData for ' + self.url; + + if (errorCallback) { + err.msg = msg; + errorCallback(err); + } else { + console.error(msg + '\n The error stack trace includes: \n' + err.stack); + } + }); + } + else { + var err = new errorHandler('loadConvolver', errorTrace, self.url); + var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; + + if (errorCallback) { + err.message = msg; + errorCallback(err); + } else { + console.error(msg + '\n The error stack trace includes: \n' + err.stack); + } + } + }; + + + request.onerror = function () { var err = new errorHandler('loadConvolver', errorTrace, self.url); - var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; + var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; if (errorCallback) { err.message = msg; @@ -8682,33 +8938,172 @@ p5.Convolver.prototype._loadBuffer = function (_path, callback, errorCallback) { } else { console.error(msg + '\n The error stack trace includes: \n' + err.stack); } + }; + + request.send(); + } + /** + * Connect a source to the convolver. + * + * @method process + * @for p5.Convolver + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + * @example + *
+ * let cVerb, sound; + * function preload() { + * // We have both MP3 and OGG versions of all sound assets + * soundFormats('ogg', 'mp3'); + * + * // Try replacing 'bx-spring' with other soundfiles like + * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' + * cVerb = createConvolver('assets/bx-spring.mp3'); + * + * // Try replacing 'Damscray_DancingTiger' with + * // 'beat', 'doorbell', lucky_dragons_-_power_melody' + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playSound); + * background(220); + * text('tap to play', 20, 20); + * + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * } + * + * function playSound() { + * sound.play(); + * } + * + *
+ */ + + }, { + key: "process", + value: function process(src) { + src.connect(this.input); + } + /** + * Load and assign a new Impulse Response to the p5.Convolver. + * The impulse is added to the .impulses array. Previous + * impulses can be accessed with the .toggleImpulse(id) + * method. + * + * @method addImpulse + * @for p5.Convolver + * @param {String} path path to a sound file + * @param {Function} callback function (optional) + * @param {Function} errorCallback function (optional) + */ + + }, { + key: "addImpulse", + value: function addImpulse(path, callback, errorCallback) { + if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { + alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); } - }; + this._loadBuffer(path, callback, errorCallback); + } + /** + * Similar to .addImpulse, except that the .impulses + * Array is reset to save memory. A new .impulses + * array is created with this impulse as the only item. + * + * @method resetImpulse + * @for p5.Convolver + * @param {String} path path to a sound file + * @param {Function} callback function (optional) + * @param {Function} errorCallback function (optional) + */ + + }, { + key: "resetImpulse", + value: function resetImpulse(path, callback, errorCallback) { + if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { + alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); + } - request.onerror = function () { - var err = new errorHandler('loadConvolver', errorTrace, self.url); - var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; + this.impulses = []; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); + this._loadBuffer(path, callback, errorCallback); } - }; + /** + * If you have used .addImpulse() to add multiple impulses + * to a p5.Convolver, then you can use this method to toggle between + * the items in the .impulses Array. Accepts a parameter + * to identify which impulse you wish to use, identified either by its + * original filename (String) or by its position in the .impulses + * Array (Number).
+ * You can access the objects in the .impulses Array directly. Each + * Object has two attributes: an .audioBuffer (type: + * Web Audio + * AudioBuffer) and a .name, a String that corresponds + * with the original filename. + * + * @method toggleImpulse + * @for p5.Convolver + * @param {String|Number} id Identify the impulse by its original filename + * (String), or by its position in the + * .impulses Array (Number). + */ + + }, { + key: "toggleImpulse", + value: function toggleImpulse(id) { + if (typeof id === 'number' && id < this.impulses.length) { + this._setBuffer(this.impulses[id].audioBuffer); + } - request.send(); -}; + if (typeof id === 'string') { + for (var i = 0; i < this.impulses.length; i++) { + if (this.impulses[i].name === id) { + this._setBuffer(this.impulses[i].audioBuffer); + + break; + } + } + } + } + }, { + key: "dispose", + value: function dispose() { + reverb_get(reverb_getPrototypeOf(Convolver.prototype), "dispose", this).call(this); + + + for (var i in this.impulses) { + if (this.impulses[i]) { + this.impulses[i] = null; + } + } + } + }]); -p5.Convolver.prototype.set = null; + return Convolver; +}(Reverb); /** - * Connect a source to the convolver. + * Create a p5.Convolver. Accepts a path to a soundfile + * that will be used to generate an impulse response. * - * @method process - * @for p5.Convolver - * @param {Object} src p5.sound / Web Audio object with a sound - * output. + * @method createConvolver + * @for p5 + * @param {String} path path to a sound file + * @param {Function} [callback] function to call if loading is successful. + * The object will be passed in as the argument + * to the callback function. + * @param {Function} [errorCallback] function to call if loading is not successful. + * A custom error will be passed in as the argument + * to the callback function. + * @return {p5.Convolver} * @example *
* let cVerb, sound; @@ -8742,206 +9137,156 @@ p5.Convolver.prototype.set = null; * function playSound() { * sound.play(); * } - * *
*/ -p5.Convolver.prototype.process = function (src) { - src.connect(this.input); -}; -/** - * If you load multiple impulse files using the .addImpulse method, - * they will be stored as Objects in this Array. Toggle between them - * with the toggleImpulse(id) method. - * - * @property {Array} impulses - * @for p5.Convolver - */ - - -p5.Convolver.prototype.impulses = []; -/** - * Load and assign a new Impulse Response to the p5.Convolver. - * The impulse is added to the .impulses array. Previous - * impulses can be accessed with the .toggleImpulse(id) - * method. - * - * @method addImpulse - * @for p5.Convolver - * @param {String} path path to a sound file - * @param {Function} callback function (optional) - * @param {Function} errorCallback function (optional) - */ - -p5.Convolver.prototype.addImpulse = function (path, callback, errorCallback) { - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - - this._loadBuffer(path, callback, errorCallback); -}; -/** - * Similar to .addImpulse, except that the .impulses - * Array is reset to save memory. A new .impulses - * array is created with this impulse as the only item. - * - * @method resetImpulse - * @for p5.Convolver - * @param {String} path path to a sound file - * @param {Function} callback function (optional) - * @param {Function} errorCallback function (optional) - */ - -p5.Convolver.prototype.resetImpulse = function (path, callback, errorCallback) { +function createConvolver(path, callback, errorCallback) { if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); } - this.impulses = []; - - this._loadBuffer(path, callback, errorCallback); -}; -/** - * If you have used .addImpulse() to add multiple impulses - * to a p5.Convolver, then you can use this method to toggle between - * the items in the .impulses Array. Accepts a parameter - * to identify which impulse you wish to use, identified either by its - * original filename (String) or by its position in the .impulses - * Array (Number).
- * You can access the objects in the .impulses Array directly. Each - * Object has two attributes: an .audioBuffer (type: - * Web Audio - * AudioBuffer) and a .name, a String that corresponds - * with the original filename. - * - * @method toggleImpulse - * @for p5.Convolver - * @param {String|Number} id Identify the impulse by its original filename - * (String), or by its position in the - * .impulses Array (Number). - */ - - -p5.Convolver.prototype.toggleImpulse = function (id) { - if (typeof id === 'number' && id < this.impulses.length) { - this._setBuffer(this.impulses[id].audioBuffer); - } - - if (typeof id === 'string') { - for (var i = 0; i < this.impulses.length; i++) { - if (this.impulses[i].name === id) { - this._setBuffer(this.impulses[i].audioBuffer); + var self = this; + var cReverb = new reverb_Convolver(path, function (buffer) { + if (typeof callback === 'function') { + callback(buffer); + } - break; - } + if (typeof self._decrementPreload === 'function') { + self._decrementPreload(); } - } -}; + }, errorCallback); + cReverb.impulses = []; + return cReverb; +} -p5.Convolver.prototype.dispose = function () { - p5.Reverb.prototype.dispose.apply(this); - for (var i in this.impulses) { - if (this.impulses[i]) { - this.impulses[i] = null; - } - } -}; var Clock = __webpack_require__(11); var Clock_default = __webpack_require__.n(Clock); +function metro_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function metro_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); } } +function metro_createClass(Constructor, protoProps, staticProps) { if (protoProps) metro_defineProperties(Constructor.prototype, protoProps); if (staticProps) metro_defineProperties(Constructor, staticProps); return Constructor; } -p5.Metro = function () { - this.clock = new Clock_default.a({ - callback: this.ontick.bind(this) - }); - this.syncedParts = []; - this.bpm = 120; - - this._init(); - this.prevTick = 0; - this.tatumTime = 0; - this.tickCallback = function () {}; -}; -p5.Metro.prototype.ontick = function (tickTime) { - var elapsedTime = tickTime - this.prevTick; - var secondsFromNow = tickTime - master.audiocontext.currentTime; +var metro_Metro = +function () { + function Metro() { + metro_classCallCheck(this, Metro); - if (elapsedTime - this.tatumTime <= -0.02) { - return; - } else { - this.prevTick = tickTime; + this.clock = new Clock_default.a({ + callback: this.ontick.bind(this) + }); + this.syncedParts = []; + this.bpm = 120; - var self = this; - this.syncedParts.forEach(function (thisPart) { - if (!thisPart.isPlaying) return; - thisPart.incrementStep(secondsFromNow); + this._init(); - thisPart.phrases.forEach(function (thisPhrase) { - var phraseArray = thisPhrase.sequence; - var bNum = self.metroTicks % phraseArray.length; + this.prevTick = 0; + this.tatumTime = 0; - if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping)) { - thisPhrase.callback(secondsFromNow, phraseArray[bNum]); - } - }); - }); - this.metroTicks += 1; - this.tickCallback(secondsFromNow); + this.tickCallback = function () {}; } -}; -p5.Metro.prototype.setBPM = function (bpm) { - var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var beatTime = 60 / (bpm * this.tatums); - var now = master.audiocontext.currentTime; - this.tatumTime = beatTime; - this.clock.frequency.setValueAtTime(this.clock.frequency.value, now); - this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime); - this.bpm = bpm; -}; + metro_createClass(Metro, [{ + key: "ontick", + value: function ontick(tickTime) { + var elapsedTime = tickTime - this.prevTick; + var secondsFromNow = tickTime - master.audiocontext.currentTime; -p5.Metro.prototype.getBPM = function () { - return this.clock.getRate() / this.tatums * 60; -}; + if (elapsedTime - this.tatumTime <= -0.02) { + return; + } else { + this.prevTick = tickTime; -p5.Metro.prototype._init = function () { - this.metroTicks = 0; -}; + var self = this; + this.syncedParts.forEach(function (thisPart) { + if (!thisPart.isPlaying) return; + thisPart.incrementStep(secondsFromNow); + thisPart.phrases.forEach(function (thisPhrase) { + var phraseArray = thisPhrase.sequence; + var bNum = self.metroTicks % phraseArray.length; -p5.Metro.prototype.resetSync = function (part) { - this.syncedParts = [part]; -}; + if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping)) { + thisPhrase.callback(secondsFromNow, phraseArray[bNum]); + } + }); + }); + this.metroTicks += 1; + this.tickCallback(secondsFromNow); + } + } + }, { + key: "setBPM", + value: function setBPM(bpm) { + var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var beatTime = 60 / (bpm * this.tatums); + var now = master.audiocontext.currentTime; + this.tatumTime = beatTime; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, now); + this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime); + this.bpm = bpm; + } + }, { + key: "getBPM", + value: function getBPM() { + return this.clock.getRate() / this.tatums * 60; + } + }, { + key: "_init", + value: function _init() { + this.metroTicks = 0; + } + }, { + key: "resetSync", + value: function resetSync(part) { + this.syncedParts = [part]; + } -p5.Metro.prototype.pushSync = function (part) { - this.syncedParts.push(part); -}; + }, { + key: "pushSync", + value: function pushSync(part) { + this.syncedParts.push(part); + } + }, { + key: "start", + value: function start(timeFromNow) { + var t = timeFromNow || 0; + var now = master.audiocontext.currentTime; + this.clock.start(now + t); + this.setBPM(this.bpm); + } + }, { + key: "stop", + value: function stop(timeFromNow) { + var t = timeFromNow || 0; + var now = master.audiocontext.currentTime; + this.clock.stop(now + t); + } + }, { + key: "beatLength", + value: function beatLength(tatums) { + this.tatums = 1 / tatums / 4; + } + }]); -p5.Metro.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = master.audiocontext.currentTime; - this.clock.start(now + t); - this.setBPM(this.bpm); -}; + return Metro; +}(); + + var metro = (metro_Metro); +function looper_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); } } + +function looper_createClass(Constructor, protoProps, staticProps) { if (protoProps) looper_defineProperties(Constructor.prototype, protoProps); if (staticProps) looper_defineProperties(Constructor, staticProps); return Constructor; } + +function looper_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -p5.Metro.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = master.audiocontext.currentTime; - this.clock.stop(now + t); -}; -p5.Metro.prototype.beatLength = function (tatums) { - this.tatums = 1 / tatums / 4; -}; var BPM = 120; /** @@ -9027,7 +9372,9 @@ p5.prototype.setBPM = function (bpm, rampTime) { */ -p5.Phrase = function (name, callback, sequence) { +var Phrase = function Phrase(name, callback, sequence) { + looper_classCallCheck(this, Phrase); + this.phraseStep = 0; this.name = name; this.callback = callback; @@ -9098,377 +9445,417 @@ p5.Phrase = function (name, callback, sequence) { */ -p5.Part = function (steps, bLength) { - this.length = steps || 0; - - this.partStep = 0; - this.phrases = []; - this.isPlaying = false; - this.noLoop(); - this.tatums = bLength || 0.0625; - - this.metro = new p5.Metro(); - - this.metro._init(); - - this.metro.beatLength(this.tatums); - this.metro.setBPM(BPM); - master.parts.push(this); - - this.callback = function () {}; -}; -/** - * Set the tempo of this part, in Beats Per Minute. - * - * @method setBPM - * @for p5.Part - * @param {Number} BPM Beats Per Minute - * @param {Number} [rampTime] Seconds from now - */ - - -p5.Part.prototype.setBPM = function (tempo, rampTime) { - this.metro.setBPM(tempo, rampTime); -}; -/** - * Returns the tempo, in Beats Per Minute, of this part. - * - * @method getBPM - * @for p5.Part - * @return {Number} - */ - - -p5.Part.prototype.getBPM = function () { - return this.metro.getBPM(); -}; -/** - * Start playback of this part. It will play - * through all of its phrases at a speed - * determined by setBPM. - * - * @method start - * @for p5.Part - * @param {Number} [time] seconds from now - */ - - -p5.Part.prototype.start = function (time) { - if (!this.isPlaying) { - this.isPlaying = true; - this.metro.resetSync(this); - var t = time || 0; - this.metro.start(t); - } -}; -/** - * Loop playback of this part. It will begin - * looping through all of its phrases at a speed - * determined by setBPM. - * - * @method loop - * @for p5.Part - * @param {Number} [time] seconds from now - */ - +var looper_Part = +function () { + function Part(steps, bLength) { + looper_classCallCheck(this, Part); -p5.Part.prototype.loop = function (time) { - this.looping = true; + this.length = steps || 0; - this.onended = function () { this.partStep = 0; - }; - - var t = time || 0; - this.start(t); -}; -/** - * Tell the part to stop looping. - * - * @method noLoop - * @for p5.Part - */ - - -p5.Part.prototype.noLoop = function () { - this.looping = false; - - this.onended = function () { - this.stop(); - }; -}; -/** - * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again. - * - * @method stop - * @for p5.Part - * @param {Number} [time] seconds from now - */ - - -p5.Part.prototype.stop = function (time) { - this.partStep = 0; - this.pause(time); -}; -/** - * Pause the part. Playback will resume - * from the current step. - * - * @method pause - * @for p5.Part - * @param {Number} time seconds from now - */ - - -p5.Part.prototype.pause = function (time) { - this.isPlaying = false; - var t = time || 0; - this.metro.stop(t); -}; -/** - * Add a p5.Phrase to this Part. - * - * @method addPhrase - * @for p5.Part - * @param {p5.Phrase} phrase reference to a p5.Phrase - */ - + this.phrases = []; + this.isPlaying = false; + this.noLoop(); + this.tatums = bLength || 0.0625; -p5.Part.prototype.addPhrase = function (name, callback, array) { - var p; + this.metro = new metro(); - if (arguments.length === 3) { - p = new p5.Phrase(name, callback, array); - } else if (arguments[0] instanceof p5.Phrase) { - p = arguments[0]; - } else { - throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase'; - } + this.metro._init(); - this.phrases.push(p); + this.metro.beatLength(this.tatums); + this.metro.setBPM(BPM); + master.parts.push(this); - if (p.sequence.length > this.length) { - this.length = p.sequence.length; + this.callback = function () {}; } -}; -/** - * Remove a phrase from this part, based on the name it was - * given when it was created. - * - * @method removePhrase - * @for p5.Part - * @param {String} phraseName - */ + /** + * Set the tempo of this part, in Beats Per Minute. + * + * @method setBPM + * @for p5.Part + * @param {Number} BPM Beats Per Minute + * @param {Number} [rampTime] Seconds from now + */ -p5.Part.prototype.removePhrase = function (name) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - this.phrases.splice(i, 1); + looper_createClass(Part, [{ + key: "setBPM", + value: function setBPM(tempo, rampTime) { + this.metro.setBPM(tempo, rampTime); } - } -}; -/** - * Get a phrase from this part, based on the name it was - * given when it was created. Now you can modify its array. - * - * @method getPhrase - * @for p5.Part - * @param {String} phraseName - */ - + /** + * Returns the tempo, in Beats Per Minute, of this part. + * + * @method getBPM + * @for p5.Part + * @return {Number} + */ + + }, { + key: "getBPM", + value: function getBPM() { + return this.metro.getBPM(); + } + /** + * Start playback of this part. It will play + * through all of its phrases at a speed + * determined by setBPM. + * + * @method start + * @for p5.Part + * @param {Number} [time] seconds from now + */ + + }, { + key: "start", + value: function start(time) { + if (!this.isPlaying) { + this.isPlaying = true; + this.metro.resetSync(this); + var t = time || 0; + this.metro.start(t); + } + } + /** + * Loop playback of this part. It will begin + * looping through all of its phrases at a speed + * determined by setBPM. + * + * @method loop + * @for p5.Part + * @param {Number} [time] seconds from now + */ + + }, { + key: "loop", + value: function loop(time) { + this.looping = true; + + this.onended = function () { + this.partStep = 0; + }; -p5.Part.prototype.getPhrase = function (name) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - return this.phrases[i]; + var t = time || 0; + this.start(t); } - } -}; -/** - * Find all sequences with the specified name, and replace their patterns with the specified array. - * - * @method replaceSequence - * @for p5.Part - * @param {String} phraseName - * @param {Array} sequence Array of values to pass into the callback - * at each step of the phrase. - */ + /** + * Tell the part to stop looping. + * + * @method noLoop + * @for p5.Part + */ + + }, { + key: "noLoop", + value: function noLoop() { + this.looping = false; + + this.onended = function () { + this.stop(); + }; + } + /** + * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again. + * + * @method stop + * @for p5.Part + * @param {Number} [time] seconds from now + */ + + }, { + key: "stop", + value: function stop(time) { + this.partStep = 0; + this.pause(time); + } + /** + * Pause the part. Playback will resume + * from the current step. + * + * @method pause + * @for p5.Part + * @param {Number} time seconds from now + */ + + }, { + key: "pause", + value: function pause(time) { + this.isPlaying = false; + var t = time || 0; + this.metro.stop(t); + } + /** + * Add a p5.Phrase to this Part. + * + * @method addPhrase + * @for p5.Part + * @param {p5.Phrase} phrase reference to a p5.Phrase + */ + + }, { + key: "addPhrase", + value: function addPhrase(name, callback, array) { + var p; + + if (arguments.length === 3) { + p = new Phrase(name, callback, array); + } else if (arguments[0] instanceof Phrase) { + p = arguments[0]; + } else { + throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase'; + } + this.phrases.push(p); -p5.Part.prototype.replaceSequence = function (name, array) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - this.phrases[i].sequence = array; + if (p.sequence.length > this.length) { + this.length = p.sequence.length; + } } - } -}; - -p5.Part.prototype.incrementStep = function (time) { - if (this.partStep < this.length - 1) { - this.callback(time); - this.partStep += 1; - } else { - if (!this.looping && this.partStep === this.length - 1) { - this.onended(); + /** + * Remove a phrase from this part, based on the name it was + * given when it was created. + * + * @method removePhrase + * @for p5.Part + * @param {String} phraseName + */ + + }, { + key: "removePhrase", + value: function removePhrase(name) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + this.phrases.splice(i, 1); + } + } } - } -}; -/** - * Set the function that will be called at every step. This will clear the previous function. - * - * @method onStep - * @for p5.Part - * @param {Function} callback The name of the callback - * you want to fire - * on every beat/tatum. - */ - + /** + * Get a phrase from this part, based on the name it was + * given when it was created. Now you can modify its array. + * + * @method getPhrase + * @for p5.Part + * @param {String} phraseName + */ + + }, { + key: "getPhrase", + value: function getPhrase(name) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + return this.phrases[i]; + } + } + } + /** + * Find all sequences with the specified name, and replace their patterns with the specified array. + * + * @method replaceSequence + * @for p5.Part + * @param {String} phraseName + * @param {Array} sequence Array of values to pass into the callback + * at each step of the phrase. + */ + + }, { + key: "replaceSequence", + value: function replaceSequence(name, array) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + this.phrases[i].sequence = array; + } + } + } + }, { + key: "incrementStep", + value: function incrementStep(time) { + if (this.partStep < this.length - 1) { + this.callback(time); + this.partStep += 1; + } else { + if (!this.looping && this.partStep === this.length - 1) { + this.onended(); + } + } + } + /** + * Set the function that will be called at every step. This will clear the previous function. + * + * @method onStep + * @for p5.Part + * @param {Function} callback The name of the callback + * you want to fire + * on every beat/tatum. + */ + + }, { + key: "onStep", + value: function onStep(callback) { + this.callback = callback; + } + }]); -p5.Part.prototype.onStep = function (callback) { - this.callback = callback; -}; + return Part; +}(); /** * A Score consists of a series of Parts. The parts will * be played back in order. For example, you could have an * A part, a B part, and a C part, and play them back in this order - * new p5.Score(a, a, b, a, c) - * - * @class p5.Score - * @constructor - * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence. - */ - - -p5.Score = function () { - this.parts = []; - this.currentPart = 0; - var thisScore = this; - - for (var i in arguments) { - if (arguments[i] && this.parts[i]) { - this.parts[i] = arguments[i]; - this.parts[i].nextPart = this.parts[i + 1]; - - this.parts[i].onended = function () { - thisScore.resetPart(i); - playNextPart(thisScore); - }; - } - } - - this.looping = false; -}; - -p5.Score.prototype.onended = function () { - if (this.looping) { - this.parts[0].start(); - } else { - this.parts[this.parts.length - 1].onended = function () { - this.stop(); - this.resetParts(); - }; - } - - this.currentPart = 0; -}; -/** - * Start playback of the score. - * - * @method start - * @for p5.Score - */ - - -p5.Score.prototype.start = function () { - this.parts[this.currentPart].start(); - this.scoreStep = 0; -}; -/** - * Stop playback of the score. - * - * @method stop - * @for p5.Score - */ - - -p5.Score.prototype.stop = function () { - this.parts[this.currentPart].stop(); - this.currentPart = 0; - this.scoreStep = 0; -}; -/** - * Pause playback of the score. - * - * @method pause - * @for p5.Score - */ - - -p5.Score.prototype.pause = function () { - this.parts[this.currentPart].stop(); -}; -/** - * Loop playback of the score. - * - * @method loop - * @for p5.Score - */ - - -p5.Score.prototype.loop = function () { - this.looping = true; - this.start(); -}; -/** - * Stop looping playback of the score. If it - * is currently playing, this will go into effect - * after the current round of playback completes. + * new p5.Score(a, a, b, a, c) * - * @method noLoop - * @for p5.Score + * @class p5.Score + * @constructor + * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence. */ -p5.Score.prototype.noLoop = function () { - this.looping = false; -}; +var Score = +function () { + function Score() { + looper_classCallCheck(this, Score); -p5.Score.prototype.resetParts = function () { - var self = this; - this.parts.forEach(function (part) { - self.resetParts[part]; - }); -}; + this.parts = []; + this.currentPart = 0; + var thisScore = this; -p5.Score.prototype.resetPart = function (i) { - this.parts[i].stop(); - this.parts[i].partStep = 0; + for (var i in arguments) { + if (arguments[i] && this.parts[i]) { + this.parts[i] = arguments[i]; + this.parts[i].nextPart = this.parts[i + 1]; - for (var p in this.parts[i].phrases) { - if (this.parts[i]) { - this.parts[i].phrases[p].phraseStep = 0; + this.parts[i].onended = function () { + thisScore.resetPart(i); + playNextPart(thisScore); + }; + } } + + this.looping = false; } -}; -/** - * Set the tempo for all parts in the score - * - * @method setBPM - * @for p5.Score - * @param {Number} BPM Beats Per Minute - * @param {Number} rampTime Seconds from now - */ + looper_createClass(Score, [{ + key: "onended", + value: function onended() { + if (this.looping) { + this.parts[0].start(); + } else { + this.parts[this.parts.length - 1].onended = function () { + this.stop(); + this.resetParts(); + }; + } -p5.Score.prototype.setBPM = function (bpm, rampTime) { - for (var i in this.parts) { - if (this.parts[i]) { - this.parts[i].setBPM(bpm, rampTime); + this.currentPart = 0; } - } -}; + /** + * Start playback of the score. + * + * @method start + * @for p5.Score + */ + + }, { + key: "start", + value: function start() { + this.parts[this.currentPart].start(); + this.scoreStep = 0; + } + /** + * Stop playback of the score. + * + * @method stop + * @for p5.Score + */ + + }, { + key: "stop", + value: function stop() { + this.parts[this.currentPart].stop(); + this.currentPart = 0; + this.scoreStep = 0; + } + /** + * Pause playback of the score. + * + * @method pause + * @for p5.Score + */ + + }, { + key: "pause", + value: function pause() { + this.parts[this.currentPart].stop(); + } + /** + * Loop playback of the score. + * + * @method loop + * @for p5.Score + */ + + }, { + key: "loop", + value: function loop() { + this.looping = true; + this.start(); + } + /** + * Stop looping playback of the score. If it + * is currently playing, this will go into effect + * after the current round of playback completes. + * + * @method noLoop + * @for p5.Score + */ + + }, { + key: "noLoop", + value: function noLoop() { + this.looping = false; + } + }, { + key: "resetParts", + value: function resetParts() { + var self = this; + this.parts.forEach(function (part) { + self.resetParts[part]; + }); + } + }, { + key: "resetPart", + value: function resetPart(i) { + this.parts[i].stop(); + this.parts[i].partStep = 0; + + for (var p in this.parts[i].phrases) { + if (this.parts[i]) { + this.parts[i].phrases[p].phraseStep = 0; + } + } + } + /** + * Set the tempo for all parts in the score + * + * @method setBPM + * @for p5.Score + * @param {Number} BPM Beats Per Minute + * @param {Number} rampTime Seconds from now + */ + + }, { + key: "setBPM", + value: function setBPM(bpm, rampTime) { + for (var i in this.parts) { + if (this.parts[i]) { + this.parts[i].setBPM(bpm, rampTime); + } + } + } + }]); + + return Score; +}(); function playNextPart(aScore) { aScore.currentPart++; @@ -9484,6 +9871,14 @@ function playNextPart(aScore) { } +function soundLoop_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function soundLoop_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); } } + +function soundLoop_createClass(Constructor, protoProps, staticProps) { if (protoProps) soundLoop_defineProperties(Constructor.prototype, protoProps); if (staticProps) soundLoop_defineProperties(Constructor, staticProps); return Constructor; } + + + /** * SoundLoop * @@ -9535,521 +9930,837 @@ function playNextPart(aScore) { * */ -p5.SoundLoop = function (callback, interval) { - this.callback = callback; - /** - * musicalTimeMode uses Tone.Time convention - * true if string, false if number - * @property {Boolean} musicalTimeMode - */ +var soundLoop_SoundLoop = +function () { + function SoundLoop(callback, interval) { + soundLoop_classCallCheck(this, SoundLoop); - this.musicalTimeMode = typeof this._interval === 'number' ? false : true; - this._interval = interval || 1; - /** - * musicalTimeMode variables - * modify these only when the interval is specified in musicalTime format as a string - */ + /** + * Getters and Setters, setting any paramter will result in a change in the clock's + * frequency, that will be reflected after the next callback + * beats per minute (defaults to 60) + * @property {Number} bpm + * @for p5.SoundLoop + */ + Object.defineProperty(this, 'bpm', { + get: function get() { + return this._bpm; + }, + set: function set(bpm) { + if (!this.musicalTimeMode) { + console.warn('Changing the BPM in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); + } + + this._bpm = bpm; + + this._update(); + } + }); + /** + * number of quarter notes in a measure (defaults to 4) + * @property {Number} timeSignature + * @for p5.SoundLoop + */ + + Object.defineProperty(this, 'timeSignature', { + get: function get() { + return this._timeSignature; + }, + set: function set(timeSig) { + if (!this.musicalTimeMode) { + console.warn('Changing the timeSignature in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); + } + + this._timeSignature = timeSig; + + this._update(); + } + }); + /** + * length of the loops interval + * @property {Number|String} interval + * @for p5.SoundLoop + */ + + Object.defineProperty(this, 'interval', { + get: function get() { + return this._interval; + }, + set: function set(interval) { + this.musicalTimeMode = typeof interval === 'number' ? false : true; + this._interval = interval; + + this._update(); + } + }); + /** + * how many times the callback has been called so far + * @property {Number} iterations + * @for p5.SoundLoop + * @readonly + */ + + Object.defineProperty(this, 'iterations', { + get: function get() { + return this.clock.ticks; + } + }); + this.callback = callback; + /** + * musicalTimeMode uses Tone.Time convention + * true if string, false if number + * @property {Boolean} musicalTimeMode + */ + + this.musicalTimeMode = typeof this._interval === 'number' ? false : true; + this._interval = interval || 1; + /** + * musicalTimeMode variables + * modify these only when the interval is specified in musicalTime format as a string + */ + + this._timeSignature = 4; + this._bpm = 60; + this.isPlaying = false; + /** + * Set a limit to the number of loops to play. defaults to Infinity + * @property {Number} maxIterations + */ - this._timeSignature = 4; - this._bpm = 60; - this.isPlaying = false; + this.maxIterations = Infinity; + var self = this; + this.clock = new Clock_default.a({ + callback: function callback(time) { + var timeFromNow = time - master.audiocontext.currentTime; + /** + * Do not initiate the callback if timeFromNow is < 0 + * This ususually occurs for a few milliseconds when the page + * is not fully loaded + * + * The callback should only be called until maxIterations is reached + */ + + if (timeFromNow > 0 && self.iterations <= self.maxIterations) { + self.callback(timeFromNow); + } + }, + frequency: this._calcFreq() + }); + } /** - * Set a limit to the number of loops to play. defaults to Infinity - * @property {Number} maxIterations + * Start the loop + * @method start + * @for p5.SoundLoop + * @param {Number} [timeFromNow] schedule a starting time */ - this.maxIterations = Infinity; - var self = this; - this.clock = new Clock_default.a({ - callback: function callback(time) { - var timeFromNow = time - master.audiocontext.currentTime; - /** - * Do not initiate the callback if timeFromNow is < 0 - * This ususually occurs for a few milliseconds when the page - * is not fully loaded - * - * The callback should only be called until maxIterations is reached - */ - - if (timeFromNow > 0 && self.iterations <= self.maxIterations) { - self.callback(timeFromNow); - } - }, - frequency: this._calcFreq() - }); -}; -/** - * Start the loop - * @method start - * @for p5.SoundLoop - * @param {Number} [timeFromNow] schedule a starting time - */ + soundLoop_createClass(SoundLoop, [{ + key: "start", + value: function start(timeFromNow) { + var t = timeFromNow || 0; + var now = master.audiocontext.currentTime; -p5.SoundLoop.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = master.audiocontext.currentTime; + if (!this.isPlaying) { + this.clock.start(now + t); + this.isPlaying = true; + } + } + /** + * Stop the loop + * @method stop + * @for p5.SoundLoop + * @param {Number} [timeFromNow] schedule a stopping time + */ + + }, { + key: "stop", + value: function stop(timeFromNow) { + var t = timeFromNow || 0; + var now = master.audiocontext.currentTime; - if (!this.isPlaying) { - this.clock.start(now + t); - this.isPlaying = true; - } -}; -/** - * Stop the loop - * @method stop - * @for p5.SoundLoop - * @param {Number} [timeFromNow] schedule a stopping time - */ + if (this.isPlaying) { + this.clock.stop(now + t); + this.isPlaying = false; + } + } + /** + * Pause the loop + * @method pause + * @for p5.SoundLoop + * @param {Number} [timeFromNow] schedule a pausing time + */ + + }, { + key: "pause", + value: function pause(timeFromNow) { + var t = timeFromNow || 0; + var now = master.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.pause(now + t); + this.isPlaying = false; + } + } + /** + * Synchronize loops. Use this method to start two or more loops in synchronization + * or to start a loop in synchronization with a loop that is already playing + * This method will schedule the implicit loop in sync with the explicit master loop + * i.e. loopToStart.syncedStart(loopToSyncWith) + * + * @method syncedStart + * @for p5.SoundLoop + * @param {Object} otherLoop a p5.SoundLoop to sync with + * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds + */ + + }, { + key: "syncedStart", + value: function syncedStart(otherLoop, timeFromNow) { + var t = timeFromNow || 0; + var now = master.audiocontext.currentTime; -p5.SoundLoop.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = master.audiocontext.currentTime; + if (!otherLoop.isPlaying) { + otherLoop.clock.start(now + t); + otherLoop.isPlaying = true; + this.clock.start(now + t); + this.isPlaying = true; + } else if (otherLoop.isPlaying) { + var time = otherLoop.clock._nextTick - master.audiocontext.currentTime; + this.clock.start(now + time); + this.isPlaying = true; + } + } + /** + * Updates frequency value, reflected in next callback + * @private + * @for p5.SoundLoop + * @method _update + */ + + }, { + key: "_update", + value: function _update() { + this.clock.frequency.value = this._calcFreq(); + } + /** + * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature + * @private + * @for p5.SoundLoop + * @method _calcFreq + * @return {Number} new clock frequency value + */ + + }, { + key: "_calcFreq", + value: function _calcFreq() { + if (typeof this._interval === 'number') { + this.musicalTimeMode = false; + return 1 / this._interval; + } + else if (typeof this._interval === 'string') { + this.musicalTimeMode = true; + return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4); + } + } + /** + * Convert notation from musical time format to seconds + * Uses Tone.Time convention + * @private + * @for p5.SoundLoop + * @method _convertNotation + * @param {String} value value to be converted + * @return {Number} converted value in seconds + */ + + }, { + key: "_convertNotation", + value: function _convertNotation(value) { + var type = value.slice(-1); + value = Number(value.slice(0, -1)); + + switch (type) { + case 'm': + return this._measure(value); + + case 'n': + return this._note(value); + + default: + console.warn('Specified interval is not formatted correctly. See Tone.js ' + 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'); + } + } + /** + * Helper conversion methods of measure and note + * @private + * @for p5.SoundLoop + * @method _measure + */ + + }, { + key: "_measure", + value: function _measure(value) { + return value * this._timeSignature; + } + /** + * @private + * @method _note + * @for p5.SoundLoop + */ + + }, { + key: "_note", + value: function _note(value) { + return this._timeSignature / value; + } + }]); - if (this.isPlaying) { - this.clock.stop(now + t); - this.isPlaying = false; - } -}; -/** - * Pause the loop - * @method pause - * @for p5.SoundLoop - * @param {Number} [timeFromNow] schedule a pausing time - */ + return SoundLoop; +}(); + var soundLoop = (soundLoop_SoundLoop); +function compressor_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { compressor_typeof = function _typeof(obj) { return typeof obj; }; } else { compressor_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return compressor_typeof(obj); } -p5.SoundLoop.prototype.pause = function (timeFromNow) { - var t = timeFromNow || 0; - var now = master.audiocontext.currentTime; +function compressor_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - if (this.isPlaying) { - this.clock.pause(now + t); - this.isPlaying = false; - } -}; -/** - * Synchronize loops. Use this method to start two or more loops in synchronization - * or to start a loop in synchronization with a loop that is already playing - * This method will schedule the implicit loop in sync with the explicit master loop - * i.e. loopToStart.syncedStart(loopToSyncWith) - * - * @method syncedStart - * @for p5.SoundLoop - * @param {Object} otherLoop a p5.SoundLoop to sync with - * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds - */ +function compressor_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); } } +function compressor_createClass(Constructor, protoProps, staticProps) { if (protoProps) compressor_defineProperties(Constructor.prototype, protoProps); if (staticProps) compressor_defineProperties(Constructor, staticProps); return Constructor; } -p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) { - var t = timeFromNow || 0; - var now = master.audiocontext.currentTime; +function compressor_possibleConstructorReturn(self, call) { if (call && (compressor_typeof(call) === "object" || typeof call === "function")) { return call; } return compressor_assertThisInitialized(self); } - if (!otherLoop.isPlaying) { - otherLoop.clock.start(now + t); - otherLoop.isPlaying = true; - this.clock.start(now + t); - this.isPlaying = true; - } else if (otherLoop.isPlaying) { - var time = otherLoop.clock._nextTick - master.audiocontext.currentTime; - this.clock.start(now + time); - this.isPlaying = true; - } -}; -/** - * Updates frequency value, reflected in next callback - * @private - * @for p5.SoundLoop - * @method _update - */ +function compressor_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +function compressor_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { compressor_get = Reflect.get; } else { compressor_get = function _get(target, property, receiver) { var base = compressor_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return compressor_get(target, property, receiver || target); } -p5.SoundLoop.prototype._update = function () { - this.clock.frequency.value = this._calcFreq(); -}; -/** - * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature - * @private - * @for p5.SoundLoop - * @method _calcFreq - * @return {Number} new clock frequency value - */ +function compressor_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = compressor_getPrototypeOf(object); if (object === null) break; } return object; } + +function compressor_getPrototypeOf(o) { compressor_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return compressor_getPrototypeOf(o); } + +function compressor_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) compressor_setPrototypeOf(subClass, superClass); } + +function compressor_setPrototypeOf(o, p) { compressor_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return compressor_setPrototypeOf(o, p); } -p5.SoundLoop.prototype._calcFreq = function () { - if (typeof this._interval === 'number') { - this.musicalTimeMode = false; - return 1 / this._interval; - } - else if (typeof this._interval === 'string') { - this.musicalTimeMode = true; - return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4); - } -}; /** - * Convert notation from musical time format to seconds - * Uses Tone.Time convention - * @private - * @for p5.SoundLoop - * @method _convertNotation - * @param {String} value value to be converted - * @return {Number} converted value in seconds + * Compressor is an audio effect class that performs dynamics compression + * on an audio input source. This is a very commonly used technique in music + * and sound production. Compression creates an overall louder, richer, + * and fuller sound by lowering the volume of louds and raising that of softs. + * Compression can be used to avoid clipping (sound distortion due to + * peaks in volume) and is especially useful when many sounds are played + * at once. Compression can be used on indivudal sound sources in addition + * to the master output. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Compressor + * @constructor + * @extends p5.Effect + * + * */ +var Compressor = +function (_Effect) { + compressor_inherits(Compressor, _Effect); -p5.SoundLoop.prototype._convertNotation = function (value) { - var type = value.slice(-1); - value = Number(value.slice(0, -1)); + function Compressor() { + var _this; - switch (type) { - case 'm': - return this._measure(value); + compressor_classCallCheck(this, Compressor); - case 'n': - return this._note(value); + _this = compressor_possibleConstructorReturn(this, compressor_getPrototypeOf(Compressor).call(this)); + /** + * + * The p5.Compressor is built with a Web Audio Dynamics Compressor Node + * + * @property {AudioNode} compressor + */ - default: - console.warn('Specified interval is not formatted correctly. See Tone.js ' + 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'); + _this.compressor = _this.ac.createDynamicsCompressor(); + + _this.input.connect(_this.compressor); + + _this.compressor.connect(_this.wet); + + return _this; } -}; -/** - * Helper conversion methods of measure and note - * @private - * @for p5.SoundLoop - * @method _measure - */ + /** + * Performs the same function as .connect, but also accepts + * optional parameters to set compressor's audioParams + * @method process + * @for p5.Compressor + * + * @param {Object} src Sound source to be connected + * + * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} [knee] A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} [threshold] The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + */ -p5.SoundLoop.prototype._measure = function (value) { - return value * this._timeSignature; -}; -/** - * @private - * @method _note - * @for p5.SoundLoop - */ + compressor_createClass(Compressor, [{ + key: "process", + value: function process(src, attack, knee, ratio, threshold, release) { + src.connect(this.input); + this.set(attack, knee, ratio, threshold, release); + } + /** + * Set the paramters of a compressor. + * @method set + * @for p5.Compressor + * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} knee A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} ratio The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} threshold The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + */ + + }, { + key: "set", + value: function set(attack, knee, ratio, threshold, release) { + if (typeof attack !== 'undefined') { + this.attack(attack); + } + if (typeof knee !== 'undefined') { + this.knee(knee); + } -p5.SoundLoop.prototype._note = function (value) { - return this._timeSignature / value; -}; -/** - * Getters and Setters, setting any parameter will result in a change in the clock's - * frequency, that will be reflected after the next callback - * beats per minute (defaults to 60) - * @property {Number} bpm - * @for p5.SoundLoop - */ + if (typeof ratio !== 'undefined') { + this.ratio(ratio); + } + if (typeof threshold !== 'undefined') { + this.threshold(threshold); + } -Object.defineProperty(p5.SoundLoop.prototype, 'bpm', { - get: function get() { - return this._bpm; - }, - set: function set(bpm) { - if (!this.musicalTimeMode) { - console.warn('Changing the BPM in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); + if (typeof release !== 'undefined') { + this.release(release); + } } + /** + * Get current attack or set value w/ time ramp + * + * + * @method attack + * @for p5.Compressor + * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} [time] Assign time value to schedule the change in value + */ + + }, { + key: "attack", + value: function attack(_attack, time) { + var t = time || 0; + + if (typeof _attack === 'number') { + this.compressor.attack.value = _attack; + this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.compressor.attack.linearRampToValueAtTime(_attack, this.ac.currentTime + 0.02 + t); + } else if (typeof _attack !== 'undefined') { + _attack.connect(this.compressor.attack); + } - this._bpm = bpm; + return this.compressor.attack.value; + } + /** + * Get current knee or set value w/ time ramp + * + * @method knee + * @for p5.Compressor + * @param {Number} [knee] A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} [time] Assign time value to schedule the change in value + */ + + }, { + key: "knee", + value: function knee(_knee, time) { + var t = time || 0; + + if (typeof _knee === 'number') { + this.compressor.knee.value = _knee; + this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.compressor.knee.linearRampToValueAtTime(_knee, this.ac.currentTime + 0.02 + t); + } else if (typeof _knee !== 'undefined') { + _knee.connect(this.compressor.knee); + } - this._update(); - } -}); -/** - * number of quarter notes in a measure (defaults to 4) - * @property {Number} timeSignature - * @for p5.SoundLoop - */ + return this.compressor.knee.value; + } + /** + * Get current ratio or set value w/ time ramp + * @method ratio + * @for p5.Compressor + * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} [time] Assign time value to schedule the change in value + */ + + }, { + key: "ratio", + value: function ratio(_ratio, time) { + var t = time || 0; + + if (typeof _ratio === 'number') { + this.compressor.ratio.value = _ratio; + this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.compressor.ratio.linearRampToValueAtTime(_ratio, this.ac.currentTime + 0.02 + t); + } else if (typeof _ratio !== 'undefined') { + _ratio.connect(this.compressor.ratio); + } -Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', { - get: function get() { - return this._timeSignature; - }, - set: function set(timeSig) { - if (!this.musicalTimeMode) { - console.warn('Changing the timeSignature in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); + return this.compressor.ratio.value; } + /** + * Get current threshold or set value w/ time ramp + * @method threshold + * @for p5.Compressor + * @param {Number} threshold The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} [time] Assign time value to schedule the change in value + */ + + }, { + key: "threshold", + value: function threshold(_threshold, time) { + var t = time || 0; + + if (typeof _threshold === 'number') { + this.compressor.threshold.value = _threshold; + this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.compressor.threshold.linearRampToValueAtTime(_threshold, this.ac.currentTime + 0.02 + t); + } else if (typeof _threshold !== 'undefined') { + _threshold.connect(this.compressor.threshold); + } - this._timeSignature = timeSig; + return this.compressor.threshold.value; + } + /** + * Get current release or set value w/ time ramp + * @method release + * @for p5.Compressor + * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + * + * @param {Number} [time] Assign time value to schedule the change in value + */ + + }, { + key: "release", + value: function release(_release, time) { + var t = time || 0; + + if (typeof _release === 'number') { + this.compressor.release.value = _release; + this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.compressor.release.linearRampToValueAtTime(_release, this.ac.currentTime + 0.02 + t); + } else if (typeof number !== 'undefined') { + _release.connect(this.compressor.release); + } - this._update(); - } -}); -/** - * length of the loops interval - * @property {Number|String} interval - * @for p5.SoundLoop - */ + return this.compressor.release.value; + } + /** + * Return the current reduction value + * + * @method reduction + * @for p5.Compressor + * @return {Number} Value of the amount of gain reduction that is applied to the signal + */ + + }, { + key: "reduction", + value: function reduction() { + return this.compressor.reduction.value; + } + }, { + key: "dispose", + value: function dispose() { + compressor_get(compressor_getPrototypeOf(Compressor.prototype), "dispose", this).call(this); + + if (this.compressor) { + this.compressor.disconnect(); + delete this.compressor; + } + } + }]); -Object.defineProperty(p5.SoundLoop.prototype, 'interval', { - get: function get() { - return this._interval; - }, - set: function set(interval) { - this.musicalTimeMode = typeof interval === 'number' ? false : true; - this._interval = interval; + return Compressor; +}(effect); - this._update(); - } -}); -/** - * how many times the callback has been called so far - * @property {Number} iterations - * @for p5.SoundLoop - * @readonly - */ + var compressor = (Compressor); +function peakDetect_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -Object.defineProperty(p5.SoundLoop.prototype, 'iterations', { - get: function get() { - return this.clock.ticks; - } -}); - var soundLoop = (p5.SoundLoop); +function peakDetect_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); } } + +function peakDetect_createClass(Constructor, protoProps, staticProps) { if (protoProps) peakDetect_defineProperties(Constructor.prototype, protoProps); if (staticProps) peakDetect_defineProperties(Constructor, staticProps); return Constructor; } /** - * Compressor is an audio effect class that performs dynamics compression - * on an audio input source. This is a very commonly used technique in music - * and sound production. Compression creates an overall louder, richer, - * and fuller sound by lowering the volume of louds and raising that of softs. - * Compression can be used to avoid clipping (sound distortion due to - * peaks in volume) and is especially useful when many sounds are played - * at once. Compression can be used on indivudal sound sources in addition - * to the master output. + *

PeakDetect works in conjunction with p5.FFT to + * look for onsets in some or all of the frequency spectrum. + *

+ *

+ * To use p5.PeakDetect, call update in the draw loop + * and pass in a p5.FFT object. + *

+ *

+ * You can listen for a specific part of the frequency spectrum by + * setting the range between freq1 and freq2. + *

+ * + *

threshold is the threshold for detecting a peak, + * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud + * as 1.0.

+ * + *

+ * The update method is meant to be run in the draw loop, and + * frames determines how many loops must pass before + * another peak can be detected. + * For example, if the frameRate() = 60, you could detect the beat of a + * 120 beat-per-minute song with this equation: + * framesPerPeak = 60 / (estimatedBPM / 60 ); + *

+ * + *

+ * Based on example contribtued by @b2renger, and a simple beat detection + * explanation by Felix Turner. + *

+ * + * @class p5.PeakDetect + * @constructor + * @param {Number} [freq1] lowFrequency - defaults to 20Hz + * @param {Number} [freq2] highFrequency - defaults to 20000 Hz + * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1 + * scaled logarithmically where 0.1 is 1/2 the loudness + * of 1.0. Defaults to 0.35. + * @param {Number} [framesPerPeak] Defaults to 20. + * @example + *
+ * + * var cnv, soundFile, fft, peakDetect; + * var ellipseWidth = 10; * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. + * function preload() { + * soundFile = loadSound('assets/beat.mp3'); + * } * - * @class p5.Compressor - * @constructor - * @extends p5.Effect + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); * + * // p5.PeakDetect requires a p5.FFT + * fft = new p5.FFT(); + * peakDetect = new p5.PeakDetect(); + * } * - */ - -p5.Compressor = function () { - effect.call(this); - /** - * The p5.Compressor is built with a Web Audio Dynamics Compressor Node - * - * @property {AudioNode} compressor - */ - - this.compressor = this.ac.createDynamicsCompressor(); - this.input.connect(this.compressor); - this.compressor.connect(this.wet); -}; - -p5.Compressor.prototype = Object.create(effect.prototype); -/** - * Performs the same function as .connect, but also accepts - * optional parameters to set compressor's audioParams - * @method process - * @for p5.Compressor - * - * @param {Object} src Sound source to be connected - * - * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} [knee] A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} [threshold] The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - */ - -p5.Compressor.prototype.process = function (src, attack, knee, ratio, threshold, release) { - src.connect(this.input); - this.set(attack, knee, ratio, threshold, release); -}; -/** - * Set the paramters of a compressor. - * @method set - * @for p5.Compressor - * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} knee A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} ratio The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} threshold The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - */ - - -p5.Compressor.prototype.set = function (attack, knee, ratio, threshold, release) { - if (typeof attack !== 'undefined') { - this.attack(attack); - } - - if (typeof knee !== 'undefined') { - this.knee(knee); - } - - if (typeof ratio !== 'undefined') { - this.ratio(ratio); - } - - if (typeof threshold !== 'undefined') { - this.threshold(threshold); - } - - if (typeof release !== 'undefined') { - this.release(release); - } -}; -/** - * Get current attack or set value w/ time ramp + * function draw() { + * background(0); + * text('click to play/pause', width/2, height/2); * + * // peakDetect accepts an fft post-analysis + * fft.analyze(); + * peakDetect.update(fft); * - * @method attack - * @for p5.Compressor - * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} [time] Assign time value to schedule the change in value - */ - - -p5.Compressor.prototype.attack = function (attack, time) { - var t = time || 0; - - if (typeof attack === 'number') { - this.compressor.attack.value = attack; - this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t); - } else if (typeof attack !== 'undefined') { - attack.connect(this.compressor.attack); - } - - return this.compressor.attack.value; -}; -/** - * Get current knee or set value w/ time ramp - * - * @method knee - * @for p5.Compressor - * @param {Number} [knee] A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} [time] Assign time value to schedule the change in value - */ - - -p5.Compressor.prototype.knee = function (knee, time) { - var t = time || 0; - - if (typeof knee === 'number') { - this.compressor.knee.value = knee; - this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t); - } else if (typeof knee !== 'undefined') { - knee.connect(this.compressor.knee); - } - - return this.compressor.knee.value; -}; -/** - * Get current ratio or set value w/ time ramp - * @method ratio - * @for p5.Compressor - * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} [time] Assign time value to schedule the change in value + * if ( peakDetect.isDetected ) { + * ellipseWidth = 50; + * } else { + * ellipseWidth *= 0.95; + * } + * + * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); + * } + * + * // toggle play/stop when canvas is clicked + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * if (soundFile.isPlaying() ) { + * soundFile.stop(); + * } else { + * soundFile.play(); + * } + * } + * } + *
*/ +var PeakDetect = +function () { + function PeakDetect(freq1, freq2, threshold, _framesPerPeak) { + peakDetect_classCallCheck(this, PeakDetect); + this.framesPerPeak = _framesPerPeak || 20; + this.framesSinceLastPeak = 0; + this.decayRate = 0.95; + this.threshold = threshold || 0.35; + this.cutoff = 0; + + this.cutoffMult = 1.5; + this.energy = 0; + this.penergy = 0; + + this.currentValue = 0; + /** + * isDetected is set to true when a peak is detected. + * + * @attribute isDetected {Boolean} + * @default false + */ -p5.Compressor.prototype.ratio = function (ratio, time) { - var t = time || 0; + this.isDetected = false; + this.f1 = freq1 || 40; + this.f2 = freq2 || 20000; - if (typeof ratio === 'number') { - this.compressor.ratio.value = ratio; - this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t); - } else if (typeof ratio !== 'undefined') { - ratio.connect(this.compressor.ratio); + this._onPeak = function () {}; } - - return this.compressor.ratio.value; -}; -/** - * Get current threshold or set value w/ time ramp - * @method threshold - * @for p5.Compressor - * @param {Number} threshold The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} [time] Assign time value to schedule the change in value - */ + /** + * The update method is run in the draw loop. + * + * Accepts an FFT object. You must call .analyze() + * on the FFT object prior to updating the peakDetect + * because it relies on a completed FFT analysis. + * + * @method update + * @param {p5.FFT} fftObject A p5.FFT object + */ -p5.Compressor.prototype.threshold = function (threshold, time) { - var t = time || 0; + peakDetect_createClass(PeakDetect, [{ + key: "update", + value: function update(fftObject) { + var nrg = this.energy = fftObject.getEnergy(this.f1, this.f2) / 255; - if (typeof threshold === 'number') { - this.compressor.threshold.value = threshold; - this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t); - } else if (typeof threshold !== 'undefined') { - threshold.connect(this.compressor.threshold); - } + if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) { + this._onPeak(); - return this.compressor.threshold.value; -}; -/** - * Get current release or set value w/ time ramp - * @method release - * @for p5.Compressor - * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - * - * @param {Number} [time] Assign time value to schedule the change in value - */ + this.isDetected = true; + this.cutoff = nrg * this.cutoffMult; + this.framesSinceLastPeak = 0; + } else { + this.isDetected = false; -p5.Compressor.prototype.release = function (release, time) { - var t = time || 0; + if (this.framesSinceLastPeak <= this.framesPerPeak) { + this.framesSinceLastPeak++; + } else { + this.cutoff *= this.decayRate; + this.cutoff = Math.max(this.cutoff, this.threshold); + } + } - if (typeof release === 'number') { - this.compressor.release.value = release; - this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t); - } else if (typeof number !== 'undefined') { - release.connect(this.compressor.release); - } + this.currentValue = nrg; + this.penergy = nrg; + } + /** + * onPeak accepts two arguments: a function to call when + * a peak is detected. The value of the peak, + * between 0.0 and 1.0, is passed to the callback. + * + * @method onPeak + * @param {Function} callback Name of a function that will + * be called when a peak is + * detected. + * @param {Object} [val] Optional value to pass + * into the function when + * a peak is detected. + * @example + *
+ * var cnv, soundFile, fft, peakDetect; + * var ellipseWidth = 0; + * + * function preload() { + * soundFile = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * cnv = createCanvas(100,100); + * textAlign(CENTER); + * + * fft = new p5.FFT(); + * peakDetect = new p5.PeakDetect(); + * + * setupSound(); + * + * // when a beat is detected, call triggerBeat() + * peakDetect.onPeak(triggerBeat); + * } + * + * function draw() { + * background(0); + * fill(255); + * text('click to play', width/2, height/2); + * + * fft.analyze(); + * peakDetect.update(fft); + * + * ellipseWidth *= 0.95; + * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); + * } + * + * // this function is called by peakDetect.onPeak + * function triggerBeat() { + * ellipseWidth = 50; + * } + * + * // mouseclick starts/stops sound + * function setupSound() { + * cnv.mouseClicked( function() { + * if (soundFile.isPlaying() ) { + * soundFile.stop(); + * } else { + * soundFile.play(); + * } + * }); + * } + *
+ */ + + }, { + key: "onPeak", + value: function onPeak(callback, val) { + var self = this; + + self._onPeak = function () { + callback(self.energy, val); + }; + } + }]); - return this.compressor.release.value; -}; -/** - * Return the current reduction value - * - * @method reduction - * @for p5.Compressor - * @return {Number} Value of the amount of gain reduction that is applied to the signal - */ + return PeakDetect; +}(); + var peakDetect = (PeakDetect); +function soundRecorder_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -p5.Compressor.prototype.reduction = function () { - return this.compressor.reduction.value; -}; +function soundRecorder_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); } } -p5.Compressor.prototype.dispose = function () { - effect.prototype.dispose.apply(this); +function soundRecorder_createClass(Constructor, protoProps, staticProps) { if (protoProps) soundRecorder_defineProperties(Constructor.prototype, protoProps); if (staticProps) soundRecorder_defineProperties(Constructor, staticProps); return Constructor; } - if (this.compressor) { - this.compressor.disconnect(); - delete this.compressor; - } -}; @@ -10129,1336 +10840,1636 @@ var soundRecorder_ac = master.audiocontext; * */ -p5.SoundRecorder = function () { - this.input = soundRecorder_ac.createGain(); - this.output = soundRecorder_ac.createGain(); - this._inputChannels = 2; - this._outputChannels = 2; - - var workletBufferSize = safeBufferSize(1024); - this._workletNode = new AudioWorkletNode(soundRecorder_ac, processorNames_default.a.recorderProcessor, { - outputChannelCount: [this._outputChannels], - processorOptions: { - numInputChannels: this._inputChannels, - bufferSize: workletBufferSize - } - }); - - this._workletNode.port.onmessage = function (event) { - if (event.data.name === 'buffers') { - var buffers = [new Float32Array(event.data.leftBuffer), new Float32Array(event.data.rightBuffer)]; - - this._callback(buffers); - } - }.bind(this); - /** - * callback invoked when the recording is over - * @private - * @type Function(Float32Array) - */ - - - this._callback = function () {}; - - - this._workletNode.connect(p5.soundOut._silentNode); - - this.setInput(); - - master.soundArray.push(this); -}; -/** - * Connect a specific device to the p5.SoundRecorder. - * If no parameter is given, p5.SoundRecorer will record - * all audible p5.sound from your sketch. - * - * @method setInput - * @for p5.SoundRecorder - * @param {Object} [unit] p5.sound object or a web audio unit - * that outputs sound - */ - - -p5.SoundRecorder.prototype.setInput = function (unit) { - this.input.disconnect(); - this.input = null; - this.input = soundRecorder_ac.createGain(); - this.input.connect(this._workletNode); - this.input.connect(this.output); - - if (unit) { - unit.connect(this.input); - } else { - p5.soundOut.output.connect(this.input); - } -}; -/** - * Start recording. To access the recording, provide - * a p5.SoundFile as the first parameter. The p5.SoundRecorder - * will send its recording to that p5.SoundFile for playback once - * recording is complete. Optional parameters include duration - * (in seconds) of the recording, and a callback function that - * will be called once the complete recording has been - * transfered to the p5.SoundFile. - * - * @method record - * @for p5.SoundRecorder - * @param {p5.SoundFile} soundFile p5.SoundFile - * @param {Number} [duration] Time (in seconds) - * @param {Function} [callback] The name of a function that will be - * called once the recording completes - */ - - -p5.SoundRecorder.prototype.record = function (sFile, duration, callback) { - this._workletNode.port.postMessage({ - name: 'start', - duration: duration - }); - - if (sFile && callback) { - this._callback = function (buffer) { - sFile.setBuffer(buffer); - callback(); - }; - } else if (sFile) { - this._callback = function (buffer) { - sFile.setBuffer(buffer); - }; - } -}; -/** - * Stop the recording. Once the recording is stopped, - * the results will be sent to the p5.SoundFile that - * was given on .record(), and if a callback function - * was provided on record, that function will be called. - * - * @method stop - * @for p5.SoundRecorder - */ - - -p5.SoundRecorder.prototype.stop = function () { - this._workletNode.port.postMessage({ - name: 'stop' - }); -}; - -p5.SoundRecorder.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); - - this._callback = function () {}; - - if (this.input) { - this.input.disconnect(); - } +var soundRecorder_SoundRecorder = +function () { + function SoundRecorder() { + soundRecorder_classCallCheck(this, SoundRecorder); - this.input = null; - this._workletNode = null; -}; -/** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. - * For uploading audio to a server, use - * `p5.SoundFile.saveBlob`. - * - * @for p5 - * @method saveSound - * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save - * @param {String} fileName name of the resulting .wav file. - */ + this.input = soundRecorder_ac.createGain(); + this.output = soundRecorder_ac.createGain(); + this._inputChannels = 2; + this._outputChannels = 2; + var workletBufferSize = safeBufferSize(1024); + this._workletNode = new AudioWorkletNode(soundRecorder_ac, processorNames_default.a.recorderProcessor, { + outputChannelCount: [this._outputChannels], + processorOptions: { + numInputChannels: this._inputChannels, + bufferSize: workletBufferSize + } + }); -p5.prototype.saveSound = function (soundFile, fileName) { - var dataView = convertToWav(soundFile.buffer); - p5.prototype.writeFile([dataView], fileName, 'wav'); -}; -var peakDetect = __webpack_require__(40); + this._workletNode.port.onmessage = function (event) { + if (event.data.name === 'buffers') { + var buffers = [new Float32Array(event.data.leftBuffer), new Float32Array(event.data.rightBuffer)]; + this._callback(buffers); + } + }.bind(this); + /** + * callback invoked when the recording is over + * @private + * @type Function(Float32Array) + */ -/** - * A gain node is usefull to set the relative volume of sound. - * It's typically used to build mixers. - * - * @class p5.Gain - * @constructor - * @example - *
- * - * // load two soundfile and crossfade beetween them - * let sound1,sound2; - * let sound1Gain, sound2Gain, masterGain; - * function preload(){ - * soundFormats('ogg', 'mp3'); - * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01'); - * sound2 = loadSound('assets/beat'); - * } - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(startSound); - * // create a 'master' gain to which we will connect both soundfiles - * masterGain = new p5.Gain(); - * masterGain.connect(); - * sound1.disconnect(); // diconnect from p5 output - * sound1Gain = new p5.Gain(); // setup a gain node - * sound1Gain.setInput(sound1); // connect the first sound to its input - * sound1Gain.connect(masterGain); // connect its output to the 'master' - * sound2.disconnect(); - * sound2Gain = new p5.Gain(); - * sound2Gain.setInput(sound2); - * sound2Gain.connect(masterGain); - * } - * function startSound() { - * sound1.loop(); - * sound2.loop(); - * loop(); - * } - * function mouseReleased() { - * sound1.stop(); - * sound2.stop(); - * } - * function draw(){ - * background(220); - * textAlign(CENTER); - * textSize(11); - * fill(0); - * if (!sound1.isPlaying()) { - * text('tap and drag to play', width/2, height/2); - * return; - * } - * // map the horizontal position of the mouse to values useable for volume * control of sound1 - * var sound1Volume = constrain(map(mouseX,width,0,0,1), 0, 1); - * var sound2Volume = 1-sound1Volume; - * sound1Gain.amp(sound1Volume); - * sound2Gain.amp(sound2Volume); - * // map the vertical position of the mouse to values useable for 'master * volume control' - * var masterVolume = constrain(map(mouseY,height,0,0,1), 0, 1); - * masterGain.amp(masterVolume); - * text('master', width/2, height - masterVolume * height * 0.9) - * fill(255, 0, 255); - * textAlign(LEFT); - * text('sound1', 5, height - sound1Volume * height * 0.9); - * textAlign(RIGHT); - * text('sound2', width - 5, height - sound2Volume * height * 0.9); - * } - *
- */ -p5.Gain = function () { - this.ac = master.audiocontext; - this.input = this.ac.createGain(); - this.output = this.ac.createGain(); + this._callback = function () {}; - this.input.gain.value = 0.5; - this.input.connect(this.output); - master.soundArray.push(this); -}; -/** - * Connect a source to the gain node. - * - * @method setInput - * @for p5.Gain - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - */ + this._workletNode.connect(p5.soundOut._silentNode); + this.setInput(); -p5.Gain.prototype.setInput = function (src) { - src.connect(this.input); -}; -/** - * Send output to a p5.sound or web audio object - * - * @method connect - * @for p5.Gain - * @param {Object} unit - */ + master.soundArray.push(this); + } + /** + * Connect a specific device to the p5.SoundRecorder. + * If no parameter is given, p5.SoundRecorer will record + * all audible p5.sound from your sketch. + * + * @method setInput + * @for p5.SoundRecorder + * @param {Object} [unit] p5.sound object or a web audio unit + * that outputs sound + */ -p5.Gain.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - this.output.connect(u.input ? u.input : u); -}; -/** - * Disconnect all output. - * - * @method disconnect - * @for p5.Gain - */ + soundRecorder_createClass(SoundRecorder, [{ + key: "setInput", + value: function setInput(unit) { + this.input.disconnect(); + this.input = null; + this.input = soundRecorder_ac.createGain(); + this.input.connect(this._workletNode); + this.input.connect(this.output); + if (unit) { + unit.connect(this.input); + } else { + p5.soundOut.output.connect(this.input); + } + } + /** + * Start recording. To access the recording, provide + * a p5.SoundFile as the first parameter. The p5.SoundRecorder + * will send its recording to that p5.SoundFile for playback once + * recording is complete. Optional parameters include duration + * (in seconds) of the recording, and a callback function that + * will be called once the complete recording has been + * transfered to the p5.SoundFile. + * + * @method record + * @for p5.SoundRecorder + * @param {p5.SoundFile} soundFile p5.SoundFile + * @param {Number} [duration] Time (in seconds) + * @param {Function} [callback] The name of a function that will be + * called once the recording completes + */ + + }, { + key: "record", + value: function record(sFile, duration, callback) { + this._workletNode.port.postMessage({ + name: 'start', + duration: duration + }); -p5.Gain.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } -}; -/** - * Set the output level of the gain node. - * - * @method amp - * @for p5.Gain - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ + if (sFile && callback) { + this._callback = function (buffer) { + sFile.setBuffer(buffer); + callback(); + }; + } else if (sFile) { + this._callback = function (buffer) { + sFile.setBuffer(buffer); + }; + } + } + /** + * Stop the recording. Once the recording is stopped, + * the results will be sent to the p5.SoundFile that + * was given on .record(), and if a callback function + * was provided on record, that function will be called. + * + * @method stop + * @for p5.SoundRecorder + */ + + }, { + key: "stop", + value: function stop() { + this._workletNode.port.postMessage({ + name: 'stop' + }); + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + this._callback = function () {}; -p5.Gain.prototype.amp = function (vol) { - var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var now = master.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); -}; + if (this.input) { + this.input.disconnect(); + } -p5.Gain.prototype.dispose = function () { - var index = master.soundArray.indexOf(this); - master.soundArray.splice(index, 1); + this.input = null; + this._workletNode = null; + } + }]); - if (this.output) { - this.output.disconnect(); - delete this.output; - } + return SoundRecorder; +}(); - if (this.input) { - this.input.disconnect(); - delete this.input; - } -}; + var soundRecorder = (soundRecorder_SoundRecorder); +function distortion_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { distortion_typeof = function _typeof(obj) { return typeof obj; }; } else { distortion_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return distortion_typeof(obj); } + +function distortion_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function distortion_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); } } + +function distortion_createClass(Constructor, protoProps, staticProps) { if (protoProps) distortion_defineProperties(Constructor.prototype, protoProps); if (staticProps) distortion_defineProperties(Constructor, staticProps); return Constructor; } + +function distortion_possibleConstructorReturn(self, call) { if (call && (distortion_typeof(call) === "object" || typeof call === "function")) { return call; } return distortion_assertThisInitialized(self); } + +function distortion_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function distortion_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { distortion_get = Reflect.get; } else { distortion_get = function _get(target, property, receiver) { var base = distortion_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return distortion_get(target, property, receiver || target); } + +function distortion_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = distortion_getPrototypeOf(object); if (object === null) break; } return object; } + +function distortion_getPrototypeOf(o) { distortion_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return distortion_getPrototypeOf(o); } + +function distortion_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) distortion_setPrototypeOf(subClass, superClass); } + +function distortion_setPrototypeOf(o, p) { distortion_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return distortion_setPrototypeOf(o, p); } + + + +function makeDistortionCurve(amount) { + var k = typeof amount === 'number' ? amount : 50; + var numSamples = 44100; + var curve = new Float32Array(numSamples); + var deg = Math.PI / 180; + var i = 0; + var x; - var gain = (p5.Gain); + for (; i < numSamples; ++i) { + x = i * 2 / numSamples - 1; + curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x)); + } + return curve; +} /** - * Base class for monophonic synthesizers. Any extensions of this class - * should follow the API and implement the methods below in order to - * remain compatible with p5.PolySynth(); + * A Distortion effect created with a Waveshaper Node, + * with an approach adapted from + * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) * - * @class p5.AudioVoice + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Distortion + * @extends p5.Effect * @constructor + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + * */ -p5.AudioVoice = function () { - this.ac = master.audiocontext; - this.output = this.ac.createGain(); - this.connect(); - master.soundArray.push(this); -}; -p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) {}; +var Distortion = +function (_Effect) { + distortion_inherits(Distortion, _Effect); -p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) {}; + function Distortion(amount, oversample) { + var _this; -p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {}; + distortion_classCallCheck(this, Distortion); -p5.AudioVoice.prototype.amp = function (vol, rampTime) {}; -/** - * Connect to p5 objects or Web Audio Nodes - * @method connect - * @for p5.AudioVoice - * @param {Object} unit - */ + _this = distortion_possibleConstructorReturn(this, distortion_getPrototypeOf(Distortion).call(this)); + if (typeof amount === 'undefined') { + amount = 0.25; + } -p5.AudioVoice.prototype.connect = function (unit) { - var u = unit || master.input; - this.output.connect(u.input ? u.input : u); -}; -/** - * Disconnect from soundOut - * @method disconnect - * @for p5.AudioVoice - */ + if (typeof amount !== 'number') { + throw new Error('amount must be a number'); + } + if (typeof oversample === 'undefined') { + oversample = '2x'; + } -p5.AudioVoice.prototype.disconnect = function () { - this.output.disconnect(); -}; + if (typeof oversample !== 'string') { + throw new Error('oversample must be a String'); + } -p5.AudioVoice.prototype.dispose = function () { - if (this.output) { - this.output.disconnect(); - delete this.output; - } -}; + var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000); + /** + * The p5.Distortion is built with a + * + * Web Audio WaveShaper Node. + * + * @property {AudioNode} WaveShaperNode + */ - var audioVoice_0 = (p5.AudioVoice); + _this.waveShaperNode = _this.ac.createWaveShaper(); + _this.amount = curveAmount; + _this.waveShaperNode.curve = makeDistortionCurve(curveAmount); + _this.waveShaperNode.oversample = oversample; + _this.input.connect(_this.waveShaperNode); + _this.waveShaperNode.connect(_this.wet); -var DEFAULT_SUSTAIN = 0.15; -/** - * A MonoSynth is used as a single voice for sound synthesis. - * This is a class to be used in conjunction with the PolySynth - * class. Custom synthetisers should be built inheriting from - * this class. - * - * @class p5.MonoSynth - * @constructor - * @example - *
- * let monoSynth; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * background(220); - * textAlign(CENTER); - * text('tap to play', width/2, height/2); - * - * monoSynth = new p5.MonoSynth(); - * } - * - * function playSynth() { - * userStartAudio(); - * - * let note = random(['Fb4', 'G4']); - * // note velocity (volume, from 0 to 1) - * let velocity = random(); - * // time from now (in seconds) - * let time = 0; - * // note duration (in seconds) - * let dur = 1/6; - * - * monoSynth.play(note, velocity, time, dur); - * } - *
- **/ + return _this; + } + /** + * Process a sound source, optionally specify amount and oversample values. + * + * @method process + * @for p5.Distortion + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + */ -p5.MonoSynth = function () { - audioVoice_0.call(this); - this.oscillator = new p5.Oscillator(); - this.env = new p5.Envelope(); - this.env.setRange(1, 0); - this.env.setExp(true); - this.setADSR(0.02, 0.25, 0.05, 0.35); + distortion_createClass(Distortion, [{ + key: "process", + value: function process(src, amount, oversample) { + src.connect(this.input); + this.set(amount, oversample); + } + /** + * Set the amount and oversample of the waveshaper distortion. + * + * @method set + * @for p5.Distortion + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + */ + + }, { + key: "set", + value: function set(amount, oversample) { + if (amount) { + var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000); + this.amount = curveAmount; + this.waveShaperNode.curve = makeDistortionCurve(curveAmount); + } - this.oscillator.disconnect(); - this.oscillator.connect(this.output); - this.env.disconnect(); - this.env.setInput(this.output.gain); + if (oversample) { + this.waveShaperNode.oversample = oversample; + } + } + /** + * Return the distortion amount, typically between 0-1. + * + * @method getAmount + * @for p5.Distortion + * @return {Number} Unbounded distortion amount. + * Normal values range from 0-1. + */ + + }, { + key: "getAmount", + value: function getAmount() { + return this.amount; + } + /** + * Return the oversampling. + * + * @method getOversample + * @for p5.Distortion + * @return {String} Oversample can either be 'none', '2x', or '4x'. + */ + + }, { + key: "getOversample", + value: function getOversample() { + return this.waveShaperNode.oversample; + } + }, { + key: "dispose", + value: function dispose() { + distortion_get(distortion_getPrototypeOf(Distortion.prototype), "dispose", this).call(this); + + if (this.waveShaperNode) { + this.waveShaperNode.disconnect(); + this.waveShaperNode = null; + } + } + }]); - this.oscillator.output.gain.value = 1.0; - this.oscillator.start(); - this.connect(); - master.soundArray.push(this); -}; + return Distortion; +}(effect); -p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype); -/** - * Play tells the MonoSynth to start playing a note. This method schedules - * the calling of .triggerAttack and .triggerRelease. - * - * @method play - * @for p5.MonoSynth - * @param {String | Number} note the note you want to play, specified as a - * frequency in Hertz (Number) or as a midi - * value in Note/Octave format ("C4", "Eb3"...etc") - * See - * Tone. Defaults to 440 hz. - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope. Defaults to 0.15 seconds. - * @example - *
- * let monoSynth; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * background(220); - * textAlign(CENTER); - * text('tap to play', width/2, height/2); - * - * monoSynth = new p5.MonoSynth(); - * } - * - * function playSynth() { - * userStartAudio(); - * - * let note = random(['Fb4', 'G4']); - * // note velocity (volume, from 0 to 1) - * let velocity = random(); - * // time from now (in seconds) - * let time = 0; - * // note duration (in seconds) - * let dur = 1/6; - * - * monoSynth.play(note, velocity, time, dur); - * } - *
- * - */ + var distortion = (Distortion); +function gain_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) { - this.triggerAttack(note, velocity, ~~secondsFromNow); - this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN)); -}; -/** - * Trigger the Attack, and Decay portion of the Envelope. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. - * - * @param {String | Number} note the note you want to play, specified as a - * frequency in Hertz (Number) or as a midi - * value in Note/Octave format ("C4", "Eb3"...etc") - * See - * Tone. Defaults to 440 hz - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @method triggerAttack - * @for p5.MonoSynth - * @example - *
- * let monoSynth; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(triggerAttack); - * background(220); - * text('tap here for attack, let go to release', 5, 20, width - 20); - * monoSynth = new p5.MonoSynth(); - * } - * - * function triggerAttack() { - * userStartAudio(); - * - * monoSynth.triggerAttack("E3"); - * } - * - * function mouseReleased() { - * monoSynth.triggerRelease(); - * } - *
- */ +function gain_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); } } + +function gain_createClass(Constructor, protoProps, staticProps) { if (protoProps) gain_defineProperties(Constructor.prototype, protoProps); if (staticProps) gain_defineProperties(Constructor, staticProps); return Constructor; } -p5.MonoSynth.prototype.triggerAttack = function (note, velocity) { - var secondsFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var freq = noteToFreq(note); - var vel = velocity || 0.1; - this.oscillator.freq(freq, 0, secondsFromNow); - this.env.ramp(this.output.gain, secondsFromNow, vel); -}; /** - * Trigger the release of the Envelope. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. + * A gain node is usefull to set the relative volume of sound. + * It's typically used to build mixers. * - * @param {Number} secondsFromNow time to trigger the release - * @method triggerRelease - * @for p5.MonoSynth + * @class p5.Gain + * @constructor * @example *
- * let monoSynth; * + * // load two soundfile and crossfade beetween them + * let sound1,sound2; + * let sound1Gain, sound2Gain, masterGain; + * function preload(){ + * soundFormats('ogg', 'mp3'); + * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01'); + * sound2 = loadSound('assets/beat'); + * } * function setup() { * let cnv = createCanvas(100, 100); - * cnv.mousePressed(triggerAttack); - * background(220); - * text('tap here for attack, let go to release', 5, 20, width - 20); - * monoSynth = new p5.MonoSynth(); + * cnv.mousePressed(startSound); + * // create a 'master' gain to which we will connect both soundfiles + * masterGain = new p5.Gain(); + * masterGain.connect(); + * sound1.disconnect(); // diconnect from p5 output + * sound1Gain = new p5.Gain(); // setup a gain node + * sound1Gain.setInput(sound1); // connect the first sound to its input + * sound1Gain.connect(masterGain); // connect its output to the 'master' + * sound2.disconnect(); + * sound2Gain = new p5.Gain(); + * sound2Gain.setInput(sound2); + * sound2Gain.connect(masterGain); * } - * - * function triggerAttack() { - * userStartAudio(); - * - * monoSynth.triggerAttack("E3"); + * function startSound() { + * sound1.loop(); + * sound2.loop(); + * loop(); * } - * * function mouseReleased() { - * monoSynth.triggerRelease(); + * sound1.stop(); + * sound2.stop(); * } - *
- */ - - -p5.MonoSynth.prototype.triggerRelease = function () { - var secondsFromNow = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; - this.env.ramp(this.output.gain, secondsFromNow, 0); -}; -/** - * Set values like a traditional - * - * ADSR envelope - * . - * - * @method setADSR - * @for p5.MonoSynth - * @param {Number} attackTime Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + * function draw(){ + * background(220); + * textAlign(CENTER); + * textSize(11); + * fill(0); + * if (!sound1.isPlaying()) { + * text('tap and drag to play', width/2, height/2); + * return; + * } + * // map the horizontal position of the mouse to values useable for volume * control of sound1 + * var sound1Volume = constrain(map(mouseX,width,0,0,1), 0, 1); + * var sound2Volume = 1-sound1Volume; + * sound1Gain.amp(sound1Volume); + * sound2Gain.amp(sound2Volume); + * // map the vertical position of the mouse to values useable for 'master * volume control' + * var masterVolume = constrain(map(mouseY,height,0,0,1), 0, 1); + * masterGain.amp(masterVolume); + * text('master', width/2, height - masterVolume * height * 0.9) + * fill(255, 0, 255); + * textAlign(LEFT); + * text('sound1', 5, height - sound1Volume * height * 0.9); + * textAlign(RIGHT); + * text('sound2', width - 5, height - sound2Volume * height * 0.9); + * } + * */ +var gain_Gain = +function () { + function Gain() { + gain_classCallCheck(this, Gain); -p5.MonoSynth.prototype.setADSR = function (attack, decay, sustain, release) { - this.env.setADSR(attack, decay, sustain, release); -}; -/** - * Getters and Setters - * @property {Number} attack - * @for p5.MonoSynth - */ + this.ac = master.audiocontext; + this.input = this.ac.createGain(); + this.output = this.ac.createGain(); -/** - * @property {Number} decay - * @for p5.MonoSynth - */ + this.input.gain.value = 0.5; + this.input.connect(this.output); -/** - * @property {Number} sustain - * @for p5.MonoSynth - */ + master.soundArray.push(this); + } + /** + * Connect a source to the gain node. + * + * @method setInput + * @for p5.Gain + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + */ -/** - * @property {Number} release - * @for p5.MonoSynth - */ + gain_createClass(Gain, [{ + key: "setInput", + value: function setInput(src) { + src.connect(this.input); + } + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @for p5.Gain + * @param {Object} unit + */ + + }, { + key: "connect", + value: function connect(unit) { + var u = unit || p5.soundOut.input; + this.output.connect(u.input ? u.input : u); + } + /** + * Disconnect all output. + * + * @method disconnect + * @for p5.Gain + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + } + /** + * Set the output level of the gain node. + * + * @method amp + * @for p5.Gain + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + + }, { + key: "amp", + value: function amp(vol) { + var rampTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var tFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var now = master.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now); + this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); + } + }, { + key: "dispose", + value: function dispose() { + var index = master.soundArray.indexOf(this); + master.soundArray.splice(index, 1); + + if (this.output) { + this.output.disconnect(); + delete this.output; + } -Object.defineProperties(p5.MonoSynth.prototype, { - attack: { - get: function get() { - return this.env.aTime; - }, - set: function set(attack) { - this.env.setADSR(attack, this.env.dTime, this.env.sPercent, this.env.rTime); - } - }, - decay: { - get: function get() { - return this.env.dTime; - }, - set: function set(decay) { - this.env.setADSR(this.env.aTime, decay, this.env.sPercent, this.env.rTime); - } - }, - sustain: { - get: function get() { - return this.env.sPercent; - }, - set: function set(sustain) { - this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime); - } - }, - release: { - get: function get() { - return this.env.rTime; - }, - set: function set(release) { - this.env.setADSR(this.env.aTime, this.env.dTime, this.env.sPercent, release); + if (this.input) { + this.input.disconnect(); + delete this.input; + } } - } -}); -/** - * MonoSynth amp - * @method amp - * @for p5.MonoSynth - * @param {Number} vol desired volume - * @param {Number} [rampTime] Time to reach new volume - * @return {Number} new volume value - */ + }]); -p5.MonoSynth.prototype.amp = function (vol, rampTime) { - var t = rampTime || 0; + return Gain; +}(); - if (typeof vol !== 'undefined') { - this.oscillator.amp(vol, t); - } + var gain = (gain_Gain); +function audioVoice_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - return this.oscillator.amp().value; -}; -/** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @for p5.MonoSynth - * @param {Object} unit A p5.sound or Web Audio object - */ +function audioVoice_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); } } + +function audioVoice_createClass(Constructor, protoProps, staticProps) { if (protoProps) audioVoice_defineProperties(Constructor.prototype, protoProps); if (staticProps) audioVoice_defineProperties(Constructor, staticProps); return Constructor; } -p5.MonoSynth.prototype.connect = function (unit) { - var u = unit || master.input; - this.output.connect(u.input ? u.input : u); -}; /** - * Disconnect all outputs + * Base class for monophonic synthesizers. Any extensions of this class + * should follow the API and implement the methods below in order to + * remain compatible with p5.PolySynth(); * - * @method disconnect - * @for p5.MonoSynth + * @class p5.AudioVoice + * @constructor */ +var audioVoice_AudioVoice = +function () { + function AudioVoice() { + audioVoice_classCallCheck(this, AudioVoice); + + this.ac = master.audiocontext; + this.output = this.ac.createGain(); + this.connect(); + master.soundArray.push(this); + } + + audioVoice_createClass(AudioVoice, [{ + key: "play", + value: function play(note, velocity, secondsFromNow, sustime) {} + }, { + key: "triggerAttack", + value: function triggerAttack(note, velocity, secondsFromNow) {} + }, { + key: "triggerRelease", + value: function triggerRelease(secondsFromNow) {} + }, { + key: "amp", + value: function amp(vol, rampTime) {} + /** + * Connect to p5 objects or Web Audio Nodes + * @method connect + * @for p5.AudioVoice + * @param {Object} unit + */ + + }, { + key: "connect", + value: function connect(unit) { + var u = unit || master.input; + this.output.connect(u.input ? u.input : u); + } + /** + * Disconnect from soundOut + * @method disconnect + * @for p5.AudioVoice + */ + + }, { + key: "disconnect", + value: function disconnect() { + this.output.disconnect(); + } + }, { + key: "dispose", + value: function dispose() { + if (this.output) { + this.output.disconnect(); + delete this.output; + } + } + }]); -p5.MonoSynth.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } -}; -/** - * Get rid of the MonoSynth and free up its resources / memory. - * - * @method dispose - * @for p5.MonoSynth - */ + return AudioVoice; +}(); + var audioVoice_0 = (audioVoice_AudioVoice); +function monosynth_typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { monosynth_typeof = function _typeof(obj) { return typeof obj; }; } else { monosynth_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return monosynth_typeof(obj); } -p5.MonoSynth.prototype.dispose = function () { - audioVoice_0.prototype.dispose.apply(this); +function monosynth_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - if (this.env) { - this.env.dispose(); - } +function monosynth_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); } } - if (this.oscillator) { - this.oscillator.dispose(); - } -}; +function monosynth_createClass(Constructor, protoProps, staticProps) { if (protoProps) monosynth_defineProperties(Constructor.prototype, protoProps); if (staticProps) monosynth_defineProperties(Constructor, staticProps); return Constructor; } +function monosynth_possibleConstructorReturn(self, call) { if (call && (monosynth_typeof(call) === "object" || typeof call === "function")) { return call; } return monosynth_assertThisInitialized(self); } +function monosynth_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } -/** - * An AudioVoice is used as a single voice for sound synthesis. - * The PolySynth class holds an array of AudioVoice, and deals - * with voices allocations, with setting notes to be played, and - * parameters to be set. - * - * @class p5.PolySynth - * @constructor - * - * @param {Number} [synthVoice] A monophonic synth voice inheriting - * the AudioVoice class. Defaults to p5.MonoSynth - * @param {Number} [maxVoices] Number of voices, defaults to 8; - * @example - *
- * let polySynth; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * background(220); - * text('click to play', 20, 20); - * - * polySynth = new p5.PolySynth(); - * } - * - * function playSynth() { - * userStartAudio(); - * - * // note duration (in seconds) - * let dur = 1.5; - * - * // time from now (in seconds) - * let time = 0; - * - * // velocity (volume, from 0 to 1) - * let vel = 0.1; - * - * // notes can overlap with each other - * polySynth.play('G2', vel, 0, dur); - * polySynth.play('C3', vel, time += 1/3, dur); - * polySynth.play('G3', vel, time += 1/3, dur); - * } - *
- **/ +function monosynth_get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { monosynth_get = Reflect.get; } else { monosynth_get = function _get(target, property, receiver) { var base = monosynth_superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return monosynth_get(target, property, receiver || target); } -p5.PolySynth = function (audioVoice, maxVoices) { - this.audiovoices = []; - /** - * An object that holds information about which notes have been played and - * which notes are currently being played. New notes are added as keys - * on the fly. While a note has been attacked, but not released, the value of the - * key is the audiovoice which is generating that note. When notes are released, - * the value of the key becomes undefined. - * @property notes - */ +function monosynth_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = monosynth_getPrototypeOf(object); if (object === null) break; } return object; } - this.notes = {}; +function monosynth_getPrototypeOf(o) { monosynth_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return monosynth_getPrototypeOf(o); } - this._newest = 0; - this._oldest = 0; - /** - * A PolySynth must have at least 1 voice, defaults to 8 - * @property polyvalue - */ +function monosynth_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) monosynth_setPrototypeOf(subClass, superClass); } - this.maxVoices = maxVoices || 8; - /** - * Monosynth that generates the sound for each note that is triggered. The - * p5.PolySynth defaults to using the p5.MonoSynth as its voice. - * @property AudioVoice - */ +function monosynth_setPrototypeOf(o, p) { monosynth_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return monosynth_setPrototypeOf(o, p); } - this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice; - /** - * This value must only change as a note is attacked or released. Due to delay - * and sustain times, Tone.TimelineSignal is required to schedule the change in value. - * @private - * @property {Tone.TimelineSignal} _voicesInUse - */ - this._voicesInUse = new TimelineSignal_default.a(0); - this.output = master.audiocontext.createGain(); - this.connect(); - this._allocateVoices(); - master.soundArray.push(this); -}; -/** - * Construct the appropriate number of audiovoices - * @private - * @for p5.PolySynth - * @method _allocateVoices - */ -p5.PolySynth.prototype._allocateVoices = function () { - for (var i = 0; i < this.maxVoices; i++) { - this.audiovoices.push(new this.AudioVoice()); - this.audiovoices[i].disconnect(); - this.audiovoices[i].connect(this.output); - } -}; +var DEFAULT_SUSTAIN = 0.15; /** - * Play a note by triggering noteAttack and noteRelease with sustain time + * A MonoSynth is used as a single voice for sound synthesis. + * This is a class to be used in conjunction with the PolySynth + * class. Custom synthetisers should be built inheriting from + * this class. * - * @method play - * @for p5.PolySynth - * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C) - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @class p5.MonoSynth + * @constructor * @example *
- * let polySynth; + * let monoSynth; * * function setup() { * let cnv = createCanvas(100, 100); * cnv.mousePressed(playSynth); * background(220); - * text('click to play', 20, 20); + * textAlign(CENTER); + * text('tap to play', width/2, height/2); * - * polySynth = new p5.PolySynth(); + * monoSynth = new p5.MonoSynth(); * } * * function playSynth() { * userStartAudio(); * - * // note duration (in seconds) - * let dur = 1.5; - * + * let note = random(['Fb4', 'G4']); + * // note velocity (volume, from 0 to 1) + * let velocity = random(); * // time from now (in seconds) * let time = 0; + * // note duration (in seconds) + * let dur = 1/6; * - * // velocity (volume, from 0 to 1) - * let vel = 0.1; - * - * // notes can overlap with each other - * polySynth.play('G2', vel, 0, dur); - * polySynth.play('C3', vel, time += 1/3, dur); - * polySynth.play('G3', vel, time += 1/3, dur); - * } - *
- */ - - -p5.PolySynth.prototype.play = function (note, velocity, secondsFromNow) { - var susTime = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; - this.noteAttack(note, velocity, secondsFromNow); - this.noteRelease(note, secondsFromNow + susTime); -}; -/** - * noteADSR sets the envelope for a specific note that has just been triggered. - * Using this method modifies the envelope of whichever audiovoice is being used - * to play the desired note. The envelope should be reset before noteRelease is called - * in order to prevent the modified envelope from being used on other notes. - * - * @method noteADSR - * @for p5.PolySynth - * @param {Number} [note] Midi note on which ADSR should be set. - * @param {Number} [attackTime] Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - **/ - - -p5.PolySynth.prototype.noteADSR = function (note, a, d, s, r) { - var timeFromNow = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; - var now = master.audiocontext.currentTime; - var t = now + timeFromNow; - this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r); -}; -/** - * Set the PolySynths global envelope. This method modifies the envelopes of each - * monosynth so that all notes are played with this envelope. - * - * @method setADSR - * @for p5.PolySynth - * @param {Number} [attackTime] Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - **/ - - -p5.PolySynth.prototype.setADSR = function (a, d, s, r) { - this.audiovoices.forEach(function (voice) { - voice.setADSR(a, d, s, r); - }); -}; -/** - * Trigger the Attack, and Decay portion of a MonoSynth. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. - * - * @method noteAttack - * @for p5.PolySynth - * @param {Number} [note] midi note on which attack should be triggered. - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/ - * @param {Number} [secondsFromNow] time from now (in seconds) - * @example - *
- * let polySynth = new p5.PolySynth(); - * let pitches = ['G', 'D', 'G', 'C']; - * let octaves = [2, 3, 4]; - * - * function setup() { - * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playChord); - * background(220); - * text('tap to play', 20, 20); - * } - * - * function playChord() { - * userStartAudio(); - * - * // play a chord: multiple notes at the same time - * for (let i = 0; i < 4; i++) { - * let note = random(pitches) + random(octaves); - * polySynth.noteAttack(note, 0.1); - * } - * } - * - * function mouseReleased() { - * // release all voices - * polySynth.noteRelease(); + * monoSynth.play(note, velocity, time, dur); * } *
- */ + **/ +var monosynth_MonoSynth = +function (_AudioVoice) { + monosynth_inherits(MonoSynth, _AudioVoice); -p5.PolySynth.prototype.noteAttack = function (_note, _velocity) { - var secondsFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var acTime = master.audiocontext.currentTime + secondsFromNow; + function MonoSynth() { + var _this; - var note = noteToFreq(_note); - var velocity = _velocity || 0.1; - var currentVoice; + monosynth_classCallCheck(this, MonoSynth); - if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) { - this.noteRelease(note, 0); - } + _this = monosynth_possibleConstructorReturn(this, monosynth_getPrototypeOf(MonoSynth).call(this)); + _this.oscillator = new oscillator(); + _this.env = new envelope(); + _this.env.setRange(1, 0); - if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) { - currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0); - } - else { - currentVoice = this._oldest; - var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value); - this.noteRelease(oldestNote); - this._oldest = (this._oldest + 1) % (this.maxVoices - 1); - } + _this.env.setExp(true); - this.notes[note] = new TimelineSignal_default.a(); - this.notes[note].setValueAtTime(currentVoice, acTime); + _this.setADSR(0.02, 0.25, 0.05, 0.35); - var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value; - this._voicesInUse.setValueAtTime(previousVal + 1, acTime); + _this.oscillator.disconnect(); + _this.oscillator.connect(_this.output); - this._updateAfter(acTime, 1); + _this.env.disconnect(); - this._newest = currentVoice; + _this.env.setInput(_this.output.gain); - if (typeof velocity === 'number') { - var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2; - velocity = velocity > maxRange ? maxRange : velocity; - } + _this.oscillator.output.gain.value = 1.0; + + _this.oscillator.start(); + + _this.connect(); + + master.soundArray.push(monosynth_assertThisInitialized(_this)); + /** + * Getters and Setters + * @property {Number} attack + * @for p5.MonoSynth + */ + + /** + * @property {Number} decay + * @for p5.MonoSynth + */ + + /** + * @property {Number} sustain + * @for p5.MonoSynth + */ + + /** + * @property {Number} release + * @for p5.MonoSynth + */ + + Object.defineProperties(monosynth_assertThisInitialized(_this), { + attack: { + get: function get() { + return this.env.aTime; + }, + set: function set(attack) { + this.env.setADSR(attack, this.env.dTime, this.env.sPercent, this.env.rTime); + } + }, + decay: { + get: function get() { + return this.env.dTime; + }, + set: function set(decay) { + this.env.setADSR(this.env.aTime, decay, this.env.sPercent, this.env.rTime); + } + }, + sustain: { + get: function get() { + return this.env.sPercent; + }, + set: function set(sustain) { + this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime); + } + }, + release: { + get: function get() { + return this.env.rTime; + }, + set: function set(release) { + this.env.setADSR(this.env.aTime, this.env.dTime, this.env.sPercent, release); + } + } + }); + return _this; + } + /** + * Play tells the MonoSynth to start playing a note. This method schedules + * the calling of .triggerAttack and .triggerRelease. + * + * @method play + * @for p5.MonoSynth + * @param {String | Number} note the note you want to play, specified as a + * frequency in Hertz (Number) or as a midi + * value in Note/Octave format ("C4", "Eb3"...etc") + * See + * Tone. Defaults to 440 hz. + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope. Defaults to 0.15 seconds. + * @example + *
+ * let monoSynth; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * background(220); + * textAlign(CENTER); + * text('tap to play', width/2, height/2); + * + * monoSynth = new p5.MonoSynth(); + * } + * + * function playSynth() { + * userStartAudio(); + * + * let note = random(['Fb4', 'G4']); + * // note velocity (volume, from 0 to 1) + * let velocity = random(); + * // time from now (in seconds) + * let time = 0; + * // note duration (in seconds) + * let dur = 1/6; + * + * monoSynth.play(note, velocity, time, dur); + * } + *
+ * + */ + + + monosynth_createClass(MonoSynth, [{ + key: "play", + value: function play(note, velocity, secondsFromNow, susTime) { + this.triggerAttack(note, velocity, ~~secondsFromNow); + this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN)); + } + /** + * Trigger the Attack, and Decay portion of the Envelope. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. + * + * @param {String | Number} note the note you want to play, specified as a + * frequency in Hertz (Number) or as a midi + * value in Note/Octave format ("C4", "Eb3"...etc") + * See + * Tone. Defaults to 440 hz + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @method triggerAttack + * @for p5.MonoSynth + * @example + *
+ * let monoSynth; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(triggerAttack); + * background(220); + * text('tap here for attack, let go to release', 5, 20, width - 20); + * monoSynth = new p5.MonoSynth(); + * } + * + * function triggerAttack() { + * userStartAudio(); + * + * monoSynth.triggerAttack("E3"); + * } + * + * function mouseReleased() { + * monoSynth.triggerRelease(); + * } + *
+ */ + + }, { + key: "triggerAttack", + value: function triggerAttack(note, velocity) { + var secondsFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var freq = noteToFreq(note); + var vel = velocity || 0.1; + this.oscillator.freq(freq, 0, secondsFromNow); + this.env.ramp(this.output.gain, secondsFromNow, vel); + } + /** + * Trigger the release of the Envelope. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @param {Number} secondsFromNow time to trigger the release + * @method triggerRelease + * @for p5.MonoSynth + * @example + *
+ * let monoSynth; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(triggerAttack); + * background(220); + * text('tap here for attack, let go to release', 5, 20, width - 20); + * monoSynth = new p5.MonoSynth(); + * } + * + * function triggerAttack() { + * userStartAudio(); + * + * monoSynth.triggerAttack("E3"); + * } + * + * function mouseReleased() { + * monoSynth.triggerRelease(); + * } + *
+ */ + + }, { + key: "triggerRelease", + value: function triggerRelease() { + var secondsFromNow = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + this.env.ramp(this.output.gain, secondsFromNow, 0); + } + /** + * Set values like a traditional + * + * ADSR envelope + * . + * + * @method setADSR + * @for p5.MonoSynth + * @param {Number} attackTime Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + */ + + }, { + key: "setADSR", + value: function setADSR(attack, decay, sustain, release) { + this.env.setADSR(attack, decay, sustain, release); + } + /** + * MonoSynth amp + * @method amp + * @for p5.MonoSynth + * @param {Number} vol desired volume + * @param {Number} [rampTime] Time to reach new volume + * @return {Number} new volume value + */ + + }, { + key: "amp", + value: function amp(vol, rampTime) { + var t = rampTime || 0; + + if (typeof vol !== 'undefined') { + this.oscillator.amp(vol, t); + } + + return this.oscillator.amp().value; + } + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @for p5.MonoSynth + * @param {Object} unit A p5.sound or Web Audio object + */ + + }, { + key: "connect", + value: function connect(unit) { + var u = unit || master.input; + this.output.connect(u.input ? u.input : u); + } + /** + * Disconnect all outputs + * + * @method disconnect + * @for p5.MonoSynth + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + } + /** + * Get rid of the MonoSynth and free up its resources / memory. + * + * @method dispose + * @for p5.MonoSynth + */ + + }, { + key: "dispose", + value: function dispose() { + monosynth_get(monosynth_getPrototypeOf(MonoSynth.prototype), "dispose", this).call(this); + + if (this.env) { + this.env.dispose(); + } + + if (this.oscillator) { + this.oscillator.dispose(); + } + } + }]); + + return MonoSynth; +}(audioVoice_0); + + var monosynth = (monosynth_MonoSynth); +function onsetDetect_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function onsetDetect_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); } } + +function onsetDetect_createClass(Constructor, protoProps, staticProps) { if (protoProps) onsetDetect_defineProperties(Constructor.prototype, protoProps); if (staticProps) onsetDetect_defineProperties(Constructor, staticProps); return Constructor; } - this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow); -}; /** - * Private method to ensure accurate values of this._voicesInUse - * Any time a new value is scheduled, it is necessary to increment all subsequent - * scheduledValues after attack, and decrement all subsequent - * scheduledValues after release - * - * @private - * @for p5.PolySynth - * @param {[type]} time [description] - * @param {[type]} value [description] - * @return {[type]} [description] + * Listen for onsets (a sharp increase in volume) within a given + * frequency range. + * + * @class p5.OnsetDetect + * @constructor + * @param {Number} freqLow Low frequency + * @param {Number} freqHigh High frequency + * @param {Number} threshold Amplitude threshold between 0 (no energy) and 1 (maximum) + * @param {Function} callback Function to call when an onset is detected */ +var OnsetDetect = +function () { + function OnsetDetect(freqLow, freqHigh, threshold, callback) { + onsetDetect_classCallCheck(this, OnsetDetect); + + this.isDetected = false; + this.freqLow = freqLow; + this.freqHigh = freqHigh; + this.treshold = threshold; + this.energy = 0; + this.penergy = 0; + + this.sensitivity = 500; + this.callback = callback; + } + + + onsetDetect_createClass(OnsetDetect, [{ + key: "update", + value: function update(fftObject, callback) { + this.energy = fftObject.getEnergy(this.freqLow, this.freqHigh) / 255; + + if (this.isDetected === false) { + if (this.energy - this.penergy > this.treshold) { + this.isDetected = true; + + if (this.callback) { + this.callback(this.energy); + } else if (callback) { + callback(this.energy); + } + + var self = this; + setTimeout(function () { + self.isDetected = false; + }, this.sensitivity); + } + } + + this.penergy = this.energy; + } + }]); + + return OnsetDetect; +}(); + + var onsetDetect = (OnsetDetect); +function polysynth_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function polysynth_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); } } + +function polysynth_createClass(Constructor, protoProps, staticProps) { if (protoProps) polysynth_defineProperties(Constructor.prototype, protoProps); if (staticProps) polysynth_defineProperties(Constructor, staticProps); return Constructor; } -p5.PolySynth.prototype._updateAfter = function (time, value) { - if (this._voicesInUse._searchAfter(time) === null) { - return; - } else { - this._voicesInUse._searchAfter(time).value += value; - var nextTime = this._voicesInUse._searchAfter(time).time; - this._updateAfter(nextTime, value); - } -}; /** - * Trigger the Release of an AudioVoice note. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. + * An AudioVoice is used as a single voice for sound synthesis. + * The PolySynth class holds an array of AudioVoice, and deals + * with voices allocations, with setting notes to be played, and + * parameters to be set. + * + * @class p5.PolySynth + * @constructor * - * @method noteRelease - * @for p5.PolySynth - * @param {Number} [note] midi note on which attack should be triggered. - * If no value is provided, all notes will be released. - * @param {Number} [secondsFromNow] time to trigger the release + * @param {Number} [synthVoice] A monophonic synth voice inheriting + * the AudioVoice class. Defaults to p5.MonoSynth + * @param {Number} [maxVoices] Number of voices, defaults to 8; * @example *
- * let polySynth = new p5.PolySynth(); - * let pitches = ['G', 'D', 'G', 'C']; - * let octaves = [2, 3, 4]; + * let polySynth; * * function setup() { * let cnv = createCanvas(100, 100); - * cnv.mousePressed(playChord); + * cnv.mousePressed(playSynth); * background(220); - * text('tap to play', 20, 20); + * text('click to play', 20, 20); + * + * polySynth = new p5.PolySynth(); * } * - * function playChord() { + * function playSynth() { * userStartAudio(); * - * // play a chord: multiple notes at the same time - * for (let i = 0; i < 4; i++) { - * let note = random(pitches) + random(octaves); - * polySynth.noteAttack(note, 0.1); - * } - * } + * // note duration (in seconds) + * let dur = 1.5; * - * function mouseReleased() { - * // release all voices - * polySynth.noteRelease(); + * // time from now (in seconds) + * let time = 0; + * + * // velocity (volume, from 0 to 1) + * let vel = 0.1; + * + * // notes can overlap with each other + * polySynth.play('G2', vel, 0, dur); + * polySynth.play('C3', vel, time += 1/3, dur); + * polySynth.play('G3', vel, time += 1/3, dur); * } *
- * - */ - - -p5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) { - var now = master.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; + **/ - if (!_note) { - this.audiovoices.forEach(function (voice) { - voice.triggerRelease(tFromNow); - }); +var polysynth_PolySynth = +function () { + function PolySynth(audioVoice, maxVoices) { + polysynth_classCallCheck(this, PolySynth); + + this.audiovoices = []; + /** + * An object that holds information about which notes have been played and + * which notes are currently being played. New notes are added as keys + * on the fly. While a note has been attacked, but not released, the value of the + * key is the audiovoice which is generating that note. When notes are released, + * the value of the key becomes undefined. + * @property notes + */ + + this.notes = {}; + + this._newest = 0; + this._oldest = 0; + /** + * A PolySynth must have at least 1 voice, defaults to 8 + * @property polyvalue + */ + + this.maxVoices = maxVoices || 8; + /** + * Monosynth that generates the sound for each note that is triggered. The + * p5.PolySynth defaults to using the p5.MonoSynth as its voice. + * @property AudioVoice + */ + + this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice; + /** + * This value must only change as a note is attacked or released. Due to delay + * and sustain times, Tone.TimelineSignal is required to schedule the change in value. + * @private + * @property {Tone.TimelineSignal} _voicesInUse + */ + + this._voicesInUse = new TimelineSignal_default.a(0); + this.output = master.audiocontext.createGain(); + this.connect(); + + this._allocateVoices(); + + master.soundArray.push(this); + } + /** + * Construct the appropriate number of audiovoices + * @private + * @for p5.PolySynth + * @method _allocateVoices + */ - this._voicesInUse.setValueAtTime(0, t); - for (var n in this.notes) { - this.notes[n].dispose(); - delete this.notes[n]; + polysynth_createClass(PolySynth, [{ + key: "_allocateVoices", + value: function _allocateVoices() { + for (var i = 0; i < this.maxVoices; i++) { + this.audiovoices.push(new this.AudioVoice()); + this.audiovoices[i].disconnect(); + this.audiovoices[i].connect(this.output); + } } + /** + * Play a note by triggering noteAttack and noteRelease with sustain time + * + * @method play + * @for p5.PolySynth + * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C) + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * let polySynth; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * background(220); + * text('click to play', 20, 20); + * + * polySynth = new p5.PolySynth(); + * } + * + * function playSynth() { + * userStartAudio(); + * + * // note duration (in seconds) + * let dur = 1.5; + * + * // time from now (in seconds) + * let time = 0; + * + * // velocity (volume, from 0 to 1) + * let vel = 0.1; + * + * // notes can overlap with each other + * polySynth.play('G2', vel, 0, dur); + * polySynth.play('C3', vel, time += 1/3, dur); + * polySynth.play('G3', vel, time += 1/3, dur); + * } + *
+ */ + + }, { + key: "play", + value: function play(note, velocity, secondsFromNow) { + var susTime = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; + this.noteAttack(note, velocity, secondsFromNow); + this.noteRelease(note, secondsFromNow + susTime); + } + /** + * noteADSR sets the envelope for a specific note that has just been triggered. + * Using this method modifies the envelope of whichever audiovoice is being used + * to play the desired note. The envelope should be reset before noteRelease is called + * in order to prevent the modified envelope from being used on other notes. + * + * @method noteADSR + * @for p5.PolySynth + * @param {Number} [note] Midi note on which ADSR should be set. + * @param {Number} [attackTime] Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + **/ + + }, { + key: "noteADSR", + value: function noteADSR(note, a, d, s, r) { + var timeFromNow = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; + var now = master.audiocontext.currentTime; + var t = now + timeFromNow; + this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r); + } + /** + * Set the PolySynths global envelope. This method modifies the envelopes of each + * monosynth so that all notes are played with this envelope. + * + * @method setADSR + * @for p5.PolySynth + * @param {Number} [attackTime] Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + **/ + + }, { + key: "setADSR", + value: function setADSR(a, d, s, r) { + this.audiovoices.forEach(function (voice) { + voice.setADSR(a, d, s, r); + }); + } + /** + * Trigger the Attack, and Decay portion of a MonoSynth. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. + * + * @method noteAttack + * @for p5.PolySynth + * @param {Number} [note] midi note on which attack should be triggered. + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/ + * @param {Number} [secondsFromNow] time from now (in seconds) + * @example + *
+ * let polySynth = new p5.PolySynth(); + * let pitches = ['G', 'D', 'G', 'C']; + * let octaves = [2, 3, 4]; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playChord); + * background(220); + * text('tap to play', 20, 20); + * } + * + * function playChord() { + * userStartAudio(); + * + * // play a chord: multiple notes at the same time + * for (let i = 0; i < 4; i++) { + * let note = random(pitches) + random(octaves); + * polySynth.noteAttack(note, 0.1); + * } + * } + * + * function mouseReleased() { + * // release all voices + * polySynth.noteRelease(); + * } + *
+ */ + + }, { + key: "noteAttack", + value: function noteAttack(_note, _velocity) { + var secondsFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var acTime = master.audiocontext.currentTime + secondsFromNow; + + var note = noteToFreq(_note); + var velocity = _velocity || 0.1; + var currentVoice; + + if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) { + this.noteRelease(note, 0); + } - return; - } - - - var note = noteToFreq(_note); - - if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) { - console.warn('Cannot release a note that is not already playing'); - } else { - var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1); - - this._voicesInUse.setValueAtTime(previousVal - 1, t); + if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) { + currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0); + } + else { + currentVoice = this._oldest; + oldestNote = freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value); + this.noteRelease(oldestNote); + this._oldest = (this._oldest + 1) % (this.maxVoices - 1); + } - if (previousVal > 0) { - this._updateAfter(t, -1); - } - this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(tFromNow); - this.notes[note].dispose(); - delete this.notes[note]; - this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1); - } -}; -/** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @for p5.PolySynth - * @param {Object} unit A p5.sound or Web Audio object - */ + this.notes[note] = new TimelineSignal_default.a(); + this.notes[note].setValueAtTime(currentVoice, acTime); + var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value; -p5.PolySynth.prototype.connect = function (unit) { - var u = unit || master.input; - this.output.connect(u.input ? u.input : u); -}; -/** - * Disconnect all outputs - * - * @method disconnect - * @for p5.PolySynth - */ + this._voicesInUse.setValueAtTime(previousVal + 1, acTime); -p5.PolySynth.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } -}; -/** - * Get rid of the MonoSynth and free up its resources / memory. - * - * @method dispose - * @for p5.PolySynth - */ + this._updateAfter(acTime, 1); + this._newest = currentVoice; -p5.PolySynth.prototype.dispose = function () { - this.audiovoices.forEach(function (voice) { - voice.dispose(); - }); + if (typeof velocity === 'number') { + var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2; + velocity = velocity > maxRange ? maxRange : velocity; + } - if (this.output) { - this.output.disconnect(); - delete this.output; - } -}; + this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow); + } + /** + * Private method to ensure accurate values of this._voicesInUse + * Any time a new value is scheduled, it is necessary to increment all subsequent + * scheduledValues after attack, and decrement all subsequent + * scheduledValues after release + * + * @private + * @for p5.PolySynth + * @param {[type]} time [description] + * @param {[type]} value [description] + * @return {[type]} [description] + */ + + }, { + key: "_updateAfter", + value: function _updateAfter(time, value) { + if (this._voicesInUse._searchAfter(time) === null) { + return; + } else { + this._voicesInUse._searchAfter(time).value += value; -function makeDistortionCurve(amount) { - var k = typeof amount === 'number' ? amount : 50; - var numSamples = 44100; - var curve = new Float32Array(numSamples); - var deg = Math.PI / 180; - var i = 0; - var x; + var nextTime = this._voicesInUse._searchAfter(time).time; - for (; i < numSamples; ++i) { - x = i * 2 / numSamples - 1; - curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x)); - } + this._updateAfter(nextTime, value); + } + } + /** + * Trigger the Release of an AudioVoice note. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @method noteRelease + * @for p5.PolySynth + * @param {Number} [note] midi note on which attack should be triggered. + * If no value is provided, all notes will be released. + * @param {Number} [secondsFromNow] time to trigger the release + * @example + *
+ * let polySynth = new p5.PolySynth(); + * let pitches = ['G', 'D', 'G', 'C']; + * let octaves = [2, 3, 4]; + * + * function setup() { + * let cnv = createCanvas(100, 100); + * cnv.mousePressed(playChord); + * background(220); + * text('tap to play', 20, 20); + * } + * + * function playChord() { + * userStartAudio(); + * + * // play a chord: multiple notes at the same time + * for (let i = 0; i < 4; i++) { + * let note = random(pitches) + random(octaves); + * polySynth.noteAttack(note, 0.1); + * } + * } + * + * function mouseReleased() { + * // release all voices + * polySynth.noteRelease(); + * } + *
+ * + */ + + }, { + key: "noteRelease", + value: function noteRelease(_note, secondsFromNow) { + var now = master.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; - return curve; -} -/** - * A Distortion effect created with a Waveshaper Node, - * with an approach adapted from - * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Distortion - * @extends p5.Effect - * @constructor - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - * - */ + if (!_note) { + this.audiovoices.forEach(function (voice) { + voice.triggerRelease(tFromNow); + }); + this._voicesInUse.setValueAtTime(0, t); -p5.Distortion = function (amount, oversample) { - effect.call(this); + for (var n in this.notes) { + this.notes[n].dispose(); + delete this.notes[n]; + } - if (typeof amount === 'undefined') { - amount = 0.25; - } + return; + } - if (typeof amount !== 'number') { - throw new Error('amount must be a number'); - } - if (typeof oversample === 'undefined') { - oversample = '2x'; - } + var note = noteToFreq(_note); - if (typeof oversample !== 'string') { - throw new Error('oversample must be a String'); - } + if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) { + console.warn('Cannot release a note that is not already playing'); + } else { + var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1); - var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000); - /** - * The p5.Distortion is built with a - * - * Web Audio WaveShaper Node. - * - * @property {AudioNode} WaveShaperNode - */ + this._voicesInUse.setValueAtTime(previousVal - 1, t); - this.waveShaperNode = this.ac.createWaveShaper(); - this.amount = curveAmount; - this.waveShaperNode.curve = makeDistortionCurve(curveAmount); - this.waveShaperNode.oversample = oversample; - this.input.connect(this.waveShaperNode); - this.waveShaperNode.connect(this.wet); -}; -p5.Distortion.prototype = Object.create(effect.prototype); -/** - * Process a sound source, optionally specify amount and oversample values. - * - * @method process - * @for p5.Distortion - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - */ + if (previousVal > 0) { + this._updateAfter(t, -1); + } -p5.Distortion.prototype.process = function (src, amount, oversample) { - src.connect(this.input); - this.set(amount, oversample); -}; -/** - * Set the amount and oversample of the waveshaper distortion. - * - * @method set - * @for p5.Distortion - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - */ + this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(tFromNow); + this.notes[note].dispose(); + delete this.notes[note]; + this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1); + } + } + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @for p5.PolySynth + * @param {Object} unit A p5.sound or Web Audio object + */ + + }, { + key: "connect", + value: function connect(unit) { + var u = unit || master.input; + this.output.connect(u.input ? u.input : u); + } + /** + * Disconnect all outputs + * + * @method disconnect + * @for p5.PolySynth + */ + + }, { + key: "disconnect", + value: function disconnect() { + if (this.output) { + this.output.disconnect(); + } + } + /** + * Get rid of the MonoSynth and free up its resources / memory. + * + * @method dispose + * @for p5.PolySynth + */ + + }, { + key: "dispose", + value: function dispose() { + this.audiovoices.forEach(function (voice) { + voice.dispose(); + }); + if (this.output) { + this.output.disconnect(); + delete this.output; + } + } + }]); -p5.Distortion.prototype.set = function (amount, oversample) { - if (amount) { - var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000); - this.amount = curveAmount; - this.waveShaperNode.curve = makeDistortionCurve(curveAmount); - } + return PolySynth; +}(); - if (oversample) { - this.waveShaperNode.oversample = oversample; - } -}; -/** - * Return the distortion amount, typically between 0-1. - * - * @method getAmount - * @for p5.Distortion - * @return {Number} Unbounded distortion amount. - * Normal values range from 0-1. - */ + var polysynth = (polysynth_PolySynth); +function Signal_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +var Signal_Signal = function Signal() { + Signal_classCallCheck(this, Signal); -p5.Distortion.prototype.getAmount = function () { - return this.amount; + console.warn('p5.Signal is deprecated , Use Tone.js Signal instead '); }; -/** - * Return the oversampling. - * - * @method getOversample - * @for p5.Distortion - * @return {String} Oversample can either be 'none', '2x', or '4x'. - */ - -p5.Distortion.prototype.getOversample = function () { - return this.waveShaperNode.oversample; -}; + var deprecations_Signal = (Signal_Signal); -p5.Distortion.prototype.dispose = function () { - effect.prototype.dispose.apply(this); - if (this.waveShaperNode) { - this.waveShaperNode.disconnect(); - this.waveShaperNode = null; - } -}; - var distortion = (p5.Distortion); +p5.prototype.getAudioContext = audiocontext["b" ]; +p5.prototype.userStartAudio = audiocontext["c" ]; +p5.prototype.sampleRate = sampleRate; +p5.prototype.freqToMidi = freqToMidi; +p5.prototype.midiToFreq = midiToFreq; +p5.prototype.noteToFreq = noteToFreq; +p5.prototype.soundFormats = soundFormats; +p5.prototype.disposeSound = disposeSound; +p5.prototype._checkFileFormats = _checkFileFormats; +p5.prototype._mathChain = _mathChain; +p5.prototype.convertToWav = convertToWav; +p5.prototype.interleave = interleave; +p5.prototype.writeUTFBytes = writeUTFBytes; +p5.prototype.safeBufferSize = safeBufferSize; +p5.prototype.saveSound = saveSound; +p5.prototype.registerMethod('remove', p5.prototype.disposeSound); +p5.Panner = panner_0; +p5.SoundFile = soundfile; +p5.prototype.loadSound = loadSound; +p5.prototype.registerPreloadMethod('loadSound', p5.prototype); +p5.Amplitude = amplitude; +p5.FFT = fft; +p5.Oscillator = oscillator; +p5.SinOsc = SinOsc; +p5.TriOsc = TriOsc; +p5.SawOsc = SawOsc; +p5.SqrOsc = SqrOsc; +p5.Noise = noise; +p5.Pulse = pulse; +p5.AudioIn = audioin; +p5.Effect = effect; +p5.Filter = filter; +p5.LowPass = LowPass; +p5.HighPass = HighPass; +p5.BandPass = BandPass; +p5.EQ = eq; +p5.listener3D = listener3d; +p5.Panner3D = panner3d; +p5.Delay = delay; +p5.Reverb = Reverb; +p5.Convolver = reverb_Convolver; +p5.prototype.createConvolver = createConvolver; +p5.prototype.registerPreloadMethod('createConvolver', p5.prototype); +p5.Metro = metro; +p5.Phrase = Phrase; +p5.Part = looper_Part; +p5.Score = Score; +p5.SoundLoop = soundLoop; +p5.Compressor = compressor; +p5.peakDetect = peakDetect; +p5.SoundRecorder = soundRecorder; +p5.Distortion = distortion; +p5.Gain = gain; +p5.AudioVoice = audioVoice_0; +p5.MonoSynth = monosynth; +p5.OnsetDetect = onsetDetect; +p5.PolySynth = polysynth; +p5.Signal = deprecations_Signal; }) ]); diff --git a/lib/p5.sound.js.map b/lib/p5.sound.js.map index 2d1a331c..61e211ef 100644 --- a/lib/p5.sound.js.map +++ b/lib/p5.sound.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///../node_modules/tone/Tone/signal/Signal.js","webpack:///../node_modules/tone/Tone/core/Tone.js","webpack:///../node_modules/tone/Tone/signal/Multiply.js","webpack:///../node_modules/tone/Tone/signal/Add.js","webpack:///../node_modules/tone/Tone/signal/Scale.js","webpack:///./audioWorklet/processorNames.js","webpack:///./audiocontext.js","webpack:///../node_modules/tone/Tone/signal/WaveShaper.js","webpack:///../node_modules/tone/Tone/signal/TimelineSignal.js","webpack:///../node_modules/tone/Tone/type/Type.js","webpack:///../node_modules/tone/Tone/core/Gain.js","webpack:///../node_modules/tone/Tone/core/Clock.js","webpack:///../node_modules/tone/Tone/core/Context.js","webpack:///../node_modules/tone/Tone/signal/Subtract.js","webpack:///../node_modules/tone/Tone/core/Emitter.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:///../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/startaudiocontext/StartAudioContext.js","webpack:///../node_modules/tone/Tone/component/CrossFade.js","webpack:///../node_modules/audioworklet-polyfill/dist/audioworklet-polyfill.js","webpack:///./shims.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///./audioWorklet/recorderProcessor.js","webpack:///./audioWorklet/soundFileProcessor.js","webpack:///./audioWorklet/amplitudeProcessor.js","webpack:///../node_modules/tone/Tone/type/Frequency.js","webpack:///../node_modules/tone/Tone/type/TransportTime.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:///../node_modules/tone/Tone/core/TimelineState.js","webpack:///./peakDetect.js","webpack:///./master.js","webpack:///./helpers.js","webpack:///./errorHandler.js","webpack:///./audioWorklet/index.js","webpack:///./panner.js","webpack:///./soundfile.js","webpack:///./amplitude.js","webpack:///./fft.js","webpack:///./signal.js","webpack:///./oscillator.js","webpack:///./envelope.js","webpack:///./pulse.js","webpack:///./noise.js","webpack:///./audioin.js","webpack:///./effect.js","webpack:///./filter.js","webpack:///./eqFilter.js","webpack:///./eq.js","webpack:///./panner3d.js","webpack:///./listener3d.js","webpack:///./delay.js","webpack:///./reverb.js","webpack:///./metro.js","webpack:///./looper.js","webpack:///./soundLoop.js","webpack:///./compressor.js","webpack:///./soundRecorder.js","webpack:///./gain.js","webpack:///./audioVoice.js","webpack:///./monosynth.js","webpack:///./polysynth.js","webpack:///./distortion.js","webpack:///./app.js"],"names":["define","Tone","Signal","options","this","optionsObject","arguments","defaults","output","_gain","context","createGain","param","gain","Param","call","input","_param","getConstant","chain","extend","value","units","Type","Default","convert","prototype","connect","SignalBase","dispose","disconnect","inputs","outputs","isUndef","Array","audioContext","set","params","rampTime","isObject","isString","tmpObj","paramLoop","attr","parent","indexOf","attrSplit","split","i","length","splice","innerParam","join","rampTo","AudioParam","get","_collectDefaults","constructor","ret","subRet","j","subAttr","isFunction","constr","Object","keys","_super","superDefs","push","toString","className","isLetter","match","sameConstructor","defineProperty","isArray","AudioNode","unit","outputNum","inputNum","defaultArg","destination","isNumber","apply","connectSeries","currentUnit","toUnit","fan","given","fallback","givenProp","fallbackProp","values","val","arg","isBoolean","noOp","_readOnly","property","writable","enumerable","_writable","State","Started","Stopped","Paused","equalPowerScale","percent","piFactor","Math","PI","sin","dbToGain","db","pow","gainToDb","log","LN10","intervalToFrequencyRatio","interval","now","child","TempConstructor","Context","emit","setContext","ctx","sampleRate","hasAudioContext","window","hasOwnProperty","hasPromises","hasWorkers","version","TONE_SILENCE_VERSION_LOGGING","console","Multiply","createInsOuts","_mult","Gain","Add","_sum","Scale","outputMin","outputMax","_outputMin","_outputMax","_scale","_add","_setRange","min","max","module","exports","recorderProcessor","soundFileProcessor","amplitudeProcessor","global","audiocontext","AudioContext","p5","getAudioContext","userStartAudio","elements","callback","elt","Element","map","e","StartAudioContext","WaveShaper","mapping","bufferLen","_shaper","createWaveShaper","_curve","curve","isFinite","Float32Array","setMap","len","normalized","oversample","oversampling","RangeError","TimelineSignal","_events","Timeline","_initial","_fromUnits","Linear","Exponential","Target","Curve","Set","getValueAtTime","_toUnits","convertedVal","cancelScheduledValues","setValueAtTime","startTime","toSeconds","add","type","time","linearRampToValueAtTime","endTime","exponentialRampToValueAtTime","beforeEvent","_searchBefore","_minOutput","setValue","sampleTime","setTargetAtTime","timeConstant","constant","setValueCurveAtTime","duration","scaling","floats","segmentTime","after","cancel","setRampPoint","before","_searchAfter","linearRampToValueBetween","start","finish","exponentialRampToValueBetween","getAfter","previouVal","previous","getBefore","_exponentialApproach","_curveInterpolate","_linearInterpolate","_exponentialInterpolate","t0","v0","v1","t","exp","t1","progress","lowerIndex","floor","upperIndex","ceil","lowerVal","upperVal","Time","Frequency","TransportTime","Ticks","NormalRange","AudioRange","Decibels","Interval","BPM","Positive","Cents","Degrees","MIDI","BarsBeatsSixteenths","Samples","Hertz","Note","Milliseconds","Seconds","Notation","TimeBase","toFrequency","freq","valueOf","toTicks","Transport","ticks","GainNode","createGainNode","_gainNode","Clock","Emitter","_nextTick","_lastState","frequency","_state","TimelineState","_boundLoop","_loop","bind","on","lookAhead","offset","state","stop","setStateAtTime","pause","loopInterval","updateInterval","lag","currentState","event","tickTime","getStateAtTime","off","Infinity","toneConnect","B","outNum","inNum","nativeConnect","Error","nativeDisconnect","webkitAudioContext","prop","_context","_defineProperty","_latencyHint","_lookAhead","_updateInterval","_computedUpdateInterval","_worker","_createWorker","_constants","mixin","currentTime","URL","webkitURL","blob","Blob","toFixed","blobUrl","createObjectURL","worker","Worker","addEventListener","_lastUpdate","diff","buffer","createBuffer","arr","getChannelData","createBufferSource","channelCount","channelCountMode","loop","lA","blockTime","postMessage","hint","latencyHint","supported","warn","Subtract","_neg","Negate","events","eventName","ev","eventList","args","slice","object","functions","func","emitterFunc","node","outputNumber","inputNumber","overridden","_plusNow","_unaryExpressions","create","quantize","regexp","method","rh","nextSubdivision","lh","subdiv","_expr","expr","subdivision","round","addNow","_defaultExpr","_noOp","copy","toNotation","retNotation","_toNotationHelper","retTripletNotation","testNotations","threshold","_notationToUnits","notationTime","multiple","notation","primaryExprs","_primaryExpressions","notationExprs","n","m","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","name","sub","mult","div","_lfo","lfo","undefined","LFO","currentVal","exponentialRampToValue","linearRampToValue","_timeline","_toRemove","_iterating","memory","index","_search","remove","shift","cancelBefore","beginning","end","midPoint","nextEvent","_iterate","lowerBound","upperBound","forEach","forEachBefore","forEachAfter","forEachFrom","forEachAtTime","_multiply","GreaterThanZero","_thresh","root","factory","amd","TapListener","element","_dragged","_element","_bindedMove","_moved","_bindedEnd","_ended","isStarted","source","resume","startContext","removeEventListener","promise","Promise","success","checkLoop","requestAnimationFrame","onStarted","tapListeners","bindTapListener","NodeList","document","querySelectorAll","jquery","toArray","tap","body","then","CrossFade","initialFade","a","b","fade","_equalPowerA","EqualPowerGain","_equalPowerB","_invert","Expr","r","parameters","o","bufferSize","fill","processor","realm","exec","inputBuffer","outputBuffer","process","numberOfChannels","$$processors","$$context","AudioWorkletNode","self","createScriptProcessor","outputChannelCount","Map","properties","u","c","l","defaultValue","p","MessageChannel","port2","f","Processor","port","port1","onaudioprocess","$$audioWorklet","AudioWorklet","addModule","fetch","ok","status","text","AudioWorkletProcessor","registerProcessor","parameterDescriptors","createElement","style","cssText","appendChild","contentWindow","createTextNode","$hook","documentElement","transpile","String","fixSetTarget","setTargetValueAtTime","createDelay","createDelayNode","createJavaScriptNode","createPeriodicWave","createWaveTable","internal_createGain","internal_createDelay","maxDelayTime","delayTime","internal_createBufferSource","when","noteGrainOn","noteOn","internal_start","noteOff","internal_stop","playbackRate","internal_createDynamicsCompressor","createDynamicsCompressor","knee","ratio","reduction","attack","release","internal_createBiquadFilter","createBiquadFilter","detune","Q","createOscillator","internal_createOscillator","setPeriodicWave","setWaveTable","OfflineAudioContext","webkitOfflineAudioContext","navigator","getUserMedia","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","el","isSupported","canPlayType","isOGGSupported","isMP3Supported","isWAVSupported","isAACSupported","isAIFSupported","isFileSupported","extension","toLowerCase","g","Function","midi","midiToFrequency","note","pitch","octave","noteNumber","noteToScaleIndex","transpose","harmonize","intervals","toMidi","frequencyToMidi","toNote","A4","LN2","scaleIndexToNote","cbb","cb","c#","cx","dbb","d","d#","dx","ebb","eb","e#","ex","fbb","fb","f#","fx","gbb","gb","g#","gx","abb","ab","a#","ax","bbb","bb","b#","bx","_secondsToTicks","applyBinary","Constructor","_eval","applyUnary","getNumber","literalNumber","_replacements","inputCount","_parseInputs","_nodes","result","tree","_parseTree","_disposeNodes","_Expressions","signal","glue",",","abs","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","x","_eqPower","initial","PeakDetect","freq1","freq2","_framesPerPeak","framesPerPeak","framesSinceLastPeak","decayRate","cutoff","cutoffMult","energy","penergy","currentValue","isDetected","f1","f2","_onPeak","update","fftObject","nrg","getEnergy","onPeak","Master","limiter","meter","fftMeter","soundArray","parts","extensions","p5sound","getMasterVolume","masterVolume","vol","tFromNow","currentVol","soundOut","_silentNode","freqToMidi","mathlog2","midiToFreq","noteToFreq","wholeNotes","A","C","D","E","F","G","toUpperCase","soundFormats","disposeSound","registerMethod","_checkFileFormats","paths","path","extTest","pop","pathSplit","pathCore","_mathChain","math","thisChain","nextChain","mathOps","convertToWav","audioBuffer","leftChannel","rightChannel","interleaved","interleave","ArrayBuffer","view","DataView","writeUTFBytes","setUint32","setUint16","lng","volume","setInt16","inputIndex","string","setUint8","charCodeAt","safeBufferSize","idealBufferSize","tempAudioWorkletNode","processorNames","ScriptProcessorNode","CustomError","errorTrace","failedPath","err","tempStack","splitStack","originalStack","stack","filter","ln","moduleSources","require","ac","initializedAudioWorklets","loadAudioWorkletModules","all","moduleSrc","objectURL","audioWorklet","preload","_incrementPreload","onWorkletModulesLoad","_decrementPreload","createStereoPanner","Panner","stereoPanner","pan","inputChannels","obj","numInputChannels","left","right","channelInterpretation","splitter","createChannelSplitter","createChannelMerger","v","rightVal","cos","leftVal","numChannels","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","panPosition","panner","load","_whileLoading","_clearOnEnd","registerPreloadMethod","loadSound","location","origin","cordova","alert","errorCallback","request","XMLHttpRequest","evt","_updateProgress","open","responseType","decodeAudioData","response","buff","msg","error","statusText","message","send","reader","readAsArrayBuffer","lengthComputable","percentComplete","loaded","isLoaded","play","rate","amp","_cueStart","cueStart","cueEnd","setVolume","isPlaying","_initSourceNode","_initCounterNode","_arrayIndex","loopStart","loopEnd","playMode","str","pTime","setLoop","bool","isLooping","isPaused","timeFromNow","stopAll","_time","_rampTime","_tFromNow","getVolume","pval","getPan","reverse","reverseBuffer","setPitch","num","newPlaybackRate","getPlaybackRate","jump","cueTime","cTime","dur","channels","frames","getPeaks","width","sampleSize","sampleStep","peaks","chan","currentPos","curVol","onended","getLevel","setPath","setBuffer","buf","size","newBuffer","channelNum","channel","_createCounterBuffer","audioBuf","arrayBuffer","cNode","workletBufferSize","processorOptions","onmessage","data","_onTimeUpdate","processPeaks","_initThreshold","_minThreshold","_minPeaks","bufLen","allPeaks","initialThreshold","minThreshold","minPeaks","offlineContext","startRendering","oncomplete","filteredBuffer","renderedBuffer","bufferData","getPeaksAtThreshold","intervalCounts","countIntervalsBetweenNearbyPeaks","groups","groupNeighborsByTempo","topTempos","sort","intA","intB","count","tempo","bpmVariance","tempoPeaks","getPeaksAtTopTempo","Peak","sampleIndex","amplitude","tempos","peaksObj","peak","peaksArray","startPeak","endPeak","startPos","endPos","foundInterval","some","intervalCount","tempoCounts","theoreticalTempo","mapTempo","foundTempo","tempoCount","isNaN","peaksAtTopTempo","key","intervalBPM","peakTime","dif","Cue","id","addCue","cue","removeCue","cueLength","clearCues","playbackTime","callbackTime","leftLimit","_prevUpdateTime","rightLimit","save","fileName","saveSound","getBlob","dataView","thisBufferSourceNode","target","soundFile","_","Amplitude","smoothing","parameterData","normalize","volNorm","stereoVol","stereoVolNorm","setInput","toggleNormalize","smooth","FFT","bins","analyser","createAnalyser","defineProperties","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","frequency1","frequency2","nyquist","swap","lowIndex","highIndex","numFrequencies","toReturn","getFreq","getCentroid","cumulative_sum","centroid_normalization","mean_freq_index","spec_centroid_freq","linAverages","_N","N","spectrum","spectrumLength","spectrumStep","linearAverages","groupIndex","specIndex","logAverages","octaveBands","octaveIndex","specIndexFrequency","hi","getOctaveBands","_fCtr0","fCtr0","lastFrequencyBand","lo","ctr","newFrequencyBand","fft","Mult","_input","scale","inMin","inMax","outMin","outMax","mapOutMin","mapOutMax","Oscillator","started","phaseAmount","oscillator","_freqMods","connection","freqNode","getAmp","phase","setType","getType","oscMods","osc2","delayAmt","dNode","sigChain","mathObj","chainSource","SinOsc","TriOsc","SawOsc","SqrOsc","Envelope","l1","t2","l2","t3","l3","aTime","aLevel","dTime","dLevel","rTime","rLevel","_rampHighPercentage","_rampLowPercentage","control","_init","isExponential","sourceToClear","wasTriggered","_setRampAD","setADSR","sPercent","setRange","_rampAttackTime","checkExpInput","_rampDecayTime","TCDenominator","_rampAttackTC","_rampDecayTC","setRampPercentages","p1","p2","setExp","isExp","secondsFromNow","susTime","triggerAttack","triggerRelease","lastAttack","valToSet","ramp","v2","destination1","destination2","AudioIn","Reverb","Noise","Filter","Delay","Env","Pulse","w","dcOffset","createDCOffset","dcGain","mW","sig","SignalAdd","mods","currentFreq","freqMod","bufferSource","_whiteNoiseBuffer","whiteBuffer","noiseData","random","_pinkNoiseBuffer","pinkBuffer","b0","b1","b2","b3","b4","b5","b6","white","_brownNoiseBuffer","brownBuffer","lastOut","assignType","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","Effect","_drywet","wet","drywet","biquad","_on","_untoggledType","src","res","toggle","LowPass","HighPass","BandPass","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","rebuild","decay","impulse","impulseL","impulseR","Convolver","impulses","_loadBuffer","cReverb","_path","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","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","_note","timeSig","Compressor","compressor","number","SoundRecorder","_inputChannels","_outputChannels","buffers","leftBuffer","rightBuffer","_callback","record","sFile","writeFile","AudioVoice","velocity","sustime","DEFAULT_SUSTAIN","MonoSynth","env","vel","sustain","PolySynth","audioVoice","maxVoices","audiovoices","notes","_newest","_oldest","_voicesInUse","_allocateVoices","noteAttack","noteRelease","noteADSR","voice","_velocity","acTime","currentVoice","oldestNote","previousVal","_updateAfter","maxRange","nextTime","makeDistortionCurve","amount","k","numSamples","deg","Distortion","curveAmount","waveShaperNode","getAmount","getOversample"],"mappings":"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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 = 41);\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});","/**\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","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","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/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","module.exports = {\n recorderProcessor: 'recorder-processor',\n soundFileProcessor: 'sound-file-processor',\n amplitudeProcessor: 'amplitude-processor',\n};\n","global.TONE_SILENCE_VERSION_LOGGING = true;\n\nimport StartAudioContext from 'startaudiocontext';\nimport Tone from 'Tone/core/Tone';\nimport 'Tone/core/Context';\n\n// Create the Audio Context\nconst audiocontext = new window.AudioContext();\n\n// Tone and p5.sound share the same audio context\nTone.setContext(audiocontext);\n\n/**\n *

Returns the Audio Context for this sketch. Useful for users\n * who would like to dig deeper into the Web Audio API\n * .

\n *\n *

Some browsers require users to startAudioContext\n * with a user gesture, such as touchStarted in the example below.

\n *\n * @for p5\n * @method getAudioContext\n * @return {Object} AudioContext for this sketch\n * @example\n *
\n * function draw() {\n * background(255);\n * textAlign(CENTER);\n *\n * if (getAudioContext().state !== 'running') {\n * text('click to start audio', width/2, height/2);\n * } else {\n * text('audio is enabled', width/2, height/2);\n * }\n * }\n *\n * function touchStarted() {\n * if (getAudioContext().state !== 'running') {\n * getAudioContext().resume();\n * }\n * var synth = new p5.MonoSynth();\n * synth.play('A4', 0.5, 0, 0.2);\n * }\n *\n *
\n */\np5.prototype.getAudioContext = function () {\n return audiocontext;\n};\n\n/**\n *

It is not only a good practice to give users control over starting\n * audio. This policy is enforced by many web browsers, including iOS and\n * Google Chrome, which create the Web Audio API's\n * Audio Context\n * in a suspended state.

\n *\n *

In these browser-specific policies, sound will not play until a user\n * interaction event (i.e. mousePressed()) explicitly resumes\n * the AudioContext, or starts an audio node. This can be accomplished by\n * calling start() on a p5.Oscillator,\n * play() on a p5.SoundFile, or simply\n * userStartAudio().

\n *\n *

userStartAudio() starts the AudioContext on a user\n * gesture. The default behavior will enable audio on any\n * mouseUp or touchEnd event. It can also be placed in a specific\n * interaction function, such as mousePressed() as in the\n * example below. This method utilizes\n * StartAudioContext\n * , a library by Yotam Mann (MIT Licence, 2016).

\n * @param {Element|Array} [element(s)] This argument can be an Element,\n * Selector String, NodeList, p5.Element,\n * jQuery Element, or an Array of any of those.\n * @param {Function} [callback] Callback to invoke when the AudioContext\n * has started\n * @return {Promise} Returns a Promise that resolves when\n * the AudioContext state is 'running'\n * @method userStartAudio\n * @for p5\n * @example\n *
\n * function setup() {\n * // mimics the autoplay policy\n * getAudioContext().suspend();\n *\n * let mySynth = new p5.MonoSynth();\n *\n * // This won't play until the context has resumed\n * mySynth.play('A6');\n * }\n * function draw() {\n * background(220);\n * textAlign(CENTER, CENTER);\n * text(getAudioContext().state, width/2, height/2);\n * }\n * function mousePressed() {\n * userStartAudio();\n * }\n *
\n */\np5.prototype.userStartAudio = function (elements, callback) {\n var elt = elements;\n if (elements instanceof p5.Element) {\n elt = elements.elt;\n } else if (elements instanceof Array && elements[0] instanceof p5.Element) {\n elt = elements.map(function (e) {\n return e.elt;\n });\n }\n return StartAudioContext(audiocontext, elt, callback);\n};\n\nexport default audiocontext;\n","define([\"Tone/core/Tone\", \"Tone/signal/SignalBase\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Wraps the native Web Audio API \n\t * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {function|Array|Number} mapping The function used to define the values. \n\t * The mapping function should take two arguments: \n\t * the first is the value at the current position \n\t * and the second is the array position. \n\t * If the argument is an array, that array will be\n\t * set as the wave shaping function. The input\n\t * signal is an AudioRange [-1, 1] value and the output\n\t * signal can take on any numerical values. \n\t * \n\t * @param {Number} [bufferLen=1024] The length of the WaveShaperNode buffer.\n\t * @example\n\t * var timesTwo = new Tone.WaveShaper(function(val){\n\t * \treturn val * 2;\n\t * }, 2048);\n\t * @example\n\t * //a waveshaper can also be constructed with an array of values\n\t * var invert = new Tone.WaveShaper([1, -1]);\n\t */\n\tTone.WaveShaper = function(mapping, bufferLen){\n\n\t\t/**\n\t\t * the waveshaper\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._shaper = this.input = this.output = this.context.createWaveShaper();\n\n\t\t/**\n\t\t * the waveshapers curve\n\t\t * @type {Float32Array}\n\t\t * @private\n\t\t */\n\t\tthis._curve = null;\n\n\t\tif (Array.isArray(mapping)){\n\t\t\tthis.curve = mapping;\n\t\t} else if (isFinite(mapping) || this.isUndef(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(mapping, 1024));\n\t\t} else if (this.isFunction(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(bufferLen, 1024));\n\t\t\tthis.setMap(mapping);\n\t\t} \n\t};\n\n\tTone.extend(Tone.WaveShaper, Tone.SignalBase);\n\n\t/**\n\t * Uses a mapping function to set the value of the curve. \n\t * @param {function} mapping The function used to define the values. \n\t * The mapping function take two arguments: \n\t * the first is the value at the current position \n\t * which goes from -1 to 1 over the number of elements\n\t * in the curve array. The second argument is the array position. \n\t * @returns {Tone.WaveShaper} this\n\t * @example\n\t * //map the input signal from [-1, 1] to [0, 10]\n\t * shaper.setMap(function(val, index){\n\t * \treturn (val + 1) * 5;\n\t * })\n\t */\n\tTone.WaveShaper.prototype.setMap = function(mapping){\n\t\tfor (var i = 0, len = this._curve.length; i < len; i++){\n\t\t\tvar normalized = (i / (len - 1)) * 2 - 1;\n\t\t\tthis._curve[i] = mapping(normalized, i);\n\t\t}\n\t\tthis._shaper.curve = this._curve;\n\t\treturn this;\n\t};\n\n\t/**\n\t * The array to set as the waveshaper curve. For linear curves\n\t * array length does not make much difference, but for complex curves\n\t * longer arrays will provide smoother interpolation. \n\t * @memberOf Tone.WaveShaper#\n\t * @type {Array}\n\t * @name curve\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"curve\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.curve;\n\t\t},\n\t\tset : function(mapping){\n\t\t\tthis._curve = new Float32Array(mapping);\n\t\t\tthis._shaper.curve = this._curve;\n\t\t}\n\t});\n\n\t/**\n\t * Specifies what type of oversampling (if any) should be used when \n\t * applying the shaping curve. Can either be \"none\", \"2x\" or \"4x\". \n\t * @memberOf Tone.WaveShaper#\n\t * @type {string}\n\t * @name oversample\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"oversample\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.oversample;\n\t\t},\n\t\tset : function(oversampling){\n\t\t\tif ([\"none\", \"2x\", \"4x\"].indexOf(oversampling) !== -1){\n\t\t\t\tthis._shaper.oversample = oversampling;\n\t\t\t} else {\n\t\t\t\tthrow new RangeError(\"Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'\");\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.WaveShaper} this\n\t */\n\tTone.WaveShaper.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.disconnect();\n\t\tthis._shaper = null;\n\t\tthis._curve = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.WaveShaper;\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});","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 * \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 * @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});","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});","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/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});","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});","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});","/**\n * StartAudioContext.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2016 Yotam Mann\n */\n(function (root, factory) {\n\tif (typeof define === \"function\" && define.amd) {\n\t\tdefine([], factory)\n\t } else if (typeof module === \"object\" && module.exports) {\n module.exports = factory()\n\t} else {\n\t\troot.StartAudioContext = factory()\n }\n}(this, function () {\n\n\t//TAP LISTENER/////////////////////////////////////////////////////////////\n\n\t/**\n\t * @class Listens for non-dragging tap ends on the given element\n\t * @param {Element} element\n\t * @internal\n\t */\n\tvar TapListener = function(element, context){\n\n\t\tthis._dragged = false\n\n\t\tthis._element = element\n\n\t\tthis._bindedMove = this._moved.bind(this)\n\t\tthis._bindedEnd = this._ended.bind(this, context)\n\n\t\telement.addEventListener(\"touchstart\", this._bindedEnd)\n\t\telement.addEventListener(\"touchmove\", this._bindedMove)\n\t\telement.addEventListener(\"touchend\", this._bindedEnd)\n\t\telement.addEventListener(\"mouseup\", this._bindedEnd)\n\t}\n\n\t/**\n\t * drag move event\n\t */\n\tTapListener.prototype._moved = function(e){\n\t\tthis._dragged = true\n\t};\n\n\t/**\n\t * tap ended listener\n\t */\n\tTapListener.prototype._ended = function(context){\n\t\tif (!this._dragged){\n\t\t\tstartContext(context)\n\t\t}\n\t\tthis._dragged = false\n\t};\n\n\t/**\n\t * remove all the bound events\n\t */\n\tTapListener.prototype.dispose = function(){\n\t\tthis._element.removeEventListener(\"touchstart\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"touchmove\", this._bindedMove)\n\t\tthis._element.removeEventListener(\"touchend\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"mouseup\", this._bindedEnd)\n\t\tthis._bindedMove = null\n\t\tthis._bindedEnd = null\n\t\tthis._element = null\n\t};\n\n\t//END TAP LISTENER/////////////////////////////////////////////////////////\n\n\t/**\n\t * Plays a silent sound and also invoke the \"resume\" method\n\t * @param {AudioContext} context\n\t * @private\n\t */\n\tfunction startContext(context){\n\t\t// this accomplishes the iOS specific requirement\n\t\tvar buffer = context.createBuffer(1, 1, context.sampleRate)\n\t\tvar source = context.createBufferSource()\n\t\tsource.buffer = buffer\n\t\tsource.connect(context.destination)\n\t\tsource.start(0)\n\n\t\t// resume the audio context\n\t\tif (context.resume){\n\t\t\tcontext.resume()\n\t\t}\n\t}\n\n\t/**\n\t * Returns true if the audio context is started\n\t * @param {AudioContext} context\n\t * @return {Boolean}\n\t * @private\n\t */\n\tfunction isStarted(context){\n\t\t return context.state === \"running\"\n\t}\n\n\t/**\n\t * Invokes the callback as soon as the AudioContext\n\t * is started\n\t * @param {AudioContext} context\n\t * @param {Function} callback\n\t */\n\tfunction onStarted(context, callback){\n\n\t\tfunction checkLoop(){\n\t\t\tif (isStarted(context)){\n\t\t\t\tcallback()\n\t\t\t} else {\n\t\t\t\trequestAnimationFrame(checkLoop)\n\t\t\t\tif (context.resume){\n\t\t\t\t\tcontext.resume()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isStarted(context)){\n\t\t\tcallback()\n\t\t} else {\n\t\t\tcheckLoop()\n\t\t}\n\t}\n\n\t/**\n\t * Add a tap listener to the audio context\n\t * @param {Array|Element|String|jQuery} element\n\t * @param {Array} tapListeners\n\t */\n\tfunction bindTapListener(element, tapListeners, context){\n\t\tif (Array.isArray(element) || (NodeList && element instanceof NodeList)){\n\t\t\tfor (var i = 0; i < element.length; i++){\n\t\t\t\tbindTapListener(element[i], tapListeners, context)\n\t\t\t}\n\t\t} else if (typeof element === \"string\"){\n\t\t\tbindTapListener(document.querySelectorAll(element), tapListeners, context)\n\t\t} else if (element.jquery && typeof element.toArray === \"function\"){\n\t\t\tbindTapListener(element.toArray(), tapListeners, context)\n\t\t} else if (Element && element instanceof Element){\n\t\t\t//if it's an element, create a TapListener\n\t\t\tvar tap = new TapListener(element, context)\n\t\t\ttapListeners.push(tap)\n\t\t} \n\t}\n\n\t/**\n\t * @param {AudioContext} context The AudioContext to start.\n\t * @param {Array|String|Element|jQuery=} elements For iOS, the list of elements\n\t * to bind tap event listeners\n\t * which will start the AudioContext. If\n\t * no elements are given, it will bind\n\t * to the document.body.\n\t * @param {Function=} callback The callback to invoke when the AudioContext is started.\n\t * @return {Promise} The promise is invoked when the AudioContext\n\t * is started.\n\t */\n\tfunction StartAudioContext(context, elements, callback){\n\n\t\t//the promise is invoked when the AudioContext is started\n\t\tvar promise = new Promise(function(success) {\n\t\t\tonStarted(context, success)\n\t\t})\n\n\t\t// The TapListeners bound to the elements\n\t\tvar tapListeners = []\n\n\t\t// add all the tap listeners\n\t\tif (!elements){\n\t\t\telements = document.body\n\t\t}\n\t\tbindTapListener(elements, tapListeners, context)\n\n\t\t//dispose all these tap listeners when the context is started\n\t\tpromise.then(function(){\n\t\t\tfor (var i = 0; i < tapListeners.length; i++){\n\t\t\t\ttapListeners[i].dispose()\n\t\t\t}\n\t\t\ttapListeners = null\n\n\t\t\tif (callback){\n\t\t\t\tcallback()\n\t\t\t}\n\t\t})\n\n\t\treturn promise\n\t}\n\n\treturn StartAudioContext\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","!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._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\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.numOutputChannels = options.outputChannelCount || 2;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.bufferSize = processorOptions.bufferSize || 1024;\\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) {\\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 this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannelCopy);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n }\\n\\n this.recordedSamples += this.bufferSize;\\n }\\n\\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 var _this2 = this;\\n\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this2.bufferSize);\\n });\\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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0].length;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar SoundFileProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\\n\\n function SoundFileProcessor(options) {\\n var _this;\\n\\n _classCallCheck(this, SoundFileProcessor);\\n\\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\\n var processorOptions = options.processorOptions || {};\\n _this.bufferSize = processorOptions.bufferSize || 256;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\\n return _this;\\n }\\n\\n _createClass(SoundFileProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs) {\\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\\n\\n this.inputRingBuffer.push([input[0]]);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n var inputChannel = this.inputRingBufferArraySequence[0];\\n var position = inputChannel[inputChannel.length - 1] || 0;\\n this.port.postMessage({\\n name: 'position',\\n position: position\\n });\\n }\\n\\n return true;\\n }\\n }]);\\n\\n return SoundFileProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);\"","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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0].length;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar AmplitudeProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\\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.numOutputChannels = options.outputChannelCount || 1;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.normalize = processorOptions.normalize || false;\\n _this.smoothing = processorOptions.smoothing || 0;\\n _this.bufferSize = processorOptions.bufferSize || 2048;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this.bufferSize);\\n });\\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 } else if (data.name === 'smoothing') {\\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\\n }\\n };\\n\\n return _this;\\n } // TO DO make this stereo / dependent on # of audio channels\\n\\n\\n _createClass(AmplitudeProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs, outputs) {\\n var input = inputs[0];\\n var output = outputs[0];\\n var smoothing = this.smoothing;\\n this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\\n } // pull 128 frames out of the ring buffer\\n // if the ring buffer does not have enough frames, the output will be silent\\n\\n\\n this.outputRingBuffer.pull(output);\\n return true;\\n }\\n }]);\\n\\n return AmplitudeProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);\"","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});","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});","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});","/**\n *

PeakDetect works in conjunction with p5.FFT to\n * look for onsets in some or all of the frequency spectrum.\n *

\n *

\n * To use p5.PeakDetect, call update in the draw loop\n * and pass in a p5.FFT object.\n *

\n *

\n * You can listen for a specific part of the frequency spectrum by\n * setting the range between freq1 and freq2.\n *

\n *\n *

threshold is the threshold for detecting a peak,\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\n * as 1.0.

\n *\n *

\n * The update method is meant to be run in the draw loop, and\n * frames determines how many loops must pass before\n * another peak can be detected.\n * For example, if the frameRate() = 60, you could detect the beat of a\n * 120 beat-per-minute song with this equation:\n * framesPerPeak = 60 / (estimatedBPM / 60 );\n *

\n *\n *

\n * Based on example contribtued by @b2renger, and a simple beat detection\n * explanation by Felix Turner.\n *

\n *\n * @class p5.PeakDetect\n * @constructor\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\n * scaled logarithmically where 0.1 is 1/2 the loudness\n * of 1.0. Defaults to 0.35.\n * @param {Number} [framesPerPeak] Defaults to 20.\n * @example\n *
\n *\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 10;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * background(0);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n *\n * // p5.PeakDetect requires a p5.FFT\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n * }\n *\n * function draw() {\n * background(0);\n * text('click to play/pause', width/2, height/2);\n *\n * // peakDetect accepts an fft post-analysis\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * if ( peakDetect.isDetected ) {\n * ellipseWidth = 50;\n * } else {\n * ellipseWidth *= 0.95;\n * }\n *\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // toggle play/stop when canvas is clicked\n * function mouseClicked() {\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * }\n * }\n *
\n */\np5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) {\n // framesPerPeak determines how often to look for a beat.\n // If a beat is provided, try to look for a beat based on bpm\n this.framesPerPeak = _framesPerPeak || 20;\n this.framesSinceLastPeak = 0;\n this.decayRate = 0.95;\n\n this.threshold = threshold || 0.35;\n this.cutoff = 0;\n\n // how much to increase the cutoff\n // TO DO: document this / figure out how to make it accessible\n this.cutoffMult = 1.5;\n\n this.energy = 0;\n this.penergy = 0;\n\n // TO DO: document this property / figure out how to make it accessible\n this.currentValue = 0;\n\n /**\n * isDetected is set to true when a peak is detected.\n *\n * @attribute isDetected {Boolean}\n * @default false\n */\n this.isDetected = false;\n\n this.f1 = freq1 || 40;\n this.f2 = freq2 || 20000;\n\n // function to call when a peak is detected\n this._onPeak = function () {};\n};\n\n/**\n * The update method is run in the draw loop.\n *\n * Accepts an FFT object. You must call .analyze()\n * on the FFT object prior to updating the peakDetect\n * because it relies on a completed FFT analysis.\n *\n * @method update\n * @param {p5.FFT} fftObject A p5.FFT object\n */\np5.PeakDetect.prototype.update = function (fftObject) {\n var nrg = (this.energy = fftObject.getEnergy(this.f1, this.f2) / 255);\n if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) {\n // trigger callback\n this._onPeak();\n this.isDetected = true;\n\n // debounce\n this.cutoff = nrg * this.cutoffMult;\n this.framesSinceLastPeak = 0;\n } else {\n this.isDetected = false;\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\n this.framesSinceLastPeak++;\n } else {\n this.cutoff *= this.decayRate;\n this.cutoff = Math.max(this.cutoff, this.threshold);\n }\n }\n\n this.currentValue = nrg;\n this.penergy = nrg;\n};\n\n/**\n * onPeak accepts two arguments: a function to call when\n * a peak is detected. The value of the peak,\n * between 0.0 and 1.0, is passed to the callback.\n *\n * @method onPeak\n * @param {Function} callback Name of a function that will\n * be called when a peak is\n * detected.\n * @param {Object} [val] Optional value to pass\n * into the function when\n * a peak is detected.\n * @example\n *
\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 0;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * cnv = createCanvas(100,100);\n * textAlign(CENTER);\n *\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n *\n * setupSound();\n *\n * // when a beat is detected, call triggerBeat()\n * peakDetect.onPeak(triggerBeat);\n * }\n *\n * function draw() {\n * background(0);\n * fill(255);\n * text('click to play', width/2, height/2);\n *\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * ellipseWidth *= 0.95;\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // this function is called by peakDetect.onPeak\n * function triggerBeat() {\n * ellipseWidth = 50;\n * }\n *\n * // mouseclick starts/stops sound\n * function setupSound() {\n * cnv.mouseClicked( function() {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * });\n * }\n *
\n */\np5.PeakDetect.prototype.onPeak = function (callback, val) {\n var self = this;\n\n self._onPeak = function () {\n callback(self.energy, val);\n };\n};\n","import audiocontext from './audiocontext.js';\n// Master contains the master sound output.\nvar Master = function () {\n this.input = audiocontext.createGain();\n this.output = audiocontext.createGain();\n\n //put a hard limiter on the output\n this.limiter = audiocontext.createDynamicsCompressor();\n this.limiter.threshold.value = -3;\n this.limiter.ratio.value = 20;\n this.limiter.knee.value = 1;\n\n this.audiocontext = audiocontext;\n\n this.output.disconnect();\n\n // connect input to limiter\n this.input.connect(this.limiter);\n\n // connect limiter to output\n this.limiter.connect(this.output);\n\n // meter is just for global Amplitude / FFT analysis\n this.meter = audiocontext.createGain();\n this.fftMeter = audiocontext.createGain();\n this.output.connect(this.meter);\n this.output.connect(this.fftMeter);\n\n // connect output to destination\n this.output.connect(this.audiocontext.destination);\n\n // an array of all sounds in the sketch\n this.soundArray = [];\n // an array of all musical parts in the sketch\n this.parts = [];\n\n // file extensions to search for\n this.extensions = [];\n};\n\n// create a single instance of the p5Sound / master output for use within this sketch\nconst p5sound = new Master();\n// console.log(p5sound.audiocontext)\n\n/**\n * Returns a number representing the master amplitude (volume) for sound\n * in this sketch.\n *\n * @method getMasterVolume\n * @return {Number} Master amplitude (volume) for sound in this sketch.\n * Should be between 0.0 (silence) and 1.0.\n */\np5.prototype.getMasterVolume = function () {\n return p5sound.output.gain.value;\n};\n\n/**\n *

Scale the output of all sound in this sketch

\n * Scaled between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n *

How This Works: When you load the p5.sound module, it\n * creates a single instance of p5sound. All sound objects in this\n * module output to p5sound before reaching your computer's output.\n * So if you change the amplitude of p5sound, it impacts all of the\n * sound in this module.

\n *\n *

If no value is provided, returns a Web Audio API Gain Node

\n *\n * @method masterVolume\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\np5.prototype.masterVolume = function (vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = p5sound.output.gain.value;\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(p5sound.output.gain);\n } else {\n // return the Gain Node\n return p5sound.output.gain;\n }\n};\n\n/**\n * `p5.soundOut` is the p5.sound master output. It sends output to\n * the destination of this window's web audio context. It contains\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\n * and Gain Nodes for .input and .output.\n *\n * @property {Object} soundOut\n */\np5.prototype.soundOut = p5.soundOut = p5sound;\n\n// a silent connection to the DesinationNode\n// which will ensure that anything connected to it\n// will not be garbage collected\np5.soundOut._silentNode = p5sound.audiocontext.createGain();\np5.soundOut._silentNode.gain.value = 0;\np5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\n\nexport default p5sound;\n","import p5sound from './master';\nimport processorNames from './audioWorklet/processorNames';\n/**\n * @for p5\n */\n\n/**\n * Returns a number representing the sample rate, in samples per second,\n * of all sound objects in this audio context. It is determined by the\n * sampling rate of your operating system's sound card, and it is not\n * currently possile to change.\n * It is often 44100, or twice the range of human hearing.\n *\n * @method sampleRate\n * @return {Number} samplerate samples per second\n */\np5.prototype.sampleRate = function () {\n return p5sound.audiocontext.sampleRate;\n};\n\n/**\n * Returns the closest MIDI note value for\n * a given frequency.\n *\n * @method freqToMidi\n * @param {Number} frequency A freqeuncy, for example, the \"A\"\n * above Middle C is 440Hz\n * @return {Number} MIDI note value\n */\np5.prototype.freqToMidi = function (f) {\n var mathlog2 = Math.log(f / 440) / Math.log(2);\n var m = Math.round(12 * mathlog2) + 69;\n return m;\n};\n\n/**\n * Returns the frequency value of a MIDI note value.\n * General MIDI treats notes as integers where middle C\n * is 60, C# is 61, D is 62 etc. Useful for generating\n * musical frequencies with oscillators.\n *\n * @method midiToFreq\n * @param {Number} midiNote The number of a MIDI note\n * @return {Number} Frequency value of the given MIDI note\n * @example\n *
\n * let midiNotes = [60, 64, 67, 72];\n * let noteIndex = 0;\n * let midiVal, freq;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * osc = new p5.TriOsc();\n * env = new p5.Envelope();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 10, 20);\n * if (midiVal) {\n * text('MIDI: ' + midiVal, 10, 40);\n * text('Freq: ' + freq, 10, 60);\n * }\n * }\n *\n * function startSound() {\n * // see also: userStartAudio();\n * osc.start();\n *\n * midiVal = midiNotes[noteIndex % midiNotes.length];\n * freq = midiToFreq(midiVal);\n * osc.freq(freq);\n * env.ramp(osc, 0, 1.0, 0);\n *\n * noteIndex++;\n * }\n *
\n */\nexport var midiToFreq = (p5.prototype.midiToFreq = function (m) {\n return 440 * Math.pow(2, (m - 69) / 12.0);\n});\n\n// This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\nexport var noteToFreq = function (note) {\n if (typeof note !== 'string') {\n return note;\n }\n var wholeNotes = { A: 21, B: 23, C: 24, D: 26, E: 28, F: 29, G: 31 };\n var value = wholeNotes[note[0].toUpperCase()];\n var octave = ~~note.slice(-1);\n value += 12 * (octave - 1);\n\n switch (note[1]) {\n case '#':\n value += 1;\n break;\n case 'b':\n value -= 1;\n break;\n default:\n break;\n }\n return midiToFreq(value);\n};\n\n/**\n * List the SoundFile formats that you will include. LoadSound\n * will search your directory for these extensions, and will pick\n * a format that is compatable with the client's web browser.\n * Here is a free online file\n * converter.\n *\n * @method soundFormats\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\n * @example\n *
\n * function preload() {\n * // set the global sound formats\n * soundFormats('mp3', 'ogg');\n *\n * // load either beatbox.mp3, or .ogg, depending on browser\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('sound loaded! tap to play', 10, 20, width - 20);\n * cnv.mousePressed(function() {\n * mySound.play();\n * });\n * }\n *
\n */\np5.prototype.soundFormats = function () {\n // reset extensions array\n p5sound.extensions = [];\n // add extensions\n for (var i = 0; i < arguments.length; i++) {\n arguments[i] = arguments[i].toLowerCase();\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\n p5sound.extensions.push(arguments[i]);\n } else {\n throw arguments[i] + ' is not a valid sound format!';\n }\n }\n};\n\np5.prototype.disposeSound = function () {\n for (var i = 0; i < p5sound.soundArray.length; i++) {\n p5sound.soundArray[i].dispose();\n }\n};\n\n// register removeSound to dispose of p5sound SoundFiles, Convolvers,\n// Oscillators etc when sketch ends\np5.prototype.registerMethod('remove', p5.prototype.disposeSound);\n\np5.prototype._checkFileFormats = function (paths) {\n var path;\n // if path is a single string, check to see if extension is provided\n if (typeof paths === 'string') {\n path = paths;\n // see if extension is provided\n var extTest = path.split('.').pop();\n // if an extension is provided...\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\n if (!p5.prototype.isFileSupported(extTest)) {\n var pathSplit = path.split('.');\n var pathCore = pathSplit[pathSplit.length - 1];\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n pathCore = '';\n if (pathSplit.length === 2) {\n pathCore += pathSplit[0];\n }\n for (let i = 1; i <= pathSplit.length - 2; i++) {\n var p = pathSplit[i];\n pathCore += '.' + p;\n }\n path = pathCore += '.';\n path = path += extension;\n break;\n }\n }\n }\n }\n // if no extension is provided...\n else {\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n path = path + '.' + extension;\n break;\n }\n }\n }\n } // end 'if string'\n\n // path can either be a single string, or an array\n else if (typeof paths === 'object') {\n for (var i = 0; i < paths.length; i++) {\n var extension = paths[i].split('.').pop();\n var supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n // console.log('.'+extension + ' is ' + supported +\n // ' supported by your browser.');\n path = paths[i];\n break;\n }\n }\n }\n return path;\n};\n\n/**\n * Used by Osc and Envelope to chain signal math\n */\np5.prototype._mathChain = function (o, math, thisChain, nextChain, type) {\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n o.mathOps[i].dispose();\n thisChain = i;\n if (thisChain < o.mathOps.length - 1) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n o.mathOps[thisChain - 1].disconnect();\n o.mathOps[thisChain - 1].connect(math);\n math.connect(nextChain);\n o.mathOps[thisChain] = math;\n return o;\n};\n\n// helper methods to convert audio file as .wav format,\n// will use as saving .wav file and saving blob object\n// Thank you to Matt Diamond's RecorderJS (MIT License)\n// https://github.com/mattdiamond/Recorderjs\nexport function convertToWav(audioBuffer) {\n var leftChannel, rightChannel;\n leftChannel = audioBuffer.getChannelData(0);\n\n // handle mono files\n if (audioBuffer.numberOfChannels > 1) {\n rightChannel = audioBuffer.getChannelData(1);\n } else {\n rightChannel = leftChannel;\n }\n\n var interleaved = interleave(leftChannel, rightChannel);\n\n // create the buffer and view to create the .WAV file\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\n var view = new window.DataView(buffer);\n\n // write the WAV container,\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\n\n // RIFF chunk descriptor\n writeUTFBytes(view, 0, 'RIFF');\n view.setUint32(4, 36 + interleaved.length * 2, true);\n writeUTFBytes(view, 8, 'WAVE');\n // FMT sub-chunk\n writeUTFBytes(view, 12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n // stereo (2 channels)\n view.setUint16(22, 2, true);\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\n view.setUint16(32, 4, true);\n view.setUint16(34, 16, true);\n // data sub-chunk\n writeUTFBytes(view, 36, 'data');\n view.setUint32(40, interleaved.length * 2, true);\n\n // write the PCM samples\n var lng = interleaved.length;\n var index = 44;\n var volume = 1;\n for (var i = 0; i < lng; i++) {\n view.setInt16(index, interleaved[i] * (0x7fff * volume), true);\n index += 2;\n }\n\n return view;\n}\n\n// helper methods to save waves\nfunction interleave(leftChannel, rightChannel) {\n var length = leftChannel.length + rightChannel.length;\n var result = new Float32Array(length);\n\n var inputIndex = 0;\n\n for (var index = 0; index < length; ) {\n result[index++] = leftChannel[inputIndex];\n result[index++] = rightChannel[inputIndex];\n inputIndex++;\n }\n return result;\n}\n\nfunction writeUTFBytes(view, offset, string) {\n var lng = string.length;\n for (var i = 0; i < lng; i++) {\n view.setUint8(offset + i, string.charCodeAt(i));\n }\n}\n\nexport function safeBufferSize(idealBufferSize) {\n let bufferSize = idealBufferSize;\n\n // if the AudioWorkletNode is actually a ScriptProcessorNode created via polyfill,\n // make sure that our chosen buffer size isn't smaller than the buffer size automatically\n // selected by the polyfill\n // reference: https://github.com/GoogleChromeLabs/audioworklet-polyfill/issues/13#issuecomment-425014930\n let tempAudioWorkletNode = new AudioWorkletNode(\n p5sound.audiocontext,\n processorNames.soundFileProcessor\n );\n if (tempAudioWorkletNode instanceof ScriptProcessorNode) {\n bufferSize = tempAudioWorkletNode.bufferSize;\n }\n tempAudioWorkletNode.disconnect();\n tempAudioWorkletNode = null;\n\n return bufferSize;\n}\n\n// export default {\n// // convertToWav: convertToWav,\n// // midiToFreq: midiToFreq,\n// // noteToFreq: noteToFreq,\n// // safeBufferSize: safeBufferSize\n// };\n","/*\n Helper function to generate an error\n with a custom stack trace that points to the sketch\n and removes other parts of the stack trace.\n\n @private\n @class customError\n @constructor\n @param {String} name custom error name\n @param {String} errorTrace custom error trace\n @param {String} failedPath path to the file that failed to load\n @property {String} name custom error name\n @property {String} message custom error message\n @property {String} stack trace the error back to a line in the user's sketch.\n Note: this edits out stack trace within p5.js and p5.sound.\n @property {String} originalStack unedited, original stack trace\n @property {String} failedPath path to the file that failed to load\n @return {Error} returns a custom Error object\n */\nvar CustomError = function (name, errorTrace, failedPath) {\n var err = new Error();\n var tempStack, splitStack;\n\n err.name = name;\n err.originalStack = err.stack + errorTrace;\n tempStack = err.stack + errorTrace;\n err.failedPath = failedPath;\n\n // only print the part of the stack trace that refers to the user code:\n splitStack = tempStack.split('\\n').filter(function (ln) {\n return !ln.match(/(p5.|native code|globalInit)/g);\n });\n err.stack = splitStack.join('\\n');\n\n return err; // TODO: is this really a constructor?\n};\nexport default CustomError;\n","import p5sound from '../master.js'\nconst moduleSources = [\n require('raw-loader!./recorderProcessor').default,\n require('raw-loader!./soundFileProcessor').default,\n require('raw-loader!./amplitudeProcessor').default,\n];\nconst ac = p5sound.audiocontext;\n\nlet initializedAudioWorklets = false;\n\nfunction loadAudioWorkletModules() {\n return Promise.all(\n moduleSources.map(function (moduleSrc) {\n const blob = new Blob([moduleSrc], { type: 'application/javascript' });\n const objectURL = URL.createObjectURL(blob);\n return ac.audioWorklet.addModule(objectURL);\n })\n );\n}\n\np5.prototype.registerMethod('init', function () {\n if (initializedAudioWorklets) return;\n // ensure that a preload function exists so that p5 will wait for preloads to finish\n if (!this.preload && !window.preload) {\n this.preload = function () {};\n }\n\n // use p5's preload system to load necessary AudioWorklet modules before setup()\n this._incrementPreload();\n const onWorkletModulesLoad = function () {\n initializedAudioWorklets = true;\n this._decrementPreload();\n }.bind(this);\n loadAudioWorkletModules().then(onWorkletModulesLoad);\n});\n","import p5sound from './master';\nvar ac = p5sound.audiocontext;\n\n// Stereo panner\n// if there is a stereo panner node use it\nif (typeof ac.createStereoPanner !== 'undefined') {\n p5.Panner = function (input, output) {\n this.stereoPanner = this.input = ac.createStereoPanner();\n input.connect(this.stereoPanner);\n this.stereoPanner.connect(output);\n };\n\n p5.Panner.prototype.pan = function (val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\n };\n\n //not implemented because stereopanner\n //node does not require this and will automatically\n //convert single channel or multichannel to stereo.\n //tested with single and stereo, not with (>2) multichannel\n p5.Panner.prototype.inputChannels = function () {};\n\n p5.Panner.prototype.connect = function (obj) {\n this.stereoPanner.connect(obj);\n };\n\n p5.Panner.prototype.disconnect = function () {\n if (this.stereoPanner) {\n this.stereoPanner.disconnect();\n }\n };\n} else {\n // if there is no createStereoPanner object\n // such as in safari 7.1.7 at the time of writing this\n // use this method to create the effect\n p5.Panner = function (input, output, numInputChannels) {\n this.input = ac.createGain();\n input.connect(this.input);\n\n this.left = ac.createGain();\n this.right = ac.createGain();\n this.left.channelInterpretation = 'discrete';\n this.right.channelInterpretation = 'discrete';\n\n // if input is stereo\n if (numInputChannels > 1) {\n this.splitter = ac.createChannelSplitter(2);\n this.input.connect(this.splitter);\n\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n } else {\n this.input.connect(this.left);\n this.input.connect(this.right);\n }\n\n this.output = ac.createChannelMerger(2);\n this.left.connect(this.output, 0, 1);\n this.right.connect(this.output, 0, 0);\n this.output.connect(output);\n };\n\n // -1 is left, +1 is right\n p5.Panner.prototype.pan = function (val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n var v = (val + 1) / 2;\n var rightVal = Math.cos((v * Math.PI) / 2);\n var leftVal = Math.sin((v * Math.PI) / 2);\n this.left.gain.linearRampToValueAtTime(leftVal, t);\n this.right.gain.linearRampToValueAtTime(rightVal, t);\n };\n\n p5.Panner.prototype.inputChannels = function (numChannels) {\n if (numChannels === 1) {\n this.input.disconnect();\n this.input.connect(this.left);\n this.input.connect(this.right);\n } else if (numChannels === 2) {\n if (typeof this.splitter === 'undefined') {\n this.splitter = ac.createChannelSplitter(2);\n }\n this.input.disconnect();\n this.input.connect(this.splitter);\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n }\n };\n\n p5.Panner.prototype.connect = function (obj) {\n this.output.connect(obj);\n };\n\n p5.Panner.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n };\n}\n","import CustomError from './errorHandler';\nimport p5sound from './master';\nimport { midiToFreq, convertToWav, safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\nconst ac = p5sound.audiocontext;\n\n/**\n *

SoundFile object with a path to a file.

\n *\n *

The p5.SoundFile may not be available immediately because\n * it loads the file information asynchronously.

\n *\n *

To do something with the sound as soon as it loads\n * pass the name of a function as the second parameter.

\n *\n *

Only one file path is required. However, audio file formats\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\n * web browsers. If you want to ensure compatability, instead of a single\n * file path, you may include an Array of filepaths, and the browser will\n * choose a format that works.

\n *\n * @class p5.SoundFile\n * @constructor\n * @param {String|Array} path path to a sound file (String). Optionally,\n * you may include multiple file formats in\n * an array. Alternately, accepts an object\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if file fails to\n * load. This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\n * is loading. That function will\n * receive progress of the request to\n * load the sound file\n * (between 0 and 1) as its first\n * parameter. This progress\n * does not account for the additional\n * time needed to decode the audio data.\n *\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\np5.SoundFile = function (paths, onload, onerror, whileLoading) {\n if (typeof paths !== 'undefined') {\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\n var path = p5.prototype._checkFileFormats(paths);\n this.url = path;\n } else if (typeof paths === 'object') {\n if (\n !(window.File && window.FileReader && window.FileList && window.Blob)\n ) {\n // The File API isn't supported in this browser\n throw 'Unable to load file because the File API is not supported';\n }\n }\n\n // if type is a p5.File...get the actual file\n if (paths.file) {\n paths = paths.file;\n }\n\n this.file = paths;\n }\n\n // private _onended callback, set by the method: onended(callback)\n this._onended = function () {};\n\n this._looping = false;\n this._playing = false;\n this._paused = false;\n this._pauseTime = 0;\n\n // cues for scheduling events with addCue() removeCue()\n this._cues = [];\n this._cueIDCounter = 0;\n\n // position of the most recently played sample\n this._lastPos = 0;\n this._counterNode = null;\n this._workletNode = null;\n\n // array of sources so that they can all be stopped!\n this.bufferSourceNodes = [];\n\n // current source\n this.bufferSourceNode = null;\n\n this.buffer = null;\n this.playbackRate = 1;\n\n this.input = p5sound.audiocontext.createGain();\n this.output = p5sound.audiocontext.createGain();\n\n this.reversed = false;\n\n // start and end of playback / loop\n this.startTime = 0;\n this.endTime = null;\n this.pauseTime = 0;\n\n // \"restart\" would stop playback before retriggering\n this.mode = 'sustain';\n\n // time that playback was started, in millis\n this.startMillis = null;\n\n // stereo panning\n this.panPosition = 0.0;\n this.panner = new p5.Panner(this.output, p5sound.input, 2);\n\n // it is possible to instantiate a soundfile with no path\n if (this.url || this.file) {\n this.load(onload, onerror);\n }\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n\n if (typeof whileLoading === 'function') {\n this._whileLoading = whileLoading;\n } else {\n this._whileLoading = function () {};\n }\n\n this._clearOnEnd = _clearOnEnd.bind(this);\n};\n\n// register preload handling of loadSound\np5.prototype.registerPreloadMethod('loadSound', p5.prototype);\n\n/**\n * loadSound() returns a new p5.SoundFile from a specified\n * path. If called during preload(), the p5.SoundFile will be ready\n * to play in time for setup() and draw(). If called outside of\n * preload, the p5.SoundFile will not be ready immediately, so\n * loadSound accepts a callback as the second parameter. Using a\n * \n * local server is recommended when loading external files.\n *\n * @method loadSound\n * @for p5\n * @param {String|Array} path Path to the sound file, or an array with\n * paths to soundfiles in multiple formats\n * i.e. ['sound.ogg', 'sound.mp3'].\n * Alternately, accepts an object: either\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is\n * an error loading the file.\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\n * This function will receive the percentage loaded\n * so far, from 0.0 to 1.0.\n * @return {SoundFile} Returns a p5.SoundFile\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\np5.prototype.loadSound = function (path, callback, onerror, whileLoading) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n window.alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n\n var self = this;\n var s = new p5.SoundFile(\n path,\n function () {\n if (typeof callback === 'function') {\n callback.apply(self, arguments);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n onerror,\n whileLoading\n );\n\n return s;\n};\n\n/**\n * This is a helper function that the p5.SoundFile calls to load\n * itself. Accepts a callback (the name of another function)\n * as an optional parameter.\n *\n * @private\n * @for p5.SoundFile\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is an error\n */\np5.SoundFile.prototype.load = function (callback, errorCallback) {\n var self = this;\n var errorTrace = new Error().stack;\n\n if (this.url !== undefined && this.url !== '') {\n var request = new XMLHttpRequest();\n request.addEventListener(\n 'progress',\n function (evt) {\n self._updateProgress(evt);\n },\n false\n );\n request.open('GET', this.url, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on sucess loading file:\n if (!self.panner) return;\n ac.decodeAudioData(\n request.response,\n // success decoding buffer:\n function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n if (!self.panner) return;\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n if (!self.panner) return;\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n };\n\n request.send();\n } else if (this.file !== undefined) {\n var reader = new FileReader();\n reader.onload = function () {\n if (!self.panner) return;\n ac.decodeAudioData(reader.result, function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n });\n };\n reader.onerror = function (e) {\n if (!self.panner) return;\n if (onerror) {\n onerror(e);\n }\n };\n reader.readAsArrayBuffer(this.file);\n }\n};\n\n// TO DO: use this method to create a loading bar that shows progress during file upload/decode.\np5.SoundFile.prototype._updateProgress = function (evt) {\n if (evt.lengthComputable) {\n var percentComplete = (evt.loaded / evt.total) * 0.99;\n this._whileLoading(percentComplete, evt);\n // ...\n } else {\n // Unable to compute progress information since the total size is unknown\n this._whileLoading('size unknown');\n }\n};\n\n/**\n * Returns true if the sound file finished loading successfully.\n *\n * @method isLoaded\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isLoaded = function () {\n if (this.buffer) {\n return true;\n } else {\n return false;\n }\n};\n\n/**\n * Play the p5.SoundFile\n *\n * @method play\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) amplitude (volume)\n * of playback\n * @param {Number} [cueStart] (optional) cue start time in seconds\n * @param {Number} [duration] (optional) duration of playback in seconds\n */\np5.SoundFile.prototype.play = function (\n startTime,\n rate,\n amp,\n _cueStart,\n duration\n) {\n if (!this.output) {\n console.warn('SoundFile.play() called after dispose');\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var cueStart, cueEnd;\n var time = startTime || 0;\n if (time < 0) {\n time = 0;\n }\n\n time = time + now;\n\n if (typeof rate !== 'undefined') {\n this.rate(rate);\n }\n\n if (typeof amp !== 'undefined') {\n this.setVolume(amp);\n }\n\n // TO DO: if already playing, create array of buffers for easy stop()\n if (this.buffer) {\n // reset the pause time (if it was paused)\n this._pauseTime = 0;\n\n // handle restart playmode\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\n this.bufferSourceNode.stop(time);\n this._counterNode.stop(time);\n }\n\n //dont create another instance if already playing\n if (this.mode === 'untildone' && this.isPlaying()) {\n return;\n }\n // make a new source and counter. They are automatically assigned playbackRate and buffer\n this.bufferSourceNode = this._initSourceNode();\n\n // garbage collect counterNode and create a new one\n delete this._counterNode;\n this._counterNode = this._initCounterNode();\n\n if (_cueStart) {\n if (_cueStart >= 0 && _cueStart < this.buffer.duration) {\n // this.startTime = cueStart;\n cueStart = _cueStart;\n } else {\n throw 'start time out of range';\n }\n } else {\n cueStart = 0;\n }\n\n if (duration) {\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\n duration =\n duration <= this.buffer.duration - cueStart\n ? duration\n : this.buffer.duration;\n }\n\n // if it was paused, play at the pause position\n if (this._paused) {\n this.bufferSourceNode.start(time, this.pauseTime, duration);\n this._counterNode.start(time, this.pauseTime, duration);\n } else {\n this.bufferSourceNode.start(time, cueStart, duration);\n this._counterNode.start(time, cueStart, duration);\n }\n\n this._playing = true;\n this._paused = false;\n\n // add source to sources array, which is used in stopAll()\n this.bufferSourceNodes.push(this.bufferSourceNode);\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\n\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\n }\n // If soundFile hasn't loaded the buffer yet, throw an error\n else {\n throw 'not ready to play file, buffer has yet to load. Try preload()';\n }\n\n // if looping, will restart at original time\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n\n if (this._looping === true) {\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\n this.bufferSourceNode.loopStart = cueStart;\n this.bufferSourceNode.loopEnd = cueEnd;\n this._counterNode.loopStart = cueStart;\n this._counterNode.loopEnd = cueEnd;\n }\n};\n\n/**\n * p5.SoundFile has two play modes: restart and\n * sustain. Play Mode determines what happens to a\n * p5.SoundFile if it is triggered while in the middle of playback.\n * In sustain mode, playback will continue simultaneous to the\n * new playback. In restart mode, play() will stop playback\n * and start over. With untilDone, a sound will play only if it's\n * not already playing. Sustain is the default mode.\n *\n * @method playMode\n * @for p5.SoundFile\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\n * @example\n *
\n * let mySound;\n * function preload(){\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * noFill();\n * rect(0, height/2, width - 1, height/2 - 1);\n * rect(0, 0, width - 1, height/2);\n * textAlign(CENTER, CENTER);\n * fill(20);\n * text('restart', width/2, 1 * height/4);\n * text('sustain', width/2, 3 * height/4);\n * }\n * function canvasPressed() {\n * if (mouseX < height/2) {\n * mySound.playMode('restart');\n * } else {\n * mySound.playMode('sustain');\n * }\n * mySound.play();\n * }\n *\n *
\n */\np5.SoundFile.prototype.playMode = function (str) {\n var s = str.toLowerCase();\n\n // if restart, stop all other sounds from playing\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNodes[i].stop(now);\n }\n }\n\n // set play mode to effect future playback\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\n this.mode = s;\n } else {\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\n }\n};\n\n/**\n * Pauses a file that is currently playing. If the file is not\n * playing, then nothing will happen.\n *\n * After pausing, .play() will resume from the paused\n * position.\n * If p5.SoundFile had been set to loop before it was paused,\n * it will continue to loop after it is unpaused with .play().\n *\n * @method pause\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @example\n *
\n * let soundFile;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\np5.SoundFile.prototype.pause = function (startTime) {\n var now = p5sound.audiocontext.currentTime;\n var time = startTime || 0;\n var pTime = time + now;\n\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\n this._paused = true;\n this._playing = false;\n\n this.pauseTime = this.currentTime();\n this.bufferSourceNode.stop(pTime);\n this._counterNode.stop(pTime);\n\n this._pauseTime = this.currentTime();\n // TO DO: make sure play() still starts from orig start position\n } else {\n this._pauseTime = 0;\n }\n};\n\n/**\n * Loop the p5.SoundFile. Accepts optional parameters to set the\n * playback rate, playback volume, loopStart, loopEnd.\n *\n * @method loop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) playback volume\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\n * @param {Number} [duration] (optional) loop duration in seconds\n * @example\n *
\n * let soundFile;\n * let loopStart = 0.5;\n * let loopDuration = 0.2;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\np5.SoundFile.prototype.loop = function (\n startTime,\n rate,\n amp,\n loopStart,\n duration\n) {\n this._looping = true;\n this.play(startTime, rate, amp, loopStart, duration);\n};\n\n/**\n * Set a p5.SoundFile's looping flag to true or false. If the sound\n * is currently playing, this change will take effect when it\n * reaches the end of the current playback.\n *\n * @method setLoop\n * @for p5.SoundFile\n * @param {Boolean} Boolean set looping to true or false\n */\np5.SoundFile.prototype.setLoop = function (bool) {\n if (bool === true) {\n this._looping = true;\n } else if (bool === false) {\n this._looping = false;\n } else {\n throw 'Error: setLoop accepts either true or false';\n }\n if (this.bufferSourceNode) {\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n }\n};\n\n/**\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\n *\n * @method isLooping\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isLooping = function () {\n if (!this.bufferSourceNode) {\n return false;\n }\n if (this._looping === true && this.isPlaying() === true) {\n return true;\n }\n return false;\n};\n\n/**\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\n * paused or stopped).\n *\n * @method isPlaying\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isPlaying = function () {\n return this._playing;\n};\n\n/**\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\n * playing or stopped).\n *\n * @method isPaused\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isPaused = function () {\n return this._paused;\n};\n\n/**\n * Stop soundfile playback.\n *\n * @method stop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * in seconds from now\n */\np5.SoundFile.prototype.stop = function (timeFromNow) {\n var time = timeFromNow || 0;\n\n if (this.mode === 'sustain' || this.mode === 'untildone') {\n this.stopAll(time);\n this._playing = false;\n this.pauseTime = 0;\n this._paused = false;\n } else if (this.buffer && this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n this.pauseTime = 0;\n this.bufferSourceNode.stop(now + t);\n this._counterNode.stop(now + t);\n this._playing = false;\n this._paused = false;\n }\n};\n\n/**\n * Stop playback on all of this soundfile's sources.\n * @private\n */\np5.SoundFile.prototype.stopAll = function (_time) {\n var now = p5sound.audiocontext.currentTime;\n var time = _time || 0;\n if (this.buffer && this.bufferSourceNode) {\n for (var i in this.bufferSourceNodes) {\n const bufferSourceNode = this.bufferSourceNodes[i];\n if (bufferSourceNode) {\n try {\n bufferSourceNode.stop(now + time);\n } catch (e) {\n // this was throwing errors only on Safari\n }\n }\n }\n this._counterNode.stop(now + time);\n this._onended(this);\n }\n};\n\n/**\n * Multiply the output volume (amplitude) of a sound file\n * between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n * @method setVolume\n * @for p5.SoundFile\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\np5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) {\n if (typeof vol === 'number') {\n var rampTime = _rampTime || 0;\n var tFromNow = _tFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now + tFromNow);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n};\n\n// same as setVolume, to match Processing Sound\np5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;\n\n// these are the same thing\np5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;\n\np5.SoundFile.prototype.getVolume = function () {\n return this.output.gain.value;\n};\n\n/**\n * Set the stereo panning of a p5.sound object to\n * a floating point number between -1.0 (left) and 1.0 (right).\n * Default is 0.0 (center).\n *\n * @method pan\n * @for p5.SoundFile\n * @param {Number} [panValue] Set the stereo panner\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @example\n *
\n * let ballX = 0;\n * let soundFile;\n *\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/beatbox.mp3');\n * }\n *\n * function draw() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * ballX = constrain(mouseX, 0, width);\n * ellipse(ballX, height/2, 20, 20);\n * }\n *\n * function canvasPressed(){\n * // map the ball's x location to a panning degree\n * // between -1.0 (left) and 1.0 (right)\n * let panning = map(ballX, 0., width,-1.0, 1.0);\n * soundFile.pan(panning);\n * soundFile.play();\n * }\n *
\n */\np5.SoundFile.prototype.pan = function (pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n};\n\n/**\n * Returns the current stereo pan position (-1.0 to 1.0)\n *\n * @method getPan\n * @for p5.SoundFile\n * @return {Number} Returns the stereo pan setting of the Oscillator\n * as a number between -1.0 (left) and 1.0 (right).\n * 0.0 is center and default.\n */\np5.SoundFile.prototype.getPan = function () {\n return this.panPosition;\n};\n\n/**\n * Set the playback rate of a sound file. Will change the speed and the pitch.\n * Values less than zero will reverse the audio buffer.\n *\n * @method rate\n * @for p5.SoundFile\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\n * .5 is half-speed, 2.0 is twice as fast.\n * Values less than zero play backwards.\n * @example\n *
\n * let mySound;\n *\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * }\n * function canvasPressed() {\n * mySound.loop();\n * }\n * function mouseReleased() {\n * mySound.pause();\n * }\n * function draw() {\n * background(220);\n *\n * // Set the rate to a range between 0.1 and 4\n * // Changing the rate also alters the pitch\n * let playbackRate = map(mouseY, 0.1, height, 2, 0);\n * playbackRate = constrain(playbackRate, 0.01, 4);\n * mySound.rate(playbackRate);\n *\n * line(0, mouseY, width, mouseY);\n * text('rate: ' + round(playbackRate * 100) + '%', 10, 20);\n * }\n *\n * \n *
\n *\n */\np5.SoundFile.prototype.rate = function (playbackRate) {\n var reverse = false;\n if (typeof playbackRate === 'undefined') {\n return this.playbackRate;\n }\n\n this.playbackRate = playbackRate;\n\n if (playbackRate === 0) {\n playbackRate = 0.0000000000001;\n } else if (playbackRate < 0 && !this.reversed) {\n playbackRate = Math.abs(playbackRate);\n reverse = true;\n } else if (playbackRate > 0 && this.reversed) {\n reverse = true;\n }\n\n if (this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n this._counterNode.playbackRate.cancelScheduledValues(now);\n this._counterNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n }\n\n if (reverse) {\n this.reverseBuffer();\n }\n return this.playbackRate;\n};\n\n// TO DO: document this\np5.SoundFile.prototype.setPitch = function (num) {\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\n this.rate(newPlaybackRate);\n};\n\np5.SoundFile.prototype.getPlaybackRate = function () {\n return this.playbackRate;\n};\n\n/**\n * Returns the duration of a sound file in seconds.\n *\n * @method duration\n * @for p5.SoundFile\n * @return {Number} The duration of the soundFile in seconds.\n */\np5.SoundFile.prototype.duration = function () {\n // Return Duration\n if (this.buffer) {\n return this.buffer.duration;\n } else {\n return 0;\n }\n};\n\n/**\n * Return the current position of the p5.SoundFile playhead, in seconds.\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\n * has been called, currentTime will count backwards.\n *\n * @method currentTime\n * @for p5.SoundFile\n * @return {Number} currentTime of the soundFile in seconds.\n */\np5.SoundFile.prototype.currentTime = function () {\n return this.reversed\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\n : this._lastPos / ac.sampleRate;\n};\n\n/**\n * Move the playhead of a soundfile that is currently playing to a\n * new position and a new duration, in seconds.\n * If none are given, will reset the file to play entire duration\n * from start to finish. To set the position of a soundfile that is\n * not currently playing, use the `play` or `loop` methods.\n *\n * @method jump\n * @for p5.SoundFile\n * @param {Number} cueTime cueTime of the soundFile in seconds.\n * @param {Number} duration duration in seconds.\n */\np5.SoundFile.prototype.jump = function (cueTime, duration) {\n if (cueTime < 0 || cueTime > this.buffer.duration) {\n throw 'jump time out of range';\n }\n if (duration > this.buffer.duration - cueTime) {\n throw 'end time out of range';\n }\n\n var cTime = cueTime || 0;\n var dur = duration || undefined;\n if (this.isPlaying()) {\n this.stop(0);\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\n }\n};\n\n/**\n * Return the number of channels in a sound file.\n * For example, Mono = 1, Stereo = 2.\n *\n * @method channels\n * @for p5.SoundFile\n * @return {Number} [channels]\n */\np5.SoundFile.prototype.channels = function () {\n return this.buffer.numberOfChannels;\n};\n\n/**\n * Return the sample rate of the sound file.\n *\n * @method sampleRate\n * @for p5.SoundFile\n * @return {Number} [sampleRate]\n */\np5.SoundFile.prototype.sampleRate = function () {\n return this.buffer.sampleRate;\n};\n\n/**\n * Return the number of samples in a sound file.\n * Equal to sampleRate * duration.\n *\n * @method frames\n * @for p5.SoundFile\n * @return {Number} [sampleCount]\n */\np5.SoundFile.prototype.frames = function () {\n return this.buffer.length;\n};\n\n/**\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\n * used to draw a static waveform. Scans through the p5.SoundFile's\n * audio buffer to find the greatest amplitudes. Accepts one\n * parameter, 'length', which determines size of the array.\n * Larger arrays result in more precise waveform visualizations.\n *\n * Inspired by Wavesurfer.js.\n *\n * @method getPeaks\n * @for p5.SoundFile\n * @params {Number} [length] length is the size of the returned array.\n * Larger length results in more precision.\n * Defaults to 5*width of the browser window.\n * @returns {Float32Array} Array of peaks.\n */\np5.SoundFile.prototype.getPeaks = function (length) {\n if (this.buffer) {\n // set length to window's width if no length is provided\n if (!length) {\n length = window.width * 5;\n }\n if (this.buffer) {\n var buffer = this.buffer;\n var sampleSize = buffer.length / length;\n var sampleStep = ~~(sampleSize / 10) || 1;\n var channels = buffer.numberOfChannels;\n var peaks = new Float32Array(Math.round(length));\n\n for (var c = 0; c < channels; c++) {\n var chan = buffer.getChannelData(c);\n for (var i = 0; i < length; i++) {\n var start = ~~(i * sampleSize);\n var end = ~~(start + sampleSize);\n var max = 0;\n for (var j = start; j < end; j += sampleStep) {\n var value = chan[j];\n if (value > max) {\n max = value;\n // faster than Math.abs\n } else if (-value > max) {\n max = value;\n }\n }\n if (c === 0 || Math.abs(max) > peaks[i]) {\n peaks[i] = max;\n }\n }\n }\n\n return peaks;\n }\n } else {\n throw 'Cannot load peaks yet, buffer is not loaded';\n }\n};\n\n/**\n * Reverses the p5.SoundFile's buffer source.\n * Playback must be handled separately (see example).\n *\n * @method reverseBuffer\n * @for p5.SoundFile\n * @example\n *
\n * let drum;\n * function preload() {\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function canvasPressed() {\n * drum.stop();\n * drum.reverseBuffer();\n * drum.play();\n * }\n * \n *
\n */\np5.SoundFile.prototype.reverseBuffer = function () {\n if (this.buffer) {\n var currentPos = this._lastPos / ac.sampleRate;\n var curVol = this.getVolume();\n this.setVolume(0, 0.001);\n\n const numChannels = this.buffer.numberOfChannels;\n for (var i = 0; i < numChannels; i++) {\n this.buffer.getChannelData(i).reverse();\n }\n // set reversed flag\n this.reversed = !this.reversed;\n\n if (this.isPlaying() && currentPos) {\n this.jump(this.duration() - currentPos);\n }\n this.setVolume(curVol, 0.001);\n } else {\n throw 'SoundFile is not done loading';\n }\n};\n\n/**\n * Schedule an event to be called when the soundfile\n * reaches the end of a buffer. If the soundfile is\n * playing through once, this will be called when it\n * ends. If it is looping, it will be called when\n * stop is called.\n *\n * @method onended\n * @for p5.SoundFile\n * @param {Function} callback function to call when the\n * soundfile has ended.\n */\np5.SoundFile.prototype.onended = function (callback) {\n this._onended = callback;\n return this;\n};\n\np5.SoundFile.prototype.add = function () {\n // TO DO\n};\n\np5.SoundFile.prototype.dispose = function () {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference to soundfile\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop(now);\n if (this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n if (this.bufferSourceNodes[i] !== null) {\n this.bufferSourceNodes[i].disconnect();\n try {\n this.bufferSourceNodes[i].stop(now);\n } catch (e) {\n console.warn('no buffer source node to dispose');\n }\n this.bufferSourceNodes[i] = null;\n }\n }\n if (this.isPlaying()) {\n try {\n this._counterNode.stop(now);\n } catch (e) {\n console.log(e);\n }\n this._counterNode = null;\n }\n }\n if (this.output) {\n this.output.disconnect();\n this.output = null;\n }\n if (this.panner) {\n this.panner.disconnect();\n this.panner = null;\n }\n};\n\n/**\n * Connects the output of a p5sound object to input of another\n * p5.sound object. For example, you may connect a p5.SoundFile to an\n * FFT or an Effect. If no parameter is given, it will connect to\n * the master output. Most p5sound objects connect to the master\n * output when they are created.\n *\n * @method connect\n * @for p5.SoundFile\n * @param {Object} [object] Audio object that accepts an input\n */\np5.SoundFile.prototype.connect = function (unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else {\n if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n } else {\n this.panner.connect(unit);\n }\n }\n};\n\n/**\n * Disconnects the output of this p5sound object.\n *\n * @method disconnect\n * @for p5.SoundFile\n */\np5.SoundFile.prototype.disconnect = function () {\n if (this.panner) {\n this.panner.disconnect();\n }\n};\n\n/**\n */\np5.SoundFile.prototype.getLevel = function () {\n console.warn(\n 'p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'\n );\n};\n\n/**\n * Reset the source for this SoundFile to a\n * new path (URL).\n *\n * @method setPath\n * @for p5.SoundFile\n * @param {String} path path to audio file\n * @param {Function} callback Callback\n */\np5.SoundFile.prototype.setPath = function (p, callback) {\n var path = p5.prototype._checkFileFormats(p);\n this.url = path;\n this.load(callback);\n};\n\n/**\n * Replace the current Audio Buffer with a new Buffer.\n *\n * @method setBuffer\n * @for p5.SoundFile\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\n * will create a stereo source. 1 will create\n * a mono source.\n */\np5.SoundFile.prototype.setBuffer = function (buf) {\n var numChannels = buf.length;\n var size = buf[0].length;\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\n\n if (!(buf[0] instanceof Float32Array)) {\n buf[0] = new Float32Array(buf[0]);\n }\n\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\n var channel = newBuffer.getChannelData(channelNum);\n channel.set(buf[channelNum]);\n }\n\n this.buffer = newBuffer;\n\n // set numbers of channels on input to the panner\n this.panner.inputChannels(numChannels);\n};\n\n//////////////////////////////////////////////////\n// script processor node with an empty buffer to help\n// keep a sample-accurate position in playback buffer.\n// Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV\n// Copyright [2015] [Sonoport (Asia) Pte. Ltd.],\n// Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0\n////////////////////////////////////////////////////////////////////////////////////\n\nvar _createCounterBuffer = function (buffer) {\n const len = buffer.length;\n const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate);\n const arrayBuffer = audioBuf.getChannelData(0);\n for (var index = 0; index < len; index++) {\n arrayBuffer[index] = index;\n }\n return audioBuf;\n};\n\n// initialize counterNode, set its initial buffer and playbackRate\np5.SoundFile.prototype._initCounterNode = function () {\n var self = this;\n var now = ac.currentTime;\n var cNode = ac.createBufferSource();\n\n const workletBufferSize = safeBufferSize(256);\n\n // dispose of worklet node if it already exists\n if (self._workletNode) {\n self._workletNode.disconnect();\n delete self._workletNode;\n }\n self._workletNode = new AudioWorkletNode(\n ac,\n processorNames.soundFileProcessor,\n {\n processorOptions: { bufferSize: workletBufferSize },\n }\n );\n self._workletNode.port.onmessage = (event) => {\n if (event.data.name === 'position') {\n // event.data.position should only be 0 when paused\n if (event.data.position === 0) {\n return;\n }\n this._lastPos = event.data.position;\n\n // do any callbacks that have been scheduled\n this._onTimeUpdate(self._lastPos);\n }\n };\n\n // create counter buffer of the same length as self.buffer\n cNode.buffer = _createCounterBuffer(self.buffer);\n\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\n\n cNode.connect(self._workletNode);\n self._workletNode.connect(p5.soundOut._silentNode);\n\n return cNode;\n};\n\n// initialize sourceNode, set its initial buffer and playbackRate\np5.SoundFile.prototype._initSourceNode = function () {\n var bufferSourceNode = ac.createBufferSource();\n bufferSourceNode.buffer = this.buffer;\n bufferSourceNode.playbackRate.value = this.playbackRate;\n bufferSourceNode.connect(this.output);\n return bufferSourceNode;\n};\n\n/**\n * processPeaks returns an array of timestamps where it thinks there is a beat.\n *\n * This is an asynchronous function that processes the soundfile in an offline audio context,\n * and sends the results to your callback function.\n *\n * The process involves running the soundfile through a lowpass filter, and finding all of the\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\n *\n * @method processPeaks\n * @for p5.SoundFile\n * @param {Function} callback a function to call once this data is returned\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\n * @return {Array} Array of timestamped peaks\n */\np5.SoundFile.prototype.processPeaks = function (\n callback,\n _initThreshold,\n _minThreshold,\n _minPeaks\n) {\n var bufLen = this.buffer.length;\n var sampleRate = this.buffer.sampleRate;\n var buffer = this.buffer;\n var allPeaks = [];\n\n var initialThreshold = _initThreshold || 0.9,\n threshold = initialThreshold,\n minThreshold = _minThreshold || 0.22,\n minPeaks = _minPeaks || 200;\n\n // Create offline context\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\n\n // create buffer source\n var source = offlineContext.createBufferSource();\n source.buffer = buffer;\n\n // Create filter. TO DO: allow custom setting of filter\n var filter = offlineContext.createBiquadFilter();\n filter.type = 'lowpass';\n source.connect(filter);\n filter.connect(offlineContext.destination);\n\n // start playing at time:0\n source.start(0);\n offlineContext.startRendering(); // Render the song\n\n // act on the result\n offlineContext.oncomplete = function (e) {\n if (!self.panner) return;\n var filteredBuffer = e.renderedBuffer;\n var bufferData = filteredBuffer.getChannelData(0);\n\n // step 1:\n // create Peak instances, add them to array, with strength and sampleIndex\n do {\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\n threshold -= 0.005;\n } while (\n Object.keys(allPeaks).length < minPeaks &&\n threshold >= minThreshold\n );\n\n // step 2:\n // find intervals for each peak in the sampleIndex, add tempos array\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\n\n // step 3: find top tempos\n var groups = groupNeighborsByTempo(\n intervalCounts,\n filteredBuffer.sampleRate\n );\n\n // sort top intervals\n var topTempos = groups\n .sort(function (intA, intB) {\n return intB.count - intA.count;\n })\n .splice(0, 5);\n\n // set this SoundFile's tempo to the top tempo ??\n this.tempo = topTempos[0].tempo;\n\n // step 4:\n // new array of peaks at top tempo within a bpmVariance\n var bpmVariance = 5;\n var tempoPeaks = getPeaksAtTopTempo(\n allPeaks,\n topTempos[0].tempo,\n filteredBuffer.sampleRate,\n bpmVariance\n );\n\n callback(tempoPeaks);\n };\n};\n\n// process peaks\nvar Peak = function (amp, i) {\n this.sampleIndex = i;\n this.amplitude = amp;\n this.tempos = [];\n this.intervals = [];\n};\n\n// 1. for processPeaks() Function to identify peaks above a threshold\n// returns an array of peak indexes as frames (samples) of the original soundfile\nfunction getPeaksAtThreshold(data, threshold) {\n var peaksObj = {};\n var length = data.length;\n\n for (var i = 0; i < length; i++) {\n if (data[i] > threshold) {\n var amp = data[i];\n var peak = new Peak(amp, i);\n peaksObj[i] = peak;\n // Skip forward ~ 1/8s to get past this peak.\n i += 6000;\n }\n i++;\n }\n return peaksObj;\n}\n\n// 2. for processPeaks()\nfunction countIntervalsBetweenNearbyPeaks(peaksObj) {\n var intervalCounts = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n for (var index = 0; index < peaksArray.length; index++) {\n // find intervals in comparison to nearby peaks\n for (var i = 0; i < 10; i++) {\n var startPeak = peaksObj[peaksArray[index]];\n var endPeak = peaksObj[peaksArray[index + i]];\n\n if (startPeak && endPeak) {\n var startPos = startPeak.sampleIndex;\n var endPos = endPeak.sampleIndex;\n var interval = endPos - startPos;\n\n // add a sample interval to the startPeak in the allPeaks array\n if (interval > 0) {\n startPeak.intervals.push(interval);\n }\n\n // tally the intervals and return interval counts\n var foundInterval = intervalCounts.some(function (intervalCount) {\n if (intervalCount.interval === interval) {\n intervalCount.count++;\n return intervalCount;\n }\n });\n\n // store with JSON like formatting\n if (!foundInterval) {\n intervalCounts.push({\n interval: interval,\n count: 1,\n });\n }\n }\n }\n }\n\n return intervalCounts;\n}\n\n// 3. for processPeaks --> find tempo\nfunction groupNeighborsByTempo(intervalCounts, sampleRate) {\n var tempoCounts = [];\n\n intervalCounts.forEach(function (intervalCount) {\n try {\n // Convert an interval to tempo\n var theoreticalTempo = Math.abs(\n 60 / (intervalCount.interval / sampleRate)\n );\n\n theoreticalTempo = mapTempo(theoreticalTempo);\n\n var foundTempo = tempoCounts.some(function (tempoCount) {\n if (tempoCount.tempo === theoreticalTempo)\n return (tempoCount.count += intervalCount.count);\n });\n if (!foundTempo) {\n if (isNaN(theoreticalTempo)) {\n return;\n }\n tempoCounts.push({\n tempo: Math.round(theoreticalTempo),\n count: intervalCount.count,\n });\n }\n } catch (e) {\n throw e;\n }\n });\n\n return tempoCounts;\n}\n\n// 4. for processPeaks - get peaks at top tempo\nfunction getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\n var peaksAtTopTempo = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n // TO DO: filter out peaks that have the tempo and return\n for (var i = 0; i < peaksArray.length; i++) {\n var key = peaksArray[i];\n var peak = peaksObj[key];\n\n for (var j = 0; j < peak.intervals.length; j++) {\n var intervalBPM = Math.round(\n Math.abs(60 / (peak.intervals[j] / sampleRate))\n );\n\n intervalBPM = mapTempo(intervalBPM);\n\n if (Math.abs(intervalBPM - tempo) < bpmVariance) {\n // convert sampleIndex to seconds\n peaksAtTopTempo.push(peak.sampleIndex / sampleRate);\n }\n }\n }\n\n // filter out peaks that are very close to each other\n peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) {\n var dif = arr[index + 1] - peakTime;\n if (dif > 0.01) {\n return true;\n }\n });\n\n return peaksAtTopTempo;\n}\n\n// helper function for processPeaks\nfunction mapTempo(theoreticalTempo) {\n // these scenarios create infinite while loop\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) {\n return;\n }\n\n // Adjust the tempo to fit within the 90-180 BPM range\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\n\n return theoreticalTempo;\n}\n\n/*** SCHEDULE EVENTS ***/\n\n// Cue inspired by JavaScript setTimeout, and the\n// Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\nvar Cue = function (callback, time, id, val) {\n this.callback = callback;\n this.time = time;\n this.id = id;\n this.val = val;\n};\n\n/**\n * Schedule events to trigger every time a MediaElement\n * (audio/video) reaches a playback cue point.\n *\n * Accepts a callback function, a time (in seconds) at which to trigger\n * the callback, and an optional parameter for the callback.\n *\n * Time will be passed as the first parameter to the callback function,\n * and param will be the second parameter.\n *\n *\n * @method addCue\n * @for p5.SoundFile\n * @param {Number} time Time in seconds, relative to this media\n * element's playback. For example, to trigger\n * an event every time playback reaches two\n * seconds, pass in the number 2. This will be\n * passed as the first parameter to\n * the callback function.\n * @param {Function} callback Name of a function that will be\n * called at the given time. The callback will\n * receive time and (optionally) param as its\n * two parameters.\n * @param {Object} [value] An object to be passed as the\n * second parameter to the\n * callback function.\n * @return {Number} id ID of this cue,\n * useful for removeCue(id)\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 10, 20);\n *\n * // schedule calls to changeText\n * mySound.addCue(0, changeText, \"hello\" );\n * mySound.addCue(0.5, changeText, \"hello,\" );\n * mySound.addCue(1, changeText, \"hello, p5!\");\n * mySound.addCue(1.5, changeText, \"hello, p5!!\");\n * mySound.addCue(2, changeText, \"hello, p5!!!!!\");\n * }\n *\n * function changeText(val) {\n * background(220);\n * text(val, 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.play();\n * }\n *
\n */\np5.SoundFile.prototype.addCue = function (time, callback, val) {\n var id = this._cueIDCounter++;\n\n var cue = new Cue(callback, time, id, val);\n this._cues.push(cue);\n\n // if (!this.elt.ontimeupdate) {\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\n // }\n\n return id;\n};\n\n/**\n * Remove a callback based on its ID. The ID is returned by the\n * addCue method.\n *\n * @method removeCue\n * @for p5.SoundFile\n * @param {Number} id ID of the cue, as returned by addCue\n */\np5.SoundFile.prototype.removeCue = function (id) {\n var cueLength = this._cues.length;\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n if (cue.id === id) {\n this._cues.splice(i, 1);\n break;\n }\n }\n\n if (this._cues.length === 0) {\n // TO DO: remove callback\n // this.elt.ontimeupdate = null\n }\n};\n\n/**\n * Remove all of the callbacks that had originally been scheduled\n * via the addCue method.\n *\n * @method clearCues\n */\np5.SoundFile.prototype.clearCues = function () {\n this._cues = [];\n // this.elt.ontimeupdate = null;\n};\n\n// private method that checks for cues to be fired if events\n// have been scheduled using addCue(callback, time).\np5.SoundFile.prototype._onTimeUpdate = function (position) {\n var playbackTime = position / this.buffer.sampleRate;\n var cueLength = this._cues.length;\n\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n var callbackTime = cue.time;\n var val = cue.val;\n var leftLimit = this._prevUpdateTime || 0;\n var rightLimit = playbackTime;\n if (leftLimit <= callbackTime && callbackTime <= rightLimit) {\n // pass the scheduled callbackTime as parameter to the callback\n cue.callback(val);\n }\n }\n\n this._prevUpdateTime = playbackTime;\n};\n\n/**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device. To upload a file to a server, see\n * getBlob\n *\n * @method save\n * @for p5.SoundFile\n * @param {String} [fileName] name of the resulting .wav file.\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to download', 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.save('my cool filename');\n * }\n *
\n */\np5.SoundFile.prototype.save = function (fileName) {\n p5.prototype.saveSound(this, fileName, 'wav');\n};\n\n/**\n * This method is useful for sending a SoundFile to a server. It returns the\n * .wav-encoded audio data as a \"Blob\".\n * A Blob is a file-like data object that can be uploaded to a server\n * with an http request. We'll\n * use the `httpDo` options object to send a POST request with some\n * specific options: we encode the request as `multipart/form-data`,\n * and attach the blob as one of the form values using `FormData`.\n *\n *\n * @method getBlob\n * @for p5.SoundFile\n * @returns {Blob} A file-like data object\n * @example\n *
\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n *\n * function setup() {\n * noCanvas();\n * let soundBlob = mySound.getBlob();\n *\n * // Now we can send the blob to a server...\n * let serverUrl = 'https://jsonplaceholder.typicode.com/posts';\n * let httpRequestOptions = {\n * method: 'POST',\n * body: new FormData().append('soundBlob', soundBlob),\n * headers: new Headers({\n * 'Content-Type': 'multipart/form-data'\n * })\n * };\n * httpDo(serverUrl, httpRequestOptions);\n *\n * // We can also create an `ObjectURL` pointing to the Blob\n * let blobUrl = URL.createObjectURL(soundBlob);\n *\n * // The `
\n */\np5.SoundFile.prototype.getBlob = function () {\n const dataView = convertToWav(this.buffer);\n return new Blob([dataView], { type: 'audio/wav' });\n};\n\n// event handler to remove references to the bufferSourceNode when it is done playing\nfunction _clearOnEnd(e) {\n const thisBufferSourceNode = e.target;\n const soundFile = this;\n\n // delete this.bufferSourceNode from the sources array when it is done playing:\n thisBufferSourceNode._playing = false;\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\n\n // call the onended callback\n soundFile._onended(soundFile);\n\n // delete bufferSourceNode(s) in soundFile.bufferSourceNodes\n // iterate in reverse order because the index changes by splice\n soundFile.bufferSourceNodes\n .map((_, i) => i)\n .reverse()\n .forEach(function (i) {\n const n = soundFile.bufferSourceNodes[i];\n\n if (n._playing === false) {\n soundFile.bufferSourceNodes.splice(i, 1);\n }\n });\n\n if (soundFile.bufferSourceNodes.length === 0) {\n soundFile._playing = false;\n }\n}\n","import p5sound from './master';\nimport { safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\n/**\n * Amplitude measures volume between 0.0 and 1.0.\n * Listens to all p5sound by default, or use setInput()\n * to listen to a specific sound source. Accepts an optional\n * smoothing value, which defaults to 0.\n *\n * @class p5.Amplitude\n * @constructor\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\n * amplitude readings (defaults to 0)\n * @example\n *
\n * let sound, amplitude;\n *\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound() {\n * if (sound.isPlaying() ){\n * sound.stop();\n * } else {\n * sound.play();\n * }\n * }\n *\n *
\n */\np5.Amplitude = function (smoothing) {\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\n this.bufferSize = safeBufferSize(2048);\n\n // set audio context\n this.audiocontext = p5sound.audiocontext;\n this._workletNode = new AudioWorkletNode(\n this.audiocontext,\n processorNames.amplitudeProcessor,\n {\n outputChannelCount: [1],\n\n parameterData: { smoothing: smoothing || 0 },\n processorOptions: {\n normalize: false,\n smoothing: smoothing || 0,\n numInputChannels: 2,\n bufferSize: this.bufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'amplitude') {\n this.volume = event.data.volume;\n this.volNorm = event.data.volNorm;\n this.stereoVol = event.data.stereoVol;\n this.stereoVolNorm = event.data.stereoVolNorm;\n }\n }.bind(this);\n\n // for connections\n this.input = this._workletNode;\n\n this.output = this.audiocontext.createGain();\n\n // the variables to return\n this.volume = 0;\n this.volNorm = 0;\n this.stereoVol = [0, 0];\n this.stereoVolNorm = [0, 0];\n\n this.normalize = false;\n\n this._workletNode.connect(this.output);\n this.output.gain.value = 0;\n\n // this may only be necessary because of a Chrome bug\n this.output.connect(this.audiocontext.destination);\n\n // connect to p5sound master output by default, unless set by input()\n p5sound.meter.connect(this._workletNode);\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Connects to the p5sound instance (master output) by default.\n * Optionally, you can pass in a specific source (i.e. a soundfile).\n *\n * @method setInput\n * @for p5.Amplitude\n * @param {soundObject|undefined} [snd] set the sound source\n * (optional, defaults to\n * master output)\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\n * to smooth amplitude readings\n * @example\n *
\n * function preload(){\n * sound1 = loadSound('assets/beat.mp3');\n * sound2 = loadSound('assets/drum.mp3');\n * }\n * function setup(){\n * cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n *\n * amplitude = new p5.Amplitude();\n * amplitude.setInput(sound2);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound1.isPlaying() && sound2.isPlaying()) {\n * sound1.stop();\n * sound2.stop();\n * } else {\n * sound1.play();\n * sound2.play();\n * }\n * }\n *
\n */\np5.Amplitude.prototype.setInput = function (source, smoothing) {\n p5sound.meter.disconnect();\n\n if (smoothing) {\n this._workletNode.parameters.get('smoothing').value = smoothing;\n }\n\n // connect to the master out of p5s instance if no snd is provided\n if (source == null) {\n console.log(\n 'Amplitude input source is not ready! Connecting to master output instead'\n );\n p5sound.meter.connect(this._workletNode);\n }\n\n // if it is a p5.Signal\n else if (source instanceof p5.Signal) {\n source.output.connect(this._workletNode);\n }\n // connect to the sound if it is available\n else if (source) {\n source.connect(this._workletNode);\n this._workletNode.disconnect();\n this._workletNode.connect(this.output);\n }\n\n // otherwise, connect to the master out of p5s instance (default)\n else {\n p5sound.meter.connect(this._workletNode);\n }\n};\n\np5.Amplitude.prototype.connect = function (unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(this.panner.connect(p5sound.input));\n }\n};\n\np5.Amplitude.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Returns a single Amplitude reading at the moment it is called.\n * For continuous readings, run in the draw loop.\n *\n * @method getLevel\n * @for p5.Amplitude\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\n * @return {Number} Amplitude as a number between 0.0 and 1.0\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220, 150);\n * textAlign(CENTER);\n * text('tap to play', width/2, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound.isPlaying()) {\n * sound.stop();\n * } else {\n * sound.play();\n * }\n * }\n *
\n */\np5.Amplitude.prototype.getLevel = function (channel) {\n if (typeof channel !== 'undefined') {\n if (this.normalize) {\n return this.stereoVolNorm[channel];\n } else {\n return this.stereoVol[channel];\n }\n } else if (this.normalize) {\n return this.volNorm;\n } else {\n return this.volume;\n }\n};\n\n/**\n * Determines whether the results of Amplitude.process() will be\n * Normalized. To normalize, Amplitude finds the difference the\n * loudest reading it has processed and the maximum amplitude of\n * 1.0. Amplitude adds this difference to all values to produce\n * results that will reliably map between 0.0 and 1.0. However,\n * if a louder moment occurs, the amount that Normalize adds to\n * all the values will change. Accepts an optional boolean parameter\n * (true or false). Normalizing is off by default.\n *\n * @method toggleNormalize\n * @for p5.Amplitude\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\n */\np5.Amplitude.prototype.toggleNormalize = function (bool) {\n if (typeof bool === 'boolean') {\n this.normalize = bool;\n } else {\n this.normalize = !this.normalize;\n }\n this._workletNode.port.postMessage({\n name: 'toggleNormalize',\n normalize: this.normalize,\n });\n};\n\n/**\n * Smooth Amplitude analysis by averaging with the last analysis\n * frame. Off by default.\n *\n * @method smooth\n * @for p5.Amplitude\n * @param {Number} set smoothing from 0.0 <= 1\n */\np5.Amplitude.prototype.smooth = function (s) {\n if (s >= 0 && s < 1) {\n this._workletNode.port.postMessage({ name: 'smoothing', smoothing: s });\n } else {\n console.log('Error: smoothing must be between 0 and 1');\n }\n};\n\np5.Amplitude.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n this._workletNode.disconnect();\n delete this._workletNode;\n};\n","import p5sound from './master';\n\n/**\n *

FFT (Fast Fourier Transform) is an analysis algorithm that\n * isolates individual\n * \n * audio frequencies within a waveform.

\n *\n *

Once instantiated, a p5.FFT object can return an array based on\n * two types of analyses:
• FFT.waveform() computes\n * amplitude values along the time domain. The array indices correspond\n * to samples across a brief moment in time. Each value represents\n * amplitude of the waveform at that sample of time.
\n * • FFT.analyze() computes amplitude values along the\n * frequency domain. The array indices correspond to frequencies (i.e.\n * pitches), from the lowest to the highest that humans can hear. Each\n * value represents amplitude at that slice of the frequency spectrum.\n * Use with getEnergy() to measure amplitude at specific\n * frequencies, or within a range of frequencies.

\n *\n *

FFT analyzes a very short snapshot of sound called a sample\n * buffer. It returns an array of amplitude measurements, referred\n * to as bins. The array is 1024 bins long by default.\n * You can change the bin array length, but it must be a power of 2\n * between 16 and 1024 in order for the FFT algorithm to function\n * correctly. The actual size of the FFT buffer is twice the\n * number of bins, so given a standard sample rate, the buffer is\n * 2048/44100 seconds long.

\n *\n *\n * @class p5.FFT\n * @constructor\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\n * 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n * @param {Number} [bins] Length of resulting array.\n * Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(togglePlay);\n * fft = new p5.FFT();\n * sound.amp(0.2);\n * }\n *\n * function draw(){\n * background(220);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h )\n * }\n *\n * let waveform = fft.waveform();\n * noFill();\n * beginShape();\n * stroke(20);\n * for (let i = 0; i < waveform.length; i++){\n * let x = map(i, 0, waveform.length, 0, width);\n * let y = map( waveform[i], -1, 1, 0, height);\n * vertex(x,y);\n * }\n * endShape();\n *\n * text('tap to play', 20, 20);\n * }\n *\n * function togglePlay() {\n * if (sound.isPlaying()) {\n * sound.pause();\n * } else {\n * sound.loop();\n * }\n * }\n *
\n */\np5.FFT = function (smoothing, bins) {\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\n\n Object.defineProperties(this, {\n bins: {\n get: function () {\n return this.analyser.fftSize / 2;\n },\n set: function (b) {\n this.analyser.fftSize = b * 2;\n },\n configurable: true,\n enumerable: true,\n },\n smoothing: {\n get: function () {\n return this.analyser.smoothingTimeConstant;\n },\n set: function (s) {\n this.analyser.smoothingTimeConstant = s;\n },\n configurable: true,\n enumerable: true,\n },\n });\n\n // set default smoothing and bins\n this.smooth(smoothing);\n this.bins = bins || 1024;\n\n // default connections to p5sound fftMeter\n p5sound.fftMeter.connect(this.analyser);\n\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\n\n // predefined frequency ranges, these will be tweakable\n this.bass = [20, 140];\n this.lowMid = [140, 400];\n this.mid = [400, 2600];\n this.highMid = [2600, 5200];\n this.treble = [5200, 14000];\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Set the input source for the FFT analysis. If no source is\n * provided, FFT will analyze all sound in the sketch.\n *\n * @method setInput\n * @for p5.FFT\n * @param {Object} [source] p5.sound object (or web audio API source node)\n */\np5.FFT.prototype.setInput = function (source) {\n if (!source) {\n p5sound.fftMeter.connect(this.analyser);\n } else {\n if (source.output) {\n source.output.connect(this.analyser);\n } else if (source.connect) {\n source.connect(this.analyser);\n }\n p5sound.fftMeter.disconnect();\n }\n};\n\n/**\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\n * a snapshot of amplitude readings in a single buffer. Length will be\n * equal to bins (defaults to 1024). Can be used to draw the waveform\n * of a sound.\n *\n * @method waveform\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {String} [precision] If any value is provided, will return results\n * in a Float32 Array which is more precise\n * than a regular array.\n * @return {Array} Array Array of amplitude values (-1 to 1)\n * over time. Array length = bins.\n *\n */\np5.FFT.prototype.waveform = function () {\n var bins, mode;\n var normalArray = new Array();\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n bins = arguments[i];\n this.analyser.fftSize = bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\n if (mode && !p5.prototype._isSafari()) {\n timeToFloat(this, this.timeDomain);\n this.analyser.getFloatTimeDomainData(this.timeDomain);\n return this.timeDomain;\n } else {\n timeToInt(this, this.timeDomain);\n this.analyser.getByteTimeDomainData(this.timeDomain);\n for (var j = 0; j < this.timeDomain.length; j++) {\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\n normalArray.push(scaled);\n }\n return normalArray;\n }\n};\n\n/**\n * Returns an array of amplitude values (between 0 and 255)\n * across the frequency spectrum. Length is equal to FFT bins\n * (1024 by default). The array indices correspond to frequencies\n * (i.e. pitches), from the lowest to the highest that humans can\n * hear. Each value represents amplitude at that slice of the\n * frequency spectrum. Must be called prior to using\n * getEnergy().\n *\n * @method analyze\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {Number} [scale] If \"dB,\" returns decibel\n * float measurements between\n * -140 and 0 (max).\n * Otherwise returns integers from 0-255.\n * @return {Array} spectrum Array of energy (amplitude/volume)\n * values across the frequency spectrum.\n * Lowest energy (silence) = 0, highest\n * possible is 255.\n * @example\n *
\n * let osc, fft;\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(startSound);\n * osc = new p5.Oscillator();\n * osc.amp(0);\n * fft = new p5.FFT();\n * }\n *\n * function draw(){\n * background(220);\n *\n * let freq = map(mouseX, 0, windowWidth, 20, 10000);\n * freq = constrain(freq, 1, 20000);\n * osc.freq(freq);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h );\n * }\n *\n * stroke(255);\n * if (!osc.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text(round(freq)+'Hz', 10, 20);\n * }\n * }\n *\n * function startSound() {\n * osc.start();\n * osc.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * osc.amp(0, 0.2);\n * }\n *
\n *\n *\n */\np5.FFT.prototype.analyze = function () {\n var mode;\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n this.bins = arguments[i];\n this.analyser.fftSize = this.bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n if (mode && mode.toLowerCase() === 'db') {\n freqToFloat(this);\n this.analyser.getFloatFrequencyData(this.freqDomain);\n return this.freqDomain;\n } else {\n freqToInt(this, this.freqDomain);\n this.analyser.getByteFrequencyData(this.freqDomain);\n var normalArray = Array.apply([], this.freqDomain);\n\n return normalArray;\n }\n};\n\n/**\n * Returns the amount of energy (volume) at a specific\n * \n * frequency, or the average amount of energy between two\n * frequencies. Accepts Number(s) corresponding\n * to frequency (in Hz), or a String corresponding to predefined\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\n * Returns a range between 0 (no energy/volume at that frequency) and\n * 255 (maximum energy).\n * NOTE: analyze() must be called prior to getEnergy(). Analyze()\n * tells the FFT to analyze frequency data, and getEnergy() uses\n * the results determine the value at a specific frequency or\n * range of frequencies.

\n *\n * @method getEnergy\n * @for p5.FFT\n * @param {Number|String} frequency1 Will return a value representing\n * energy at this frequency. Alternately,\n * the strings \"bass\", \"lowMid\" \"mid\",\n * \"highMid\", and \"treble\" will return\n * predefined frequency ranges.\n * @param {Number} [frequency2] If a second frequency is given,\n * will return average amount of\n * energy that exists between the\n * two frequencies.\n * @return {Number} Energy Energy (volume/amplitude) from\n * 0 and 255.\n *\n */\np5.FFT.prototype.getEnergy = function (frequency1, frequency2) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n\n if (frequency1 === 'bass') {\n frequency1 = this.bass[0];\n frequency2 = this.bass[1];\n } else if (frequency1 === 'lowMid') {\n frequency1 = this.lowMid[0];\n frequency2 = this.lowMid[1];\n } else if (frequency1 === 'mid') {\n frequency1 = this.mid[0];\n frequency2 = this.mid[1];\n } else if (frequency1 === 'highMid') {\n frequency1 = this.highMid[0];\n frequency2 = this.highMid[1];\n } else if (frequency1 === 'treble') {\n frequency1 = this.treble[0];\n frequency2 = this.treble[1];\n }\n\n if (typeof frequency1 !== 'number') {\n throw 'invalid input for getEnergy()';\n } else if (!frequency2) {\n // if only one parameter:\n var index = Math.round((frequency1 / nyquist) * this.freqDomain.length);\n return this.freqDomain[index];\n } else if (frequency1 && frequency2) {\n // if two parameters:\n // if second is higher than first\n if (frequency1 > frequency2) {\n var swap = frequency2;\n frequency2 = frequency1;\n frequency1 = swap;\n }\n var lowIndex = Math.round((frequency1 / nyquist) * this.freqDomain.length);\n var highIndex = Math.round((frequency2 / nyquist) * this.freqDomain.length);\n\n var total = 0;\n var numFrequencies = 0;\n // add up all of the values for the frequencies\n for (var i = lowIndex; i <= highIndex; i++) {\n total += this.freqDomain[i];\n numFrequencies += 1;\n }\n // divide by total number of frequencies\n var toReturn = total / numFrequencies;\n return toReturn;\n } else {\n throw 'invalid input for getEnergy()';\n }\n};\n\n// compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\np5.FFT.prototype.getFreq = function (freq1, freq2) {\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\n var x = this.getEnergy(freq1, freq2);\n return x;\n};\n\n/**\n * Returns the\n * \n * spectral centroid of the input signal.\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\n * tells the FFT to analyze frequency data, and getCentroid() uses\n * the results determine the spectral centroid.

\n *\n * @method getCentroid\n * @for p5.FFT\n * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz.\n *\n *\n * @example\n *
\n * function setup(){\n * cnv = createCanvas(100,100);\n * cnv.mousePressed(userStartAudio);\n * sound = new p5.AudioIn();\n * sound.start();\n * fft = new p5.FFT();\n * sound.connect(fft);\n *}\n *\n *function draw() {\n * if (getAudioContext().state !== 'running') {\n * background(220);\n * text('tap here and enable mic to begin', 10, 20, width - 20);\n * return;\n * }\n * let centroidplot = 0.0;\n * let spectralCentroid = 0;\n *\n * background(0);\n * stroke(0,255,0);\n * let spectrum = fft.analyze();\n * fill(0,255,0); // spectrum is green\n *\n * //draw the spectrum\n * for (let i = 0; i < spectrum.length; i++){\n * let x = map(log(i), 0, log(spectrum.length), 0, width);\n * let h = map(spectrum[i], 0, 255, 0, height);\n * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\n * rect(x, height, rectangle_width, -h )\n * }\n * let nyquist = 22050;\n *\n * // get the centroid\n * spectralCentroid = fft.getCentroid();\n *\n * // the mean_freq_index calculation is for the display.\n * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\n *\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\n *\n * stroke(255,0,0); // the line showing where the centroid is will be red\n *\n * rect(centroidplot, 0, width / spectrum.length, height)\n * noStroke();\n * fill(255,255,255); // text is white\n * text('centroid: ', 10, 20);\n * text(round(spectralCentroid)+' Hz', 10, 40);\n *}\n *
\n */\np5.FFT.prototype.getCentroid = function () {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var cumulative_sum = 0;\n var centroid_normalization = 0;\n\n for (var i = 0; i < this.freqDomain.length; i++) {\n cumulative_sum += i * this.freqDomain[i];\n centroid_normalization += this.freqDomain[i];\n }\n\n var mean_freq_index = 0;\n\n if (centroid_normalization !== 0) {\n mean_freq_index = cumulative_sum / centroid_normalization;\n }\n\n var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length);\n return spec_centroid_freq;\n};\n\n/**\n * Smooth FFT analysis by averaging with the last analysis frame.\n *\n * @method smooth\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n */\np5.FFT.prototype.smooth = function (s) {\n if (typeof s !== 'undefined') {\n this.smoothing = s;\n }\n return this.smoothing;\n};\n\np5.FFT.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.analyser) {\n this.analyser.disconnect();\n delete this.analyser;\n }\n};\n\n/**\n * Returns an array of average amplitude values for a given number\n * of frequency bands split equally. N defaults to 16.\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\n * tells the FFT to analyze frequency data, and linAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method linAverages\n * @for p5.FFT\n * @param {Number} N Number of returned frequency groups\n * @return {Array} linearAverages Array of average amplitude values for each group\n */\np5.FFT.prototype.linAverages = function (_N) {\n var N = _N || 16; // This prevents undefined, null or 0 values of N\n\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n var spectrumStep = Math.floor(spectrumLength / N);\n\n var linearAverages = new Array(N);\n // Keep a second index for the current average group and place the values accordingly\n // with only one loop in the spectrum data\n var groupIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n linearAverages[groupIndex] =\n linearAverages[groupIndex] !== undefined\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n\n // Increase the group index when the last element of the group is processed\n if (specIndex % spectrumStep === spectrumStep - 1) {\n groupIndex++;\n }\n }\n\n return linearAverages;\n};\n\n/**\n * Returns an array of average amplitude values of the spectrum, for a given\n * set of \n * Octave Bands\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\n * tells the FFT to analyze frequency data, and logAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method logAverages\n * @for p5.FFT\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\n * @return {Array} logAverages Array of average amplitude values for each group\n */\np5.FFT.prototype.logAverages = function (octaveBands) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n\n var logAverages = new Array(octaveBands.length);\n // Keep a second index for the current average group and place the values accordingly\n // With only one loop in the spectrum data\n var octaveIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n var specIndexFrequency = Math.round(\n (specIndex * nyquist) / this.freqDomain.length\n );\n\n // Increase the group index if the current frequency exceeds the limits of the band\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\n octaveIndex++;\n }\n\n logAverages[octaveIndex] =\n logAverages[octaveIndex] !== undefined\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n }\n\n return logAverages;\n};\n\n/**\n * Calculates and Returns the 1/N\n * Octave Bands\n * N defaults to 3 and minimum central frequency to 15.625Hz.\n * (1/3 Octave Bands ~= 31 Frequency Bands)\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\n * and produce less frequency groups.\n *\n * @method getOctaveBands\n * @for p5.FFT\n * @param {Number} N Specifies the 1/N type of generated octave bands\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\n * @return {Array} octaveBands Array of octave band objects with their bounds\n */\np5.FFT.prototype.getOctaveBands = function (_N, _fCtr0) {\n var N = _N || 3; // Default to 1/3 Octave Bands\n var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\n\n var octaveBands = [];\n var lastFrequencyBand = {\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\n ctr: fCtr0,\n hi: fCtr0 * Math.pow(2, 1 / (2 * N)),\n };\n octaveBands.push(lastFrequencyBand);\n\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n while (lastFrequencyBand.hi < nyquist) {\n var newFrequencyBand = {};\n newFrequencyBand.lo = lastFrequencyBand.hi;\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\n\n octaveBands.push(newFrequencyBand);\n lastFrequencyBand = newFrequencyBand;\n }\n\n return octaveBands;\n};\n\n// helper methods to convert type from float (dB) to int (0-255)\nfunction freqToFloat(fft) {\n if (fft.freqDomain instanceof Float32Array === false) {\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction freqToInt(fft) {\n if (fft.freqDomain instanceof Uint8Array === false) {\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToFloat(fft) {\n if (fft.timeDomain instanceof Float32Array === false) {\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToInt(fft) {\n if (fft.timeDomain instanceof Uint8Array === false) {\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\n\nexport default p5.FFT;\n","// Signal is built with the Tone.js signal by Yotam Mann\n// https://github.com/TONEnoTONE/Tone.js/\nimport Signal from 'Tone/signal/Signal';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\n\n/**\n *

p5.Signal is a constant audio-rate signal used by p5.Oscillator\n * and p5.Envelope for modulation math.

\n *\n *

This is necessary because Web Audio is processed on a separate clock.\n * For example, the p5 draw loop runs about 60 times per second. But\n * the audio clock must process samples 44100 times per second. If we\n * want to add a value to each of those samples, we can't do it in the\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\n * a Tone.Signal from the Tone.js library by Yotam Mann.\n * If you want to work directly with audio signals for modular\n * synthesis, check out\n * tone.js.

\n *\n * @class p5.Signal\n * @constructor\n * @return {Tone.Signal} A Signal object from the Tone.js library\n * @example\n *
\n * let carrier, modulator;\n * let hasStarted = false;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * carrier = new p5.Oscillator('sine');\n * carrier.amp(1); // set amplitude\n * carrier.freq(220); // set frequency\n *\n * modulator = new p5.Oscillator('sawtooth');\n * modulator.disconnect();\n * modulator.start();\n * modulator.amp(1);\n * modulator.freq(4);\n *\n * // Modulator's default amplitude range is -1 to 1.\n * // Multiply it by -200, so the range is -200 to 200\n * // then add 220 so the range is 20 to 420\n * carrier.freq( modulator.mult(-400).add(220) );\n * }\n *\n * function canvasPressed() {\n * userStartAudio();\n * carrier.amp(1.0);\n * if(!hasStarted){\n * carrier.start();\n * hasStarted = true;\n * }\n * }\n *\n * function mouseReleased() {\n * carrier.amp(0);\n * }\n *
\n */\np5.Signal = function (value) {\n var s = new Signal(value);\n // p5sound.soundArray.push(s);\n return s; // TODO: is this really a constructor?\n};\n\n/**\n * Fade to value, for smooth transitions\n *\n * @method fade\n * @for p5.Signal\n * @param {Number} value Value to set this signal\n * @param {Number} [secondsFromNow] Length of fade, in seconds from now\n */\nSignal.prototype.fade = Signal.prototype.linearRampToValueAtTime;\nMult.prototype.fade = Signal.prototype.fade;\nAdd.prototype.fade = Signal.prototype.fade;\nScale.prototype.fade = Signal.prototype.fade;\n\n/**\n * Connect a p5.sound object or Web Audio node to this\n * p5.Signal so that its amplitude values can be scaled.\n *\n * @method setInput\n * @for p5.Signal\n * @param {Object} input\n */\nSignal.prototype.setInput = function (_input) {\n _input.connect(this);\n};\nMult.prototype.setInput = Signal.prototype.setInput;\nAdd.prototype.setInput = Signal.prototype.setInput;\nScale.prototype.setInput = Signal.prototype.setInput;\n\n// signals can add / mult / scale themselves\n\n/**\n * Add a constant value to this audio signal,\n * and return the resulting audio signal. Does\n * not change the value of the original signal,\n * instead it returns a new p5.SignalAdd.\n *\n * @method add\n * @for p5.Signal\n * @param {Number} number\n * @return {p5.Signal} object\n */\nSignal.prototype.add = function (num) {\n var add = new Add(num);\n // add.setInput(this);\n this.connect(add);\n return add;\n};\nMult.prototype.add = Signal.prototype.add;\nAdd.prototype.add = Signal.prototype.add;\nScale.prototype.add = Signal.prototype.add;\n\n/**\n * Multiply this signal by a constant value,\n * and return the resulting audio signal. Does\n * not change the value of the original signal,\n * instead it returns a new p5.SignalMult.\n *\n * @method mult\n * @for p5.Signal\n * @param {Number} number to multiply\n * @return {p5.Signal} object\n */\nSignal.prototype.mult = function (num) {\n var mult = new Mult(num);\n // mult.setInput(this);\n this.connect(mult);\n return mult;\n};\nMult.prototype.mult = Signal.prototype.mult;\nAdd.prototype.mult = Signal.prototype.mult;\nScale.prototype.mult = Signal.prototype.mult;\n\n/**\n * Scale this signal value to a given range,\n * and return the result as an audio signal. Does\n * not change the value of the original signal,\n * instead it returns a new p5.SignalScale.\n *\n * @method scale\n * @for p5.Signal\n * @param {Number} number to multiply\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Signal} object\n */\nSignal.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var mapOutMin, mapOutMax;\n if (arguments.length === 4) {\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\n } else {\n mapOutMin = arguments[0];\n mapOutMax = arguments[1];\n }\n var scale = new Scale(mapOutMin, mapOutMax);\n this.connect(scale);\n return scale;\n};\n\nMult.prototype.scale = Signal.prototype.scale;\nAdd.prototype.scale = Signal.prototype.scale;\nScale.prototype.scale = Signal.prototype.scale;\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\n\n/**\n *

Creates a signal that oscillates between -1.0 and 1.0.\n * By default, the oscillation takes the form of a sinusoidal\n * shape ('sine'). Additional types include 'triangle',\n * 'sawtooth' and 'square'. The frequency defaults to\n * 440 oscillations per second (440Hz, equal to the pitch of an\n * 'A' note).

\n *\n *

Set the type of oscillation with setType(), or by instantiating a\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\n *

\n *\n * @class p5.Oscillator\n * @constructor\n * @param {Number} [freq] frequency defaults to 440Hz\n * @param {String} [type] type of oscillator. Options:\n * 'sine' (default), 'triangle',\n * 'sawtooth', 'square'\n * @example\n *
\n * let osc, playing, freq, amp;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator('sine');\n * }\n *\n * function draw() {\n * background(220)\n * freq = constrain(map(mouseX, 0, width, 100, 500), 100, 500);\n * amp = constrain(map(mouseY, height, 0, 0, 1), 0, 1);\n *\n * text('tap to play', 20, 20);\n * text('freq: ' + freq, 20, 40);\n * text('amp: ' + amp, 20, 60);\n *\n * if (playing) {\n * // smooth the transitions by 0.1 seconds\n * osc.freq(freq, 0.1);\n * osc.amp(amp, 0.1);\n * }\n * }\n *\n * function playOscillator() {\n * // starting an oscillator on a user gesture will enable audio\n * // in browsers that have a strict autoplay policy.\n * // See also: userStartAudio();\n * osc.start();\n * playing = true;\n * }\n *\n * function mouseReleased() {\n * // ramp amplitude to 0 over 0.5 seconds\n * osc.amp(0, 0.5);\n * playing = false;\n * }\n *
\n */\np5.Oscillator = function (freq, type) {\n if (typeof freq === 'string') {\n let f = type;\n type = freq;\n freq = f;\n }\n if (typeof type === 'number') {\n let f = type;\n type = freq;\n freq = f;\n }\n this.started = false;\n\n // components\n this.phaseAmount = undefined;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.f = freq || 440.0; // frequency\n this.oscillator.type = type || 'sine';\n this.oscillator.frequency.setValueAtTime(\n this.f,\n p5sound.audiocontext.currentTime\n );\n\n // connections\n this.output = p5sound.audiocontext.createGain();\n\n this._freqMods = []; // modulators connected to this oscillator's frequency\n\n // set default output gain to 0.5\n this.output.gain.value = 0.5;\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\n\n this.oscillator.connect(this.output);\n // stereo panning\n this.panPosition = 0.0;\n this.connection = p5sound.input; // connect to p5sound by default\n this.panner = new p5.Panner(this.output, this.connection, 1);\n\n //array of math operation signal chaining\n this.mathOps = [this.output];\n\n // add to the soundArray so we can dispose of the osc later\n p5sound.soundArray.push(this);\n};\n\n/**\n * Start an oscillator.\n *\n * Starting an oscillator on a user gesture will enable audio in browsers\n * that have a strict autoplay policy, including Chrome and most mobile\n * devices. See also: `userStartAudio()`.\n *\n * @method start\n * @for p5.Oscillator\n * @param {Number} [time] startTime in seconds from now.\n * @param {Number} [frequency] frequency in Hz.\n */\np5.Oscillator.prototype.start = function (time, f) {\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n }\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n\n // set old osc free to be garbage collected (memory)\n if (this.oscillator) {\n this.oscillator.disconnect();\n delete this.oscillator;\n }\n\n // var detune = this.oscillator.frequency.value;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.value = Math.abs(freq);\n this.oscillator.type = type;\n // this.oscillator.detune.value = detune;\n this.oscillator.connect(this.output);\n time = time || 0;\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\n this.freqNode = this.oscillator.frequency;\n\n // if other oscillators are already connected to this osc's freq\n for (var i in this._freqMods) {\n if (typeof this._freqMods[i].connect !== 'undefined') {\n this._freqMods[i].connect(this.oscillator.frequency);\n }\n }\n\n this.started = true;\n }\n};\n\n/**\n * Stop an oscillator. Accepts an optional parameter\n * to determine how long (in seconds from now) until the\n * oscillator stops.\n *\n * @method stop\n * @for p5.Oscillator\n * @param {Number} secondsFromNow Time, in seconds from now.\n */\np5.Oscillator.prototype.stop = function (time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n this.started = false;\n }\n};\n\n/**\n * Set the amplitude between 0 and 1.0. Or, pass in an object\n * such as an oscillator to modulate amplitude with an audio signal.\n *\n * @method amp\n * @for p5.Oscillator\n * @param {Number|Object} vol between 0 and 1.0\n * or a modulating signal/oscillator\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {AudioParam} gain If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's\n * gain/amplitude/volume)\n */\np5.Oscillator.prototype.amp = function (vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n};\n\n// these are now the same thing\np5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;\n\n/**\n * Returns the value of output gain\n *\n * @method getAmp\n * @for p5.Oscillator\n *\n * @returns {number} Amplitude value between 0.0 and 1.0\n */\n\np5.Oscillator.prototype.getAmp = function () {\n return this.output.gain.value;\n};\n\n/**\n * Set frequency of an oscillator to a value. Or, pass in an object\n * such as an oscillator to modulate the frequency with an audio signal.\n *\n * @method freq\n * @for p5.Oscillator\n * @param {Number|Object} Frequency Frequency in Hz\n * or modulating signal/oscillator\n * @param {Number} [rampTime] Ramp time (in seconds)\n * @param {Number} [timeFromNow] Schedule this event to happen\n * at x seconds from now\n * @return {AudioParam} Frequency If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's frequency\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator(300);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playOscillator() {\n * osc.start();\n * osc.amp(0.5);\n * // start at 700Hz\n * osc.freq(700);\n * // ramp to 60Hz over 0.7 seconds\n * osc.freq(60, 0.7);\n * osc.amp(0, 0.1, 0.7);\n * }\n *
\n */\np5.Oscillator.prototype.freq = function (val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number' && !isNaN(val)) {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n\n if (rampTime === 0) {\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\n } else {\n if (val > 0) {\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n } else {\n this.oscillator.frequency.linearRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n }\n }\n\n // reset phase if oscillator has a phase\n if (this.phaseAmount) {\n this.phase(this.phaseAmount);\n }\n } else if (val) {\n if (val.output) {\n val = val.output;\n }\n val.connect(this.oscillator.frequency);\n\n // keep track of what is modulating this param\n // so it can be re-connected if\n this._freqMods.push(val);\n } else {\n // return the Frequency Node\n return this.oscillator.frequency;\n }\n};\n/**\n * Returns the value of frequency of oscillator\n *\n * @method getFreq\n * @for p5.Oscillator\n * @returns {number} Frequency of oscillator in Hertz\n */\n\np5.Oscillator.prototype.getFreq = function () {\n return this.oscillator.frequency.value;\n};\n\n/**\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method setType\n * @for p5.Oscillator\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\n */\np5.Oscillator.prototype.setType = function (type) {\n this.oscillator.type = type;\n};\n/**\n * Returns current type of oscillator eg. 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method getType\n * @for p5.Oscillator\n * @returns {String} type of oscillator eg . 'sine', 'triangle', 'sawtooth' or 'square'.\n */\n\np5.Oscillator.prototype.getType = function () {\n return this.oscillator.type;\n};\n\n/**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.Oscillator\n * @param {Object} unit A p5.sound or Web Audio object\n */\np5.Oscillator.prototype.connect = function (unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n this.connection = unit.input;\n } else {\n this.panner.connect(unit);\n this.connection = unit;\n }\n};\n\n/**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.Oscillator\n */\np5.Oscillator.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n if (this.output) {\n this.output.connect(this.panner);\n }\n }\n this.oscMods = [];\n};\n\n/**\n * Pan between Left (-1) and Right (1)\n *\n * @method pan\n * @for p5.Oscillator\n * @param {Number} panning Number between -1 and 1\n * @param {Number} timeFromNow schedule this event to happen\n * seconds from now\n */\np5.Oscillator.prototype.pan = function (pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n};\n\n/**\n * Returns the current value of panPosition , between Left (-1) and Right (1)\n *\n * @method getPan\n * @for p5.Oscillator\n *\n * @returns {number} panPosition of oscillator , between Left (-1) and Right (1)\n */\n\np5.Oscillator.prototype.getPan = function () {\n return this.panPosition;\n};\n\n// get rid of the oscillator\np5.Oscillator.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.oscillator) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.disconnect();\n this.panner = null;\n this.oscillator = null;\n }\n // if it is a Pulse\n if (this.osc2) {\n this.osc2.dispose();\n }\n};\n\n/**\n * Set the phase of an oscillator between 0.0 and 1.0.\n * In this implementation, phase is a delay time\n * based on the oscillator's current frequency.\n *\n * @method phase\n * @for p5.Oscillator\n * @param {Number} phase float between 0.0 and 1.0\n */\np5.Oscillator.prototype.phase = function (p) {\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f);\n var now = p5sound.audiocontext.currentTime;\n\n this.phaseAmount = p;\n\n if (!this.dNode) {\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n // put the delay node in between output and panner\n this.oscillator.disconnect();\n this.oscillator.connect(this.dNode);\n this.dNode.connect(this.output);\n }\n\n // set delay time to match phase:\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\n};\n\n// ========================== //\n// SIGNAL MATH FOR MODULATION //\n// ========================== //\n\n// return sigChain(this, scale, thisChain, nextChain, Scale);\nvar sigChain = function (o, mathObj, thisChain, nextChain, type) {\n var chainSource = o.oscillator;\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n chainSource.disconnect();\n o.mathOps[i].dispose();\n thisChain = i;\n // assume nextChain is output gain node unless...\n if (thisChain < o.mathOps.length - 2) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n if (thisChain === o.mathOps.length - 1) {\n o.mathOps.push(nextChain);\n }\n // assume source is the oscillator unless i > 0\n if (i > 0) {\n chainSource = o.mathOps[i - 1];\n }\n chainSource.disconnect();\n chainSource.connect(mathObj);\n mathObj.connect(nextChain);\n o.mathOps[thisChain] = mathObj;\n return o;\n};\n\n/**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method again\n * will override the initial add() with a new value.\n *\n * @method add\n * @for p5.Oscillator\n * @param {Number} number Constant number to add\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n *\n */\np5.Oscillator.prototype.add = function (num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, add, thisChain, nextChain, Add);\n};\n\n/**\n * Multiply the p5.Oscillator's output amplitude\n * by a fixed value (i.e. turn it up!). Calling this method\n * again will override the initial mult() with a new value.\n *\n * @method mult\n * @for p5.Oscillator\n * @param {Number} number Constant number to multiply\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with multiplied output\n */\np5.Oscillator.prototype.mult = function (num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, mult, thisChain, nextChain, Mult);\n};\n\n/**\n * Scale this oscillator's amplitude values to a given\n * range, and return the oscillator. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Oscillator\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n */\np5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var mapOutMin, mapOutMax;\n if (arguments.length === 4) {\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\n } else {\n mapOutMin = arguments[0];\n mapOutMax = arguments[1];\n }\n var scale = new Scale(mapOutMin, mapOutMax);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, scale, thisChain, nextChain, Scale);\n\n // this.output.disconnect();\n // this.output.connect(scale)\n};\n\n// ============================== //\n// SinOsc, TriOsc, SqrOsc, SawOsc //\n// ============================== //\n\n/**\n * Constructor: new p5.SinOsc().\n * This creates a Sine Wave Oscillator and is\n * equivalent to new p5.Oscillator('sine')\n * or creating a p5.Oscillator and then calling\n * its method setType('sine').\n * See p5.Oscillator for methods.\n *\n * @class p5.SinOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.SinOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'sine');\n};\n\np5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Constructor: new p5.TriOsc().\n * This creates a Triangle Wave Oscillator and is\n * equivalent to new p5.Oscillator('triangle')\n * or creating a p5.Oscillator and then calling\n * its method setType('triangle').\n * See p5.Oscillator for methods.\n *\n * @class p5.TriOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.TriOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'triangle');\n};\n\np5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Constructor: new p5.SawOsc().\n * This creates a SawTooth Wave Oscillator and is\n * equivalent to new p5.Oscillator('sawtooth')\n * or creating a p5.Oscillator and then calling\n * its method setType('sawtooth').\n * See p5.Oscillator for methods.\n *\n * @class p5.SawOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.SawOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'sawtooth');\n};\n\np5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Constructor: new p5.SqrOsc().\n * This creates a Square Wave Oscillator and is\n * equivalent to new p5.Oscillator('square')\n * or creating a p5.Oscillator and then calling\n * its method setType('square').\n * See p5.Oscillator for methods.\n *\n * @class p5.SqrOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.SqrOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'square');\n};\n\np5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);\n\nexport const Oscillator = p5.Oscillator;\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\n\n/**\n *

Envelopes are pre-defined amplitude distribution over time.\n * Typically, envelopes are used to control the output volume\n * of an object, a series of fades referred to as Attack, Decay,\n * Sustain and Release (\n * ADSR\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\n * control an Oscillator's frequency like this: osc.freq(env).

\n *

Use setRange to change the attack/release level.\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

\n *

Use the play method to play the entire envelope,\n * the ramp method for a pingable trigger,\n * or triggerAttack/\n * triggerRelease to trigger noteOn/noteOff.

\n *\n * @class p5.Envelope\n * @constructor\n * @example\n *
\n * let t1 = 0.1; // attack time in seconds\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n *\n * let env;\n * let triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('tap to play', 20, 20);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope(t1, l1, t2, l2);\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function playSound() {\n * // starting the oscillator ensures that audio is enabled.\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n */\np5.Envelope = function (t1, l1, t2, l2, t3, l3) {\n /**\n * Time until envelope reaches attackLevel\n * @property attackTime\n */\n this.aTime = t1 || 0.1;\n /**\n * Level once attack is complete.\n * @property attackLevel\n */\n this.aLevel = l1 || 1;\n /**\n * Time until envelope reaches decayLevel.\n * @property decayTime\n */\n this.dTime = t2 || 0.5;\n /**\n * Level after decay. The envelope will sustain here until it is released.\n * @property decayLevel\n */\n this.dLevel = l2 || 0;\n /**\n * Duration of the release portion of the envelope.\n * @property releaseTime\n */\n this.rTime = t3 || 0;\n /**\n * Level at the end of the release.\n * @property releaseLevel\n */\n this.rLevel = l3 || 0;\n\n this._rampHighPercentage = 0.98;\n\n this._rampLowPercentage = 0.02;\n\n this.output = p5sound.audiocontext.createGain();\n\n this.control = new TimelineSignal();\n\n this._init(); // this makes sure the envelope starts at zero\n\n this.control.connect(this.output); // connect to the output\n\n this.connection = null; // store connection\n\n //array of math operation signal chaining\n this.mathOps = [this.control];\n\n //whether envelope should be linear or exponential curve\n this.isExponential = false;\n\n // oscillator or buffer source to clear on env complete\n // to save resources if/when it is retriggered\n this.sourceToClear = null;\n\n // set to true if attack is set, then false on release\n this.wasTriggered = false;\n\n // add to the soundArray so we can dispose of the env later\n p5sound.soundArray.push(this);\n};\n\n// this init function just smooths the starting value to zero and gives a start point for the timeline\n// - it was necessary to remove glitches at the beginning.\np5.Envelope.prototype._init = function () {\n var now = p5sound.audiocontext.currentTime;\n var t = now;\n this.control.setTargetAtTime(0.00001, t, 0.001);\n //also, compute the correct time constants\n this._setRampAD(this.aTime, this.dTime);\n};\n\n/**\n * Reset the envelope with a series of time/value pairs.\n *\n * @method set\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds) before level\n * reaches attackLevel\n * @param {Number} attackLevel Typically an amplitude between\n * 0.0 and 1.0\n * @param {Number} decayTime Time\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\n * decayLevel = sustainLevel)\n * @param {Number} releaseTime Release Time (in seconds)\n * @param {Number} releaseLevel Amplitude\n * @example\n *
\n * let attackTime;\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n * let l3 = 0.2; // release time in seconds\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n *\n * attackTime = map(mouseX, 0, width, 0.0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 20);\n * }\n *\n * // mouseClick triggers envelope if over canvas\n * function playSound() {\n * env.set(attackTime, l1, t2, l2, l3);\n *\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n *\n */\np5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) {\n this.aTime = t1;\n this.aLevel = l1;\n this.dTime = t2 || 0;\n this.dLevel = l2 || 0;\n this.rTime = t3 || 0;\n this.rLevel = l3 || 0;\n\n // set time constants for ramp\n this._setRampAD(t1, t2);\n};\n\n/**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) {\n this.aTime = aTime;\n this.dTime = dTime || 0;\n\n // lerp\n this.sPercent = sPercent || 0;\n this.dLevel =\n typeof sPercent !== 'undefined'\n ? sPercent * (this.aLevel - this.rLevel) + this.rLevel\n : 0;\n\n this.rTime = rTime || 0;\n\n // also set time constants for ramp\n this._setRampAD(aTime, dTime);\n};\n\n/**\n * Set max (attackLevel) and min (releaseLevel) of envelope.\n *\n * @method setRange\n * @for p5.Envelope\n * @param {Number} aLevel attack level (defaults to 1)\n * @param {Number} rLevel release level (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setRange = function (aLevel, rLevel) {\n this.aLevel = aLevel || 1;\n this.rLevel = rLevel || 0;\n\n // not sure if this belongs here:\n\n // {Number} [dLevel] decay/sustain level (optional)\n // if (typeof(dLevel) !== 'undefined') {\n // this.dLevel = dLevel\n // } else if (this.sPercent) {\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\n // }\n};\n\n// private (undocumented) method called when ADSR is set to set time constants for ramp\n//\n// Set the \n// time constants for simple exponential ramps.\n// The larger the time constant value, the slower the\n// transition will be.\n//\n// method _setRampAD\n// param {Number} attackTimeConstant attack time constant\n// param {Number} decayTimeConstant decay time constant\n//\np5.Envelope.prototype._setRampAD = function (t1, t2) {\n this._rampAttackTime = this.checkExpInput(t1);\n this._rampDecayTime = this.checkExpInput(t2);\n\n var TCDenominator = 1.0;\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\n};\n\n// private method\np5.Envelope.prototype.setRampPercentages = function (p1, p2) {\n //set the percentages that the simple exponential ramps go to\n this._rampHighPercentage = this.checkExpInput(p1);\n this._rampLowPercentage = this.checkExpInput(p2);\n var TCDenominator = 1.0;\n //now re-compute the time constants based on those percentages\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\n};\n\n/**\n * Assign a parameter to be controlled by this envelope.\n * If a p5.Sound object is given, then the p5.Envelope will control its\n * output gain. If multiple inputs are provided, the env will\n * control all of them.\n *\n * @method setInput\n * @for p5.Envelope\n * @param {Object} [...inputs] A p5.sound object or\n * Web Audio Param.\n */\np5.Envelope.prototype.setInput = function () {\n for (var i = 0; i < arguments.length; i++) {\n this.connect(arguments[i]);\n }\n};\n\n/**\n * Set whether the envelope ramp is linear (default) or exponential.\n * Exponential ramps can be useful because we perceive amplitude\n * and frequency logarithmically.\n *\n * @method setExp\n * @for p5.Envelope\n * @param {Boolean} isExp true is exponential, false is linear\n */\np5.Envelope.prototype.setExp = function (isExp) {\n this.isExponential = isExp;\n};\n\n//helper method to protect against zero values being sent to exponential functions\np5.Envelope.prototype.checkExpInput = function (value) {\n if (value <= 0) {\n value = 0.00000001;\n }\n return value;\n};\n\n/**\n *

Play tells the envelope to start acting on a given input.\n * If the input is a p5.sound object (i.e. AudioIn, Oscillator,\n * SoundFile), then Envelope will control its output volume.\n * Envelopes can also be used to control any \n * Web Audio Audio Param.

\n *\n * @method play\n * @for p5.Envelope\n * @param {Object} unit A p5.sound object or\n * Web Audio Param.\n * @param {Number} [startTime] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * triOsc.start();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * // ensure that audio is enabled\n * userStartAudio();\n *\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) {\n var tFromNow = secondsFromNow || 0;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n this.triggerAttack(unit, tFromNow);\n\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + ~~susTime);\n};\n\n/**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go. Input can be\n * any p5.sound object, or a \n * Web Audio Param.\n *\n * @method triggerAttack\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time from now (in seconds)\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n this.lastAttack = t;\n this.wasTriggered = true;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // after each ramp completes, cancel scheduled values\n // (so they can be overridden in case env has been re-triggered)\n // then, set current value (with linearRamp to avoid click)\n // then, schedule the next automation...\n\n // attack\n t += this.aTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.aLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.aLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // decay to decay level (if using ADSR, then decay level == sustain level)\n t += this.dTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.dLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.dLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n};\n\n/**\n * Trigger the Release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method triggerRelease\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time to trigger the release\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) {\n // only trigger a release if an attack was triggered\n if (!this.wasTriggered) {\n // this currently causes a bit of trouble:\n // if a later release has been scheduled (via the play function)\n // a new earlier release won't interrupt it, because\n // this.wasTriggered has already been set to false.\n // If we want new earlier releases to override, then we need to\n // keep track of the last release time, and if the new release time is\n // earlier, then use it.\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear or exponential ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // release\n t += this.rTime;\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.rLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.rLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n this.wasTriggered = false;\n};\n\n/**\n * Exponentially ramp to a value using the first two\n * values from setADSR(attackTime, decayTime)\n * as \n * time constants for simple exponential ramps.\n * If the value is higher than current value, it uses attackTime,\n * while a decrease uses decayTime.\n *\n * @method ramp\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow When to trigger the ramp\n * @param {Number} v Target value\n * @param {Number} [v2] Second target value\n * @example\n *
\n * let env, osc, amp;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let attackLevel = 1;\n * let decayLevel = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * fill(0,255,0);\n * noStroke();\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime);\n * osc = new p5.Oscillator();\n * osc.amp(env);\n * amp = new p5.Amplitude();\n *\n * cnv.mousePressed(triggerRamp);\n * }\n *\n * function triggerRamp() {\n * // ensures audio is enabled. See also: `userStartAudio`\n * osc.start();\n *\n * env.ramp(osc, 0, attackLevel, decayLevel);\n * }\n *\n * function draw() {\n * background(20);\n * text('tap to play', 10, 20);\n * let h = map(amp.getLevel(), 0, 0.4, 0, height);;\n * rect(0, height, width, -h);\n * }\n *
\n */\np5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n var destination1 = this.checkExpInput(v1);\n var destination2 =\n typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\n\n // connect env to unit if not already connected\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n //get current value\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\n // this.control.cancelScheduledValues(t);\n\n //if it's going up\n if (destination1 > currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\n t += this._rampAttackTime;\n }\n\n //if it's going down\n else if (destination1 < currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\n t += this._rampDecayTime;\n }\n\n // Now the second part of envelope begins\n if (destination2 === undefined) return;\n\n //if it's going up\n if (destination2 > destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\n }\n\n //if it's going down\n else if (destination2 < destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\n }\n};\n\np5.Envelope.prototype.connect = function (unit) {\n this.connection = unit;\n\n // assume we're talking about output gain\n // unless given a different audio param\n if (\n unit instanceof p5.Oscillator ||\n unit instanceof p5.SoundFile ||\n unit instanceof p5.AudioIn ||\n unit instanceof p5.Reverb ||\n unit instanceof p5.Noise ||\n unit instanceof p5.Filter ||\n unit instanceof p5.Delay\n ) {\n unit = unit.output.gain;\n }\n if (unit instanceof AudioParam) {\n //set the initial value\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\n }\n if (unit instanceof p5.Signal) {\n unit.setValue(0);\n }\n this.output.connect(unit);\n};\n\np5.Envelope.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n// Signal Math\n\n/**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method\n * again will override the initial add() with new values.\n *\n * @method add\n * @for p5.Envelope\n * @param {Number} number Constant number to add\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.add = function (num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\n};\n\n/**\n * Multiply the p5.Envelope's output amplitude\n * by a fixed value. Calling this method\n * again will override the initial mult() with new values.\n *\n * @method mult\n * @for p5.Envelope\n * @param {Number} number Constant number to multiply\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.mult = function (num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\n};\n\n/**\n * Scale this envelope's amplitude values to a given\n * range, and return the envelope. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Envelope\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var scale = new Scale(inMin, inMax, outMin, outMax);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\n};\n\n// get rid of the oscillator\np5.Envelope.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.disconnect();\n if (this.control) {\n this.control.dispose();\n this.control = null;\n }\n for (var i = 1; i < this.mathOps.length; i++) {\n this.mathOps[i].dispose();\n }\n};\n\n// Different name for backwards compatibility, replicates p5.Envelope class\np5.Env = function (t1, l1, t2, l2, t3, l3) {\n console.warn(\n 'WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\n 'Please use the new p5.Envelope instead.'\n );\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\n};\np5.Env.prototype = Object.create(p5.Envelope.prototype);\n\nexport default p5.Envelope;\n","import p5sound from './master'\nimport './oscillator'\n\n/**\n * Creates a Pulse object, an oscillator that implements\n * Pulse Width Modulation.\n * The pulse is created with two oscillators.\n * Accepts a parameter for frequency, and to set the\n * width between the pulses. See \n * p5.Oscillator for a full list of methods.\n *\n * @class p5.Pulse\n * @extends p5.Oscillator\n * @constructor\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\n * @param {Number} [w] Width between the pulses (0 to 1.0,\n * defaults to 0)\n * @example\n *
\n * let pulse;\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startPulse);\n * background(220);\n *\n * pulse = new p5.Pulse();\n * pulse.amp(0.5);\n * pulse.freq(220);\n * }\n * function startPulse() {\n * pulse.start();\n * pulse.amp(0.5, 0.02);\n * }\n * function mouseReleased() {\n * pulse.amp(0, 0.2);\n * }\n * function draw() {\n * background(220);\n * text('tap to play', 5, 20, width - 20);\n * let w = map(mouseX, 0, width, 0, 1);\n * w = constrain(w, 0, 1);\n * pulse.width(w);\n * text('pulse width: ' + w, 5, height - 20);\n * }\n *
\n */\np5.Pulse = function (freq, w) {\n p5.Oscillator.call(this, freq, 'sawtooth');\n\n // width of PWM, should be betw 0 to 1.0\n this.w = w || 0;\n\n // create a second oscillator with inverse frequency\n this.osc2 = new p5.SawOsc(freq);\n\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n\n // dc offset\n this.dcOffset = createDCOffset();\n this.dcGain = p5sound.audiocontext.createGain();\n this.dcOffset.connect(this.dcGain);\n this.dcGain.connect(this.output);\n // set delay time based on PWM width\n this.f = freq || 440;\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n\n // disconnect osc2 and connect it to delay, which is connected to output\n this.osc2.disconnect();\n this.osc2.panner.disconnect();\n this.osc2.amp(-1); // inverted amplitude\n this.osc2.output.connect(this.dNode);\n this.dNode.connect(this.output);\n\n this.output.gain.value = 1;\n this.output.connect(this.panner);\n};\n\np5.Pulse.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Set the width of a Pulse object (an oscillator that implements\n * Pulse Width Modulation).\n *\n * @method width\n * @param {Number} [width] Width between the pulses (0 to 1.0,\n * defaults to 0)\n */\np5.Pulse.prototype.width = function (w) {\n if (typeof w === 'number') {\n if (w <= 1.0 && w >= 0.0) {\n this.w = w;\n // set delay time based on PWM width\n\n // var mW = map(this.w, 0, 1.0, 0, 1/this.f);\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n }\n\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n } else {\n w.connect(this.dNode.delayTime);\n var sig = new p5.SignalAdd(-0.5);\n sig.setInput(w);\n sig = sig.mult(-1);\n sig = sig.mult(1.7);\n sig.connect(this.dcGain.gain);\n }\n};\n\np5.Pulse.prototype.start = function (f, time) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.setValueAtTime(freq, now);\n this.oscillator.type = type;\n this.oscillator.connect(this.output);\n this.oscillator.start(t + now);\n\n // set up osc2\n this.osc2.oscillator = p5sound.audiocontext.createOscillator();\n this.osc2.oscillator.frequency.setValueAtTime(freq, t + now);\n this.osc2.oscillator.type = type;\n this.osc2.oscillator.connect(this.osc2.output);\n this.osc2.start(t + now);\n this.freqNode = [this.oscillator.frequency, this.osc2.oscillator.frequency];\n\n // start dcOffset, too\n this.dcOffset = createDCOffset();\n this.dcOffset.connect(this.dcGain);\n this.dcOffset.start(t + now);\n\n // if LFO connections depend on these oscillators\n if (this.mods !== undefined && this.mods.frequency !== undefined) {\n this.mods.frequency.connect(this.freqNode[0]);\n this.mods.frequency.connect(this.freqNode[1]);\n }\n this.started = true;\n this.osc2.started = true;\n }\n};\n\np5.Pulse.prototype.stop = function (time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n if (this.osc2.oscillator) {\n this.osc2.oscillator.stop(t + now);\n }\n this.dcOffset.stop(t + now);\n this.started = false;\n this.osc2.started = false;\n }\n};\n\np5.Pulse.prototype.freq = function (val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number') {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n var currentFreq = this.oscillator.frequency.value;\n this.oscillator.frequency.cancelScheduledValues(now);\n this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n this.osc2.oscillator.frequency.cancelScheduledValues(now);\n this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);\n this.osc2.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n\n if (this.freqMod) {\n this.freqMod.output.disconnect();\n this.freqMod = null;\n }\n } else if (val.output) {\n val.output.disconnect();\n val.output.connect(this.oscillator.frequency);\n val.output.connect(this.osc2.oscillator.frequency);\n this.freqMod = val;\n }\n};\n\n// inspiration: http://webaudiodemos.appspot.com/oscilloscope/\nfunction createDCOffset() {\n var ac = p5sound.audiocontext;\n var buffer = ac.createBuffer(1, 2048, ac.sampleRate);\n var data = buffer.getChannelData(0);\n for (var i = 0; i < 2048; i++) data[i] = 1.0;\n var bufferSource = ac.createBufferSource();\n bufferSource.buffer = buffer;\n bufferSource.loop = true;\n return bufferSource;\n}\n","import p5sound from './master';\n\n// generate noise buffers\nconst _whiteNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var whiteBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = whiteBuffer.getChannelData(0);\n for (var i = 0; i < bufferSize; i++) {\n noiseData[i] = Math.random() * 2 - 1;\n }\n whiteBuffer.type = 'white';\n return whiteBuffer;\n})();\n\nconst _pinkNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var pinkBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = pinkBuffer.getChannelData(0);\n var b0, b1, b2, b3, b4, b5, b6;\n b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n b0 = 0.99886 * b0 + white * 0.0555179;\n b1 = 0.99332 * b1 + white * 0.0750759;\n b2 = 0.969 * b2 + white * 0.153852;\n b3 = 0.8665 * b3 + white * 0.3104856;\n b4 = 0.55 * b4 + white * 0.5329522;\n b5 = -0.7616 * b5 - white * 0.016898;\n noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;\n noiseData[i] *= 0.11; // (roughly) compensate for gain\n b6 = white * 0.115926;\n }\n pinkBuffer.type = 'pink';\n return pinkBuffer;\n})();\n\nconst _brownNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var brownBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = brownBuffer.getChannelData(0);\n var lastOut = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n noiseData[i] = (lastOut + 0.02 * white) / 1.02;\n lastOut = noiseData[i];\n noiseData[i] *= 3.5;\n }\n brownBuffer.type = 'brown';\n return brownBuffer;\n})();\n\n/**\n * Noise is a type of oscillator that generates a buffer with random values.\n *\n * @class p5.Noise\n * @extends p5.Oscillator\n * @constructor\n * @param {String} type Type of noise can be 'white' (default),\n * 'brown' or 'pink'.\n */\np5.Noise = function (type) {\n var assignType;\n p5.Oscillator.call(this);\n delete this.f;\n delete this.freq;\n delete this.oscillator;\n\n if (type === 'brown') {\n assignType = _brownNoiseBuffer;\n } else if (type === 'pink') {\n assignType = _pinkNoiseBuffer;\n } else {\n assignType = _whiteNoiseBuffer;\n }\n this.buffer = assignType;\n};\n\np5.Noise.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Set type of noise to 'white', 'pink' or 'brown'.\n * White is the default.\n *\n * @method setType\n * @param {String} [type] 'white', 'pink' or 'brown'\n */\np5.Noise.prototype.setType = function (type) {\n switch (type) {\n case 'white':\n this.buffer = _whiteNoiseBuffer;\n break;\n case 'pink':\n this.buffer = _pinkNoiseBuffer;\n break;\n case 'brown':\n this.buffer = _brownNoiseBuffer;\n break;\n default:\n this.buffer = _whiteNoiseBuffer;\n }\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.start(now + 0.01);\n }\n};\n\np5.Noise.prototype.getType = function () {\n return this.buffer.type;\n};\n\np5.Noise.prototype.start = function () {\n if (this.started) {\n this.stop();\n }\n this.noise = p5sound.audiocontext.createBufferSource();\n this.noise.buffer = this.buffer;\n this.noise.loop = true;\n this.noise.connect(this.output);\n var now = p5sound.audiocontext.currentTime;\n this.noise.start(now);\n this.started = true;\n};\n\np5.Noise.prototype.stop = function () {\n var now = p5sound.audiocontext.currentTime;\n if (this.noise) {\n this.noise.stop(now);\n this.started = false;\n }\n};\n\np5.Noise.prototype.dispose = function () {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.noise) {\n this.noise.disconnect();\n this.stop(now);\n }\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n }\n this.output = null;\n this.panner = null;\n this.buffer = null;\n this.noise = null;\n};\n","import p5sound from './master';\n\n// an array of input sources\np5sound.inputSources = [];\n\n/**\n *

Get audio from an input, i.e. your computer's microphone.

\n *\n *

Turn the mic on/off with the start() and stop() methods. When the mic\n * is on, its volume can be measured with getLevel or by connecting an\n * FFT object.

\n *\n *

If you want to hear the AudioIn, use the .connect() method.\n * AudioIn does not connect to p5.sound output by default to prevent\n * feedback.

\n *\n *

Note: This uses the getUserMedia/\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\n * is limited to localhost and https, but access over http may be limited.

\n *\n * @class p5.AudioIn\n * @constructor\n * @param {Function} [errorCallback] A function to call if there is an error\n * accessing the AudioIn. For example,\n * Safari and iOS devices do not\n * currently allow microphone access.\n * @example\n *
\n * let mic;\n *\n * function setup(){\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(userStartAudio);\n * textAlign(CENTER);\n * mic = new p5.AudioIn();\n * mic.start();\n * }\n *\n * function draw(){\n * background(0);\n * fill(255);\n * text('tap to start', width/2, 20);\n *\n * micLevel = mic.getLevel();\n * let y = height - micLevel * height;\n * ellipse(width/2, y, 10, 10);\n * }\n *
\n */\np5.AudioIn = function (errorCallback) {\n // set up audio input\n /**\n * @property {GainNode} input\n */\n this.input = p5sound.audiocontext.createGain();\n /**\n * @property {GainNode} output\n */\n this.output = p5sound.audiocontext.createGain();\n\n /**\n * @property {MediaStream|null} stream\n */\n this.stream = null;\n /**\n * @property {MediaStreamAudioSourceNode|null} mediaStream\n */\n this.mediaStream = null;\n /**\n * @property {Number|null} currentSource\n */\n this.currentSource = null;\n\n /**\n * Client must allow browser to access their microphone / audioin source.\n * Default: false. Will become true when the client enables access.\n *\n * @property {Boolean} enabled\n */\n this.enabled = false;\n\n /**\n * Input amplitude, connect to it by default but not to master out\n *\n * @property {p5.Amplitude} amplitude\n */\n this.amplitude = new p5.Amplitude();\n this.output.connect(this.amplitude.input);\n\n if (\n !window.MediaStreamTrack ||\n !window.navigator.mediaDevices ||\n !window.navigator.mediaDevices.getUserMedia\n ) {\n errorCallback\n ? errorCallback()\n : window.alert(\n 'This browser does not support MediaStreamTrack and mediaDevices'\n );\n }\n\n // add to soundArray so we can dispose on close\n p5sound.soundArray.push(this);\n};\n\n/**\n * Start processing audio input. This enables the use of other\n * AudioIn methods like getLevel(). Note that by default, AudioIn\n * is not connected to p5.sound's output. So you won't hear\n * anything unless you use the connect() method.
\n *\n * Certain browsers limit access to the user's microphone. For example,\n * Chrome only allows access from localhost and over https. For this reason,\n * you may want to include an errorCallback—a function that is called in case\n * the browser won't provide mic access.\n *\n * @method start\n * @for p5.AudioIn\n * @param {Function} [successCallback] Name of a function to call on\n * success.\n * @param {Function} [errorCallback] Name of a function to call if\n * there was an error. For example,\n * some browsers do not support\n * getUserMedia.\n */\np5.AudioIn.prototype.start = function (successCallback, errorCallback) {\n var self = this;\n\n if (this.stream) {\n this.stop();\n }\n\n // set the audio source\n var audioSource = p5sound.inputSources[self.currentSource];\n var constraints = {\n audio: {\n sampleRate: p5sound.audiocontext.sampleRate,\n echoCancellation: false,\n },\n };\n\n // if developers determine which source to use\n if (p5sound.inputSources[this.currentSource]) {\n constraints.audio.deviceId = audioSource.deviceId;\n }\n\n window.navigator.mediaDevices\n .getUserMedia(constraints)\n .then(function (stream) {\n self.stream = stream;\n self.enabled = true;\n // Wrap a MediaStreamSourceNode around the live input\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\n self.mediaStream.connect(self.output);\n // only send to the Amplitude reader, so we can see it but not hear it.\n self.amplitude.setInput(self.output);\n if (successCallback) successCallback();\n })\n .catch(function (err) {\n if (errorCallback) errorCallback(err);\n else console.error(err);\n });\n};\n\n/**\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\n * If re-starting, the user may be prompted for permission access.\n *\n * @method stop\n * @for p5.AudioIn\n */\np5.AudioIn.prototype.stop = function () {\n if (this.stream) {\n this.stream.getTracks().forEach(function (track) {\n track.stop();\n });\n\n this.mediaStream.disconnect();\n\n delete this.mediaStream;\n delete this.stream;\n }\n};\n\n/**\n * Connect to an audio unit. If no parameter is provided, will\n * connect to the master output (i.e. your speakers).
\n *\n * @method connect\n * @for p5.AudioIn\n * @param {Object} [unit] An object that accepts audio input,\n * such as an FFT\n */\np5.AudioIn.prototype.connect = function (unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else if (unit.hasOwnProperty('analyser')) {\n this.output.connect(unit.analyser);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(p5sound.input);\n }\n};\n\n/**\n * Disconnect the AudioIn from all audio units. For example, if\n * connect() had been called, disconnect() will stop sending\n * signal to your speakers.
\n *\n * @method disconnect\n * @for p5.AudioIn\n */\np5.AudioIn.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n // stay connected to amplitude even if not outputting to p5\n this.output.connect(this.amplitude.input);\n }\n};\n\n/**\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\n * class contains its own instance of the Amplitude class to help\n * make it easy to get a microphone's volume level. Accepts an\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\n * .start() before using .getLevel().
\n *\n * @method getLevel\n * @for p5.AudioIn\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\n * Smooths values based on previous values.\n * @return {Number} Volume level (between 0.0 and 1.0)\n */\np5.AudioIn.prototype.getLevel = function (smoothing) {\n if (smoothing) {\n this.amplitude.smoothing = smoothing;\n }\n return this.amplitude.getLevel();\n};\n\n/**\n * Set amplitude (volume) of a mic input between 0 and 1.0.
\n *\n * @method amp\n * @for p5.AudioIn\n * @param {Number} vol between 0 and 1.0\n * @param {Number} [time] ramp time (optional)\n */\np5.AudioIn.prototype.amp = function (vol, t) {\n if (t) {\n var rampTime = t || 0;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(\n currentVol,\n p5sound.audiocontext.currentTime\n );\n this.output.gain.linearRampToValueAtTime(\n vol,\n rampTime + p5sound.audiocontext.currentTime\n );\n } else {\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\n }\n};\n\n/**\n * Returns a list of available input sources. This is a wrapper\n * for \n * MediaDevices.enumerateDevices() - Web APIs | MDN\n * and it returns a Promise.\n * @method getSources\n * @for p5.AudioIn\n * @param {Function} [successCallback] This callback function handles the sources when they\n * have been enumerated. The callback function\n * receives the deviceList array as its only argument\n * @param {Function} [errorCallback] This optional callback receives the error\n * message as its argument.\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\n * to the enumerateDevices() method\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\np5.AudioIn.prototype.getSources = function (onSuccess, onError) {\n return new Promise(function (resolve, reject) {\n window.navigator.mediaDevices\n .enumerateDevices()\n .then(function (devices) {\n p5sound.inputSources = devices.filter(function (device) {\n return device.kind === 'audioinput';\n });\n resolve(p5sound.inputSources);\n if (onSuccess) {\n onSuccess(p5sound.inputSources);\n }\n })\n .catch(function (error) {\n reject(error);\n if (onError) {\n onError(error);\n } else {\n console.error(\n 'This browser does not support MediaStreamTrack.getSources()'\n );\n }\n });\n });\n};\n\n/**\n * Set the input source. Accepts a number representing a\n * position in the array returned by getSources().\n * This is only available in browsers that support\n * \n * navigator.mediaDevices.enumerateDevices()\n *\n * @method setSource\n * @for p5.AudioIn\n * @param {number} num position of input source in the array\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\np5.AudioIn.prototype.setSource = function (num) {\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\n // set the current source\n this.currentSource = num;\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\n } else {\n console.log('unable to set input source');\n }\n\n // restart stream if currently active\n if (this.stream && this.stream.active) {\n this.start();\n }\n};\n\n// private method\np5.AudioIn.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop();\n\n if (this.output) {\n this.output.disconnect();\n }\n if (this.amplitude) {\n this.amplitude.disconnect();\n }\n delete this.amplitude;\n delete this.output;\n};\n","import p5sound from './master';\nimport CrossFade from 'Tone/component/CrossFade.js';\n\n/**\n * Effect is a base class for audio effects in p5.
\n * This module handles the nodes and methods that are\n * common and useful for current and future effects.\n *\n *\n * This class is extended by p5.Distortion,\n * p5.Compressor,\n * p5.Delay,\n * p5.Filter,\n * p5.Reverb.\n *\n * @class p5.Effect\n * @constructor\n *\n * @param {Object} [ac] Reference to the audio context of the p5 object\n * @param {AudioNode} [input] Gain Node effect wrapper\n * @param {AudioNode} [output] Gain Node effect wrapper\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\n * @param {AudioNode} [wet] Effects that extend this class should connect\n * to the wet signal to this gain node, so that dry and wet\n * signals are mixed properly.\n */\np5.Effect = function () {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n /**\n *\tThe p5.Effect class is built\n * \tusing Tone.js CrossFade\n * \t@private\n */\n\n this._drywet = new CrossFade(1);\n\n /**\n *\tIn classes that extend\n *\tp5.Effect, connect effect nodes\n *\tto the wet parameter\n */\n this.wet = this.ac.createGain();\n\n this.input.connect(this._drywet.a);\n this.wet.connect(this._drywet.b);\n this._drywet.connect(this.output);\n\n this.connect();\n\n //Add to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Set the output volume of the filter.\n *\n * @method amp\n * @for p5.Effect\n * @param {Number} [vol] amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts until rampTime\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\n */\np5.Effect.prototype.amp = function (vol, rampTime = 0, tFromNow = 0) {\n const now = p5sound.audiocontext.currentTime;\n const startTime = now + tFromNow;\n const endTime = startTime + rampTime + 0.001;\n const currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, startTime + 0.001);\n this.output.gain.linearRampToValueAtTime(vol, endTime);\n};\n\n/**\n * Link effects together in a chain\n * Example usage: filter.chain(reverb, delay, panner);\n * May be used with an open-ended number of arguments\n *\n * @method chain\n * @for p5.Effect\n * @param {Object} [arguments] Chain together multiple sound objects\n */\np5.Effect.prototype.chain = function () {\n if (arguments.length > 0) {\n this.connect(arguments[0]);\n for (var i = 1; i < arguments.length; i += 1) {\n arguments[i - 1].connect(arguments[i]);\n }\n }\n return this;\n};\n\n/**\n * Adjust the dry/wet value.\n *\n * @method drywet\n * @for p5.Effect\n * @param {Number} [fade] The desired drywet value (0 - 1.0)\n */\np5.Effect.prototype.drywet = function (fade) {\n if (typeof fade !== 'undefined') {\n this._drywet.fade.value = fade;\n }\n return this._drywet.fade.value;\n};\n\n/**\n * Send output to a p5.js-sound, Web Audio Node, or use signal to\n * control an AudioParam\n *\n * @method connect\n * @for p5.Effect\n * @param {Object} unit\n */\np5.Effect.prototype.connect = function (unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all output.\n * @method disconnect\n * @for p5.Effect\n */\np5.Effect.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\np5.Effect.prototype.dispose = function () {\n // remove refernce form soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n if (this._drywet) {\n this._drywet.disconnect();\n delete this._drywet;\n }\n\n if (this.wet) {\n this.wet.disconnect();\n delete this.wet;\n }\n\n this.ac = undefined;\n};\n\nconst Effect = p5.Effect;\n\nexport default Effect","import Effect from './effect';\n\n/**\n *

A p5.Filter uses a Web Audio Biquad Filter to filter\n * the frequency response of an input source. Subclasses\n * include:

\n * p5.LowPass:\n * Allows frequencies below the cutoff frequency to pass through,\n * and attenuates frequencies above the cutoff.
\n * p5.HighPass:\n * The opposite of a lowpass filter.
\n * p5.BandPass:\n * Allows a range of frequencies to pass through and attenuates\n * the frequencies below and above this frequency range.
\n *\n * The .res() method controls either width of the\n * bandpass, or resonance of the low/highpass cutoff frequency.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Filter\n * @extends p5.Effect\n * @constructor\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\n * @example\n *
\n * let fft, noise, filter;\n *\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(makeNoise);\n * fill(255, 0, 255);\n *\n * filter = new p5.BandPass();\n * noise = new p5.Noise();\n * noise.disconnect();\n * noise.connect(filter);\n *\n * fft = new p5.FFT();\n * }\n *\n * function draw() {\n * background(220);\n *\n * // set the BandPass frequency based on mouseX\n * let freq = map(mouseX, 0, width, 20, 10000);\n * freq = constrain(freq, 0, 22050);\n * filter.freq(freq);\n * // give the filter a narrow band (lower res = wider bandpass)\n * filter.res(50);\n *\n * // draw filtered spectrum\n * let spectrum = fft.analyze();\n * noStroke();\n * for (let i = 0; i < spectrum.length; i++) {\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width/spectrum.length, h);\n * }\n * if (!noise.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text('Frequency: ' + round(freq)+'Hz', 20, 20, width - 20);\n * }\n * }\n *\n * function makeNoise() {\n * // see also: `userStartAudio()`\n * noise.start();\n * noise.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * noise.amp(0, 0.2);\n * }\n *\n *
\n */\np5.Filter = function (type) {\n Effect.call(this);\n //add extend Effect by adding a Biquad Filter\n\n /**\n * The p5.Filter is built with a\n * \n * Web Audio BiquadFilter Node.\n *\n * @property {DelayNode} biquadFilter\n */\n\n this.biquad = this.ac.createBiquadFilter();\n\n this.input.connect(this.biquad);\n\n this.biquad.connect(this.wet);\n\n if (type) {\n this.setType(type);\n }\n\n //Properties useful for the toggle method.\n this._on = true;\n this._untoggledType = this.biquad.type;\n};\np5.Filter.prototype = Object.create(Effect.prototype);\n\n/**\n * Filter an audio signal according to a set\n * of filter parameters.\n *\n * @method process\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance/Width of the filter frequency\n * from 0.001 to 1000\n */\np5.Filter.prototype.process = function (src, freq, res, time) {\n src.connect(this.input);\n this.set(freq, res, time);\n};\n\n/**\n * Set the frequency and the resonance of the filter.\n *\n * @method set\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\np5.Filter.prototype.set = function (freq, res, time) {\n if (freq) {\n this.freq(freq, time);\n }\n if (res) {\n this.res(res, time);\n }\n};\n\n/**\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\n * human hearing, although in reality most people hear in a narrower\n * range).\n *\n * @method freq\n * @param {Number} freq Filter Frequency\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current frequency value\n */\np5.Filter.prototype.freq = function (freq, time) {\n var t = time || 0;\n if (freq <= 0) {\n freq = 1;\n }\n if (typeof freq === 'number') {\n this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.frequency.exponentialRampToValueAtTime(\n freq,\n this.ac.currentTime + 0.02 + t\n );\n } else if (freq) {\n freq.connect(this.biquad.frequency);\n }\n return this.biquad.frequency.value;\n};\n\n/**\n * Controls either width of a bandpass frequency,\n * or the resonance of a low/highpass cutoff frequency.\n *\n * @method res\n * @param {Number} res Resonance/Width of filter freq\n * from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current res value\n */\np5.Filter.prototype.res = function (res, time) {\n var t = time || 0;\n if (typeof res === 'number') {\n this.biquad.Q.value = res;\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);\n } else if (res) {\n res.connect(this.biquad.Q);\n }\n return this.biquad.Q.value;\n};\n\n/**\n * Controls the gain attribute of a Biquad Filter.\n * This is distinctly different from .amp() which is inherited from p5.Effect\n * .amp() controls the volume via the output gain node\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\n *\n * @method gain\n * @param {Number} gain\n * @return {Number} Returns the current or updated gain value\n */\np5.Filter.prototype.gain = function (gain, time) {\n var t = time || 0;\n if (typeof gain === 'number') {\n this.biquad.gain.value = gain;\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.gain.linearRampToValueAtTime(\n gain,\n this.ac.currentTime + 0.02 + t\n );\n } else if (gain) {\n gain.connect(this.biquad.gain);\n }\n return this.biquad.gain.value;\n};\n\n/**\n * Toggle function. Switches between the specified type and allpass\n *\n * @method toggle\n * @return {boolean} [Toggle value]\n */\np5.Filter.prototype.toggle = function () {\n this._on = !this._on;\n\n if (this._on === true) {\n this.biquad.type = this._untoggledType;\n } else if (this._on === false) {\n this.biquad.type = 'allpass';\n }\n\n return this._on;\n};\n\n/**\n * Set the type of a p5.Filter. Possible types include:\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\n * \"allpass\".\n *\n * @method setType\n * @param {String} t\n */\np5.Filter.prototype.setType = function (t) {\n this.biquad.type = t;\n this._untoggledType = this.biquad.type;\n};\n\np5.Filter.prototype.dispose = function () {\n // remove reference from soundArray\n Effect.prototype.dispose.apply(this);\n if (this.biquad) {\n this.biquad.disconnect();\n delete this.biquad;\n }\n};\n\n/**\n * Constructor: new p5.LowPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('lowpass').\n * See p5.Filter for methods.\n *\n * @class p5.LowPass\n * @constructor\n * @extends p5.Filter\n */\np5.LowPass = function () {\n p5.Filter.call(this, 'lowpass');\n};\np5.LowPass.prototype = Object.create(p5.Filter.prototype);\n\n/**\n * Constructor: new p5.HighPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('highpass').\n * See p5.Filter for methods.\n *\n * @class p5.HighPass\n * @constructor\n * @extends p5.Filter\n */\np5.HighPass = function () {\n p5.Filter.call(this, 'highpass');\n};\np5.HighPass.prototype = Object.create(p5.Filter.prototype);\n\n/**\n * Constructor: new p5.BandPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('bandpass').\n * See p5.Filter for methods.\n *\n * @class p5.BandPass\n * @constructor\n * @extends p5.Filter\n */\np5.BandPass = function () {\n p5.Filter.call(this, 'bandpass');\n};\np5.BandPass.prototype = Object.create(p5.Filter.prototype);\n\nexport default p5.Filter;\n","import Filter from './filter';\nimport p5sound from './master';\n\n/**\n * EQFilter extends p5.Filter with constraints\n * necessary for the p5.EQ\n *\n * @private\n */\nvar EQFilter = function (freq, res) {\n Filter.call(this, 'peaking');\n this.disconnect();\n this.set(freq, res);\n this.biquad.gain.value = 0;\n delete this.input;\n delete this.output;\n delete this._drywet;\n delete this.wet;\n};\nEQFilter.prototype = Object.create(Filter.prototype);\n\nEQFilter.prototype.amp = function () {\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\n};\nEQFilter.prototype.drywet = function () {\n console.warn('`drywet()` is not available for p5.EQ bands.');\n};\nEQFilter.prototype.connect = function (unit) {\n var u = unit || p5.soundOut.input;\n if (this.biquad) {\n this.biquad.connect(u.input ? u.input : u);\n } else {\n this.output.connect(u.input ? u.input : u);\n }\n};\n\nEQFilter.prototype.disconnect = function () {\n if (this.biquad) {\n this.biquad.disconnect();\n }\n};\nEQFilter.prototype.dispose = function () {\n // remove reference form soundArray\n const index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n this.disconnect();\n delete this.biquad;\n};\n\nexport default EQFilter;\n","import Effect from './effect';\nimport EQFilter from './eqFilter';\n\n/**\n * p5.EQ is an audio effect that performs the function of a multiband\n * audio equalizer. Equalization is used to adjust the balance of\n * frequency compoenents of an audio signal. This process is commonly used\n * in sound production and recording to change the waveform before it reaches\n * a sound output device. EQ can also be used as an audio effect to create\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\n * built using a chain of Web Audio Biquad Filter Nodes and can be\n * instantiated with 3 or 8 bands. Bands can be added or removed from\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.EQ\n * @constructor\n * @extends p5.Effect\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\n * @return {Object} p5.EQ object\n *\n * @example\n *
\n * let eq, soundFile\n * let eqBandIndex = 0;\n * let eqBandNames = ['lows', 'mids', 'highs'];\n *\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * soundFile = loadSound('assets/beat');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(toggleSound);\n *\n * eq = new p5.EQ(eqBandNames.length);\n * soundFile.disconnect();\n * eq.process(soundFile);\n * }\n *\n * function draw() {\n * background(30);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n * text('filtering ', 50, 25);\n *\n * fill(255, 40, 255);\n * textSize(26);\n * text(eqBandNames[eqBandIndex], 50, 55);\n *\n * fill(255);\n * textSize(9);\n *\n * if (!soundFile.isPlaying()) {\n * text('tap to play', 50, 80);\n * } else {\n * text('tap to filter next band', 50, 80)\n * }\n * }\n *\n * function toggleSound() {\n * if (!soundFile.isPlaying()) {\n * soundFile.play();\n * } else {\n * eqBandIndex = (eqBandIndex + 1) % eq.bands.length;\n * }\n *\n * for (let i = 0; i < eq.bands.length; i++) {\n * eq.bands[i].gain(0);\n * }\n * // filter the band we want to filter\n * eq.bands[eqBandIndex].gain(-40);\n * }\n *
\n */\np5.EQ = function (_eqsize) {\n Effect.call(this);\n\n //p5.EQ can be of size (3) or (8), defaults to 3\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\n\n var factor;\n _eqsize === 3 ? (factor = Math.pow(2, 3)) : (factor = 2);\n\n /**\n * The p5.EQ is built with abstracted p5.Filter objects.\n * To modify any bands, use methods of the \n * p5.Filter API, especially `gain` and `freq`.\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\n * @property {Array} bands\n *\n */\n this.bands = [];\n\n var freq, res;\n for (var i = 0; i < _eqsize; i++) {\n if (i === _eqsize - 1) {\n freq = 21000;\n res = 0.01;\n } else if (i === 0) {\n freq = 100;\n res = 0.1;\n } else if (i === 1) {\n freq = _eqsize === 3 ? 360 * factor : 360;\n res = 1;\n } else {\n freq = this.bands[i - 1].freq() * factor;\n res = 1;\n }\n this.bands[i] = this._newBand(freq, res);\n\n if (i > 0) {\n this.bands[i - 1].connect(this.bands[i].biquad);\n } else {\n this.input.connect(this.bands[i].biquad);\n }\n }\n this.bands[_eqsize - 1].connect(this.output);\n};\np5.EQ.prototype = Object.create(Effect.prototype);\n\n/**\n * Process an input by connecting it to the EQ\n * @method process\n * @param {Object} src Audio source\n */\np5.EQ.prototype.process = function (src) {\n src.connect(this.input);\n};\n\n// /**\n// * Set the frequency and gain of each band in the EQ. This method should be\n// * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\n// * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\n// *\n// * @method set\n// * @for p5.EQ\n// * @param {Number} [freq0] Frequency value for band with index 0\n// * @param {Number} [gain0] Gain value for band with index 0\n// * @param {Number} [freq1] Frequency value for band with index 1\n// * @param {Number} [gain1] Gain value for band with index 1\n// * @param {Number} [freq2] Frequency value for band with index 2\n// * @param {Number} [gain2] Gain value for band with index 2\n// * @param {Number} [freq3] Frequency value for band with index 3\n// * @param {Number} [gain3] Gain value for band with index 3\n// * @param {Number} [freq4] Frequency value for band with index 4\n// * @param {Number} [gain4] Gain value for band with index 4\n// * @param {Number} [freq5] Frequency value for band with index 5\n// * @param {Number} [gain5] Gain value for band with index 5\n// * @param {Number} [freq6] Frequency value for band with index 6\n// * @param {Number} [gain6] Gain value for band with index 6\n// * @param {Number} [freq7] Frequency value for band with index 7\n// * @param {Number} [gain7] Gain value for band with index 7\n// */\np5.EQ.prototype.set = function () {\n if (arguments.length === this.bands.length * 2) {\n for (var i = 0; i < arguments.length; i += 2) {\n this.bands[i / 2].freq(arguments[i]);\n this.bands[i / 2].gain(arguments[i + 1]);\n }\n } else {\n console.error(\n 'Argument mismatch. .set() should be called with ' +\n this.bands.length * 2 +\n ' arguments. (one frequency and gain value pair for each band of the eq)'\n );\n }\n};\n\n/**\n * Add a new band. Creates a p5.Filter and strips away everything but\n * the raw biquad filter. This method returns an abstracted p5.Filter,\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\n * @private\n * @for p5.EQ\n * @method _newBand\n * @param {Number} freq\n * @param {Number} res\n * @return {Object} Abstracted Filter\n */\np5.EQ.prototype._newBand = function (freq, res) {\n return new EQFilter(freq, res);\n};\n\np5.EQ.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n\n if (this.bands) {\n while (this.bands.length > 0) {\n delete this.bands.pop().dispose();\n }\n delete this.bands;\n }\n};\n\nexport default p5.EQ;\n","import Effect from './effect';\n\n/**\n * Panner3D is based on the \n * Web Audio Spatial Panner Node.\n * This panner is a spatial processing node that allows audio to be positioned\n * and oriented in 3D space.\n *\n * The position is relative to an \n * Audio Context Listener, which can be accessed\n * by p5.soundOut.audiocontext.listener\n *\n *\n * @class p5.Panner3D\n * @constructor\n */\n\np5.Panner3D = function () {\n Effect.call(this);\n\n /**\n * \n * Web Audio Spatial Panner Node\n *\n * Properties include
\n * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType)\n * : \"equal power\" or \"HRTF\"
\n * [DistanceModel](https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType)\n * : \"linear\", \"inverse\", or \"exponential\"\n *\n * @property {AudioNode} panner\n *\n */\n this.panner = this.ac.createPanner();\n this.panner.panningModel = 'HRTF';\n this.panner.distanceModel = 'linear';\n this.panner.connect(this.output);\n this.input.connect(this.panner);\n};\n\np5.Panner3D.prototype = Object.create(Effect.prototype);\n\n/**\n * Connect an audio sorce\n *\n * @method process\n * @for p5.Panner3D\n * @param {Object} src Input source\n */\np5.Panner3D.prototype.process = function (src) {\n src.connect(this.input);\n};\n/**\n * Set the X,Y,Z position of the Panner\n * @method set\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\np5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.panner.positionX.value,\n this.panner.positionY.value,\n this.panner.positionZ.value,\n ];\n};\n\n/**\n * Getter and setter methods for position coordinates\n * @method positionX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for position coordinates\n * @method positionY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for position coordinates\n * @method positionZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\np5.Panner3D.prototype.positionX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.positionX.value = xVal;\n this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.panner.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.positionX);\n }\n return this.panner.positionX.value;\n};\np5.Panner3D.prototype.positionY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.positionY.value = yVal;\n this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.panner.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.positionY);\n }\n return this.panner.positionY.value;\n};\np5.Panner3D.prototype.positionZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.positionZ.value = zVal;\n this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.panner.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.positionZ);\n }\n return this.panner.positionZ.value;\n};\n\n/**\n * Set the X,Y,Z position of the Panner\n * @method orient\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\np5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) {\n this.orientX(xVal, time);\n this.orientY(yVal, time);\n this.orientZ(zVal, time);\n return [\n this.panner.orientationX.value,\n this.panner.orientationY.value,\n this.panner.orientationZ.value,\n ];\n};\n\n/**\n * Getter and setter methods for orient coordinates\n * @method orientX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for orient coordinates\n * @method orientY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for orient coordinates\n * @method orientZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\np5.Panner3D.prototype.orientX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.orientationX.value = xVal;\n this.panner.orientationX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.orientationX);\n }\n return this.panner.orientationX.value;\n};\np5.Panner3D.prototype.orientY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.orientationY.value = yVal;\n this.panner.orientationY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.orientationY);\n }\n return this.panner.orientationY.value;\n};\np5.Panner3D.prototype.orientZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.orientationZ.value = zVal;\n this.panner.orientationZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.orientationZ);\n }\n return this.panner.orientationZ.value;\n};\n\n/**\n * Set the rolloff factor and max distance\n * @method setFalloff\n * @for p5.Panner3D\n * @param {Number} [maxDistance]\n * @param {Number} [rolloffFactor]\n */\np5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) {\n this.maxDist(maxDistance);\n this.rolloff(rolloffFactor);\n};\n/**\n * Maxium distance between the source and the listener\n * @method maxDist\n * @for p5.Panner3D\n * @param {Number} maxDistance\n * @return {Number} updated value\n */\np5.Panner3D.prototype.maxDist = function (maxDistance) {\n if (typeof maxDistance === 'number') {\n this.panner.maxDistance = maxDistance;\n }\n return this.panner.maxDistance;\n};\n\n/**\n * How quickly the volume is reduced as the source moves away from the listener\n * @method rollof\n * @for p5.Panner3D\n * @param {Number} rolloffFactor\n * @return {Number} updated value\n */\np5.Panner3D.prototype.rolloff = function (rolloffFactor) {\n if (typeof rolloffFactor === 'number') {\n this.panner.rolloffFactor = rolloffFactor;\n }\n return this.panner.rolloffFactor;\n};\n\np5.Panner3D.dispose = function () {\n Effect.prototype.dispose.apply(this);\n if (this.panner) {\n this.panner.disconnect();\n delete this.panner;\n }\n};\n\nexport default p5.Panner3D;\n","import p5sound from './master';\n\n// /**\n// * listener is a class that can construct both a Spatial Panner\n// * and a Spatial Listener. The panner is based on the\n// * Web Audio Spatial Panner Node\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\n// * This panner is a spatial processing node that allows audio to be positioned\n// * and oriented in 3D space.\n// *\n// * The Listener modifies the properties of the Audio Context Listener.\n// * Both objects types use the same methods. The default is a spatial panner.\n// *\n// * p5.Panner3D - Constructs a Spatial Panner
\n// * p5.Listener3D - Constructs a Spatial Listener
\n// *\n// * @class listener\n// * @constructor\n// * @return {Object} p5.Listener3D Object\n// *\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\n// */\n\np5.Listener3D = function (type) {\n this.ac = p5sound.audiocontext;\n this.listener = this.ac.listener;\n};\n\n// /**\n// * Connect an audio sorce\n// * @param {Object} src Input source\n// */\np5.Listener3D.prototype.process = function (src) {\n src.connect(this.input);\n};\n// /**\n// * Set the X,Y,Z position of the Panner\n// * @param {[Number]} xVal\n// * @param {[Number]} yVal\n// * @param {[Number]} zVal\n// * @param {[Number]} time\n// * @return {[Array]} [Updated x, y, z values as an array]\n// */\np5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.listener.positionX.value,\n this.listener.positionY.value,\n this.listener.positionZ.value,\n ];\n};\n\n// /**\n// * Getter and setter methods for position coordinates\n// * @return {Number} [updated coordinate value]\n// */\np5.Listener3D.prototype.positionX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.positionX.value = xVal;\n this.listener.positionX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.positionX);\n }\n return this.listener.positionX.value;\n};\np5.Listener3D.prototype.positionY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.positionY.value = yVal;\n this.listener.positionY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.positionY);\n }\n return this.listener.positionY.value;\n};\np5.Listener3D.prototype.positionZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.positionZ.value = zVal;\n this.listener.positionZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.positionZ);\n }\n return this.listener.positionZ.value;\n};\n\n// cannot define method when class definition is commented\n// /**\n// * Overrides the listener orient() method because Listener has slightly\n// * different params. In human terms, Forward vectors are the direction the\n// * nose is pointing. Up vectors are the direction of the top of the head.\n// *\n// * @method orient\n// * @param {Number} xValF Forward vector X direction\n// * @param {Number} yValF Forward vector Y direction\n// * @param {Number} zValF Forward vector Z direction\n// * @param {Number} xValU Up vector X direction\n// * @param {Number} yValU Up vector Y direction\n// * @param {Number} zValU Up vector Z direction\n// * @param {Number} time\n// * @return {Array} All orienation params\n// */\np5.Listener3D.prototype.orient = function (\n xValF,\n yValF,\n zValF,\n xValU,\n yValU,\n zValU,\n time\n) {\n if (arguments.length === 3 || arguments.length === 4) {\n time = arguments[3];\n this.orientForward(xValF, yValF, zValF, time);\n } else if (arguments.length === 6 || arguments === 7) {\n this.orientForward(xValF, yValF, zValF);\n this.orientUp(xValU, yValU, zValU, time);\n }\n\n return [\n this.listener.forwardX.value,\n this.listener.forwardY.value,\n this.listener.forwardZ.value,\n this.listener.upX.value,\n this.listener.upY.value,\n this.listener.upZ.value,\n ];\n};\n\np5.Listener3D.prototype.orientForward = function (xValF, yValF, zValF, time) {\n this.forwardX(xValF, time);\n this.forwardY(yValF, time);\n this.forwardZ(zValF, time);\n\n return [\n this.listener.forwardX,\n this.listener.forwardY,\n this.listener.forwardZ,\n ];\n};\n\np5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) {\n this.upX(xValU, time);\n this.upY(yValU, time);\n this.upZ(zValU, time);\n\n return [this.listener.upX, this.listener.upY, this.listener.upZ];\n};\n// /**\n// * Getter and setter methods for orient coordinates\n// * @return {Number} [updated coordinate value]\n// */\np5.Listener3D.prototype.forwardX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.forwardX.value = xVal;\n this.listener.forwardX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.forwardX);\n }\n return this.listener.forwardX.value;\n};\np5.Listener3D.prototype.forwardY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.forwardY.value = yVal;\n this.listener.forwardY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.forwardY);\n }\n return this.listener.forwardY.value;\n};\np5.Listener3D.prototype.forwardZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.forwardZ.value = zVal;\n this.listener.forwardZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.forwardZ);\n }\n return this.listener.forwardZ.value;\n};\np5.Listener3D.prototype.upX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.upX.value = xVal;\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.upX);\n }\n return this.listener.upX.value;\n};\np5.Listener3D.prototype.upY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.upY.value = yVal;\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.upY);\n }\n return this.listener.upY.value;\n};\np5.Listener3D.prototype.upZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.upZ.value = zVal;\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.upZ);\n }\n return this.listener.upZ.value;\n};\n\nexport default p5.Listener3D;\n","import Filter from './filter';\nimport Effect from './effect';\n\n/**\n * Delay is an echo effect. It processes an existing sound source,\n * and outputs a delayed version of that sound. The p5.Delay can\n * produce different effects depending on the delayTime, feedback,\n * filter, and type. In the example below, a feedback of 0.5 (the\n * default value) will produce a looping delay that decreases in\n * volume by 50% each repeat. A filter will cut out the high\n * frequencies so that the delay does not sound as piercing as the\n * original source.\n *\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n * @class p5.Delay\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * osc = new p5.Oscillator('square');\n * osc.amp(0.5);\n * delay = new p5.Delay();\n *\n * // delay.process() accepts 4 parameters:\n * // source, delayTime (in seconds), feedback, filter frequency\n * delay.process(osc, 0.12, .7, 2300);\n *\n * cnv.mousePressed(oscStart);\n * }\n *\n * function oscStart() {\n * osc.start();\n * }\n *\n * function mouseReleased() {\n * osc.stop();\n * }\n *
\n */\np5.Delay = function () {\n Effect.call(this);\n\n this._split = this.ac.createChannelSplitter(2);\n this._merge = this.ac.createChannelMerger(2);\n\n this._leftGain = this.ac.createGain();\n this._rightGain = this.ac.createGain();\n\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n *\n * @for p5.Delay\n * @property {DelayNode} leftDelay\n */\n this.leftDelay = this.ac.createDelay();\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n * @for p5.Delay\n * @property {DelayNode} rightDelay\n */\n this.rightDelay = this.ac.createDelay();\n\n this._leftFilter = new Filter();\n this._rightFilter = new Filter();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\n this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n\n // graph routing\n this.input.connect(this._split);\n this.leftDelay.connect(this._leftGain);\n this.rightDelay.connect(this._rightGain);\n this._leftGain.connect(this._leftFilter.input);\n this._rightGain.connect(this._rightFilter.input);\n this._merge.connect(this.wet);\n\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n\n // default routing\n this.setType(0);\n\n this._maxDelay = this.leftDelay.delayTime.maxValue;\n\n // set initial feedback to 0.5\n this.feedback(0.5);\n};\n\np5.Delay.prototype = Object.create(Effect.prototype);\n/**\n * Add delay to an audio signal according to a set\n * of delay parameters.\n *\n * @method process\n * @for p5.Delay\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\n * Some browsers limit delayTime to\n * 1 second.\n * @param {Number} [feedback] sends the delay back through itself\n * in a loop that decreases in volume\n * each time.\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\n * below the lowPass will be part of the\n * delay.\n */\np5.Delay.prototype.process = function (src, _delayTime, _feedback, _filter) {\n var feedback = _feedback || 0;\n var delayTime = _delayTime || 0;\n if (feedback >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n }\n if (delayTime >= this._maxDelay) {\n throw new Error(\n 'Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.'\n );\n }\n\n src.connect(this.input);\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this._leftGain.gain.value = feedback;\n this._rightGain.gain.value = feedback;\n\n if (_filter) {\n this._leftFilter.freq(_filter);\n this._rightFilter.freq(_filter);\n }\n};\n\n/**\n * Set the delay (echo) time, in seconds. Usually this value will be\n * a floating point number between 0.0 and 1.0.\n *\n * @method delayTime\n * @for p5.Delay\n * @param {Number} delayTime Time (in seconds) of the delay\n */\np5.Delay.prototype.delayTime = function (t) {\n // if t is an audio node...\n if (typeof t !== 'number') {\n t.connect(this.leftDelay.delayTime);\n t.connect(this.rightDelay.delayTime);\n } else {\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n }\n};\n\n/**\n * Feedback occurs when Delay sends its signal back through its input\n * in a loop. The feedback amount determines how much signal to send each\n * time through the loop. A feedback greater than 1.0 is not desirable because\n * it will increase the overall output each time through the loop,\n * creating an infinite feedback loop. The default value is 0.5\n *\n * @method feedback\n * @for p5.Delay\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\n * Oscillator that can be used to\n * modulate this param\n * @returns {Number} Feedback value\n *\n */\np5.Delay.prototype.feedback = function (f) {\n // if f is an audio node...\n if (f && typeof f !== 'number') {\n f.connect(this._leftGain.gain);\n f.connect(this._rightGain.gain);\n } else if (f >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n } else if (typeof f === 'number') {\n this._leftGain.gain.value = f;\n this._rightGain.gain.value = f;\n }\n\n // return value of feedback\n return this._leftGain.gain.value;\n};\n\n/**\n * Set a lowpass filter frequency for the delay. A lowpass filter\n * will cut off any frequencies higher than the filter frequency.\n *\n * @method filter\n * @for p5.Delay\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\n * frequencies higher than the filter frequency.\n * @param {Number|Object} res Resonance of the filter frequency\n * cutoff, or an object (i.e. a p5.Oscillator)\n * that can be used to modulate this parameter.\n * High numbers (i.e. 15) will produce a resonance,\n * low numbers (i.e. .2) will produce a slope.\n */\np5.Delay.prototype.filter = function (freq, q) {\n this._leftFilter.set(freq, q);\n this._rightFilter.set(freq, q);\n};\n\n/**\n * Choose a preset type of delay. 'pingPong' bounces the signal\n * from the left to the right channel to produce a stereo effect.\n * Any other parameter will revert to the default delay setting.\n *\n * @method setType\n * @for p5.Delay\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\n */\np5.Delay.prototype.setType = function (t) {\n if (t === 1) {\n t = 'pingPong';\n }\n this._split.disconnect();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n this._split.connect(this.leftDelay, 0);\n this._split.connect(this.rightDelay, 1);\n switch (t) {\n case 'pingPong':\n this._rightFilter.setType(this._leftFilter.biquad.type);\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.rightDelay);\n this._rightFilter.output.connect(this.leftDelay);\n break;\n default:\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.leftDelay);\n this._rightFilter.output.connect(this.rightDelay);\n }\n};\n\n// DocBlocks for methods inherited from p5.Effect\n/**\n * Set the output level of the delay effect.\n *\n * @method amp\n * @for p5.Delay\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n/**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Delay\n * @param {Object} unit\n */\n/**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Delay\n */\n\np5.Delay.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n\n this._split.disconnect();\n this._leftFilter.dispose();\n this._rightFilter.dispose();\n this._merge.disconnect();\n this._leftGain.disconnect();\n this._rightGain.disconnect();\n this.leftDelay.disconnect();\n this.rightDelay.disconnect();\n\n this._split = undefined;\n this._leftFilter = undefined;\n this._rightFilter = undefined;\n this._merge = undefined;\n this._leftGain = undefined;\n this._rightGain = undefined;\n this.leftDelay = undefined;\n this.rightDelay = undefined;\n};\nexport default p5.Delay;\n","import CustomError from './errorHandler';\nimport Effect from './effect';\n\n/**\n * Reverb adds depth to a sound through a large number of decaying\n * echoes. It creates the perception that sound is occurring in a\n * physical space. The p5.Reverb has paramters for Time (how long does the\n * reverb last) and decayRate (how much the sound decays with each echo)\n * that can be set with the .set() or .process() methods. The p5.Convolver\n * extends p5.Reverb allowing you to recreate the sound of actual physical\n * spaces through convolution.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Reverb\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let soundFile, reverb;\n * function preload() {\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * reverb = new p5.Reverb();\n * soundFile.disconnect(); // so we'll only hear reverb...\n *\n * // connect soundFile to reverb, process w/\n * // 3 second reverbTime, decayRate of 2%\n * reverb.process(soundFile, 3, 2);\n * }\n *\n * function draw() {\n * let dryWet = constrain(map(mouseX, 0, width, 0, 1), 0, 1);\n * // 1 = all reverb, 0 = no reverb\n * reverb.drywet(dryWet);\n *\n * background(220);\n * text('tap to play', 10, 20);\n * text('dry/wet: ' + round(dryWet * 100) + '%', 10, height - 20);\n * }\n *\n * function playSound() {\n * soundFile.play();\n * }\n *
\n */\n\np5.Reverb = function () {\n Effect.call(this);\n\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n // default params\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n};\n\np5.Reverb.prototype = Object.create(Effect.prototype);\n\np5.Reverb.prototype._initConvolverNode = function () {\n this.convolverNode = this.ac.createConvolver();\n this.input.connect(this.convolverNode);\n this.convolverNode.connect(this.wet);\n};\n\np5.Reverb.prototype._teardownConvolverNode = function () {\n if (this.convolverNode) {\n this.convolverNode.disconnect();\n delete this.convolverNode;\n }\n};\n\np5.Reverb.prototype._setBuffer = function (audioBuffer) {\n this._teardownConvolverNode();\n this._initConvolverNode();\n this.convolverNode.buffer = audioBuffer;\n};\n/**\n * Connect a source to the reverb, and assign reverb parameters.\n *\n * @method process\n * @for p5.Reverb\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\np5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) {\n src.connect(this.input);\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n};\n\n/**\n * Set the reverb settings. Similar to .process(), but without\n * assigning a new input.\n *\n * @method set\n * @for p5.Reverb\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\np5.Reverb.prototype.set = function (seconds, decayRate, reverse) {\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n};\n\n// DocBlocks for methods inherited from p5.Effect\n/**\n * Set the output level of the reverb effect.\n *\n * @method amp\n * @for p5.Reverb\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n/**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Reverb\n * @param {Object} unit\n */\n/**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Reverb\n */\n\n/**\n * Inspired by Simple Reverb by Jordan Santell\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\n *\n * Utility function for building an impulse response\n * based on the module parameters.\n *\n * @private\n */\np5.Reverb.prototype._buildImpulse = function () {\n var rate = this.ac.sampleRate;\n var length = rate * this._seconds;\n var decay = this._decay;\n var impulse = this.ac.createBuffer(2, length, rate);\n var impulseL = impulse.getChannelData(0);\n var impulseR = impulse.getChannelData(1);\n var n, i;\n for (i = 0; i < length; i++) {\n n = this._reverse ? length - i : i;\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n }\n this._setBuffer(impulse);\n};\n\np5.Reverb.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n this._teardownConvolverNode();\n};\n\n// =======================================================================\n// *** p5.Convolver ***\n// =======================================================================\n\n/**\n *

p5.Convolver extends p5.Reverb. It can emulate the sound of real\n * physical spaces through a process called \n * convolution.

\n *\n *

Convolution multiplies any audio input by an \"impulse response\"\n * to simulate the dispersion of sound over time. The impulse response is\n * generated from an audio file that you provide. One way to\n * generate an impulse response is to pop a balloon in a reverberant space\n * and record the echo. Convolution can also be used to experiment with\n * sound.

\n *\n *

Use the method createConvolution(path) to instantiate a\n * p5.Convolver with a path to your impulse response audio file.

\n *\n * @class p5.Convolver\n * @extends p5.Effect\n * @constructor\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call when loading succeeds\n * @param {Function} [errorCallback] function to call if loading fails.\n * This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\np5.Convolver = function (path, callback, errorCallback) {\n p5.Reverb.call(this);\n\n /**\n * Internally, the p5.Convolver uses the a\n * \n * Web Audio Convolver Node.\n *\n * @property {ConvolverNode} convolverNode\n */\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n if (path) {\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n } else {\n // parameters\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n }\n};\n\np5.Convolver.prototype = Object.create(p5.Reverb.prototype);\n\np5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\n\n/**\n * Create a p5.Convolver. Accepts a path to a soundfile\n * that will be used to generate an impulse response.\n *\n * @method createConvolver\n * @for p5\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call if loading is successful.\n * The object will be passed in as the argument\n * to the callback function.\n * @param {Function} [errorCallback] function to call if loading is not successful.\n * A custom error will be passed in as the argument\n * to the callback function.\n * @return {p5.Convolver}\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\np5.prototype.createConvolver = function (path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n var self = this;\n var cReverb = new p5.Convolver(\n path,\n function (buffer) {\n if (typeof callback === 'function') {\n callback(buffer);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n errorCallback\n );\n cReverb.impulses = [];\n return cReverb;\n};\n\n/**\n * Private method to load a buffer as an Impulse Response,\n * assign it to the convolverNode, and add to the Array of .impulses.\n *\n * @param {String} path\n * @param {Function} callback\n * @param {Function} errorCallback\n * @private\n */\np5.Convolver.prototype._loadBuffer = function (_path, callback, errorCallback) {\n var path = p5.prototype._checkFileFormats(_path);\n var self = this;\n var errorTrace = new Error().stack;\n var ac = p5.prototype.getAudioContext();\n\n var request = new XMLHttpRequest();\n request.open('GET', path, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on success loading file:\n ac.decodeAudioData(\n request.response,\n function (buff) {\n var buffer = {};\n var chunks = path.split('/');\n buffer.name = chunks[chunks.length - 1];\n buffer.audioBuffer = buff;\n self.impulses.push(buffer);\n self._setBuffer(buffer.audioBuffer);\n if (callback) {\n callback(buffer);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(msg + '\\n The error stack trace includes: \\n' + err.stack);\n }\n };\n request.send();\n};\n\np5.Convolver.prototype.set = null;\n\n/**\n * Connect a source to the convolver.\n *\n * @method process\n * @for p5.Convolver\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *\n *
\n */\np5.Convolver.prototype.process = function (src) {\n src.connect(this.input);\n};\n\n/**\n * If you load multiple impulse files using the .addImpulse method,\n * they will be stored as Objects in this Array. Toggle between them\n * with the toggleImpulse(id) method.\n *\n * @property {Array} impulses\n * @for p5.Convolver\n */\np5.Convolver.prototype.impulses = [];\n\n/**\n * Load and assign a new Impulse Response to the p5.Convolver.\n * The impulse is added to the .impulses array. Previous\n * impulses can be accessed with the .toggleImpulse(id)\n * method.\n *\n * @method addImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\np5.Convolver.prototype.addImpulse = function (path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this._loadBuffer(path, callback, errorCallback);\n};\n\n/**\n * Similar to .addImpulse, except that the .impulses\n * Array is reset to save memory. A new .impulses\n * array is created with this impulse as the only item.\n *\n * @method resetImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\np5.Convolver.prototype.resetImpulse = function (path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n};\n\n/**\n * If you have used .addImpulse() to add multiple impulses\n * to a p5.Convolver, then you can use this method to toggle between\n * the items in the .impulses Array. Accepts a parameter\n * to identify which impulse you wish to use, identified either by its\n * original filename (String) or by its position in the .impulses\n * Array (Number).
\n * You can access the objects in the .impulses Array directly. Each\n * Object has two attributes: an .audioBuffer (type:\n * Web Audio \n * AudioBuffer) and a .name, a String that corresponds\n * with the original filename.\n *\n * @method toggleImpulse\n * @for p5.Convolver\n * @param {String|Number} id Identify the impulse by its original filename\n * (String), or by its position in the\n * .impulses Array (Number).\n */\np5.Convolver.prototype.toggleImpulse = function (id) {\n if (typeof id === 'number' && id < this.impulses.length) {\n this._setBuffer(this.impulses[id].audioBuffer);\n }\n if (typeof id === 'string') {\n for (var i = 0; i < this.impulses.length; i++) {\n if (this.impulses[i].name === id) {\n this._setBuffer(this.impulses[i].audioBuffer);\n break;\n }\n }\n }\n};\n\np5.Convolver.prototype.dispose = function () {\n p5.Reverb.prototype.dispose.apply(this);\n\n // remove all the Impulse Response buffers\n for (var i in this.impulses) {\n if (this.impulses[i]) {\n this.impulses[i] = null;\n }\n }\n};\n","import p5sound from './master';\n// requires the Tone.js library's Clock (MIT license, Yotam Mann)\n// https://github.com/TONEnoTONE/Tone.js/\nimport Clock from 'Tone/core/Clock';\n\np5.Metro = function () {\n this.clock = new Clock({\n callback: this.ontick.bind(this),\n });\n this.syncedParts = [];\n this.bpm = 120; // gets overridden by p5.Part\n this._init();\n\n this.prevTick = 0;\n this.tatumTime = 0;\n\n this.tickCallback = function () {};\n};\n\np5.Metro.prototype.ontick = function (tickTime) {\n var elapsedTime = tickTime - this.prevTick;\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\n if (elapsedTime - this.tatumTime <= -0.02) {\n return;\n } else {\n // console.log('ok', this.syncedParts[0].phrases[0].name);\n this.prevTick = tickTime;\n\n // for all of the active things on the metro:\n var self = this;\n this.syncedParts.forEach(function (thisPart) {\n if (!thisPart.isPlaying) return;\n thisPart.incrementStep(secondsFromNow);\n // each synced source keeps track of its own beat number\n thisPart.phrases.forEach(function (thisPhrase) {\n var phraseArray = thisPhrase.sequence;\n var bNum = self.metroTicks % phraseArray.length;\n if (\n phraseArray[bNum] !== 0 &&\n (self.metroTicks < phraseArray.length || !thisPhrase.looping)\n ) {\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\n }\n });\n });\n this.metroTicks += 1;\n this.tickCallback(secondsFromNow);\n }\n};\n\np5.Metro.prototype.setBPM = function (bpm, rampTime = 0) {\n var beatTime = 60 / (bpm * this.tatums);\n var now = p5sound.audiocontext.currentTime;\n this.tatumTime = beatTime;\n\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\n this.bpm = bpm;\n};\n\np5.Metro.prototype.getBPM = function () {\n return (this.clock.getRate() / this.tatums) * 60;\n};\n\np5.Metro.prototype._init = function () {\n this.metroTicks = 0;\n // this.setBPM(120);\n};\n\n// clear existing synced parts, add only this one\np5.Metro.prototype.resetSync = function (part) {\n this.syncedParts = [part];\n};\n\n// push a new synced part to the array\np5.Metro.prototype.pushSync = function (part) {\n this.syncedParts.push(part);\n};\n\np5.Metro.prototype.start = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.start(now + t);\n this.setBPM(this.bpm);\n};\n\np5.Metro.prototype.stop = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.stop(now + t);\n};\n\np5.Metro.prototype.beatLength = function (tatums) {\n this.tatums = 1 / tatums / 4; // lowest possible division of a beat\n};\n","import p5sound from './master';\n\nvar BPM = 120;\n\n/**\n * Set the global tempo, in beats per minute, for all\n * p5.Parts. This method will impact all active p5.Parts.\n *\n * @method setBPM\n * @for p5\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\np5.prototype.setBPM = function (bpm, rampTime) {\n BPM = bpm;\n for (var i in p5sound.parts) {\n if (p5sound.parts[i]) {\n p5sound.parts[i].setBPM(bpm, rampTime);\n }\n }\n};\n\n/**\n *

A phrase is a pattern of musical events over time, i.e.\n * a series of notes and rests.

\n *\n *

Phrases must be added to a p5.Part for playback, and\n * each part can play multiple phrases at the same time.\n * For example, one Phrase might be a kick drum, another\n * could be a snare, and another could be the bassline.

\n *\n *

The first parameter is a name so that the phrase can be\n * modified or deleted later. The callback is a a function that\n * this phrase will call at every step—for example it might be\n * called playNote(value){}. The array determines\n * which value is passed into the callback at each step of the\n * phrase. It can be numbers, an object with multiple numbers,\n * or a zero (0) indicates a rest so the callback won't be called).

\n *\n * @class p5.Phrase\n * @constructor\n * @param {String} name Name so that you can access the Phrase.\n * @param {Function} callback The name of a function that this phrase\n * will call. Typically it will play a sound,\n * and accept two parameters: a time at which\n * to play the sound (in seconds from now),\n * and a value from the sequence array. The\n * time should be passed into the play() or\n * start() method to ensure precision.\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n * @example\n *
\n * let mySound, myPhrase, myPart;\n * let pattern = [1,0,0,2,0,2,0,0];\n *\n * function preload() {\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * text('tap to play', width/2, height/2);\n * textAlign(CENTER, CENTER);\n *\n * myPhrase = new p5.Phrase('bbox', onEachStep, pattern);\n * myPart = new p5.Part();\n * myPart.addPhrase(myPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function onEachStep(time, playbackRate) {\n * mySound.rate(playbackRate);\n * mySound.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n * myPart.start();\n * }\n *
\n */\np5.Phrase = function (name, callback, sequence) {\n this.phraseStep = 0;\n this.name = name;\n this.callback = callback;\n /**\n * Array of values to pass into the callback\n * at each step of the phrase. Depending on the callback\n * function's requirements, these values may be numbers,\n * strings, or an object with multiple parameters.\n * Zero (0) indicates a rest.\n *\n * @property {Array} sequence\n */\n this.sequence = sequence;\n};\n\n/**\n *

A p5.Part plays back one or more p5.Phrases. Instantiate a part\n * with steps and tatums. By default, each step represents a 1/16th note.

\n *\n *

See p5.Phrase for more about musical timing.

\n *\n * @class p5.Part\n * @constructor\n * @param {Number} [steps] Steps in the part\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)\n * @example\n *
\n * let box, drum, myPart;\n * let boxPat = [1,0,0,2,0,2,0,0];\n * let drumPat = [0,1,1,0,2,0,1,0];\n *\n * function preload() {\n * box = loadSound('assets/beatbox.mp3');\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * textAlign(CENTER, CENTER);\n * text('tap to play', width/2, height/2);\n *\n * let boxPhrase = new p5.Phrase('box', playBox, boxPat);\n * let drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\n * myPart = new p5.Part();\n * myPart.addPhrase(boxPhrase);\n * myPart.addPhrase(drumPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function playBox(time, playbackRate) {\n * box.rate(playbackRate);\n * box.play(time);\n * }\n *\n * function playDrum(time, playbackRate) {\n * drum.rate(playbackRate);\n * drum.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n *\n * myPart.start();\n * }\n *
\n */\np5.Part = function (steps, bLength) {\n this.length = steps || 0; // how many beats\n this.partStep = 0;\n this.phrases = [];\n this.isPlaying = false;\n this.noLoop();\n this.tatums = bLength || 0.0625; // defaults to quarter note\n\n this.metro = new p5.Metro();\n this.metro._init();\n this.metro.beatLength(this.tatums);\n this.metro.setBPM(BPM);\n p5sound.parts.push(this);\n this.callback = function () {};\n};\n\n/**\n * Set the tempo of this part, in Beats Per Minute.\n *\n * @method setBPM\n * @for p5.Part\n * @param {Number} BPM Beats Per Minute\n * @param {Number} [rampTime] Seconds from now\n */\np5.Part.prototype.setBPM = function (tempo, rampTime) {\n this.metro.setBPM(tempo, rampTime);\n};\n\n/**\n * Returns the tempo, in Beats Per Minute, of this part.\n *\n * @method getBPM\n * @for p5.Part\n * @return {Number}\n */\np5.Part.prototype.getBPM = function () {\n return this.metro.getBPM();\n};\n\n/**\n * Start playback of this part. It will play\n * through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method start\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\np5.Part.prototype.start = function (time) {\n if (!this.isPlaying) {\n this.isPlaying = true;\n this.metro.resetSync(this);\n var t = time || 0;\n this.metro.start(t);\n }\n};\n\n/**\n * Loop playback of this part. It will begin\n * looping through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method loop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\np5.Part.prototype.loop = function (time) {\n this.looping = true;\n // rest onended function\n this.onended = function () {\n this.partStep = 0;\n };\n var t = time || 0;\n this.start(t);\n};\n\n/**\n * Tell the part to stop looping.\n *\n * @method noLoop\n * @for p5.Part\n */\np5.Part.prototype.noLoop = function () {\n this.looping = false;\n // rest onended function\n this.onended = function () {\n this.stop();\n };\n};\n\n/**\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\n *\n * @method stop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\np5.Part.prototype.stop = function (time) {\n this.partStep = 0;\n this.pause(time);\n};\n\n/**\n * Pause the part. Playback will resume\n * from the current step.\n *\n * @method pause\n * @for p5.Part\n * @param {Number} time seconds from now\n */\np5.Part.prototype.pause = function (time) {\n this.isPlaying = false;\n var t = time || 0;\n this.metro.stop(t);\n};\n\n/**\n * Add a p5.Phrase to this Part.\n *\n * @method addPhrase\n * @for p5.Part\n * @param {p5.Phrase} phrase reference to a p5.Phrase\n */\np5.Part.prototype.addPhrase = function (name, callback, array) {\n var p;\n if (arguments.length === 3) {\n p = new p5.Phrase(name, callback, array);\n } else if (arguments[0] instanceof p5.Phrase) {\n p = arguments[0];\n } else {\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\n }\n this.phrases.push(p);\n // reset the length if phrase is longer than part's existing length\n if (p.sequence.length > this.length) {\n this.length = p.sequence.length;\n }\n};\n\n/**\n * Remove a phrase from this part, based on the name it was\n * given when it was created.\n *\n * @method removePhrase\n * @for p5.Part\n * @param {String} phraseName\n */\np5.Part.prototype.removePhrase = function (name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases.splice(i, 1);\n }\n }\n};\n\n/**\n * Get a phrase from this part, based on the name it was\n * given when it was created. Now you can modify its array.\n *\n * @method getPhrase\n * @for p5.Part\n * @param {String} phraseName\n */\np5.Part.prototype.getPhrase = function (name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n return this.phrases[i];\n }\n }\n};\n\n/**\n * Find all sequences with the specified name, and replace their patterns with the specified array.\n *\n * @method replaceSequence\n * @for p5.Part\n * @param {String} phraseName\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n */\np5.Part.prototype.replaceSequence = function (name, array) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases[i].sequence = array;\n }\n }\n};\n\np5.Part.prototype.incrementStep = function (time) {\n if (this.partStep < this.length - 1) {\n this.callback(time);\n this.partStep += 1;\n } else {\n if (!this.looping && this.partStep === this.length - 1) {\n // this.callback(time);\n this.onended();\n }\n }\n};\n\n/**\n * Set the function that will be called at every step. This will clear the previous function.\n *\n * @method onStep\n * @for p5.Part\n * @param {Function} callback The name of the callback\n * you want to fire\n * on every beat/tatum.\n */\np5.Part.prototype.onStep = function (callback) {\n this.callback = callback;\n};\n\n// ===============\n// p5.Score\n// ===============\n\n/**\n * A Score consists of a series of Parts. The parts will\n * be played back in order. For example, you could have an\n * A part, a B part, and a C part, and play them back in this order\n * new p5.Score(a, a, b, a, c)\n *\n * @class p5.Score\n * @constructor\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\n */\np5.Score = function () {\n // for all of the arguments\n this.parts = [];\n this.currentPart = 0;\n\n var thisScore = this;\n for (var i in arguments) {\n if (arguments[i] && this.parts[i]) {\n this.parts[i] = arguments[i];\n this.parts[i].nextPart = this.parts[i + 1];\n this.parts[i].onended = function () {\n thisScore.resetPart(i);\n playNextPart(thisScore);\n };\n }\n }\n this.looping = false;\n};\n\np5.Score.prototype.onended = function () {\n if (this.looping) {\n // this.resetParts();\n this.parts[0].start();\n } else {\n this.parts[this.parts.length - 1].onended = function () {\n this.stop();\n this.resetParts();\n };\n }\n this.currentPart = 0;\n};\n\n/**\n * Start playback of the score.\n *\n * @method start\n * @for p5.Score\n */\np5.Score.prototype.start = function () {\n this.parts[this.currentPart].start();\n this.scoreStep = 0;\n};\n\n/**\n * Stop playback of the score.\n *\n * @method stop\n * @for p5.Score\n */\np5.Score.prototype.stop = function () {\n this.parts[this.currentPart].stop();\n this.currentPart = 0;\n this.scoreStep = 0;\n};\n\n/**\n * Pause playback of the score.\n *\n * @method pause\n * @for p5.Score\n */\np5.Score.prototype.pause = function () {\n this.parts[this.currentPart].stop();\n};\n\n/**\n * Loop playback of the score.\n *\n * @method loop\n * @for p5.Score\n */\np5.Score.prototype.loop = function () {\n this.looping = true;\n this.start();\n};\n\n/**\n * Stop looping playback of the score. If it\n * is currently playing, this will go into effect\n * after the current round of playback completes.\n *\n * @method noLoop\n * @for p5.Score\n */\np5.Score.prototype.noLoop = function () {\n this.looping = false;\n};\n\np5.Score.prototype.resetParts = function () {\n var self = this;\n this.parts.forEach(function (part) {\n self.resetParts[part];\n });\n};\n\np5.Score.prototype.resetPart = function (i) {\n this.parts[i].stop();\n this.parts[i].partStep = 0;\n for (var p in this.parts[i].phrases) {\n if (this.parts[i]) {\n this.parts[i].phrases[p].phraseStep = 0;\n }\n }\n};\n\n/**\n * Set the tempo for all parts in the score\n *\n * @method setBPM\n * @for p5.Score\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\np5.Score.prototype.setBPM = function (bpm, rampTime) {\n for (var i in this.parts) {\n if (this.parts[i]) {\n this.parts[i].setBPM(bpm, rampTime);\n }\n }\n};\n\nfunction playNextPart(aScore) {\n aScore.currentPart++;\n if (aScore.currentPart >= aScore.parts.length) {\n aScore.scoreStep = 0;\n aScore.onended();\n } else {\n aScore.scoreStep = 0;\n aScore.parts[aScore.currentPart - 1].stop();\n aScore.parts[aScore.currentPart].start();\n }\n}\n","import p5sound from './master';\nimport Clock from 'Tone/core/Clock';\n\n/**\n * SoundLoop\n *\n * @class p5.SoundLoop\n * @constructor\n *\n * @param {Function} callback this function will be called on each iteration of theloop\n * @param {Number|String} [interval] amount of time (if a number) or beats (if a string, following Tone.Time convention) for each iteration of the loop. Defaults to 1 second.\n *\n * @example\n *
\n * let synth, soundLoop;\n * let notePattern = [60, 62, 64, 67, 69, 72];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * colorMode(HSB);\n * background(0, 0, 86);\n * text('tap to start/stop', 10, 20);\n *\n * //the looper's callback is passed the timeFromNow\n * //this value should be used as a reference point from\n * //which to schedule sounds\n * let intervalInSeconds = 0.2;\n * soundLoop = new p5.SoundLoop(onSoundLoop, intervalInSeconds);\n *\n * synth = new p5.MonoSynth();\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * if (soundLoop.isPlaying) {\n * soundLoop.stop();\n * } else {\n * // start the loop\n * soundLoop.start();\n * }\n * }\n *\n * function onSoundLoop(timeFromNow) {\n * let noteIndex = (soundLoop.iterations - 1) % notePattern.length;\n * let note = midiToFreq(notePattern[noteIndex]);\n * synth.play(note, 0.5, timeFromNow);\n * background(noteIndex * 360 / notePattern.length, 50, 100);\n * }\n *
\n */\np5.SoundLoop = function (callback, interval) {\n this.callback = callback;\n /**\n * musicalTimeMode uses Tone.Time convention\n * true if string, false if number\n * @property {Boolean} musicalTimeMode\n */\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\n\n this._interval = interval || 1;\n\n /**\n * musicalTimeMode variables\n * modify these only when the interval is specified in musicalTime format as a string\n */\n this._timeSignature = 4;\n this._bpm = 60;\n\n this.isPlaying = false;\n\n /**\n * Set a limit to the number of loops to play. defaults to Infinity\n * @property {Number} maxIterations\n */\n this.maxIterations = Infinity;\n var self = this;\n\n this.clock = new Clock({\n callback: function (time) {\n var timeFromNow = time - p5sound.audiocontext.currentTime;\n /**\n * Do not initiate the callback if timeFromNow is < 0\n * This ususually occurs for a few milliseconds when the page\n * is not fully loaded\n *\n * The callback should only be called until maxIterations is reached\n */\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\n self.callback(timeFromNow);\n }\n },\n frequency: this._calcFreq(),\n });\n};\n\n/**\n * Start the loop\n * @method start\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a starting time\n */\np5.SoundLoop.prototype.start = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (!this.isPlaying) {\n this.clock.start(now + t);\n this.isPlaying = true;\n }\n};\n\n/**\n * Stop the loop\n * @method stop\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a stopping time\n */\np5.SoundLoop.prototype.stop = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.stop(now + t);\n this.isPlaying = false;\n }\n};\n/**\n * Pause the loop\n * @method pause\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a pausing time\n */\np5.SoundLoop.prototype.pause = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.pause(now + t);\n this.isPlaying = false;\n }\n};\n\n/**\n * Synchronize loops. Use this method to start two or more loops in synchronization\n * or to start a loop in synchronization with a loop that is already playing\n * This method will schedule the implicit loop in sync with the explicit master loop\n * i.e. loopToStart.syncedStart(loopToSyncWith)\n *\n * @method syncedStart\n * @for p5.SoundLoop\n * @param {Object} otherLoop a p5.SoundLoop to sync with\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\n */\np5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n\n if (!otherLoop.isPlaying) {\n otherLoop.clock.start(now + t);\n otherLoop.isPlaying = true;\n this.clock.start(now + t);\n this.isPlaying = true;\n } else if (otherLoop.isPlaying) {\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\n this.clock.start(now + time);\n this.isPlaying = true;\n }\n};\n\n/**\n * Updates frequency value, reflected in next callback\n * @private\n * @for p5.SoundLoop\n * @method _update\n */\np5.SoundLoop.prototype._update = function () {\n this.clock.frequency.value = this._calcFreq();\n};\n\n/**\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\n * @private\n * @for p5.SoundLoop\n * @method _calcFreq\n * @return {Number} new clock frequency value\n */\np5.SoundLoop.prototype._calcFreq = function () {\n //Seconds mode, bpm / timesignature has no effect\n if (typeof this._interval === 'number') {\n this.musicalTimeMode = false;\n return 1 / this._interval;\n }\n //Musical timing mode, calculate interval based bpm, interval,and time signature\n else if (typeof this._interval === 'string') {\n this.musicalTimeMode = true;\n return (\n (this._bpm / 60 / this._convertNotation(this._interval)) *\n (this._timeSignature / 4)\n );\n }\n};\n\n/**\n * Convert notation from musical time format to seconds\n * Uses Tone.Time convention\n * @private\n * @for p5.SoundLoop\n * @method _convertNotation\n * @param {String} value value to be converted\n * @return {Number} converted value in seconds\n */\np5.SoundLoop.prototype._convertNotation = function (value) {\n var type = value.slice(-1);\n value = Number(value.slice(0, -1));\n switch (type) {\n case 'm':\n return this._measure(value);\n case 'n':\n return this._note(value);\n default:\n console.warn(\n 'Specified interval is not formatted correctly. See Tone.js ' +\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'\n );\n }\n};\n\n/**\n * Helper conversion methods of measure and note\n * @private\n * @for p5.SoundLoop\n * @method _measure\n */\np5.SoundLoop.prototype._measure = function (value) {\n return value * this._timeSignature;\n};\n\n/**\n * @private\n * @method _note\n * @for p5.SoundLoop\n */\np5.SoundLoop.prototype._note = function (value) {\n return this._timeSignature / value;\n};\n\n/**\n * Getters and Setters, setting any paramter will result in a change in the clock's\n * frequency, that will be reflected after the next callback\n * beats per minute (defaults to 60)\n * @property {Number} bpm\n * @for p5.SoundLoop\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'bpm', {\n get: function () {\n return this._bpm;\n },\n set: function (bpm) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the BPM in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._bpm = bpm;\n this._update();\n },\n});\n\n/**\n * number of quarter notes in a measure (defaults to 4)\n * @property {Number} timeSignature\n * @for p5.SoundLoop\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {\n get: function () {\n return this._timeSignature;\n },\n set: function (timeSig) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the timeSignature in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._timeSignature = timeSig;\n this._update();\n },\n});\n\n/**\n * length of the loops interval\n * @property {Number|String} interval\n * @for p5.SoundLoop\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'interval', {\n get: function () {\n return this._interval;\n },\n set: function (interval) {\n this.musicalTimeMode = typeof interval === 'number' ? false : true;\n this._interval = interval;\n this._update();\n },\n});\n\n/**\n * how many times the callback has been called so far\n * @property {Number} iterations\n * @for p5.SoundLoop\n * @readonly\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'iterations', {\n get: function () {\n return this.clock.ticks;\n },\n});\n\nexport default p5.SoundLoop;\n","import Effect from './effect';\n\n/**\n * Compressor is an audio effect class that performs dynamics compression\n * on an audio input source. This is a very commonly used technique in music\n * and sound production. Compression creates an overall louder, richer,\n * and fuller sound by lowering the volume of louds and raising that of softs.\n * Compression can be used to avoid clipping (sound distortion due to\n * peaks in volume) and is especially useful when many sounds are played\n * at once. Compression can be used on indivudal sound sources in addition\n * to the master output.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Compressor\n * @constructor\n * @extends p5.Effect\n *\n *\n */\np5.Compressor = function () {\n Effect.call(this);\n\n /**\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\n * \n * @property {AudioNode} compressor\n */\n\n this.compressor = this.ac.createDynamicsCompressor();\n\n this.input.connect(this.compressor);\n this.compressor.connect(this.wet);\n};\n\np5.Compressor.prototype = Object.create(Effect.prototype);\n\n/**\n * Performs the same function as .connect, but also accepts\n * optional parameters to set compressor's audioParams\n * @method process\n * @for p5.Compressor\n *\n * @param {Object} src Sound source to be connected\n *\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\np5.Compressor.prototype.process = function (\n src,\n attack,\n knee,\n ratio,\n threshold,\n release\n) {\n src.connect(this.input);\n this.set(attack, knee, ratio, threshold, release);\n};\n\n/**\n * Set the paramters of a compressor.\n * @method set\n * @for p5.Compressor\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} knee A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\np5.Compressor.prototype.set = function (\n attack,\n knee,\n ratio,\n threshold,\n release\n) {\n if (typeof attack !== 'undefined') {\n this.attack(attack);\n }\n if (typeof knee !== 'undefined') {\n this.knee(knee);\n }\n if (typeof ratio !== 'undefined') {\n this.ratio(ratio);\n }\n if (typeof threshold !== 'undefined') {\n this.threshold(threshold);\n }\n if (typeof release !== 'undefined') {\n this.release(release);\n }\n};\n\n/**\n * Get current attack or set value w/ time ramp\n *\n *\n * @method attack\n * @for p5.Compressor\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.attack = function (attack, time) {\n var t = time || 0;\n if (typeof attack === 'number') {\n this.compressor.attack.value = attack;\n this.compressor.attack.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.attack.linearRampToValueAtTime(\n attack,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof attack !== 'undefined') {\n attack.connect(this.compressor.attack);\n }\n return this.compressor.attack.value;\n};\n\n/**\n * Get current knee or set value w/ time ramp\n *\n * @method knee\n * @for p5.Compressor\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.knee = function (knee, time) {\n var t = time || 0;\n if (typeof knee === 'number') {\n this.compressor.knee.value = knee;\n this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.compressor.knee.linearRampToValueAtTime(\n knee,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof knee !== 'undefined') {\n knee.connect(this.compressor.knee);\n }\n return this.compressor.knee.value;\n};\n\n/**\n * Get current ratio or set value w/ time ramp\n * @method ratio\n * @for p5.Compressor\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.ratio = function (ratio, time) {\n var t = time || 0;\n if (typeof ratio === 'number') {\n this.compressor.ratio.value = ratio;\n this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.compressor.ratio.linearRampToValueAtTime(\n ratio,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof ratio !== 'undefined') {\n ratio.connect(this.compressor.ratio);\n }\n return this.compressor.ratio.value;\n};\n\n/**\n * Get current threshold or set value w/ time ramp\n * @method threshold\n * @for p5.Compressor\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.threshold = function (threshold, time) {\n var t = time || 0;\n if (typeof threshold === 'number') {\n this.compressor.threshold.value = threshold;\n this.compressor.threshold.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.threshold.linearRampToValueAtTime(\n threshold,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof threshold !== 'undefined') {\n threshold.connect(this.compressor.threshold);\n }\n return this.compressor.threshold.value;\n};\n\n/**\n * Get current release or set value w/ time ramp\n * @method release\n * @for p5.Compressor\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n *\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.release = function (release, time) {\n var t = time || 0;\n if (typeof release === 'number') {\n this.compressor.release.value = release;\n this.compressor.release.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.release.linearRampToValueAtTime(\n release,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof number !== 'undefined') {\n release.connect(this.compressor.release);\n }\n return this.compressor.release.value;\n};\n\n/**\n * Return the current reduction value\n *\n * @method reduction\n * @for p5.Compressor\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\n */\np5.Compressor.prototype.reduction = function () {\n return this.compressor.reduction.value;\n};\n\np5.Compressor.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n if (this.compressor) {\n this.compressor.disconnect();\n delete this.compressor;\n }\n};\n","// inspiration: recorder.js, Tone.js & typedarray.org\n\nimport p5sound from './master';\nimport { convertToWav, safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\nconst ac = p5sound.audiocontext;\n\n/**\n *

Record sounds for playback and/or to save as a .wav file.\n * The p5.SoundRecorder records all sound output from your sketch,\n * or can be assigned a specific source with setInput().

\n *

The record() method accepts a p5.SoundFile as a parameter.\n * When playback is stopped (either after the given amount of time,\n * or with the stop() method), the p5.SoundRecorder will send its\n * recording to that p5.SoundFile for playback.

\n *\n * @class p5.SoundRecorder\n * @constructor\n * @example\n *
\n * let mic, recorder, soundFile;\n * let state = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * textAlign(CENTER, CENTER);\n *\n * // create an audio in\n * mic = new p5.AudioIn();\n *\n * // prompts user to enable their browser mic\n * mic.start();\n *\n * // create a sound recorder\n * recorder = new p5.SoundRecorder();\n *\n * // connect the mic to the recorder\n * recorder.setInput(mic);\n *\n * // this sound file will be used to\n * // playback & save the recording\n * soundFile = new p5.SoundFile();\n *\n * text('tap to record', width/2, height/2);\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * // make sure user enabled the mic\n * if (state === 0 && mic.enabled) {\n *\n * // record to our p5.SoundFile\n * recorder.record(soundFile);\n *\n * background(255,0,0);\n * text('Recording!', width/2, height/2);\n * state++;\n * }\n * else if (state === 1) {\n * background(0,255,0);\n *\n * // stop recorder and\n * // send result to soundFile\n * recorder.stop();\n *\n * text('Done! Tap to play and download', width/2, height/2, width - 20);\n * state++;\n * }\n *\n * else if (state === 2) {\n * soundFile.play(); // play the result!\n * save(soundFile, 'mySound.wav');\n * state++;\n * }\n * }\n *
\n */\np5.SoundRecorder = function () {\n this.input = ac.createGain();\n this.output = ac.createGain();\n\n this._inputChannels = 2;\n this._outputChannels = 2; // stereo output, even if input is mono\n\n const workletBufferSize = safeBufferSize(1024);\n\n this._workletNode = new AudioWorkletNode(\n ac,\n processorNames.recorderProcessor,\n {\n outputChannelCount: [this._outputChannels],\n processorOptions: {\n numInputChannels: this._inputChannels,\n bufferSize: workletBufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'buffers') {\n const buffers = [\n new Float32Array(event.data.leftBuffer),\n new Float32Array(event.data.rightBuffer),\n ];\n this._callback(buffers);\n }\n }.bind(this);\n\n /**\n * callback invoked when the recording is over\n * @private\n * @type Function(Float32Array)\n */\n this._callback = function () {};\n\n // connections\n this._workletNode.connect(p5.soundOut._silentNode);\n this.setInput();\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Connect a specific device to the p5.SoundRecorder.\n * If no parameter is given, p5.SoundRecorer will record\n * all audible p5.sound from your sketch.\n *\n * @method setInput\n * @for p5.SoundRecorder\n * @param {Object} [unit] p5.sound object or a web audio unit\n * that outputs sound\n */\np5.SoundRecorder.prototype.setInput = function (unit) {\n this.input.disconnect();\n this.input = null;\n this.input = ac.createGain();\n this.input.connect(this._workletNode);\n this.input.connect(this.output);\n if (unit) {\n unit.connect(this.input);\n } else {\n p5.soundOut.output.connect(this.input);\n }\n};\n\n/**\n * Start recording. To access the recording, provide\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\n * will send its recording to that p5.SoundFile for playback once\n * recording is complete. Optional parameters include duration\n * (in seconds) of the recording, and a callback function that\n * will be called once the complete recording has been\n * transfered to the p5.SoundFile.\n *\n * @method record\n * @for p5.SoundRecorder\n * @param {p5.SoundFile} soundFile p5.SoundFile\n * @param {Number} [duration] Time (in seconds)\n * @param {Function} [callback] The name of a function that will be\n * called once the recording completes\n */\np5.SoundRecorder.prototype.record = function (sFile, duration, callback) {\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\n\n if (sFile && callback) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n callback();\n };\n } else if (sFile) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n };\n }\n};\n\n/**\n * Stop the recording. Once the recording is stopped,\n * the results will be sent to the p5.SoundFile that\n * was given on .record(), and if a callback function\n * was provided on record, that function will be called.\n *\n * @method stop\n * @for p5.SoundRecorder\n */\np5.SoundRecorder.prototype.stop = function () {\n this._workletNode.port.postMessage({ name: 'stop' });\n};\n\np5.SoundRecorder.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this._callback = function () {};\n if (this.input) {\n this.input.disconnect();\n }\n this.input = null;\n this._workletNode = null;\n};\n\n/**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device.\n * For uploading audio to a server, use\n * `p5.SoundFile.saveBlob`.\n *\n * @for p5\n * @method saveSound\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\n * @param {String} fileName name of the resulting .wav file.\n */\n// add to p5.prototype as this is used by the p5 `save()` method.\np5.prototype.saveSound = function (soundFile, fileName) {\n const dataView = convertToWav(soundFile.buffer);\n p5.prototype.writeFile([dataView], fileName, 'wav');\n};\n","import p5sound from './master';\n\n/**\n * A gain node is usefull to set the relative volume of sound.\n * It's typically used to build mixers.\n *\n * @class p5.Gain\n * @constructor\n * @example\n *
\n *\n * // load two soundfile and crossfade beetween them\n * let sound1,sound2;\n * let sound1Gain, sound2Gain, masterGain;\n * function preload(){\n * soundFormats('ogg', 'mp3');\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\n * sound2 = loadSound('assets/beat');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * // create a 'master' gain to which we will connect both soundfiles\n * masterGain = new p5.Gain();\n * masterGain.connect();\n * sound1.disconnect(); // diconnect from p5 output\n * sound1Gain = new p5.Gain(); // setup a gain node\n * sound1Gain.setInput(sound1); // connect the first sound to its input\n * sound1Gain.connect(masterGain); // connect its output to the 'master'\n * sound2.disconnect();\n * sound2Gain = new p5.Gain();\n * sound2Gain.setInput(sound2);\n * sound2Gain.connect(masterGain);\n * }\n * function startSound() {\n * sound1.loop();\n * sound2.loop();\n * loop();\n * }\n * function mouseReleased() {\n * sound1.stop();\n * sound2.stop();\n * }\n * function draw(){\n * background(220);\n * textAlign(CENTER);\n * textSize(11);\n * fill(0);\n * if (!sound1.isPlaying()) {\n * text('tap and drag to play', width/2, height/2);\n * return;\n * }\n * // map the horizontal position of the mouse to values useable for volume * control of sound1\n * var sound1Volume = constrain(map(mouseX,width,0,0,1), 0, 1);\n * var sound2Volume = 1-sound1Volume;\n * sound1Gain.amp(sound1Volume);\n * sound2Gain.amp(sound2Volume);\n * // map the vertical position of the mouse to values useable for 'master * volume control'\n * var masterVolume = constrain(map(mouseY,height,0,0,1), 0, 1);\n * masterGain.amp(masterVolume);\n * text('master', width/2, height - masterVolume * height * 0.9)\n * fill(255, 0, 255);\n * textAlign(LEFT);\n * text('sound1', 5, height - sound1Volume * height * 0.9);\n * textAlign(RIGHT);\n * text('sound2', width - 5, height - sound2Volume * height * 0.9);\n * }\n *
\n */\n\np5.Gain = function () {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n this.input.connect(this.output);\n\n // add to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Connect a source to the gain node.\n *\n * @method setInput\n * @for p5.Gain\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n */\n\np5.Gain.prototype.setInput = function (src) {\n src.connect(this.input);\n};\n\n/**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Gain\n * @param {Object} unit\n */\np5.Gain.prototype.connect = function (unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Gain\n */\np5.Gain.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Set the output level of the gain node.\n *\n * @method amp\n * @for p5.Gain\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\np5.Gain.prototype.amp = function (vol, rampTime = 0, tFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n};\n\np5.Gain.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n};\n\nexport default p5.Gain;\n","import p5sound from './master';\n\n/**\n * Base class for monophonic synthesizers. Any extensions of this class\n * should follow the API and implement the methods below in order to\n * remain compatible with p5.PolySynth();\n *\n * @class p5.AudioVoice\n * @constructor\n */\np5.AudioVoice = function () {\n this.ac = p5sound.audiocontext;\n this.output = this.ac.createGain();\n this.connect();\n p5sound.soundArray.push(this);\n};\n\np5.AudioVoice.prototype.play = function (\n note,\n velocity,\n secondsFromNow,\n sustime\n) {};\n\np5.AudioVoice.prototype.triggerAttack = function (\n note,\n velocity,\n secondsFromNow\n) {};\n\np5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {};\n\np5.AudioVoice.prototype.amp = function (vol, rampTime) {};\n\n/**\n * Connect to p5 objects or Web Audio Nodes\n * @method connect\n * @for p5.AudioVoice\n * @param {Object} unit\n */\np5.AudioVoice.prototype.connect = function (unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect from soundOut\n * @method disconnect\n * @for p5.AudioVoice\n */\np5.AudioVoice.prototype.disconnect = function () {\n this.output.disconnect();\n};\n\np5.AudioVoice.prototype.dispose = function () {\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n};\n\nexport default p5.AudioVoice;\n","import p5sound from './master';\nimport AudioVoice from './audioVoice';\nimport { noteToFreq } from './helpers';\n\nvar DEFAULT_SUSTAIN = 0.15;\n\n/**\n * A MonoSynth is used as a single voice for sound synthesis.\n * This is a class to be used in conjunction with the PolySynth\n * class. Custom synthetisers should be built inheriting from\n * this class.\n *\n * @class p5.MonoSynth\n * @constructor\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n **/\n\np5.MonoSynth = function () {\n AudioVoice.call(this);\n\n this.oscillator = new p5.Oscillator();\n\n this.env = new p5.Envelope();\n this.env.setRange(1, 0);\n this.env.setExp(true);\n\n //set params\n this.setADSR(0.02, 0.25, 0.05, 0.35);\n\n // oscillator --> env --> this.output (gain) --> p5.soundOut\n this.oscillator.disconnect();\n this.oscillator.connect(this.output);\n\n this.env.disconnect();\n this.env.setInput(this.output.gain);\n\n // reset oscillator gain to 1.0\n this.oscillator.output.gain.value = 1.0;\n\n this.oscillator.start();\n this.connect();\n\n p5sound.soundArray.push(this);\n};\n\np5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);\n\n/**\n * Play tells the MonoSynth to start playing a note. This method schedules\n * the calling of .triggerAttack and .triggerRelease.\n *\n * @method play\n * @for p5.MonoSynth\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope. Defaults to 0.15 seconds.\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n *\n */\np5.MonoSynth.prototype.play = function (\n note,\n velocity,\n secondsFromNow,\n susTime\n) {\n this.triggerAttack(note, velocity, ~~secondsFromNow);\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\n};\n\n/**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @method triggerAttack\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\np5.MonoSynth.prototype.triggerAttack = function (\n note,\n velocity,\n secondsFromNow = 0\n) {\n var freq = noteToFreq(note);\n var vel = velocity || 0.1;\n this.oscillator.freq(freq, 0, secondsFromNow);\n this.env.ramp(this.output.gain, secondsFromNow, vel);\n};\n\n/**\n * Trigger the release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @param {Number} secondsFromNow time to trigger the release\n * @method triggerRelease\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\np5.MonoSynth.prototype.triggerRelease = function (secondsFromNow = 0) {\n this.env.ramp(this.output.gain, secondsFromNow, 0);\n};\n\n/**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.MonoSynth\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n */\np5.MonoSynth.prototype.setADSR = function (attack, decay, sustain, release) {\n this.env.setADSR(attack, decay, sustain, release);\n};\n\n/**\n * Getters and Setters\n * @property {Number} attack\n * @for p5.MonoSynth\n */\n/**\n * @property {Number} decay\n * @for p5.MonoSynth\n */\n/**\n * @property {Number} sustain\n * @for p5.MonoSynth\n */\n/**\n * @property {Number} release\n * @for p5.MonoSynth\n */\nObject.defineProperties(p5.MonoSynth.prototype, {\n attack: {\n get: function () {\n return this.env.aTime;\n },\n set: function (attack) {\n this.env.setADSR(\n attack,\n this.env.dTime,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n decay: {\n get: function () {\n return this.env.dTime;\n },\n set: function (decay) {\n this.env.setADSR(\n this.env.aTime,\n decay,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n sustain: {\n get: function () {\n return this.env.sPercent;\n },\n set: function (sustain) {\n this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime);\n },\n },\n release: {\n get: function () {\n return this.env.rTime;\n },\n set: function (release) {\n this.env.setADSR(\n this.env.aTime,\n this.env.dTime,\n this.env.sPercent,\n release\n );\n },\n },\n});\n\n/**\n * MonoSynth amp\n * @method amp\n * @for p5.MonoSynth\n * @param {Number} vol desired volume\n * @param {Number} [rampTime] Time to reach new volume\n * @return {Number} new volume value\n */\np5.MonoSynth.prototype.amp = function (vol, rampTime) {\n var t = rampTime || 0;\n if (typeof vol !== 'undefined') {\n this.oscillator.amp(vol, t);\n }\n return this.oscillator.amp().value;\n};\n\n/**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.MonoSynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\n\np5.MonoSynth.prototype.connect = function (unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.MonoSynth\n */\np5.MonoSynth.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.MonoSynth\n */\np5.MonoSynth.prototype.dispose = function () {\n AudioVoice.prototype.dispose.apply(this);\n\n if (this.env) {\n this.env.dispose();\n }\n if (this.oscillator) {\n this.oscillator.dispose();\n }\n};\n","import p5sound from './master';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\nimport { noteToFreq } from './helpers';\n\n/**\n * An AudioVoice is used as a single voice for sound synthesis.\n * The PolySynth class holds an array of AudioVoice, and deals\n * with voices allocations, with setting notes to be played, and\n * parameters to be set.\n *\n * @class p5.PolySynth\n * @constructor\n *\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\n * the AudioVoice class. Defaults to p5.MonoSynth\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n **/\np5.PolySynth = function (audioVoice, maxVoices) {\n //audiovoices will contain maxVoices many monophonic synths\n this.audiovoices = [];\n\n /**\n * An object that holds information about which notes have been played and\n * which notes are currently being played. New notes are added as keys\n * on the fly. While a note has been attacked, but not released, the value of the\n * key is the audiovoice which is generating that note. When notes are released,\n * the value of the key becomes undefined.\n * @property notes\n */\n this.notes = {};\n\n //indices of the most recently used, and least recently used audiovoice\n this._newest = 0;\n this._oldest = 0;\n\n /**\n * A PolySynth must have at least 1 voice, defaults to 8\n * @property polyvalue\n */\n this.maxVoices = maxVoices || 8;\n\n /**\n * Monosynth that generates the sound for each note that is triggered. The\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\n * @property AudioVoice\n */\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\n\n /**\n * This value must only change as a note is attacked or released. Due to delay\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\n * @private\n * @property {Tone.TimelineSignal} _voicesInUse\n */\n this._voicesInUse = new TimelineSignal(0);\n\n this.output = p5sound.audiocontext.createGain();\n this.connect();\n\n //Construct the appropriate number of audiovoices\n this._allocateVoices();\n p5sound.soundArray.push(this);\n};\n\n/**\n * Construct the appropriate number of audiovoices\n * @private\n * @for p5.PolySynth\n * @method _allocateVoices\n */\np5.PolySynth.prototype._allocateVoices = function () {\n for (var i = 0; i < this.maxVoices; i++) {\n this.audiovoices.push(new this.AudioVoice());\n this.audiovoices[i].disconnect();\n this.audiovoices[i].connect(this.output);\n }\n};\n\n/**\n * Play a note by triggering noteAttack and noteRelease with sustain time\n *\n * @method play\n * @for p5.PolySynth\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n */\np5.PolySynth.prototype.play = function (\n note,\n velocity,\n secondsFromNow,\n susTime = 1\n) {\n this.noteAttack(note, velocity, secondsFromNow);\n this.noteRelease(note, secondsFromNow + susTime);\n};\n\n/**\n * noteADSR sets the envelope for a specific note that has just been triggered.\n * Using this method modifies the envelope of whichever audiovoice is being used\n * to play the desired note. The envelope should be reset before noteRelease is called\n * in order to prevent the modified envelope from being used on other notes.\n *\n * @method noteADSR\n * @for p5.PolySynth\n * @param {Number} [note] Midi note on which ADSR should be set.\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\n\np5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var t = now + timeFromNow;\n this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r);\n};\n\n/**\n * Set the PolySynths global envelope. This method modifies the envelopes of each\n * monosynth so that all notes are played with this envelope.\n *\n * @method setADSR\n * @for p5.PolySynth\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\np5.PolySynth.prototype.setADSR = function (a, d, s, r) {\n this.audiovoices.forEach(function (voice) {\n voice.setADSR(a, d, s, r);\n });\n};\n\n/**\n * Trigger the Attack, and Decay portion of a MonoSynth.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @method noteAttack\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\n * @param {Number} [secondsFromNow] time from now (in seconds)\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n */\np5.PolySynth.prototype.noteAttack = function (\n _note,\n _velocity,\n secondsFromNow = 0\n) {\n //this value is used by this._voicesInUse\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\n\n //Convert note to frequency if necessary. This is because entries into this.notes\n //should be based on frequency for the sake of consistency.\n var note = noteToFreq(_note);\n var velocity = _velocity || 0.1;\n\n var currentVoice;\n\n //Release the note if it is already playing\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\n this.noteRelease(note, 0);\n }\n\n //Check to see how many voices are in use at the time the note will start\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\n }\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\n //with a new note\n else {\n currentVoice = this._oldest;\n\n var oldestNote = p5.prototype.freqToMidi(\n this.audiovoices[this._oldest].oscillator.freq().value\n );\n this.noteRelease(oldestNote);\n this._oldest = (this._oldest + 1) % (this.maxVoices - 1);\n }\n\n //Overrite the entry in the notes object. A note (frequency value)\n //corresponds to the index of the audiovoice that is playing it\n this.notes[note] = new TimelineSignal();\n this.notes[note].setValueAtTime(currentVoice, acTime);\n\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //Add 1 and schedule this value at time 't', when this note will start playing\n var previousVal =\n this._voicesInUse._searchBefore(acTime) === null\n ? 0\n : this._voicesInUse._searchBefore(acTime).value;\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\n\n //Then update all scheduled values that follow to increase by 1\n this._updateAfter(acTime, 1);\n\n this._newest = currentVoice;\n //The audiovoice handles the actual scheduling of the note\n if (typeof velocity === 'number') {\n var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2;\n velocity = velocity > maxRange ? maxRange : velocity;\n }\n\n // use secondsFromNow because this method will add AudioContext currentTime\n this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);\n};\n\n/**\n * Private method to ensure accurate values of this._voicesInUse\n * Any time a new value is scheduled, it is necessary to increment all subsequent\n * scheduledValues after attack, and decrement all subsequent\n * scheduledValues after release\n *\n * @private\n * @for p5.PolySynth\n * @param {[type]} time [description]\n * @param {[type]} value [description]\n * @return {[type]} [description]\n */\np5.PolySynth.prototype._updateAfter = function (time, value) {\n if (this._voicesInUse._searchAfter(time) === null) {\n return;\n } else {\n this._voicesInUse._searchAfter(time).value += value;\n var nextTime = this._voicesInUse._searchAfter(time).time;\n this._updateAfter(nextTime, value);\n }\n};\n\n/**\n * Trigger the Release of an AudioVoice note. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method noteRelease\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * If no value is provided, all notes will be released.\n * @param {Number} [secondsFromNow] time to trigger the release\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n *\n */\np5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n // if a note value is not provided, release all voices\n if (!_note) {\n this.audiovoices.forEach(function (voice) {\n voice.triggerRelease(tFromNow);\n });\n this._voicesInUse.setValueAtTime(0, t);\n for (var n in this.notes) {\n this.notes[n].dispose();\n delete this.notes[n];\n }\n return;\n }\n\n //Make sure note is in frequency inorder to query the this.notes object\n var note = noteToFreq(_note);\n\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\n console.warn('Cannot release a note that is not already playing');\n } else {\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //subtract 1 and schedule this value at time 't', when this note will stop playing\n var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\n if (previousVal > 0) {\n this._updateAfter(t, -1);\n }\n\n this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(\n tFromNow\n );\n this.notes[note].dispose();\n delete this.notes[note];\n\n this._newest =\n this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\n }\n};\n\n/**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.PolySynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\np5.PolySynth.prototype.connect = function (unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.PolySynth\n */\np5.PolySynth.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.PolySynth\n */\np5.PolySynth.prototype.dispose = function () {\n this.audiovoices.forEach(function (voice) {\n voice.dispose();\n });\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n};\n","import Effect from './effect.js';\n\n/*\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n */\nfunction makeDistortionCurve(amount) {\n var k = typeof amount === 'number' ? amount : 50;\n var numSamples = 44100;\n var curve = new Float32Array(numSamples);\n var deg = Math.PI / 180;\n var i = 0;\n var x;\n for (; i < numSamples; ++i) {\n x = (i * 2) / numSamples - 1;\n curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x));\n }\n return curve;\n}\n\n/**\n * A Distortion effect created with a Waveshaper Node,\n * with an approach adapted from\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Distortion\n * @extends p5.Effect\n * @constructor\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n *\n */\np5.Distortion = function (amount, oversample) {\n Effect.call(this);\n\n if (typeof amount === 'undefined') {\n amount = 0.25;\n }\n if (typeof amount !== 'number') {\n throw new Error('amount must be a number');\n }\n if (typeof oversample === 'undefined') {\n oversample = '2x';\n }\n if (typeof oversample !== 'string') {\n throw new Error('oversample must be a String');\n }\n\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n\n /**\n * The p5.Distortion is built with a\n * \n * Web Audio WaveShaper Node.\n *\n * @property {AudioNode} WaveShaperNode\n */\n this.waveShaperNode = this.ac.createWaveShaper();\n\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n this.waveShaperNode.oversample = oversample;\n\n this.input.connect(this.waveShaperNode);\n\n this.waveShaperNode.connect(this.wet);\n};\n\np5.Distortion.prototype = Object.create(Effect.prototype);\n\n/**\n * Process a sound source, optionally specify amount and oversample values.\n *\n * @method process\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\np5.Distortion.prototype.process = function (src, amount, oversample) {\n src.connect(this.input);\n this.set(amount, oversample);\n};\n\n/**\n * Set the amount and oversample of the waveshaper distortion.\n *\n * @method set\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\np5.Distortion.prototype.set = function (amount, oversample) {\n if (amount) {\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n }\n if (oversample) {\n this.waveShaperNode.oversample = oversample;\n }\n};\n\n/**\n * Return the distortion amount, typically between 0-1.\n *\n * @method getAmount\n * @for p5.Distortion\n * @return {Number} Unbounded distortion amount.\n * Normal values range from 0-1.\n */\np5.Distortion.prototype.getAmount = function () {\n return this.amount;\n};\n\n/**\n * Return the oversampling.\n *\n * @method getOversample\n * @for p5.Distortion\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\n */\np5.Distortion.prototype.getOversample = function () {\n return this.waveShaperNode.oversample;\n};\n\np5.Distortion.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n if (this.waveShaperNode) {\n this.waveShaperNode.disconnect();\n this.waveShaperNode = null;\n }\n};\n\nexport default p5.Distortion;\n","import 'audioworklet-polyfill';\nimport './shims';\nimport './audiocontext';\nimport './master';\nimport './helpers';\nimport './errorHandler';\nimport './audioWorklet';\nimport './panner';\nimport './soundfile';\nimport './amplitude';\nimport './fft';\nimport './signal';\nimport './oscillator';\nimport './envelope';\nimport './pulse';\nimport './noise';\nimport './audioin';\nimport './filter';\nimport './eq';\nimport './panner3d';\nimport './listener3d';\nimport './delay';\nimport './reverb';\nimport './metro';\nimport './looper';\nimport './soundLoop';\nimport './compressor';\nimport './soundRecorder';\nimport './peakDetect';\nimport './gain';\nimport './monosynth';\nimport './polysynth';\nimport './distortion';\nimport './audioVoice';\nimport './monosynth';\nimport './polysynth';\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///../node_modules/tone/Tone/core/Tone.js","webpack:///../node_modules/tone/Tone/signal/Multiply.js","webpack:///../node_modules/tone/Tone/signal/Signal.js","webpack:///./audiocontext.js","webpack:///../node_modules/tone/Tone/signal/Add.js","webpack:///./audioWorklet/processorNames.js","webpack:///../node_modules/tone/Tone/signal/WaveShaper.js","webpack:///../node_modules/tone/Tone/signal/TimelineSignal.js","webpack:///../node_modules/tone/Tone/signal/Scale.js","webpack:///../node_modules/tone/Tone/type/Type.js","webpack:///../node_modules/tone/Tone/core/Gain.js","webpack:///../node_modules/tone/Tone/core/Clock.js","webpack:///../node_modules/tone/Tone/core/Context.js","webpack:///../node_modules/tone/Tone/signal/Subtract.js","webpack:///../node_modules/tone/Tone/core/Emitter.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:///../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/startaudiocontext/StartAudioContext.js","webpack:///../node_modules/tone/Tone/component/CrossFade.js","webpack:///../node_modules/audioworklet-polyfill/dist/audioworklet-polyfill.js","webpack:///./shims.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///./audioWorklet/recorderProcessor.js","webpack:///./audioWorklet/soundFileProcessor.js","webpack:///./audioWorklet/amplitudeProcessor.js","webpack:///../node_modules/tone/Tone/type/Frequency.js","webpack:///../node_modules/tone/Tone/type/TransportTime.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:///../node_modules/tone/Tone/core/TimelineState.js","webpack:///./master.js","webpack:///./helpers.js","webpack:///./errorHandler.js","webpack:///./audioWorklet/index.js","webpack:///./panner.js","webpack:///./soundfile.js","webpack:///./amplitude.js","webpack:///./fft.js","webpack:///./oscillator.js","webpack:///./envelope.js","webpack:///./noise.js","webpack:///./pulse.js","webpack:///./audioin.js","webpack:///./effect.js","webpack:///./filter.js","webpack:///./eqFilter.js","webpack:///./eq.js","webpack:///./listener3d.js","webpack:///./panner3d.js","webpack:///./delay.js","webpack:///./reverb.js","webpack:///./metro.js","webpack:///./looper.js","webpack:///./soundLoop.js","webpack:///./compressor.js","webpack:///./peakDetect.js","webpack:///./soundRecorder.js","webpack:///./distortion.js","webpack:///./gain.js","webpack:///./audioVoice.js","webpack:///./monosynth.js","webpack:///./onsetDetect.js","webpack:///./polysynth.js","webpack:///./deprecations/Signal.js","webpack:///./app.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","Multiply","createInsOuts","_mult","Gain","_param","_gain","getConstant","units","Type","Default","convert","SignalBase","global","audiocontext","AudioContext","getAudioContext","userStartAudio","elements","callback","elt","p5","Element","map","e","StartAudioContext","Add","_sum","module","exports","recorderProcessor","soundFileProcessor","amplitudeProcessor","WaveShaper","mapping","bufferLen","_shaper","createWaveShaper","_curve","curve","isFinite","Float32Array","setMap","len","normalized","oversample","oversampling","RangeError","TimelineSignal","_events","Timeline","_initial","_fromUnits","Linear","Exponential","Target","Curve","Set","getValueAtTime","_toUnits","convertedVal","cancelScheduledValues","setValueAtTime","startTime","toSeconds","add","type","time","linearRampToValueAtTime","endTime","exponentialRampToValueAtTime","beforeEvent","_searchBefore","_minOutput","setValue","max","sampleTime","setTargetAtTime","timeConstant","constant","setValueCurveAtTime","duration","scaling","floats","segmentTime","after","cancel","setRampPoint","before","_searchAfter","linearRampToValueBetween","start","finish","exponentialRampToValueBetween","getAfter","previouVal","previous","getBefore","_exponentialApproach","_curveInterpolate","_linearInterpolate","_exponentialInterpolate","t0","v0","v1","t","exp","t1","progress","lowerIndex","floor","upperIndex","ceil","lowerVal","upperVal","Scale","outputMin","outputMax","_outputMin","_outputMax","_scale","_add","_setRange","min","Time","Frequency","TransportTime","Ticks","NormalRange","AudioRange","Decibels","Interval","BPM","Positive","Cents","Degrees","MIDI","BarsBeatsSixteenths","Samples","Hertz","Note","Milliseconds","Seconds","Notation","TimeBase","toFrequency","freq","valueOf","toTicks","Transport","ticks","GainNode","createGainNode","_gainNode","Clock","Emitter","_nextTick","_lastState","frequency","_state","TimelineState","_boundLoop","_loop","bind","on","lookAhead","offset","state","stop","setStateAtTime","pause","loopInterval","updateInterval","lag","currentState","event","tickTime","getStateAtTime","off","Infinity","toneConnect","B","outNum","inNum","nativeConnect","Error","nativeDisconnect","webkitAudioContext","prop","_context","_defineProperty","_latencyHint","_lookAhead","_updateInterval","_computedUpdateInterval","_worker","_createWorker","_constants","mixin","currentTime","URL","webkitURL","blob","Blob","toFixed","blobUrl","createObjectURL","worker","Worker","addEventListener","_lastUpdate","diff","buffer","createBuffer","arr","getChannelData","createBufferSource","channelCount","channelCountMode","loop","lA","blockTime","postMessage","hint","latencyHint","supported","warn","Subtract","_neg","Negate","events","eventName","ev","eventList","args","slice","object","functions","func","emitterFunc","node","outputNumber","inputNumber","overridden","_plusNow","_unaryExpressions","create","quantize","regexp","method","rh","nextSubdivision","lh","subdiv","_expr","expr","subdivision","round","addNow","_defaultExpr","_noOp","copy","toNotation","retNotation","_toNotationHelper","retTripletNotation","testNotations","threshold","_notationToUnits","notationTime","multiple","notation","primaryExprs","_primaryExpressions","notationExprs","n","m","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","name","sub","mult","div","_lfo","lfo","undefined","LFO","currentVal","exponentialRampToValue","linearRampToValue","_timeline","_toRemove","_iterating","memory","index","_search","remove","shift","cancelBefore","beginning","end","midPoint","nextEvent","_iterate","lowerBound","upperBound","forEach","forEachBefore","forEachAfter","forEachFrom","forEachAtTime","_multiply","GreaterThanZero","_thresh","root","factory","amd","TapListener","element","_dragged","_element","_bindedMove","_moved","_bindedEnd","_ended","isStarted","source","resume","startContext","removeEventListener","promise","Promise","success","checkLoop","requestAnimationFrame","onStarted","tapListeners","bindTapListener","NodeList","document","querySelectorAll","jquery","toArray","tap","body","then","CrossFade","initialFade","a","b","fade","_equalPowerA","EqualPowerGain","_equalPowerB","_invert","Expr","r","parameters","o","bufferSize","fill","processor","realm","exec","inputBuffer","outputBuffer","process","numberOfChannels","$$processors","$$context","AudioWorkletNode","self","createScriptProcessor","outputChannelCount","Map","properties","u","c","l","defaultValue","p","MessageChannel","port2","f","Processor","port","port1","onaudioprocess","$$audioWorklet","AudioWorklet","addModule","fetch","ok","status","text","AudioWorkletProcessor","registerProcessor","parameterDescriptors","createElement","style","cssText","appendChild","contentWindow","createTextNode","$hook","documentElement","transpile","String","fixSetTarget","setTargetValueAtTime","createDelay","createDelayNode","createJavaScriptNode","createPeriodicWave","createWaveTable","internal_createGain","internal_createDelay","maxDelayTime","delayTime","internal_createBufferSource","when","noteGrainOn","noteOn","internal_start","noteOff","internal_stop","playbackRate","internal_createDynamicsCompressor","createDynamicsCompressor","knee","ratio","reduction","attack","release","internal_createBiquadFilter","createBiquadFilter","detune","Q","createOscillator","internal_createOscillator","setPeriodicWave","setWaveTable","OfflineAudioContext","webkitOfflineAudioContext","navigator","getUserMedia","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","el","isSupported","canPlayType","isOGGSupported","isMP3Supported","isWAVSupported","isAACSupported","isAIFSupported","isFileSupported","extension","toLowerCase","g","Function","midi","midiToFrequency","note","pitch","octave","noteNumber","noteToScaleIndex","transpose","harmonize","intervals","toMidi","frequencyToMidi","toNote","A4","LN2","scaleIndexToNote","cbb","cb","c#","cx","dbb","d","d#","dx","ebb","eb","e#","ex","fbb","fb","f#","fx","gbb","gb","g#","gx","abb","ab","a#","ax","bbb","bb","b#","bx","_secondsToTicks","applyBinary","Constructor","_eval","applyUnary","getNumber","literalNumber","_replacements","inputCount","_parseInputs","_nodes","result","tree","_parseTree","_disposeNodes","_Expressions","signal","glue",",","abs","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","x","_eqPower","initial","Master","limiter","meter","fftMeter","soundArray","parts","extensions","p5sound","getMasterVolume","masterVolume","vol","tFromNow","currentVol","soundOut","_silentNode","freqToMidi","mathlog2","midiToFreq","noteToFreq","wholeNotes","A","C","D","E","F","G","toUpperCase","soundFormats","disposeSound","_checkFileFormats","paths","path","extTest","pop","pathSplit","pathCore","_mathChain","math","thisChain","nextChain","mathOps","convertToWav","audioBuffer","leftChannel","rightChannel","interleaved","interleave","ArrayBuffer","view","DataView","writeUTFBytes","setUint32","setUint16","lng","volume","setInt16","inputIndex","string","setUint8","charCodeAt","safeBufferSize","idealBufferSize","tempAudioWorkletNode","processorNames","ScriptProcessorNode","saveSound","soundFile","fileName","dataView","writeFile","CustomError","errorTrace","failedPath","err","tempStack","splitStack","originalStack","stack","filter","ln","moduleSources","require","ac","loadAudioWorkletModules","all","moduleSrc","objectURL","audioWorklet","registerMethod","preload","_incrementPreload","onWorkletModulesLoad","_decrementPreload","panner","createStereoPanner","Panner","stereoPanner","pan","obj","numInputChannels","left","right","channelInterpretation","splitter","createChannelSplitter","createChannelMerger","v","rightVal","cos","leftVal","numChannels","_createCounterBuffer","audioBuf","arrayBuffer","Peak","amp","sampleIndex","amplitude","tempos","getPeaksAtThreshold","data","peaksObj","peak","countIntervalsBetweenNearbyPeaks","intervalCounts","peaksArray","sort","startPeak","endPeak","startPos","endPos","foundInterval","some","intervalCount","count","groupNeighborsByTempo","tempoCounts","theoreticalTempo","mapTempo","foundTempo","tempoCount","tempo","isNaN","getPeaksAtTopTempo","bpmVariance","peaksAtTopTempo","key","intervalBPM","peakTime","dif","Cue","id","_clearOnEnd","thisBufferSourceNode","target","_playing","_onended","bufferSourceNodes","_","reverse","SoundFile","onload","onerror","whileLoading","url","File","FileReader","FileList","file","_looping","_paused","_pauseTime","_cues","_cueIDCounter","_lastPos","_counterNode","_workletNode","bufferSourceNode","reversed","pauseTime","mode","startMillis","panPosition","load","_whileLoading","setVolume","errorCallback","request","XMLHttpRequest","evt","_updateProgress","open","responseType","decodeAudioData","response","buff","inputChannels","msg","error","statusText","message","send","reader","readAsArrayBuffer","lengthComputable","percentComplete","loaded","rate","_cueStart","cueStart","cueEnd","isPlaying","_initSourceNode","_initCounterNode","_arrayIndex","loopStart","loopEnd","str","pTime","play","bool","timeFromNow","stopAll","_time","pval","reverseBuffer","num","newPlaybackRate","_rampTime","_tFromNow","cueTime","cTime","dur","width","sampleSize","sampleStep","channels","peaks","chan","currentPos","curVol","getVolume","jump","buf","size","newBuffer","channelNum","channel","cNode","workletBufferSize","processorOptions","onmessage","_onTimeUpdate","_initThreshold","_minThreshold","_minPeaks","bufLen","allPeaks","initialThreshold","minThreshold","minPeaks","offlineContext","startRendering","oncomplete","filteredBuffer","renderedBuffer","bufferData","groups","topTempos","intA","intB","tempoPeaks","cue","cueLength","playbackTime","callbackTime","leftLimit","_prevUpdateTime","rightLimit","loadSound","location","origin","cordova","alert","Amplitude","smoothing","parameterData","normalize","volNorm","stereoVol","stereoVolNorm","FFT","bins","analyser","createAnalyser","defineProperties","fftSize","configurable","smoothingTimeConstant","smooth","freqDomain","Uint8Array","frequencyBinCount","timeDomain","bass","lowMid","mid","highMid","treble","normalArray","_isSafari","timeToFloat","getFloatTimeDomainData","timeToInt","getByteTimeDomainData","scaled","freqToFloat","getFloatFrequencyData","freqToInt","getByteFrequencyData","frequency1","frequency2","nyquist","swap","lowIndex","highIndex","numFrequencies","toReturn","freq1","freq2","getEnergy","cumulative_sum","centroid_normalization","mean_freq_index","spec_centroid_freq","_N","N","spectrum","spectrumLength","spectrumStep","linearAverages","groupIndex","specIndex","octaveBands","logAverages","octaveIndex","specIndexFrequency","hi","_fCtr0","fCtr0","lastFrequencyBand","lo","ctr","newFrequencyBand","fft","sigChain","mathObj","chainSource","oscillator","Oscillator","started","phaseAmount","_freqMods","connection","freqNode","phase","oscMods","osc2","delayAmt","dNode","Mult","inMin","inMax","outMin","outMax","mapOutMin","mapOutMax","scale","SinOsc","TriOsc","SawOsc","SqrOsc","Envelope","l1","t2","l2","t3","l3","aTime","aLevel","dTime","dLevel","rTime","rLevel","_rampHighPercentage","_rampLowPercentage","control","_init","isExponential","sourceToClear","wasTriggered","_setRampAD","setADSR","sPercent","setRange","_rampAttackTime","checkExpInput","_rampDecayTime","TCDenominator","_rampAttackTC","_rampDecayTC","setRampPercentages","p1","p2","setInput","setExp","isExp","secondsFromNow","susTime","triggerAttack","triggerRelease","lastAttack","valToSet","ramp","v2","destination1","destination2","AudioIn","Reverb","Noise","Filter","Delay","Env","_whiteNoiseBuffer","whiteBuffer","noiseData","random","_pinkNoiseBuffer","pinkBuffer","b0","b1","b2","b3","b4","b5","b6","white","_brownNoiseBuffer","brownBuffer","lastOut","assignType","noise","Pulse","w","dcOffset","createDCOffset","dcGain","mW","sig","mult1","mult2","mods","currentFreq","freqMod","bufferSource","inputSources","stream","mediaStream","currentSource","enabled","MediaStreamTrack","mediaDevices","successCallback","audioSource","constraints","audio","echoCancellation","deviceId","createMediaStreamSource","getTracks","track","getLevel","onSuccess","onError","resolve","reject","enumerateDevices","devices","device","kind","active","Effect","_drywet","wet","biquad","setType","_on","_untoggledType","src","res","LowPass","HighPass","BandPass","EQFilter","EQ","_eqsize","factor","bands","_newBand","Listener3D","listener","xVal","yVal","zVal","positionX","positionY","positionZ","xValF","yValF","zValF","xValU","yValU","zValU","orientForward","orientUp","forwardX","forwardY","forwardZ","upX","upY","upZ","Panner3D","createPanner","panningModel","distanceModel","orientX","orientY","orientZ","orientationX","orientationY","orientationZ","maxDistance","rolloffFactor","maxDist","rolloff","_split","_merge","_leftGain","_rightGain","leftDelay","rightDelay","_leftFilter","_rightFilter","_maxDelay","maxValue","feedback","_delayTime","_feedback","_filter","_initConvolverNode","_seconds","_decay","_reverse","_buildImpulse","convolverNode","createConvolver","_teardownConvolverNode","decayRate","rebuild","decay","impulse","impulseL","impulseR","_setBuffer","Convolver","impulses","_loadBuffer","_path","chunks","cReverb","Metro","clock","ontick","syncedParts","prevTick","tatumTime","tickCallback","elapsedTime","thisPart","incrementStep","phrases","thisPhrase","phraseArray","sequence","bNum","metroTicks","looping","beatTime","tatums","getRate","part","setBPM","Phrase","phraseStep","Part","steps","bLength","partStep","noLoop","metro","beatLength","getBPM","resetSync","onended","array","Score","currentPart","thisScore","nextPart","resetPart","playNextPart","resetParts","scoreStep","aScore","SoundLoop","_bpm","musicalTimeMode","_update","timeSig","_interval","maxIterations","iterations","_calcFreq","otherLoop","_convertNotation","Number","_measure","_note","Compressor","compressor","number","PeakDetect","_framesPerPeak","framesPerPeak","framesSinceLastPeak","cutoff","cutoffMult","energy","penergy","currentValue","isDetected","f1","f2","_onPeak","fftObject","nrg","SoundRecorder","_inputChannels","_outputChannels","buffers","leftBuffer","rightBuffer","_callback","sFile","setBuffer","makeDistortionCurve","amount","k","numSamples","deg","Distortion","curveAmount","waveShaperNode","AudioVoice","velocity","sustime","DEFAULT_SUSTAIN","MonoSynth","env","sustain","vel","OnsetDetect","freqLow","freqHigh","treshold","sensitivity","setTimeout","PolySynth","audioVoice","maxVoices","audiovoices","notes","_newest","_oldest","_voicesInUse","_allocateVoices","noteAttack","noteRelease","voice","_velocity","acTime","currentVoice","oldestNote","previousVal","_updateAfter","maxRange","nextTime","registerPreloadMethod","listener3D","peakDetect"],"mappings":"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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 = 40);\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","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","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});","global.TONE_SILENCE_VERSION_LOGGING = true;\n\nimport StartAudioContext from 'startaudiocontext';\nimport Tone from 'Tone/core/Tone';\nimport 'Tone/core/Context';\n\n// Create the Audio Context\nconst audiocontext = new window.AudioContext();\n\n// Tone and p5.sound share the same audio context\nTone.setContext(audiocontext);\n\n/**\n *

Returns the Audio Context for this sketch. Useful for users\n * who would like to dig deeper into the Web Audio API\n * .

\n *\n *

Some browsers require users to startAudioContext\n * with a user gesture, such as touchStarted in the example below.

\n *\n * @for p5\n * @method getAudioContext\n * @return {Object} AudioContext for this sketch\n * @example\n *
\n * function draw() {\n * background(255);\n * textAlign(CENTER);\n *\n * if (getAudioContext().state !== 'running') {\n * text('click to start audio', width/2, height/2);\n * } else {\n * text('audio is enabled', width/2, height/2);\n * }\n * }\n *\n * function touchStarted() {\n * if (getAudioContext().state !== 'running') {\n * getAudioContext().resume();\n * }\n * var synth = new p5.MonoSynth();\n * synth.play('A4', 0.5, 0, 0.2);\n * }\n *\n *
\n */\nexport function getAudioContext() {\n return audiocontext;\n}\n\n/**\n *

It is not only a good practice to give users control over starting\n * audio. This policy is enforced by many web browsers, including iOS and\n * Google Chrome, which create the Web Audio API's\n * Audio Context\n * in a suspended state.

\n *\n *

In these browser-specific policies, sound will not play until a user\n * interaction event (i.e. mousePressed()) explicitly resumes\n * the AudioContext, or starts an audio node. This can be accomplished by\n * calling start() on a p5.Oscillator,\n * play() on a p5.SoundFile, or simply\n * userStartAudio().

\n *\n *

userStartAudio() starts the AudioContext on a user\n * gesture. The default behavior will enable audio on any\n * mouseUp or touchEnd event. It can also be placed in a specific\n * interaction function, such as mousePressed() as in the\n * example below. This method utilizes\n * StartAudioContext\n * , a library by Yotam Mann (MIT Licence, 2016).

\n * @param {Element|Array} [element(s)] This argument can be an Element,\n * Selector String, NodeList, p5.Element,\n * jQuery Element, or an Array of any of those.\n * @param {Function} [callback] Callback to invoke when the AudioContext\n * has started\n * @return {Promise} Returns a Promise that resolves when\n * the AudioContext state is 'running'\n * @method userStartAudio\n * @for p5\n * @example\n *
\n * function setup() {\n * // mimics the autoplay policy\n * getAudioContext().suspend();\n *\n * let mySynth = new p5.MonoSynth();\n *\n * // This won't play until the context has resumed\n * mySynth.play('A6');\n * }\n * function draw() {\n * background(220);\n * textAlign(CENTER, CENTER);\n * text(getAudioContext().state, width/2, height/2);\n * }\n * function mousePressed() {\n * userStartAudio();\n * }\n *
\n */\nexport function userStartAudio(elements, callback) {\n var elt = elements;\n if (elements instanceof p5.Element) {\n elt = elements.elt;\n } else if (elements instanceof Array && elements[0] instanceof p5.Element) {\n elt = elements.map(function (e) {\n return e.elt;\n });\n }\n return StartAudioContext(audiocontext, elt, callback);\n}\n\nexport default audiocontext;\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});","module.exports = {\n recorderProcessor: 'recorder-processor',\n soundFileProcessor: 'sound-file-processor',\n amplitudeProcessor: 'amplitude-processor',\n};\n","define([\"Tone/core/Tone\", \"Tone/signal/SignalBase\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Wraps the native Web Audio API \n\t * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {function|Array|Number} mapping The function used to define the values. \n\t * The mapping function should take two arguments: \n\t * the first is the value at the current position \n\t * and the second is the array position. \n\t * If the argument is an array, that array will be\n\t * set as the wave shaping function. The input\n\t * signal is an AudioRange [-1, 1] value and the output\n\t * signal can take on any numerical values. \n\t * \n\t * @param {Number} [bufferLen=1024] The length of the WaveShaperNode buffer.\n\t * @example\n\t * var timesTwo = new Tone.WaveShaper(function(val){\n\t * \treturn val * 2;\n\t * }, 2048);\n\t * @example\n\t * //a waveshaper can also be constructed with an array of values\n\t * var invert = new Tone.WaveShaper([1, -1]);\n\t */\n\tTone.WaveShaper = function(mapping, bufferLen){\n\n\t\t/**\n\t\t * the waveshaper\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._shaper = this.input = this.output = this.context.createWaveShaper();\n\n\t\t/**\n\t\t * the waveshapers curve\n\t\t * @type {Float32Array}\n\t\t * @private\n\t\t */\n\t\tthis._curve = null;\n\n\t\tif (Array.isArray(mapping)){\n\t\t\tthis.curve = mapping;\n\t\t} else if (isFinite(mapping) || this.isUndef(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(mapping, 1024));\n\t\t} else if (this.isFunction(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(bufferLen, 1024));\n\t\t\tthis.setMap(mapping);\n\t\t} \n\t};\n\n\tTone.extend(Tone.WaveShaper, Tone.SignalBase);\n\n\t/**\n\t * Uses a mapping function to set the value of the curve. \n\t * @param {function} mapping The function used to define the values. \n\t * The mapping function take two arguments: \n\t * the first is the value at the current position \n\t * which goes from -1 to 1 over the number of elements\n\t * in the curve array. The second argument is the array position. \n\t * @returns {Tone.WaveShaper} this\n\t * @example\n\t * //map the input signal from [-1, 1] to [0, 10]\n\t * shaper.setMap(function(val, index){\n\t * \treturn (val + 1) * 5;\n\t * })\n\t */\n\tTone.WaveShaper.prototype.setMap = function(mapping){\n\t\tfor (var i = 0, len = this._curve.length; i < len; i++){\n\t\t\tvar normalized = (i / (len - 1)) * 2 - 1;\n\t\t\tthis._curve[i] = mapping(normalized, i);\n\t\t}\n\t\tthis._shaper.curve = this._curve;\n\t\treturn this;\n\t};\n\n\t/**\n\t * The array to set as the waveshaper curve. For linear curves\n\t * array length does not make much difference, but for complex curves\n\t * longer arrays will provide smoother interpolation. \n\t * @memberOf Tone.WaveShaper#\n\t * @type {Array}\n\t * @name curve\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"curve\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.curve;\n\t\t},\n\t\tset : function(mapping){\n\t\t\tthis._curve = new Float32Array(mapping);\n\t\t\tthis._shaper.curve = this._curve;\n\t\t}\n\t});\n\n\t/**\n\t * Specifies what type of oversampling (if any) should be used when \n\t * applying the shaping curve. Can either be \"none\", \"2x\" or \"4x\". \n\t * @memberOf Tone.WaveShaper#\n\t * @type {string}\n\t * @name oversample\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"oversample\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.oversample;\n\t\t},\n\t\tset : function(oversampling){\n\t\t\tif ([\"none\", \"2x\", \"4x\"].indexOf(oversampling) !== -1){\n\t\t\t\tthis._shaper.oversample = oversampling;\n\t\t\t} else {\n\t\t\t\tthrow new RangeError(\"Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'\");\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.WaveShaper} this\n\t */\n\tTone.WaveShaper.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.disconnect();\n\t\tthis._shaper = null;\n\t\tthis._curve = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.WaveShaper;\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});","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/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 * \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 * @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});","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});","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/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});","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});","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});","/**\n * StartAudioContext.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2016 Yotam Mann\n */\n(function (root, factory) {\n\tif (typeof define === \"function\" && define.amd) {\n\t\tdefine([], factory)\n\t } else if (typeof module === \"object\" && module.exports) {\n module.exports = factory()\n\t} else {\n\t\troot.StartAudioContext = factory()\n }\n}(this, function () {\n\n\t//TAP LISTENER/////////////////////////////////////////////////////////////\n\n\t/**\n\t * @class Listens for non-dragging tap ends on the given element\n\t * @param {Element} element\n\t * @internal\n\t */\n\tvar TapListener = function(element, context){\n\n\t\tthis._dragged = false\n\n\t\tthis._element = element\n\n\t\tthis._bindedMove = this._moved.bind(this)\n\t\tthis._bindedEnd = this._ended.bind(this, context)\n\n\t\telement.addEventListener(\"touchstart\", this._bindedEnd)\n\t\telement.addEventListener(\"touchmove\", this._bindedMove)\n\t\telement.addEventListener(\"touchend\", this._bindedEnd)\n\t\telement.addEventListener(\"mouseup\", this._bindedEnd)\n\t}\n\n\t/**\n\t * drag move event\n\t */\n\tTapListener.prototype._moved = function(e){\n\t\tthis._dragged = true\n\t};\n\n\t/**\n\t * tap ended listener\n\t */\n\tTapListener.prototype._ended = function(context){\n\t\tif (!this._dragged){\n\t\t\tstartContext(context)\n\t\t}\n\t\tthis._dragged = false\n\t};\n\n\t/**\n\t * remove all the bound events\n\t */\n\tTapListener.prototype.dispose = function(){\n\t\tthis._element.removeEventListener(\"touchstart\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"touchmove\", this._bindedMove)\n\t\tthis._element.removeEventListener(\"touchend\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"mouseup\", this._bindedEnd)\n\t\tthis._bindedMove = null\n\t\tthis._bindedEnd = null\n\t\tthis._element = null\n\t};\n\n\t//END TAP LISTENER/////////////////////////////////////////////////////////\n\n\t/**\n\t * Plays a silent sound and also invoke the \"resume\" method\n\t * @param {AudioContext} context\n\t * @private\n\t */\n\tfunction startContext(context){\n\t\t// this accomplishes the iOS specific requirement\n\t\tvar buffer = context.createBuffer(1, 1, context.sampleRate)\n\t\tvar source = context.createBufferSource()\n\t\tsource.buffer = buffer\n\t\tsource.connect(context.destination)\n\t\tsource.start(0)\n\n\t\t// resume the audio context\n\t\tif (context.resume){\n\t\t\tcontext.resume()\n\t\t}\n\t}\n\n\t/**\n\t * Returns true if the audio context is started\n\t * @param {AudioContext} context\n\t * @return {Boolean}\n\t * @private\n\t */\n\tfunction isStarted(context){\n\t\t return context.state === \"running\"\n\t}\n\n\t/**\n\t * Invokes the callback as soon as the AudioContext\n\t * is started\n\t * @param {AudioContext} context\n\t * @param {Function} callback\n\t */\n\tfunction onStarted(context, callback){\n\n\t\tfunction checkLoop(){\n\t\t\tif (isStarted(context)){\n\t\t\t\tcallback()\n\t\t\t} else {\n\t\t\t\trequestAnimationFrame(checkLoop)\n\t\t\t\tif (context.resume){\n\t\t\t\t\tcontext.resume()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isStarted(context)){\n\t\t\tcallback()\n\t\t} else {\n\t\t\tcheckLoop()\n\t\t}\n\t}\n\n\t/**\n\t * Add a tap listener to the audio context\n\t * @param {Array|Element|String|jQuery} element\n\t * @param {Array} tapListeners\n\t */\n\tfunction bindTapListener(element, tapListeners, context){\n\t\tif (Array.isArray(element) || (NodeList && element instanceof NodeList)){\n\t\t\tfor (var i = 0; i < element.length; i++){\n\t\t\t\tbindTapListener(element[i], tapListeners, context)\n\t\t\t}\n\t\t} else if (typeof element === \"string\"){\n\t\t\tbindTapListener(document.querySelectorAll(element), tapListeners, context)\n\t\t} else if (element.jquery && typeof element.toArray === \"function\"){\n\t\t\tbindTapListener(element.toArray(), tapListeners, context)\n\t\t} else if (Element && element instanceof Element){\n\t\t\t//if it's an element, create a TapListener\n\t\t\tvar tap = new TapListener(element, context)\n\t\t\ttapListeners.push(tap)\n\t\t} \n\t}\n\n\t/**\n\t * @param {AudioContext} context The AudioContext to start.\n\t * @param {Array|String|Element|jQuery=} elements For iOS, the list of elements\n\t * to bind tap event listeners\n\t * which will start the AudioContext. If\n\t * no elements are given, it will bind\n\t * to the document.body.\n\t * @param {Function=} callback The callback to invoke when the AudioContext is started.\n\t * @return {Promise} The promise is invoked when the AudioContext\n\t * is started.\n\t */\n\tfunction StartAudioContext(context, elements, callback){\n\n\t\t//the promise is invoked when the AudioContext is started\n\t\tvar promise = new Promise(function(success) {\n\t\t\tonStarted(context, success)\n\t\t})\n\n\t\t// The TapListeners bound to the elements\n\t\tvar tapListeners = []\n\n\t\t// add all the tap listeners\n\t\tif (!elements){\n\t\t\telements = document.body\n\t\t}\n\t\tbindTapListener(elements, tapListeners, context)\n\n\t\t//dispose all these tap listeners when the context is started\n\t\tpromise.then(function(){\n\t\t\tfor (var i = 0; i < tapListeners.length; i++){\n\t\t\t\ttapListeners[i].dispose()\n\t\t\t}\n\t\t\ttapListeners = null\n\n\t\t\tif (callback){\n\t\t\t\tcallback()\n\t\t\t}\n\t\t})\n\n\t\treturn promise\n\t}\n\n\treturn StartAudioContext\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","!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._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\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.numOutputChannels = options.outputChannelCount || 2;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.bufferSize = processorOptions.bufferSize || 1024;\\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) {\\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 this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannelCopy);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n }\\n\\n this.recordedSamples += this.bufferSize;\\n }\\n\\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 var _this2 = this;\\n\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this2.bufferSize);\\n });\\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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar SoundFileProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\\n\\n function SoundFileProcessor(options) {\\n var _this;\\n\\n _classCallCheck(this, SoundFileProcessor);\\n\\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\\n var processorOptions = options.processorOptions || {};\\n _this.bufferSize = processorOptions.bufferSize || 256;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\\n return _this;\\n }\\n\\n _createClass(SoundFileProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs) {\\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\\n\\n this.inputRingBuffer.push([input[0]]);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n var inputChannel = this.inputRingBufferArraySequence[0];\\n var position = inputChannel[inputChannel.length - 1] || 0;\\n this.port.postMessage({\\n name: 'position',\\n position: position\\n });\\n }\\n\\n return true;\\n }\\n }]);\\n\\n return SoundFileProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);\"","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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar AmplitudeProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\\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.numOutputChannels = options.outputChannelCount || 1;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.normalize = processorOptions.normalize || false;\\n _this.smoothing = processorOptions.smoothing || 0;\\n _this.bufferSize = processorOptions.bufferSize || 2048;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this.bufferSize);\\n });\\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 } else if (data.name === 'smoothing') {\\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\\n }\\n };\\n\\n return _this;\\n } // TO DO make this stereo / dependent on # of audio channels\\n\\n\\n _createClass(AmplitudeProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs, outputs) {\\n var input = inputs[0];\\n var output = outputs[0];\\n var smoothing = this.smoothing;\\n this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\\n } // pull 128 frames out of the ring buffer\\n // if the ring buffer does not have enough frames, the output will be silent\\n\\n\\n this.outputRingBuffer.pull(output);\\n return true;\\n }\\n }]);\\n\\n return AmplitudeProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);\"","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});","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});","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});","import audiocontext from './audiocontext.js';\n// Master contains the master sound output.\nclass Master {\n constructor() {\n this.input = audiocontext.createGain();\n this.output = audiocontext.createGain();\n\n //put a hard limiter on the output\n this.limiter = audiocontext.createDynamicsCompressor();\n this.limiter.threshold.value = -3;\n this.limiter.ratio.value = 20;\n this.limiter.knee.value = 1;\n\n this.audiocontext = audiocontext;\n\n this.output.disconnect();\n\n // connect input to limiter\n this.input.connect(this.limiter);\n\n // connect limiter to output\n this.limiter.connect(this.output);\n\n // meter is just for global Amplitude / FFT analysis\n this.meter = audiocontext.createGain();\n this.fftMeter = audiocontext.createGain();\n this.output.connect(this.meter);\n this.output.connect(this.fftMeter);\n\n // connect output to destination\n this.output.connect(this.audiocontext.destination);\n\n // an array of all sounds in the sketch\n this.soundArray = [];\n // an array of all musical parts in the sketch\n this.parts = [];\n\n // file extensions to search for\n this.extensions = [];\n }\n}\n\n// create a single instance of the p5Sound / master output for use within this sketch\nconst p5sound = new Master();\n\n/**\n * Returns a number representing the master amplitude (volume) for sound\n * in this sketch.\n *\n * @method getMasterVolume\n * @return {Number} Master amplitude (volume) for sound in this sketch.\n * Should be between 0.0 (silence) and 1.0.\n */\np5.prototype.getMasterVolume = function () {\n return p5sound.output.gain.value;\n};\n\n/**\n *

Scale the output of all sound in this sketch

\n * Scaled between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n *

How This Works: When you load the p5.sound module, it\n * creates a single instance of p5sound. All sound objects in this\n * module output to p5sound before reaching your computer's output.\n * So if you change the amplitude of p5sound, it impacts all of the\n * sound in this module.

\n *\n *

If no value is provided, returns a Web Audio API Gain Node

\n *\n * @method masterVolume\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\np5.prototype.masterVolume = function (vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = p5sound.output.gain.value;\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(p5sound.output.gain);\n } else {\n // return the Gain Node\n return p5sound.output.gain;\n }\n};\n\n/**\n * `p5.soundOut` is the p5.sound master output. It sends output to\n * the destination of this window's web audio context. It contains\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\n * and Gain Nodes for .input and .output.\n *\n * @property {Object} soundOut\n */\np5.prototype.soundOut = p5.soundOut = p5sound;\n\n// a silent connection to the DesinationNode\n// which will ensure that anything connected to it\n// will not be garbage collected\np5.soundOut._silentNode = p5sound.audiocontext.createGain();\np5.soundOut._silentNode.gain.value = 0;\np5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\n\nexport default p5sound;\n","import p5sound from './master';\nimport processorNames from './audioWorklet/processorNames';\n/**\n * @for p5\n */\n\n/**\n * Returns a number representing the sample rate, in samples per second,\n * of all sound objects in this audio context. It is determined by the\n * sampling rate of your operating system's sound card, and it is not\n * currently possile to change.\n * It is often 44100, or twice the range of human hearing.\n *\n * @method sampleRate\n * @return {Number} samplerate samples per second\n */\nfunction sampleRate() {\n return p5sound.audiocontext.sampleRate;\n}\n\n/**\n * Returns the closest MIDI note value for\n * a given frequency.\n *\n * @method freqToMidi\n * @param {Number} frequency A freqeuncy, for example, the \"A\"\n * above Middle C is 440Hz\n * @return {Number} MIDI note value\n */\nfunction freqToMidi(f) {\n var mathlog2 = Math.log(f / 440) / Math.log(2);\n var m = Math.round(12 * mathlog2) + 69;\n return m;\n}\n\n/**\n * Returns the frequency value of a MIDI note value.\n * General MIDI treats notes as integers where middle C\n * is 60, C# is 61, D is 62 etc. Useful for generating\n * musical frequencies with oscillators.\n *\n * @method midiToFreq\n * @param {Number} midiNote The number of a MIDI note\n * @return {Number} Frequency value of the given MIDI note\n * @example\n *
\n * let midiNotes = [60, 64, 67, 72];\n * let noteIndex = 0;\n * let midiVal, freq;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * osc = new p5.TriOsc();\n * env = new p5.Envelope();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 10, 20);\n * if (midiVal) {\n * text('MIDI: ' + midiVal, 10, 40);\n * text('Freq: ' + freq, 10, 60);\n * }\n * }\n *\n * function startSound() {\n * // see also: userStartAudio();\n * osc.start();\n *\n * midiVal = midiNotes[noteIndex % midiNotes.length];\n * freq = midiToFreq(midiVal);\n * osc.freq(freq);\n * env.ramp(osc, 0, 1.0, 0);\n *\n * noteIndex++;\n * }\n *
\n */\nfunction midiToFreq(m) {\n return 440 * Math.pow(2, (m - 69) / 12.0);\n}\n\n// This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\nfunction noteToFreq(note) {\n if (typeof note !== 'string') {\n return note;\n }\n var wholeNotes = { A: 21, B: 23, C: 24, D: 26, E: 28, F: 29, G: 31 };\n var value = wholeNotes[note[0].toUpperCase()];\n var octave = ~~note.slice(-1);\n value += 12 * (octave - 1);\n\n switch (note[1]) {\n case '#':\n value += 1;\n break;\n case 'b':\n value -= 1;\n break;\n default:\n break;\n }\n return midiToFreq(value);\n}\n\n/**\n * List the SoundFile formats that you will include. LoadSound\n * will search your directory for these extensions, and will pick\n * a format that is compatable with the client's web browser.\n * Here is a free online file\n * converter.\n *\n * @method soundFormats\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\n * @example\n *
\n * function preload() {\n * // set the global sound formats\n * soundFormats('mp3', 'ogg');\n *\n * // load either beatbox.mp3, or .ogg, depending on browser\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('sound loaded! tap to play', 10, 20, width - 20);\n * cnv.mousePressed(function() {\n * mySound.play();\n * });\n * }\n *
\n */\n\nfunction soundFormats() {\n // reset extensions array\n p5sound.extensions = [];\n // add extensions\n for (var i = 0; i < arguments.length; i++) {\n arguments[i] = arguments[i].toLowerCase();\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\n p5sound.extensions.push(arguments[i]);\n } else {\n throw arguments[i] + ' is not a valid sound format!';\n }\n }\n}\n\nfunction disposeSound() {\n for (var i = 0; i < p5sound.soundArray.length; i++) {\n p5sound.soundArray[i].dispose();\n }\n}\n\nfunction _checkFileFormats(paths) {\n var path;\n // if path is a single string, check to see if extension is provided\n if (typeof paths === 'string') {\n path = paths;\n // see if extension is provided\n var extTest = path.split('.').pop();\n // if an extension is provided...\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\n if (!p5.prototype.isFileSupported(extTest)) {\n var pathSplit = path.split('.');\n var pathCore = pathSplit[pathSplit.length - 1];\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n pathCore = '';\n if (pathSplit.length === 2) {\n pathCore += pathSplit[0];\n }\n for (let i = 1; i <= pathSplit.length - 2; i++) {\n var p = pathSplit[i];\n pathCore += '.' + p;\n }\n path = pathCore += '.';\n path = path += extension;\n break;\n }\n }\n }\n }\n // if no extension is provided...\n else {\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n path = path + '.' + extension;\n break;\n }\n }\n }\n } // end 'if string'\n\n // path can either be a single string, or an array\n else if (typeof paths === 'object') {\n for (var i = 0; i < paths.length; i++) {\n var extension = paths[i].split('.').pop();\n var supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n // console.log('.'+extension + ' is ' + supported +\n // ' supported by your browser.');\n path = paths[i];\n break;\n }\n }\n }\n return path;\n}\n\n/**\n * Used by Osc and Envelope to chain signal math\n */\nfunction _mathChain(o, math, thisChain, nextChain, type) {\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n o.mathOps[i].dispose();\n thisChain = i;\n if (thisChain < o.mathOps.length - 1) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n o.mathOps[thisChain - 1].disconnect();\n o.mathOps[thisChain - 1].connect(math);\n math.connect(nextChain);\n o.mathOps[thisChain] = math;\n return o;\n}\n\n// helper methods to convert audio file as .wav format,\n// will use as saving .wav file and saving blob object\n// Thank you to Matt Diamond's RecorderJS (MIT License)\n// https://github.com/mattdiamond/Recorderjs\nfunction convertToWav(audioBuffer) {\n var leftChannel, rightChannel;\n leftChannel = audioBuffer.getChannelData(0);\n\n // handle mono files\n if (audioBuffer.numberOfChannels > 1) {\n rightChannel = audioBuffer.getChannelData(1);\n } else {\n rightChannel = leftChannel;\n }\n\n var interleaved = interleave(leftChannel, rightChannel);\n\n // create the buffer and view to create the .WAV file\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\n var view = new window.DataView(buffer);\n\n // write the WAV container,\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\n\n // RIFF chunk descriptor\n writeUTFBytes(view, 0, 'RIFF');\n view.setUint32(4, 36 + interleaved.length * 2, true);\n writeUTFBytes(view, 8, 'WAVE');\n // FMT sub-chunk\n writeUTFBytes(view, 12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n // stereo (2 channels)\n view.setUint16(22, 2, true);\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\n view.setUint16(32, 4, true);\n view.setUint16(34, 16, true);\n // data sub-chunk\n writeUTFBytes(view, 36, 'data');\n view.setUint32(40, interleaved.length * 2, true);\n\n // write the PCM samples\n var lng = interleaved.length;\n var index = 44;\n var volume = 1;\n for (var i = 0; i < lng; i++) {\n view.setInt16(index, interleaved[i] * (0x7fff * volume), true);\n index += 2;\n }\n\n return view;\n}\n\n// helper methods to save waves\nfunction interleave(leftChannel, rightChannel) {\n var length = leftChannel.length + rightChannel.length;\n var result = new Float32Array(length);\n\n var inputIndex = 0;\n\n for (var index = 0; index < length; ) {\n result[index++] = leftChannel[inputIndex];\n result[index++] = rightChannel[inputIndex];\n inputIndex++;\n }\n return result;\n}\n\nfunction writeUTFBytes(view, offset, string) {\n var lng = string.length;\n for (var i = 0; i < lng; i++) {\n view.setUint8(offset + i, string.charCodeAt(i));\n }\n}\n\nfunction safeBufferSize(idealBufferSize) {\n let bufferSize = idealBufferSize;\n\n // if the AudioWorkletNode is actually a ScriptProcessorNode created via polyfill,\n // make sure that our chosen buffer size isn't smaller than the buffer size automatically\n // selected by the polyfill\n // reference: https://github.com/GoogleChromeLabs/audioworklet-polyfill/issues/13#issuecomment-425014930\n let tempAudioWorkletNode = new AudioWorkletNode(\n p5sound.audiocontext,\n processorNames.soundFileProcessor\n );\n if (tempAudioWorkletNode instanceof ScriptProcessorNode) {\n bufferSize = tempAudioWorkletNode.bufferSize;\n }\n tempAudioWorkletNode.disconnect();\n tempAudioWorkletNode = null;\n\n return bufferSize;\n}\n\n/**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device.\n * For uploading audio to a server, use\n * `p5.SoundFile.saveBlob`.\n *\n * @for p5\n * @method saveSound\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\n * @param {String} fileName name of the resulting .wav file.\n */\n// add to p5.prototype as this is used by the p5 `save()` method.\nfunction saveSound(soundFile, fileName) {\n const dataView = convertToWav(soundFile.buffer);\n p5.prototype.writeFile([dataView], fileName, 'wav');\n}\n\nexport {\n sampleRate,\n freqToMidi,\n midiToFreq,\n noteToFreq,\n soundFormats,\n disposeSound,\n _checkFileFormats,\n _mathChain,\n convertToWav,\n interleave,\n writeUTFBytes,\n safeBufferSize,\n saveSound,\n};\n","/*\n Helper function to generate an error\n with a custom stack trace that points to the sketch\n and removes other parts of the stack trace.\n\n @private\n @class customError\n @constructor\n @param {String} name custom error name\n @param {String} errorTrace custom error trace\n @param {String} failedPath path to the file that failed to load\n @property {String} name custom error name\n @property {String} message custom error message\n @property {String} stack trace the error back to a line in the user's sketch.\n Note: this edits out stack trace within p5.js and p5.sound.\n @property {String} originalStack unedited, original stack trace\n @property {String} failedPath path to the file that failed to load\n @return {Error} returns a custom Error object\n */\nvar CustomError = function (name, errorTrace, failedPath) {\n var err = new Error();\n var tempStack, splitStack;\n\n err.name = name;\n err.originalStack = err.stack + errorTrace;\n tempStack = err.stack + errorTrace;\n err.failedPath = failedPath;\n\n // only print the part of the stack trace that refers to the user code:\n splitStack = tempStack.split('\\n').filter(function (ln) {\n return !ln.match(/(p5.|native code|globalInit)/g);\n });\n err.stack = splitStack.join('\\n');\n\n return err; // TODO: is this really a constructor?\n};\nexport default CustomError;\n","import p5sound from '../master.js';\nconst moduleSources = [\n require('raw-loader!./recorderProcessor').default,\n require('raw-loader!./soundFileProcessor').default,\n require('raw-loader!./amplitudeProcessor').default,\n];\nconst ac = p5sound.audiocontext;\n\nfunction loadAudioWorkletModules() {\n return Promise.all(\n moduleSources.map(function (moduleSrc) {\n const blob = new Blob([moduleSrc], { type: 'application/javascript' });\n const objectURL = URL.createObjectURL(blob);\n return ac.audioWorklet.addModule(objectURL);\n })\n );\n}\n\np5.prototype.registerMethod('init', function () {\n // ensure that a preload function exists so that p5 will wait for preloads to finish\n if (!this.preload && !window.preload) {\n this.preload = function () {};\n }\n\n // use p5's preload system to load necessary AudioWorklet modules before setup()\n this._incrementPreload();\n const onWorkletModulesLoad = function () {\n this._decrementPreload();\n }.bind(this);\n loadAudioWorkletModules().then(onWorkletModulesLoad);\n});\n","import p5sound from './master';\nvar ac = p5sound.audiocontext;\nvar panner;\n// Stereo panner\n// if there is a stereo panner node use it\nif (typeof ac.createStereoPanner !== 'undefined') {\n class Panner {\n constructor(input, output) {\n this.stereoPanner = this.input = ac.createStereoPanner();\n input.connect(this.stereoPanner);\n this.stereoPanner.connect(output);\n }\n\n pan(val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\n }\n\n //not implemented because stereopanner\n //node does not require this and will automatically\n //convert single channel or multichannel to stereo.\n //tested with single and stereo, not with (>2) multichannel\n inputChannels() {}\n\n connect(obj) {\n this.stereoPanner.connect(obj);\n }\n\n disconnect() {\n if (this.stereoPanner) {\n this.stereoPanner.disconnect();\n }\n }\n }\n\n panner = Panner;\n} else {\n // if there is no createStereoPanner object\n // such as in safari 7.1.7 at the time of writing this\n // use this method to create the effect\n class Panner {\n constructor(input, output, numInputChannels) {\n this.input = ac.createGain();\n input.connect(this.input);\n\n this.left = ac.createGain();\n this.right = ac.createGain();\n this.left.channelInterpretation = 'discrete';\n this.right.channelInterpretation = 'discrete';\n\n // if input is stereo\n if (numInputChannels > 1) {\n this.splitter = ac.createChannelSplitter(2);\n this.input.connect(this.splitter);\n\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n } else {\n this.input.connect(this.left);\n this.input.connect(this.right);\n }\n\n this.output = ac.createChannelMerger(2);\n this.left.connect(this.output, 0, 1);\n this.right.connect(this.output, 0, 0);\n this.output.connect(output);\n }\n\n // -1 is left, +1 is right\n pan(val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n var v = (val + 1) / 2;\n var rightVal = Math.cos((v * Math.PI) / 2);\n var leftVal = Math.sin((v * Math.PI) / 2);\n this.left.gain.linearRampToValueAtTime(leftVal, t);\n this.right.gain.linearRampToValueAtTime(rightVal, t);\n }\n\n inputChannels(numChannels) {\n if (numChannels === 1) {\n this.input.disconnect();\n this.input.connect(this.left);\n this.input.connect(this.right);\n } else if (numChannels === 2) {\n if (typeof this.splitter === 'undefined') {\n this.splitter = ac.createChannelSplitter(2);\n }\n this.input.disconnect();\n this.input.connect(this.splitter);\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n }\n }\n\n connect(obj) {\n this.output.connect(obj);\n }\n\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n }\n panner = Panner;\n}\n\nexport default panner;\n","import CustomError from './errorHandler';\nimport p5sound from './master';\nimport { midiToFreq, convertToWav, safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\nimport Panner from './panner';\n\nconst ac = p5sound.audiocontext;\n\nvar _createCounterBuffer = function (buffer) {\n const len = buffer.length;\n const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate);\n const arrayBuffer = audioBuf.getChannelData(0);\n for (var index = 0; index < len; index++) {\n arrayBuffer[index] = index;\n }\n return audioBuf;\n};\n\n// process peaks\nclass Peak {\n constructor(amp, i) {\n this.sampleIndex = i;\n this.amplitude = amp;\n this.tempos = [];\n this.intervals = [];\n }\n}\n\n// 1. for processPeaks() Function to identify peaks above a threshold\n// returns an array of peak indexes as frames (samples) of the original soundfile\nfunction getPeaksAtThreshold(data, threshold) {\n var peaksObj = {};\n var length = data.length;\n\n for (var i = 0; i < length; i++) {\n if (data[i] > threshold) {\n var amp = data[i];\n var peak = new Peak(amp, i);\n peaksObj[i] = peak;\n // Skip forward ~ 1/8s to get past this peak.\n i += 6000;\n }\n i++;\n }\n return peaksObj;\n}\n\n// 2. for processPeaks()\nfunction countIntervalsBetweenNearbyPeaks(peaksObj) {\n var intervalCounts = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n for (var index = 0; index < peaksArray.length; index++) {\n // find intervals in comparison to nearby peaks\n for (var i = 0; i < 10; i++) {\n var startPeak = peaksObj[peaksArray[index]];\n var endPeak = peaksObj[peaksArray[index + i]];\n\n if (startPeak && endPeak) {\n var startPos = startPeak.sampleIndex;\n var endPos = endPeak.sampleIndex;\n var interval = endPos - startPos;\n\n // add a sample interval to the startPeak in the allPeaks array\n if (interval > 0) {\n startPeak.intervals.push(interval);\n }\n\n // tally the intervals and return interval counts\n var foundInterval = intervalCounts.some(function (intervalCount) {\n if (intervalCount.interval === interval) {\n intervalCount.count++;\n return intervalCount;\n }\n });\n\n // store with JSON like formatting\n if (!foundInterval) {\n intervalCounts.push({\n interval: interval,\n count: 1,\n });\n }\n }\n }\n }\n\n return intervalCounts;\n}\n\n// 3. for processPeaks --> find tempo\nfunction groupNeighborsByTempo(intervalCounts, sampleRate) {\n var tempoCounts = [];\n\n intervalCounts.forEach(function (intervalCount) {\n try {\n // Convert an interval to tempo\n var theoreticalTempo = Math.abs(\n 60 / (intervalCount.interval / sampleRate)\n );\n\n theoreticalTempo = mapTempo(theoreticalTempo);\n\n var foundTempo = tempoCounts.some(function (tempoCount) {\n if (tempoCount.tempo === theoreticalTempo)\n return (tempoCount.count += intervalCount.count);\n });\n if (!foundTempo) {\n if (isNaN(theoreticalTempo)) {\n return;\n }\n tempoCounts.push({\n tempo: Math.round(theoreticalTempo),\n count: intervalCount.count,\n });\n }\n } catch (e) {\n throw e;\n }\n });\n\n return tempoCounts;\n}\n\n// 4. for processPeaks - get peaks at top tempo\nfunction getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\n var peaksAtTopTempo = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n // TO DO: filter out peaks that have the tempo and return\n for (var i = 0; i < peaksArray.length; i++) {\n var key = peaksArray[i];\n var peak = peaksObj[key];\n\n for (var j = 0; j < peak.intervals.length; j++) {\n var intervalBPM = Math.round(\n Math.abs(60 / (peak.intervals[j] / sampleRate))\n );\n\n intervalBPM = mapTempo(intervalBPM);\n\n if (Math.abs(intervalBPM - tempo) < bpmVariance) {\n // convert sampleIndex to seconds\n peaksAtTopTempo.push(peak.sampleIndex / sampleRate);\n }\n }\n }\n\n // filter out peaks that are very close to each other\n peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) {\n var dif = arr[index + 1] - peakTime;\n if (dif > 0.01) {\n return true;\n }\n });\n\n return peaksAtTopTempo;\n}\n\n// helper function for processPeaks\nfunction mapTempo(theoreticalTempo) {\n // these scenarios create infinite while loop\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) {\n return;\n }\n\n // Adjust the tempo to fit within the 90-180 BPM range\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\n\n return theoreticalTempo;\n}\n\n/*** SCHEDULE EVENTS ***/\n\n// Cue inspired by JavaScript setTimeout, and the\n// Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\nclass Cue {\n constructor(callback, time, id, val) {\n this.callback = callback;\n this.time = time;\n this.id = id;\n this.val = val;\n }\n}\n\n// event handler to remove references to the bufferSourceNode when it is done playing\nfunction _clearOnEnd(e) {\n const thisBufferSourceNode = e.target;\n const soundFile = this;\n\n // delete this.bufferSourceNode from the sources array when it is done playing:\n thisBufferSourceNode._playing = false;\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\n\n // call the onended callback\n soundFile._onended(soundFile);\n\n // delete bufferSourceNode(s) in soundFile.bufferSourceNodes\n // iterate in reverse order because the index changes by splice\n soundFile.bufferSourceNodes\n .map((_, i) => i)\n .reverse()\n .forEach(function (i) {\n const n = soundFile.bufferSourceNodes[i];\n\n if (n._playing === false) {\n soundFile.bufferSourceNodes.splice(i, 1);\n }\n });\n\n if (soundFile.bufferSourceNodes.length === 0) {\n soundFile._playing = false;\n }\n}\n\n/**\n *

SoundFile object with a path to a file.

\n *\n *

The p5.SoundFile may not be available immediately because\n * it loads the file information asynchronously.

\n *\n *

To do something with the sound as soon as it loads\n * pass the name of a function as the second parameter.

\n *\n *

Only one file path is required. However, audio file formats\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\n * web browsers. If you want to ensure compatability, instead of a single\n * file path, you may include an Array of filepaths, and the browser will\n * choose a format that works.

\n *\n * @class p5.SoundFile\n * @constructor\n * @param {String|Array} path path to a sound file (String). Optionally,\n * you may include multiple file formats in\n * an array. Alternately, accepts an object\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if file fails to\n * load. This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\n * is loading. That function will\n * receive progress of the request to\n * load the sound file\n * (between 0 and 1) as its first\n * parameter. This progress\n * does not account for the additional\n * time needed to decode the audio data.\n *\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\nclass SoundFile {\n constructor(paths, onload, onerror, whileLoading) {\n if (typeof paths !== 'undefined') {\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\n var path = p5.prototype._checkFileFormats(paths);\n this.url = path;\n } else if (typeof paths === 'object') {\n if (\n !(window.File && window.FileReader && window.FileList && window.Blob)\n ) {\n // The File API isn't supported in this browser\n throw 'Unable to load file because the File API is not supported';\n }\n }\n\n // if type is a p5.File...get the actual file\n if (paths.file) {\n paths = paths.file;\n }\n\n this.file = paths;\n }\n\n // private _onended callback, set by the method: onended(callback)\n this._onended = function () {};\n\n this._looping = false;\n this._playing = false;\n this._paused = false;\n this._pauseTime = 0;\n\n // cues for scheduling events with addCue() removeCue()\n this._cues = [];\n this._cueIDCounter = 0;\n\n // position of the most recently played sample\n this._lastPos = 0;\n this._counterNode = null;\n this._workletNode = null;\n\n // array of sources so that they can all be stopped!\n this.bufferSourceNodes = [];\n\n // current source\n this.bufferSourceNode = null;\n\n this.buffer = null;\n this.playbackRate = 1;\n\n this.input = p5sound.audiocontext.createGain();\n this.output = p5sound.audiocontext.createGain();\n\n this.reversed = false;\n\n // start and end of playback / loop\n this.startTime = 0;\n this.endTime = null;\n this.pauseTime = 0;\n\n // \"restart\" would stop playback before retriggering\n this.mode = 'sustain';\n\n // time that playback was started, in millis\n this.startMillis = null;\n\n // stereo panning\n this.panPosition = 0.0;\n this.panner = new Panner(this.output, p5sound.input, 2);\n\n // it is possible to instantiate a soundfile with no path\n if (this.url || this.file) {\n this.load(onload, onerror);\n }\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n\n if (typeof whileLoading === 'function') {\n this._whileLoading = whileLoading;\n } else {\n this._whileLoading = function () {};\n }\n\n this._clearOnEnd = _clearOnEnd.bind(this);\n\n // same as setVolume, to match Processing Sound\n this.amp = this.setVolume;\n\n // these are the same thing\n this.fade = this.setVolume;\n }\n\n /**\n * This is a helper function that the p5.SoundFile calls to load\n * itself. Accepts a callback (the name of another function)\n * as an optional parameter.\n *\n * @private\n * @for p5.SoundFile\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is an error\n */\n load(callback, errorCallback) {\n var self = this;\n var errorTrace = new Error().stack;\n\n if (this.url !== undefined && this.url !== '') {\n var request = new XMLHttpRequest();\n request.addEventListener(\n 'progress',\n function (evt) {\n self._updateProgress(evt);\n },\n false\n );\n request.open('GET', this.url, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on sucess loading file:\n if (!self.panner) return;\n ac.decodeAudioData(\n request.response,\n // success decoding buffer:\n function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n if (!self.panner) return;\n var err = new CustomError(\n 'decodeAudioData',\n errorTrace,\n self.url\n );\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n if (!self.panner) return;\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n };\n\n request.send();\n } else if (this.file !== undefined) {\n var reader = new FileReader();\n reader.onload = function () {\n if (!self.panner) return;\n ac.decodeAudioData(reader.result, function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n });\n };\n reader.onerror = function (e) {\n if (!self.panner) return;\n if (onerror) {\n onerror(e);\n }\n };\n reader.readAsArrayBuffer(this.file);\n }\n }\n\n // TO DO: use this method to create a loading bar that shows progress during file upload/decode.\n _updateProgress(evt) {\n if (evt.lengthComputable) {\n var percentComplete = (evt.loaded / evt.total) * 0.99;\n this._whileLoading(percentComplete, evt);\n // ...\n } else {\n // Unable to compute progress information since the total size is unknown\n this._whileLoading('size unknown');\n }\n }\n\n /**\n * Returns true if the sound file finished loading successfully.\n *\n * @method isLoaded\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isLoaded() {\n if (this.buffer) {\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Play the p5.SoundFile\n *\n * @method play\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) amplitude (volume)\n * of playback\n * @param {Number} [cueStart] (optional) cue start time in seconds\n * @param {Number} [duration] (optional) duration of playback in seconds\n */\n play(startTime, rate, amp, _cueStart, duration) {\n if (!this.output) {\n console.warn('SoundFile.play() called after dispose');\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var cueStart, cueEnd;\n var time = startTime || 0;\n if (time < 0) {\n time = 0;\n }\n\n time = time + now;\n\n if (typeof rate !== 'undefined') {\n this.rate(rate);\n }\n\n if (typeof amp !== 'undefined') {\n this.setVolume(amp);\n }\n\n // TO DO: if already playing, create array of buffers for easy stop()\n if (this.buffer) {\n // reset the pause time (if it was paused)\n this._pauseTime = 0;\n\n // handle restart playmode\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\n this.bufferSourceNode.stop(time);\n this._counterNode.stop(time);\n }\n\n //dont create another instance if already playing\n if (this.mode === 'untildone' && this.isPlaying()) {\n return;\n }\n // make a new source and counter. They are automatically assigned playbackRate and buffer\n this.bufferSourceNode = this._initSourceNode();\n\n // garbage collect counterNode and create a new one\n delete this._counterNode;\n this._counterNode = this._initCounterNode();\n\n if (_cueStart) {\n if (_cueStart >= 0 && _cueStart < this.buffer.duration) {\n // this.startTime = cueStart;\n cueStart = _cueStart;\n } else {\n throw 'start time out of range';\n }\n } else {\n cueStart = 0;\n }\n\n if (duration) {\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\n duration =\n duration <= this.buffer.duration - cueStart\n ? duration\n : this.buffer.duration;\n }\n\n // if it was paused, play at the pause position\n if (this._paused) {\n this.bufferSourceNode.start(time, this.pauseTime, duration);\n this._counterNode.start(time, this.pauseTime, duration);\n } else {\n this.bufferSourceNode.start(time, cueStart, duration);\n this._counterNode.start(time, cueStart, duration);\n }\n\n this._playing = true;\n this._paused = false;\n\n // add source to sources array, which is used in stopAll()\n this.bufferSourceNodes.push(this.bufferSourceNode);\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\n\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\n }\n // If soundFile hasn't loaded the buffer yet, throw an error\n else {\n throw 'not ready to play file, buffer has yet to load. Try preload()';\n }\n\n // if looping, will restart at original time\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n\n if (this._looping === true) {\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\n this.bufferSourceNode.loopStart = cueStart;\n this.bufferSourceNode.loopEnd = cueEnd;\n this._counterNode.loopStart = cueStart;\n this._counterNode.loopEnd = cueEnd;\n }\n }\n\n /**\n * p5.SoundFile has two play modes: restart and\n * sustain. Play Mode determines what happens to a\n * p5.SoundFile if it is triggered while in the middle of playback.\n * In sustain mode, playback will continue simultaneous to the\n * new playback. In restart mode, play() will stop playback\n * and start over. With untilDone, a sound will play only if it's\n * not already playing. Sustain is the default mode.\n *\n * @method playMode\n * @for p5.SoundFile\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\n * @example\n *
\n * let mySound;\n * function preload(){\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * noFill();\n * rect(0, height/2, width - 1, height/2 - 1);\n * rect(0, 0, width - 1, height/2);\n * textAlign(CENTER, CENTER);\n * fill(20);\n * text('restart', width/2, 1 * height/4);\n * text('sustain', width/2, 3 * height/4);\n * }\n * function canvasPressed() {\n * if (mouseX < height/2) {\n * mySound.playMode('restart');\n * } else {\n * mySound.playMode('sustain');\n * }\n * mySound.play();\n * }\n *\n *
\n */\n playMode(str) {\n var s = str.toLowerCase();\n\n // if restart, stop all other sounds from playing\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNodes[i].stop(now);\n }\n }\n\n // set play mode to effect future playback\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\n this.mode = s;\n } else {\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\n }\n }\n\n /**\n * Pauses a file that is currently playing. If the file is not\n * playing, then nothing will happen.\n *\n * After pausing, .play() will resume from the paused\n * position.\n * If p5.SoundFile had been set to loop before it was paused,\n * it will continue to loop after it is unpaused with .play().\n *\n * @method pause\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @example\n *
\n * let soundFile;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\n pause(startTime) {\n var now = p5sound.audiocontext.currentTime;\n var time = startTime || 0;\n var pTime = time + now;\n\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\n this._paused = true;\n this._playing = false;\n\n this.pauseTime = this.currentTime();\n this.bufferSourceNode.stop(pTime);\n this._counterNode.stop(pTime);\n\n this._pauseTime = this.currentTime();\n // TO DO: make sure play() still starts from orig start position\n } else {\n this._pauseTime = 0;\n }\n }\n\n /**\n * Loop the p5.SoundFile. Accepts optional parameters to set the\n * playback rate, playback volume, loopStart, loopEnd.\n *\n * @method loop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) playback volume\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\n * @param {Number} [duration] (optional) loop duration in seconds\n * @example\n *
\n * let soundFile;\n * let loopStart = 0.5;\n * let loopDuration = 0.2;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\n loop(startTime, rate, amp, loopStart, duration) {\n this._looping = true;\n this.play(startTime, rate, amp, loopStart, duration);\n }\n\n /**\n * Set a p5.SoundFile's looping flag to true or false. If the sound\n * is currently playing, this change will take effect when it\n * reaches the end of the current playback.\n *\n * @method setLoop\n * @for p5.SoundFile\n * @param {Boolean} Boolean set looping to true or false\n */\n setLoop(bool) {\n if (bool === true) {\n this._looping = true;\n } else if (bool === false) {\n this._looping = false;\n } else {\n throw 'Error: setLoop accepts either true or false';\n }\n if (this.bufferSourceNode) {\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n }\n }\n\n /**\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\n *\n * @method isLooping\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isLooping() {\n if (!this.bufferSourceNode) {\n return false;\n }\n if (this._looping === true && this.isPlaying() === true) {\n return true;\n }\n return false;\n }\n\n /**\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\n * paused or stopped).\n *\n * @method isPlaying\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isPlaying() {\n return this._playing;\n }\n\n /**\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\n * playing or stopped).\n *\n * @method isPaused\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isPaused() {\n return this._paused;\n }\n\n /**\n * Stop soundfile playback.\n *\n * @method stop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * in seconds from now\n */\n stop(timeFromNow) {\n var time = timeFromNow || 0;\n\n if (this.mode === 'sustain' || this.mode === 'untildone') {\n this.stopAll(time);\n this._playing = false;\n this.pauseTime = 0;\n this._paused = false;\n } else if (this.buffer && this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n this.pauseTime = 0;\n this.bufferSourceNode.stop(now + t);\n this._counterNode.stop(now + t);\n this._playing = false;\n this._paused = false;\n }\n }\n\n /**\n * Stop playback on all of this soundfile's sources.\n * @private\n */\n stopAll(_time) {\n var now = p5sound.audiocontext.currentTime;\n var time = _time || 0;\n if (this.buffer && this.bufferSourceNode) {\n for (var i in this.bufferSourceNodes) {\n const bufferSourceNode = this.bufferSourceNodes[i];\n if (bufferSourceNode) {\n try {\n bufferSourceNode.stop(now + time);\n } catch (e) {\n // this was throwing errors only on Safari\n }\n }\n }\n this._counterNode.stop(now + time);\n this._onended(this);\n }\n }\n\n getVolume() {\n return this.output.gain.value;\n }\n\n /**\n * Set the stereo panning of a p5.sound object to\n * a floating point number between -1.0 (left) and 1.0 (right).\n * Default is 0.0 (center).\n *\n * @method pan\n * @for p5.SoundFile\n * @param {Number} [panValue] Set the stereo panner\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @example\n *
\n * let ballX = 0;\n * let soundFile;\n *\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/beatbox.mp3');\n * }\n *\n * function draw() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * ballX = constrain(mouseX, 0, width);\n * ellipse(ballX, height/2, 20, 20);\n * }\n *\n * function canvasPressed(){\n * // map the ball's x location to a panning degree\n * // between -1.0 (left) and 1.0 (right)\n * let panning = map(ballX, 0., width,-1.0, 1.0);\n * soundFile.pan(panning);\n * soundFile.play();\n * }\n *
\n */\n pan(pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n }\n\n /**\n * Returns the current stereo pan position (-1.0 to 1.0)\n *\n * @method getPan\n * @for p5.SoundFile\n * @return {Number} Returns the stereo pan setting of the Oscillator\n * as a number between -1.0 (left) and 1.0 (right).\n * 0.0 is center and default.\n */\n getPan() {\n return this.panPosition;\n }\n\n /**\n * Set the playback rate of a sound file. Will change the speed and the pitch.\n * Values less than zero will reverse the audio buffer.\n *\n * @method rate\n * @for p5.SoundFile\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\n * .5 is half-speed, 2.0 is twice as fast.\n * Values less than zero play backwards.\n * @example\n *
\n * let mySound;\n *\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * }\n * function canvasPressed() {\n * mySound.loop();\n * }\n * function mouseReleased() {\n * mySound.pause();\n * }\n * function draw() {\n * background(220);\n *\n * // Set the rate to a range between 0.1 and 4\n * // Changing the rate also alters the pitch\n * let playbackRate = map(mouseY, 0.1, height, 2, 0);\n * playbackRate = constrain(playbackRate, 0.01, 4);\n * mySound.rate(playbackRate);\n *\n * line(0, mouseY, width, mouseY);\n * text('rate: ' + round(playbackRate * 100) + '%', 10, 20);\n * }\n *\n * \n *
\n *\n */\n rate(playbackRate) {\n var reverse = false;\n if (typeof playbackRate === 'undefined') {\n return this.playbackRate;\n }\n\n this.playbackRate = playbackRate;\n\n if (playbackRate === 0) {\n playbackRate = 0.0000000000001;\n } else if (playbackRate < 0 && !this.reversed) {\n playbackRate = Math.abs(playbackRate);\n reverse = true;\n } else if (playbackRate > 0 && this.reversed) {\n reverse = true;\n }\n\n if (this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n this._counterNode.playbackRate.cancelScheduledValues(now);\n this._counterNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n }\n\n if (reverse) {\n this.reverseBuffer();\n }\n return this.playbackRate;\n }\n\n // TO DO: document this\n setPitch(num) {\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\n this.rate(newPlaybackRate);\n }\n\n getPlaybackRate() {\n return this.playbackRate;\n }\n\n /**\n * Multiply the output volume (amplitude) of a sound file\n * between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n * @method setVolume\n * @for p5.SoundFile\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\n setVolume(vol, _rampTime, _tFromNow) {\n if (typeof vol === 'number') {\n var rampTime = _rampTime || 0;\n var tFromNow = _tFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now + tFromNow);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n }\n /**\n * Returns the duration of a sound file in seconds.\n *\n * @method duration\n * @for p5.SoundFile\n * @return {Number} The duration of the soundFile in seconds.\n */\n duration() {\n // Return Duration\n if (this.buffer) {\n return this.buffer.duration;\n } else {\n return 0;\n }\n }\n\n /**\n * Return the current position of the p5.SoundFile playhead, in seconds.\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\n * has been called, currentTime will count backwards.\n *\n * @method currentTime\n * @for p5.SoundFile\n * @return {Number} currentTime of the soundFile in seconds.\n */\n currentTime() {\n return this.reversed\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\n : this._lastPos / ac.sampleRate;\n }\n\n /**\n * Move the playhead of a soundfile that is currently playing to a\n * new position and a new duration, in seconds.\n * If none are given, will reset the file to play entire duration\n * from start to finish. To set the position of a soundfile that is\n * not currently playing, use the `play` or `loop` methods.\n *\n * @method jump\n * @for p5.SoundFile\n * @param {Number} cueTime cueTime of the soundFile in seconds.\n * @param {Number} duration duration in seconds.\n */\n jump(cueTime, duration) {\n if (cueTime < 0 || cueTime > this.buffer.duration) {\n throw 'jump time out of range';\n }\n if (duration > this.buffer.duration - cueTime) {\n throw 'end time out of range';\n }\n\n var cTime = cueTime || 0;\n var dur = duration || undefined;\n if (this.isPlaying()) {\n this.stop(0);\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\n }\n }\n\n /**\n * Return the number of channels in a sound file.\n * For example, Mono = 1, Stereo = 2.\n *\n * @method channels\n * @for p5.SoundFile\n * @return {Number} [channels]\n */\n channels() {\n return this.buffer.numberOfChannels;\n }\n\n /**\n * Return the sample rate of the sound file.\n *\n * @method sampleRate\n * @for p5.SoundFile\n * @return {Number} [sampleRate]\n */\n sampleRate() {\n return this.buffer.sampleRate;\n }\n\n /**\n * Return the number of samples in a sound file.\n * Equal to sampleRate * duration.\n *\n * @method frames\n * @for p5.SoundFile\n * @return {Number} [sampleCount]\n */\n frames() {\n return this.buffer.length;\n }\n\n /**\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\n * used to draw a static waveform. Scans through the p5.SoundFile's\n * audio buffer to find the greatest amplitudes. Accepts one\n * parameter, 'length', which determines size of the array.\n * Larger arrays result in more precise waveform visualizations.\n *\n * Inspired by Wavesurfer.js.\n *\n * @method getPeaks\n * @for p5.SoundFile\n * @params {Number} [length] length is the size of the returned array.\n * Larger length results in more precision.\n * Defaults to 5*width of the browser window.\n * @returns {Float32Array} Array of peaks.\n */\n getPeaks(length) {\n if (this.buffer) {\n // set length to window's width if no length is provided\n if (!length) {\n length = window.width * 5;\n }\n if (this.buffer) {\n var buffer = this.buffer;\n var sampleSize = buffer.length / length;\n var sampleStep = ~~(sampleSize / 10) || 1;\n var channels = buffer.numberOfChannels;\n var peaks = new Float32Array(Math.round(length));\n\n for (var c = 0; c < channels; c++) {\n var chan = buffer.getChannelData(c);\n for (var i = 0; i < length; i++) {\n var start = ~~(i * sampleSize);\n var end = ~~(start + sampleSize);\n var max = 0;\n for (var j = start; j < end; j += sampleStep) {\n var value = chan[j];\n if (value > max) {\n max = value;\n // faster than Math.abs\n } else if (-value > max) {\n max = value;\n }\n }\n if (c === 0 || Math.abs(max) > peaks[i]) {\n peaks[i] = max;\n }\n }\n }\n\n return peaks;\n }\n } else {\n throw 'Cannot load peaks yet, buffer is not loaded';\n }\n }\n\n /**\n * Reverses the p5.SoundFile's buffer source.\n * Playback must be handled separately (see example).\n *\n * @method reverseBuffer\n * @for p5.SoundFile\n * @example\n *
\n * let drum;\n * function preload() {\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function canvasPressed() {\n * drum.stop();\n * drum.reverseBuffer();\n * drum.play();\n * }\n * \n *
\n */\n reverseBuffer() {\n if (this.buffer) {\n var currentPos = this._lastPos / ac.sampleRate;\n var curVol = this.getVolume();\n this.setVolume(0, 0.001);\n\n const numChannels = this.buffer.numberOfChannels;\n for (var i = 0; i < numChannels; i++) {\n this.buffer.getChannelData(i).reverse();\n }\n // set reversed flag\n this.reversed = !this.reversed;\n\n if (this.isPlaying() && currentPos) {\n this.jump(this.duration() - currentPos);\n }\n this.setVolume(curVol, 0.001);\n } else {\n throw 'SoundFile is not done loading';\n }\n }\n\n /**\n * Schedule an event to be called when the soundfile\n * reaches the end of a buffer. If the soundfile is\n * playing through once, this will be called when it\n * ends. If it is looping, it will be called when\n * stop is called.\n *\n * @method onended\n * @for p5.SoundFile\n * @param {Function} callback function to call when the\n * soundfile has ended.\n */\n onended(callback) {\n this._onended = callback;\n return this;\n }\n\n add() {\n // TO DO\n }\n\n dispose() {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference to soundfile\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop(now);\n if (this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n if (this.bufferSourceNodes[i] !== null) {\n this.bufferSourceNodes[i].disconnect();\n try {\n this.bufferSourceNodes[i].stop(now);\n } catch (e) {\n console.warn('no buffer source node to dispose');\n }\n this.bufferSourceNodes[i] = null;\n }\n }\n if (this.isPlaying()) {\n try {\n this._counterNode.stop(now);\n } catch (e) {\n console.log(e);\n }\n this._counterNode = null;\n }\n }\n if (this.output) {\n this.output.disconnect();\n this.output = null;\n }\n if (this.panner) {\n this.panner.disconnect();\n this.panner = null;\n }\n }\n\n /**\n * Connects the output of a p5sound object to input of another\n * p5.sound object. For example, you may connect a p5.SoundFile to an\n * FFT or an Effect. If no parameter is given, it will connect to\n * the master output. Most p5sound objects connect to the master\n * output when they are created.\n *\n * @method connect\n * @for p5.SoundFile\n * @param {Object} [object] Audio object that accepts an input\n */\n connect(unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else {\n if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n } else {\n this.panner.connect(unit);\n }\n }\n }\n\n /**\n * Disconnects the output of this p5sound object.\n *\n * @method disconnect\n * @for p5.SoundFile\n */\n disconnect() {\n if (this.panner) {\n this.panner.disconnect();\n }\n }\n\n /**\n */\n getLevel() {\n console.warn(\n 'p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'\n );\n }\n\n /**\n * Reset the source for this SoundFile to a\n * new path (URL).\n *\n * @method setPath\n * @for p5.SoundFile\n * @param {String} path path to audio file\n * @param {Function} callback Callback\n */\n setPath(p, callback) {\n var path = p5.prototype._checkFileFormats(p);\n this.url = path;\n this.load(callback);\n }\n\n /**\n * Replace the current Audio Buffer with a new Buffer.\n *\n * @method setBuffer\n * @for p5.SoundFile\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\n * will create a stereo source. 1 will create\n * a mono source.\n */\n setBuffer(buf) {\n var numChannels = buf.length;\n var size = buf[0].length;\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\n\n if (!(buf[0] instanceof Float32Array)) {\n buf[0] = new Float32Array(buf[0]);\n }\n\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\n var channel = newBuffer.getChannelData(channelNum);\n channel.set(buf[channelNum]);\n }\n\n this.buffer = newBuffer;\n\n // set numbers of channels on input to the panner\n this.panner.inputChannels(numChannels);\n }\n\n // initialize counterNode, set its initial buffer and playbackRate\n _initCounterNode() {\n var self = this;\n var now = ac.currentTime;\n var cNode = ac.createBufferSource();\n\n const workletBufferSize = safeBufferSize(256);\n\n // dispose of worklet node if it already exists\n if (self._workletNode) {\n self._workletNode.disconnect();\n delete self._workletNode;\n }\n self._workletNode = new AudioWorkletNode(\n ac,\n processorNames.soundFileProcessor,\n {\n processorOptions: { bufferSize: workletBufferSize },\n }\n );\n self._workletNode.port.onmessage = (event) => {\n if (event.data.name === 'position') {\n // event.data.position should only be 0 when paused\n if (event.data.position === 0) {\n return;\n }\n this._lastPos = event.data.position;\n\n // do any callbacks that have been scheduled\n this._onTimeUpdate(self._lastPos);\n }\n };\n\n // create counter buffer of the same length as self.buffer\n cNode.buffer = _createCounterBuffer(self.buffer);\n\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\n\n cNode.connect(self._workletNode);\n self._workletNode.connect(p5.soundOut._silentNode);\n\n return cNode;\n }\n\n // initialize sourceNode, set its initial buffer and playbackRate\n _initSourceNode() {\n var bufferSourceNode = ac.createBufferSource();\n bufferSourceNode.buffer = this.buffer;\n bufferSourceNode.playbackRate.value = this.playbackRate;\n bufferSourceNode.connect(this.output);\n return bufferSourceNode;\n }\n\n /**\n * processPeaks returns an array of timestamps where it thinks there is a beat.\n *\n * This is an asynchronous function that processes the soundfile in an offline audio context,\n * and sends the results to your callback function.\n *\n * The process involves running the soundfile through a lowpass filter, and finding all of the\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\n *\n * @method processPeaks\n * @for p5.SoundFile\n * @param {Function} callback a function to call once this data is returned\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\n * @return {Array} Array of timestamped peaks\n */\n processPeaks(callback, _initThreshold, _minThreshold, _minPeaks) {\n var bufLen = this.buffer.length;\n var sampleRate = this.buffer.sampleRate;\n var buffer = this.buffer;\n var allPeaks = [];\n\n var initialThreshold = _initThreshold || 0.9,\n threshold = initialThreshold,\n minThreshold = _minThreshold || 0.22,\n minPeaks = _minPeaks || 200;\n\n // Create offline context\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\n\n // create buffer source\n var source = offlineContext.createBufferSource();\n source.buffer = buffer;\n\n // Create filter. TO DO: allow custom setting of filter\n var filter = offlineContext.createBiquadFilter();\n filter.type = 'lowpass';\n source.connect(filter);\n filter.connect(offlineContext.destination);\n\n // start playing at time:0\n source.start(0);\n offlineContext.startRendering(); // Render the song\n\n // act on the result\n offlineContext.oncomplete = function (e) {\n if (!self.panner) return;\n var filteredBuffer = e.renderedBuffer;\n var bufferData = filteredBuffer.getChannelData(0);\n\n // step 1:\n // create Peak instances, add them to array, with strength and sampleIndex\n do {\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\n threshold -= 0.005;\n } while (\n Object.keys(allPeaks).length < minPeaks &&\n threshold >= minThreshold\n );\n\n // step 2:\n // find intervals for each peak in the sampleIndex, add tempos array\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\n\n // step 3: find top tempos\n var groups = groupNeighborsByTempo(\n intervalCounts,\n filteredBuffer.sampleRate\n );\n\n // sort top intervals\n var topTempos = groups\n .sort(function (intA, intB) {\n return intB.count - intA.count;\n })\n .splice(0, 5);\n\n // set this SoundFile's tempo to the top tempo ??\n this.tempo = topTempos[0].tempo;\n\n // step 4:\n // new array of peaks at top tempo within a bpmVariance\n var bpmVariance = 5;\n var tempoPeaks = getPeaksAtTopTempo(\n allPeaks,\n topTempos[0].tempo,\n filteredBuffer.sampleRate,\n bpmVariance\n );\n\n callback(tempoPeaks);\n };\n }\n\n /**\n * Schedule events to trigger every time a MediaElement\n * (audio/video) reaches a playback cue point.\n *\n * Accepts a callback function, a time (in seconds) at which to trigger\n * the callback, and an optional parameter for the callback.\n *\n * Time will be passed as the first parameter to the callback function,\n * and param will be the second parameter.\n *\n *\n * @method addCue\n * @for p5.SoundFile\n * @param {Number} time Time in seconds, relative to this media\n * element's playback. For example, to trigger\n * an event every time playback reaches two\n * seconds, pass in the number 2. This will be\n * passed as the first parameter to\n * the callback function.\n * @param {Function} callback Name of a function that will be\n * called at the given time. The callback will\n * receive time and (optionally) param as its\n * two parameters.\n * @param {Object} [value] An object to be passed as the\n * second parameter to the\n * callback function.\n * @return {Number} id ID of this cue,\n * useful for removeCue(id)\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 10, 20);\n *\n * // schedule calls to changeText\n * mySound.addCue(0, changeText, \"hello\" );\n * mySound.addCue(0.5, changeText, \"hello,\" );\n * mySound.addCue(1, changeText, \"hello, p5!\");\n * mySound.addCue(1.5, changeText, \"hello, p5!!\");\n * mySound.addCue(2, changeText, \"hello, p5!!!!!\");\n * }\n *\n * function changeText(val) {\n * background(220);\n * text(val, 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.play();\n * }\n *
\n */\n addCue(time, callback, val) {\n var id = this._cueIDCounter++;\n\n var cue = new Cue(callback, time, id, val);\n this._cues.push(cue);\n\n // if (!this.elt.ontimeupdate) {\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\n // }\n\n return id;\n }\n\n /**\n * Remove a callback based on its ID. The ID is returned by the\n * addCue method.\n *\n * @method removeCue\n * @for p5.SoundFile\n * @param {Number} id ID of the cue, as returned by addCue\n */\n removeCue(id) {\n var cueLength = this._cues.length;\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n if (cue.id === id) {\n this._cues.splice(i, 1);\n break;\n }\n }\n\n if (this._cues.length === 0) {\n // TO DO: remove callback\n // this.elt.ontimeupdate = null\n }\n }\n\n /**\n * Remove all of the callbacks that had originally been scheduled\n * via the addCue method.\n *\n * @method clearCues\n */\n clearCues() {\n this._cues = [];\n // this.elt.ontimeupdate = null;\n }\n\n // private method that checks for cues to be fired if events\n // have been scheduled using addCue(callback, time).\n _onTimeUpdate(position) {\n var playbackTime = position / this.buffer.sampleRate;\n var cueLength = this._cues.length;\n\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n var callbackTime = cue.time;\n var val = cue.val;\n var leftLimit = this._prevUpdateTime || 0;\n var rightLimit = playbackTime;\n if (leftLimit <= callbackTime && callbackTime <= rightLimit) {\n // pass the scheduled callbackTime as parameter to the callback\n cue.callback(val);\n }\n }\n\n this._prevUpdateTime = playbackTime;\n }\n\n /**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device. To upload a file to a server, see\n * getBlob\n *\n * @method save\n * @for p5.SoundFile\n * @param {String} [fileName] name of the resulting .wav file.\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to download', 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.save('my cool filename');\n * }\n *
\n */\n save(fileName) {\n p5.prototype.saveSound(this, fileName, 'wav');\n }\n\n /**\n * This method is useful for sending a SoundFile to a server. It returns the\n * .wav-encoded audio data as a \"Blob\".\n * A Blob is a file-like data object that can be uploaded to a server\n * with an http request. We'll\n * use the `httpDo` options object to send a POST request with some\n * specific options: we encode the request as `multipart/form-data`,\n * and attach the blob as one of the form values using `FormData`.\n *\n *\n * @method getBlob\n * @for p5.SoundFile\n * @returns {Blob} A file-like data object\n * @example\n *
\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n *\n * function setup() {\n * noCanvas();\n * let soundBlob = mySound.getBlob();\n *\n * // Now we can send the blob to a server...\n * let serverUrl = 'https://jsonplaceholder.typicode.com/posts';\n * let httpRequestOptions = {\n * method: 'POST',\n * body: new FormData().append('soundBlob', soundBlob),\n * headers: new Headers({\n * 'Content-Type': 'multipart/form-data'\n * })\n * };\n * httpDo(serverUrl, httpRequestOptions);\n *\n * // We can also create an `ObjectURL` pointing to the Blob\n * let blobUrl = URL.createObjectURL(soundBlob);\n *\n * // The `
\n */\n getBlob() {\n const dataView = convertToWav(this.buffer);\n return new Blob([dataView], { type: 'audio/wav' });\n }\n}\n\n/**\n * loadSound() returns a new p5.SoundFile from a specified\n * path. If called during preload(), the p5.SoundFile will be ready\n * to play in time for setup() and draw(). If called outside of\n * preload, the p5.SoundFile will not be ready immediately, so\n * loadSound accepts a callback as the second parameter. Using a\n * \n * local server is recommended when loading external files.\n *\n * @method loadSound\n * @for p5\n * @param {String|Array} path Path to the sound file, or an array with\n * paths to soundfiles in multiple formats\n * i.e. ['sound.ogg', 'sound.mp3'].\n * Alternately, accepts an object: either\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is\n * an error loading the file.\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\n * This function will receive the percentage loaded\n * so far, from 0.0 to 1.0.\n * @return {SoundFile} Returns a p5.SoundFile\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\nfunction loadSound(path, callback, onerror, whileLoading) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n window.alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n\n var self = this;\n var s = new SoundFile(\n path,\n function () {\n if (typeof callback === 'function') {\n callback.apply(self, arguments);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n onerror,\n whileLoading\n );\n\n return s;\n}\n\nexport default SoundFile;\nexport { loadSound };\n","import p5sound from './master';\nimport { safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\n/**\n * Amplitude measures volume between 0.0 and 1.0.\n * Listens to all p5sound by default, or use setInput()\n * to listen to a specific sound source. Accepts an optional\n * smoothing value, which defaults to 0.\n *\n * @class p5.Amplitude\n * @constructor\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\n * amplitude readings (defaults to 0)\n * @example\n *
\n * let sound, amplitude;\n *\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function togglePlay() {\n * if (sound.isPlaying() ){\n * sound.pause();\n * } else {\n * sound.loop();\n *\t\tamplitude = new p5.Amplitude();\n *\t\tamplitude.setInput(sound);\n * }\n * }\n *\n *
\n */\nclass Amplitude {\n constructor(smoothing) {\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\n this.bufferSize = safeBufferSize(2048);\n\n // set audio context\n this.audiocontext = p5sound.audiocontext;\n this._workletNode = new AudioWorkletNode(\n this.audiocontext,\n processorNames.amplitudeProcessor,\n {\n outputChannelCount: [1],\n\n parameterData: { smoothing: smoothing || 0 },\n processorOptions: {\n normalize: false,\n smoothing: smoothing || 0,\n numInputChannels: 2,\n bufferSize: this.bufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'amplitude') {\n this.volume = event.data.volume;\n this.volNorm = event.data.volNorm;\n this.stereoVol = event.data.stereoVol;\n this.stereoVolNorm = event.data.stereoVolNorm;\n }\n }.bind(this);\n\n // for connections\n this.input = this._workletNode;\n\n this.output = this.audiocontext.createGain();\n\n // the variables to return\n this.volume = 0;\n this.volNorm = 0;\n this.stereoVol = [0, 0];\n this.stereoVolNorm = [0, 0];\n\n this.normalize = false;\n\n this._workletNode.connect(this.output);\n this.output.gain.value = 0;\n\n // this may only be necessary because of a Chrome bug\n this.output.connect(this.audiocontext.destination);\n\n // connect to p5sound master output by default, unless set by input()\n p5sound.meter.connect(this._workletNode);\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Connects to the p5sound instance (master output) by default.\n * Optionally, you can pass in a specific source (i.e. a soundfile).\n *\n * @method setInput\n * @for p5.Amplitude\n * @param {soundObject|undefined} [snd] set the sound source\n * (optional, defaults to\n * master output)\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\n * to smooth amplitude readings\n * @example\n *
\n * function preload(){\n * sound1 = loadSound('assets/beat.mp3');\n * sound2 = loadSound('assets/drum.mp3');\n * }\n * function setup(){\n * cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n *\n * amplitude = new p5.Amplitude();\n * amplitude.setInput(sound2);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound1.isPlaying() && sound2.isPlaying()) {\n * sound1.stop();\n * sound2.stop();\n * } else {\n * sound1.play();\n * sound2.play();\n * }\n * }\n *
\n */\n setInput(source, smoothing) {\n p5sound.meter.disconnect();\n\n if (smoothing) {\n this._workletNode.parameters.get('smoothing').value = smoothing;\n }\n\n // connect to the master out of p5s instance if no snd is provided\n if (source == null) {\n console.log(\n 'Amplitude input source is not ready! Connecting to master output instead'\n );\n p5sound.meter.connect(this._workletNode);\n }\n\n // connect to the sound if it is available\n else if (source) {\n source.connect(this._workletNode);\n this._workletNode.disconnect();\n this._workletNode.connect(this.output);\n }\n\n // otherwise, connect to the master out of p5s instance (default)\n else {\n p5sound.meter.connect(this._workletNode);\n }\n }\n\n connect(unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(this.panner.connect(p5sound.input));\n }\n }\n\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Returns a single Amplitude reading at the moment it is called.\n * For continuous readings, run in the draw loop.\n *\n * @method getLevel\n * @for p5.Amplitude\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\n * @return {Number} Amplitude as a number between 0.0 and 1.0\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220, 150);\n * textAlign(CENTER);\n * text('tap to play', width/2, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound.isPlaying()) {\n * sound.stop();\n * } else {\n * sound.play();\n * }\n * }\n *
\n */\n getLevel(channel) {\n if (typeof channel !== 'undefined') {\n if (this.normalize) {\n return this.stereoVolNorm[channel];\n } else {\n return this.stereoVol[channel];\n }\n } else if (this.normalize) {\n return this.volNorm;\n } else {\n return this.volume;\n }\n }\n\n /**\n * Determines whether the results of Amplitude.process() will be\n * Normalized. To normalize, Amplitude finds the difference the\n * loudest reading it has processed and the maximum amplitude of\n * 1.0. Amplitude adds this difference to all values to produce\n * results that will reliably map between 0.0 and 1.0. However,\n * if a louder moment occurs, the amount that Normalize adds to\n * all the values will change. Accepts an optional boolean parameter\n * (true or false). Normalizing is off by default.\n *\n * @method toggleNormalize\n * @for p5.Amplitude\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\n */\n toggleNormalize(bool) {\n if (typeof bool === 'boolean') {\n this.normalize = bool;\n } else {\n this.normalize = !this.normalize;\n }\n this._workletNode.port.postMessage({\n name: 'toggleNormalize',\n normalize: this.normalize,\n });\n }\n /**\n * Smooth Amplitude analysis by averaging with the last analysis\n * frame. Off by default.\n *\n * @method smooth\n * @for p5.Amplitude\n * @param {Number} set smoothing from 0.0 <= 1\n */\n smooth(s) {\n if (s >= 0 && s < 1) {\n this._workletNode.port.postMessage({ name: 'smoothing', smoothing: s });\n } else {\n console.log('Error: smoothing must be between 0 and 1');\n }\n }\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n this._workletNode.disconnect();\n delete this._workletNode;\n }\n}\n\nexport default Amplitude;\n","import p5sound from './master';\n\n/**\n *

FFT (Fast Fourier Transform) is an analysis algorithm that\n * isolates individual\n * \n * audio frequencies within a waveform.

\n *\n *

Once instantiated, a p5.FFT object can return an array based on\n * two types of analyses:
• FFT.waveform() computes\n * amplitude values along the time domain. The array indices correspond\n * to samples across a brief moment in time. Each value represents\n * amplitude of the waveform at that sample of time.
\n * • FFT.analyze() computes amplitude values along the\n * frequency domain. The array indices correspond to frequencies (i.e.\n * pitches), from the lowest to the highest that humans can hear. Each\n * value represents amplitude at that slice of the frequency spectrum.\n * Use with getEnergy() to measure amplitude at specific\n * frequencies, or within a range of frequencies.

\n *\n *

FFT analyzes a very short snapshot of sound called a sample\n * buffer. It returns an array of amplitude measurements, referred\n * to as bins. The array is 1024 bins long by default.\n * You can change the bin array length, but it must be a power of 2\n * between 16 and 1024 in order for the FFT algorithm to function\n * correctly. The actual size of the FFT buffer is twice the\n * number of bins, so given a standard sample rate, the buffer is\n * 2048/44100 seconds long.

\n *\n *\n * @class p5.FFT\n * @constructor\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\n * 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n * @param {Number} [bins] Length of resulting array.\n * Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(togglePlay);\n * fft = new p5.FFT();\n * sound.amp(0.2);\n * }\n *\n * function draw(){\n * background(220);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h )\n * }\n *\n * let waveform = fft.waveform();\n * noFill();\n * beginShape();\n * stroke(20);\n * for (let i = 0; i < waveform.length; i++){\n * let x = map(i, 0, waveform.length, 0, width);\n * let y = map( waveform[i], -1, 1, 0, height);\n * vertex(x,y);\n * }\n * endShape();\n *\n * text('tap to play', 20, 20);\n * }\n *\n * function togglePlay() {\n * if (sound.isPlaying()) {\n * sound.pause();\n * } else {\n * sound.loop();\n * }\n * }\n *
\n */\nclass FFT {\n constructor(smoothing, bins) {\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\n\n Object.defineProperties(this, {\n bins: {\n get: function () {\n return this.analyser.fftSize / 2;\n },\n set: function (b) {\n this.analyser.fftSize = b * 2;\n },\n configurable: true,\n enumerable: true,\n },\n smoothing: {\n get: function () {\n return this.analyser.smoothingTimeConstant;\n },\n set: function (s) {\n this.analyser.smoothingTimeConstant = s;\n },\n configurable: true,\n enumerable: true,\n },\n });\n\n // set default smoothing and bins\n this.smooth(smoothing);\n this.bins = bins || 1024;\n\n // default connections to p5sound fftMeter\n p5sound.fftMeter.connect(this.analyser);\n\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\n\n // predefined frequency ranges, these will be tweakable\n this.bass = [20, 140];\n this.lowMid = [140, 400];\n this.mid = [400, 2600];\n this.highMid = [2600, 5200];\n this.treble = [5200, 14000];\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Set the input source for the FFT analysis. If no source is\n * provided, FFT will analyze all sound in the sketch.\n *\n * @method setInput\n * @for p5.FFT\n * @param {Object} [source] p5.sound object (or web audio API source node)\n */\n setInput(source) {\n if (!source) {\n p5sound.fftMeter.connect(this.analyser);\n } else {\n if (source.output) {\n source.output.connect(this.analyser);\n } else if (source.connect) {\n source.connect(this.analyser);\n }\n p5sound.fftMeter.disconnect();\n }\n }\n\n /**\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\n * a snapshot of amplitude readings in a single buffer. Length will be\n * equal to bins (defaults to 1024). Can be used to draw the waveform\n * of a sound.\n *\n * @method waveform\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {String} [precision] If any value is provided, will return results\n * in a Float32 Array which is more precise\n * than a regular array.\n * @return {Array} Array Array of amplitude values (-1 to 1)\n * over time. Array length = bins.\n *\n */\n waveform() {\n var bins, mode;\n var normalArray = new Array();\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n bins = arguments[i];\n this.analyser.fftSize = bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\n if (mode && !p5.prototype._isSafari()) {\n timeToFloat(this, this.timeDomain);\n this.analyser.getFloatTimeDomainData(this.timeDomain);\n return this.timeDomain;\n } else {\n timeToInt(this, this.timeDomain);\n this.analyser.getByteTimeDomainData(this.timeDomain);\n for (var j = 0; j < this.timeDomain.length; j++) {\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\n normalArray.push(scaled);\n }\n return normalArray;\n }\n }\n\n /**\n * Returns an array of amplitude values (between 0 and 255)\n * across the frequency spectrum. Length is equal to FFT bins\n * (1024 by default). The array indices correspond to frequencies\n * (i.e. pitches), from the lowest to the highest that humans can\n * hear. Each value represents amplitude at that slice of the\n * frequency spectrum. Must be called prior to using\n * getEnergy().\n *\n * @method analyze\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {Number} [scale] If \"dB,\" returns decibel\n * float measurements between\n * -140 and 0 (max).\n * Otherwise returns integers from 0-255.\n * @return {Array} spectrum Array of energy (amplitude/volume)\n * values across the frequency spectrum.\n * Lowest energy (silence) = 0, highest\n * possible is 255.\n * @example\n *
\n * let osc, fft;\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(startSound);\n * osc = new p5.Oscillator();\n * osc.amp(0);\n * fft = new p5.FFT();\n * }\n *\n * function draw(){\n * background(220);\n *\n * let freq = map(mouseX, 0, windowWidth, 20, 10000);\n * freq = constrain(freq, 1, 20000);\n * osc.freq(freq);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h );\n * }\n *\n * stroke(255);\n * if (!osc.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text(round(freq)+'Hz', 10, 20);\n * }\n * }\n *\n * function startSound() {\n * osc.start();\n * osc.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * osc.amp(0, 0.2);\n * }\n *
\n *\n *\n */\n analyze() {\n var mode;\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n this.bins = arguments[i];\n this.analyser.fftSize = this.bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n if (mode && mode.toLowerCase() === 'db') {\n freqToFloat(this);\n this.analyser.getFloatFrequencyData(this.freqDomain);\n return this.freqDomain;\n } else {\n freqToInt(this, this.freqDomain);\n this.analyser.getByteFrequencyData(this.freqDomain);\n var normalArray = Array.apply([], this.freqDomain);\n\n return normalArray;\n }\n }\n\n /**\n * Returns the amount of energy (volume) at a specific\n * \n * frequency, or the average amount of energy between two\n * frequencies. Accepts Number(s) corresponding\n * to frequency (in Hz), or a \"string\" corresponding to predefined\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\n * Returns a range between 0 (no energy/volume at that frequency) and\n * 255 (maximum energy).\n * NOTE: analyze() must be called prior to getEnergy(). analyze()\n * tells the FFT to analyze frequency data, and getEnergy() uses\n * the results to determine the value at a specific frequency or\n * range of frequencies.

\n *\n * @method getEnergy\n * @for p5.FFT\n * @param {Number|String} frequency1 Will return a value representing\n * energy at this frequency. Alternately,\n * the strings \"bass\", \"lowMid\" \"mid\",\n * \"highMid\", and \"treble\" will return\n * predefined frequency ranges.\n * @param {Number} [frequency2] If a second frequency is given,\n * will return average amount of\n * energy that exists between the\n * two frequencies.\n * @return {Number} Energy Energy (volume/amplitude) from\n * 0 and 255.\n *\n */\n getEnergy(frequency1, frequency2) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n\n if (frequency1 === 'bass') {\n frequency1 = this.bass[0];\n frequency2 = this.bass[1];\n } else if (frequency1 === 'lowMid') {\n frequency1 = this.lowMid[0];\n frequency2 = this.lowMid[1];\n } else if (frequency1 === 'mid') {\n frequency1 = this.mid[0];\n frequency2 = this.mid[1];\n } else if (frequency1 === 'highMid') {\n frequency1 = this.highMid[0];\n frequency2 = this.highMid[1];\n } else if (frequency1 === 'treble') {\n frequency1 = this.treble[0];\n frequency2 = this.treble[1];\n }\n\n if (typeof frequency1 !== 'number') {\n throw 'invalid input for getEnergy()';\n } else if (!frequency2) {\n // if only one parameter:\n var index = Math.round((frequency1 / nyquist) * this.freqDomain.length);\n return this.freqDomain[index];\n } else if (frequency1 && frequency2) {\n // if two parameters:\n // if second is higher than first\n if (frequency1 > frequency2) {\n var swap = frequency2;\n frequency2 = frequency1;\n frequency1 = swap;\n }\n var lowIndex = Math.round(\n (frequency1 / nyquist) * this.freqDomain.length\n );\n var highIndex = Math.round(\n (frequency2 / nyquist) * this.freqDomain.length\n );\n\n var total = 0;\n var numFrequencies = 0;\n // add up all of the values for the frequencies\n for (var i = lowIndex; i <= highIndex; i++) {\n total += this.freqDomain[i];\n numFrequencies += 1;\n }\n // divide by total number of frequencies\n var toReturn = total / numFrequencies;\n return toReturn;\n } else {\n throw 'invalid input for getEnergy()';\n }\n }\n\n // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\n getFreq(freq1, freq2) {\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\n var x = this.getEnergy(freq1, freq2);\n return x;\n }\n\n /**\n * Returns the\n * \n * spectral centroid of the input signal.\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\n * tells the FFT to analyze frequency data, and getCentroid() uses\n * the results determine the spectral centroid.

\n *\n * @method getCentroid\n * @for p5.FFT\n * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz.\n *\n *\n * @example\n *
\n * function setup(){\n * cnv = createCanvas(100,100);\n * cnv.mousePressed(userStartAudio);\n * sound = new p5.AudioIn();\n * sound.start();\n * fft = new p5.FFT();\n * sound.connect(fft);\n *}\n *\n *function draw() {\n * if (getAudioContext().state !== 'running') {\n * background(220);\n * text('tap here and enable mic to begin', 10, 20, width - 20);\n * return;\n * }\n * let centroidplot = 0.0;\n * let spectralCentroid = 0;\n *\n * background(0);\n * stroke(0,255,0);\n * let spectrum = fft.analyze();\n * fill(0,255,0); // spectrum is green\n *\n * //draw the spectrum\n * for (let i = 0; i < spectrum.length; i++){\n * let x = map(log(i), 0, log(spectrum.length), 0, width);\n * let h = map(spectrum[i], 0, 255, 0, height);\n * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\n * rect(x, height, rectangle_width, -h )\n * }\n * let nyquist = 22050;\n *\n * // get the centroid\n * spectralCentroid = fft.getCentroid();\n *\n * // the mean_freq_index calculation is for the display.\n * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\n *\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\n *\n * stroke(255,0,0); // the line showing where the centroid is will be red\n *\n * rect(centroidplot, 0, width / spectrum.length, height)\n * noStroke();\n * fill(255,255,255); // text is white\n * text('centroid: ', 10, 20);\n * text(round(spectralCentroid)+' Hz', 10, 40);\n *}\n *
\n */\n getCentroid() {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var cumulative_sum = 0;\n var centroid_normalization = 0;\n\n for (var i = 0; i < this.freqDomain.length; i++) {\n cumulative_sum += i * this.freqDomain[i];\n centroid_normalization += this.freqDomain[i];\n }\n\n var mean_freq_index = 0;\n\n if (centroid_normalization !== 0) {\n mean_freq_index = cumulative_sum / centroid_normalization;\n }\n\n var spec_centroid_freq =\n mean_freq_index * (nyquist / this.freqDomain.length);\n return spec_centroid_freq;\n }\n\n /**\n * Smooth FFT analysis by averaging with the last analysis frame.\n *\n * @method smooth\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n */\n smooth(s) {\n if (typeof s !== 'undefined') {\n this.smoothing = s;\n }\n return this.smoothing;\n }\n\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.analyser) {\n this.analyser.disconnect();\n delete this.analyser;\n }\n }\n\n /**\n * Returns an array of average amplitude values for a given number\n * of frequency bands split equally. N defaults to 16.\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\n * tells the FFT to analyze frequency data, and linAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method linAverages\n * @for p5.FFT\n * @param {Number} N Number of returned frequency groups\n * @return {Array} linearAverages Array of average amplitude values for each group\n */\n\n linAverages(_N) {\n var N = _N || 16; // This prevents undefined, null or 0 values of N\n\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n var spectrumStep = Math.floor(spectrumLength / N);\n\n var linearAverages = new Array(N);\n // Keep a second index for the current average group and place the values accordingly\n // with only one loop in the spectrum data\n var groupIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n linearAverages[groupIndex] =\n linearAverages[groupIndex] !== undefined\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n\n // Increase the group index when the last element of the group is processed\n if (specIndex % spectrumStep === spectrumStep - 1) {\n groupIndex++;\n }\n }\n\n return linearAverages;\n }\n\n /**\n * Returns an array of average amplitude values of the spectrum, for a given\n * set of \n * Octave Bands\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\n * tells the FFT to analyze frequency data, and logAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method logAverages\n * @for p5.FFT\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\n * @return {Array} logAverages Array of average amplitude values for each group\n */\n logAverages(octaveBands) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n\n var logAverages = new Array(octaveBands.length);\n // Keep a second index for the current average group and place the values accordingly\n // With only one loop in the spectrum data\n var octaveIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n var specIndexFrequency = Math.round(\n (specIndex * nyquist) / this.freqDomain.length\n );\n\n // Increase the group index if the current frequency exceeds the limits of the band\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\n octaveIndex++;\n }\n\n logAverages[octaveIndex] =\n logAverages[octaveIndex] !== undefined\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n }\n\n return logAverages;\n }\n\n /**\n * Calculates and Returns the 1/N\n * Octave Bands\n * N defaults to 3 and minimum central frequency to 15.625Hz.\n * (1/3 Octave Bands ~= 31 Frequency Bands)\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\n * and produce less frequency groups.\n *\n * @method getOctaveBands\n * @for p5.FFT\n * @param {Number} N Specifies the 1/N type of generated octave bands\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\n * @return {Array} octaveBands Array of octave band objects with their bounds\n */\n getOctaveBands(_N, _fCtr0) {\n var N = _N || 3; // Default to 1/3 Octave Bands\n var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\n\n var octaveBands = [];\n var lastFrequencyBand = {\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\n ctr: fCtr0,\n hi: fCtr0 * Math.pow(2, 1 / (2 * N)),\n };\n octaveBands.push(lastFrequencyBand);\n\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n while (lastFrequencyBand.hi < nyquist) {\n var newFrequencyBand = {};\n newFrequencyBand.lo = lastFrequencyBand.hi;\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\n\n octaveBands.push(newFrequencyBand);\n lastFrequencyBand = newFrequencyBand;\n }\n\n return octaveBands;\n }\n}\n\n// helper methods to convert type from float (dB) to int (0-255)\nfunction freqToFloat(fft) {\n if (fft.freqDomain instanceof Float32Array === false) {\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction freqToInt(fft) {\n if (fft.freqDomain instanceof Uint8Array === false) {\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToFloat(fft) {\n if (fft.timeDomain instanceof Float32Array === false) {\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToInt(fft) {\n if (fft.timeDomain instanceof Uint8Array === false) {\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\n\nexport default FFT;\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\nimport Panner from './panner';\n// ========================== //\n// SIGNAL MATH FOR MODULATION //\n// ========================== //\n\n// return sigChain(this, scale, thisChain, nextChain, Scale);\nfunction sigChain(o, mathObj, thisChain, nextChain, type) {\n var chainSource = o.oscillator;\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n chainSource.disconnect();\n o.mathOps[i].dispose();\n thisChain = i;\n // assume nextChain is output gain node unless...\n if (thisChain < o.mathOps.length - 2) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n if (thisChain === o.mathOps.length - 1) {\n o.mathOps.push(nextChain);\n }\n // assume source is the oscillator unless i > 0\n if (i > 0) {\n chainSource = o.mathOps[i - 1];\n }\n chainSource.disconnect();\n chainSource.connect(mathObj);\n mathObj.connect(nextChain);\n o.mathOps[thisChain] = mathObj;\n return o;\n}\n\n/**\n *

Creates a signal that oscillates between -1.0 and 1.0.\n * By default, the oscillation takes the form of a sinusoidal\n * shape ('sine'). Additional types include 'triangle',\n * 'sawtooth' and 'square'. The frequency defaults to\n * 440 oscillations per second (440Hz, equal to the pitch of an\n * 'A' note).

\n *\n *

Set the type of oscillation with setType(), or by instantiating a\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\n *

\n *\n * @class p5.Oscillator\n * @constructor\n * @param {Number} [freq] frequency defaults to 440Hz\n * @param {String} [type] type of oscillator. Options:\n * 'sine' (default), 'triangle',\n * 'sawtooth', 'square'\n * @example\n *
\n * let osc, playing, freq, amp;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator('sine');\n * }\n *\n * function draw() {\n * background(220)\n * freq = constrain(map(mouseX, 0, width, 100, 500), 100, 500);\n * amp = constrain(map(mouseY, height, 0, 0, 1), 0, 1);\n *\n * text('tap to play', 20, 20);\n * text('freq: ' + freq, 20, 40);\n * text('amp: ' + amp, 20, 60);\n *\n * if (playing) {\n * // smooth the transitions by 0.1 seconds\n * osc.freq(freq, 0.1);\n * osc.amp(amp, 0.1);\n * }\n * }\n *\n * function playOscillator() {\n * // starting an oscillator on a user gesture will enable audio\n * // in browsers that have a strict autoplay policy.\n * // See also: userStartAudio();\n * osc.start();\n * playing = true;\n * }\n *\n * function mouseReleased() {\n * // ramp amplitude to 0 over 0.5 seconds\n * osc.amp(0, 0.5);\n * playing = false;\n * }\n *
\n */\nclass Oscillator {\n constructor(freq, type) {\n if (typeof freq === 'string') {\n let f = type;\n type = freq;\n freq = f;\n }\n if (typeof type === 'number') {\n let f = type;\n type = freq;\n freq = f;\n }\n this.started = false;\n\n // components\n this.phaseAmount = undefined;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.f = freq || 440.0; // frequency\n this.oscillator.type = type || 'sine';\n this.oscillator.frequency.setValueAtTime(\n this.f,\n p5sound.audiocontext.currentTime\n );\n\n // connections\n this.output = p5sound.audiocontext.createGain();\n\n this._freqMods = []; // modulators connected to this oscillator's frequency\n\n // set default output gain to 0.5\n this.output.gain.value = 0.5;\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\n\n this.oscillator.connect(this.output);\n // stereo panning\n this.panPosition = 0.0;\n this.connection = p5sound.input; // connect to p5sound by default\n this.panner = new Panner(this.output, this.connection, 1);\n\n //array of math operation signal chaining\n this.mathOps = [this.output];\n\n // add to the soundArray so we can dispose of the osc later\n p5sound.soundArray.push(this);\n\n // these methods are now the same thing\n this.fade = this.amp;\n }\n\n /**\n * Start an oscillator.\n *\n * Starting an oscillator on a user gesture will enable audio in browsers\n * that have a strict autoplay policy, including Chrome and most mobile\n * devices. See also: `userStartAudio()`.\n *\n * @method start\n * @for p5.Oscillator\n * @param {Number} [time] startTime in seconds from now.\n * @param {Number} [frequency] frequency in Hz.\n */\n start(time, f) {\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n }\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n\n // set old osc free to be garbage collected (memory)\n if (this.oscillator) {\n this.oscillator.disconnect();\n delete this.oscillator;\n }\n\n // var detune = this.oscillator.frequency.value;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.value = Math.abs(freq);\n this.oscillator.type = type;\n // this.oscillator.detune.value = detune;\n this.oscillator.connect(this.output);\n time = time || 0;\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\n this.freqNode = this.oscillator.frequency;\n\n // if other oscillators are already connected to this osc's freq\n for (var i in this._freqMods) {\n if (typeof this._freqMods[i].connect !== 'undefined') {\n this._freqMods[i].connect(this.oscillator.frequency);\n }\n }\n\n this.started = true;\n }\n }\n\n /**\n * Stop an oscillator. Accepts an optional parameter\n * to determine how long (in seconds from now) until the\n * oscillator stops.\n *\n * @method stop\n * @for p5.Oscillator\n * @param {Number} secondsFromNow Time, in seconds from now.\n */\n stop(time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n this.started = false;\n }\n }\n\n /**\n * Set the amplitude between 0 and 1.0. Or, pass in an object\n * such as an oscillator to modulate amplitude with an audio signal.\n *\n * @method amp\n * @for p5.Oscillator\n * @param {Number|Object} vol between 0 and 1.0\n * or a modulating signal/oscillator\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {AudioParam} gain If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's\n * gain/amplitude/volume)\n */\n amp(vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n }\n\n /**\n * Returns the value of output gain\n *\n * @method getAmp\n * @for p5.Oscillator\n *\n * @returns {number} Amplitude value between 0.0 and 1.0\n */\n\n getAmp() {\n return this.output.gain.value;\n }\n\n /**\n * Set frequency of an oscillator to a value. Or, pass in an object\n * such as an oscillator to modulate the frequency with an audio signal.\n *\n * @method freq\n * @for p5.Oscillator\n * @param {Number|Object} Frequency Frequency in Hz\n * or modulating signal/oscillator\n * @param {Number} [rampTime] Ramp time (in seconds)\n * @param {Number} [timeFromNow] Schedule this event to happen\n * at x seconds from now\n * @return {AudioParam} Frequency If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's frequency\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator(300);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playOscillator() {\n * osc.start();\n * osc.amp(0.5);\n * // start at 700Hz\n * osc.freq(700);\n * // ramp to 60Hz over 0.7 seconds\n * osc.freq(60, 0.7);\n * osc.amp(0, 0.1, 0.7);\n * }\n *
\n */\n freq(val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number' && !isNaN(val)) {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n\n if (rampTime === 0) {\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\n } else {\n if (val > 0) {\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n } else {\n this.oscillator.frequency.linearRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n }\n }\n\n // reset phase if oscillator has a phase\n if (this.phaseAmount) {\n this.phase(this.phaseAmount);\n }\n } else if (val) {\n if (val.output) {\n val = val.output;\n }\n val.connect(this.oscillator.frequency);\n\n // keep track of what is modulating this param\n // so it can be re-connected if\n this._freqMods.push(val);\n } else {\n // return the Frequency Node\n return this.oscillator.frequency;\n }\n }\n /**\n * Returns the value of frequency of oscillator\n *\n * @method getFreq\n * @for p5.Oscillator\n * @returns {number} Frequency of oscillator in Hertz\n */\n\n getFreq() {\n return this.oscillator.frequency.value;\n }\n\n /**\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method setType\n * @for p5.Oscillator\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\n */\n setType(type) {\n this.oscillator.type = type;\n }\n /**\n * Returns current type of oscillator eg. 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method getType\n * @for p5.Oscillator\n * @returns {String} type of oscillator eg . 'sine', 'triangle', 'sawtooth' or 'square'.\n */\n\n getType() {\n return this.oscillator.type;\n }\n\n /**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.Oscillator\n * @param {Object} unit A p5.sound or Web Audio object\n */\n connect(unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n this.connection = unit.input;\n } else {\n this.panner.connect(unit);\n this.connection = unit;\n }\n }\n\n /**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.Oscillator\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n if (this.output) {\n this.output.connect(this.panner);\n }\n }\n this.oscMods = [];\n }\n\n /**\n * Pan between Left (-1) and Right (1)\n *\n * @method pan\n * @for p5.Oscillator\n * @param {Number} panning Number between -1 and 1\n * @param {Number} timeFromNow schedule this event to happen\n * seconds from now\n */\n pan(pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n }\n\n /**\n * Returns the current value of panPosition , between Left (-1) and Right (1)\n *\n * @method getPan\n * @for p5.Oscillator\n *\n * @returns {number} panPosition of oscillator , between Left (-1) and Right (1)\n */\n\n getPan() {\n return this.panPosition;\n }\n\n // get rid of the oscillator\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.oscillator) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.disconnect();\n this.panner = null;\n this.oscillator = null;\n }\n // if it is a Pulse\n if (this.osc2) {\n this.osc2.dispose();\n }\n }\n\n /**\n * Set the phase of an oscillator between 0.0 and 1.0.\n * In this implementation, phase is a delay time\n * based on the oscillator's current frequency.\n *\n * @method phase\n * @for p5.Oscillator\n * @param {Number} phase float between 0.0 and 1.0\n */\n phase(p) {\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f);\n var now = p5sound.audiocontext.currentTime;\n\n this.phaseAmount = p;\n\n if (!this.dNode) {\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n // put the delay node in between output and panner\n this.oscillator.disconnect();\n this.oscillator.connect(this.dNode);\n this.dNode.connect(this.output);\n }\n\n // set delay time to match phase:\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\n }\n\n /**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method again\n * will override the initial add() with a new value.\n *\n * @method add\n * @for p5.Oscillator\n * @param {Number} number Constant number to add\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n *\n */\n add(num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, add, thisChain, nextChain, Add);\n }\n /**\n * Multiply the p5.Oscillator's output amplitude\n * by a fixed value (i.e. turn it up!). Calling this method\n * again will override the initial mult() with a new value.\n *\n * @method mult\n * @for p5.Oscillator\n * @param {Number} number Constant number to multiply\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with multiplied output\n */\n mult(num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, mult, thisChain, nextChain, Mult);\n }\n\n /**\n * Scale this oscillator's amplitude values to a given\n * range, and return the oscillator. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Oscillator\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n */\n scale(inMin, inMax, outMin, outMax) {\n var mapOutMin, mapOutMax;\n if (arguments.length === 4) {\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; //find a way to get rid of p5.prototype ?\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; //find a way to get rid of p5.prototype ?\n } else {\n mapOutMin = arguments[0];\n mapOutMax = arguments[1];\n }\n var scale = new Scale(mapOutMin, mapOutMax);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, scale, thisChain, nextChain, Scale);\n\n // this.output.disconnect();\n // this.output.connect(scale)\n }\n}\n\n// ============================== //\n// SinOsc, TriOsc, SqrOsc, SawOsc //\n// ============================== //\n\n/**\n * Constructor: new p5.SinOsc().\n * This creates a Sine Wave Oscillator and is\n * equivalent to new p5.Oscillator('sine')\n * or creating a p5.Oscillator and then calling\n * its method setType('sine').\n * See p5.Oscillator for methods.\n *\n * @class p5.SinOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass SinOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'sine');\n }\n}\n\n/**\n * Constructor: new p5.TriOsc().\n * This creates a Triangle Wave Oscillator and is\n * equivalent to new p5.Oscillator('triangle')\n * or creating a p5.Oscillator and then calling\n * its method setType('triangle').\n * See p5.Oscillator for methods.\n *\n * @class p5.TriOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass TriOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'triangle');\n }\n}\n\n/**\n * Constructor: new p5.SawOsc().\n * This creates a SawTooth Wave Oscillator and is\n * equivalent to new p5.Oscillator('sawtooth')\n * or creating a p5.Oscillator and then calling\n * its method setType('sawtooth').\n * See p5.Oscillator for methods.\n *\n * @class p5.SawOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass SawOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'sawtooth');\n }\n}\n\n/**\n * Constructor: new p5.SqrOsc().\n * This creates a Square Wave Oscillator and is\n * equivalent to new p5.Oscillator('square')\n * or creating a p5.Oscillator and then calling\n * its method setType('square').\n * See p5.Oscillator for methods.\n *\n * @class p5.SqrOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass SqrOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'square');\n }\n}\n\nexport default Oscillator;\nexport { SinOsc, TriOsc, SawOsc, SqrOsc };\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\n\n/**\n *

Envelopes are pre-defined amplitude distribution over time.\n * Typically, envelopes are used to control the output volume\n * of an object, a series of fades referred to as Attack, Decay,\n * Sustain and Release (\n * ADSR\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\n * control an Oscillator's frequency like this: osc.freq(env).

\n *

Use setRange to change the attack/release level.\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

\n *

Use the play method to play the entire envelope,\n * the ramp method for a pingable trigger,\n * or triggerAttack/\n * triggerRelease to trigger noteOn/noteOff.

\n *\n * @class p5.Envelope\n * @constructor\n * @example\n *
\n * let t1 = 0.1; // attack time in seconds\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n *\n * let env;\n * let triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('tap to play', 20, 20);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope(t1, l1, t2, l2);\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function playSound() {\n * // starting the oscillator ensures that audio is enabled.\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n */\np5.Envelope = function (t1, l1, t2, l2, t3, l3) {\n /**\n * Time until envelope reaches attackLevel\n * @property attackTime\n */\n this.aTime = t1 || 0.1;\n /**\n * Level once attack is complete.\n * @property attackLevel\n */\n this.aLevel = l1 || 1;\n /**\n * Time until envelope reaches decayLevel.\n * @property decayTime\n */\n this.dTime = t2 || 0.5;\n /**\n * Level after decay. The envelope will sustain here until it is released.\n * @property decayLevel\n */\n this.dLevel = l2 || 0;\n /**\n * Duration of the release portion of the envelope.\n * @property releaseTime\n */\n this.rTime = t3 || 0;\n /**\n * Level at the end of the release.\n * @property releaseLevel\n */\n this.rLevel = l3 || 0;\n\n this._rampHighPercentage = 0.98;\n\n this._rampLowPercentage = 0.02;\n\n this.output = p5sound.audiocontext.createGain();\n\n this.control = new TimelineSignal();\n\n this._init(); // this makes sure the envelope starts at zero\n\n this.control.connect(this.output); // connect to the output\n\n this.connection = null; // store connection\n\n //array of math operation signal chaining\n this.mathOps = [this.control];\n\n //whether envelope should be linear or exponential curve\n this.isExponential = false;\n\n // oscillator or buffer source to clear on env complete\n // to save resources if/when it is retriggered\n this.sourceToClear = null;\n\n // set to true if attack is set, then false on release\n this.wasTriggered = false;\n\n // add to the soundArray so we can dispose of the env later\n p5sound.soundArray.push(this);\n};\n\n// this init function just smooths the starting value to zero and gives a start point for the timeline\n// - it was necessary to remove glitches at the beginning.\np5.Envelope.prototype._init = function () {\n var now = p5sound.audiocontext.currentTime;\n var t = now;\n this.control.setTargetAtTime(0.00001, t, 0.001);\n //also, compute the correct time constants\n this._setRampAD(this.aTime, this.dTime);\n};\n\n/**\n * Reset the envelope with a series of time/value pairs.\n *\n * @method set\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds) before level\n * reaches attackLevel\n * @param {Number} attackLevel Typically an amplitude between\n * 0.0 and 1.0\n * @param {Number} decayTime Time\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\n * decayLevel = sustainLevel)\n * @param {Number} releaseTime Release Time (in seconds)\n * @param {Number} releaseLevel Amplitude\n * @example\n *
\n * let attackTime;\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n * let l3 = 0.2; // release time in seconds\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n *\n * attackTime = map(mouseX, 0, width, 0.0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 20);\n * }\n *\n * // mouseClick triggers envelope if over canvas\n * function playSound() {\n * env.set(attackTime, l1, t2, l2, l3);\n *\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n *\n */\np5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) {\n this.aTime = t1;\n this.aLevel = l1;\n this.dTime = t2 || 0;\n this.dLevel = l2 || 0;\n this.rTime = t3 || 0;\n this.rLevel = l3 || 0;\n\n // set time constants for ramp\n this._setRampAD(t1, t2);\n};\n\n/**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) {\n this.aTime = aTime;\n this.dTime = dTime || 0;\n\n // lerp\n this.sPercent = sPercent || 0;\n this.dLevel =\n typeof sPercent !== 'undefined'\n ? sPercent * (this.aLevel - this.rLevel) + this.rLevel\n : 0;\n\n this.rTime = rTime || 0;\n\n // also set time constants for ramp\n this._setRampAD(aTime, dTime);\n};\n\n/**\n * Set max (attackLevel) and min (releaseLevel) of envelope.\n *\n * @method setRange\n * @for p5.Envelope\n * @param {Number} aLevel attack level (defaults to 1)\n * @param {Number} rLevel release level (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setRange = function (aLevel, rLevel) {\n this.aLevel = aLevel || 1;\n this.rLevel = rLevel || 0;\n\n // not sure if this belongs here:\n\n // {Number} [dLevel] decay/sustain level (optional)\n // if (typeof(dLevel) !== 'undefined') {\n // this.dLevel = dLevel\n // } else if (this.sPercent) {\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\n // }\n};\n\n// private (undocumented) method called when ADSR is set to set time constants for ramp\n//\n// Set the \n// time constants for simple exponential ramps.\n// The larger the time constant value, the slower the\n// transition will be.\n//\n// method _setRampAD\n// param {Number} attackTimeConstant attack time constant\n// param {Number} decayTimeConstant decay time constant\n//\np5.Envelope.prototype._setRampAD = function (t1, t2) {\n this._rampAttackTime = this.checkExpInput(t1);\n this._rampDecayTime = this.checkExpInput(t2);\n\n var TCDenominator = 1.0;\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\n};\n\n// private method\np5.Envelope.prototype.setRampPercentages = function (p1, p2) {\n //set the percentages that the simple exponential ramps go to\n this._rampHighPercentage = this.checkExpInput(p1);\n this._rampLowPercentage = this.checkExpInput(p2);\n var TCDenominator = 1.0;\n //now re-compute the time constants based on those percentages\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\n};\n\n/**\n * Assign a parameter to be controlled by this envelope.\n * If a p5.Sound object is given, then the p5.Envelope will control its\n * output gain. If multiple inputs are provided, the env will\n * control all of them.\n *\n * @method setInput\n * @for p5.Envelope\n * @param {Object} [...inputs] A p5.sound object or\n * Web Audio Param.\n */\np5.Envelope.prototype.setInput = function () {\n for (var i = 0; i < arguments.length; i++) {\n this.connect(arguments[i]);\n }\n};\n\n/**\n * Set whether the envelope ramp is linear (default) or exponential.\n * Exponential ramps can be useful because we perceive amplitude\n * and frequency logarithmically.\n *\n * @method setExp\n * @for p5.Envelope\n * @param {Boolean} isExp true is exponential, false is linear\n */\np5.Envelope.prototype.setExp = function (isExp) {\n this.isExponential = isExp;\n};\n\n//helper method to protect against zero values being sent to exponential functions\np5.Envelope.prototype.checkExpInput = function (value) {\n if (value <= 0) {\n value = 0.00000001;\n }\n return value;\n};\n\n/**\n *

Play tells the envelope to start acting on a given input.\n * If the input is a p5.sound object (i.e. AudioIn, Oscillator,\n * SoundFile), then Envelope will control its output volume.\n * Envelopes can also be used to control any \n * Web Audio Audio Param.

\n *\n * @method play\n * @for p5.Envelope\n * @param {Object} unit A p5.sound object or\n * Web Audio Param.\n * @param {Number} [startTime] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * triOsc.start();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * // ensure that audio is enabled\n * userStartAudio();\n *\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) {\n var tFromNow = secondsFromNow || 0;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n this.triggerAttack(unit, tFromNow);\n\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + ~~susTime);\n};\n\n/**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go. Input can be\n * any p5.sound object, or a \n * Web Audio Param.\n *\n * @method triggerAttack\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time from now (in seconds)\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n this.lastAttack = t;\n this.wasTriggered = true;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // after each ramp completes, cancel scheduled values\n // (so they can be overridden in case env has been re-triggered)\n // then, set current value (with linearRamp to avoid click)\n // then, schedule the next automation...\n\n // attack\n t += this.aTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.aLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.aLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // decay to decay level (if using ADSR, then decay level == sustain level)\n t += this.dTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.dLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.dLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n};\n\n/**\n * Trigger the Release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method triggerRelease\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time to trigger the release\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) {\n // only trigger a release if an attack was triggered\n if (!this.wasTriggered) {\n // this currently causes a bit of trouble:\n // if a later release has been scheduled (via the play function)\n // a new earlier release won't interrupt it, because\n // this.wasTriggered has already been set to false.\n // If we want new earlier releases to override, then we need to\n // keep track of the last release time, and if the new release time is\n // earlier, then use it.\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear or exponential ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // release\n t += this.rTime;\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.rLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.rLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n this.wasTriggered = false;\n};\n\n/**\n * Exponentially ramp to a value using the first two\n * values from setADSR(attackTime, decayTime)\n * as \n * time constants for simple exponential ramps.\n * If the value is higher than current value, it uses attackTime,\n * while a decrease uses decayTime.\n *\n * @method ramp\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow When to trigger the ramp\n * @param {Number} v Target value\n * @param {Number} [v2] Second target value\n * @example\n *
\n * let env, osc, amp;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let attackLevel = 1;\n * let decayLevel = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * fill(0,255,0);\n * noStroke();\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime);\n * osc = new p5.Oscillator();\n * osc.amp(env);\n * amp = new p5.Amplitude();\n *\n * cnv.mousePressed(triggerRamp);\n * }\n *\n * function triggerRamp() {\n * // ensures audio is enabled. See also: `userStartAudio`\n * osc.start();\n *\n * env.ramp(osc, 0, attackLevel, decayLevel);\n * }\n *\n * function draw() {\n * background(20);\n * text('tap to play', 10, 20);\n * let h = map(amp.getLevel(), 0, 0.4, 0, height);;\n * rect(0, height, width, -h);\n * }\n *
\n */\np5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n var destination1 = this.checkExpInput(v1);\n var destination2 =\n typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\n\n // connect env to unit if not already connected\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n //get current value\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\n // this.control.cancelScheduledValues(t);\n\n //if it's going up\n if (destination1 > currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\n t += this._rampAttackTime;\n }\n\n //if it's going down\n else if (destination1 < currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\n t += this._rampDecayTime;\n }\n\n // Now the second part of envelope begins\n if (destination2 === undefined) return;\n\n //if it's going up\n if (destination2 > destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\n }\n\n //if it's going down\n else if (destination2 < destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\n }\n};\n\np5.Envelope.prototype.connect = function (unit) {\n this.connection = unit;\n\n // assume we're talking about output gain\n // unless given a different audio param\n if (\n unit instanceof p5.Oscillator ||\n unit instanceof p5.SoundFile ||\n unit instanceof p5.AudioIn ||\n unit instanceof p5.Reverb ||\n unit instanceof p5.Noise ||\n unit instanceof p5.Filter ||\n unit instanceof p5.Delay\n ) {\n unit = unit.output.gain;\n }\n if (unit instanceof AudioParam) {\n //set the initial value\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\n }\n\n this.output.connect(unit);\n};\n\np5.Envelope.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n// Signal Math\n\n/**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method\n * again will override the initial add() with new values.\n *\n * @method add\n * @for p5.Envelope\n * @param {Number} number Constant number to add\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.add = function (num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\n};\n\n/**\n * Multiply the p5.Envelope's output amplitude\n * by a fixed value. Calling this method\n * again will override the initial mult() with new values.\n *\n * @method mult\n * @for p5.Envelope\n * @param {Number} number Constant number to multiply\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.mult = function (num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\n};\n\n/**\n * Scale this envelope's amplitude values to a given\n * range, and return the envelope. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Envelope\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var scale = new Scale(inMin, inMax, outMin, outMax);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\n};\n\n// get rid of the oscillator\np5.Envelope.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.disconnect();\n if (this.control) {\n this.control.dispose();\n this.control = null;\n }\n for (var i = 1; i < this.mathOps.length; i++) {\n this.mathOps[i].dispose();\n }\n};\n\n// Different name for backwards compatibility, replicates p5.Envelope class\np5.Env = function (t1, l1, t2, l2, t3, l3) {\n console.warn(\n 'WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\n 'Please use the new p5.Envelope instead.'\n );\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\n};\np5.Env.prototype = Object.create(p5.Envelope.prototype);\n\nconst Envelope = p5.Envelope;\nexport default Envelope;\n","import p5sound from './master';\nimport Oscillator from './oscillator';\n\n// generate noise buffers\nconst _whiteNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var whiteBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = whiteBuffer.getChannelData(0);\n for (var i = 0; i < bufferSize; i++) {\n noiseData[i] = Math.random() * 2 - 1;\n }\n whiteBuffer.type = 'white';\n return whiteBuffer;\n})();\n\nconst _pinkNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var pinkBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = pinkBuffer.getChannelData(0);\n var b0, b1, b2, b3, b4, b5, b6;\n b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n b0 = 0.99886 * b0 + white * 0.0555179;\n b1 = 0.99332 * b1 + white * 0.0750759;\n b2 = 0.969 * b2 + white * 0.153852;\n b3 = 0.8665 * b3 + white * 0.3104856;\n b4 = 0.55 * b4 + white * 0.5329522;\n b5 = -0.7616 * b5 - white * 0.016898;\n noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;\n noiseData[i] *= 0.11; // (roughly) compensate for gain\n b6 = white * 0.115926;\n }\n pinkBuffer.type = 'pink';\n return pinkBuffer;\n})();\n\nconst _brownNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var brownBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = brownBuffer.getChannelData(0);\n var lastOut = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n noiseData[i] = (lastOut + 0.02 * white) / 1.02;\n lastOut = noiseData[i];\n noiseData[i] *= 3.5;\n }\n brownBuffer.type = 'brown';\n return brownBuffer;\n})();\n\n/**\n * Noise is a type of oscillator that generates a buffer with random values.\n *\n * @class p5.Noise\n * @extends p5.Oscillator\n * @constructor\n * @param {String} type Type of noise can be 'white' (default),\n * 'brown' or 'pink'.\n */\nclass Noise extends Oscillator {\n constructor(type) {\n super();\n var assignType;\n delete this.f;\n delete this.freq;\n delete this.oscillator;\n\n if (type === 'brown') {\n assignType = _brownNoiseBuffer;\n } else if (type === 'pink') {\n assignType = _pinkNoiseBuffer;\n } else {\n assignType = _whiteNoiseBuffer;\n }\n this.buffer = assignType;\n }\n\n /**\n * Set type of noise to 'white', 'pink' or 'brown'.\n * White is the default.\n *\n * @method setType\n * @param {String} [type] 'white', 'pink' or 'brown'\n */\n setType(type) {\n switch (type) {\n case 'white':\n this.buffer = _whiteNoiseBuffer;\n break;\n case 'pink':\n this.buffer = _pinkNoiseBuffer;\n break;\n case 'brown':\n this.buffer = _brownNoiseBuffer;\n break;\n default:\n this.buffer = _whiteNoiseBuffer;\n }\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.start(now + 0.01);\n }\n }\n\n getType() {\n return this.buffer.type;\n }\n start() {\n if (this.started) {\n this.stop();\n }\n this.noise = p5sound.audiocontext.createBufferSource();\n this.noise.buffer = this.buffer;\n this.noise.loop = true;\n this.noise.connect(this.output);\n var now = p5sound.audiocontext.currentTime;\n this.noise.start(now);\n this.started = true;\n }\n\n stop() {\n var now = p5sound.audiocontext.currentTime;\n if (this.noise) {\n this.noise.stop(now);\n this.started = false;\n }\n }\n\n dispose() {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.noise) {\n this.noise.disconnect();\n this.stop(now);\n }\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n }\n this.output = null;\n this.panner = null;\n this.buffer = null;\n this.noise = null;\n }\n}\n\nexport default Noise;\n","import Signal from 'Tone/signal/Signal';\nimport Multiply from 'Tone/signal/Multiply';\n\nimport p5sound from './master';\nimport Oscillator, { SawOsc } from './oscillator';\n\n/**\n * Creates a Pulse object, an oscillator that implements\n * Pulse Width Modulation.\n * The pulse is created with two oscillators.\n * Accepts a parameter for frequency, and to set the\n * width between the pulses. See \n * p5.Oscillator for a full list of methods.\n *\n * @class p5.Pulse\n * @extends p5.Oscillator\n * @constructor\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\n * @param {Number} [w] Width between the pulses (0 to 1.0,\n * defaults to 0)\n * @example\n *
\n * let pulse;\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startPulse);\n * background(220);\n *\n * pulse = new p5.Pulse();\n * pulse.amp(0.5);\n * pulse.freq(220);\n * }\n * function startPulse() {\n * pulse.start();\n * pulse.amp(0.5, 0.02);\n * }\n * function mouseReleased() {\n * pulse.amp(0, 0.2);\n * }\n * function draw() {\n * background(220);\n * text('tap to play', 5, 20, width - 20);\n * let w = map(mouseX, 0, width, 0, 1);\n * w = constrain(w, 0, 1);\n * pulse.width(w);\n * text('pulse width: ' + w, 5, height - 20);\n * }\n *
\n */\nclass Pulse extends Oscillator {\n constructor(freq, w) {\n super(freq, 'sawtooth');\n\n // width of PWM, should be betw 0 to 1.0\n this.w = w || 0;\n\n // create a second oscillator with inverse frequency\n this.osc2 = new SawOsc(freq);\n\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n\n // dc offset\n this.dcOffset = createDCOffset();\n this.dcGain = p5sound.audiocontext.createGain();\n this.dcOffset.connect(this.dcGain);\n this.dcGain.connect(this.output);\n // set delay time based on PWM width\n this.f = freq || 440;\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n\n // disconnect osc2 and connect it to delay, which is connected to output\n this.osc2.disconnect();\n this.osc2.panner.disconnect();\n this.osc2.amp(-1); // inverted amplitude\n this.osc2.output.connect(this.dNode);\n this.dNode.connect(this.output);\n\n this.output.gain.value = 1;\n this.output.connect(this.panner);\n }\n\n /**\n * Set the width of a Pulse object (an oscillator that implements\n * Pulse Width Modulation).\n *\n * @method width\n * @param {Number} [width] Width between the pulses (0 to 1.0,\n * defaults to 0)\n */\n width(w) {\n if (typeof w === 'number') {\n if (w <= 1.0 && w >= 0.0) {\n this.w = w;\n // set delay time based on PWM width\n\n // var mW = map(this.w, 0, 1.0, 0, 1/this.f);\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n }\n\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n } else {\n w.connect(this.dNode.delayTime);\n let sig = new Signal(-0.5); //repalce it with tones Signals Method\n w.connect(sig);\n let mult1 = new Multiply(-1);\n let mult2 = new Multiply(1.7);\n sig = sig.connect(mult1).connect(mult2);\n sig.connect(this.dcGain.gain);\n }\n }\n\n start(f, time) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.setValueAtTime(freq, now);\n this.oscillator.type = type;\n this.oscillator.connect(this.output);\n this.oscillator.start(t + now);\n\n // set up osc2\n this.osc2.oscillator = p5sound.audiocontext.createOscillator();\n this.osc2.oscillator.frequency.setValueAtTime(freq, t + now);\n this.osc2.oscillator.type = type;\n this.osc2.oscillator.connect(this.osc2.output);\n this.osc2.start(t + now);\n this.freqNode = [\n this.oscillator.frequency,\n this.osc2.oscillator.frequency,\n ];\n\n // start dcOffset, too\n this.dcOffset = createDCOffset();\n this.dcOffset.connect(this.dcGain);\n this.dcOffset.start(t + now);\n\n // if LFO connections depend on these oscillators\n if (this.mods !== undefined && this.mods.frequency !== undefined) {\n this.mods.frequency.connect(this.freqNode[0]);\n this.mods.frequency.connect(this.freqNode[1]);\n }\n this.started = true;\n this.osc2.started = true;\n }\n }\n\n stop(time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n if (this.osc2.oscillator) {\n this.osc2.oscillator.stop(t + now);\n }\n this.dcOffset.stop(t + now);\n this.started = false;\n this.osc2.started = false;\n }\n }\n\n freq(val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number') {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n var currentFreq = this.oscillator.frequency.value;\n this.oscillator.frequency.cancelScheduledValues(now);\n this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n this.osc2.oscillator.frequency.cancelScheduledValues(now);\n this.osc2.oscillator.frequency.setValueAtTime(\n currentFreq,\n now + tFromNow\n );\n this.osc2.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n\n if (this.freqMod) {\n this.freqMod.output.disconnect();\n this.freqMod = null;\n }\n } else if (val.output) {\n val.output.disconnect();\n val.output.connect(this.oscillator.frequency);\n val.output.connect(this.osc2.oscillator.frequency);\n this.freqMod = val;\n }\n }\n}\n\n// inspiration: http://webaudiodemos.appspot.com/oscilloscope/\nfunction createDCOffset() {\n var ac = p5sound.audiocontext;\n var buffer = ac.createBuffer(1, 2048, ac.sampleRate);\n var data = buffer.getChannelData(0);\n for (var i = 0; i < 2048; i++) data[i] = 1.0;\n var bufferSource = ac.createBufferSource();\n bufferSource.buffer = buffer;\n bufferSource.loop = true;\n return bufferSource;\n}\n\nexport default Pulse;\n","import p5sound from './master';\nimport Amplitude from './amplitude';\n\n// an array of input sources\np5sound.inputSources = [];\n\n/**\n *

Get audio from an input, i.e. your computer's microphone.

\n *\n *

Turn the mic on/off with the start() and stop() methods. When the mic\n * is on, its volume can be measured with getLevel or by connecting an\n * FFT object.

\n *\n *

If you want to hear the AudioIn, use the .connect() method.\n * AudioIn does not connect to p5.sound output by default to prevent\n * feedback.

\n *\n *

Note: This uses the getUserMedia/\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\n * is limited to localhost and https, but access over http may be limited.

\n *\n * @class p5.AudioIn\n * @constructor\n * @param {Function} [errorCallback] A function to call if there is an error\n * accessing the AudioIn. For example,\n * Safari and iOS devices do not\n * currently allow microphone access.\n * @example\n *
\n * let mic;\n *\n * function setup(){\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(useraudiocontextStartAudio);\n * textAlign(CENTER);\n * mic = new p5.AudioIn();\n * mic.start();\n * }\n *\n * function draw(){\n * background(0);\n * fill(255);\n * text('tap to start', width/2, 20);\n *\n * micLevel = mic.getLevel();\n * let y = height - micLevel * height;\n * ellipse(width/2, y, 10, 10);\n * }\n *
\n */\nclass AudioIn {\n constructor(errorCallback) {\n // set up audio input\n /**\n * @property {GainNode} input\n */\n this.input = p5sound.audiocontext.createGain();\n /**\n * @property {GainNode} output\n */\n this.output = p5sound.audiocontext.createGain();\n\n /**\n * @property {MediaStream|null} stream\n */\n this.stream = null;\n /**\n * @property {MediaStreamAudioSourceNode|null} mediaStream\n */\n this.mediaStream = null;\n /**\n * @property {Number|null} currentSource\n */\n this.currentSource = null;\n\n /**\n * Client must allow browser to access their microphone / audioin source.\n * Default: false. Will become true when the client enables access.\n *\n * @property {Boolean} enabled\n */\n this.enabled = false;\n\n /**\n * Input amplitude, connect to it by default but not to master out\n *\n * @property {p5.Amplitude} amplitude\n */\n this.amplitude = new Amplitude();\n this.output.connect(this.amplitude.input);\n\n if (\n !window.MediaStreamTrack ||\n !window.navigator.mediaDevices ||\n !window.navigator.mediaDevices.getUserMedia\n ) {\n errorCallback\n ? errorCallback()\n : window.alert(\n 'This browser does not support MediaStreamTrack and mediaDevices'\n );\n }\n\n // add to soundArray so we can dispose on close\n p5sound.soundArray.push(this);\n }\n /**\n * Start processing audio input. This enables the use of other\n * AudioIn methods like getLevel(). Note that by default, AudioIn\n * is not connected to p5.sound's output. So you won't hear\n * anything unless you use the connect() method.
\n *\n * Certain browsers limit access to the user's microphone. For example,\n * Chrome only allows access from localhost and over https. For this reason,\n * you may want to include an errorCallback—a function that is called in case\n * the browser won't provide mic access.\n *\n * @method start\n * @for p5.AudioIn\n * @param {Function} [successCallback] Name of a function to call on\n * success.\n * @param {Function} [errorCallback] Name of a function to call if\n * there was an error. For example,\n * some browsers do not support\n * getUserMedia.\n */\n start(successCallback, errorCallback) {\n var self = this;\n\n if (this.stream) {\n this.stop();\n }\n\n // set the audio source\n var audioSource = p5sound.inputSources[self.currentSource];\n var constraints = {\n audio: {\n sampleRate: p5sound.audiocontext.sampleRate,\n echoCancellation: false,\n },\n };\n\n // if developers determine which source to use\n if (p5sound.inputSources[this.currentSource]) {\n constraints.audio.deviceId = audioSource.deviceId;\n }\n\n window.navigator.mediaDevices\n .getUserMedia(constraints)\n .then(function (stream) {\n self.stream = stream;\n self.enabled = true;\n // Wrap a MediaStreamSourceNode around the live input\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\n self.mediaStream.connect(self.output);\n // only send to the Amplitude reader, so we can see it but not hear it.\n self.amplitude.setInput(self.output);\n if (successCallback) successCallback();\n })\n .catch(function (err) {\n if (errorCallback) errorCallback(err);\n else console.error(err);\n });\n }\n\n /**\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\n * If re-starting, the user may be prompted for permission access.\n *\n * @method stop\n * @for p5.AudioIn\n */\n stop() {\n if (this.stream) {\n this.stream.getTracks().forEach(function (track) {\n track.stop();\n });\n\n this.mediaStream.disconnect();\n\n delete this.mediaStream;\n delete this.stream;\n }\n }\n\n /**\n * Connect to an audio unit. If no parameter is provided, will\n * connect to the master output (i.e. your speakers).
\n *\n * @method connect\n * @for p5.AudioIn\n * @param {Object} [unit] An object that accepts audio input,\n * such as an FFT\n */\n connect(unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else if (unit.hasOwnProperty('analyser')) {\n this.output.connect(unit.analyser);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(p5sound.input);\n }\n }\n\n /**\n * Disconnect the AudioIn from all audio units. For example, if\n * connect() had been called, disconnect() will stop sending\n * signal to your speakers.
\n *\n * @method disconnect\n * @for p5.AudioIn\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n // stay connected to amplitude even if not outputting to p5\n this.output.connect(this.amplitude.input);\n }\n }\n\n /**\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\n * class contains its own instance of the Amplitude class to help\n * make it easy to get a microphone's volume level. Accepts an\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\n * .start() before using .getLevel().
\n *\n * @method getLevel\n * @for p5.AudioIn\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\n * Smooths values based on previous values.\n * @return {Number} Volume level (between 0.0 and 1.0)\n */\n getLevel(smoothing) {\n if (smoothing) {\n this.amplitude.smoothing = smoothing;\n }\n return this.amplitude.getLevel();\n }\n\n /**\n * Set amplitude (volume) of a mic input between 0 and 1.0.
\n *\n * @method amp\n * @for p5.AudioIn\n * @param {Number} vol between 0 and 1.0\n * @param {Number} [time] ramp time (optional)\n */\n amp(vol, t) {\n if (t) {\n var rampTime = t || 0;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(\n currentVol,\n p5sound.audiocontext.currentTime\n );\n this.output.gain.linearRampToValueAtTime(\n vol,\n rampTime + p5sound.audiocontext.currentTime\n );\n } else {\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\n }\n }\n\n /**\n * Returns a list of available input sources. This is a wrapper\n * for \n * MediaDevices.enumerateDevices() - Web APIs | MDN\n * and it returns a Promise.\n * @method getSources\n * @for p5.AudioIn\n * @param {Function} [successCallback] This callback function handles the sources when they\n * have been enumerated. The callback function\n * receives the deviceList array as its only argument\n * @param {Function} [errorCallback] This optional callback receives the error\n * message as its argument.\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\n * to the enumerateDevices() method\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\n getSources(onSuccess, onError) {\n return new Promise(function (resolve, reject) {\n window.navigator.mediaDevices\n .enumerateDevices()\n .then(function (devices) {\n p5sound.inputSources = devices.filter(function (device) {\n return device.kind === 'audioinput';\n });\n resolve(p5sound.inputSources);\n if (onSuccess) {\n onSuccess(p5sound.inputSources);\n }\n })\n .catch(function (error) {\n reject(error);\n if (onError) {\n onError(error);\n } else {\n console.error(\n 'This browser does not support MediaStreamTrack.getSources()'\n );\n }\n });\n });\n }\n\n /**\n * Set the input source. Accepts a number representing a\n * position in the array returned by getSources().\n * This is only available in browsers that support\n * \n * navigator.mediaDevices.enumerateDevices()\n *\n * @method setSource\n * @for p5.AudioIn\n * @param {number} num position of input source in the array\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\n setSource(num) {\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\n // set the current source\n this.currentSource = num;\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\n } else {\n console.log('unable to set input source');\n }\n\n // restart stream if currently active\n if (this.stream && this.stream.active) {\n this.start();\n }\n }\n\n // private method\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop();\n\n if (this.output) {\n this.output.disconnect();\n }\n if (this.amplitude) {\n this.amplitude.disconnect();\n }\n delete this.amplitude;\n delete this.output;\n }\n}\n\nexport default AudioIn;\n","import p5sound from './master';\nimport CrossFade from 'Tone/component/CrossFade.js';\n\n/**\n * Effect is a base class for audio effects in p5.
\n * This module handles the nodes and methods that are\n * common and useful for current and future effects.\n *\n *\n * This class is extended by p5.Distortion,\n * p5.Compressor,\n * p5.Delay,\n * p5.Filter,\n * p5.Reverb.\n *\n * @class p5.Effect\n * @constructor\n *\n * @param {Object} [ac] Reference to the audio context of the p5 object\n * @param {AudioNode} [input] Gain Node effect wrapper\n * @param {AudioNode} [output] Gain Node effect wrapper\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\n * @param {AudioNode} [wet] Effects that extend this class should connect\n * to the wet signal to this gain node, so that dry and wet\n * signals are mixed properly.\n */\nclass Effect {\n constructor() {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n /**\n *\tThe p5.Effect class is built\n * \tusing Tone.js CrossFade\n * \t@private\n */\n\n this._drywet = new CrossFade(1);\n\n /**\n *\tIn classes that extend\n *\tp5.Effect, connect effect nodes\n *\tto the wet parameter\n */\n this.wet = this.ac.createGain();\n\n this.input.connect(this._drywet.a);\n this.wet.connect(this._drywet.b);\n this._drywet.connect(this.output);\n\n this.connect();\n\n //Add to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Set the output volume of the filter.\n *\n * @method amp\n * @for p5.Effect\n * @param {Number} [vol] amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts until rampTime\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\n */\n amp(vol, rampTime = 0, tFromNow = 0) {\n const now = p5sound.audiocontext.currentTime;\n const startTime = now + tFromNow;\n const endTime = startTime + rampTime + 0.001;\n const currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, startTime + 0.001);\n this.output.gain.linearRampToValueAtTime(vol, endTime);\n }\n\n /**\n * Link effects together in a chain\n * Example usage: filter.chain(reverb, delay, panner);\n * May be used with an open-ended number of arguments\n *\n * @method chain\n * @for p5.Effect\n * @param {Object} [arguments] Chain together multiple sound objects\n */\n chain() {\n if (arguments.length > 0) {\n this.connect(arguments[0]);\n for (var i = 1; i < arguments.length; i += 1) {\n arguments[i - 1].connect(arguments[i]);\n }\n }\n return this;\n }\n\n /**\n * Adjust the dry/wet value.\n *\n * @method drywet\n * @for p5.Effect\n * @param {Number} [fade] The desired drywet value (0 - 1.0)\n */\n drywet() {\n if (typeof fade !== 'undefined') {\n this._drywet.fade.value = fade;\n }\n return this._drywet.fade.value;\n }\n\n /**\n * Send output to a p5.js-sound, Web Audio Node, or use signal to\n * control an AudioParam\n *\n * @method connect\n * @for p5.Effect\n * @param {Object} unit\n */\n connect(unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all output.\n * @method disconnect\n * @for p5.Effect\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n dispose() {\n // remove refernce form soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n if (this._drywet) {\n this._drywet.disconnect();\n delete this._drywet;\n }\n\n if (this.wet) {\n this.wet.disconnect();\n delete this.wet;\n }\n\n this.ac = undefined;\n }\n}\n\nexport default Effect;\n","import Effect from './effect';\n\n/**\n *

A p5.Filter uses a Web Audio Biquad Filter to filter\n * the frequency response of an input source. Subclasses\n * include:

\n * p5.LowPass:\n * Allows frequencies below the cutoff frequency to pass through,\n * and attenuates frequencies above the cutoff.
\n * p5.HighPass:\n * The opposite of a lowpass filter.
\n * p5.BandPass:\n * Allows a range of frequencies to pass through and attenuates\n * the frequencies below and above this frequency range.
\n *\n * The .res() method controls either width of the\n * bandpass, or resonance of the low/highpass cutoff frequency.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Filter\n * @extends p5.Effect\n * @constructor\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\n * @example\n *
\n * let fft, noise, filter;\n *\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(makeNoise);\n * fill(255, 0, 255);\n *\n * filter = new p5.BandPass();\n * noise = new p5.Noise();\n * noise.disconnect();\n * noise.connect(filter);\n *\n * fft = new p5.FFT();\n * }\n *\n * function draw() {\n * background(220);\n *\n * // set the BandPass frequency based on mouseX\n * let freq = map(mouseX, 0, width, 20, 10000);\n * freq = constrain(freq, 0, 22050);\n * filter.freq(freq);\n * // give the filter a narrow band (lower res = wider bandpass)\n * filter.res(50);\n *\n * // draw filtered spectrum\n * let spectrum = fft.analyze();\n * noStroke();\n * for (let i = 0; i < spectrum.length; i++) {\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width/spectrum.length, h);\n * }\n * if (!noise.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text('Frequency: ' + round(freq)+'Hz', 20, 20, width - 20);\n * }\n * }\n *\n * function makeNoise() {\n * // see also: `userStartAudio()`\n * noise.start();\n * noise.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * noise.amp(0, 0.2);\n * }\n *\n *
\n */\nclass Filter extends Effect {\n constructor(type) {\n super();\n //add extend Effect by adding a Biquad Filter\n\n /**\n * The p5.Filter is built with a\n * \n * Web Audio BiquadFilter Node.\n *\n * @property {DelayNode} biquadFilter\n */\n\n this.biquad = this.ac.createBiquadFilter();\n\n this.input.connect(this.biquad);\n\n this.biquad.connect(this.wet);\n\n if (type) {\n this.setType(type);\n }\n\n //Properties useful for the toggle method.\n this._on = true;\n this._untoggledType = this.biquad.type;\n }\n\n /**\n * Filter an audio signal according to a set\n * of filter parameters.\n *\n * @method process\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance/Width of the filter frequency\n * from 0.001 to 1000\n */\n process(src, freq, res, time) {\n src.connect(this.input);\n this.set(freq, res, time);\n }\n\n /**\n * Set the frequency and the resonance of the filter.\n *\n * @method set\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n set(freq, res, time) {\n if (freq) {\n this.freq(freq, time);\n }\n if (res) {\n this.res(res, time);\n }\n }\n\n /**\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\n * human hearing, although in reality most people hear in a narrower\n * range).\n *\n * @method freq\n * @param {Number} freq Filter Frequency\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current frequency value\n */\n freq(freq, time) {\n var t = time || 0;\n if (freq <= 0) {\n freq = 1;\n }\n if (typeof freq === 'number') {\n this.biquad.frequency.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.biquad.frequency.exponentialRampToValueAtTime(\n freq,\n this.ac.currentTime + 0.02 + t\n );\n } else if (freq) {\n freq.connect(this.biquad.frequency);\n }\n return this.biquad.frequency.value;\n }\n\n /**\n * Controls either width of a bandpass frequency,\n * or the resonance of a low/highpass cutoff frequency.\n *\n * @method res\n * @param {Number} res Resonance/Width of filter freq\n * from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current res value\n */\n res(res, time) {\n var t = time || 0;\n if (typeof res === 'number') {\n this.biquad.Q.value = res;\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.Q.linearRampToValueAtTime(\n res,\n this.ac.currentTime + 0.02 + t\n );\n } else if (res) {\n res.connect(this.biquad.Q);\n }\n return this.biquad.Q.value;\n }\n\n /**\n * Controls the gain attribute of a Biquad Filter.\n * This is distinctly different from .amp() which is inherited from p5.Effect\n * .amp() controls the volume via the output gain node\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\n *\n * @method gain\n * @param {Number} gain\n * @return {Number} Returns the current or updated gain value\n */\n gain(gain, time) {\n var t = time || 0;\n if (typeof gain === 'number') {\n this.biquad.gain.value = gain;\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.gain.linearRampToValueAtTime(\n gain,\n this.ac.currentTime + 0.02 + t\n );\n } else if (gain) {\n gain.connect(this.biquad.gain);\n }\n return this.biquad.gain.value;\n }\n\n /**\n * Toggle function. Switches between the specified type and allpass\n *\n * @method toggle\n * @return {boolean} [Toggle value]\n */\n toggle() {\n this._on = !this._on;\n\n if (this._on === true) {\n this.biquad.type = this._untoggledType;\n } else if (this._on === false) {\n this.biquad.type = 'allpass';\n }\n\n return this._on;\n }\n\n /**\n * Set the type of a p5.Filter. Possible types include:\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\n * \"allpass\".\n *\n * @method setType\n * @param {String} t\n */\n setType(t) {\n this.biquad.type = t;\n this._untoggledType = this.biquad.type;\n }\n\n dispose() {\n // remove reference from soundArray\n super.dispose();\n if (this.biquad) {\n this.biquad.disconnect();\n delete this.biquad;\n }\n }\n}\n\n/**\n * Constructor: new p5.LowPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('lowpass').\n * See p5.Filter for methods.\n *\n * @class p5.LowPass\n * @constructor\n * @extends p5.Filter\n */\nclass LowPass extends Filter {\n constructor() {\n super('lowpass');\n }\n}\n\n/**\n * Constructor: new p5.HighPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('highpass').\n * See p5.Filter for methods.\n *\n * @class p5.HighPass\n * @constructor\n * @extends p5.Filter\n */\nclass HighPass extends Filter {\n constructor() {\n super('highpass');\n }\n}\n\n/**\n * Constructor: new p5.BandPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('bandpass').\n * See p5.Filter for methods.\n *\n * @class p5.BandPass\n * @constructor\n * @extends p5.Filter\n */\nclass BandPass extends Filter {\n constructor() {\n super('bandpass');\n }\n}\nexport default Filter;\nexport { LowPass, HighPass, BandPass };\n","import Filter from './filter';\nimport p5sound from './master';\n\n/**\n * EQFilter extends p5.Filter with constraints\n * necessary for the p5.EQ\n *\n * @private\n */\nclass EQFilter extends Filter {\n constructor(freq, res) {\n super('peaking');\n\n this.disconnect();\n this.set(freq, res);\n this.biquad.gain.value = 0;\n delete this.input;\n delete this.output;\n delete this._drywet;\n delete this.wet;\n }\n\n amp() {\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\n }\n\n drywet() {\n console.warn('`drywet()` is not available for p5.EQ bands.');\n }\n\n connect(unit) {\n var u = unit || p5.soundOut.input;\n if (this.biquad) {\n this.biquad.connect(u.input ? u.input : u);\n } else {\n this.output.connect(u.input ? u.input : u);\n }\n }\n disconnect() {\n if (this.biquad) {\n this.biquad.disconnect();\n }\n }\n\n dispose() {\n // remove reference form soundArray\n const index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n this.disconnect();\n delete this.biquad;\n }\n}\n\nexport default EQFilter;\n","import Effect from './effect';\nimport EQFilter from './eqFilter';\n\n/**\n * p5.EQ is an audio effect that performs the function of a multiband\n * audio equalizer. Equalization is used to adjust the balance of\n * frequency compoenents of an audio signal. This process is commonly used\n * in sound production and recording to change the waveform before it reaches\n * a sound output device. EQ can also be used as an audio effect to create\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\n * built using a chain of Web Audio Biquad Filter Nodes and can be\n * instantiated with 3 or 8 bands. Bands can be added or removed from\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.EQ\n * @constructor\n * @extends p5.Effect\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\n * @return {Object} p5.EQ object\n *\n * @example\n *
\n * let eq, soundFile\n * let eqBandIndex = 0;\n * let eqBandNames = ['lows', 'mids', 'highs'];\n *\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * soundFile = loadSound('assets/beat');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(toggleSound);\n *\n * eq = new p5.EQ(eqBandNames.length);\n * soundFile.disconnect();\n * eq.process(soundFile);\n * }\n *\n * function draw() {\n * background(30);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n * text('filtering ', 50, 25);\n *\n * fill(255, 40, 255);\n * textSize(26);\n * text(eqBandNames[eqBandIndex], 50, 55);\n *\n * fill(255);\n * textSize(9);\n *\n * if (!soundFile.isPlaying()) {\n * text('tap to play', 50, 80);\n * } else {\n * text('tap to filter next band', 50, 80)\n * }\n * }\n *\n * function toggleSound() {\n * if (!soundFile.isPlaying()) {\n * soundFile.play();\n * } else {\n * eqBandIndex = (eqBandIndex + 1) % eq.bands.length;\n * }\n *\n * for (let i = 0; i < eq.bands.length; i++) {\n * eq.bands[i].gain(0);\n * }\n * // filter the band we want to filter\n * eq.bands[eqBandIndex].gain(-40);\n * }\n *
\n */\nclass EQ extends Effect {\n constructor(_eqsize) {\n super();\n\n //p5.EQ can be of size (3) or (8), defaults to 3\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\n\n var factor;\n _eqsize === 3 ? (factor = Math.pow(2, 3)) : (factor = 2);\n\n /**\n * The p5.EQ is built with abstracted p5.Filter objects.\n * To modify any bands, use methods of the \n * p5.Filter API, especially `gain` and `freq`.\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\n * @property {Array} bands\n *\n */\n this.bands = [];\n\n var freq, res;\n for (var i = 0; i < _eqsize; i++) {\n if (i === _eqsize - 1) {\n freq = 21000;\n res = 0.01;\n } else if (i === 0) {\n freq = 100;\n res = 0.1;\n } else if (i === 1) {\n freq = _eqsize === 3 ? 360 * factor : 360;\n res = 1;\n } else {\n freq = this.bands[i - 1].freq() * factor;\n res = 1;\n }\n this.bands[i] = this._newBand(freq, res);\n\n if (i > 0) {\n this.bands[i - 1].connect(this.bands[i].biquad);\n } else {\n this.input.connect(this.bands[i].biquad);\n }\n }\n this.bands[_eqsize - 1].connect(this.output);\n }\n\n /**\n * Process an input by connecting it to the EQ\n * @method process\n * @param {Object} src Audio source\n */\n process(src) {\n src.connect(this.input);\n }\n\n // /**\n // * Set the frequency and gain of each band in the EQ. This method should be\n // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\n // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\n // *\n // * @method set\n // * @for p5.EQ\n // * @param {Number} [freq0] Frequency value for band with index 0\n // * @param {Number} [gain0] Gain value for band with index 0\n // * @param {Number} [freq1] Frequency value for band with index 1\n // * @param {Number} [gain1] Gain value for band with index 1\n // * @param {Number} [freq2] Frequency value for band with index 2\n // * @param {Number} [gain2] Gain value for band with index 2\n // * @param {Number} [freq3] Frequency value for band with index 3\n // * @param {Number} [gain3] Gain value for band with index 3\n // * @param {Number} [freq4] Frequency value for band with index 4\n // * @param {Number} [gain4] Gain value for band with index 4\n // * @param {Number} [freq5] Frequency value for band with index 5\n // * @param {Number} [gain5] Gain value for band with index 5\n // * @param {Number} [freq6] Frequency value for band with index 6\n // * @param {Number} [gain6] Gain value for band with index 6\n // * @param {Number} [freq7] Frequency value for band with index 7\n // * @param {Number} [gain7] Gain value for band with index 7\n // */\n set() {\n if (arguments.length === this.bands.length * 2) {\n for (var i = 0; i < arguments.length; i += 2) {\n this.bands[i / 2].freq(arguments[i]);\n this.bands[i / 2].gain(arguments[i + 1]);\n }\n } else {\n console.error(\n 'Argument mismatch. .set() should be called with ' +\n this.bands.length * 2 +\n ' arguments. (one frequency and gain value pair for each band of the eq)'\n );\n }\n }\n\n /**\n * Add a new band. Creates a p5.Filter and strips away everything but\n * the raw biquad filter. This method returns an abstracted p5.Filter,\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\n * @private\n * @for p5.EQ\n * @method _newBand\n * @param {Number} freq\n * @param {Number} res\n * @return {Object} Abstracted Filter\n */\n _newBand(freq, res) {\n return new EQFilter(freq, res);\n }\n\n dispose() {\n super.dispose();\n\n if (this.bands) {\n while (this.bands.length > 0) {\n delete this.bands.pop().dispose();\n }\n delete this.bands;\n }\n }\n}\nexport default EQ;\n","import p5sound from './master';\n\n// /**\n// * listener is a class that can construct both a Spatial Panner\n// * and a Spatial Listener. The panner is based on the\n// * Web Audio Spatial Panner Node\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\n// * This panner is a spatial processing node that allows audio to be positioned\n// * and oriented in 3D space.\n// *\n// * The Listener modifies the properties of the Audio Context Listener.\n// * Both objects types use the same methods. The default is a spatial panner.\n// *\n// * p5.Panner3D - Constructs a Spatial Panner
\n// * p5.Listener3D - Constructs a Spatial Listener
\n// *\n// * @class listener\n// * @constructor\n// * @return {Object} p5.Listener3D Object\n// *\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\n// */\n\nclass Listener3D {\n constructor(type) {\n this.ac = p5sound.audiocontext;\n this.listener = this.ac.listener;\n }\n\n // /**\n // * Connect an audio sorce\n // * @param {Object} src Input source\n // */\n process(src) {\n src.connect(this.input);\n }\n // /**\n // * Set the X,Y,Z position of the Panner\n // * @param {[Number]} xVal\n // * @param {[Number]} yVal\n // * @param {[Number]} zVal\n // * @param {[Number]} time\n // * @return {[Array]} [Updated x, y, z values as an array]\n // */\n position(xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.listener.positionX.value,\n this.listener.positionY.value,\n this.listener.positionZ.value,\n ];\n }\n\n // /**\n // * Getter and setter methods for position coordinates\n // * @return {Number} [updated coordinate value]\n // */\n positionX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.positionX.value = xVal;\n this.listener.positionX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.positionX);\n }\n return this.listener.positionX.value;\n }\n positionY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.positionY.value = yVal;\n this.listener.positionY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.positionY);\n }\n return this.listener.positionY.value;\n }\n positionZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.positionZ.value = zVal;\n this.listener.positionZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.positionZ);\n }\n return this.listener.positionZ.value;\n }\n\n // cannot define method when class definition is commented\n // /**\n // * Overrides the listener orient() method because Listener has slightly\n // * different params. In human terms, Forward vectors are the direction the\n // * nose is pointing. Up vectors are the direction of the top of the head.\n // *\n // * @method orient\n // * @param {Number} xValF Forward vector X direction\n // * @param {Number} yValF Forward vector Y direction\n // * @param {Number} zValF Forward vector Z direction\n // * @param {Number} xValU Up vector X direction\n // * @param {Number} yValU Up vector Y direction\n // * @param {Number} zValU Up vector Z direction\n // * @param {Number} time\n // * @return {Array} All orienation params\n // */\n orient(xValF, yValF, zValF, xValU, yValU, zValU, time) {\n if (arguments.length === 3 || arguments.length === 4) {\n time = arguments[3];\n this.orientForward(xValF, yValF, zValF, time);\n } else if (arguments.length === 6 || arguments === 7) {\n this.orientForward(xValF, yValF, zValF);\n this.orientUp(xValU, yValU, zValU, time);\n }\n\n return [\n this.listener.forwardX.value,\n this.listener.forwardY.value,\n this.listener.forwardZ.value,\n this.listener.upX.value,\n this.listener.upY.value,\n this.listener.upZ.value,\n ];\n }\n\n orientForward(xValF, yValF, zValF, time) {\n this.forwardX(xValF, time);\n this.forwardY(yValF, time);\n this.forwardZ(zValF, time);\n\n return [\n this.listener.forwardX,\n this.listener.forwardY,\n this.listener.forwardZ,\n ];\n }\n\n orientUp(xValU, yValU, zValU, time) {\n this.upX(xValU, time);\n this.upY(yValU, time);\n this.upZ(zValU, time);\n\n return [this.listener.upX, this.listener.upY, this.listener.upZ];\n }\n // /**\n // * Getter and setter methods for orient coordinates\n // * @return {Number} [updated coordinate value]\n // */\n forwardX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.forwardX.value = xVal;\n this.listener.forwardX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.forwardX);\n }\n return this.listener.forwardX.value;\n }\n forwardY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.forwardY.value = yVal;\n this.listener.forwardY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.forwardY);\n }\n return this.listener.forwardY.value;\n }\n forwardZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.forwardZ.value = zVal;\n this.listener.forwardZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.forwardZ);\n }\n return this.listener.forwardZ.value;\n }\n upX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.upX.value = xVal;\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.upX);\n }\n return this.listener.upX.value;\n }\n upY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.upY.value = yVal;\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.upY);\n }\n return this.listener.upY.value;\n }\n upZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.upZ.value = zVal;\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.upZ);\n }\n return this.listener.upZ.value;\n }\n}\n\nexport default Listener3D;\n","import Effect from './effect';\n\n/**\n * Panner3D is based on the \n * Web Audio Spatial Panner Node.\n * This panner is a spatial processing node that allows audio to be positioned\n * and oriented in 3D space.\n *\n * The position is relative to an \n * Audio Context Listener, which can be accessed\n * by p5.soundOut.audiocontext.listener\n *\n *\n * @class p5.Panner3D\n * @constructor\n */\n\nclass Panner3D extends Effect {\n constructor() {\n super();\n /**\n * \n * Web Audio Spatial Panner Node\n *\n * Properties include
\n * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType)\n * : \"equal power\" or \"HRTF\"
\n * [DistanceModel](https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType)\n * : \"linear\", \"inverse\", or \"exponential\"\n *\n * @property {AudioNode} panner\n *\n */\n this.panner = this.ac.createPanner();\n this.panner.panningModel = 'HRTF';\n this.panner.distanceModel = 'linear';\n this.panner.connect(this.output);\n this.input.connect(this.panner);\n }\n\n /**\n * Connect an audio sorce\n *\n * @method process\n * @for p5.Panner3D\n * @param {Object} src Input source\n */\n process(src) {\n src.connect(this.input);\n }\n /**\n * Set the X,Y,Z position of the Panner\n * @method set\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\n set(xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.panner.positionX.value,\n this.panner.positionY.value,\n this.panner.positionZ.value,\n ];\n }\n\n /**\n * Getter and setter methods for position coordinates\n * @method positionX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for position coordinates\n * @method positionY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for position coordinates\n * @method positionZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n positionX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.positionX.value = xVal;\n this.panner.positionX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.positionX);\n }\n return this.panner.positionX.value;\n }\n positionY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.positionY.value = yVal;\n this.panner.positionY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.positionY);\n }\n return this.panner.positionY.value;\n }\n positionZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.positionZ.value = zVal;\n this.panner.positionZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.positionZ);\n }\n return this.panner.positionZ.value;\n }\n\n /**\n * Set the X,Y,Z position of the Panner\n * @method orient\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\n orient(xVal, yVal, zVal, time) {\n this.orientX(xVal, time);\n this.orientY(yVal, time);\n this.orientZ(zVal, time);\n return [\n this.panner.orientationX.value,\n this.panner.orientationY.value,\n this.panner.orientationZ.value,\n ];\n }\n\n /**\n * Getter and setter methods for orient coordinates\n * @method orientX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for orient coordinates\n * @method orientY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for orient coordinates\n * @method orientZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n orientX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.orientationX.value = xVal;\n this.panner.orientationX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.orientationX);\n }\n return this.panner.orientationX.value;\n }\n orientY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.orientationY.value = yVal;\n this.panner.orientationY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.orientationY);\n }\n return this.panner.orientationY.value;\n }\n orientZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.orientationZ.value = zVal;\n this.panner.orientationZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.orientationZ);\n }\n return this.panner.orientationZ.value;\n }\n\n /**\n * Set the rolloff factor and max distance\n * @method setFalloff\n * @for p5.Panner3D\n * @param {Number} [maxDistance]\n * @param {Number} [rolloffFactor]\n */\n setFalloff(maxDistance, rolloffFactor) {\n this.maxDist(maxDistance);\n this.rolloff(rolloffFactor);\n }\n /**\n * Maxium distance between the source and the listener\n * @method maxDist\n * @for p5.Panner3D\n * @param {Number} maxDistance\n * @return {Number} updated value\n */\n maxDist(maxDistance) {\n if (typeof maxDistance === 'number') {\n this.panner.maxDistance = maxDistance;\n }\n return this.panner.maxDistance;\n }\n\n /**\n * How quickly the volume is reduced as the source moves away from the listener\n * @method rollof\n * @for p5.Panner3D\n * @param {Number} rolloffFactor\n * @return {Number} updated value\n */\n rolloff(rolloffFactor) {\n if (typeof rolloffFactor === 'number') {\n this.panner.rolloffFactor = rolloffFactor;\n }\n return this.panner.rolloffFactor;\n }\n\n dispose() {\n super.dispose();\n if (this.panner) {\n this.panner.disconnect();\n delete this.panner;\n }\n }\n}\n\nexport default Panner3D;\n","import Filter from './filter';\nimport Effect from './effect';\n\n/**\n * Delay is an echo effect. It processes an existing sound source,\n * and outputs a delayed version of that sound. The p5.Delay can\n * produce different effects depending on the delayTime, feedback,\n * filter, and type. In the example below, a feedback of 0.5 (the\n * default value) will produce a looping delay that decreases in\n * volume by 50% each repeat. A filter will cut out the high\n * frequencies so that the delay does not sound as piercing as the\n * original source.\n *\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n * @class p5.Delay\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * osc = new p5.Oscillator('square');\n * osc.amp(0.5);\n * delay = new p5.Delay();\n *\n * // delay.process() accepts 4 parameters:\n * // source, delayTime (in seconds), feedback, filter frequency\n * delay.process(osc, 0.12, .7, 2300);\n *\n * cnv.mousePressed(oscStart);\n * }\n *\n * function oscStart() {\n * osc.start();\n * }\n *\n * function mouseReleased() {\n * osc.stop();\n * }\n *
\n */\nclass Delay extends Effect {\n constructor() {\n super();\n\n this._split = this.ac.createChannelSplitter(2);\n this._merge = this.ac.createChannelMerger(2);\n\n this._leftGain = this.ac.createGain();\n this._rightGain = this.ac.createGain();\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n *\n * @for p5.Delay\n * @property {DelayNode} leftDelay\n */\n this.leftDelay = this.ac.createDelay();\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n * @for p5.Delay\n * @property {DelayNode} rightDelay\n */\n this.rightDelay = this.ac.createDelay();\n\n this._leftFilter = new Filter();\n this._rightFilter = new Filter();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\n this._rightFilter.biquad.frequency.setValueAtTime(\n 1200,\n this.ac.currentTime\n );\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n\n // graph routing\n this.input.connect(this._split);\n this.leftDelay.connect(this._leftGain);\n this.rightDelay.connect(this._rightGain);\n this._leftGain.connect(this._leftFilter.input);\n this._rightGain.connect(this._rightFilter.input);\n this._merge.connect(this.wet);\n\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n\n // default routing\n this.setType(0);\n\n this._maxDelay = this.leftDelay.delayTime.maxValue;\n\n // set initial feedback to 0.5\n this.feedback(0.5);\n }\n /**\n * Add delay to an audio signal according to a set\n * of delay parameters.\n *\n * @method process\n * @for p5.Delay\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\n * Some browsers limit delayTime to\n * 1 second.\n * @param {Number} [feedback] sends the delay back through itself\n * in a loop that decreases in volume\n * each time.\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\n * below the lowPass will be part of the\n * delay.\n */\n process(src, _delayTime, _feedback, _filter) {\n var feedback = _feedback || 0;\n var delayTime = _delayTime || 0;\n if (feedback >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n }\n if (delayTime >= this._maxDelay) {\n throw new Error(\n 'Delay Time exceeds maximum delay time of ' +\n this._maxDelay +\n ' second.'\n );\n }\n\n src.connect(this.input);\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this._leftGain.gain.value = feedback;\n this._rightGain.gain.value = feedback;\n\n if (_filter) {\n this._leftFilter.freq(_filter);\n this._rightFilter.freq(_filter);\n }\n }\n\n /**\n * Set the delay (echo) time, in seconds. Usually this value will be\n * a floating point number between 0.0 and 1.0.\n *\n * @method delayTime\n * @for p5.Delay\n * @param {Number} delayTime Time (in seconds) of the delay\n */\n delayTime(t) {\n // if t is an audio node...\n if (typeof t !== 'number') {\n t.connect(this.leftDelay.delayTime);\n t.connect(this.rightDelay.delayTime);\n } else {\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n }\n }\n\n /**\n * Feedback occurs when Delay sends its signal back through its input\n * in a loop. The feedback amount determines how much signal to send each\n * time through the loop. A feedback greater than 1.0 is not desirable because\n * it will increase the overall output each time through the loop,\n * creating an infinite feedback loop. The default value is 0.5\n *\n * @method feedback\n * @for p5.Delay\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\n * Oscillator that can be used to\n * modulate this param\n * @returns {Number} Feedback value\n *\n */\n feedback(f) {\n // if f is an audio node...\n if (f && typeof f !== 'number') {\n f.connect(this._leftGain.gain);\n f.connect(this._rightGain.gain);\n } else if (f >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n } else if (typeof f === 'number') {\n this._leftGain.gain.value = f;\n this._rightGain.gain.value = f;\n }\n\n // return value of feedback\n return this._leftGain.gain.value;\n }\n\n /**\n * Set a lowpass filter frequency for the delay. A lowpass filter\n * will cut off any frequencies higher than the filter frequency.\n *\n * @method filter\n * @for p5.Delay\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\n * frequencies higher than the filter frequency.\n * @param {Number|Object} res Resonance of the filter frequency\n * cutoff, or an object (i.e. a p5.Oscillator)\n * that can be used to modulate this parameter.\n * High numbers (i.e. 15) will produce a resonance,\n * low numbers (i.e. .2) will produce a slope.\n */\n filter(freq, q) {\n this._leftFilter.set(freq, q);\n this._rightFilter.set(freq, q);\n }\n\n /**\n * Choose a preset type of delay. 'pingPong' bounces the signal\n * from the left to the right channel to produce a stereo effect.\n * Any other parameter will revert to the default delay setting.\n *\n * @method setType\n * @for p5.Delay\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\n */\n setType(t) {\n if (t === 1) {\n t = 'pingPong';\n }\n this._split.disconnect();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n this._split.connect(this.leftDelay, 0);\n this._split.connect(this.rightDelay, 1);\n switch (t) {\n case 'pingPong':\n this._rightFilter.setType(this._leftFilter.biquad.type);\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.rightDelay);\n this._rightFilter.output.connect(this.leftDelay);\n break;\n default:\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.leftDelay);\n this._rightFilter.output.connect(this.rightDelay);\n }\n }\n\n // DocBlocks for methods inherited from p5.Effect\n /**\n * Set the output level of the delay effect.\n *\n * @method amp\n * @for p5.Delay\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n /**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Delay\n * @param {Object} unit\n */\n /**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Delay\n */\n\n dispose() {\n super.dispose();\n\n this._split.disconnect();\n this._leftFilter.dispose();\n this._rightFilter.dispose();\n this._merge.disconnect();\n this._leftGain.disconnect();\n this._rightGain.disconnect();\n this.leftDelay.disconnect();\n this.rightDelay.disconnect();\n\n this._split = undefined;\n this._leftFilter = undefined;\n this._rightFilter = undefined;\n this._merge = undefined;\n this._leftGain = undefined;\n this._rightGain = undefined;\n this.leftDelay = undefined;\n this.rightDelay = undefined;\n }\n}\n\nexport default Delay;\n","import { getAudioContext } from './audiocontext';\nimport CustomError from './errorHandler';\nimport Effect from './effect';\n\n/**\n * Reverb adds depth to a sound through a large number of decaying\n * echoes. It creates the perception that sound is occurring in a\n * physical space. The p5.Reverb has paramters for Time (how long does the\n * reverb last) and decayRate (how much the sound decays with each echo)\n * that can be set with the .set() or .process() methods. The p5.Convolver\n * extends p5.Reverb allowing you to recreate the sound of actual physical\n * spaces through convolution.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Reverb\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let soundFile, reverb;\n * function preload() {\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * reverb = new p5.Reverb();\n * soundFile.disconnect(); // so we'll only hear reverb...\n *\n * // connect soundFile to reverb, process w/\n * // 3 second reverbTime, decayRate of 2%\n * reverb.process(soundFile, 3, 2);\n * }\n *\n * function draw() {\n * let dryWet = constrain(map(mouseX, 0, width, 0, 1), 0, 1);\n * // 1 = all reverb, 0 = no reverb\n * reverb.drywet(dryWet);\n *\n * background(220);\n * text('tap to play', 10, 20);\n * text('dry/wet: ' + round(dryWet * 100) + '%', 10, height - 20);\n * }\n *\n * function playSound() {\n * soundFile.play();\n * }\n *
\n */\n\nclass Reverb extends Effect {\n constructor() {\n super();\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n // default params\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n }\n\n _initConvolverNode() {\n this.convolverNode = this.ac.createConvolver();\n this.input.connect(this.convolverNode);\n this.convolverNode.connect(this.wet);\n }\n\n _teardownConvolverNode() {\n if (this.convolverNode) {\n this.convolverNode.disconnect();\n delete this.convolverNode;\n }\n }\n\n _setBuffer(audioBuffer) {\n this._teardownConvolverNode();\n this._initConvolverNode();\n this.convolverNode.buffer = audioBuffer;\n }\n /**\n * Connect a source to the reverb, and assign reverb parameters.\n *\n * @method process\n * @for p5.Reverb\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\n process(src, seconds, decayRate, reverse) {\n src.connect(this.input);\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n }\n\n /**\n * Set the reverb settings. Similar to .process(), but without\n * assigning a new input.\n *\n * @method set\n * @for p5.Reverb\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\n set(seconds, decayRate, reverse) {\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n }\n\n // DocBlocks for methods inherited from p5.Effect\n /**\n * Set the output level of the reverb effect.\n *\n * @method amp\n * @for p5.Reverb\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n /**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Reverb\n * @param {Object} unit\n */\n /**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Reverb\n */\n\n /**\n * Inspired by Simple Reverb by Jordan Santell\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\n *\n * Utility function for building an impulse response\n * based on the module parameters.\n *\n * @private\n */\n _buildImpulse() {\n var rate = this.ac.sampleRate;\n var length = rate * this._seconds;\n var decay = this._decay;\n var impulse = this.ac.createBuffer(2, length, rate);\n var impulseL = impulse.getChannelData(0);\n var impulseR = impulse.getChannelData(1);\n var n, i;\n for (i = 0; i < length; i++) {\n n = this._reverse ? length - i : i;\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n }\n this._setBuffer(impulse);\n }\n\n dispose() {\n super.dispose();\n this._teardownConvolverNode();\n }\n}\n\n// =======================================================================\n// *** p5.Convolver ***\n// =======================================================================\n\n/**\n *

p5.Convolver extends p5.Reverb. It can emulate the sound of real\n * physical spaces through a process called \n * convolution.

\n *\n *

Convolution multiplies any audio input by an \"impulse response\"\n * to simulate the dispersion of sound over time. The impulse response is\n * generated from an audio file that you provide. One way to\n * generate an impulse response is to pop a balloon in a reverberant space\n * and record the echo. Convolution can also be used to experiment with\n * sound.

\n *\n *

Use the method createConvolution(path) to instantiate a\n * p5.Convolver with a path to your impulse response audio file.

\n *\n * @class p5.Convolver\n * @extends p5.Effect\n * @constructor\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call when loading succeeds\n * @param {Function} [errorCallback] function to call if loading fails.\n * This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\nclass Convolver extends Reverb {\n constructor(path, callback, errorCallback) {\n super();\n /**\n * Internally, the p5.Convolver uses the a\n * \n * Web Audio Convolver Node.\n *\n * @property {ConvolverNode} convolverNode\n */\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n if (path) {\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n } else {\n // parameters\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n }\n\n /**\n * If you load multiple impulse files using the .addImpulse method,\n * they will be stored as Objects in this Array. Toggle between them\n * with the toggleImpulse(id) method.\n *\n * @property {Array} impulses\n * @for p5.Convolver\n */\n this.impulses = [];\n this.set = null;\n }\n\n /**\n * Private method to load a buffer as an Impulse Response,\n * assign it to the convolverNode, and add to the Array of .impulses.\n *\n * @param {String} path\n * @param {Function} callback\n * @param {Function} errorCallback\n * @private\n */\n _loadBuffer(_path, callback, errorCallback) {\n var path = p5.prototype._checkFileFormats(_path);\n var self = this;\n var errorTrace = new Error().stack;\n var ac = getAudioContext();\n\n var request = new XMLHttpRequest();\n request.open('GET', path, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on success loading file:\n ac.decodeAudioData(\n request.response,\n function (buff) {\n var buffer = {};\n var chunks = path.split('/');\n buffer.name = chunks[chunks.length - 1];\n buffer.audioBuffer = buff;\n self.impulses.push(buffer);\n self._setBuffer(buffer.audioBuffer);\n if (callback) {\n callback(buffer);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n };\n request.send();\n }\n\n /**\n * Connect a source to the convolver.\n *\n * @method process\n * @for p5.Convolver\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *\n *
\n */\n process(src) {\n src.connect(this.input);\n }\n\n /**\n * Load and assign a new Impulse Response to the p5.Convolver.\n * The impulse is added to the .impulses array. Previous\n * impulses can be accessed with the .toggleImpulse(id)\n * method.\n *\n * @method addImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\n addImpulse(path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this._loadBuffer(path, callback, errorCallback);\n }\n\n /**\n * Similar to .addImpulse, except that the .impulses\n * Array is reset to save memory. A new .impulses\n * array is created with this impulse as the only item.\n *\n * @method resetImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\n resetImpulse(path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n }\n\n /**\n * If you have used .addImpulse() to add multiple impulses\n * to a p5.Convolver, then you can use this method to toggle between\n * the items in the .impulses Array. Accepts a parameter\n * to identify which impulse you wish to use, identified either by its\n * original filename (String) or by its position in the .impulses\n * Array (Number).
\n * You can access the objects in the .impulses Array directly. Each\n * Object has two attributes: an .audioBuffer (type:\n * Web Audio \n * AudioBuffer) and a .name, a String that corresponds\n * with the original filename.\n *\n * @method toggleImpulse\n * @for p5.Convolver\n * @param {String|Number} id Identify the impulse by its original filename\n * (String), or by its position in the\n * .impulses Array (Number).\n */\n toggleImpulse(id) {\n if (typeof id === 'number' && id < this.impulses.length) {\n this._setBuffer(this.impulses[id].audioBuffer);\n }\n if (typeof id === 'string') {\n for (var i = 0; i < this.impulses.length; i++) {\n if (this.impulses[i].name === id) {\n this._setBuffer(this.impulses[i].audioBuffer);\n break;\n }\n }\n }\n }\n\n dispose() {\n super.dispose();\n\n // remove all the Impulse Response buffers\n for (var i in this.impulses) {\n if (this.impulses[i]) {\n this.impulses[i] = null;\n }\n }\n }\n}\n\n/**\n * Create a p5.Convolver. Accepts a path to a soundfile\n * that will be used to generate an impulse response.\n *\n * @method createConvolver\n * @for p5\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call if loading is successful.\n * The object will be passed in as the argument\n * to the callback function.\n * @param {Function} [errorCallback] function to call if loading is not successful.\n * A custom error will be passed in as the argument\n * to the callback function.\n * @return {p5.Convolver}\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\nfunction createConvolver(path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n var self = this;\n var cReverb = new Convolver(\n path,\n function (buffer) {\n if (typeof callback === 'function') {\n callback(buffer);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n errorCallback\n );\n cReverb.impulses = [];\n return cReverb;\n}\n\nexport { Reverb, Convolver, createConvolver };\n","import p5sound from './master';\n// requires the Tone.js library's Clock (MIT license, Yotam Mann)\n// https://github.com/TONEnoTONE/Tone.js/\nimport Clock from 'Tone/core/Clock';\n\nclass Metro {\n constructor() {\n this.clock = new Clock({\n callback: this.ontick.bind(this),\n });\n this.syncedParts = [];\n this.bpm = 120; // gets overridden by p5.Part\n this._init();\n\n this.prevTick = 0;\n this.tatumTime = 0;\n\n this.tickCallback = function () {};\n }\n\n ontick(tickTime) {\n var elapsedTime = tickTime - this.prevTick;\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\n if (elapsedTime - this.tatumTime <= -0.02) {\n return;\n } else {\n // console.log('ok', this.syncedParts[0].phrases[0].name);\n this.prevTick = tickTime;\n\n // for all of the active things on the metro:\n var self = this;\n this.syncedParts.forEach(function (thisPart) {\n if (!thisPart.isPlaying) return;\n thisPart.incrementStep(secondsFromNow);\n // each synced source keeps track of its own beat number\n thisPart.phrases.forEach(function (thisPhrase) {\n var phraseArray = thisPhrase.sequence;\n var bNum = self.metroTicks % phraseArray.length;\n if (\n phraseArray[bNum] !== 0 &&\n (self.metroTicks < phraseArray.length || !thisPhrase.looping)\n ) {\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\n }\n });\n });\n this.metroTicks += 1;\n this.tickCallback(secondsFromNow);\n }\n }\n\n setBPM(bpm, rampTime = 0) {\n var beatTime = 60 / (bpm * this.tatums);\n var now = p5sound.audiocontext.currentTime;\n this.tatumTime = beatTime;\n\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\n this.bpm = bpm;\n }\n\n getBPM() {\n return (this.clock.getRate() / this.tatums) * 60;\n }\n\n _init() {\n this.metroTicks = 0;\n // this.setBPM(120);\n }\n\n // clear existing synced parts, add only this one\n resetSync(part) {\n this.syncedParts = [part];\n }\n\n // push a new synced part to the array\n pushSync(part) {\n this.syncedParts.push(part);\n }\n\n start(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.start(now + t);\n this.setBPM(this.bpm);\n }\n\n stop(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.stop(now + t);\n }\n\n beatLength(tatums) {\n this.tatums = 1 / tatums / 4; // lowest possible division of a beat\n }\n}\nexport default Metro;\n","import p5sound from './master';\nimport Metro from './metro';\n\nvar BPM = 120;\n\n/**\n * Set the global tempo, in beats per minute, for all\n * p5.Parts. This method will impact all active p5.Parts.\n *\n * @method setBPM\n * @for p5\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\np5.prototype.setBPM = function (bpm, rampTime) {\n BPM = bpm;\n for (var i in p5sound.parts) {\n if (p5sound.parts[i]) {\n p5sound.parts[i].setBPM(bpm, rampTime);\n }\n }\n};\n\n/**\n *

A phrase is a pattern of musical events over time, i.e.\n * a series of notes and rests.

\n *\n *

Phrases must be added to a p5.Part for playback, and\n * each part can play multiple phrases at the same time.\n * For example, one Phrase might be a kick drum, another\n * could be a snare, and another could be the bassline.

\n *\n *

The first parameter is a name so that the phrase can be\n * modified or deleted later. The callback is a a function that\n * this phrase will call at every step—for example it might be\n * called playNote(value){}. The array determines\n * which value is passed into the callback at each step of the\n * phrase. It can be numbers, an object with multiple numbers,\n * or a zero (0) indicates a rest so the callback won't be called).

\n *\n * @class p5.Phrase\n * @constructor\n * @param {String} name Name so that you can access the Phrase.\n * @param {Function} callback The name of a function that this phrase\n * will call. Typically it will play a sound,\n * and accept two parameters: a time at which\n * to play the sound (in seconds from now),\n * and a value from the sequence array. The\n * time should be passed into the play() or\n * start() method to ensure precision.\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n * @example\n *
\n * let mySound, myPhrase, myPart;\n * let pattern = [1,0,0,2,0,2,0,0];\n *\n * function preload() {\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * text('tap to play', width/2, height/2);\n * textAlign(CENTER, CENTER);\n *\n * myPhrase = new p5.Phrase('bbox', onEachStep, pattern);\n * myPart = new p5.Part();\n * myPart.addPhrase(myPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function onEachStep(time, playbackRate) {\n * mySound.rate(playbackRate);\n * mySound.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n * myPart.start();\n * }\n *
\n */\nclass Phrase {\n constructor(name, callback, sequence) {\n this.phraseStep = 0;\n this.name = name;\n this.callback = callback;\n /**\n * Array of values to pass into the callback\n * at each step of the phrase. Depending on the callback\n * function's requirements, these values may be numbers,\n * strings, or an object with multiple parameters.\n * Zero (0) indicates a rest.\n *\n * @property {Array} sequence\n */\n this.sequence = sequence;\n }\n}\n\n/**\n *

A p5.Part plays back one or more p5.Phrases. Instantiate a part\n * with steps and tatums. By default, each step represents a 1/16th note.

\n *\n *

See p5.Phrase for more about musical timing.

\n *\n * @class p5.Part\n * @constructor\n * @param {Number} [steps] Steps in the part\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)\n * @example\n *
\n * let box, drum, myPart;\n * let boxPat = [1,0,0,2,0,2,0,0];\n * let drumPat = [0,1,1,0,2,0,1,0];\n *\n * function preload() {\n * box = loadSound('assets/beatbox.mp3');\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * textAlign(CENTER, CENTER);\n * text('tap to play', width/2, height/2);\n *\n * let boxPhrase = new p5.Phrase('box', playBox, boxPat);\n * let drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\n * myPart = new p5.Part();\n * myPart.addPhrase(boxPhrase);\n * myPart.addPhrase(drumPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function playBox(time, playbackRate) {\n * box.rate(playbackRate);\n * box.play(time);\n * }\n *\n * function playDrum(time, playbackRate) {\n * drum.rate(playbackRate);\n * drum.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n *\n * myPart.start();\n * }\n *
\n */\nclass Part {\n constructor(steps, bLength) {\n this.length = steps || 0; // how many beats\n this.partStep = 0;\n this.phrases = [];\n this.isPlaying = false;\n this.noLoop();\n this.tatums = bLength || 0.0625; // defaults to quarter note\n\n this.metro = new Metro();\n this.metro._init();\n this.metro.beatLength(this.tatums);\n this.metro.setBPM(BPM);\n p5sound.parts.push(this);\n this.callback = function () {};\n }\n\n /**\n * Set the tempo of this part, in Beats Per Minute.\n *\n * @method setBPM\n * @for p5.Part\n * @param {Number} BPM Beats Per Minute\n * @param {Number} [rampTime] Seconds from now\n */\n setBPM(tempo, rampTime) {\n this.metro.setBPM(tempo, rampTime);\n }\n\n /**\n * Returns the tempo, in Beats Per Minute, of this part.\n *\n * @method getBPM\n * @for p5.Part\n * @return {Number}\n */\n getBPM() {\n return this.metro.getBPM();\n }\n\n /**\n * Start playback of this part. It will play\n * through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method start\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\n start(time) {\n if (!this.isPlaying) {\n this.isPlaying = true;\n this.metro.resetSync(this);\n var t = time || 0;\n this.metro.start(t);\n }\n }\n\n /**\n * Loop playback of this part. It will begin\n * looping through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method loop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\n loop(time) {\n this.looping = true;\n // rest onended function\n this.onended = function () {\n this.partStep = 0;\n };\n var t = time || 0;\n this.start(t);\n }\n\n /**\n * Tell the part to stop looping.\n *\n * @method noLoop\n * @for p5.Part\n */\n noLoop() {\n this.looping = false;\n // rest onended function\n this.onended = function () {\n this.stop();\n };\n }\n\n /**\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\n *\n * @method stop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\n stop(time) {\n this.partStep = 0;\n this.pause(time);\n }\n\n /**\n * Pause the part. Playback will resume\n * from the current step.\n *\n * @method pause\n * @for p5.Part\n * @param {Number} time seconds from now\n */\n pause(time) {\n this.isPlaying = false;\n var t = time || 0;\n this.metro.stop(t);\n }\n\n /**\n * Add a p5.Phrase to this Part.\n *\n * @method addPhrase\n * @for p5.Part\n * @param {p5.Phrase} phrase reference to a p5.Phrase\n */\n addPhrase(name, callback, array) {\n var p;\n if (arguments.length === 3) {\n p = new Phrase(name, callback, array);\n } else if (arguments[0] instanceof Phrase) {\n p = arguments[0];\n } else {\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\n }\n this.phrases.push(p);\n // reset the length if phrase is longer than part's existing length\n if (p.sequence.length > this.length) {\n this.length = p.sequence.length;\n }\n }\n\n /**\n * Remove a phrase from this part, based on the name it was\n * given when it was created.\n *\n * @method removePhrase\n * @for p5.Part\n * @param {String} phraseName\n */\n removePhrase(name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases.splice(i, 1);\n }\n }\n }\n\n /**\n * Get a phrase from this part, based on the name it was\n * given when it was created. Now you can modify its array.\n *\n * @method getPhrase\n * @for p5.Part\n * @param {String} phraseName\n */\n getPhrase(name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n return this.phrases[i];\n }\n }\n }\n\n /**\n * Find all sequences with the specified name, and replace their patterns with the specified array.\n *\n * @method replaceSequence\n * @for p5.Part\n * @param {String} phraseName\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n */\n replaceSequence(name, array) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases[i].sequence = array;\n }\n }\n }\n\n incrementStep(time) {\n if (this.partStep < this.length - 1) {\n this.callback(time);\n this.partStep += 1;\n } else {\n if (!this.looping && this.partStep === this.length - 1) {\n // this.callback(time);\n this.onended();\n }\n }\n }\n\n /**\n * Set the function that will be called at every step. This will clear the previous function.\n *\n * @method onStep\n * @for p5.Part\n * @param {Function} callback The name of the callback\n * you want to fire\n * on every beat/tatum.\n */\n onStep(callback) {\n this.callback = callback;\n }\n}\n\n// ===============\n// p5.Score\n// ===============\n\n/**\n * A Score consists of a series of Parts. The parts will\n * be played back in order. For example, you could have an\n * A part, a B part, and a C part, and play them back in this order\n * new p5.Score(a, a, b, a, c)\n *\n * @class p5.Score\n * @constructor\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\n */\nclass Score {\n constructor() {\n // for all of the arguments\n this.parts = [];\n this.currentPart = 0;\n\n var thisScore = this;\n for (var i in arguments) {\n if (arguments[i] && this.parts[i]) {\n this.parts[i] = arguments[i];\n this.parts[i].nextPart = this.parts[i + 1];\n this.parts[i].onended = function () {\n thisScore.resetPart(i);\n playNextPart(thisScore);\n };\n }\n }\n this.looping = false;\n }\n\n onended() {\n if (this.looping) {\n // this.resetParts();\n this.parts[0].start();\n } else {\n this.parts[this.parts.length - 1].onended = function () {\n this.stop();\n this.resetParts();\n };\n }\n this.currentPart = 0;\n }\n\n /**\n * Start playback of the score.\n *\n * @method start\n * @for p5.Score\n */\n start() {\n this.parts[this.currentPart].start();\n this.scoreStep = 0;\n }\n\n /**\n * Stop playback of the score.\n *\n * @method stop\n * @for p5.Score\n */\n stop() {\n this.parts[this.currentPart].stop();\n this.currentPart = 0;\n this.scoreStep = 0;\n }\n\n /**\n * Pause playback of the score.\n *\n * @method pause\n * @for p5.Score\n */\n pause() {\n this.parts[this.currentPart].stop();\n }\n\n /**\n * Loop playback of the score.\n *\n * @method loop\n * @for p5.Score\n */\n loop() {\n this.looping = true;\n this.start();\n }\n\n /**\n * Stop looping playback of the score. If it\n * is currently playing, this will go into effect\n * after the current round of playback completes.\n *\n * @method noLoop\n * @for p5.Score\n */\n noLoop() {\n this.looping = false;\n }\n\n resetParts() {\n var self = this;\n this.parts.forEach(function (part) {\n self.resetParts[part];\n });\n }\n\n resetPart(i) {\n this.parts[i].stop();\n this.parts[i].partStep = 0;\n for (var p in this.parts[i].phrases) {\n if (this.parts[i]) {\n this.parts[i].phrases[p].phraseStep = 0;\n }\n }\n }\n\n /**\n * Set the tempo for all parts in the score\n *\n * @method setBPM\n * @for p5.Score\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\n setBPM(bpm, rampTime) {\n for (var i in this.parts) {\n if (this.parts[i]) {\n this.parts[i].setBPM(bpm, rampTime);\n }\n }\n }\n}\n\nfunction playNextPart(aScore) {\n aScore.currentPart++;\n if (aScore.currentPart >= aScore.parts.length) {\n aScore.scoreStep = 0;\n aScore.onended();\n } else {\n aScore.scoreStep = 0;\n aScore.parts[aScore.currentPart - 1].stop();\n aScore.parts[aScore.currentPart].start();\n }\n}\n\nexport { Phrase, Part, Score };\n","import p5sound from './master';\nimport Clock from 'Tone/core/Clock';\n\n/**\n * SoundLoop\n *\n * @class p5.SoundLoop\n * @constructor\n *\n * @param {Function} callback this function will be called on each iteration of theloop\n * @param {Number|String} [interval] amount of time (if a number) or beats (if a string, following Tone.Time convention) for each iteration of the loop. Defaults to 1 second.\n *\n * @example\n *
\n * let synth, soundLoop;\n * let notePattern = [60, 62, 64, 67, 69, 72];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * colorMode(HSB);\n * background(0, 0, 86);\n * text('tap to start/stop', 10, 20);\n *\n * //the looper's callback is passed the timeFromNow\n * //this value should be used as a reference point from\n * //which to schedule sounds\n * let intervalInSeconds = 0.2;\n * soundLoop = new p5.SoundLoop(onSoundLoop, intervalInSeconds);\n *\n * synth = new p5.MonoSynth();\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * if (soundLoop.isPlaying) {\n * soundLoop.stop();\n * } else {\n * // start the loop\n * soundLoop.start();\n * }\n * }\n *\n * function onSoundLoop(timeFromNow) {\n * let noteIndex = (soundLoop.iterations - 1) % notePattern.length;\n * let note = midiToFreq(notePattern[noteIndex]);\n * synth.play(note, 0.5, timeFromNow);\n * background(noteIndex * 360 / notePattern.length, 50, 100);\n * }\n *
\n */\nclass SoundLoop {\n constructor(callback, interval) {\n /**\n * Getters and Setters, setting any paramter will result in a change in the clock's\n * frequency, that will be reflected after the next callback\n * beats per minute (defaults to 60)\n * @property {Number} bpm\n * @for p5.SoundLoop\n */\n Object.defineProperty(this, 'bpm', {\n get: function () {\n return this._bpm;\n },\n set: function (bpm) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the BPM in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._bpm = bpm;\n this._update();\n },\n });\n\n /**\n * number of quarter notes in a measure (defaults to 4)\n * @property {Number} timeSignature\n * @for p5.SoundLoop\n */\n Object.defineProperty(this, 'timeSignature', {\n get: function () {\n return this._timeSignature;\n },\n set: function (timeSig) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the timeSignature in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._timeSignature = timeSig;\n this._update();\n },\n });\n\n /**\n * length of the loops interval\n * @property {Number|String} interval\n * @for p5.SoundLoop\n */\n Object.defineProperty(this, 'interval', {\n get: function () {\n return this._interval;\n },\n set: function (interval) {\n this.musicalTimeMode = typeof interval === 'number' ? false : true;\n this._interval = interval;\n this._update();\n },\n });\n\n /**\n * how many times the callback has been called so far\n * @property {Number} iterations\n * @for p5.SoundLoop\n * @readonly\n */\n Object.defineProperty(this, 'iterations', {\n get: function () {\n return this.clock.ticks;\n },\n });\n\n this.callback = callback;\n /**\n * musicalTimeMode uses Tone.Time convention\n * true if string, false if number\n * @property {Boolean} musicalTimeMode\n */\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\n\n this._interval = interval || 1;\n\n /**\n * musicalTimeMode variables\n * modify these only when the interval is specified in musicalTime format as a string\n */\n this._timeSignature = 4;\n this._bpm = 60;\n\n this.isPlaying = false;\n\n /**\n * Set a limit to the number of loops to play. defaults to Infinity\n * @property {Number} maxIterations\n */\n this.maxIterations = Infinity;\n var self = this;\n\n this.clock = new Clock({\n callback: function (time) {\n var timeFromNow = time - p5sound.audiocontext.currentTime;\n /**\n * Do not initiate the callback if timeFromNow is < 0\n * This ususually occurs for a few milliseconds when the page\n * is not fully loaded\n *\n * The callback should only be called until maxIterations is reached\n */\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\n self.callback(timeFromNow);\n }\n },\n frequency: this._calcFreq(),\n });\n }\n\n /**\n * Start the loop\n * @method start\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a starting time\n */\n start(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (!this.isPlaying) {\n this.clock.start(now + t);\n this.isPlaying = true;\n }\n }\n\n /**\n * Stop the loop\n * @method stop\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a stopping time\n */\n stop(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.stop(now + t);\n this.isPlaying = false;\n }\n }\n\n /**\n * Pause the loop\n * @method pause\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a pausing time\n */\n pause(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.pause(now + t);\n this.isPlaying = false;\n }\n }\n\n /**\n * Synchronize loops. Use this method to start two or more loops in synchronization\n * or to start a loop in synchronization with a loop that is already playing\n * This method will schedule the implicit loop in sync with the explicit master loop\n * i.e. loopToStart.syncedStart(loopToSyncWith)\n *\n * @method syncedStart\n * @for p5.SoundLoop\n * @param {Object} otherLoop a p5.SoundLoop to sync with\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\n */\n syncedStart(otherLoop, timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n\n if (!otherLoop.isPlaying) {\n otherLoop.clock.start(now + t);\n otherLoop.isPlaying = true;\n this.clock.start(now + t);\n this.isPlaying = true;\n } else if (otherLoop.isPlaying) {\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\n this.clock.start(now + time);\n this.isPlaying = true;\n }\n }\n /**\n * Updates frequency value, reflected in next callback\n * @private\n * @for p5.SoundLoop\n * @method _update\n */\n _update() {\n this.clock.frequency.value = this._calcFreq();\n }\n\n /**\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\n * @private\n * @for p5.SoundLoop\n * @method _calcFreq\n * @return {Number} new clock frequency value\n */\n _calcFreq() {\n //Seconds mode, bpm / timesignature has no effect\n if (typeof this._interval === 'number') {\n this.musicalTimeMode = false;\n return 1 / this._interval;\n }\n //Musical timing mode, calculate interval based bpm, interval,and time signature\n else if (typeof this._interval === 'string') {\n this.musicalTimeMode = true;\n return (\n (this._bpm / 60 / this._convertNotation(this._interval)) *\n (this._timeSignature / 4)\n );\n }\n }\n\n /**\n * Convert notation from musical time format to seconds\n * Uses Tone.Time convention\n * @private\n * @for p5.SoundLoop\n * @method _convertNotation\n * @param {String} value value to be converted\n * @return {Number} converted value in seconds\n */\n _convertNotation(value) {\n var type = value.slice(-1);\n value = Number(value.slice(0, -1));\n switch (type) {\n case 'm':\n return this._measure(value);\n case 'n':\n return this._note(value);\n default:\n console.warn(\n 'Specified interval is not formatted correctly. See Tone.js ' +\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'\n );\n }\n }\n\n /**\n * Helper conversion methods of measure and note\n * @private\n * @for p5.SoundLoop\n * @method _measure\n */\n _measure(value) {\n return value * this._timeSignature;\n }\n\n /**\n * @private\n * @method _note\n * @for p5.SoundLoop\n */\n _note(value) {\n return this._timeSignature / value;\n }\n}\n\nexport default SoundLoop;\n","import Effect from './effect';\n\n/**\n * Compressor is an audio effect class that performs dynamics compression\n * on an audio input source. This is a very commonly used technique in music\n * and sound production. Compression creates an overall louder, richer,\n * and fuller sound by lowering the volume of louds and raising that of softs.\n * Compression can be used to avoid clipping (sound distortion due to\n * peaks in volume) and is especially useful when many sounds are played\n * at once. Compression can be used on indivudal sound sources in addition\n * to the master output.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Compressor\n * @constructor\n * @extends p5.Effect\n *\n *\n */\nclass Compressor extends Effect {\n constructor() {\n super();\n /**\n *\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\n * \n * @property {AudioNode} compressor\n */\n\n this.compressor = this.ac.createDynamicsCompressor();\n\n this.input.connect(this.compressor);\n this.compressor.connect(this.wet);\n }\n\n /**\n * Performs the same function as .connect, but also accepts\n * optional parameters to set compressor's audioParams\n * @method process\n * @for p5.Compressor\n *\n * @param {Object} src Sound source to be connected\n *\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\n process(src, attack, knee, ratio, threshold, release) {\n src.connect(this.input);\n this.set(attack, knee, ratio, threshold, release);\n }\n\n /**\n * Set the paramters of a compressor.\n * @method set\n * @for p5.Compressor\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} knee A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\n set(attack, knee, ratio, threshold, release) {\n if (typeof attack !== 'undefined') {\n this.attack(attack);\n }\n if (typeof knee !== 'undefined') {\n this.knee(knee);\n }\n if (typeof ratio !== 'undefined') {\n this.ratio(ratio);\n }\n if (typeof threshold !== 'undefined') {\n this.threshold(threshold);\n }\n if (typeof release !== 'undefined') {\n this.release(release);\n }\n }\n\n /**\n * Get current attack or set value w/ time ramp\n *\n *\n * @method attack\n * @for p5.Compressor\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n attack(attack, time) {\n var t = time || 0;\n if (typeof attack === 'number') {\n this.compressor.attack.value = attack;\n this.compressor.attack.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.attack.linearRampToValueAtTime(\n attack,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof attack !== 'undefined') {\n attack.connect(this.compressor.attack);\n }\n return this.compressor.attack.value;\n }\n\n /**\n * Get current knee or set value w/ time ramp\n *\n * @method knee\n * @for p5.Compressor\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n knee(knee, time) {\n var t = time || 0;\n if (typeof knee === 'number') {\n this.compressor.knee.value = knee;\n this.compressor.knee.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.knee.linearRampToValueAtTime(\n knee,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof knee !== 'undefined') {\n knee.connect(this.compressor.knee);\n }\n return this.compressor.knee.value;\n }\n\n /**\n * Get current ratio or set value w/ time ramp\n * @method ratio\n * @for p5.Compressor\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n ratio(ratio, time) {\n var t = time || 0;\n if (typeof ratio === 'number') {\n this.compressor.ratio.value = ratio;\n this.compressor.ratio.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.ratio.linearRampToValueAtTime(\n ratio,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof ratio !== 'undefined') {\n ratio.connect(this.compressor.ratio);\n }\n return this.compressor.ratio.value;\n }\n\n /**\n * Get current threshold or set value w/ time ramp\n * @method threshold\n * @for p5.Compressor\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n threshold(threshold, time) {\n var t = time || 0;\n if (typeof threshold === 'number') {\n this.compressor.threshold.value = threshold;\n this.compressor.threshold.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.threshold.linearRampToValueAtTime(\n threshold,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof threshold !== 'undefined') {\n threshold.connect(this.compressor.threshold);\n }\n return this.compressor.threshold.value;\n }\n\n /**\n * Get current release or set value w/ time ramp\n * @method release\n * @for p5.Compressor\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n *\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n release(release, time) {\n var t = time || 0;\n if (typeof release === 'number') {\n this.compressor.release.value = release;\n this.compressor.release.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.release.linearRampToValueAtTime(\n release,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof number !== 'undefined') {\n release.connect(this.compressor.release);\n }\n return this.compressor.release.value;\n }\n\n /**\n * Return the current reduction value\n *\n * @method reduction\n * @for p5.Compressor\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\n */\n reduction() {\n return this.compressor.reduction.value;\n }\n\n dispose() {\n super.dispose();\n if (this.compressor) {\n this.compressor.disconnect();\n delete this.compressor;\n }\n }\n}\n\nexport default Compressor;\n","/**\n *

PeakDetect works in conjunction with p5.FFT to\n * look for onsets in some or all of the frequency spectrum.\n *

\n *

\n * To use p5.PeakDetect, call update in the draw loop\n * and pass in a p5.FFT object.\n *

\n *

\n * You can listen for a specific part of the frequency spectrum by\n * setting the range between freq1 and freq2.\n *

\n *\n *

threshold is the threshold for detecting a peak,\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\n * as 1.0.

\n *\n *

\n * The update method is meant to be run in the draw loop, and\n * frames determines how many loops must pass before\n * another peak can be detected.\n * For example, if the frameRate() = 60, you could detect the beat of a\n * 120 beat-per-minute song with this equation:\n * framesPerPeak = 60 / (estimatedBPM / 60 );\n *

\n *\n *

\n * Based on example contribtued by @b2renger, and a simple beat detection\n * explanation by Felix Turner.\n *

\n *\n * @class p5.PeakDetect\n * @constructor\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\n * scaled logarithmically where 0.1 is 1/2 the loudness\n * of 1.0. Defaults to 0.35.\n * @param {Number} [framesPerPeak] Defaults to 20.\n * @example\n *
\n *\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 10;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * background(0);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n *\n * // p5.PeakDetect requires a p5.FFT\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n * }\n *\n * function draw() {\n * background(0);\n * text('click to play/pause', width/2, height/2);\n *\n * // peakDetect accepts an fft post-analysis\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * if ( peakDetect.isDetected ) {\n * ellipseWidth = 50;\n * } else {\n * ellipseWidth *= 0.95;\n * }\n *\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // toggle play/stop when canvas is clicked\n * function mouseClicked() {\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * }\n * }\n *
\n */\nclass PeakDetect {\n // framesPerPeak determines how often to look for a beat.\n // If a beat is provided, try to look for a beat based on bpm\n constructor(freq1, freq2, threshold, _framesPerPeak) {\n this.framesPerPeak = _framesPerPeak || 20;\n this.framesSinceLastPeak = 0;\n this.decayRate = 0.95;\n\n this.threshold = threshold || 0.35;\n this.cutoff = 0;\n\n // how much to increase the cutoff\n // TO DO: document this / figure out how to make it accessible\n this.cutoffMult = 1.5;\n\n this.energy = 0;\n this.penergy = 0;\n\n // TO DO: document this property / figure out how to make it accessible\n this.currentValue = 0;\n\n /**\n * isDetected is set to true when a peak is detected.\n *\n * @attribute isDetected {Boolean}\n * @default false\n */\n this.isDetected = false;\n\n this.f1 = freq1 || 40;\n this.f2 = freq2 || 20000;\n\n // function to call when a peak is detected\n this._onPeak = function () {};\n }\n\n /**\n * The update method is run in the draw loop.\n *\n * Accepts an FFT object. You must call .analyze()\n * on the FFT object prior to updating the peakDetect\n * because it relies on a completed FFT analysis.\n *\n * @method update\n * @param {p5.FFT} fftObject A p5.FFT object\n */\n update(fftObject) {\n var nrg = (this.energy = fftObject.getEnergy(this.f1, this.f2) / 255);\n if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) {\n // trigger callback\n this._onPeak();\n this.isDetected = true;\n\n // debounce\n this.cutoff = nrg * this.cutoffMult;\n this.framesSinceLastPeak = 0;\n } else {\n this.isDetected = false;\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\n this.framesSinceLastPeak++;\n } else {\n this.cutoff *= this.decayRate;\n this.cutoff = Math.max(this.cutoff, this.threshold);\n }\n }\n\n this.currentValue = nrg;\n this.penergy = nrg;\n }\n\n /**\n * onPeak accepts two arguments: a function to call when\n * a peak is detected. The value of the peak,\n * between 0.0 and 1.0, is passed to the callback.\n *\n * @method onPeak\n * @param {Function} callback Name of a function that will\n * be called when a peak is\n * detected.\n * @param {Object} [val] Optional value to pass\n * into the function when\n * a peak is detected.\n * @example\n *
\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 0;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * cnv = createCanvas(100,100);\n * textAlign(CENTER);\n *\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n *\n * setupSound();\n *\n * // when a beat is detected, call triggerBeat()\n * peakDetect.onPeak(triggerBeat);\n * }\n *\n * function draw() {\n * background(0);\n * fill(255);\n * text('click to play', width/2, height/2);\n *\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * ellipseWidth *= 0.95;\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // this function is called by peakDetect.onPeak\n * function triggerBeat() {\n * ellipseWidth = 50;\n * }\n *\n * // mouseclick starts/stops sound\n * function setupSound() {\n * cnv.mouseClicked( function() {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * });\n * }\n *
\n */\n onPeak(callback, val) {\n var self = this;\n\n self._onPeak = function () {\n callback(self.energy, val);\n };\n }\n}\n\nexport default PeakDetect;\n","// inspiration: recorder.js, Tone.js & typedarray.org\n\nimport p5sound from './master';\nimport { safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\nconst ac = p5sound.audiocontext;\n\n/**\n *

Record sounds for playback and/or to save as a .wav file.\n * The p5.SoundRecorder records all sound output from your sketch,\n * or can be assigned a specific source with setInput().

\n *

The record() method accepts a p5.SoundFile as a parameter.\n * When playback is stopped (either after the given amount of time,\n * or with the stop() method), the p5.SoundRecorder will send its\n * recording to that p5.SoundFile for playback.

\n *\n * @class p5.SoundRecorder\n * @constructor\n * @example\n *
\n * let mic, recorder, soundFile;\n * let state = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * textAlign(CENTER, CENTER);\n *\n * // create an audio in\n * mic = new p5.AudioIn();\n *\n * // prompts user to enable their browser mic\n * mic.start();\n *\n * // create a sound recorder\n * recorder = new p5.SoundRecorder();\n *\n * // connect the mic to the recorder\n * recorder.setInput(mic);\n *\n * // this sound file will be used to\n * // playback & save the recording\n * soundFile = new p5.SoundFile();\n *\n * text('tap to record', width/2, height/2);\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * // make sure user enabled the mic\n * if (state === 0 && mic.enabled) {\n *\n * // record to our p5.SoundFile\n * recorder.record(soundFile);\n *\n * background(255,0,0);\n * text('Recording!', width/2, height/2);\n * state++;\n * }\n * else if (state === 1) {\n * background(0,255,0);\n *\n * // stop recorder and\n * // send result to soundFile\n * recorder.stop();\n *\n * text('Done! Tap to play and download', width/2, height/2, width - 20);\n * state++;\n * }\n *\n * else if (state === 2) {\n * soundFile.play(); // play the result!\n * save(soundFile, 'mySound.wav');\n * state++;\n * }\n * }\n *
\n */\nclass SoundRecorder {\n constructor() {\n this.input = ac.createGain();\n this.output = ac.createGain();\n\n this._inputChannels = 2;\n this._outputChannels = 2; // stereo output, even if input is mono\n\n const workletBufferSize = safeBufferSize(1024);\n\n this._workletNode = new AudioWorkletNode(\n ac,\n processorNames.recorderProcessor,\n {\n outputChannelCount: [this._outputChannels],\n processorOptions: {\n numInputChannels: this._inputChannels,\n bufferSize: workletBufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'buffers') {\n const buffers = [\n new Float32Array(event.data.leftBuffer),\n new Float32Array(event.data.rightBuffer),\n ];\n this._callback(buffers);\n }\n }.bind(this);\n\n /**\n * callback invoked when the recording is over\n * @private\n * @type Function(Float32Array)\n */\n this._callback = function () {};\n\n // connections\n this._workletNode.connect(p5.soundOut._silentNode);\n this.setInput();\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Connect a specific device to the p5.SoundRecorder.\n * If no parameter is given, p5.SoundRecorer will record\n * all audible p5.sound from your sketch.\n *\n * @method setInput\n * @for p5.SoundRecorder\n * @param {Object} [unit] p5.sound object or a web audio unit\n * that outputs sound\n */\n setInput(unit) {\n this.input.disconnect();\n this.input = null;\n this.input = ac.createGain();\n this.input.connect(this._workletNode);\n this.input.connect(this.output);\n if (unit) {\n unit.connect(this.input);\n } else {\n p5.soundOut.output.connect(this.input);\n }\n }\n\n /**\n * Start recording. To access the recording, provide\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\n * will send its recording to that p5.SoundFile for playback once\n * recording is complete. Optional parameters include duration\n * (in seconds) of the recording, and a callback function that\n * will be called once the complete recording has been\n * transfered to the p5.SoundFile.\n *\n * @method record\n * @for p5.SoundRecorder\n * @param {p5.SoundFile} soundFile p5.SoundFile\n * @param {Number} [duration] Time (in seconds)\n * @param {Function} [callback] The name of a function that will be\n * called once the recording completes\n */\n record(sFile, duration, callback) {\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\n\n if (sFile && callback) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n callback();\n };\n } else if (sFile) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n };\n }\n }\n\n /**\n * Stop the recording. Once the recording is stopped,\n * the results will be sent to the p5.SoundFile that\n * was given on .record(), and if a callback function\n * was provided on record, that function will be called.\n *\n * @method stop\n * @for p5.SoundRecorder\n */\n stop() {\n this._workletNode.port.postMessage({ name: 'stop' });\n }\n\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this._callback = function () {};\n if (this.input) {\n this.input.disconnect();\n }\n this.input = null;\n this._workletNode = null;\n }\n}\n\nexport default SoundRecorder;\n","import Effect from './effect.js';\n\n/*\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n */\nfunction makeDistortionCurve(amount) {\n var k = typeof amount === 'number' ? amount : 50;\n var numSamples = 44100;\n var curve = new Float32Array(numSamples);\n var deg = Math.PI / 180;\n var i = 0;\n var x;\n for (; i < numSamples; ++i) {\n x = (i * 2) / numSamples - 1;\n curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x));\n }\n return curve;\n}\n\n/**\n * A Distortion effect created with a Waveshaper Node,\n * with an approach adapted from\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Distortion\n * @extends p5.Effect\n * @constructor\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n *\n */\nclass Distortion extends Effect {\n constructor(amount, oversample) {\n super();\n if (typeof amount === 'undefined') {\n amount = 0.25;\n }\n if (typeof amount !== 'number') {\n throw new Error('amount must be a number');\n }\n if (typeof oversample === 'undefined') {\n oversample = '2x';\n }\n if (typeof oversample !== 'string') {\n throw new Error('oversample must be a String');\n }\n\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n\n /**\n * The p5.Distortion is built with a\n * \n * Web Audio WaveShaper Node.\n *\n * @property {AudioNode} WaveShaperNode\n */\n this.waveShaperNode = this.ac.createWaveShaper();\n\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n this.waveShaperNode.oversample = oversample;\n\n this.input.connect(this.waveShaperNode);\n\n this.waveShaperNode.connect(this.wet);\n }\n\n /**\n * Process a sound source, optionally specify amount and oversample values.\n *\n * @method process\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\n process(src, amount, oversample) {\n src.connect(this.input);\n this.set(amount, oversample);\n }\n\n /**\n * Set the amount and oversample of the waveshaper distortion.\n *\n * @method set\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\n set(amount, oversample) {\n if (amount) {\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n }\n if (oversample) {\n this.waveShaperNode.oversample = oversample;\n }\n }\n\n /**\n * Return the distortion amount, typically between 0-1.\n *\n * @method getAmount\n * @for p5.Distortion\n * @return {Number} Unbounded distortion amount.\n * Normal values range from 0-1.\n */\n getAmount() {\n return this.amount;\n }\n\n /**\n * Return the oversampling.\n *\n * @method getOversample\n * @for p5.Distortion\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\n */\n getOversample() {\n return this.waveShaperNode.oversample;\n }\n\n dispose() {\n super.dispose();\n if (this.waveShaperNode) {\n this.waveShaperNode.disconnect();\n this.waveShaperNode = null;\n }\n }\n}\n\nexport default Distortion;\n","import p5sound from './master';\n\n/**\n * A gain node is usefull to set the relative volume of sound.\n * It's typically used to build mixers.\n *\n * @class p5.Gain\n * @constructor\n * @example\n *
\n *\n * // load two soundfile and crossfade beetween them\n * let sound1,sound2;\n * let sound1Gain, sound2Gain, masterGain;\n * function preload(){\n * soundFormats('ogg', 'mp3');\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\n * sound2 = loadSound('assets/beat');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * // create a 'master' gain to which we will connect both soundfiles\n * masterGain = new p5.Gain();\n * masterGain.connect();\n * sound1.disconnect(); // diconnect from p5 output\n * sound1Gain = new p5.Gain(); // setup a gain node\n * sound1Gain.setInput(sound1); // connect the first sound to its input\n * sound1Gain.connect(masterGain); // connect its output to the 'master'\n * sound2.disconnect();\n * sound2Gain = new p5.Gain();\n * sound2Gain.setInput(sound2);\n * sound2Gain.connect(masterGain);\n * }\n * function startSound() {\n * sound1.loop();\n * sound2.loop();\n * loop();\n * }\n * function mouseReleased() {\n * sound1.stop();\n * sound2.stop();\n * }\n * function draw(){\n * background(220);\n * textAlign(CENTER);\n * textSize(11);\n * fill(0);\n * if (!sound1.isPlaying()) {\n * text('tap and drag to play', width/2, height/2);\n * return;\n * }\n * // map the horizontal position of the mouse to values useable for volume * control of sound1\n * var sound1Volume = constrain(map(mouseX,width,0,0,1), 0, 1);\n * var sound2Volume = 1-sound1Volume;\n * sound1Gain.amp(sound1Volume);\n * sound2Gain.amp(sound2Volume);\n * // map the vertical position of the mouse to values useable for 'master * volume control'\n * var masterVolume = constrain(map(mouseY,height,0,0,1), 0, 1);\n * masterGain.amp(masterVolume);\n * text('master', width/2, height - masterVolume * height * 0.9)\n * fill(255, 0, 255);\n * textAlign(LEFT);\n * text('sound1', 5, height - sound1Volume * height * 0.9);\n * textAlign(RIGHT);\n * text('sound2', width - 5, height - sound2Volume * height * 0.9);\n * }\n *
\n */\n\nclass Gain {\n constructor() {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n this.input.connect(this.output);\n\n // add to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Connect a source to the gain node.\n *\n * @method setInput\n * @for p5.Gain\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n */\n\n setInput(src) {\n src.connect(this.input);\n }\n\n /**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Gain\n * @param {Object} unit\n */\n connect(unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Gain\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Set the output level of the gain node.\n *\n * @method amp\n * @for p5.Gain\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n amp(vol, rampTime = 0, tFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n }\n\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n }\n}\n\nexport default Gain;\n","import p5sound from './master';\n\n/**\n * Base class for monophonic synthesizers. Any extensions of this class\n * should follow the API and implement the methods below in order to\n * remain compatible with p5.PolySynth();\n *\n * @class p5.AudioVoice\n * @constructor\n */\nclass AudioVoice {\n constructor() {\n this.ac = p5sound.audiocontext;\n this.output = this.ac.createGain();\n this.connect();\n p5sound.soundArray.push(this);\n }\n play(note, velocity, secondsFromNow, sustime) {}\n\n triggerAttack(note, velocity, secondsFromNow) {}\n\n triggerRelease(secondsFromNow) {}\n\n amp(vol, rampTime) {}\n\n /**\n * Connect to p5 objects or Web Audio Nodes\n * @method connect\n * @for p5.AudioVoice\n * @param {Object} unit\n */\n connect(unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect from soundOut\n * @method disconnect\n * @for p5.AudioVoice\n */\n disconnect() {\n this.output.disconnect();\n }\n\n dispose() {\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n }\n}\n\nexport default AudioVoice;\n","import AudioVoice from './audioVoice';\nimport Envelope from './envelope';\nimport p5sound from './master';\nimport Oscillator from './oscillator';\nimport { noteToFreq } from './helpers';\n\nvar DEFAULT_SUSTAIN = 0.15;\n\n/**\n * A MonoSynth is used as a single voice for sound synthesis.\n * This is a class to be used in conjunction with the PolySynth\n * class. Custom synthetisers should be built inheriting from\n * this class.\n *\n * @class p5.MonoSynth\n * @constructor\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n **/\n\nclass MonoSynth extends AudioVoice {\n constructor() {\n super();\n this.oscillator = new Oscillator();\n\n this.env = new Envelope(); //to be changed\n this.env.setRange(1, 0);\n this.env.setExp(true);\n\n //set params\n this.setADSR(0.02, 0.25, 0.05, 0.35);\n\n // oscillator --> env --> this.output (gain) --> p5.soundOut\n this.oscillator.disconnect();\n this.oscillator.connect(this.output);\n\n this.env.disconnect();\n this.env.setInput(this.output.gain);\n\n // reset oscillator gain to 1.0\n this.oscillator.output.gain.value = 1.0;\n\n this.oscillator.start();\n this.connect();\n\n p5sound.soundArray.push(this);\n\n /**\n * Getters and Setters\n * @property {Number} attack\n * @for p5.MonoSynth\n */\n /**\n * @property {Number} decay\n * @for p5.MonoSynth\n */\n /**\n * @property {Number} sustain\n * @for p5.MonoSynth\n */\n /**\n * @property {Number} release\n * @for p5.MonoSynth\n */\n Object.defineProperties(this, {\n attack: {\n get: function () {\n return this.env.aTime;\n },\n set: function (attack) {\n this.env.setADSR(\n attack,\n this.env.dTime,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n decay: {\n get: function () {\n return this.env.dTime;\n },\n set: function (decay) {\n this.env.setADSR(\n this.env.aTime,\n decay,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n sustain: {\n get: function () {\n return this.env.sPercent;\n },\n set: function (sustain) {\n this.env.setADSR(\n this.env.aTime,\n this.env.dTime,\n sustain,\n this.env.rTime\n );\n },\n },\n release: {\n get: function () {\n return this.env.rTime;\n },\n set: function (release) {\n this.env.setADSR(\n this.env.aTime,\n this.env.dTime,\n this.env.sPercent,\n release\n );\n },\n },\n });\n }\n\n /**\n * Play tells the MonoSynth to start playing a note. This method schedules\n * the calling of .triggerAttack and .triggerRelease.\n *\n * @method play\n * @for p5.MonoSynth\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope. Defaults to 0.15 seconds.\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n *\n */\n play(note, velocity, secondsFromNow, susTime) {\n this.triggerAttack(note, velocity, ~~secondsFromNow);\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\n }\n\n /**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @method triggerAttack\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\n triggerAttack(note, velocity, secondsFromNow = 0) {\n var freq = noteToFreq(note);\n var vel = velocity || 0.1;\n this.oscillator.freq(freq, 0, secondsFromNow);\n this.env.ramp(this.output.gain, secondsFromNow, vel);\n }\n\n /**\n * Trigger the release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @param {Number} secondsFromNow time to trigger the release\n * @method triggerRelease\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\n triggerRelease(secondsFromNow = 0) {\n this.env.ramp(this.output.gain, secondsFromNow, 0);\n }\n\n /**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.MonoSynth\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n */\n setADSR(attack, decay, sustain, release) {\n this.env.setADSR(attack, decay, sustain, release);\n }\n\n /**\n * MonoSynth amp\n * @method amp\n * @for p5.MonoSynth\n * @param {Number} vol desired volume\n * @param {Number} [rampTime] Time to reach new volume\n * @return {Number} new volume value\n */\n amp(vol, rampTime) {\n var t = rampTime || 0;\n if (typeof vol !== 'undefined') {\n this.oscillator.amp(vol, t);\n }\n return this.oscillator.amp().value;\n }\n\n /**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.MonoSynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\n\n connect(unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.MonoSynth\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.MonoSynth\n */\n dispose() {\n super.dispose();\n\n if (this.env) {\n this.env.dispose();\n }\n if (this.oscillator) {\n this.oscillator.dispose();\n }\n }\n}\n\nexport default MonoSynth;\n","/**\n * Listen for onsets (a sharp increase in volume) within a given\n * frequency range.\n *\n * @class p5.OnsetDetect\n * @constructor\n * @param {Number} freqLow Low frequency\n * @param {Number} freqHigh High frequency\n * @param {Number} threshold Amplitude threshold between 0 (no energy) and 1 (maximum)\n * @param {Function} callback Function to call when an onset is detected\n */\nclass OnsetDetect {\n constructor(freqLow, freqHigh, threshold, callback) {\n this.isDetected = false;\n this.freqLow = freqLow;\n this.freqHigh = freqHigh;\n this.treshold = threshold;\n this.energy = 0;\n this.penergy = 0;\n\n // speed of decay\n this.sensitivity = 500;\n\n this.callback = callback;\n }\n\n // callback here too?\n update(fftObject, callback) {\n this.energy = fftObject.getEnergy(this.freqLow, this.freqHigh) / 255;\n\n if (this.isDetected === false) {\n if (this.energy - this.penergy > this.treshold) {\n this.isDetected = true;\n\n if (this.callback) {\n this.callback(this.energy);\n } else if (callback) {\n callback(this.energy);\n }\n\n var self = this;\n setTimeout(function () {\n self.isDetected = false;\n }, this.sensitivity);\n }\n }\n\n this.penergy = this.energy;\n }\n}\n\nexport default OnsetDetect;\n","import p5sound from './master';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\nimport { noteToFreq, freqToMidi } from './helpers';\n\n/**\n * An AudioVoice is used as a single voice for sound synthesis.\n * The PolySynth class holds an array of AudioVoice, and deals\n * with voices allocations, with setting notes to be played, and\n * parameters to be set.\n *\n * @class p5.PolySynth\n * @constructor\n *\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\n * the AudioVoice class. Defaults to p5.MonoSynth\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n **/\nclass PolySynth {\n constructor(audioVoice, maxVoices) {\n //audiovoices will contain maxVoices many monophonic synths\n this.audiovoices = [];\n\n /**\n * An object that holds information about which notes have been played and\n * which notes are currently being played. New notes are added as keys\n * on the fly. While a note has been attacked, but not released, the value of the\n * key is the audiovoice which is generating that note. When notes are released,\n * the value of the key becomes undefined.\n * @property notes\n */\n this.notes = {};\n\n //indices of the most recently used, and least recently used audiovoice\n this._newest = 0;\n this._oldest = 0;\n\n /**\n * A PolySynth must have at least 1 voice, defaults to 8\n * @property polyvalue\n */\n this.maxVoices = maxVoices || 8;\n\n /**\n * Monosynth that generates the sound for each note that is triggered. The\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\n * @property AudioVoice\n */\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\n\n /**\n * This value must only change as a note is attacked or released. Due to delay\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\n * @private\n * @property {Tone.TimelineSignal} _voicesInUse\n */\n this._voicesInUse = new TimelineSignal(0);\n\n this.output = p5sound.audiocontext.createGain();\n this.connect();\n\n //Construct the appropriate number of audiovoices\n this._allocateVoices();\n p5sound.soundArray.push(this);\n }\n\n /**\n * Construct the appropriate number of audiovoices\n * @private\n * @for p5.PolySynth\n * @method _allocateVoices\n */\n _allocateVoices() {\n for (var i = 0; i < this.maxVoices; i++) {\n this.audiovoices.push(new this.AudioVoice());\n this.audiovoices[i].disconnect();\n this.audiovoices[i].connect(this.output);\n }\n }\n\n /**\n * Play a note by triggering noteAttack and noteRelease with sustain time\n *\n * @method play\n * @for p5.PolySynth\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n */\n play(note, velocity, secondsFromNow, susTime = 1) {\n this.noteAttack(note, velocity, secondsFromNow);\n this.noteRelease(note, secondsFromNow + susTime);\n }\n\n /**\n * noteADSR sets the envelope for a specific note that has just been triggered.\n * Using this method modifies the envelope of whichever audiovoice is being used\n * to play the desired note. The envelope should be reset before noteRelease is called\n * in order to prevent the modified envelope from being used on other notes.\n *\n * @method noteADSR\n * @for p5.PolySynth\n * @param {Number} [note] Midi note on which ADSR should be set.\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\n\n noteADSR(note, a, d, s, r, timeFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var t = now + timeFromNow;\n this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r);\n }\n\n /**\n * Set the PolySynths global envelope. This method modifies the envelopes of each\n * monosynth so that all notes are played with this envelope.\n *\n * @method setADSR\n * @for p5.PolySynth\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\n setADSR(a, d, s, r) {\n this.audiovoices.forEach(function (voice) {\n voice.setADSR(a, d, s, r);\n });\n }\n\n /**\n * Trigger the Attack, and Decay portion of a MonoSynth.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @method noteAttack\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\n * @param {Number} [secondsFromNow] time from now (in seconds)\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n */\n noteAttack(_note, _velocity, secondsFromNow = 0) {\n //this value is used by this._voicesInUse\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\n\n //Convert note to frequency if necessary. This is because entries into this.notes\n //should be based on frequency for the sake of consistency.\n var note = noteToFreq(_note);\n var velocity = _velocity || 0.1;\n\n var currentVoice;\n\n //Release the note if it is already playing\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\n this.noteRelease(note, 0);\n }\n\n //Check to see how many voices are in use at the time the note will start\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\n }\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\n //with a new note\n else {\n currentVoice = this._oldest;\n\n oldestNote = freqToMidi(\n this.audiovoices[this._oldest].oscillator.freq().value\n );\n this.noteRelease(oldestNote);\n this._oldest = (this._oldest + 1) % (this.maxVoices - 1);\n }\n\n //Overrite the entry in the notes object. A note (frequency value)\n //corresponds to the index of the audiovoice that is playing it\n this.notes[note] = new TimelineSignal();\n this.notes[note].setValueAtTime(currentVoice, acTime);\n\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //Add 1 and schedule this value at time 't', when this note will start playing\n var previousVal =\n this._voicesInUse._searchBefore(acTime) === null\n ? 0\n : this._voicesInUse._searchBefore(acTime).value;\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\n\n //Then update all scheduled values that follow to increase by 1\n this._updateAfter(acTime, 1);\n\n this._newest = currentVoice;\n //The audiovoice handles the actual scheduling of the note\n if (typeof velocity === 'number') {\n var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2;\n velocity = velocity > maxRange ? maxRange : velocity;\n }\n\n // use secondsFromNow because this method will add AudioContext currentTime\n this.audiovoices[currentVoice].triggerAttack(\n note,\n velocity,\n secondsFromNow\n );\n }\n\n /**\n * Private method to ensure accurate values of this._voicesInUse\n * Any time a new value is scheduled, it is necessary to increment all subsequent\n * scheduledValues after attack, and decrement all subsequent\n * scheduledValues after release\n *\n * @private\n * @for p5.PolySynth\n * @param {[type]} time [description]\n * @param {[type]} value [description]\n * @return {[type]} [description]\n */\n _updateAfter(time, value) {\n if (this._voicesInUse._searchAfter(time) === null) {\n return;\n } else {\n this._voicesInUse._searchAfter(time).value += value;\n var nextTime = this._voicesInUse._searchAfter(time).time;\n this._updateAfter(nextTime, value);\n }\n }\n\n /**\n * Trigger the Release of an AudioVoice note. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method noteRelease\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * If no value is provided, all notes will be released.\n * @param {Number} [secondsFromNow] time to trigger the release\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n *\n */\n noteRelease(_note, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n // if a note value is not provided, release all voices\n if (!_note) {\n this.audiovoices.forEach(function (voice) {\n voice.triggerRelease(tFromNow);\n });\n this._voicesInUse.setValueAtTime(0, t);\n for (var n in this.notes) {\n this.notes[n].dispose();\n delete this.notes[n];\n }\n return;\n }\n\n //Make sure note is in frequency inorder to query the this.notes object\n var note = noteToFreq(_note);\n\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\n console.warn('Cannot release a note that is not already playing');\n } else {\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //subtract 1 and schedule this value at time 't', when this note will stop playing\n var previousVal = Math.max(\n ~~this._voicesInUse.getValueAtTime(t).value,\n 1\n );\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\n if (previousVal > 0) {\n this._updateAfter(t, -1);\n }\n\n this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(\n tFromNow\n );\n this.notes[note].dispose();\n delete this.notes[note];\n\n this._newest =\n this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\n }\n }\n\n /**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.PolySynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\n connect(unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.PolySynth\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.PolySynth\n */\n dispose() {\n this.audiovoices.forEach(function (voice) {\n voice.dispose();\n });\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n }\n}\n\nexport default PolySynth;\n","class Signal {\n constructor() {\n console.warn('p5.Signal is deprecated , Use Tone.js Signal instead ');\n }\n}\n\nexport default Signal;\n","import 'audioworklet-polyfill';\nimport './shims';\n\nimport { getAudioContext, userStartAudio } from './audiocontext';\np5.prototype.getAudioContext = getAudioContext;\np5.prototype.userStartAudio = userStartAudio;\n\nimport './master';\n\nimport {\n sampleRate,\n freqToMidi,\n midiToFreq,\n noteToFreq,\n soundFormats,\n disposeSound,\n _checkFileFormats,\n _mathChain,\n convertToWav,\n interleave,\n writeUTFBytes,\n safeBufferSize,\n saveSound,\n} from './helpers';\np5.prototype.sampleRate = sampleRate;\np5.prototype.freqToMidi = freqToMidi;\np5.prototype.midiToFreq = midiToFreq;\np5.prototype.noteToFreq = noteToFreq;\np5.prototype.soundFormats = soundFormats;\np5.prototype.disposeSound = disposeSound;\np5.prototype._checkFileFormats = _checkFileFormats;\np5.prototype._mathChain = _mathChain;\np5.prototype.convertToWav = convertToWav;\np5.prototype.interleave = interleave;\np5.prototype.writeUTFBytes = writeUTFBytes;\np5.prototype.safeBufferSize = safeBufferSize;\np5.prototype.saveSound = saveSound;\n\n// register removeSound to dispose of p5sound SoundFiles, Convolvers,\n// Oscillators etc when sketch ends\np5.prototype.registerMethod('remove', p5.prototype.disposeSound);\n\nimport './errorHandler';\nimport './audioWorklet';\n\nimport Panner from './panner';\np5.Panner = Panner;\n\nimport SoundFile, { loadSound } from './soundfile';\np5.SoundFile = SoundFile;\np5.prototype.loadSound = loadSound;\n// register preload handling of loadSound\np5.prototype.registerPreloadMethod('loadSound', p5.prototype);\n\nimport Amplitude from './amplitude';\np5.Amplitude = Amplitude;\n\nimport FFT from './fft';\np5.FFT = FFT;\n\nimport Oscillator, { SinOsc, TriOsc, SawOsc, SqrOsc } from './oscillator';\np5.Oscillator = Oscillator;\np5.SinOsc = SinOsc;\np5.TriOsc = TriOsc;\np5.SawOsc = SawOsc;\np5.SqrOsc = SqrOsc;\n\nimport './envelope';\n\nimport Noise from './noise';\np5.Noise = Noise;\n\nimport Pulse from './pulse';\np5.Pulse = Pulse;\n\nimport AudioIn from './audioin';\np5.AudioIn = AudioIn;\n\nimport Effect from './effect';\np5.Effect = Effect;\n\nimport Filter, { LowPass, HighPass, BandPass } from './filter';\np5.Filter = Filter;\np5.LowPass = LowPass;\np5.HighPass = HighPass;\np5.BandPass = BandPass;\n\nimport EQ from './eq';\np5.EQ = EQ;\n\nimport listener3D from './listener3d';\np5.listener3D = listener3D;\n\nimport Panner3D from './panner3d';\np5.Panner3D = Panner3D;\n\nimport Delay from './delay';\np5.Delay = Delay;\n\nimport { Reverb, Convolver, createConvolver } from './reverb';\np5.Reverb = Reverb;\np5.Convolver = Convolver;\np5.prototype.createConvolver = createConvolver;\np5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\n\nimport Metro from './metro';\np5.Metro = Metro;\n\nimport { Phrase, Part, Score } from './looper';\np5.Phrase = Phrase;\np5.Part = Part;\np5.Score = Score;\n\nimport SoundLoop from './soundLoop';\np5.SoundLoop = SoundLoop;\n\nimport Compressor from './compressor';\np5.Compressor = Compressor;\n\nimport peakDetect from './peakDetect';\np5.peakDetect = peakDetect;\n\nimport SoundRecorder from './soundRecorder';\np5.SoundRecorder = SoundRecorder;\n\nimport Distortion from './distortion';\np5.Distortion = Distortion;\n\nimport Gain from './gain';\np5.Gain = Gain;\n\nimport AudioVoice from './audioVoice';\np5.AudioVoice = AudioVoice;\n\nimport MonoSynth from './monosynth';\np5.MonoSynth = MonoSynth;\n\nimport OnsetDetect from './onsetDetect';\np5.OnsetDetect = OnsetDetect;\n\nimport PolySynth from './polysynth';\np5.PolySynth = PolySynth;\n\n// Following are the deprecated classes\nimport Signal from './deprecations/Signal';\np5.Signal = Signal;\n"],"sourceRoot":""} \ No newline at end of file diff --git a/lib/p5.sound.min.js b/lib/p5.sound.min.js index 57f0e078..2c508e02 100644 --- a/lib/p5.sound.min.js +++ b/lib/p5.sound.min.js @@ -1,3 +1,3 @@ -/** [p5.sound] Version: 0.3.12 - 2020-06-26 */ - !function(n){var i={};function o(t){if(i[t])return i[t].exports;var e=i[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=n,o.c=i,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},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 n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)o.d(n,i,function(t){return e[t]}.bind(null,i));return n},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=41)}([function(t,e,n){var i,o;i=[n(1),n(7),n(9),n(18),n(10)],void 0===(o=function(e){"use strict";return e.Signal=function(){var t=this.optionsObject(arguments,["value","units"],e.Signal.defaults);this.output=this._gain=this.context.createGain(),t.param=this._gain.gain,e.Param.call(this,t),this.input=this._param=this._gain.gain,this.context.getConstant(1).chain(this._gain)},e.extend(e.Signal,e.Param),e.Signal.defaults={value:0,units:e.Type.Default,convert:!0},e.Signal.prototype.connect=e.SignalBase.prototype.connect,e.Signal.prototype.dispose=function(){return e.Param.prototype.dispose.call(this),this._param=null,this._gain.disconnect(),this._gain=null,this},e.Signal}.apply(e,i))||(t.exports=o)},function(t,e,n){var i;void 0===(i=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 i=this._searchAfter(t);i&&(this.cancelScheduledValues(t),i.type===u.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):i.type===u.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},u.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.linearRampToValueAtTime(t,n),this},u.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,n),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),n=this._searchBefore(t),i=this._initial;if(null===n)i=this._initial;else if(n.type===u.TimelineSignal.Type.Target){var o,r=this._events.getBefore(n.time);o=null===r?this._initial:r.value,i=this._exponentialApproach(n.time,o,n.value,n.constant,t)}else i=n.type===u.TimelineSignal.Type.Curve?this._curveInterpolate(n.time,n.value,n.duration,t):null===e?n.value:e.type===u.TimelineSignal.Type.Linear?this._linearInterpolate(n.time,n.value,e.time,e.value,t):e.type===u.TimelineSignal.Type.Exponential?this._exponentialInterpolate(n.time,n.value,e.time,e.value,t):n.value;return i},u.TimelineSignal.prototype.connect=u.SignalBase.prototype.connect,u.TimelineSignal.prototype._exponentialApproach=function(t,e,n,i,o){return n+(e-n)*Math.exp(-(o-t)/i)},u.TimelineSignal.prototype._linearInterpolate=function(t,e,n,i,o){return e+(o-t)/(n-t)*(i-e)},u.TimelineSignal.prototype._exponentialInterpolate=function(t,e,n,i,o){return(e=Math.max(this._minOutput,e))*Math.pow(i/e,(o-t)/(n-t))},u.TimelineSignal.prototype._curveInterpolate=function(t,e,n,i){var o=e.length;if(t+n<=i)return e[o-1];if(i<=t)return e[0];var r=(i-t)/n,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,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(1),n(16),n(30),n(31),n(12)],void 0===(o=function(e){return e.Type={Default:"number",Time:"time",Frequency:"frequency",TransportTime:"transportTime",Ticks:"ticks",NormalRange:"normalRange",AudioRange:"audioRange",Decibels:"db",Interval:"interval",BPM:"bpm",Positive:"positive",Cents:"cents",Degrees:"degrees",MIDI:"midi",BarsBeatsSixteenths:"barsBeatsSixteenths",Samples:"samples",Hertz:"hertz",Note:"note",Milliseconds:"milliseconds",Seconds:"seconds",Notation:"notation"},e.prototype.toSeconds=function(t){return this.isNumber(t)?t:this.isUndef(t)?this.now():this.isString(t)?new e.Time(t).toSeconds():t instanceof e.TimeBase?t.toSeconds():void 0},e.prototype.toFrequency=function(t){return this.isNumber(t)?t:this.isString(t)||this.isUndef(t)?new e.Frequency(t).valueOf():t instanceof e.TimeBase?t.toFrequency():void 0},e.prototype.toTicks=function(t){return this.isNumber(t)||this.isString(t)?new e.TransportTime(t).toTicks():this.isUndef(t)?e.Transport.ticks:t instanceof e.TimeBase?t.toTicks():void 0},e}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(1),n(18),n(9)],void 0===(o=function(n){"use strict";return window.GainNode&&!AudioContext.prototype.createGain&&(AudioContext.prototype.createGain=AudioContext.prototype.createGainNode),n.Gain=function(){var t=this.optionsObject(arguments,["gain","units"],n.Gain.defaults);this.input=this.output=this._gainNode=this.context.createGain(),this.gain=new n.Param({param:this._gainNode.gain,units:t.units,value:t.gain,convert:t.convert}),this._readOnly("gain")},n.extend(n.Gain),n.Gain.defaults={gain:1,convert:!0},n.Gain.prototype.dispose=function(){n.Param.prototype.dispose.call(this),this._gainNode.disconnect(),this._gainNode=null,this._writable("gain"),this.gain.dispose(),this.gain=null},n.prototype.createInsOuts=function(t,e){1===t?this.input=new n.Gain:1this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var n=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=n.time,this.isUndef(n.offset)||(this.ticks=n.offset),this.emit("start",n.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",n.time)):e===o.State.Paused&&this.emit("pause",n.time)}var i=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(i),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,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(1),n(14)],void 0===(o=function(i){function t(t,e,n){if(t.input)Array.isArray(t.input)?(i.prototype.isUndef(n)&&(n=0),this.connect(t.input[n])):this.connect(t.input,e,n);else try{t instanceof AudioNode?o.call(this,t,e,n):o.call(this,t,e)}catch(e){throw new Error("error connecting to node: "+t+"\n"+e)}}var o,r;return!window.hasOwnProperty("AudioContext")&&window.hasOwnProperty("webkitAudioContext")&&(window.AudioContext=window.webkitAudioContext),i.Context=function(t){for(var e in i.Emitter.call(this),t=t||new window.AudioContext,this._context=t,this._context)this._defineProperty(this._context,e);this._latencyHint="interactive",this._lookAhead=.1,this._updateInterval=this._lookAhead/3,this._computedUpdateInterval=0,this._worker=this._createWorker(),this._constants={}},i.extend(i.Context,i.Emitter),i.Emitter.mixin(i.Context),i.Context.prototype._defineProperty=function(e,n){this.isUndef(this[n])&&Object.defineProperty(this,n,{get:function(){return"function"==typeof e[n]?e[n].bind(e):e[n]},set:function(t){e[n]=t}})},i.Context.prototype.now=function(){return this._context.currentTime},i.Context.prototype._createWorker=function(){window.URL=window.URL||window.webkitURL;var t=new Blob(["var timeoutTime = "+(1e3*this._updateInterval).toFixed(1)+";self.onmessage = function(msg){\ttimeoutTime = parseInt(msg.data);};function tick(){\tsetTimeout(tick, timeoutTime);\tself.postMessage('tick');}tick();"]),e=URL.createObjectURL(t),n=new Worker(e);return n.addEventListener("message",function(){this.emit("tick")}.bind(this)),n.addEventListener("message",function(){var t=this.now();if(this.isNumber(this._lastUpdate)){var e=t-this._lastUpdate;this._computedUpdateInterval=Math.max(e,.97*this._computedUpdateInterval)}this._lastUpdate=t}.bind(this)),n},i.Context.prototype.getConstant=function(t){if(this._constants[t])return this._constants[t];for(var e=this._context.createBuffer(1,128,this._context.sampleRate),n=e.getChannelData(0),i=0;ithis.memory){var n=this.length-this.memory;this._timeline.splice(0,n)}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,n=this._timeline.length,i=n;if(0t)return o;r.time>t?i=o:r.time=t;)n--;return this._iterate(e,n+1),this},e.Timeline.prototype.forEachAtTime=function(e,n){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&n(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(1),n(2),n(0)],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,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(1),n(0),n(2),n(7)],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,i))||(t.exports=o)},function(t,e,n){var i,o,r;o=[],void 0===(r="function"==typeof(i=function(){var s=function(t,e){this._dragged=!1,this._element=t,this._bindedMove=this._moved.bind(this),this._bindedEnd=this._ended.bind(this,e),t.addEventListener("touchstart",this._bindedEnd),t.addEventListener("touchmove",this._bindedMove),t.addEventListener("touchend",this._bindedEnd),t.addEventListener("mouseup",this._bindedEnd)};function r(t){return"running"===t.state}return s.prototype._moved=function(t){this._dragged=!0},s.prototype._ended=function(t){this._dragged||function(t){var e=t.createBuffer(1,1,t.sampleRate),n=t.createBufferSource();n.buffer=e,n.connect(t.destination),n.start(0),t.resume&&t.resume()}(t),this._dragged=!1},s.prototype.dispose=function(){this._element.removeEventListener("touchstart",this._bindedEnd),this._element.removeEventListener("touchmove",this._bindedMove),this._element.removeEventListener("touchend",this._bindedEnd),this._element.removeEventListener("mouseup",this._bindedEnd),this._bindedMove=null,this._bindedEnd=null,this._element=null},function(e,t,n){var i=new Promise(function(t){!function(e,n){r(e)?n():function t(){r(e)?n():(requestAnimationFrame(t),e.resume&&e.resume())}()}(e,t)}),o=[];return function t(e,n,i){if(Array.isArray(e)||NodeList&&e instanceof NodeList)for(var o=0;o= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\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.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\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) {\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 this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\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 var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\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,n){"use strict";n.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 _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\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\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'},function(t,e,n){"use strict";n.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 _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\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\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\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.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\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 } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'},function(t,e,n){var i,o;i=[n(1),n(17)],void 0===(o=function(o){o.Frequency=function(t,e){if(!(this instanceof o.Frequency))return new o.Frequency(t,e);o.TimeBase.call(this,t,e)},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(t){return this.midiToFrequency(t)}},o.Frequency.prototype._primaryExpressions.note={regexp:/^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,method:function(t,e){var n=i[t.toLowerCase()]+12*(parseInt(e)+1);return this.midiToFrequency(n)}},o.Frequency.prototype._primaryExpressions.tr={regexp:/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,method:function(t,e,n){var i=1;return t&&"0"!==t&&(i*=this._beatsToUnits(this._timeSignature()*parseFloat(t))),e&&"0"!==e&&(i*=this._beatsToUnits(parseFloat(e))),n&&"0"!==n&&(i*=this._beatsToUnits(parseFloat(n)/4)),i}},o.Frequency.prototype.transpose=function(t){return this._expr=function(t,e){return t()*this.intervalToFrequencyRatio(e)}.bind(this,this._expr,t),this},o.Frequency.prototype.harmonize=function(t){return this._expr=function(t,e){for(var n=t(),i=[],o=0;othis.cutoff&&e>this.threshold&&0this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var n=t||0,i=e||void 0;this.isPlaying()&&(this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,n,i))},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,n=e.length/t,i=~~(n/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/b.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var n=this.buffer.numberOfChannels,i=0;ie){var r=t[o],s=new T(r,o);n[o]=s,o+=6e3}o++}return n}function S(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180t[r].hi&&r++,o[r]=void 0!==o[r]?(o[r]+n[s])/2:n[s]}return o},p5.FFT.prototype.getOctaveBands=function(t,e){var n=t||3,i=e||15.625,o=[],r={lo:i/Math.pow(2,1/(2*n)),ctr:i,hi:i*Math.pow(2,1/(2*n))};o.push(r);for(var s=l.audiocontext.sampleRate/2;r.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,i&&(this._leftFilter.freq(i),this._rightFilter.freq(i))},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(){L.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};p5.Delay;p5.Reverb=function(){L.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(L.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,n,i){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),n&&(this._decay=n),i&&(this._reverse=i),o&&this._buildImpulse()},p5.Reverb.prototype.set=function(t,e,n){var i=!1;t&&(this._seconds=t,i=!0),e&&(this._decay=e),n&&(this._reverse=n),i&&this._buildImpulse()},p5.Reverb.prototype._buildImpulse=function(){var t,e,n=this.ac.sampleRate,i=n*this._seconds,o=this._decay,r=this.ac.createBuffer(2,i,n),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 n in Y=t,l.parts)l.parts[n]&&l.parts[n].setBPM(t,e)},p5.Phrase=function(t,e,n){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=n},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(Y),l.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,n){var i;if(3===arguments.length)i=new p5.Phrase(t,e,n);else{if(!(t instanceof p5.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";i=t}this.phrases.push(i),i.sequence.length>this.length&&(this.length=i.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 n in this.phrases)this.phrases[n].name===t&&(this.phrases[n].sequence=e)},p5.Part.prototype.incrementStep=function(t){this.partStept)this.cancelScheduledValues(t),this.linearRampToValueAtTime(e,t);else{var i=this._searchAfter(t);i&&(this.cancelScheduledValues(t),i.type===u.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):i.type===u.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},u.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.linearRampToValueAtTime(t,n),this},u.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,n),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),n=this._searchBefore(t),i=this._initial;if(null===n)i=this._initial;else if(n.type===u.TimelineSignal.Type.Target){var r,o=this._events.getBefore(n.time);r=null===o?this._initial:o.value,i=this._exponentialApproach(n.time,r,n.value,n.constant,t)}else i=n.type===u.TimelineSignal.Type.Curve?this._curveInterpolate(n.time,n.value,n.duration,t):null===e?n.value:e.type===u.TimelineSignal.Type.Linear?this._linearInterpolate(n.time,n.value,e.time,e.value,t):e.type===u.TimelineSignal.Type.Exponential?this._exponentialInterpolate(n.time,n.value,e.time,e.value,t):n.value;return i},u.TimelineSignal.prototype.connect=u.SignalBase.prototype.connect,u.TimelineSignal.prototype._exponentialApproach=function(t,e,n,i,r){return n+(e-n)*Math.exp(-(r-t)/i)},u.TimelineSignal.prototype._linearInterpolate=function(t,e,n,i,r){return e+(r-t)/(n-t)*(i-e)},u.TimelineSignal.prototype._exponentialInterpolate=function(t,e,n,i,r){return(e=Math.max(this._minOutput,e))*Math.pow(i/e,(r-t)/(n-t))},u.TimelineSignal.prototype._curveInterpolate=function(t,e,n,i){var r=e.length;if(t+n<=i)return e[r-1];if(i<=t)return e[0];var o=(i-t)/n,s=Math.floor((r-1)*o),a=Math.ceil((r-1)*o),u=e[s],c=e[a];return a===s?u:this._linearInterpolate(s,u,a,c,o*(r-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,i))||(t.exports=r)},function(t,e,n){var i,r;i=[n(0),n(4),n(1),n(2)],void 0===(r=function(n){"use strict";return n.Scale=function(t,e){this._outputMin=this.defaultArg(t,0),this._outputMax=this.defaultArg(e,1),this._scale=this.input=new n.Multiply(1),this._add=this.output=new n.Add(0),this._scale.connect(this._add),this._setRange()},n.extend(n.Scale,n.SignalBase),Object.defineProperty(n.Scale.prototype,"min",{get:function(){return this._outputMin},set:function(t){this._outputMin=t,this._setRange()}}),Object.defineProperty(n.Scale.prototype,"max",{get:function(){return this._outputMax},set:function(t){this._outputMax=t,this._setRange()}}),n.Scale.prototype._setRange=function(){this._add.value=this._outputMin,this._scale.value=this._outputMax-this._outputMin},n.Scale.prototype.dispose=function(){return n.prototype.dispose.call(this),this._add.dispose(),this._add=null,this._scale.dispose(),this._scale=null,this},n.Scale}.apply(e,i))||(t.exports=r)},function(t,e,n){var i,r;i=[n(0),n(16),n(30),n(31),n(12)],void 0===(r=function(e){return e.Type={Default:"number",Time:"time",Frequency:"frequency",TransportTime:"transportTime",Ticks:"ticks",NormalRange:"normalRange",AudioRange:"audioRange",Decibels:"db",Interval:"interval",BPM:"bpm",Positive:"positive",Cents:"cents",Degrees:"degrees",MIDI:"midi",BarsBeatsSixteenths:"barsBeatsSixteenths",Samples:"samples",Hertz:"hertz",Note:"note",Milliseconds:"milliseconds",Seconds:"seconds",Notation:"notation"},e.prototype.toSeconds=function(t){return this.isNumber(t)?t:this.isUndef(t)?this.now():this.isString(t)?new e.Time(t).toSeconds():t instanceof e.TimeBase?t.toSeconds():void 0},e.prototype.toFrequency=function(t){return this.isNumber(t)?t:this.isString(t)||this.isUndef(t)?new e.Frequency(t).valueOf():t instanceof e.TimeBase?t.toFrequency():void 0},e.prototype.toTicks=function(t){return this.isNumber(t)||this.isString(t)?new e.TransportTime(t).toTicks():this.isUndef(t)?e.Transport.ticks:t instanceof e.TimeBase?t.toTicks():void 0},e}.apply(e,i))||(t.exports=r)},function(t,e,n){var i,r;i=[n(0),n(18),n(9)],void 0===(r=function(n){"use strict";return window.GainNode&&!AudioContext.prototype.createGain&&(AudioContext.prototype.createGain=AudioContext.prototype.createGainNode),n.Gain=function(){var t=this.optionsObject(arguments,["gain","units"],n.Gain.defaults);this.input=this.output=this._gainNode=this.context.createGain(),this.gain=new n.Param({param:this._gainNode.gain,units:t.units,value:t.gain,convert:t.convert}),this._readOnly("gain")},n.extend(n.Gain),n.Gain.defaults={gain:1,convert:!0},n.Gain.prototype.dispose=function(){n.Param.prototype.dispose.call(this),this._gainNode.disconnect(),this._gainNode=null,this._writable("gain"),this.gain.dispose(),this.gain=null},n.prototype.createInsOuts=function(t,e){1===t?this.input=new n.Gain:1this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var n=this._state.get(this._nextTick);e===r.State.Started?(this._nextTick=n.time,this.isUndef(n.offset)||(this.ticks=n.offset),this.emit("start",n.time,this.ticks)):e===r.State.Stopped?(this.ticks=0,this.emit("stop",n.time)):e===r.State.Paused&&this.emit("pause",n.time)}var i=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===r.State.Started&&(this.callback(i),this.ticks++))}},r.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},r.Clock.prototype.dispose=function(){r.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},r.Clock}.apply(e,i))||(t.exports=r)},function(t,e,n){var i,r;i=[n(0),n(14)],void 0===(r=function(i){function t(t,e,n){if(t.input)Array.isArray(t.input)?(i.prototype.isUndef(n)&&(n=0),this.connect(t.input[n])):this.connect(t.input,e,n);else try{t instanceof AudioNode?r.call(this,t,e,n):r.call(this,t,e)}catch(e){throw new Error("error connecting to node: "+t+"\n"+e)}}var r,o;return!window.hasOwnProperty("AudioContext")&&window.hasOwnProperty("webkitAudioContext")&&(window.AudioContext=window.webkitAudioContext),i.Context=function(t){for(var e in i.Emitter.call(this),t=t||new window.AudioContext,this._context=t,this._context)this._defineProperty(this._context,e);this._latencyHint="interactive",this._lookAhead=.1,this._updateInterval=this._lookAhead/3,this._computedUpdateInterval=0,this._worker=this._createWorker(),this._constants={}},i.extend(i.Context,i.Emitter),i.Emitter.mixin(i.Context),i.Context.prototype._defineProperty=function(e,n){this.isUndef(this[n])&&Object.defineProperty(this,n,{get:function(){return"function"==typeof e[n]?e[n].bind(e):e[n]},set:function(t){e[n]=t}})},i.Context.prototype.now=function(){return this._context.currentTime},i.Context.prototype._createWorker=function(){window.URL=window.URL||window.webkitURL;var t=new Blob(["var timeoutTime = "+(1e3*this._updateInterval).toFixed(1)+";self.onmessage = function(msg){\ttimeoutTime = parseInt(msg.data);};function tick(){\tsetTimeout(tick, timeoutTime);\tself.postMessage('tick');}tick();"]),e=URL.createObjectURL(t),n=new Worker(e);return n.addEventListener("message",function(){this.emit("tick")}.bind(this)),n.addEventListener("message",function(){var t=this.now();if(this.isNumber(this._lastUpdate)){var e=t-this._lastUpdate;this._computedUpdateInterval=Math.max(e,.97*this._computedUpdateInterval)}this._lastUpdate=t}.bind(this)),n},i.Context.prototype.getConstant=function(t){if(this._constants[t])return this._constants[t];for(var e=this._context.createBuffer(1,128,this._context.sampleRate),n=e.getChannelData(0),i=0;ithis.memory){var n=this.length-this.memory;this._timeline.splice(0,n)}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,n=this._timeline.length,i=n;if(0t)return r;o.time>t?i=r:o.time=t;)n--;return this._iterate(e,n+1),this},e.Timeline.prototype.forEachAtTime=function(e,n){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&n(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,i))||(t.exports=r)},function(t,e,n){var i,r;i=[n(0),n(1),n(2)],void 0===(r=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,i))||(t.exports=r)},function(t,e,n){var i,r;i=[n(0),n(2),n(1),n(6)],void 0===(r=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,i))||(t.exports=r)},function(t,e,n){var i,r,o;r=[],void 0===(o="function"==typeof(i=function(){var s=function(t,e){this._dragged=!1,this._element=t,this._bindedMove=this._moved.bind(this),this._bindedEnd=this._ended.bind(this,e),t.addEventListener("touchstart",this._bindedEnd),t.addEventListener("touchmove",this._bindedMove),t.addEventListener("touchend",this._bindedEnd),t.addEventListener("mouseup",this._bindedEnd)};function o(t){return"running"===t.state}return s.prototype._moved=function(t){this._dragged=!0},s.prototype._ended=function(t){this._dragged||function(t){var e=t.createBuffer(1,1,t.sampleRate),n=t.createBufferSource();n.buffer=e,n.connect(t.destination),n.start(0),t.resume&&t.resume()}(t),this._dragged=!1},s.prototype.dispose=function(){this._element.removeEventListener("touchstart",this._bindedEnd),this._element.removeEventListener("touchmove",this._bindedMove),this._element.removeEventListener("touchend",this._bindedEnd),this._element.removeEventListener("mouseup",this._bindedEnd),this._bindedMove=null,this._bindedEnd=null,this._element=null},function(e,t,n){var i=new Promise(function(t){!function(e,n){o(e)?n():function t(){o(e)?n():(requestAnimationFrame(t),e.resume&&e.resume())}()}(e,t)}),r=[];return function t(e,n,i){if(Array.isArray(e)||NodeList&&e instanceof NodeList)for(var r=0;r= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\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.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\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) {\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 this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\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 var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\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,n){"use strict";n.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 _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\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\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'},function(t,e,n){"use strict";n.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 _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\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\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\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.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\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 } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'},function(t,e,n){var i,r;i=[n(0),n(17)],void 0===(r=function(r){r.Frequency=function(t,e){if(!(this instanceof r.Frequency))return new r.Frequency(t,e);r.TimeBase.call(this,t,e)},r.extend(r.Frequency,r.TimeBase),r.Frequency.prototype._primaryExpressions=Object.create(r.TimeBase.prototype._primaryExpressions),r.Frequency.prototype._primaryExpressions.midi={regexp:/^(\d+(?:\.\d+)?midi)/,method:function(t){return this.midiToFrequency(t)}},r.Frequency.prototype._primaryExpressions.note={regexp:/^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,method:function(t,e){var n=i[t.toLowerCase()]+12*(parseInt(e)+1);return this.midiToFrequency(n)}},r.Frequency.prototype._primaryExpressions.tr={regexp:/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,method:function(t,e,n){var i=1;return t&&"0"!==t&&(i*=this._beatsToUnits(this._timeSignature()*parseFloat(t))),e&&"0"!==e&&(i*=this._beatsToUnits(parseFloat(e))),n&&"0"!==n&&(i*=this._beatsToUnits(parseFloat(n)/4)),i}},r.Frequency.prototype.transpose=function(t){return this._expr=function(t,e){return t()*this.intervalToFrequencyRatio(e)}.bind(this,this._expr,t),this},r.Frequency.prototype.harmonize=function(t){return this._expr=function(t,e){for(var n=t(),i=[],r=0;re){var o=t[r],s=new C(o,r);n[r]=s,r+=6e3}r++}return n}function q(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var n=t||0,i=e||void 0;this.isPlaying()&&(this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,n,i))}},{key:"channels",value:function(){return this.buffer.numberOfChannels}},{key:"sampleRate",value:function(){return this.buffer.sampleRate}},{key:"frames",value:function(){return this.buffer.length}},{key:"getPeaks",value: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,n=e.length/t,i=~~(n/10)||1,r=e.numberOfChannels,o=new Float32Array(Math.round(t)),s=0;so[u])&&(o[u]=h)}return o}}},{key:"reverseBuffer",value:function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/O.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var n=this.buffer.numberOfChannels,i=0;it[o].hi&&o++,r[o]=void 0!==r[o]?(r[o]+n[s])/2:n[s]}return r}},{key:"getOctaveBands",value:function(t,e){var n=t||3,i=e||15.625,r=[],o={lo:i/Math.pow(2,1/(2*n)),ctr:i,hi:i*Math.pow(2,1/(2*n))};r.push(o);for(var s=p.audiocontext.sampleRate/2;o.hi=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(o,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(o,this.ac.currentTime),this._leftGain.gain.value=r,this._rightGain.gain.value=r,i&&(this._leftFilter.freq(i),this._rightFilter.freq(i))}},{key:"delayTime",value: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))}},{key:"feedback",value: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}},{key:"filter",value:function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)}},{key:"setType",value: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)}}},{key:"dispose",value:function(){me(ve(e.prototype),"dispose",this).call(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}}]),e}();function be(t){return(be="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)}function Te(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function we(t,e){for(var n=0;nthis.length&&(this.length=i.sequence.length)}},{key:"removePhrase",value:function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)}},{key:"getPhrase",value:function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]}},{key:"replaceSequence",value:function(t,e){for(var n in this.phrases)this.phrases[n].name===t&&(this.phrases[n].sequence=e)}},{key:"incrementStep",value:function(t){this.partStep=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}function Le(t,e){for(var n=0;nthis.cutoff&&e>this.threshold&&0this.treshold){this.isDetected=!0,this.callback?this.callback(this.energy):e&&e(this.energy);var n=this;setTimeout(function(){n.isDetected=!1},this.sensitivity)}this.penergy=this.energy}}]),r}();function kn(t,e){for(var n=0;nconnect. \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});","/**\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","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","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/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","module.exports = {\n recorderProcessor: 'recorder-processor',\n soundFileProcessor: 'sound-file-processor',\n amplitudeProcessor: 'amplitude-processor',\n};\n","global.TONE_SILENCE_VERSION_LOGGING = true;\n\nimport StartAudioContext from 'startaudiocontext';\nimport Tone from 'Tone/core/Tone';\nimport 'Tone/core/Context';\n\n// Create the Audio Context\nconst audiocontext = new window.AudioContext();\n\n// Tone and p5.sound share the same audio context\nTone.setContext(audiocontext);\n\n/**\n *

Returns the Audio Context for this sketch. Useful for users\n * who would like to dig deeper into the Web Audio API\n * .

\n *\n *

Some browsers require users to startAudioContext\n * with a user gesture, such as touchStarted in the example below.

\n *\n * @for p5\n * @method getAudioContext\n * @return {Object} AudioContext for this sketch\n * @example\n *
\n * function draw() {\n * background(255);\n * textAlign(CENTER);\n *\n * if (getAudioContext().state !== 'running') {\n * text('click to start audio', width/2, height/2);\n * } else {\n * text('audio is enabled', width/2, height/2);\n * }\n * }\n *\n * function touchStarted() {\n * if (getAudioContext().state !== 'running') {\n * getAudioContext().resume();\n * }\n * var synth = new p5.MonoSynth();\n * synth.play('A4', 0.5, 0, 0.2);\n * }\n *\n *
\n */\np5.prototype.getAudioContext = function () {\n return audiocontext;\n};\n\n/**\n *

It is not only a good practice to give users control over starting\n * audio. This policy is enforced by many web browsers, including iOS and\n * Google Chrome, which create the Web Audio API's\n * Audio Context\n * in a suspended state.

\n *\n *

In these browser-specific policies, sound will not play until a user\n * interaction event (i.e. mousePressed()) explicitly resumes\n * the AudioContext, or starts an audio node. This can be accomplished by\n * calling start() on a p5.Oscillator,\n * play() on a p5.SoundFile, or simply\n * userStartAudio().

\n *\n *

userStartAudio() starts the AudioContext on a user\n * gesture. The default behavior will enable audio on any\n * mouseUp or touchEnd event. It can also be placed in a specific\n * interaction function, such as mousePressed() as in the\n * example below. This method utilizes\n * StartAudioContext\n * , a library by Yotam Mann (MIT Licence, 2016).

\n * @param {Element|Array} [element(s)] This argument can be an Element,\n * Selector String, NodeList, p5.Element,\n * jQuery Element, or an Array of any of those.\n * @param {Function} [callback] Callback to invoke when the AudioContext\n * has started\n * @return {Promise} Returns a Promise that resolves when\n * the AudioContext state is 'running'\n * @method userStartAudio\n * @for p5\n * @example\n *
\n * function setup() {\n * // mimics the autoplay policy\n * getAudioContext().suspend();\n *\n * let mySynth = new p5.MonoSynth();\n *\n * // This won't play until the context has resumed\n * mySynth.play('A6');\n * }\n * function draw() {\n * background(220);\n * textAlign(CENTER, CENTER);\n * text(getAudioContext().state, width/2, height/2);\n * }\n * function mousePressed() {\n * userStartAudio();\n * }\n *
\n */\np5.prototype.userStartAudio = function (elements, callback) {\n var elt = elements;\n if (elements instanceof p5.Element) {\n elt = elements.elt;\n } else if (elements instanceof Array && elements[0] instanceof p5.Element) {\n elt = elements.map(function (e) {\n return e.elt;\n });\n }\n return StartAudioContext(audiocontext, elt, callback);\n};\n\nexport default audiocontext;\n","define([\"Tone/core/Tone\", \"Tone/signal/SignalBase\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Wraps the native Web Audio API \n\t * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {function|Array|Number} mapping The function used to define the values. \n\t * The mapping function should take two arguments: \n\t * the first is the value at the current position \n\t * and the second is the array position. \n\t * If the argument is an array, that array will be\n\t * set as the wave shaping function. The input\n\t * signal is an AudioRange [-1, 1] value and the output\n\t * signal can take on any numerical values. \n\t * \n\t * @param {Number} [bufferLen=1024] The length of the WaveShaperNode buffer.\n\t * @example\n\t * var timesTwo = new Tone.WaveShaper(function(val){\n\t * \treturn val * 2;\n\t * }, 2048);\n\t * @example\n\t * //a waveshaper can also be constructed with an array of values\n\t * var invert = new Tone.WaveShaper([1, -1]);\n\t */\n\tTone.WaveShaper = function(mapping, bufferLen){\n\n\t\t/**\n\t\t * the waveshaper\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._shaper = this.input = this.output = this.context.createWaveShaper();\n\n\t\t/**\n\t\t * the waveshapers curve\n\t\t * @type {Float32Array}\n\t\t * @private\n\t\t */\n\t\tthis._curve = null;\n\n\t\tif (Array.isArray(mapping)){\n\t\t\tthis.curve = mapping;\n\t\t} else if (isFinite(mapping) || this.isUndef(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(mapping, 1024));\n\t\t} else if (this.isFunction(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(bufferLen, 1024));\n\t\t\tthis.setMap(mapping);\n\t\t} \n\t};\n\n\tTone.extend(Tone.WaveShaper, Tone.SignalBase);\n\n\t/**\n\t * Uses a mapping function to set the value of the curve. \n\t * @param {function} mapping The function used to define the values. \n\t * The mapping function take two arguments: \n\t * the first is the value at the current position \n\t * which goes from -1 to 1 over the number of elements\n\t * in the curve array. The second argument is the array position. \n\t * @returns {Tone.WaveShaper} this\n\t * @example\n\t * //map the input signal from [-1, 1] to [0, 10]\n\t * shaper.setMap(function(val, index){\n\t * \treturn (val + 1) * 5;\n\t * })\n\t */\n\tTone.WaveShaper.prototype.setMap = function(mapping){\n\t\tfor (var i = 0, len = this._curve.length; i < len; i++){\n\t\t\tvar normalized = (i / (len - 1)) * 2 - 1;\n\t\t\tthis._curve[i] = mapping(normalized, i);\n\t\t}\n\t\tthis._shaper.curve = this._curve;\n\t\treturn this;\n\t};\n\n\t/**\n\t * The array to set as the waveshaper curve. For linear curves\n\t * array length does not make much difference, but for complex curves\n\t * longer arrays will provide smoother interpolation. \n\t * @memberOf Tone.WaveShaper#\n\t * @type {Array}\n\t * @name curve\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"curve\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.curve;\n\t\t},\n\t\tset : function(mapping){\n\t\t\tthis._curve = new Float32Array(mapping);\n\t\t\tthis._shaper.curve = this._curve;\n\t\t}\n\t});\n\n\t/**\n\t * Specifies what type of oversampling (if any) should be used when \n\t * applying the shaping curve. Can either be \"none\", \"2x\" or \"4x\". \n\t * @memberOf Tone.WaveShaper#\n\t * @type {string}\n\t * @name oversample\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"oversample\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.oversample;\n\t\t},\n\t\tset : function(oversampling){\n\t\t\tif ([\"none\", \"2x\", \"4x\"].indexOf(oversampling) !== -1){\n\t\t\t\tthis._shaper.oversample = oversampling;\n\t\t\t} else {\n\t\t\t\tthrow new RangeError(\"Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'\");\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.WaveShaper} this\n\t */\n\tTone.WaveShaper.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.disconnect();\n\t\tthis._shaper = null;\n\t\tthis._curve = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.WaveShaper;\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});","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});","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});","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/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});","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});","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});","/**\n * StartAudioContext.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2016 Yotam Mann\n */\n(function (root, factory) {\n\tif (typeof define === \"function\" && define.amd) {\n\t\tdefine([], factory)\n\t } else if (typeof module === \"object\" && module.exports) {\n module.exports = factory()\n\t} else {\n\t\troot.StartAudioContext = factory()\n }\n}(this, function () {\n\n\t//TAP LISTENER/////////////////////////////////////////////////////////////\n\n\t/**\n\t * @class Listens for non-dragging tap ends on the given element\n\t * @param {Element} element\n\t * @internal\n\t */\n\tvar TapListener = function(element, context){\n\n\t\tthis._dragged = false\n\n\t\tthis._element = element\n\n\t\tthis._bindedMove = this._moved.bind(this)\n\t\tthis._bindedEnd = this._ended.bind(this, context)\n\n\t\telement.addEventListener(\"touchstart\", this._bindedEnd)\n\t\telement.addEventListener(\"touchmove\", this._bindedMove)\n\t\telement.addEventListener(\"touchend\", this._bindedEnd)\n\t\telement.addEventListener(\"mouseup\", this._bindedEnd)\n\t}\n\n\t/**\n\t * drag move event\n\t */\n\tTapListener.prototype._moved = function(e){\n\t\tthis._dragged = true\n\t};\n\n\t/**\n\t * tap ended listener\n\t */\n\tTapListener.prototype._ended = function(context){\n\t\tif (!this._dragged){\n\t\t\tstartContext(context)\n\t\t}\n\t\tthis._dragged = false\n\t};\n\n\t/**\n\t * remove all the bound events\n\t */\n\tTapListener.prototype.dispose = function(){\n\t\tthis._element.removeEventListener(\"touchstart\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"touchmove\", this._bindedMove)\n\t\tthis._element.removeEventListener(\"touchend\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"mouseup\", this._bindedEnd)\n\t\tthis._bindedMove = null\n\t\tthis._bindedEnd = null\n\t\tthis._element = null\n\t};\n\n\t//END TAP LISTENER/////////////////////////////////////////////////////////\n\n\t/**\n\t * Plays a silent sound and also invoke the \"resume\" method\n\t * @param {AudioContext} context\n\t * @private\n\t */\n\tfunction startContext(context){\n\t\t// this accomplishes the iOS specific requirement\n\t\tvar buffer = context.createBuffer(1, 1, context.sampleRate)\n\t\tvar source = context.createBufferSource()\n\t\tsource.buffer = buffer\n\t\tsource.connect(context.destination)\n\t\tsource.start(0)\n\n\t\t// resume the audio context\n\t\tif (context.resume){\n\t\t\tcontext.resume()\n\t\t}\n\t}\n\n\t/**\n\t * Returns true if the audio context is started\n\t * @param {AudioContext} context\n\t * @return {Boolean}\n\t * @private\n\t */\n\tfunction isStarted(context){\n\t\t return context.state === \"running\"\n\t}\n\n\t/**\n\t * Invokes the callback as soon as the AudioContext\n\t * is started\n\t * @param {AudioContext} context\n\t * @param {Function} callback\n\t */\n\tfunction onStarted(context, callback){\n\n\t\tfunction checkLoop(){\n\t\t\tif (isStarted(context)){\n\t\t\t\tcallback()\n\t\t\t} else {\n\t\t\t\trequestAnimationFrame(checkLoop)\n\t\t\t\tif (context.resume){\n\t\t\t\t\tcontext.resume()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isStarted(context)){\n\t\t\tcallback()\n\t\t} else {\n\t\t\tcheckLoop()\n\t\t}\n\t}\n\n\t/**\n\t * Add a tap listener to the audio context\n\t * @param {Array|Element|String|jQuery} element\n\t * @param {Array} tapListeners\n\t */\n\tfunction bindTapListener(element, tapListeners, context){\n\t\tif (Array.isArray(element) || (NodeList && element instanceof NodeList)){\n\t\t\tfor (var i = 0; i < element.length; i++){\n\t\t\t\tbindTapListener(element[i], tapListeners, context)\n\t\t\t}\n\t\t} else if (typeof element === \"string\"){\n\t\t\tbindTapListener(document.querySelectorAll(element), tapListeners, context)\n\t\t} else if (element.jquery && typeof element.toArray === \"function\"){\n\t\t\tbindTapListener(element.toArray(), tapListeners, context)\n\t\t} else if (Element && element instanceof Element){\n\t\t\t//if it's an element, create a TapListener\n\t\t\tvar tap = new TapListener(element, context)\n\t\t\ttapListeners.push(tap)\n\t\t} \n\t}\n\n\t/**\n\t * @param {AudioContext} context The AudioContext to start.\n\t * @param {Array|String|Element|jQuery=} elements For iOS, the list of elements\n\t * to bind tap event listeners\n\t * which will start the AudioContext. If\n\t * no elements are given, it will bind\n\t * to the document.body.\n\t * @param {Function=} callback The callback to invoke when the AudioContext is started.\n\t * @return {Promise} The promise is invoked when the AudioContext\n\t * is started.\n\t */\n\tfunction StartAudioContext(context, elements, callback){\n\n\t\t//the promise is invoked when the AudioContext is started\n\t\tvar promise = new Promise(function(success) {\n\t\t\tonStarted(context, success)\n\t\t})\n\n\t\t// The TapListeners bound to the elements\n\t\tvar tapListeners = []\n\n\t\t// add all the tap listeners\n\t\tif (!elements){\n\t\t\telements = document.body\n\t\t}\n\t\tbindTapListener(elements, tapListeners, context)\n\n\t\t//dispose all these tap listeners when the context is started\n\t\tpromise.then(function(){\n\t\t\tfor (var i = 0; i < tapListeners.length; i++){\n\t\t\t\ttapListeners[i].dispose()\n\t\t\t}\n\t\t\ttapListeners = null\n\n\t\t\tif (callback){\n\t\t\t\tcallback()\n\t\t\t}\n\t\t})\n\n\t\treturn promise\n\t}\n\n\treturn StartAudioContext\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","!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._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\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.numOutputChannels = options.outputChannelCount || 2;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.bufferSize = processorOptions.bufferSize || 1024;\\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) {\\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 this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannelCopy);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n }\\n\\n this.recordedSamples += this.bufferSize;\\n }\\n\\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 var _this2 = this;\\n\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this2.bufferSize);\\n });\\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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0].length;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar SoundFileProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\\n\\n function SoundFileProcessor(options) {\\n var _this;\\n\\n _classCallCheck(this, SoundFileProcessor);\\n\\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\\n var processorOptions = options.processorOptions || {};\\n _this.bufferSize = processorOptions.bufferSize || 256;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\\n return _this;\\n }\\n\\n _createClass(SoundFileProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs) {\\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\\n\\n this.inputRingBuffer.push([input[0]]);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n var inputChannel = this.inputRingBufferArraySequence[0];\\n var position = inputChannel[inputChannel.length - 1] || 0;\\n this.port.postMessage({\\n name: 'position',\\n position: position\\n });\\n }\\n\\n return true;\\n }\\n }]);\\n\\n return SoundFileProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);\"","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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0].length;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar AmplitudeProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\\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.numOutputChannels = options.outputChannelCount || 1;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.normalize = processorOptions.normalize || false;\\n _this.smoothing = processorOptions.smoothing || 0;\\n _this.bufferSize = processorOptions.bufferSize || 2048;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this.bufferSize);\\n });\\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 } else if (data.name === 'smoothing') {\\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\\n }\\n };\\n\\n return _this;\\n } // TO DO make this stereo / dependent on # of audio channels\\n\\n\\n _createClass(AmplitudeProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs, outputs) {\\n var input = inputs[0];\\n var output = outputs[0];\\n var smoothing = this.smoothing;\\n this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\\n } // pull 128 frames out of the ring buffer\\n // if the ring buffer does not have enough frames, the output will be silent\\n\\n\\n this.outputRingBuffer.pull(output);\\n return true;\\n }\\n }]);\\n\\n return AmplitudeProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);\"","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});","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});","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});","/**\n *

PeakDetect works in conjunction with p5.FFT to\n * look for onsets in some or all of the frequency spectrum.\n *

\n *

\n * To use p5.PeakDetect, call update in the draw loop\n * and pass in a p5.FFT object.\n *

\n *

\n * You can listen for a specific part of the frequency spectrum by\n * setting the range between freq1 and freq2.\n *

\n *\n *

threshold is the threshold for detecting a peak,\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\n * as 1.0.

\n *\n *

\n * The update method is meant to be run in the draw loop, and\n * frames determines how many loops must pass before\n * another peak can be detected.\n * For example, if the frameRate() = 60, you could detect the beat of a\n * 120 beat-per-minute song with this equation:\n * framesPerPeak = 60 / (estimatedBPM / 60 );\n *

\n *\n *

\n * Based on example contribtued by @b2renger, and a simple beat detection\n * explanation by Felix Turner.\n *

\n *\n * @class p5.PeakDetect\n * @constructor\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\n * scaled logarithmically where 0.1 is 1/2 the loudness\n * of 1.0. Defaults to 0.35.\n * @param {Number} [framesPerPeak] Defaults to 20.\n * @example\n *
\n *\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 10;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * background(0);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n *\n * // p5.PeakDetect requires a p5.FFT\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n * }\n *\n * function draw() {\n * background(0);\n * text('click to play/pause', width/2, height/2);\n *\n * // peakDetect accepts an fft post-analysis\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * if ( peakDetect.isDetected ) {\n * ellipseWidth = 50;\n * } else {\n * ellipseWidth *= 0.95;\n * }\n *\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // toggle play/stop when canvas is clicked\n * function mouseClicked() {\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * }\n * }\n *
\n */\np5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) {\n // framesPerPeak determines how often to look for a beat.\n // If a beat is provided, try to look for a beat based on bpm\n this.framesPerPeak = _framesPerPeak || 20;\n this.framesSinceLastPeak = 0;\n this.decayRate = 0.95;\n\n this.threshold = threshold || 0.35;\n this.cutoff = 0;\n\n // how much to increase the cutoff\n // TO DO: document this / figure out how to make it accessible\n this.cutoffMult = 1.5;\n\n this.energy = 0;\n this.penergy = 0;\n\n // TO DO: document this property / figure out how to make it accessible\n this.currentValue = 0;\n\n /**\n * isDetected is set to true when a peak is detected.\n *\n * @attribute isDetected {Boolean}\n * @default false\n */\n this.isDetected = false;\n\n this.f1 = freq1 || 40;\n this.f2 = freq2 || 20000;\n\n // function to call when a peak is detected\n this._onPeak = function () {};\n};\n\n/**\n * The update method is run in the draw loop.\n *\n * Accepts an FFT object. You must call .analyze()\n * on the FFT object prior to updating the peakDetect\n * because it relies on a completed FFT analysis.\n *\n * @method update\n * @param {p5.FFT} fftObject A p5.FFT object\n */\np5.PeakDetect.prototype.update = function (fftObject) {\n var nrg = (this.energy = fftObject.getEnergy(this.f1, this.f2) / 255);\n if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) {\n // trigger callback\n this._onPeak();\n this.isDetected = true;\n\n // debounce\n this.cutoff = nrg * this.cutoffMult;\n this.framesSinceLastPeak = 0;\n } else {\n this.isDetected = false;\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\n this.framesSinceLastPeak++;\n } else {\n this.cutoff *= this.decayRate;\n this.cutoff = Math.max(this.cutoff, this.threshold);\n }\n }\n\n this.currentValue = nrg;\n this.penergy = nrg;\n};\n\n/**\n * onPeak accepts two arguments: a function to call when\n * a peak is detected. The value of the peak,\n * between 0.0 and 1.0, is passed to the callback.\n *\n * @method onPeak\n * @param {Function} callback Name of a function that will\n * be called when a peak is\n * detected.\n * @param {Object} [val] Optional value to pass\n * into the function when\n * a peak is detected.\n * @example\n *
\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 0;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * cnv = createCanvas(100,100);\n * textAlign(CENTER);\n *\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n *\n * setupSound();\n *\n * // when a beat is detected, call triggerBeat()\n * peakDetect.onPeak(triggerBeat);\n * }\n *\n * function draw() {\n * background(0);\n * fill(255);\n * text('click to play', width/2, height/2);\n *\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * ellipseWidth *= 0.95;\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // this function is called by peakDetect.onPeak\n * function triggerBeat() {\n * ellipseWidth = 50;\n * }\n *\n * // mouseclick starts/stops sound\n * function setupSound() {\n * cnv.mouseClicked( function() {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * });\n * }\n *
\n */\np5.PeakDetect.prototype.onPeak = function (callback, val) {\n var self = this;\n\n self._onPeak = function () {\n callback(self.energy, val);\n };\n};\n","import audiocontext from './audiocontext.js';\n// Master contains the master sound output.\nvar Master = function () {\n this.input = audiocontext.createGain();\n this.output = audiocontext.createGain();\n\n //put a hard limiter on the output\n this.limiter = audiocontext.createDynamicsCompressor();\n this.limiter.threshold.value = -3;\n this.limiter.ratio.value = 20;\n this.limiter.knee.value = 1;\n\n this.audiocontext = audiocontext;\n\n this.output.disconnect();\n\n // connect input to limiter\n this.input.connect(this.limiter);\n\n // connect limiter to output\n this.limiter.connect(this.output);\n\n // meter is just for global Amplitude / FFT analysis\n this.meter = audiocontext.createGain();\n this.fftMeter = audiocontext.createGain();\n this.output.connect(this.meter);\n this.output.connect(this.fftMeter);\n\n // connect output to destination\n this.output.connect(this.audiocontext.destination);\n\n // an array of all sounds in the sketch\n this.soundArray = [];\n // an array of all musical parts in the sketch\n this.parts = [];\n\n // file extensions to search for\n this.extensions = [];\n};\n\n// create a single instance of the p5Sound / master output for use within this sketch\nconst p5sound = new Master();\n// console.log(p5sound.audiocontext)\n\n/**\n * Returns a number representing the master amplitude (volume) for sound\n * in this sketch.\n *\n * @method getMasterVolume\n * @return {Number} Master amplitude (volume) for sound in this sketch.\n * Should be between 0.0 (silence) and 1.0.\n */\np5.prototype.getMasterVolume = function () {\n return p5sound.output.gain.value;\n};\n\n/**\n *

Scale the output of all sound in this sketch

\n * Scaled between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n *

How This Works: When you load the p5.sound module, it\n * creates a single instance of p5sound. All sound objects in this\n * module output to p5sound before reaching your computer's output.\n * So if you change the amplitude of p5sound, it impacts all of the\n * sound in this module.

\n *\n *

If no value is provided, returns a Web Audio API Gain Node

\n *\n * @method masterVolume\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\np5.prototype.masterVolume = function (vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = p5sound.output.gain.value;\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(p5sound.output.gain);\n } else {\n // return the Gain Node\n return p5sound.output.gain;\n }\n};\n\n/**\n * `p5.soundOut` is the p5.sound master output. It sends output to\n * the destination of this window's web audio context. It contains\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\n * and Gain Nodes for .input and .output.\n *\n * @property {Object} soundOut\n */\np5.prototype.soundOut = p5.soundOut = p5sound;\n\n// a silent connection to the DesinationNode\n// which will ensure that anything connected to it\n// will not be garbage collected\np5.soundOut._silentNode = p5sound.audiocontext.createGain();\np5.soundOut._silentNode.gain.value = 0;\np5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\n\nexport default p5sound;\n","import p5sound from './master';\nimport processorNames from './audioWorklet/processorNames';\n/**\n * @for p5\n */\n\n/**\n * Returns a number representing the sample rate, in samples per second,\n * of all sound objects in this audio context. It is determined by the\n * sampling rate of your operating system's sound card, and it is not\n * currently possile to change.\n * It is often 44100, or twice the range of human hearing.\n *\n * @method sampleRate\n * @return {Number} samplerate samples per second\n */\np5.prototype.sampleRate = function () {\n return p5sound.audiocontext.sampleRate;\n};\n\n/**\n * Returns the closest MIDI note value for\n * a given frequency.\n *\n * @method freqToMidi\n * @param {Number} frequency A freqeuncy, for example, the \"A\"\n * above Middle C is 440Hz\n * @return {Number} MIDI note value\n */\np5.prototype.freqToMidi = function (f) {\n var mathlog2 = Math.log(f / 440) / Math.log(2);\n var m = Math.round(12 * mathlog2) + 69;\n return m;\n};\n\n/**\n * Returns the frequency value of a MIDI note value.\n * General MIDI treats notes as integers where middle C\n * is 60, C# is 61, D is 62 etc. Useful for generating\n * musical frequencies with oscillators.\n *\n * @method midiToFreq\n * @param {Number} midiNote The number of a MIDI note\n * @return {Number} Frequency value of the given MIDI note\n * @example\n *
\n * let midiNotes = [60, 64, 67, 72];\n * let noteIndex = 0;\n * let midiVal, freq;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * osc = new p5.TriOsc();\n * env = new p5.Envelope();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 10, 20);\n * if (midiVal) {\n * text('MIDI: ' + midiVal, 10, 40);\n * text('Freq: ' + freq, 10, 60);\n * }\n * }\n *\n * function startSound() {\n * // see also: userStartAudio();\n * osc.start();\n *\n * midiVal = midiNotes[noteIndex % midiNotes.length];\n * freq = midiToFreq(midiVal);\n * osc.freq(freq);\n * env.ramp(osc, 0, 1.0, 0);\n *\n * noteIndex++;\n * }\n *
\n */\nexport var midiToFreq = (p5.prototype.midiToFreq = function (m) {\n return 440 * Math.pow(2, (m - 69) / 12.0);\n});\n\n// This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\nexport var noteToFreq = function (note) {\n if (typeof note !== 'string') {\n return note;\n }\n var wholeNotes = { A: 21, B: 23, C: 24, D: 26, E: 28, F: 29, G: 31 };\n var value = wholeNotes[note[0].toUpperCase()];\n var octave = ~~note.slice(-1);\n value += 12 * (octave - 1);\n\n switch (note[1]) {\n case '#':\n value += 1;\n break;\n case 'b':\n value -= 1;\n break;\n default:\n break;\n }\n return midiToFreq(value);\n};\n\n/**\n * List the SoundFile formats that you will include. LoadSound\n * will search your directory for these extensions, and will pick\n * a format that is compatable with the client's web browser.\n * Here is a free online file\n * converter.\n *\n * @method soundFormats\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\n * @example\n *
\n * function preload() {\n * // set the global sound formats\n * soundFormats('mp3', 'ogg');\n *\n * // load either beatbox.mp3, or .ogg, depending on browser\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('sound loaded! tap to play', 10, 20, width - 20);\n * cnv.mousePressed(function() {\n * mySound.play();\n * });\n * }\n *
\n */\np5.prototype.soundFormats = function () {\n // reset extensions array\n p5sound.extensions = [];\n // add extensions\n for (var i = 0; i < arguments.length; i++) {\n arguments[i] = arguments[i].toLowerCase();\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\n p5sound.extensions.push(arguments[i]);\n } else {\n throw arguments[i] + ' is not a valid sound format!';\n }\n }\n};\n\np5.prototype.disposeSound = function () {\n for (var i = 0; i < p5sound.soundArray.length; i++) {\n p5sound.soundArray[i].dispose();\n }\n};\n\n// register removeSound to dispose of p5sound SoundFiles, Convolvers,\n// Oscillators etc when sketch ends\np5.prototype.registerMethod('remove', p5.prototype.disposeSound);\n\np5.prototype._checkFileFormats = function (paths) {\n var path;\n // if path is a single string, check to see if extension is provided\n if (typeof paths === 'string') {\n path = paths;\n // see if extension is provided\n var extTest = path.split('.').pop();\n // if an extension is provided...\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\n if (!p5.prototype.isFileSupported(extTest)) {\n var pathSplit = path.split('.');\n var pathCore = pathSplit[pathSplit.length - 1];\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n pathCore = '';\n if (pathSplit.length === 2) {\n pathCore += pathSplit[0];\n }\n for (let i = 1; i <= pathSplit.length - 2; i++) {\n var p = pathSplit[i];\n pathCore += '.' + p;\n }\n path = pathCore += '.';\n path = path += extension;\n break;\n }\n }\n }\n }\n // if no extension is provided...\n else {\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n path = path + '.' + extension;\n break;\n }\n }\n }\n } // end 'if string'\n\n // path can either be a single string, or an array\n else if (typeof paths === 'object') {\n for (var i = 0; i < paths.length; i++) {\n var extension = paths[i].split('.').pop();\n var supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n // console.log('.'+extension + ' is ' + supported +\n // ' supported by your browser.');\n path = paths[i];\n break;\n }\n }\n }\n return path;\n};\n\n/**\n * Used by Osc and Envelope to chain signal math\n */\np5.prototype._mathChain = function (o, math, thisChain, nextChain, type) {\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n o.mathOps[i].dispose();\n thisChain = i;\n if (thisChain < o.mathOps.length - 1) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n o.mathOps[thisChain - 1].disconnect();\n o.mathOps[thisChain - 1].connect(math);\n math.connect(nextChain);\n o.mathOps[thisChain] = math;\n return o;\n};\n\n// helper methods to convert audio file as .wav format,\n// will use as saving .wav file and saving blob object\n// Thank you to Matt Diamond's RecorderJS (MIT License)\n// https://github.com/mattdiamond/Recorderjs\nexport function convertToWav(audioBuffer) {\n var leftChannel, rightChannel;\n leftChannel = audioBuffer.getChannelData(0);\n\n // handle mono files\n if (audioBuffer.numberOfChannels > 1) {\n rightChannel = audioBuffer.getChannelData(1);\n } else {\n rightChannel = leftChannel;\n }\n\n var interleaved = interleave(leftChannel, rightChannel);\n\n // create the buffer and view to create the .WAV file\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\n var view = new window.DataView(buffer);\n\n // write the WAV container,\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\n\n // RIFF chunk descriptor\n writeUTFBytes(view, 0, 'RIFF');\n view.setUint32(4, 36 + interleaved.length * 2, true);\n writeUTFBytes(view, 8, 'WAVE');\n // FMT sub-chunk\n writeUTFBytes(view, 12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n // stereo (2 channels)\n view.setUint16(22, 2, true);\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\n view.setUint16(32, 4, true);\n view.setUint16(34, 16, true);\n // data sub-chunk\n writeUTFBytes(view, 36, 'data');\n view.setUint32(40, interleaved.length * 2, true);\n\n // write the PCM samples\n var lng = interleaved.length;\n var index = 44;\n var volume = 1;\n for (var i = 0; i < lng; i++) {\n view.setInt16(index, interleaved[i] * (0x7fff * volume), true);\n index += 2;\n }\n\n return view;\n}\n\n// helper methods to save waves\nfunction interleave(leftChannel, rightChannel) {\n var length = leftChannel.length + rightChannel.length;\n var result = new Float32Array(length);\n\n var inputIndex = 0;\n\n for (var index = 0; index < length; ) {\n result[index++] = leftChannel[inputIndex];\n result[index++] = rightChannel[inputIndex];\n inputIndex++;\n }\n return result;\n}\n\nfunction writeUTFBytes(view, offset, string) {\n var lng = string.length;\n for (var i = 0; i < lng; i++) {\n view.setUint8(offset + i, string.charCodeAt(i));\n }\n}\n\nexport function safeBufferSize(idealBufferSize) {\n let bufferSize = idealBufferSize;\n\n // if the AudioWorkletNode is actually a ScriptProcessorNode created via polyfill,\n // make sure that our chosen buffer size isn't smaller than the buffer size automatically\n // selected by the polyfill\n // reference: https://github.com/GoogleChromeLabs/audioworklet-polyfill/issues/13#issuecomment-425014930\n let tempAudioWorkletNode = new AudioWorkletNode(\n p5sound.audiocontext,\n processorNames.soundFileProcessor\n );\n if (tempAudioWorkletNode instanceof ScriptProcessorNode) {\n bufferSize = tempAudioWorkletNode.bufferSize;\n }\n tempAudioWorkletNode.disconnect();\n tempAudioWorkletNode = null;\n\n return bufferSize;\n}\n\n// export default {\n// // convertToWav: convertToWav,\n// // midiToFreq: midiToFreq,\n// // noteToFreq: noteToFreq,\n// // safeBufferSize: safeBufferSize\n// };\n","/*\n Helper function to generate an error\n with a custom stack trace that points to the sketch\n and removes other parts of the stack trace.\n\n @private\n @class customError\n @constructor\n @param {String} name custom error name\n @param {String} errorTrace custom error trace\n @param {String} failedPath path to the file that failed to load\n @property {String} name custom error name\n @property {String} message custom error message\n @property {String} stack trace the error back to a line in the user's sketch.\n Note: this edits out stack trace within p5.js and p5.sound.\n @property {String} originalStack unedited, original stack trace\n @property {String} failedPath path to the file that failed to load\n @return {Error} returns a custom Error object\n */\nvar CustomError = function (name, errorTrace, failedPath) {\n var err = new Error();\n var tempStack, splitStack;\n\n err.name = name;\n err.originalStack = err.stack + errorTrace;\n tempStack = err.stack + errorTrace;\n err.failedPath = failedPath;\n\n // only print the part of the stack trace that refers to the user code:\n splitStack = tempStack.split('\\n').filter(function (ln) {\n return !ln.match(/(p5.|native code|globalInit)/g);\n });\n err.stack = splitStack.join('\\n');\n\n return err; // TODO: is this really a constructor?\n};\nexport default CustomError;\n","import p5sound from '../master.js'\nconst moduleSources = [\n require('raw-loader!./recorderProcessor').default,\n require('raw-loader!./soundFileProcessor').default,\n require('raw-loader!./amplitudeProcessor').default,\n];\nconst ac = p5sound.audiocontext;\n\nlet initializedAudioWorklets = false;\n\nfunction loadAudioWorkletModules() {\n return Promise.all(\n moduleSources.map(function (moduleSrc) {\n const blob = new Blob([moduleSrc], { type: 'application/javascript' });\n const objectURL = URL.createObjectURL(blob);\n return ac.audioWorklet.addModule(objectURL);\n })\n );\n}\n\np5.prototype.registerMethod('init', function () {\n if (initializedAudioWorklets) return;\n // ensure that a preload function exists so that p5 will wait for preloads to finish\n if (!this.preload && !window.preload) {\n this.preload = function () {};\n }\n\n // use p5's preload system to load necessary AudioWorklet modules before setup()\n this._incrementPreload();\n const onWorkletModulesLoad = function () {\n initializedAudioWorklets = true;\n this._decrementPreload();\n }.bind(this);\n loadAudioWorkletModules().then(onWorkletModulesLoad);\n});\n","import p5sound from './master';\nvar ac = p5sound.audiocontext;\n\n// Stereo panner\n// if there is a stereo panner node use it\nif (typeof ac.createStereoPanner !== 'undefined') {\n p5.Panner = function (input, output) {\n this.stereoPanner = this.input = ac.createStereoPanner();\n input.connect(this.stereoPanner);\n this.stereoPanner.connect(output);\n };\n\n p5.Panner.prototype.pan = function (val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\n };\n\n //not implemented because stereopanner\n //node does not require this and will automatically\n //convert single channel or multichannel to stereo.\n //tested with single and stereo, not with (>2) multichannel\n p5.Panner.prototype.inputChannels = function () {};\n\n p5.Panner.prototype.connect = function (obj) {\n this.stereoPanner.connect(obj);\n };\n\n p5.Panner.prototype.disconnect = function () {\n if (this.stereoPanner) {\n this.stereoPanner.disconnect();\n }\n };\n} else {\n // if there is no createStereoPanner object\n // such as in safari 7.1.7 at the time of writing this\n // use this method to create the effect\n p5.Panner = function (input, output, numInputChannels) {\n this.input = ac.createGain();\n input.connect(this.input);\n\n this.left = ac.createGain();\n this.right = ac.createGain();\n this.left.channelInterpretation = 'discrete';\n this.right.channelInterpretation = 'discrete';\n\n // if input is stereo\n if (numInputChannels > 1) {\n this.splitter = ac.createChannelSplitter(2);\n this.input.connect(this.splitter);\n\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n } else {\n this.input.connect(this.left);\n this.input.connect(this.right);\n }\n\n this.output = ac.createChannelMerger(2);\n this.left.connect(this.output, 0, 1);\n this.right.connect(this.output, 0, 0);\n this.output.connect(output);\n };\n\n // -1 is left, +1 is right\n p5.Panner.prototype.pan = function (val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n var v = (val + 1) / 2;\n var rightVal = Math.cos((v * Math.PI) / 2);\n var leftVal = Math.sin((v * Math.PI) / 2);\n this.left.gain.linearRampToValueAtTime(leftVal, t);\n this.right.gain.linearRampToValueAtTime(rightVal, t);\n };\n\n p5.Panner.prototype.inputChannels = function (numChannels) {\n if (numChannels === 1) {\n this.input.disconnect();\n this.input.connect(this.left);\n this.input.connect(this.right);\n } else if (numChannels === 2) {\n if (typeof this.splitter === 'undefined') {\n this.splitter = ac.createChannelSplitter(2);\n }\n this.input.disconnect();\n this.input.connect(this.splitter);\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n }\n };\n\n p5.Panner.prototype.connect = function (obj) {\n this.output.connect(obj);\n };\n\n p5.Panner.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n };\n}\n","import CustomError from './errorHandler';\nimport p5sound from './master';\nimport { midiToFreq, convertToWav, safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\nconst ac = p5sound.audiocontext;\n\n/**\n *

SoundFile object with a path to a file.

\n *\n *

The p5.SoundFile may not be available immediately because\n * it loads the file information asynchronously.

\n *\n *

To do something with the sound as soon as it loads\n * pass the name of a function as the second parameter.

\n *\n *

Only one file path is required. However, audio file formats\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\n * web browsers. If you want to ensure compatability, instead of a single\n * file path, you may include an Array of filepaths, and the browser will\n * choose a format that works.

\n *\n * @class p5.SoundFile\n * @constructor\n * @param {String|Array} path path to a sound file (String). Optionally,\n * you may include multiple file formats in\n * an array. Alternately, accepts an object\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if file fails to\n * load. This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\n * is loading. That function will\n * receive progress of the request to\n * load the sound file\n * (between 0 and 1) as its first\n * parameter. This progress\n * does not account for the additional\n * time needed to decode the audio data.\n *\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\np5.SoundFile = function (paths, onload, onerror, whileLoading) {\n if (typeof paths !== 'undefined') {\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\n var path = p5.prototype._checkFileFormats(paths);\n this.url = path;\n } else if (typeof paths === 'object') {\n if (\n !(window.File && window.FileReader && window.FileList && window.Blob)\n ) {\n // The File API isn't supported in this browser\n throw 'Unable to load file because the File API is not supported';\n }\n }\n\n // if type is a p5.File...get the actual file\n if (paths.file) {\n paths = paths.file;\n }\n\n this.file = paths;\n }\n\n // private _onended callback, set by the method: onended(callback)\n this._onended = function () {};\n\n this._looping = false;\n this._playing = false;\n this._paused = false;\n this._pauseTime = 0;\n\n // cues for scheduling events with addCue() removeCue()\n this._cues = [];\n this._cueIDCounter = 0;\n\n // position of the most recently played sample\n this._lastPos = 0;\n this._counterNode = null;\n this._workletNode = null;\n\n // array of sources so that they can all be stopped!\n this.bufferSourceNodes = [];\n\n // current source\n this.bufferSourceNode = null;\n\n this.buffer = null;\n this.playbackRate = 1;\n\n this.input = p5sound.audiocontext.createGain();\n this.output = p5sound.audiocontext.createGain();\n\n this.reversed = false;\n\n // start and end of playback / loop\n this.startTime = 0;\n this.endTime = null;\n this.pauseTime = 0;\n\n // \"restart\" would stop playback before retriggering\n this.mode = 'sustain';\n\n // time that playback was started, in millis\n this.startMillis = null;\n\n // stereo panning\n this.panPosition = 0.0;\n this.panner = new p5.Panner(this.output, p5sound.input, 2);\n\n // it is possible to instantiate a soundfile with no path\n if (this.url || this.file) {\n this.load(onload, onerror);\n }\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n\n if (typeof whileLoading === 'function') {\n this._whileLoading = whileLoading;\n } else {\n this._whileLoading = function () {};\n }\n\n this._clearOnEnd = _clearOnEnd.bind(this);\n};\n\n// register preload handling of loadSound\np5.prototype.registerPreloadMethod('loadSound', p5.prototype);\n\n/**\n * loadSound() returns a new p5.SoundFile from a specified\n * path. If called during preload(), the p5.SoundFile will be ready\n * to play in time for setup() and draw(). If called outside of\n * preload, the p5.SoundFile will not be ready immediately, so\n * loadSound accepts a callback as the second parameter. Using a\n * \n * local server is recommended when loading external files.\n *\n * @method loadSound\n * @for p5\n * @param {String|Array} path Path to the sound file, or an array with\n * paths to soundfiles in multiple formats\n * i.e. ['sound.ogg', 'sound.mp3'].\n * Alternately, accepts an object: either\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is\n * an error loading the file.\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\n * This function will receive the percentage loaded\n * so far, from 0.0 to 1.0.\n * @return {SoundFile} Returns a p5.SoundFile\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\np5.prototype.loadSound = function (path, callback, onerror, whileLoading) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n window.alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n\n var self = this;\n var s = new p5.SoundFile(\n path,\n function () {\n if (typeof callback === 'function') {\n callback.apply(self, arguments);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n onerror,\n whileLoading\n );\n\n return s;\n};\n\n/**\n * This is a helper function that the p5.SoundFile calls to load\n * itself. Accepts a callback (the name of another function)\n * as an optional parameter.\n *\n * @private\n * @for p5.SoundFile\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is an error\n */\np5.SoundFile.prototype.load = function (callback, errorCallback) {\n var self = this;\n var errorTrace = new Error().stack;\n\n if (this.url !== undefined && this.url !== '') {\n var request = new XMLHttpRequest();\n request.addEventListener(\n 'progress',\n function (evt) {\n self._updateProgress(evt);\n },\n false\n );\n request.open('GET', this.url, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on sucess loading file:\n if (!self.panner) return;\n ac.decodeAudioData(\n request.response,\n // success decoding buffer:\n function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n if (!self.panner) return;\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n if (!self.panner) return;\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n };\n\n request.send();\n } else if (this.file !== undefined) {\n var reader = new FileReader();\n reader.onload = function () {\n if (!self.panner) return;\n ac.decodeAudioData(reader.result, function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n });\n };\n reader.onerror = function (e) {\n if (!self.panner) return;\n if (onerror) {\n onerror(e);\n }\n };\n reader.readAsArrayBuffer(this.file);\n }\n};\n\n// TO DO: use this method to create a loading bar that shows progress during file upload/decode.\np5.SoundFile.prototype._updateProgress = function (evt) {\n if (evt.lengthComputable) {\n var percentComplete = (evt.loaded / evt.total) * 0.99;\n this._whileLoading(percentComplete, evt);\n // ...\n } else {\n // Unable to compute progress information since the total size is unknown\n this._whileLoading('size unknown');\n }\n};\n\n/**\n * Returns true if the sound file finished loading successfully.\n *\n * @method isLoaded\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isLoaded = function () {\n if (this.buffer) {\n return true;\n } else {\n return false;\n }\n};\n\n/**\n * Play the p5.SoundFile\n *\n * @method play\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) amplitude (volume)\n * of playback\n * @param {Number} [cueStart] (optional) cue start time in seconds\n * @param {Number} [duration] (optional) duration of playback in seconds\n */\np5.SoundFile.prototype.play = function (\n startTime,\n rate,\n amp,\n _cueStart,\n duration\n) {\n if (!this.output) {\n console.warn('SoundFile.play() called after dispose');\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var cueStart, cueEnd;\n var time = startTime || 0;\n if (time < 0) {\n time = 0;\n }\n\n time = time + now;\n\n if (typeof rate !== 'undefined') {\n this.rate(rate);\n }\n\n if (typeof amp !== 'undefined') {\n this.setVolume(amp);\n }\n\n // TO DO: if already playing, create array of buffers for easy stop()\n if (this.buffer) {\n // reset the pause time (if it was paused)\n this._pauseTime = 0;\n\n // handle restart playmode\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\n this.bufferSourceNode.stop(time);\n this._counterNode.stop(time);\n }\n\n //dont create another instance if already playing\n if (this.mode === 'untildone' && this.isPlaying()) {\n return;\n }\n // make a new source and counter. They are automatically assigned playbackRate and buffer\n this.bufferSourceNode = this._initSourceNode();\n\n // garbage collect counterNode and create a new one\n delete this._counterNode;\n this._counterNode = this._initCounterNode();\n\n if (_cueStart) {\n if (_cueStart >= 0 && _cueStart < this.buffer.duration) {\n // this.startTime = cueStart;\n cueStart = _cueStart;\n } else {\n throw 'start time out of range';\n }\n } else {\n cueStart = 0;\n }\n\n if (duration) {\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\n duration =\n duration <= this.buffer.duration - cueStart\n ? duration\n : this.buffer.duration;\n }\n\n // if it was paused, play at the pause position\n if (this._paused) {\n this.bufferSourceNode.start(time, this.pauseTime, duration);\n this._counterNode.start(time, this.pauseTime, duration);\n } else {\n this.bufferSourceNode.start(time, cueStart, duration);\n this._counterNode.start(time, cueStart, duration);\n }\n\n this._playing = true;\n this._paused = false;\n\n // add source to sources array, which is used in stopAll()\n this.bufferSourceNodes.push(this.bufferSourceNode);\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\n\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\n }\n // If soundFile hasn't loaded the buffer yet, throw an error\n else {\n throw 'not ready to play file, buffer has yet to load. Try preload()';\n }\n\n // if looping, will restart at original time\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n\n if (this._looping === true) {\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\n this.bufferSourceNode.loopStart = cueStart;\n this.bufferSourceNode.loopEnd = cueEnd;\n this._counterNode.loopStart = cueStart;\n this._counterNode.loopEnd = cueEnd;\n }\n};\n\n/**\n * p5.SoundFile has two play modes: restart and\n * sustain. Play Mode determines what happens to a\n * p5.SoundFile if it is triggered while in the middle of playback.\n * In sustain mode, playback will continue simultaneous to the\n * new playback. In restart mode, play() will stop playback\n * and start over. With untilDone, a sound will play only if it's\n * not already playing. Sustain is the default mode.\n *\n * @method playMode\n * @for p5.SoundFile\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\n * @example\n *
\n * let mySound;\n * function preload(){\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * noFill();\n * rect(0, height/2, width - 1, height/2 - 1);\n * rect(0, 0, width - 1, height/2);\n * textAlign(CENTER, CENTER);\n * fill(20);\n * text('restart', width/2, 1 * height/4);\n * text('sustain', width/2, 3 * height/4);\n * }\n * function canvasPressed() {\n * if (mouseX < height/2) {\n * mySound.playMode('restart');\n * } else {\n * mySound.playMode('sustain');\n * }\n * mySound.play();\n * }\n *\n *
\n */\np5.SoundFile.prototype.playMode = function (str) {\n var s = str.toLowerCase();\n\n // if restart, stop all other sounds from playing\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNodes[i].stop(now);\n }\n }\n\n // set play mode to effect future playback\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\n this.mode = s;\n } else {\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\n }\n};\n\n/**\n * Pauses a file that is currently playing. If the file is not\n * playing, then nothing will happen.\n *\n * After pausing, .play() will resume from the paused\n * position.\n * If p5.SoundFile had been set to loop before it was paused,\n * it will continue to loop after it is unpaused with .play().\n *\n * @method pause\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @example\n *
\n * let soundFile;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\np5.SoundFile.prototype.pause = function (startTime) {\n var now = p5sound.audiocontext.currentTime;\n var time = startTime || 0;\n var pTime = time + now;\n\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\n this._paused = true;\n this._playing = false;\n\n this.pauseTime = this.currentTime();\n this.bufferSourceNode.stop(pTime);\n this._counterNode.stop(pTime);\n\n this._pauseTime = this.currentTime();\n // TO DO: make sure play() still starts from orig start position\n } else {\n this._pauseTime = 0;\n }\n};\n\n/**\n * Loop the p5.SoundFile. Accepts optional parameters to set the\n * playback rate, playback volume, loopStart, loopEnd.\n *\n * @method loop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) playback volume\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\n * @param {Number} [duration] (optional) loop duration in seconds\n * @example\n *
\n * let soundFile;\n * let loopStart = 0.5;\n * let loopDuration = 0.2;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\np5.SoundFile.prototype.loop = function (\n startTime,\n rate,\n amp,\n loopStart,\n duration\n) {\n this._looping = true;\n this.play(startTime, rate, amp, loopStart, duration);\n};\n\n/**\n * Set a p5.SoundFile's looping flag to true or false. If the sound\n * is currently playing, this change will take effect when it\n * reaches the end of the current playback.\n *\n * @method setLoop\n * @for p5.SoundFile\n * @param {Boolean} Boolean set looping to true or false\n */\np5.SoundFile.prototype.setLoop = function (bool) {\n if (bool === true) {\n this._looping = true;\n } else if (bool === false) {\n this._looping = false;\n } else {\n throw 'Error: setLoop accepts either true or false';\n }\n if (this.bufferSourceNode) {\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n }\n};\n\n/**\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\n *\n * @method isLooping\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isLooping = function () {\n if (!this.bufferSourceNode) {\n return false;\n }\n if (this._looping === true && this.isPlaying() === true) {\n return true;\n }\n return false;\n};\n\n/**\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\n * paused or stopped).\n *\n * @method isPlaying\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isPlaying = function () {\n return this._playing;\n};\n\n/**\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\n * playing or stopped).\n *\n * @method isPaused\n * @for p5.SoundFile\n * @return {Boolean}\n */\np5.SoundFile.prototype.isPaused = function () {\n return this._paused;\n};\n\n/**\n * Stop soundfile playback.\n *\n * @method stop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * in seconds from now\n */\np5.SoundFile.prototype.stop = function (timeFromNow) {\n var time = timeFromNow || 0;\n\n if (this.mode === 'sustain' || this.mode === 'untildone') {\n this.stopAll(time);\n this._playing = false;\n this.pauseTime = 0;\n this._paused = false;\n } else if (this.buffer && this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n this.pauseTime = 0;\n this.bufferSourceNode.stop(now + t);\n this._counterNode.stop(now + t);\n this._playing = false;\n this._paused = false;\n }\n};\n\n/**\n * Stop playback on all of this soundfile's sources.\n * @private\n */\np5.SoundFile.prototype.stopAll = function (_time) {\n var now = p5sound.audiocontext.currentTime;\n var time = _time || 0;\n if (this.buffer && this.bufferSourceNode) {\n for (var i in this.bufferSourceNodes) {\n const bufferSourceNode = this.bufferSourceNodes[i];\n if (bufferSourceNode) {\n try {\n bufferSourceNode.stop(now + time);\n } catch (e) {\n // this was throwing errors only on Safari\n }\n }\n }\n this._counterNode.stop(now + time);\n this._onended(this);\n }\n};\n\n/**\n * Multiply the output volume (amplitude) of a sound file\n * between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n * @method setVolume\n * @for p5.SoundFile\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\np5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) {\n if (typeof vol === 'number') {\n var rampTime = _rampTime || 0;\n var tFromNow = _tFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now + tFromNow);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n};\n\n// same as setVolume, to match Processing Sound\np5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;\n\n// these are the same thing\np5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;\n\np5.SoundFile.prototype.getVolume = function () {\n return this.output.gain.value;\n};\n\n/**\n * Set the stereo panning of a p5.sound object to\n * a floating point number between -1.0 (left) and 1.0 (right).\n * Default is 0.0 (center).\n *\n * @method pan\n * @for p5.SoundFile\n * @param {Number} [panValue] Set the stereo panner\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @example\n *
\n * let ballX = 0;\n * let soundFile;\n *\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/beatbox.mp3');\n * }\n *\n * function draw() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * ballX = constrain(mouseX, 0, width);\n * ellipse(ballX, height/2, 20, 20);\n * }\n *\n * function canvasPressed(){\n * // map the ball's x location to a panning degree\n * // between -1.0 (left) and 1.0 (right)\n * let panning = map(ballX, 0., width,-1.0, 1.0);\n * soundFile.pan(panning);\n * soundFile.play();\n * }\n *
\n */\np5.SoundFile.prototype.pan = function (pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n};\n\n/**\n * Returns the current stereo pan position (-1.0 to 1.0)\n *\n * @method getPan\n * @for p5.SoundFile\n * @return {Number} Returns the stereo pan setting of the Oscillator\n * as a number between -1.0 (left) and 1.0 (right).\n * 0.0 is center and default.\n */\np5.SoundFile.prototype.getPan = function () {\n return this.panPosition;\n};\n\n/**\n * Set the playback rate of a sound file. Will change the speed and the pitch.\n * Values less than zero will reverse the audio buffer.\n *\n * @method rate\n * @for p5.SoundFile\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\n * .5 is half-speed, 2.0 is twice as fast.\n * Values less than zero play backwards.\n * @example\n *
\n * let mySound;\n *\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * }\n * function canvasPressed() {\n * mySound.loop();\n * }\n * function mouseReleased() {\n * mySound.pause();\n * }\n * function draw() {\n * background(220);\n *\n * // Set the rate to a range between 0.1 and 4\n * // Changing the rate also alters the pitch\n * let playbackRate = map(mouseY, 0.1, height, 2, 0);\n * playbackRate = constrain(playbackRate, 0.01, 4);\n * mySound.rate(playbackRate);\n *\n * line(0, mouseY, width, mouseY);\n * text('rate: ' + round(playbackRate * 100) + '%', 10, 20);\n * }\n *\n * \n *
\n *\n */\np5.SoundFile.prototype.rate = function (playbackRate) {\n var reverse = false;\n if (typeof playbackRate === 'undefined') {\n return this.playbackRate;\n }\n\n this.playbackRate = playbackRate;\n\n if (playbackRate === 0) {\n playbackRate = 0.0000000000001;\n } else if (playbackRate < 0 && !this.reversed) {\n playbackRate = Math.abs(playbackRate);\n reverse = true;\n } else if (playbackRate > 0 && this.reversed) {\n reverse = true;\n }\n\n if (this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n this._counterNode.playbackRate.cancelScheduledValues(now);\n this._counterNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n }\n\n if (reverse) {\n this.reverseBuffer();\n }\n return this.playbackRate;\n};\n\n// TO DO: document this\np5.SoundFile.prototype.setPitch = function (num) {\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\n this.rate(newPlaybackRate);\n};\n\np5.SoundFile.prototype.getPlaybackRate = function () {\n return this.playbackRate;\n};\n\n/**\n * Returns the duration of a sound file in seconds.\n *\n * @method duration\n * @for p5.SoundFile\n * @return {Number} The duration of the soundFile in seconds.\n */\np5.SoundFile.prototype.duration = function () {\n // Return Duration\n if (this.buffer) {\n return this.buffer.duration;\n } else {\n return 0;\n }\n};\n\n/**\n * Return the current position of the p5.SoundFile playhead, in seconds.\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\n * has been called, currentTime will count backwards.\n *\n * @method currentTime\n * @for p5.SoundFile\n * @return {Number} currentTime of the soundFile in seconds.\n */\np5.SoundFile.prototype.currentTime = function () {\n return this.reversed\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\n : this._lastPos / ac.sampleRate;\n};\n\n/**\n * Move the playhead of a soundfile that is currently playing to a\n * new position and a new duration, in seconds.\n * If none are given, will reset the file to play entire duration\n * from start to finish. To set the position of a soundfile that is\n * not currently playing, use the `play` or `loop` methods.\n *\n * @method jump\n * @for p5.SoundFile\n * @param {Number} cueTime cueTime of the soundFile in seconds.\n * @param {Number} duration duration in seconds.\n */\np5.SoundFile.prototype.jump = function (cueTime, duration) {\n if (cueTime < 0 || cueTime > this.buffer.duration) {\n throw 'jump time out of range';\n }\n if (duration > this.buffer.duration - cueTime) {\n throw 'end time out of range';\n }\n\n var cTime = cueTime || 0;\n var dur = duration || undefined;\n if (this.isPlaying()) {\n this.stop(0);\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\n }\n};\n\n/**\n * Return the number of channels in a sound file.\n * For example, Mono = 1, Stereo = 2.\n *\n * @method channels\n * @for p5.SoundFile\n * @return {Number} [channels]\n */\np5.SoundFile.prototype.channels = function () {\n return this.buffer.numberOfChannels;\n};\n\n/**\n * Return the sample rate of the sound file.\n *\n * @method sampleRate\n * @for p5.SoundFile\n * @return {Number} [sampleRate]\n */\np5.SoundFile.prototype.sampleRate = function () {\n return this.buffer.sampleRate;\n};\n\n/**\n * Return the number of samples in a sound file.\n * Equal to sampleRate * duration.\n *\n * @method frames\n * @for p5.SoundFile\n * @return {Number} [sampleCount]\n */\np5.SoundFile.prototype.frames = function () {\n return this.buffer.length;\n};\n\n/**\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\n * used to draw a static waveform. Scans through the p5.SoundFile's\n * audio buffer to find the greatest amplitudes. Accepts one\n * parameter, 'length', which determines size of the array.\n * Larger arrays result in more precise waveform visualizations.\n *\n * Inspired by Wavesurfer.js.\n *\n * @method getPeaks\n * @for p5.SoundFile\n * @params {Number} [length] length is the size of the returned array.\n * Larger length results in more precision.\n * Defaults to 5*width of the browser window.\n * @returns {Float32Array} Array of peaks.\n */\np5.SoundFile.prototype.getPeaks = function (length) {\n if (this.buffer) {\n // set length to window's width if no length is provided\n if (!length) {\n length = window.width * 5;\n }\n if (this.buffer) {\n var buffer = this.buffer;\n var sampleSize = buffer.length / length;\n var sampleStep = ~~(sampleSize / 10) || 1;\n var channels = buffer.numberOfChannels;\n var peaks = new Float32Array(Math.round(length));\n\n for (var c = 0; c < channels; c++) {\n var chan = buffer.getChannelData(c);\n for (var i = 0; i < length; i++) {\n var start = ~~(i * sampleSize);\n var end = ~~(start + sampleSize);\n var max = 0;\n for (var j = start; j < end; j += sampleStep) {\n var value = chan[j];\n if (value > max) {\n max = value;\n // faster than Math.abs\n } else if (-value > max) {\n max = value;\n }\n }\n if (c === 0 || Math.abs(max) > peaks[i]) {\n peaks[i] = max;\n }\n }\n }\n\n return peaks;\n }\n } else {\n throw 'Cannot load peaks yet, buffer is not loaded';\n }\n};\n\n/**\n * Reverses the p5.SoundFile's buffer source.\n * Playback must be handled separately (see example).\n *\n * @method reverseBuffer\n * @for p5.SoundFile\n * @example\n *
\n * let drum;\n * function preload() {\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function canvasPressed() {\n * drum.stop();\n * drum.reverseBuffer();\n * drum.play();\n * }\n * \n *
\n */\np5.SoundFile.prototype.reverseBuffer = function () {\n if (this.buffer) {\n var currentPos = this._lastPos / ac.sampleRate;\n var curVol = this.getVolume();\n this.setVolume(0, 0.001);\n\n const numChannels = this.buffer.numberOfChannels;\n for (var i = 0; i < numChannels; i++) {\n this.buffer.getChannelData(i).reverse();\n }\n // set reversed flag\n this.reversed = !this.reversed;\n\n if (this.isPlaying() && currentPos) {\n this.jump(this.duration() - currentPos);\n }\n this.setVolume(curVol, 0.001);\n } else {\n throw 'SoundFile is not done loading';\n }\n};\n\n/**\n * Schedule an event to be called when the soundfile\n * reaches the end of a buffer. If the soundfile is\n * playing through once, this will be called when it\n * ends. If it is looping, it will be called when\n * stop is called.\n *\n * @method onended\n * @for p5.SoundFile\n * @param {Function} callback function to call when the\n * soundfile has ended.\n */\np5.SoundFile.prototype.onended = function (callback) {\n this._onended = callback;\n return this;\n};\n\np5.SoundFile.prototype.add = function () {\n // TO DO\n};\n\np5.SoundFile.prototype.dispose = function () {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference to soundfile\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop(now);\n if (this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n if (this.bufferSourceNodes[i] !== null) {\n this.bufferSourceNodes[i].disconnect();\n try {\n this.bufferSourceNodes[i].stop(now);\n } catch (e) {\n console.warn('no buffer source node to dispose');\n }\n this.bufferSourceNodes[i] = null;\n }\n }\n if (this.isPlaying()) {\n try {\n this._counterNode.stop(now);\n } catch (e) {\n console.log(e);\n }\n this._counterNode = null;\n }\n }\n if (this.output) {\n this.output.disconnect();\n this.output = null;\n }\n if (this.panner) {\n this.panner.disconnect();\n this.panner = null;\n }\n};\n\n/**\n * Connects the output of a p5sound object to input of another\n * p5.sound object. For example, you may connect a p5.SoundFile to an\n * FFT or an Effect. If no parameter is given, it will connect to\n * the master output. Most p5sound objects connect to the master\n * output when they are created.\n *\n * @method connect\n * @for p5.SoundFile\n * @param {Object} [object] Audio object that accepts an input\n */\np5.SoundFile.prototype.connect = function (unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else {\n if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n } else {\n this.panner.connect(unit);\n }\n }\n};\n\n/**\n * Disconnects the output of this p5sound object.\n *\n * @method disconnect\n * @for p5.SoundFile\n */\np5.SoundFile.prototype.disconnect = function () {\n if (this.panner) {\n this.panner.disconnect();\n }\n};\n\n/**\n */\np5.SoundFile.prototype.getLevel = function () {\n console.warn(\n 'p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'\n );\n};\n\n/**\n * Reset the source for this SoundFile to a\n * new path (URL).\n *\n * @method setPath\n * @for p5.SoundFile\n * @param {String} path path to audio file\n * @param {Function} callback Callback\n */\np5.SoundFile.prototype.setPath = function (p, callback) {\n var path = p5.prototype._checkFileFormats(p);\n this.url = path;\n this.load(callback);\n};\n\n/**\n * Replace the current Audio Buffer with a new Buffer.\n *\n * @method setBuffer\n * @for p5.SoundFile\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\n * will create a stereo source. 1 will create\n * a mono source.\n */\np5.SoundFile.prototype.setBuffer = function (buf) {\n var numChannels = buf.length;\n var size = buf[0].length;\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\n\n if (!(buf[0] instanceof Float32Array)) {\n buf[0] = new Float32Array(buf[0]);\n }\n\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\n var channel = newBuffer.getChannelData(channelNum);\n channel.set(buf[channelNum]);\n }\n\n this.buffer = newBuffer;\n\n // set numbers of channels on input to the panner\n this.panner.inputChannels(numChannels);\n};\n\n//////////////////////////////////////////////////\n// script processor node with an empty buffer to help\n// keep a sample-accurate position in playback buffer.\n// Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV\n// Copyright [2015] [Sonoport (Asia) Pte. Ltd.],\n// Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0\n////////////////////////////////////////////////////////////////////////////////////\n\nvar _createCounterBuffer = function (buffer) {\n const len = buffer.length;\n const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate);\n const arrayBuffer = audioBuf.getChannelData(0);\n for (var index = 0; index < len; index++) {\n arrayBuffer[index] = index;\n }\n return audioBuf;\n};\n\n// initialize counterNode, set its initial buffer and playbackRate\np5.SoundFile.prototype._initCounterNode = function () {\n var self = this;\n var now = ac.currentTime;\n var cNode = ac.createBufferSource();\n\n const workletBufferSize = safeBufferSize(256);\n\n // dispose of worklet node if it already exists\n if (self._workletNode) {\n self._workletNode.disconnect();\n delete self._workletNode;\n }\n self._workletNode = new AudioWorkletNode(\n ac,\n processorNames.soundFileProcessor,\n {\n processorOptions: { bufferSize: workletBufferSize },\n }\n );\n self._workletNode.port.onmessage = (event) => {\n if (event.data.name === 'position') {\n // event.data.position should only be 0 when paused\n if (event.data.position === 0) {\n return;\n }\n this._lastPos = event.data.position;\n\n // do any callbacks that have been scheduled\n this._onTimeUpdate(self._lastPos);\n }\n };\n\n // create counter buffer of the same length as self.buffer\n cNode.buffer = _createCounterBuffer(self.buffer);\n\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\n\n cNode.connect(self._workletNode);\n self._workletNode.connect(p5.soundOut._silentNode);\n\n return cNode;\n};\n\n// initialize sourceNode, set its initial buffer and playbackRate\np5.SoundFile.prototype._initSourceNode = function () {\n var bufferSourceNode = ac.createBufferSource();\n bufferSourceNode.buffer = this.buffer;\n bufferSourceNode.playbackRate.value = this.playbackRate;\n bufferSourceNode.connect(this.output);\n return bufferSourceNode;\n};\n\n/**\n * processPeaks returns an array of timestamps where it thinks there is a beat.\n *\n * This is an asynchronous function that processes the soundfile in an offline audio context,\n * and sends the results to your callback function.\n *\n * The process involves running the soundfile through a lowpass filter, and finding all of the\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\n *\n * @method processPeaks\n * @for p5.SoundFile\n * @param {Function} callback a function to call once this data is returned\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\n * @return {Array} Array of timestamped peaks\n */\np5.SoundFile.prototype.processPeaks = function (\n callback,\n _initThreshold,\n _minThreshold,\n _minPeaks\n) {\n var bufLen = this.buffer.length;\n var sampleRate = this.buffer.sampleRate;\n var buffer = this.buffer;\n var allPeaks = [];\n\n var initialThreshold = _initThreshold || 0.9,\n threshold = initialThreshold,\n minThreshold = _minThreshold || 0.22,\n minPeaks = _minPeaks || 200;\n\n // Create offline context\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\n\n // create buffer source\n var source = offlineContext.createBufferSource();\n source.buffer = buffer;\n\n // Create filter. TO DO: allow custom setting of filter\n var filter = offlineContext.createBiquadFilter();\n filter.type = 'lowpass';\n source.connect(filter);\n filter.connect(offlineContext.destination);\n\n // start playing at time:0\n source.start(0);\n offlineContext.startRendering(); // Render the song\n\n // act on the result\n offlineContext.oncomplete = function (e) {\n if (!self.panner) return;\n var filteredBuffer = e.renderedBuffer;\n var bufferData = filteredBuffer.getChannelData(0);\n\n // step 1:\n // create Peak instances, add them to array, with strength and sampleIndex\n do {\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\n threshold -= 0.005;\n } while (\n Object.keys(allPeaks).length < minPeaks &&\n threshold >= minThreshold\n );\n\n // step 2:\n // find intervals for each peak in the sampleIndex, add tempos array\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\n\n // step 3: find top tempos\n var groups = groupNeighborsByTempo(\n intervalCounts,\n filteredBuffer.sampleRate\n );\n\n // sort top intervals\n var topTempos = groups\n .sort(function (intA, intB) {\n return intB.count - intA.count;\n })\n .splice(0, 5);\n\n // set this SoundFile's tempo to the top tempo ??\n this.tempo = topTempos[0].tempo;\n\n // step 4:\n // new array of peaks at top tempo within a bpmVariance\n var bpmVariance = 5;\n var tempoPeaks = getPeaksAtTopTempo(\n allPeaks,\n topTempos[0].tempo,\n filteredBuffer.sampleRate,\n bpmVariance\n );\n\n callback(tempoPeaks);\n };\n};\n\n// process peaks\nvar Peak = function (amp, i) {\n this.sampleIndex = i;\n this.amplitude = amp;\n this.tempos = [];\n this.intervals = [];\n};\n\n// 1. for processPeaks() Function to identify peaks above a threshold\n// returns an array of peak indexes as frames (samples) of the original soundfile\nfunction getPeaksAtThreshold(data, threshold) {\n var peaksObj = {};\n var length = data.length;\n\n for (var i = 0; i < length; i++) {\n if (data[i] > threshold) {\n var amp = data[i];\n var peak = new Peak(amp, i);\n peaksObj[i] = peak;\n // Skip forward ~ 1/8s to get past this peak.\n i += 6000;\n }\n i++;\n }\n return peaksObj;\n}\n\n// 2. for processPeaks()\nfunction countIntervalsBetweenNearbyPeaks(peaksObj) {\n var intervalCounts = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n for (var index = 0; index < peaksArray.length; index++) {\n // find intervals in comparison to nearby peaks\n for (var i = 0; i < 10; i++) {\n var startPeak = peaksObj[peaksArray[index]];\n var endPeak = peaksObj[peaksArray[index + i]];\n\n if (startPeak && endPeak) {\n var startPos = startPeak.sampleIndex;\n var endPos = endPeak.sampleIndex;\n var interval = endPos - startPos;\n\n // add a sample interval to the startPeak in the allPeaks array\n if (interval > 0) {\n startPeak.intervals.push(interval);\n }\n\n // tally the intervals and return interval counts\n var foundInterval = intervalCounts.some(function (intervalCount) {\n if (intervalCount.interval === interval) {\n intervalCount.count++;\n return intervalCount;\n }\n });\n\n // store with JSON like formatting\n if (!foundInterval) {\n intervalCounts.push({\n interval: interval,\n count: 1,\n });\n }\n }\n }\n }\n\n return intervalCounts;\n}\n\n// 3. for processPeaks --> find tempo\nfunction groupNeighborsByTempo(intervalCounts, sampleRate) {\n var tempoCounts = [];\n\n intervalCounts.forEach(function (intervalCount) {\n try {\n // Convert an interval to tempo\n var theoreticalTempo = Math.abs(\n 60 / (intervalCount.interval / sampleRate)\n );\n\n theoreticalTempo = mapTempo(theoreticalTempo);\n\n var foundTempo = tempoCounts.some(function (tempoCount) {\n if (tempoCount.tempo === theoreticalTempo)\n return (tempoCount.count += intervalCount.count);\n });\n if (!foundTempo) {\n if (isNaN(theoreticalTempo)) {\n return;\n }\n tempoCounts.push({\n tempo: Math.round(theoreticalTempo),\n count: intervalCount.count,\n });\n }\n } catch (e) {\n throw e;\n }\n });\n\n return tempoCounts;\n}\n\n// 4. for processPeaks - get peaks at top tempo\nfunction getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\n var peaksAtTopTempo = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n // TO DO: filter out peaks that have the tempo and return\n for (var i = 0; i < peaksArray.length; i++) {\n var key = peaksArray[i];\n var peak = peaksObj[key];\n\n for (var j = 0; j < peak.intervals.length; j++) {\n var intervalBPM = Math.round(\n Math.abs(60 / (peak.intervals[j] / sampleRate))\n );\n\n intervalBPM = mapTempo(intervalBPM);\n\n if (Math.abs(intervalBPM - tempo) < bpmVariance) {\n // convert sampleIndex to seconds\n peaksAtTopTempo.push(peak.sampleIndex / sampleRate);\n }\n }\n }\n\n // filter out peaks that are very close to each other\n peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) {\n var dif = arr[index + 1] - peakTime;\n if (dif > 0.01) {\n return true;\n }\n });\n\n return peaksAtTopTempo;\n}\n\n// helper function for processPeaks\nfunction mapTempo(theoreticalTempo) {\n // these scenarios create infinite while loop\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) {\n return;\n }\n\n // Adjust the tempo to fit within the 90-180 BPM range\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\n\n return theoreticalTempo;\n}\n\n/*** SCHEDULE EVENTS ***/\n\n// Cue inspired by JavaScript setTimeout, and the\n// Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\nvar Cue = function (callback, time, id, val) {\n this.callback = callback;\n this.time = time;\n this.id = id;\n this.val = val;\n};\n\n/**\n * Schedule events to trigger every time a MediaElement\n * (audio/video) reaches a playback cue point.\n *\n * Accepts a callback function, a time (in seconds) at which to trigger\n * the callback, and an optional parameter for the callback.\n *\n * Time will be passed as the first parameter to the callback function,\n * and param will be the second parameter.\n *\n *\n * @method addCue\n * @for p5.SoundFile\n * @param {Number} time Time in seconds, relative to this media\n * element's playback. For example, to trigger\n * an event every time playback reaches two\n * seconds, pass in the number 2. This will be\n * passed as the first parameter to\n * the callback function.\n * @param {Function} callback Name of a function that will be\n * called at the given time. The callback will\n * receive time and (optionally) param as its\n * two parameters.\n * @param {Object} [value] An object to be passed as the\n * second parameter to the\n * callback function.\n * @return {Number} id ID of this cue,\n * useful for removeCue(id)\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 10, 20);\n *\n * // schedule calls to changeText\n * mySound.addCue(0, changeText, \"hello\" );\n * mySound.addCue(0.5, changeText, \"hello,\" );\n * mySound.addCue(1, changeText, \"hello, p5!\");\n * mySound.addCue(1.5, changeText, \"hello, p5!!\");\n * mySound.addCue(2, changeText, \"hello, p5!!!!!\");\n * }\n *\n * function changeText(val) {\n * background(220);\n * text(val, 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.play();\n * }\n *
\n */\np5.SoundFile.prototype.addCue = function (time, callback, val) {\n var id = this._cueIDCounter++;\n\n var cue = new Cue(callback, time, id, val);\n this._cues.push(cue);\n\n // if (!this.elt.ontimeupdate) {\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\n // }\n\n return id;\n};\n\n/**\n * Remove a callback based on its ID. The ID is returned by the\n * addCue method.\n *\n * @method removeCue\n * @for p5.SoundFile\n * @param {Number} id ID of the cue, as returned by addCue\n */\np5.SoundFile.prototype.removeCue = function (id) {\n var cueLength = this._cues.length;\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n if (cue.id === id) {\n this._cues.splice(i, 1);\n break;\n }\n }\n\n if (this._cues.length === 0) {\n // TO DO: remove callback\n // this.elt.ontimeupdate = null\n }\n};\n\n/**\n * Remove all of the callbacks that had originally been scheduled\n * via the addCue method.\n *\n * @method clearCues\n */\np5.SoundFile.prototype.clearCues = function () {\n this._cues = [];\n // this.elt.ontimeupdate = null;\n};\n\n// private method that checks for cues to be fired if events\n// have been scheduled using addCue(callback, time).\np5.SoundFile.prototype._onTimeUpdate = function (position) {\n var playbackTime = position / this.buffer.sampleRate;\n var cueLength = this._cues.length;\n\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n var callbackTime = cue.time;\n var val = cue.val;\n var leftLimit = this._prevUpdateTime || 0;\n var rightLimit = playbackTime;\n if (leftLimit <= callbackTime && callbackTime <= rightLimit) {\n // pass the scheduled callbackTime as parameter to the callback\n cue.callback(val);\n }\n }\n\n this._prevUpdateTime = playbackTime;\n};\n\n/**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device. To upload a file to a server, see\n * getBlob\n *\n * @method save\n * @for p5.SoundFile\n * @param {String} [fileName] name of the resulting .wav file.\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to download', 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.save('my cool filename');\n * }\n *
\n */\np5.SoundFile.prototype.save = function (fileName) {\n p5.prototype.saveSound(this, fileName, 'wav');\n};\n\n/**\n * This method is useful for sending a SoundFile to a server. It returns the\n * .wav-encoded audio data as a \"Blob\".\n * A Blob is a file-like data object that can be uploaded to a server\n * with an http request. We'll\n * use the `httpDo` options object to send a POST request with some\n * specific options: we encode the request as `multipart/form-data`,\n * and attach the blob as one of the form values using `FormData`.\n *\n *\n * @method getBlob\n * @for p5.SoundFile\n * @returns {Blob} A file-like data object\n * @example\n *
\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n *\n * function setup() {\n * noCanvas();\n * let soundBlob = mySound.getBlob();\n *\n * // Now we can send the blob to a server...\n * let serverUrl = 'https://jsonplaceholder.typicode.com/posts';\n * let httpRequestOptions = {\n * method: 'POST',\n * body: new FormData().append('soundBlob', soundBlob),\n * headers: new Headers({\n * 'Content-Type': 'multipart/form-data'\n * })\n * };\n * httpDo(serverUrl, httpRequestOptions);\n *\n * // We can also create an `ObjectURL` pointing to the Blob\n * let blobUrl = URL.createObjectURL(soundBlob);\n *\n * // The `
\n */\np5.SoundFile.prototype.getBlob = function () {\n const dataView = convertToWav(this.buffer);\n return new Blob([dataView], { type: 'audio/wav' });\n};\n\n// event handler to remove references to the bufferSourceNode when it is done playing\nfunction _clearOnEnd(e) {\n const thisBufferSourceNode = e.target;\n const soundFile = this;\n\n // delete this.bufferSourceNode from the sources array when it is done playing:\n thisBufferSourceNode._playing = false;\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\n\n // call the onended callback\n soundFile._onended(soundFile);\n\n // delete bufferSourceNode(s) in soundFile.bufferSourceNodes\n // iterate in reverse order because the index changes by splice\n soundFile.bufferSourceNodes\n .map((_, i) => i)\n .reverse()\n .forEach(function (i) {\n const n = soundFile.bufferSourceNodes[i];\n\n if (n._playing === false) {\n soundFile.bufferSourceNodes.splice(i, 1);\n }\n });\n\n if (soundFile.bufferSourceNodes.length === 0) {\n soundFile._playing = false;\n }\n}\n","import p5sound from './master';\nimport { safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\n/**\n * Amplitude measures volume between 0.0 and 1.0.\n * Listens to all p5sound by default, or use setInput()\n * to listen to a specific sound source. Accepts an optional\n * smoothing value, which defaults to 0.\n *\n * @class p5.Amplitude\n * @constructor\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\n * amplitude readings (defaults to 0)\n * @example\n *
\n * let sound, amplitude;\n *\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound() {\n * if (sound.isPlaying() ){\n * sound.stop();\n * } else {\n * sound.play();\n * }\n * }\n *\n *
\n */\np5.Amplitude = function (smoothing) {\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\n this.bufferSize = safeBufferSize(2048);\n\n // set audio context\n this.audiocontext = p5sound.audiocontext;\n this._workletNode = new AudioWorkletNode(\n this.audiocontext,\n processorNames.amplitudeProcessor,\n {\n outputChannelCount: [1],\n\n parameterData: { smoothing: smoothing || 0 },\n processorOptions: {\n normalize: false,\n smoothing: smoothing || 0,\n numInputChannels: 2,\n bufferSize: this.bufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'amplitude') {\n this.volume = event.data.volume;\n this.volNorm = event.data.volNorm;\n this.stereoVol = event.data.stereoVol;\n this.stereoVolNorm = event.data.stereoVolNorm;\n }\n }.bind(this);\n\n // for connections\n this.input = this._workletNode;\n\n this.output = this.audiocontext.createGain();\n\n // the variables to return\n this.volume = 0;\n this.volNorm = 0;\n this.stereoVol = [0, 0];\n this.stereoVolNorm = [0, 0];\n\n this.normalize = false;\n\n this._workletNode.connect(this.output);\n this.output.gain.value = 0;\n\n // this may only be necessary because of a Chrome bug\n this.output.connect(this.audiocontext.destination);\n\n // connect to p5sound master output by default, unless set by input()\n p5sound.meter.connect(this._workletNode);\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Connects to the p5sound instance (master output) by default.\n * Optionally, you can pass in a specific source (i.e. a soundfile).\n *\n * @method setInput\n * @for p5.Amplitude\n * @param {soundObject|undefined} [snd] set the sound source\n * (optional, defaults to\n * master output)\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\n * to smooth amplitude readings\n * @example\n *
\n * function preload(){\n * sound1 = loadSound('assets/beat.mp3');\n * sound2 = loadSound('assets/drum.mp3');\n * }\n * function setup(){\n * cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n *\n * amplitude = new p5.Amplitude();\n * amplitude.setInput(sound2);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound1.isPlaying() && sound2.isPlaying()) {\n * sound1.stop();\n * sound2.stop();\n * } else {\n * sound1.play();\n * sound2.play();\n * }\n * }\n *
\n */\np5.Amplitude.prototype.setInput = function (source, smoothing) {\n p5sound.meter.disconnect();\n\n if (smoothing) {\n this._workletNode.parameters.get('smoothing').value = smoothing;\n }\n\n // connect to the master out of p5s instance if no snd is provided\n if (source == null) {\n console.log(\n 'Amplitude input source is not ready! Connecting to master output instead'\n );\n p5sound.meter.connect(this._workletNode);\n }\n\n // if it is a p5.Signal\n else if (source instanceof p5.Signal) {\n source.output.connect(this._workletNode);\n }\n // connect to the sound if it is available\n else if (source) {\n source.connect(this._workletNode);\n this._workletNode.disconnect();\n this._workletNode.connect(this.output);\n }\n\n // otherwise, connect to the master out of p5s instance (default)\n else {\n p5sound.meter.connect(this._workletNode);\n }\n};\n\np5.Amplitude.prototype.connect = function (unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(this.panner.connect(p5sound.input));\n }\n};\n\np5.Amplitude.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Returns a single Amplitude reading at the moment it is called.\n * For continuous readings, run in the draw loop.\n *\n * @method getLevel\n * @for p5.Amplitude\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\n * @return {Number} Amplitude as a number between 0.0 and 1.0\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220, 150);\n * textAlign(CENTER);\n * text('tap to play', width/2, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound.isPlaying()) {\n * sound.stop();\n * } else {\n * sound.play();\n * }\n * }\n *
\n */\np5.Amplitude.prototype.getLevel = function (channel) {\n if (typeof channel !== 'undefined') {\n if (this.normalize) {\n return this.stereoVolNorm[channel];\n } else {\n return this.stereoVol[channel];\n }\n } else if (this.normalize) {\n return this.volNorm;\n } else {\n return this.volume;\n }\n};\n\n/**\n * Determines whether the results of Amplitude.process() will be\n * Normalized. To normalize, Amplitude finds the difference the\n * loudest reading it has processed and the maximum amplitude of\n * 1.0. Amplitude adds this difference to all values to produce\n * results that will reliably map between 0.0 and 1.0. However,\n * if a louder moment occurs, the amount that Normalize adds to\n * all the values will change. Accepts an optional boolean parameter\n * (true or false). Normalizing is off by default.\n *\n * @method toggleNormalize\n * @for p5.Amplitude\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\n */\np5.Amplitude.prototype.toggleNormalize = function (bool) {\n if (typeof bool === 'boolean') {\n this.normalize = bool;\n } else {\n this.normalize = !this.normalize;\n }\n this._workletNode.port.postMessage({\n name: 'toggleNormalize',\n normalize: this.normalize,\n });\n};\n\n/**\n * Smooth Amplitude analysis by averaging with the last analysis\n * frame. Off by default.\n *\n * @method smooth\n * @for p5.Amplitude\n * @param {Number} set smoothing from 0.0 <= 1\n */\np5.Amplitude.prototype.smooth = function (s) {\n if (s >= 0 && s < 1) {\n this._workletNode.port.postMessage({ name: 'smoothing', smoothing: s });\n } else {\n console.log('Error: smoothing must be between 0 and 1');\n }\n};\n\np5.Amplitude.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n this._workletNode.disconnect();\n delete this._workletNode;\n};\n","import p5sound from './master';\n\n/**\n *

FFT (Fast Fourier Transform) is an analysis algorithm that\n * isolates individual\n * \n * audio frequencies within a waveform.

\n *\n *

Once instantiated, a p5.FFT object can return an array based on\n * two types of analyses:
• FFT.waveform() computes\n * amplitude values along the time domain. The array indices correspond\n * to samples across a brief moment in time. Each value represents\n * amplitude of the waveform at that sample of time.
\n * • FFT.analyze() computes amplitude values along the\n * frequency domain. The array indices correspond to frequencies (i.e.\n * pitches), from the lowest to the highest that humans can hear. Each\n * value represents amplitude at that slice of the frequency spectrum.\n * Use with getEnergy() to measure amplitude at specific\n * frequencies, or within a range of frequencies.

\n *\n *

FFT analyzes a very short snapshot of sound called a sample\n * buffer. It returns an array of amplitude measurements, referred\n * to as bins. The array is 1024 bins long by default.\n * You can change the bin array length, but it must be a power of 2\n * between 16 and 1024 in order for the FFT algorithm to function\n * correctly. The actual size of the FFT buffer is twice the\n * number of bins, so given a standard sample rate, the buffer is\n * 2048/44100 seconds long.

\n *\n *\n * @class p5.FFT\n * @constructor\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\n * 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n * @param {Number} [bins] Length of resulting array.\n * Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(togglePlay);\n * fft = new p5.FFT();\n * sound.amp(0.2);\n * }\n *\n * function draw(){\n * background(220);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h )\n * }\n *\n * let waveform = fft.waveform();\n * noFill();\n * beginShape();\n * stroke(20);\n * for (let i = 0; i < waveform.length; i++){\n * let x = map(i, 0, waveform.length, 0, width);\n * let y = map( waveform[i], -1, 1, 0, height);\n * vertex(x,y);\n * }\n * endShape();\n *\n * text('tap to play', 20, 20);\n * }\n *\n * function togglePlay() {\n * if (sound.isPlaying()) {\n * sound.pause();\n * } else {\n * sound.loop();\n * }\n * }\n *
\n */\np5.FFT = function (smoothing, bins) {\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\n\n Object.defineProperties(this, {\n bins: {\n get: function () {\n return this.analyser.fftSize / 2;\n },\n set: function (b) {\n this.analyser.fftSize = b * 2;\n },\n configurable: true,\n enumerable: true,\n },\n smoothing: {\n get: function () {\n return this.analyser.smoothingTimeConstant;\n },\n set: function (s) {\n this.analyser.smoothingTimeConstant = s;\n },\n configurable: true,\n enumerable: true,\n },\n });\n\n // set default smoothing and bins\n this.smooth(smoothing);\n this.bins = bins || 1024;\n\n // default connections to p5sound fftMeter\n p5sound.fftMeter.connect(this.analyser);\n\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\n\n // predefined frequency ranges, these will be tweakable\n this.bass = [20, 140];\n this.lowMid = [140, 400];\n this.mid = [400, 2600];\n this.highMid = [2600, 5200];\n this.treble = [5200, 14000];\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Set the input source for the FFT analysis. If no source is\n * provided, FFT will analyze all sound in the sketch.\n *\n * @method setInput\n * @for p5.FFT\n * @param {Object} [source] p5.sound object (or web audio API source node)\n */\np5.FFT.prototype.setInput = function (source) {\n if (!source) {\n p5sound.fftMeter.connect(this.analyser);\n } else {\n if (source.output) {\n source.output.connect(this.analyser);\n } else if (source.connect) {\n source.connect(this.analyser);\n }\n p5sound.fftMeter.disconnect();\n }\n};\n\n/**\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\n * a snapshot of amplitude readings in a single buffer. Length will be\n * equal to bins (defaults to 1024). Can be used to draw the waveform\n * of a sound.\n *\n * @method waveform\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {String} [precision] If any value is provided, will return results\n * in a Float32 Array which is more precise\n * than a regular array.\n * @return {Array} Array Array of amplitude values (-1 to 1)\n * over time. Array length = bins.\n *\n */\np5.FFT.prototype.waveform = function () {\n var bins, mode;\n var normalArray = new Array();\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n bins = arguments[i];\n this.analyser.fftSize = bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\n if (mode && !p5.prototype._isSafari()) {\n timeToFloat(this, this.timeDomain);\n this.analyser.getFloatTimeDomainData(this.timeDomain);\n return this.timeDomain;\n } else {\n timeToInt(this, this.timeDomain);\n this.analyser.getByteTimeDomainData(this.timeDomain);\n for (var j = 0; j < this.timeDomain.length; j++) {\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\n normalArray.push(scaled);\n }\n return normalArray;\n }\n};\n\n/**\n * Returns an array of amplitude values (between 0 and 255)\n * across the frequency spectrum. Length is equal to FFT bins\n * (1024 by default). The array indices correspond to frequencies\n * (i.e. pitches), from the lowest to the highest that humans can\n * hear. Each value represents amplitude at that slice of the\n * frequency spectrum. Must be called prior to using\n * getEnergy().\n *\n * @method analyze\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {Number} [scale] If \"dB,\" returns decibel\n * float measurements between\n * -140 and 0 (max).\n * Otherwise returns integers from 0-255.\n * @return {Array} spectrum Array of energy (amplitude/volume)\n * values across the frequency spectrum.\n * Lowest energy (silence) = 0, highest\n * possible is 255.\n * @example\n *
\n * let osc, fft;\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(startSound);\n * osc = new p5.Oscillator();\n * osc.amp(0);\n * fft = new p5.FFT();\n * }\n *\n * function draw(){\n * background(220);\n *\n * let freq = map(mouseX, 0, windowWidth, 20, 10000);\n * freq = constrain(freq, 1, 20000);\n * osc.freq(freq);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h );\n * }\n *\n * stroke(255);\n * if (!osc.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text(round(freq)+'Hz', 10, 20);\n * }\n * }\n *\n * function startSound() {\n * osc.start();\n * osc.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * osc.amp(0, 0.2);\n * }\n *
\n *\n *\n */\np5.FFT.prototype.analyze = function () {\n var mode;\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n this.bins = arguments[i];\n this.analyser.fftSize = this.bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n if (mode && mode.toLowerCase() === 'db') {\n freqToFloat(this);\n this.analyser.getFloatFrequencyData(this.freqDomain);\n return this.freqDomain;\n } else {\n freqToInt(this, this.freqDomain);\n this.analyser.getByteFrequencyData(this.freqDomain);\n var normalArray = Array.apply([], this.freqDomain);\n\n return normalArray;\n }\n};\n\n/**\n * Returns the amount of energy (volume) at a specific\n * \n * frequency, or the average amount of energy between two\n * frequencies. Accepts Number(s) corresponding\n * to frequency (in Hz), or a String corresponding to predefined\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\n * Returns a range between 0 (no energy/volume at that frequency) and\n * 255 (maximum energy).\n * NOTE: analyze() must be called prior to getEnergy(). Analyze()\n * tells the FFT to analyze frequency data, and getEnergy() uses\n * the results determine the value at a specific frequency or\n * range of frequencies.

\n *\n * @method getEnergy\n * @for p5.FFT\n * @param {Number|String} frequency1 Will return a value representing\n * energy at this frequency. Alternately,\n * the strings \"bass\", \"lowMid\" \"mid\",\n * \"highMid\", and \"treble\" will return\n * predefined frequency ranges.\n * @param {Number} [frequency2] If a second frequency is given,\n * will return average amount of\n * energy that exists between the\n * two frequencies.\n * @return {Number} Energy Energy (volume/amplitude) from\n * 0 and 255.\n *\n */\np5.FFT.prototype.getEnergy = function (frequency1, frequency2) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n\n if (frequency1 === 'bass') {\n frequency1 = this.bass[0];\n frequency2 = this.bass[1];\n } else if (frequency1 === 'lowMid') {\n frequency1 = this.lowMid[0];\n frequency2 = this.lowMid[1];\n } else if (frequency1 === 'mid') {\n frequency1 = this.mid[0];\n frequency2 = this.mid[1];\n } else if (frequency1 === 'highMid') {\n frequency1 = this.highMid[0];\n frequency2 = this.highMid[1];\n } else if (frequency1 === 'treble') {\n frequency1 = this.treble[0];\n frequency2 = this.treble[1];\n }\n\n if (typeof frequency1 !== 'number') {\n throw 'invalid input for getEnergy()';\n } else if (!frequency2) {\n // if only one parameter:\n var index = Math.round((frequency1 / nyquist) * this.freqDomain.length);\n return this.freqDomain[index];\n } else if (frequency1 && frequency2) {\n // if two parameters:\n // if second is higher than first\n if (frequency1 > frequency2) {\n var swap = frequency2;\n frequency2 = frequency1;\n frequency1 = swap;\n }\n var lowIndex = Math.round((frequency1 / nyquist) * this.freqDomain.length);\n var highIndex = Math.round((frequency2 / nyquist) * this.freqDomain.length);\n\n var total = 0;\n var numFrequencies = 0;\n // add up all of the values for the frequencies\n for (var i = lowIndex; i <= highIndex; i++) {\n total += this.freqDomain[i];\n numFrequencies += 1;\n }\n // divide by total number of frequencies\n var toReturn = total / numFrequencies;\n return toReturn;\n } else {\n throw 'invalid input for getEnergy()';\n }\n};\n\n// compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\np5.FFT.prototype.getFreq = function (freq1, freq2) {\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\n var x = this.getEnergy(freq1, freq2);\n return x;\n};\n\n/**\n * Returns the\n * \n * spectral centroid of the input signal.\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\n * tells the FFT to analyze frequency data, and getCentroid() uses\n * the results determine the spectral centroid.

\n *\n * @method getCentroid\n * @for p5.FFT\n * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz.\n *\n *\n * @example\n *
\n * function setup(){\n * cnv = createCanvas(100,100);\n * cnv.mousePressed(userStartAudio);\n * sound = new p5.AudioIn();\n * sound.start();\n * fft = new p5.FFT();\n * sound.connect(fft);\n *}\n *\n *function draw() {\n * if (getAudioContext().state !== 'running') {\n * background(220);\n * text('tap here and enable mic to begin', 10, 20, width - 20);\n * return;\n * }\n * let centroidplot = 0.0;\n * let spectralCentroid = 0;\n *\n * background(0);\n * stroke(0,255,0);\n * let spectrum = fft.analyze();\n * fill(0,255,0); // spectrum is green\n *\n * //draw the spectrum\n * for (let i = 0; i < spectrum.length; i++){\n * let x = map(log(i), 0, log(spectrum.length), 0, width);\n * let h = map(spectrum[i], 0, 255, 0, height);\n * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\n * rect(x, height, rectangle_width, -h )\n * }\n * let nyquist = 22050;\n *\n * // get the centroid\n * spectralCentroid = fft.getCentroid();\n *\n * // the mean_freq_index calculation is for the display.\n * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\n *\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\n *\n * stroke(255,0,0); // the line showing where the centroid is will be red\n *\n * rect(centroidplot, 0, width / spectrum.length, height)\n * noStroke();\n * fill(255,255,255); // text is white\n * text('centroid: ', 10, 20);\n * text(round(spectralCentroid)+' Hz', 10, 40);\n *}\n *
\n */\np5.FFT.prototype.getCentroid = function () {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var cumulative_sum = 0;\n var centroid_normalization = 0;\n\n for (var i = 0; i < this.freqDomain.length; i++) {\n cumulative_sum += i * this.freqDomain[i];\n centroid_normalization += this.freqDomain[i];\n }\n\n var mean_freq_index = 0;\n\n if (centroid_normalization !== 0) {\n mean_freq_index = cumulative_sum / centroid_normalization;\n }\n\n var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length);\n return spec_centroid_freq;\n};\n\n/**\n * Smooth FFT analysis by averaging with the last analysis frame.\n *\n * @method smooth\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n */\np5.FFT.prototype.smooth = function (s) {\n if (typeof s !== 'undefined') {\n this.smoothing = s;\n }\n return this.smoothing;\n};\n\np5.FFT.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.analyser) {\n this.analyser.disconnect();\n delete this.analyser;\n }\n};\n\n/**\n * Returns an array of average amplitude values for a given number\n * of frequency bands split equally. N defaults to 16.\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\n * tells the FFT to analyze frequency data, and linAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method linAverages\n * @for p5.FFT\n * @param {Number} N Number of returned frequency groups\n * @return {Array} linearAverages Array of average amplitude values for each group\n */\np5.FFT.prototype.linAverages = function (_N) {\n var N = _N || 16; // This prevents undefined, null or 0 values of N\n\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n var spectrumStep = Math.floor(spectrumLength / N);\n\n var linearAverages = new Array(N);\n // Keep a second index for the current average group and place the values accordingly\n // with only one loop in the spectrum data\n var groupIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n linearAverages[groupIndex] =\n linearAverages[groupIndex] !== undefined\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n\n // Increase the group index when the last element of the group is processed\n if (specIndex % spectrumStep === spectrumStep - 1) {\n groupIndex++;\n }\n }\n\n return linearAverages;\n};\n\n/**\n * Returns an array of average amplitude values of the spectrum, for a given\n * set of \n * Octave Bands\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\n * tells the FFT to analyze frequency data, and logAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method logAverages\n * @for p5.FFT\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\n * @return {Array} logAverages Array of average amplitude values for each group\n */\np5.FFT.prototype.logAverages = function (octaveBands) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n\n var logAverages = new Array(octaveBands.length);\n // Keep a second index for the current average group and place the values accordingly\n // With only one loop in the spectrum data\n var octaveIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n var specIndexFrequency = Math.round(\n (specIndex * nyquist) / this.freqDomain.length\n );\n\n // Increase the group index if the current frequency exceeds the limits of the band\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\n octaveIndex++;\n }\n\n logAverages[octaveIndex] =\n logAverages[octaveIndex] !== undefined\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n }\n\n return logAverages;\n};\n\n/**\n * Calculates and Returns the 1/N\n * Octave Bands\n * N defaults to 3 and minimum central frequency to 15.625Hz.\n * (1/3 Octave Bands ~= 31 Frequency Bands)\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\n * and produce less frequency groups.\n *\n * @method getOctaveBands\n * @for p5.FFT\n * @param {Number} N Specifies the 1/N type of generated octave bands\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\n * @return {Array} octaveBands Array of octave band objects with their bounds\n */\np5.FFT.prototype.getOctaveBands = function (_N, _fCtr0) {\n var N = _N || 3; // Default to 1/3 Octave Bands\n var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\n\n var octaveBands = [];\n var lastFrequencyBand = {\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\n ctr: fCtr0,\n hi: fCtr0 * Math.pow(2, 1 / (2 * N)),\n };\n octaveBands.push(lastFrequencyBand);\n\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n while (lastFrequencyBand.hi < nyquist) {\n var newFrequencyBand = {};\n newFrequencyBand.lo = lastFrequencyBand.hi;\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\n\n octaveBands.push(newFrequencyBand);\n lastFrequencyBand = newFrequencyBand;\n }\n\n return octaveBands;\n};\n\n// helper methods to convert type from float (dB) to int (0-255)\nfunction freqToFloat(fft) {\n if (fft.freqDomain instanceof Float32Array === false) {\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction freqToInt(fft) {\n if (fft.freqDomain instanceof Uint8Array === false) {\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToFloat(fft) {\n if (fft.timeDomain instanceof Float32Array === false) {\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToInt(fft) {\n if (fft.timeDomain instanceof Uint8Array === false) {\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\n\nexport default p5.FFT;\n","// Signal is built with the Tone.js signal by Yotam Mann\n// https://github.com/TONEnoTONE/Tone.js/\nimport Signal from 'Tone/signal/Signal';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\n\n/**\n *

p5.Signal is a constant audio-rate signal used by p5.Oscillator\n * and p5.Envelope for modulation math.

\n *\n *

This is necessary because Web Audio is processed on a separate clock.\n * For example, the p5 draw loop runs about 60 times per second. But\n * the audio clock must process samples 44100 times per second. If we\n * want to add a value to each of those samples, we can't do it in the\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\n * a Tone.Signal from the Tone.js library by Yotam Mann.\n * If you want to work directly with audio signals for modular\n * synthesis, check out\n * tone.js.

\n *\n * @class p5.Signal\n * @constructor\n * @return {Tone.Signal} A Signal object from the Tone.js library\n * @example\n *
\n * let carrier, modulator;\n * let hasStarted = false;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * carrier = new p5.Oscillator('sine');\n * carrier.amp(1); // set amplitude\n * carrier.freq(220); // set frequency\n *\n * modulator = new p5.Oscillator('sawtooth');\n * modulator.disconnect();\n * modulator.start();\n * modulator.amp(1);\n * modulator.freq(4);\n *\n * // Modulator's default amplitude range is -1 to 1.\n * // Multiply it by -200, so the range is -200 to 200\n * // then add 220 so the range is 20 to 420\n * carrier.freq( modulator.mult(-400).add(220) );\n * }\n *\n * function canvasPressed() {\n * userStartAudio();\n * carrier.amp(1.0);\n * if(!hasStarted){\n * carrier.start();\n * hasStarted = true;\n * }\n * }\n *\n * function mouseReleased() {\n * carrier.amp(0);\n * }\n *
\n */\np5.Signal = function (value) {\n var s = new Signal(value);\n // p5sound.soundArray.push(s);\n return s; // TODO: is this really a constructor?\n};\n\n/**\n * Fade to value, for smooth transitions\n *\n * @method fade\n * @for p5.Signal\n * @param {Number} value Value to set this signal\n * @param {Number} [secondsFromNow] Length of fade, in seconds from now\n */\nSignal.prototype.fade = Signal.prototype.linearRampToValueAtTime;\nMult.prototype.fade = Signal.prototype.fade;\nAdd.prototype.fade = Signal.prototype.fade;\nScale.prototype.fade = Signal.prototype.fade;\n\n/**\n * Connect a p5.sound object or Web Audio node to this\n * p5.Signal so that its amplitude values can be scaled.\n *\n * @method setInput\n * @for p5.Signal\n * @param {Object} input\n */\nSignal.prototype.setInput = function (_input) {\n _input.connect(this);\n};\nMult.prototype.setInput = Signal.prototype.setInput;\nAdd.prototype.setInput = Signal.prototype.setInput;\nScale.prototype.setInput = Signal.prototype.setInput;\n\n// signals can add / mult / scale themselves\n\n/**\n * Add a constant value to this audio signal,\n * and return the resulting audio signal. Does\n * not change the value of the original signal,\n * instead it returns a new p5.SignalAdd.\n *\n * @method add\n * @for p5.Signal\n * @param {Number} number\n * @return {p5.Signal} object\n */\nSignal.prototype.add = function (num) {\n var add = new Add(num);\n // add.setInput(this);\n this.connect(add);\n return add;\n};\nMult.prototype.add = Signal.prototype.add;\nAdd.prototype.add = Signal.prototype.add;\nScale.prototype.add = Signal.prototype.add;\n\n/**\n * Multiply this signal by a constant value,\n * and return the resulting audio signal. Does\n * not change the value of the original signal,\n * instead it returns a new p5.SignalMult.\n *\n * @method mult\n * @for p5.Signal\n * @param {Number} number to multiply\n * @return {p5.Signal} object\n */\nSignal.prototype.mult = function (num) {\n var mult = new Mult(num);\n // mult.setInput(this);\n this.connect(mult);\n return mult;\n};\nMult.prototype.mult = Signal.prototype.mult;\nAdd.prototype.mult = Signal.prototype.mult;\nScale.prototype.mult = Signal.prototype.mult;\n\n/**\n * Scale this signal value to a given range,\n * and return the result as an audio signal. Does\n * not change the value of the original signal,\n * instead it returns a new p5.SignalScale.\n *\n * @method scale\n * @for p5.Signal\n * @param {Number} number to multiply\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Signal} object\n */\nSignal.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var mapOutMin, mapOutMax;\n if (arguments.length === 4) {\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\n } else {\n mapOutMin = arguments[0];\n mapOutMax = arguments[1];\n }\n var scale = new Scale(mapOutMin, mapOutMax);\n this.connect(scale);\n return scale;\n};\n\nMult.prototype.scale = Signal.prototype.scale;\nAdd.prototype.scale = Signal.prototype.scale;\nScale.prototype.scale = Signal.prototype.scale;\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\n\n/**\n *

Creates a signal that oscillates between -1.0 and 1.0.\n * By default, the oscillation takes the form of a sinusoidal\n * shape ('sine'). Additional types include 'triangle',\n * 'sawtooth' and 'square'. The frequency defaults to\n * 440 oscillations per second (440Hz, equal to the pitch of an\n * 'A' note).

\n *\n *

Set the type of oscillation with setType(), or by instantiating a\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\n *

\n *\n * @class p5.Oscillator\n * @constructor\n * @param {Number} [freq] frequency defaults to 440Hz\n * @param {String} [type] type of oscillator. Options:\n * 'sine' (default), 'triangle',\n * 'sawtooth', 'square'\n * @example\n *
\n * let osc, playing, freq, amp;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator('sine');\n * }\n *\n * function draw() {\n * background(220)\n * freq = constrain(map(mouseX, 0, width, 100, 500), 100, 500);\n * amp = constrain(map(mouseY, height, 0, 0, 1), 0, 1);\n *\n * text('tap to play', 20, 20);\n * text('freq: ' + freq, 20, 40);\n * text('amp: ' + amp, 20, 60);\n *\n * if (playing) {\n * // smooth the transitions by 0.1 seconds\n * osc.freq(freq, 0.1);\n * osc.amp(amp, 0.1);\n * }\n * }\n *\n * function playOscillator() {\n * // starting an oscillator on a user gesture will enable audio\n * // in browsers that have a strict autoplay policy.\n * // See also: userStartAudio();\n * osc.start();\n * playing = true;\n * }\n *\n * function mouseReleased() {\n * // ramp amplitude to 0 over 0.5 seconds\n * osc.amp(0, 0.5);\n * playing = false;\n * }\n *
\n */\np5.Oscillator = function (freq, type) {\n if (typeof freq === 'string') {\n let f = type;\n type = freq;\n freq = f;\n }\n if (typeof type === 'number') {\n let f = type;\n type = freq;\n freq = f;\n }\n this.started = false;\n\n // components\n this.phaseAmount = undefined;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.f = freq || 440.0; // frequency\n this.oscillator.type = type || 'sine';\n this.oscillator.frequency.setValueAtTime(\n this.f,\n p5sound.audiocontext.currentTime\n );\n\n // connections\n this.output = p5sound.audiocontext.createGain();\n\n this._freqMods = []; // modulators connected to this oscillator's frequency\n\n // set default output gain to 0.5\n this.output.gain.value = 0.5;\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\n\n this.oscillator.connect(this.output);\n // stereo panning\n this.panPosition = 0.0;\n this.connection = p5sound.input; // connect to p5sound by default\n this.panner = new p5.Panner(this.output, this.connection, 1);\n\n //array of math operation signal chaining\n this.mathOps = [this.output];\n\n // add to the soundArray so we can dispose of the osc later\n p5sound.soundArray.push(this);\n};\n\n/**\n * Start an oscillator.\n *\n * Starting an oscillator on a user gesture will enable audio in browsers\n * that have a strict autoplay policy, including Chrome and most mobile\n * devices. See also: `userStartAudio()`.\n *\n * @method start\n * @for p5.Oscillator\n * @param {Number} [time] startTime in seconds from now.\n * @param {Number} [frequency] frequency in Hz.\n */\np5.Oscillator.prototype.start = function (time, f) {\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n }\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n\n // set old osc free to be garbage collected (memory)\n if (this.oscillator) {\n this.oscillator.disconnect();\n delete this.oscillator;\n }\n\n // var detune = this.oscillator.frequency.value;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.value = Math.abs(freq);\n this.oscillator.type = type;\n // this.oscillator.detune.value = detune;\n this.oscillator.connect(this.output);\n time = time || 0;\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\n this.freqNode = this.oscillator.frequency;\n\n // if other oscillators are already connected to this osc's freq\n for (var i in this._freqMods) {\n if (typeof this._freqMods[i].connect !== 'undefined') {\n this._freqMods[i].connect(this.oscillator.frequency);\n }\n }\n\n this.started = true;\n }\n};\n\n/**\n * Stop an oscillator. Accepts an optional parameter\n * to determine how long (in seconds from now) until the\n * oscillator stops.\n *\n * @method stop\n * @for p5.Oscillator\n * @param {Number} secondsFromNow Time, in seconds from now.\n */\np5.Oscillator.prototype.stop = function (time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n this.started = false;\n }\n};\n\n/**\n * Set the amplitude between 0 and 1.0. Or, pass in an object\n * such as an oscillator to modulate amplitude with an audio signal.\n *\n * @method amp\n * @for p5.Oscillator\n * @param {Number|Object} vol between 0 and 1.0\n * or a modulating signal/oscillator\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {AudioParam} gain If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's\n * gain/amplitude/volume)\n */\np5.Oscillator.prototype.amp = function (vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n};\n\n// these are now the same thing\np5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;\n\n/**\n * Returns the value of output gain\n *\n * @method getAmp\n * @for p5.Oscillator\n *\n * @returns {number} Amplitude value between 0.0 and 1.0\n */\n\np5.Oscillator.prototype.getAmp = function () {\n return this.output.gain.value;\n};\n\n/**\n * Set frequency of an oscillator to a value. Or, pass in an object\n * such as an oscillator to modulate the frequency with an audio signal.\n *\n * @method freq\n * @for p5.Oscillator\n * @param {Number|Object} Frequency Frequency in Hz\n * or modulating signal/oscillator\n * @param {Number} [rampTime] Ramp time (in seconds)\n * @param {Number} [timeFromNow] Schedule this event to happen\n * at x seconds from now\n * @return {AudioParam} Frequency If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's frequency\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator(300);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playOscillator() {\n * osc.start();\n * osc.amp(0.5);\n * // start at 700Hz\n * osc.freq(700);\n * // ramp to 60Hz over 0.7 seconds\n * osc.freq(60, 0.7);\n * osc.amp(0, 0.1, 0.7);\n * }\n *
\n */\np5.Oscillator.prototype.freq = function (val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number' && !isNaN(val)) {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n\n if (rampTime === 0) {\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\n } else {\n if (val > 0) {\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n } else {\n this.oscillator.frequency.linearRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n }\n }\n\n // reset phase if oscillator has a phase\n if (this.phaseAmount) {\n this.phase(this.phaseAmount);\n }\n } else if (val) {\n if (val.output) {\n val = val.output;\n }\n val.connect(this.oscillator.frequency);\n\n // keep track of what is modulating this param\n // so it can be re-connected if\n this._freqMods.push(val);\n } else {\n // return the Frequency Node\n return this.oscillator.frequency;\n }\n};\n/**\n * Returns the value of frequency of oscillator\n *\n * @method getFreq\n * @for p5.Oscillator\n * @returns {number} Frequency of oscillator in Hertz\n */\n\np5.Oscillator.prototype.getFreq = function () {\n return this.oscillator.frequency.value;\n};\n\n/**\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method setType\n * @for p5.Oscillator\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\n */\np5.Oscillator.prototype.setType = function (type) {\n this.oscillator.type = type;\n};\n/**\n * Returns current type of oscillator eg. 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method getType\n * @for p5.Oscillator\n * @returns {String} type of oscillator eg . 'sine', 'triangle', 'sawtooth' or 'square'.\n */\n\np5.Oscillator.prototype.getType = function () {\n return this.oscillator.type;\n};\n\n/**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.Oscillator\n * @param {Object} unit A p5.sound or Web Audio object\n */\np5.Oscillator.prototype.connect = function (unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n this.connection = unit.input;\n } else {\n this.panner.connect(unit);\n this.connection = unit;\n }\n};\n\n/**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.Oscillator\n */\np5.Oscillator.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n if (this.output) {\n this.output.connect(this.panner);\n }\n }\n this.oscMods = [];\n};\n\n/**\n * Pan between Left (-1) and Right (1)\n *\n * @method pan\n * @for p5.Oscillator\n * @param {Number} panning Number between -1 and 1\n * @param {Number} timeFromNow schedule this event to happen\n * seconds from now\n */\np5.Oscillator.prototype.pan = function (pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n};\n\n/**\n * Returns the current value of panPosition , between Left (-1) and Right (1)\n *\n * @method getPan\n * @for p5.Oscillator\n *\n * @returns {number} panPosition of oscillator , between Left (-1) and Right (1)\n */\n\np5.Oscillator.prototype.getPan = function () {\n return this.panPosition;\n};\n\n// get rid of the oscillator\np5.Oscillator.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.oscillator) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.disconnect();\n this.panner = null;\n this.oscillator = null;\n }\n // if it is a Pulse\n if (this.osc2) {\n this.osc2.dispose();\n }\n};\n\n/**\n * Set the phase of an oscillator between 0.0 and 1.0.\n * In this implementation, phase is a delay time\n * based on the oscillator's current frequency.\n *\n * @method phase\n * @for p5.Oscillator\n * @param {Number} phase float between 0.0 and 1.0\n */\np5.Oscillator.prototype.phase = function (p) {\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f);\n var now = p5sound.audiocontext.currentTime;\n\n this.phaseAmount = p;\n\n if (!this.dNode) {\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n // put the delay node in between output and panner\n this.oscillator.disconnect();\n this.oscillator.connect(this.dNode);\n this.dNode.connect(this.output);\n }\n\n // set delay time to match phase:\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\n};\n\n// ========================== //\n// SIGNAL MATH FOR MODULATION //\n// ========================== //\n\n// return sigChain(this, scale, thisChain, nextChain, Scale);\nvar sigChain = function (o, mathObj, thisChain, nextChain, type) {\n var chainSource = o.oscillator;\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n chainSource.disconnect();\n o.mathOps[i].dispose();\n thisChain = i;\n // assume nextChain is output gain node unless...\n if (thisChain < o.mathOps.length - 2) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n if (thisChain === o.mathOps.length - 1) {\n o.mathOps.push(nextChain);\n }\n // assume source is the oscillator unless i > 0\n if (i > 0) {\n chainSource = o.mathOps[i - 1];\n }\n chainSource.disconnect();\n chainSource.connect(mathObj);\n mathObj.connect(nextChain);\n o.mathOps[thisChain] = mathObj;\n return o;\n};\n\n/**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method again\n * will override the initial add() with a new value.\n *\n * @method add\n * @for p5.Oscillator\n * @param {Number} number Constant number to add\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n *\n */\np5.Oscillator.prototype.add = function (num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, add, thisChain, nextChain, Add);\n};\n\n/**\n * Multiply the p5.Oscillator's output amplitude\n * by a fixed value (i.e. turn it up!). Calling this method\n * again will override the initial mult() with a new value.\n *\n * @method mult\n * @for p5.Oscillator\n * @param {Number} number Constant number to multiply\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with multiplied output\n */\np5.Oscillator.prototype.mult = function (num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, mult, thisChain, nextChain, Mult);\n};\n\n/**\n * Scale this oscillator's amplitude values to a given\n * range, and return the oscillator. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Oscillator\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n */\np5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var mapOutMin, mapOutMax;\n if (arguments.length === 4) {\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;\n } else {\n mapOutMin = arguments[0];\n mapOutMax = arguments[1];\n }\n var scale = new Scale(mapOutMin, mapOutMax);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, scale, thisChain, nextChain, Scale);\n\n // this.output.disconnect();\n // this.output.connect(scale)\n};\n\n// ============================== //\n// SinOsc, TriOsc, SqrOsc, SawOsc //\n// ============================== //\n\n/**\n * Constructor: new p5.SinOsc().\n * This creates a Sine Wave Oscillator and is\n * equivalent to new p5.Oscillator('sine')\n * or creating a p5.Oscillator and then calling\n * its method setType('sine').\n * See p5.Oscillator for methods.\n *\n * @class p5.SinOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.SinOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'sine');\n};\n\np5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Constructor: new p5.TriOsc().\n * This creates a Triangle Wave Oscillator and is\n * equivalent to new p5.Oscillator('triangle')\n * or creating a p5.Oscillator and then calling\n * its method setType('triangle').\n * See p5.Oscillator for methods.\n *\n * @class p5.TriOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.TriOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'triangle');\n};\n\np5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Constructor: new p5.SawOsc().\n * This creates a SawTooth Wave Oscillator and is\n * equivalent to new p5.Oscillator('sawtooth')\n * or creating a p5.Oscillator and then calling\n * its method setType('sawtooth').\n * See p5.Oscillator for methods.\n *\n * @class p5.SawOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.SawOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'sawtooth');\n};\n\np5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Constructor: new p5.SqrOsc().\n * This creates a Square Wave Oscillator and is\n * equivalent to new p5.Oscillator('square')\n * or creating a p5.Oscillator and then calling\n * its method setType('square').\n * See p5.Oscillator for methods.\n *\n * @class p5.SqrOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\np5.SqrOsc = function (freq) {\n p5.Oscillator.call(this, freq, 'square');\n};\n\np5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);\n\nexport const Oscillator = p5.Oscillator;\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\n\n/**\n *

Envelopes are pre-defined amplitude distribution over time.\n * Typically, envelopes are used to control the output volume\n * of an object, a series of fades referred to as Attack, Decay,\n * Sustain and Release (\n * ADSR\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\n * control an Oscillator's frequency like this: osc.freq(env).

\n *

Use setRange to change the attack/release level.\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

\n *

Use the play method to play the entire envelope,\n * the ramp method for a pingable trigger,\n * or triggerAttack/\n * triggerRelease to trigger noteOn/noteOff.

\n *\n * @class p5.Envelope\n * @constructor\n * @example\n *
\n * let t1 = 0.1; // attack time in seconds\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n *\n * let env;\n * let triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('tap to play', 20, 20);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope(t1, l1, t2, l2);\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function playSound() {\n * // starting the oscillator ensures that audio is enabled.\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n */\np5.Envelope = function (t1, l1, t2, l2, t3, l3) {\n /**\n * Time until envelope reaches attackLevel\n * @property attackTime\n */\n this.aTime = t1 || 0.1;\n /**\n * Level once attack is complete.\n * @property attackLevel\n */\n this.aLevel = l1 || 1;\n /**\n * Time until envelope reaches decayLevel.\n * @property decayTime\n */\n this.dTime = t2 || 0.5;\n /**\n * Level after decay. The envelope will sustain here until it is released.\n * @property decayLevel\n */\n this.dLevel = l2 || 0;\n /**\n * Duration of the release portion of the envelope.\n * @property releaseTime\n */\n this.rTime = t3 || 0;\n /**\n * Level at the end of the release.\n * @property releaseLevel\n */\n this.rLevel = l3 || 0;\n\n this._rampHighPercentage = 0.98;\n\n this._rampLowPercentage = 0.02;\n\n this.output = p5sound.audiocontext.createGain();\n\n this.control = new TimelineSignal();\n\n this._init(); // this makes sure the envelope starts at zero\n\n this.control.connect(this.output); // connect to the output\n\n this.connection = null; // store connection\n\n //array of math operation signal chaining\n this.mathOps = [this.control];\n\n //whether envelope should be linear or exponential curve\n this.isExponential = false;\n\n // oscillator or buffer source to clear on env complete\n // to save resources if/when it is retriggered\n this.sourceToClear = null;\n\n // set to true if attack is set, then false on release\n this.wasTriggered = false;\n\n // add to the soundArray so we can dispose of the env later\n p5sound.soundArray.push(this);\n};\n\n// this init function just smooths the starting value to zero and gives a start point for the timeline\n// - it was necessary to remove glitches at the beginning.\np5.Envelope.prototype._init = function () {\n var now = p5sound.audiocontext.currentTime;\n var t = now;\n this.control.setTargetAtTime(0.00001, t, 0.001);\n //also, compute the correct time constants\n this._setRampAD(this.aTime, this.dTime);\n};\n\n/**\n * Reset the envelope with a series of time/value pairs.\n *\n * @method set\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds) before level\n * reaches attackLevel\n * @param {Number} attackLevel Typically an amplitude between\n * 0.0 and 1.0\n * @param {Number} decayTime Time\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\n * decayLevel = sustainLevel)\n * @param {Number} releaseTime Release Time (in seconds)\n * @param {Number} releaseLevel Amplitude\n * @example\n *
\n * let attackTime;\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n * let l3 = 0.2; // release time in seconds\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n *\n * attackTime = map(mouseX, 0, width, 0.0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 20);\n * }\n *\n * // mouseClick triggers envelope if over canvas\n * function playSound() {\n * env.set(attackTime, l1, t2, l2, l3);\n *\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n *\n */\np5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) {\n this.aTime = t1;\n this.aLevel = l1;\n this.dTime = t2 || 0;\n this.dLevel = l2 || 0;\n this.rTime = t3 || 0;\n this.rLevel = l3 || 0;\n\n // set time constants for ramp\n this._setRampAD(t1, t2);\n};\n\n/**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) {\n this.aTime = aTime;\n this.dTime = dTime || 0;\n\n // lerp\n this.sPercent = sPercent || 0;\n this.dLevel =\n typeof sPercent !== 'undefined'\n ? sPercent * (this.aLevel - this.rLevel) + this.rLevel\n : 0;\n\n this.rTime = rTime || 0;\n\n // also set time constants for ramp\n this._setRampAD(aTime, dTime);\n};\n\n/**\n * Set max (attackLevel) and min (releaseLevel) of envelope.\n *\n * @method setRange\n * @for p5.Envelope\n * @param {Number} aLevel attack level (defaults to 1)\n * @param {Number} rLevel release level (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setRange = function (aLevel, rLevel) {\n this.aLevel = aLevel || 1;\n this.rLevel = rLevel || 0;\n\n // not sure if this belongs here:\n\n // {Number} [dLevel] decay/sustain level (optional)\n // if (typeof(dLevel) !== 'undefined') {\n // this.dLevel = dLevel\n // } else if (this.sPercent) {\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\n // }\n};\n\n// private (undocumented) method called when ADSR is set to set time constants for ramp\n//\n// Set the \n// time constants for simple exponential ramps.\n// The larger the time constant value, the slower the\n// transition will be.\n//\n// method _setRampAD\n// param {Number} attackTimeConstant attack time constant\n// param {Number} decayTimeConstant decay time constant\n//\np5.Envelope.prototype._setRampAD = function (t1, t2) {\n this._rampAttackTime = this.checkExpInput(t1);\n this._rampDecayTime = this.checkExpInput(t2);\n\n var TCDenominator = 1.0;\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\n};\n\n// private method\np5.Envelope.prototype.setRampPercentages = function (p1, p2) {\n //set the percentages that the simple exponential ramps go to\n this._rampHighPercentage = this.checkExpInput(p1);\n this._rampLowPercentage = this.checkExpInput(p2);\n var TCDenominator = 1.0;\n //now re-compute the time constants based on those percentages\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\n};\n\n/**\n * Assign a parameter to be controlled by this envelope.\n * If a p5.Sound object is given, then the p5.Envelope will control its\n * output gain. If multiple inputs are provided, the env will\n * control all of them.\n *\n * @method setInput\n * @for p5.Envelope\n * @param {Object} [...inputs] A p5.sound object or\n * Web Audio Param.\n */\np5.Envelope.prototype.setInput = function () {\n for (var i = 0; i < arguments.length; i++) {\n this.connect(arguments[i]);\n }\n};\n\n/**\n * Set whether the envelope ramp is linear (default) or exponential.\n * Exponential ramps can be useful because we perceive amplitude\n * and frequency logarithmically.\n *\n * @method setExp\n * @for p5.Envelope\n * @param {Boolean} isExp true is exponential, false is linear\n */\np5.Envelope.prototype.setExp = function (isExp) {\n this.isExponential = isExp;\n};\n\n//helper method to protect against zero values being sent to exponential functions\np5.Envelope.prototype.checkExpInput = function (value) {\n if (value <= 0) {\n value = 0.00000001;\n }\n return value;\n};\n\n/**\n *

Play tells the envelope to start acting on a given input.\n * If the input is a p5.sound object (i.e. AudioIn, Oscillator,\n * SoundFile), then Envelope will control its output volume.\n * Envelopes can also be used to control any \n * Web Audio Audio Param.

\n *\n * @method play\n * @for p5.Envelope\n * @param {Object} unit A p5.sound object or\n * Web Audio Param.\n * @param {Number} [startTime] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * triOsc.start();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * // ensure that audio is enabled\n * userStartAudio();\n *\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) {\n var tFromNow = secondsFromNow || 0;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n this.triggerAttack(unit, tFromNow);\n\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + ~~susTime);\n};\n\n/**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go. Input can be\n * any p5.sound object, or a \n * Web Audio Param.\n *\n * @method triggerAttack\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time from now (in seconds)\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n this.lastAttack = t;\n this.wasTriggered = true;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // after each ramp completes, cancel scheduled values\n // (so they can be overridden in case env has been re-triggered)\n // then, set current value (with linearRamp to avoid click)\n // then, schedule the next automation...\n\n // attack\n t += this.aTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.aLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.aLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // decay to decay level (if using ADSR, then decay level == sustain level)\n t += this.dTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.dLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.dLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n};\n\n/**\n * Trigger the Release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method triggerRelease\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time to trigger the release\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) {\n // only trigger a release if an attack was triggered\n if (!this.wasTriggered) {\n // this currently causes a bit of trouble:\n // if a later release has been scheduled (via the play function)\n // a new earlier release won't interrupt it, because\n // this.wasTriggered has already been set to false.\n // If we want new earlier releases to override, then we need to\n // keep track of the last release time, and if the new release time is\n // earlier, then use it.\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear or exponential ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // release\n t += this.rTime;\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.rLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.rLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n this.wasTriggered = false;\n};\n\n/**\n * Exponentially ramp to a value using the first two\n * values from setADSR(attackTime, decayTime)\n * as \n * time constants for simple exponential ramps.\n * If the value is higher than current value, it uses attackTime,\n * while a decrease uses decayTime.\n *\n * @method ramp\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow When to trigger the ramp\n * @param {Number} v Target value\n * @param {Number} [v2] Second target value\n * @example\n *
\n * let env, osc, amp;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let attackLevel = 1;\n * let decayLevel = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * fill(0,255,0);\n * noStroke();\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime);\n * osc = new p5.Oscillator();\n * osc.amp(env);\n * amp = new p5.Amplitude();\n *\n * cnv.mousePressed(triggerRamp);\n * }\n *\n * function triggerRamp() {\n * // ensures audio is enabled. See also: `userStartAudio`\n * osc.start();\n *\n * env.ramp(osc, 0, attackLevel, decayLevel);\n * }\n *\n * function draw() {\n * background(20);\n * text('tap to play', 10, 20);\n * let h = map(amp.getLevel(), 0, 0.4, 0, height);;\n * rect(0, height, width, -h);\n * }\n *
\n */\np5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n var destination1 = this.checkExpInput(v1);\n var destination2 =\n typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\n\n // connect env to unit if not already connected\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n //get current value\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\n // this.control.cancelScheduledValues(t);\n\n //if it's going up\n if (destination1 > currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\n t += this._rampAttackTime;\n }\n\n //if it's going down\n else if (destination1 < currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\n t += this._rampDecayTime;\n }\n\n // Now the second part of envelope begins\n if (destination2 === undefined) return;\n\n //if it's going up\n if (destination2 > destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\n }\n\n //if it's going down\n else if (destination2 < destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\n }\n};\n\np5.Envelope.prototype.connect = function (unit) {\n this.connection = unit;\n\n // assume we're talking about output gain\n // unless given a different audio param\n if (\n unit instanceof p5.Oscillator ||\n unit instanceof p5.SoundFile ||\n unit instanceof p5.AudioIn ||\n unit instanceof p5.Reverb ||\n unit instanceof p5.Noise ||\n unit instanceof p5.Filter ||\n unit instanceof p5.Delay\n ) {\n unit = unit.output.gain;\n }\n if (unit instanceof AudioParam) {\n //set the initial value\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\n }\n if (unit instanceof p5.Signal) {\n unit.setValue(0);\n }\n this.output.connect(unit);\n};\n\np5.Envelope.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n// Signal Math\n\n/**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method\n * again will override the initial add() with new values.\n *\n * @method add\n * @for p5.Envelope\n * @param {Number} number Constant number to add\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.add = function (num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\n};\n\n/**\n * Multiply the p5.Envelope's output amplitude\n * by a fixed value. Calling this method\n * again will override the initial mult() with new values.\n *\n * @method mult\n * @for p5.Envelope\n * @param {Number} number Constant number to multiply\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.mult = function (num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\n};\n\n/**\n * Scale this envelope's amplitude values to a given\n * range, and return the envelope. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Envelope\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var scale = new Scale(inMin, inMax, outMin, outMax);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\n};\n\n// get rid of the oscillator\np5.Envelope.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.disconnect();\n if (this.control) {\n this.control.dispose();\n this.control = null;\n }\n for (var i = 1; i < this.mathOps.length; i++) {\n this.mathOps[i].dispose();\n }\n};\n\n// Different name for backwards compatibility, replicates p5.Envelope class\np5.Env = function (t1, l1, t2, l2, t3, l3) {\n console.warn(\n 'WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\n 'Please use the new p5.Envelope instead.'\n );\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\n};\np5.Env.prototype = Object.create(p5.Envelope.prototype);\n\nexport default p5.Envelope;\n","import p5sound from './master'\nimport './oscillator'\n\n/**\n * Creates a Pulse object, an oscillator that implements\n * Pulse Width Modulation.\n * The pulse is created with two oscillators.\n * Accepts a parameter for frequency, and to set the\n * width between the pulses. See \n * p5.Oscillator for a full list of methods.\n *\n * @class p5.Pulse\n * @extends p5.Oscillator\n * @constructor\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\n * @param {Number} [w] Width between the pulses (0 to 1.0,\n * defaults to 0)\n * @example\n *
\n * let pulse;\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startPulse);\n * background(220);\n *\n * pulse = new p5.Pulse();\n * pulse.amp(0.5);\n * pulse.freq(220);\n * }\n * function startPulse() {\n * pulse.start();\n * pulse.amp(0.5, 0.02);\n * }\n * function mouseReleased() {\n * pulse.amp(0, 0.2);\n * }\n * function draw() {\n * background(220);\n * text('tap to play', 5, 20, width - 20);\n * let w = map(mouseX, 0, width, 0, 1);\n * w = constrain(w, 0, 1);\n * pulse.width(w);\n * text('pulse width: ' + w, 5, height - 20);\n * }\n *
\n */\np5.Pulse = function (freq, w) {\n p5.Oscillator.call(this, freq, 'sawtooth');\n\n // width of PWM, should be betw 0 to 1.0\n this.w = w || 0;\n\n // create a second oscillator with inverse frequency\n this.osc2 = new p5.SawOsc(freq);\n\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n\n // dc offset\n this.dcOffset = createDCOffset();\n this.dcGain = p5sound.audiocontext.createGain();\n this.dcOffset.connect(this.dcGain);\n this.dcGain.connect(this.output);\n // set delay time based on PWM width\n this.f = freq || 440;\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n\n // disconnect osc2 and connect it to delay, which is connected to output\n this.osc2.disconnect();\n this.osc2.panner.disconnect();\n this.osc2.amp(-1); // inverted amplitude\n this.osc2.output.connect(this.dNode);\n this.dNode.connect(this.output);\n\n this.output.gain.value = 1;\n this.output.connect(this.panner);\n};\n\np5.Pulse.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Set the width of a Pulse object (an oscillator that implements\n * Pulse Width Modulation).\n *\n * @method width\n * @param {Number} [width] Width between the pulses (0 to 1.0,\n * defaults to 0)\n */\np5.Pulse.prototype.width = function (w) {\n if (typeof w === 'number') {\n if (w <= 1.0 && w >= 0.0) {\n this.w = w;\n // set delay time based on PWM width\n\n // var mW = map(this.w, 0, 1.0, 0, 1/this.f);\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n }\n\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n } else {\n w.connect(this.dNode.delayTime);\n var sig = new p5.SignalAdd(-0.5);\n sig.setInput(w);\n sig = sig.mult(-1);\n sig = sig.mult(1.7);\n sig.connect(this.dcGain.gain);\n }\n};\n\np5.Pulse.prototype.start = function (f, time) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.setValueAtTime(freq, now);\n this.oscillator.type = type;\n this.oscillator.connect(this.output);\n this.oscillator.start(t + now);\n\n // set up osc2\n this.osc2.oscillator = p5sound.audiocontext.createOscillator();\n this.osc2.oscillator.frequency.setValueAtTime(freq, t + now);\n this.osc2.oscillator.type = type;\n this.osc2.oscillator.connect(this.osc2.output);\n this.osc2.start(t + now);\n this.freqNode = [this.oscillator.frequency, this.osc2.oscillator.frequency];\n\n // start dcOffset, too\n this.dcOffset = createDCOffset();\n this.dcOffset.connect(this.dcGain);\n this.dcOffset.start(t + now);\n\n // if LFO connections depend on these oscillators\n if (this.mods !== undefined && this.mods.frequency !== undefined) {\n this.mods.frequency.connect(this.freqNode[0]);\n this.mods.frequency.connect(this.freqNode[1]);\n }\n this.started = true;\n this.osc2.started = true;\n }\n};\n\np5.Pulse.prototype.stop = function (time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n if (this.osc2.oscillator) {\n this.osc2.oscillator.stop(t + now);\n }\n this.dcOffset.stop(t + now);\n this.started = false;\n this.osc2.started = false;\n }\n};\n\np5.Pulse.prototype.freq = function (val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number') {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n var currentFreq = this.oscillator.frequency.value;\n this.oscillator.frequency.cancelScheduledValues(now);\n this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n this.osc2.oscillator.frequency.cancelScheduledValues(now);\n this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);\n this.osc2.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n\n if (this.freqMod) {\n this.freqMod.output.disconnect();\n this.freqMod = null;\n }\n } else if (val.output) {\n val.output.disconnect();\n val.output.connect(this.oscillator.frequency);\n val.output.connect(this.osc2.oscillator.frequency);\n this.freqMod = val;\n }\n};\n\n// inspiration: http://webaudiodemos.appspot.com/oscilloscope/\nfunction createDCOffset() {\n var ac = p5sound.audiocontext;\n var buffer = ac.createBuffer(1, 2048, ac.sampleRate);\n var data = buffer.getChannelData(0);\n for (var i = 0; i < 2048; i++) data[i] = 1.0;\n var bufferSource = ac.createBufferSource();\n bufferSource.buffer = buffer;\n bufferSource.loop = true;\n return bufferSource;\n}\n","import p5sound from './master';\n\n// generate noise buffers\nconst _whiteNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var whiteBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = whiteBuffer.getChannelData(0);\n for (var i = 0; i < bufferSize; i++) {\n noiseData[i] = Math.random() * 2 - 1;\n }\n whiteBuffer.type = 'white';\n return whiteBuffer;\n})();\n\nconst _pinkNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var pinkBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = pinkBuffer.getChannelData(0);\n var b0, b1, b2, b3, b4, b5, b6;\n b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n b0 = 0.99886 * b0 + white * 0.0555179;\n b1 = 0.99332 * b1 + white * 0.0750759;\n b2 = 0.969 * b2 + white * 0.153852;\n b3 = 0.8665 * b3 + white * 0.3104856;\n b4 = 0.55 * b4 + white * 0.5329522;\n b5 = -0.7616 * b5 - white * 0.016898;\n noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;\n noiseData[i] *= 0.11; // (roughly) compensate for gain\n b6 = white * 0.115926;\n }\n pinkBuffer.type = 'pink';\n return pinkBuffer;\n})();\n\nconst _brownNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var brownBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = brownBuffer.getChannelData(0);\n var lastOut = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n noiseData[i] = (lastOut + 0.02 * white) / 1.02;\n lastOut = noiseData[i];\n noiseData[i] *= 3.5;\n }\n brownBuffer.type = 'brown';\n return brownBuffer;\n})();\n\n/**\n * Noise is a type of oscillator that generates a buffer with random values.\n *\n * @class p5.Noise\n * @extends p5.Oscillator\n * @constructor\n * @param {String} type Type of noise can be 'white' (default),\n * 'brown' or 'pink'.\n */\np5.Noise = function (type) {\n var assignType;\n p5.Oscillator.call(this);\n delete this.f;\n delete this.freq;\n delete this.oscillator;\n\n if (type === 'brown') {\n assignType = _brownNoiseBuffer;\n } else if (type === 'pink') {\n assignType = _pinkNoiseBuffer;\n } else {\n assignType = _whiteNoiseBuffer;\n }\n this.buffer = assignType;\n};\n\np5.Noise.prototype = Object.create(p5.Oscillator.prototype);\n\n/**\n * Set type of noise to 'white', 'pink' or 'brown'.\n * White is the default.\n *\n * @method setType\n * @param {String} [type] 'white', 'pink' or 'brown'\n */\np5.Noise.prototype.setType = function (type) {\n switch (type) {\n case 'white':\n this.buffer = _whiteNoiseBuffer;\n break;\n case 'pink':\n this.buffer = _pinkNoiseBuffer;\n break;\n case 'brown':\n this.buffer = _brownNoiseBuffer;\n break;\n default:\n this.buffer = _whiteNoiseBuffer;\n }\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.start(now + 0.01);\n }\n};\n\np5.Noise.prototype.getType = function () {\n return this.buffer.type;\n};\n\np5.Noise.prototype.start = function () {\n if (this.started) {\n this.stop();\n }\n this.noise = p5sound.audiocontext.createBufferSource();\n this.noise.buffer = this.buffer;\n this.noise.loop = true;\n this.noise.connect(this.output);\n var now = p5sound.audiocontext.currentTime;\n this.noise.start(now);\n this.started = true;\n};\n\np5.Noise.prototype.stop = function () {\n var now = p5sound.audiocontext.currentTime;\n if (this.noise) {\n this.noise.stop(now);\n this.started = false;\n }\n};\n\np5.Noise.prototype.dispose = function () {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.noise) {\n this.noise.disconnect();\n this.stop(now);\n }\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n }\n this.output = null;\n this.panner = null;\n this.buffer = null;\n this.noise = null;\n};\n","import p5sound from './master';\n\n// an array of input sources\np5sound.inputSources = [];\n\n/**\n *

Get audio from an input, i.e. your computer's microphone.

\n *\n *

Turn the mic on/off with the start() and stop() methods. When the mic\n * is on, its volume can be measured with getLevel or by connecting an\n * FFT object.

\n *\n *

If you want to hear the AudioIn, use the .connect() method.\n * AudioIn does not connect to p5.sound output by default to prevent\n * feedback.

\n *\n *

Note: This uses the getUserMedia/\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\n * is limited to localhost and https, but access over http may be limited.

\n *\n * @class p5.AudioIn\n * @constructor\n * @param {Function} [errorCallback] A function to call if there is an error\n * accessing the AudioIn. For example,\n * Safari and iOS devices do not\n * currently allow microphone access.\n * @example\n *
\n * let mic;\n *\n * function setup(){\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(userStartAudio);\n * textAlign(CENTER);\n * mic = new p5.AudioIn();\n * mic.start();\n * }\n *\n * function draw(){\n * background(0);\n * fill(255);\n * text('tap to start', width/2, 20);\n *\n * micLevel = mic.getLevel();\n * let y = height - micLevel * height;\n * ellipse(width/2, y, 10, 10);\n * }\n *
\n */\np5.AudioIn = function (errorCallback) {\n // set up audio input\n /**\n * @property {GainNode} input\n */\n this.input = p5sound.audiocontext.createGain();\n /**\n * @property {GainNode} output\n */\n this.output = p5sound.audiocontext.createGain();\n\n /**\n * @property {MediaStream|null} stream\n */\n this.stream = null;\n /**\n * @property {MediaStreamAudioSourceNode|null} mediaStream\n */\n this.mediaStream = null;\n /**\n * @property {Number|null} currentSource\n */\n this.currentSource = null;\n\n /**\n * Client must allow browser to access their microphone / audioin source.\n * Default: false. Will become true when the client enables access.\n *\n * @property {Boolean} enabled\n */\n this.enabled = false;\n\n /**\n * Input amplitude, connect to it by default but not to master out\n *\n * @property {p5.Amplitude} amplitude\n */\n this.amplitude = new p5.Amplitude();\n this.output.connect(this.amplitude.input);\n\n if (\n !window.MediaStreamTrack ||\n !window.navigator.mediaDevices ||\n !window.navigator.mediaDevices.getUserMedia\n ) {\n errorCallback\n ? errorCallback()\n : window.alert(\n 'This browser does not support MediaStreamTrack and mediaDevices'\n );\n }\n\n // add to soundArray so we can dispose on close\n p5sound.soundArray.push(this);\n};\n\n/**\n * Start processing audio input. This enables the use of other\n * AudioIn methods like getLevel(). Note that by default, AudioIn\n * is not connected to p5.sound's output. So you won't hear\n * anything unless you use the connect() method.
\n *\n * Certain browsers limit access to the user's microphone. For example,\n * Chrome only allows access from localhost and over https. For this reason,\n * you may want to include an errorCallback—a function that is called in case\n * the browser won't provide mic access.\n *\n * @method start\n * @for p5.AudioIn\n * @param {Function} [successCallback] Name of a function to call on\n * success.\n * @param {Function} [errorCallback] Name of a function to call if\n * there was an error. For example,\n * some browsers do not support\n * getUserMedia.\n */\np5.AudioIn.prototype.start = function (successCallback, errorCallback) {\n var self = this;\n\n if (this.stream) {\n this.stop();\n }\n\n // set the audio source\n var audioSource = p5sound.inputSources[self.currentSource];\n var constraints = {\n audio: {\n sampleRate: p5sound.audiocontext.sampleRate,\n echoCancellation: false,\n },\n };\n\n // if developers determine which source to use\n if (p5sound.inputSources[this.currentSource]) {\n constraints.audio.deviceId = audioSource.deviceId;\n }\n\n window.navigator.mediaDevices\n .getUserMedia(constraints)\n .then(function (stream) {\n self.stream = stream;\n self.enabled = true;\n // Wrap a MediaStreamSourceNode around the live input\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\n self.mediaStream.connect(self.output);\n // only send to the Amplitude reader, so we can see it but not hear it.\n self.amplitude.setInput(self.output);\n if (successCallback) successCallback();\n })\n .catch(function (err) {\n if (errorCallback) errorCallback(err);\n else console.error(err);\n });\n};\n\n/**\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\n * If re-starting, the user may be prompted for permission access.\n *\n * @method stop\n * @for p5.AudioIn\n */\np5.AudioIn.prototype.stop = function () {\n if (this.stream) {\n this.stream.getTracks().forEach(function (track) {\n track.stop();\n });\n\n this.mediaStream.disconnect();\n\n delete this.mediaStream;\n delete this.stream;\n }\n};\n\n/**\n * Connect to an audio unit. If no parameter is provided, will\n * connect to the master output (i.e. your speakers).
\n *\n * @method connect\n * @for p5.AudioIn\n * @param {Object} [unit] An object that accepts audio input,\n * such as an FFT\n */\np5.AudioIn.prototype.connect = function (unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else if (unit.hasOwnProperty('analyser')) {\n this.output.connect(unit.analyser);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(p5sound.input);\n }\n};\n\n/**\n * Disconnect the AudioIn from all audio units. For example, if\n * connect() had been called, disconnect() will stop sending\n * signal to your speakers.
\n *\n * @method disconnect\n * @for p5.AudioIn\n */\np5.AudioIn.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n // stay connected to amplitude even if not outputting to p5\n this.output.connect(this.amplitude.input);\n }\n};\n\n/**\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\n * class contains its own instance of the Amplitude class to help\n * make it easy to get a microphone's volume level. Accepts an\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\n * .start() before using .getLevel().
\n *\n * @method getLevel\n * @for p5.AudioIn\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\n * Smooths values based on previous values.\n * @return {Number} Volume level (between 0.0 and 1.0)\n */\np5.AudioIn.prototype.getLevel = function (smoothing) {\n if (smoothing) {\n this.amplitude.smoothing = smoothing;\n }\n return this.amplitude.getLevel();\n};\n\n/**\n * Set amplitude (volume) of a mic input between 0 and 1.0.
\n *\n * @method amp\n * @for p5.AudioIn\n * @param {Number} vol between 0 and 1.0\n * @param {Number} [time] ramp time (optional)\n */\np5.AudioIn.prototype.amp = function (vol, t) {\n if (t) {\n var rampTime = t || 0;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(\n currentVol,\n p5sound.audiocontext.currentTime\n );\n this.output.gain.linearRampToValueAtTime(\n vol,\n rampTime + p5sound.audiocontext.currentTime\n );\n } else {\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\n }\n};\n\n/**\n * Returns a list of available input sources. This is a wrapper\n * for \n * MediaDevices.enumerateDevices() - Web APIs | MDN\n * and it returns a Promise.\n * @method getSources\n * @for p5.AudioIn\n * @param {Function} [successCallback] This callback function handles the sources when they\n * have been enumerated. The callback function\n * receives the deviceList array as its only argument\n * @param {Function} [errorCallback] This optional callback receives the error\n * message as its argument.\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\n * to the enumerateDevices() method\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\np5.AudioIn.prototype.getSources = function (onSuccess, onError) {\n return new Promise(function (resolve, reject) {\n window.navigator.mediaDevices\n .enumerateDevices()\n .then(function (devices) {\n p5sound.inputSources = devices.filter(function (device) {\n return device.kind === 'audioinput';\n });\n resolve(p5sound.inputSources);\n if (onSuccess) {\n onSuccess(p5sound.inputSources);\n }\n })\n .catch(function (error) {\n reject(error);\n if (onError) {\n onError(error);\n } else {\n console.error(\n 'This browser does not support MediaStreamTrack.getSources()'\n );\n }\n });\n });\n};\n\n/**\n * Set the input source. Accepts a number representing a\n * position in the array returned by getSources().\n * This is only available in browsers that support\n * \n * navigator.mediaDevices.enumerateDevices()\n *\n * @method setSource\n * @for p5.AudioIn\n * @param {number} num position of input source in the array\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\np5.AudioIn.prototype.setSource = function (num) {\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\n // set the current source\n this.currentSource = num;\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\n } else {\n console.log('unable to set input source');\n }\n\n // restart stream if currently active\n if (this.stream && this.stream.active) {\n this.start();\n }\n};\n\n// private method\np5.AudioIn.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop();\n\n if (this.output) {\n this.output.disconnect();\n }\n if (this.amplitude) {\n this.amplitude.disconnect();\n }\n delete this.amplitude;\n delete this.output;\n};\n","import p5sound from './master';\nimport CrossFade from 'Tone/component/CrossFade.js';\n\n/**\n * Effect is a base class for audio effects in p5.
\n * This module handles the nodes and methods that are\n * common and useful for current and future effects.\n *\n *\n * This class is extended by p5.Distortion,\n * p5.Compressor,\n * p5.Delay,\n * p5.Filter,\n * p5.Reverb.\n *\n * @class p5.Effect\n * @constructor\n *\n * @param {Object} [ac] Reference to the audio context of the p5 object\n * @param {AudioNode} [input] Gain Node effect wrapper\n * @param {AudioNode} [output] Gain Node effect wrapper\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\n * @param {AudioNode} [wet] Effects that extend this class should connect\n * to the wet signal to this gain node, so that dry and wet\n * signals are mixed properly.\n */\np5.Effect = function () {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n /**\n *\tThe p5.Effect class is built\n * \tusing Tone.js CrossFade\n * \t@private\n */\n\n this._drywet = new CrossFade(1);\n\n /**\n *\tIn classes that extend\n *\tp5.Effect, connect effect nodes\n *\tto the wet parameter\n */\n this.wet = this.ac.createGain();\n\n this.input.connect(this._drywet.a);\n this.wet.connect(this._drywet.b);\n this._drywet.connect(this.output);\n\n this.connect();\n\n //Add to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Set the output volume of the filter.\n *\n * @method amp\n * @for p5.Effect\n * @param {Number} [vol] amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts until rampTime\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\n */\np5.Effect.prototype.amp = function (vol, rampTime = 0, tFromNow = 0) {\n const now = p5sound.audiocontext.currentTime;\n const startTime = now + tFromNow;\n const endTime = startTime + rampTime + 0.001;\n const currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, startTime + 0.001);\n this.output.gain.linearRampToValueAtTime(vol, endTime);\n};\n\n/**\n * Link effects together in a chain\n * Example usage: filter.chain(reverb, delay, panner);\n * May be used with an open-ended number of arguments\n *\n * @method chain\n * @for p5.Effect\n * @param {Object} [arguments] Chain together multiple sound objects\n */\np5.Effect.prototype.chain = function () {\n if (arguments.length > 0) {\n this.connect(arguments[0]);\n for (var i = 1; i < arguments.length; i += 1) {\n arguments[i - 1].connect(arguments[i]);\n }\n }\n return this;\n};\n\n/**\n * Adjust the dry/wet value.\n *\n * @method drywet\n * @for p5.Effect\n * @param {Number} [fade] The desired drywet value (0 - 1.0)\n */\np5.Effect.prototype.drywet = function (fade) {\n if (typeof fade !== 'undefined') {\n this._drywet.fade.value = fade;\n }\n return this._drywet.fade.value;\n};\n\n/**\n * Send output to a p5.js-sound, Web Audio Node, or use signal to\n * control an AudioParam\n *\n * @method connect\n * @for p5.Effect\n * @param {Object} unit\n */\np5.Effect.prototype.connect = function (unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all output.\n * @method disconnect\n * @for p5.Effect\n */\np5.Effect.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\np5.Effect.prototype.dispose = function () {\n // remove refernce form soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n if (this._drywet) {\n this._drywet.disconnect();\n delete this._drywet;\n }\n\n if (this.wet) {\n this.wet.disconnect();\n delete this.wet;\n }\n\n this.ac = undefined;\n};\n\nconst Effect = p5.Effect;\n\nexport default Effect","import Effect from './effect';\n\n/**\n *

A p5.Filter uses a Web Audio Biquad Filter to filter\n * the frequency response of an input source. Subclasses\n * include:

\n * p5.LowPass:\n * Allows frequencies below the cutoff frequency to pass through,\n * and attenuates frequencies above the cutoff.
\n * p5.HighPass:\n * The opposite of a lowpass filter.
\n * p5.BandPass:\n * Allows a range of frequencies to pass through and attenuates\n * the frequencies below and above this frequency range.
\n *\n * The .res() method controls either width of the\n * bandpass, or resonance of the low/highpass cutoff frequency.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Filter\n * @extends p5.Effect\n * @constructor\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\n * @example\n *
\n * let fft, noise, filter;\n *\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(makeNoise);\n * fill(255, 0, 255);\n *\n * filter = new p5.BandPass();\n * noise = new p5.Noise();\n * noise.disconnect();\n * noise.connect(filter);\n *\n * fft = new p5.FFT();\n * }\n *\n * function draw() {\n * background(220);\n *\n * // set the BandPass frequency based on mouseX\n * let freq = map(mouseX, 0, width, 20, 10000);\n * freq = constrain(freq, 0, 22050);\n * filter.freq(freq);\n * // give the filter a narrow band (lower res = wider bandpass)\n * filter.res(50);\n *\n * // draw filtered spectrum\n * let spectrum = fft.analyze();\n * noStroke();\n * for (let i = 0; i < spectrum.length; i++) {\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width/spectrum.length, h);\n * }\n * if (!noise.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text('Frequency: ' + round(freq)+'Hz', 20, 20, width - 20);\n * }\n * }\n *\n * function makeNoise() {\n * // see also: `userStartAudio()`\n * noise.start();\n * noise.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * noise.amp(0, 0.2);\n * }\n *\n *
\n */\np5.Filter = function (type) {\n Effect.call(this);\n //add extend Effect by adding a Biquad Filter\n\n /**\n * The p5.Filter is built with a\n * \n * Web Audio BiquadFilter Node.\n *\n * @property {DelayNode} biquadFilter\n */\n\n this.biquad = this.ac.createBiquadFilter();\n\n this.input.connect(this.biquad);\n\n this.biquad.connect(this.wet);\n\n if (type) {\n this.setType(type);\n }\n\n //Properties useful for the toggle method.\n this._on = true;\n this._untoggledType = this.biquad.type;\n};\np5.Filter.prototype = Object.create(Effect.prototype);\n\n/**\n * Filter an audio signal according to a set\n * of filter parameters.\n *\n * @method process\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance/Width of the filter frequency\n * from 0.001 to 1000\n */\np5.Filter.prototype.process = function (src, freq, res, time) {\n src.connect(this.input);\n this.set(freq, res, time);\n};\n\n/**\n * Set the frequency and the resonance of the filter.\n *\n * @method set\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\np5.Filter.prototype.set = function (freq, res, time) {\n if (freq) {\n this.freq(freq, time);\n }\n if (res) {\n this.res(res, time);\n }\n};\n\n/**\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\n * human hearing, although in reality most people hear in a narrower\n * range).\n *\n * @method freq\n * @param {Number} freq Filter Frequency\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current frequency value\n */\np5.Filter.prototype.freq = function (freq, time) {\n var t = time || 0;\n if (freq <= 0) {\n freq = 1;\n }\n if (typeof freq === 'number') {\n this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.frequency.exponentialRampToValueAtTime(\n freq,\n this.ac.currentTime + 0.02 + t\n );\n } else if (freq) {\n freq.connect(this.biquad.frequency);\n }\n return this.biquad.frequency.value;\n};\n\n/**\n * Controls either width of a bandpass frequency,\n * or the resonance of a low/highpass cutoff frequency.\n *\n * @method res\n * @param {Number} res Resonance/Width of filter freq\n * from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current res value\n */\np5.Filter.prototype.res = function (res, time) {\n var t = time || 0;\n if (typeof res === 'number') {\n this.biquad.Q.value = res;\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);\n } else if (res) {\n res.connect(this.biquad.Q);\n }\n return this.biquad.Q.value;\n};\n\n/**\n * Controls the gain attribute of a Biquad Filter.\n * This is distinctly different from .amp() which is inherited from p5.Effect\n * .amp() controls the volume via the output gain node\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\n *\n * @method gain\n * @param {Number} gain\n * @return {Number} Returns the current or updated gain value\n */\np5.Filter.prototype.gain = function (gain, time) {\n var t = time || 0;\n if (typeof gain === 'number') {\n this.biquad.gain.value = gain;\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.gain.linearRampToValueAtTime(\n gain,\n this.ac.currentTime + 0.02 + t\n );\n } else if (gain) {\n gain.connect(this.biquad.gain);\n }\n return this.biquad.gain.value;\n};\n\n/**\n * Toggle function. Switches between the specified type and allpass\n *\n * @method toggle\n * @return {boolean} [Toggle value]\n */\np5.Filter.prototype.toggle = function () {\n this._on = !this._on;\n\n if (this._on === true) {\n this.biquad.type = this._untoggledType;\n } else if (this._on === false) {\n this.biquad.type = 'allpass';\n }\n\n return this._on;\n};\n\n/**\n * Set the type of a p5.Filter. Possible types include:\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\n * \"allpass\".\n *\n * @method setType\n * @param {String} t\n */\np5.Filter.prototype.setType = function (t) {\n this.biquad.type = t;\n this._untoggledType = this.biquad.type;\n};\n\np5.Filter.prototype.dispose = function () {\n // remove reference from soundArray\n Effect.prototype.dispose.apply(this);\n if (this.biquad) {\n this.biquad.disconnect();\n delete this.biquad;\n }\n};\n\n/**\n * Constructor: new p5.LowPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('lowpass').\n * See p5.Filter for methods.\n *\n * @class p5.LowPass\n * @constructor\n * @extends p5.Filter\n */\np5.LowPass = function () {\n p5.Filter.call(this, 'lowpass');\n};\np5.LowPass.prototype = Object.create(p5.Filter.prototype);\n\n/**\n * Constructor: new p5.HighPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('highpass').\n * See p5.Filter for methods.\n *\n * @class p5.HighPass\n * @constructor\n * @extends p5.Filter\n */\np5.HighPass = function () {\n p5.Filter.call(this, 'highpass');\n};\np5.HighPass.prototype = Object.create(p5.Filter.prototype);\n\n/**\n * Constructor: new p5.BandPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('bandpass').\n * See p5.Filter for methods.\n *\n * @class p5.BandPass\n * @constructor\n * @extends p5.Filter\n */\np5.BandPass = function () {\n p5.Filter.call(this, 'bandpass');\n};\np5.BandPass.prototype = Object.create(p5.Filter.prototype);\n\nexport default p5.Filter;\n","import Filter from './filter';\nimport p5sound from './master';\n\n/**\n * EQFilter extends p5.Filter with constraints\n * necessary for the p5.EQ\n *\n * @private\n */\nvar EQFilter = function (freq, res) {\n Filter.call(this, 'peaking');\n this.disconnect();\n this.set(freq, res);\n this.biquad.gain.value = 0;\n delete this.input;\n delete this.output;\n delete this._drywet;\n delete this.wet;\n};\nEQFilter.prototype = Object.create(Filter.prototype);\n\nEQFilter.prototype.amp = function () {\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\n};\nEQFilter.prototype.drywet = function () {\n console.warn('`drywet()` is not available for p5.EQ bands.');\n};\nEQFilter.prototype.connect = function (unit) {\n var u = unit || p5.soundOut.input;\n if (this.biquad) {\n this.biquad.connect(u.input ? u.input : u);\n } else {\n this.output.connect(u.input ? u.input : u);\n }\n};\n\nEQFilter.prototype.disconnect = function () {\n if (this.biquad) {\n this.biquad.disconnect();\n }\n};\nEQFilter.prototype.dispose = function () {\n // remove reference form soundArray\n const index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n this.disconnect();\n delete this.biquad;\n};\n\nexport default EQFilter;\n","import Effect from './effect';\nimport EQFilter from './eqFilter';\n\n/**\n * p5.EQ is an audio effect that performs the function of a multiband\n * audio equalizer. Equalization is used to adjust the balance of\n * frequency compoenents of an audio signal. This process is commonly used\n * in sound production and recording to change the waveform before it reaches\n * a sound output device. EQ can also be used as an audio effect to create\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\n * built using a chain of Web Audio Biquad Filter Nodes and can be\n * instantiated with 3 or 8 bands. Bands can be added or removed from\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.EQ\n * @constructor\n * @extends p5.Effect\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\n * @return {Object} p5.EQ object\n *\n * @example\n *
\n * let eq, soundFile\n * let eqBandIndex = 0;\n * let eqBandNames = ['lows', 'mids', 'highs'];\n *\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * soundFile = loadSound('assets/beat');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(toggleSound);\n *\n * eq = new p5.EQ(eqBandNames.length);\n * soundFile.disconnect();\n * eq.process(soundFile);\n * }\n *\n * function draw() {\n * background(30);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n * text('filtering ', 50, 25);\n *\n * fill(255, 40, 255);\n * textSize(26);\n * text(eqBandNames[eqBandIndex], 50, 55);\n *\n * fill(255);\n * textSize(9);\n *\n * if (!soundFile.isPlaying()) {\n * text('tap to play', 50, 80);\n * } else {\n * text('tap to filter next band', 50, 80)\n * }\n * }\n *\n * function toggleSound() {\n * if (!soundFile.isPlaying()) {\n * soundFile.play();\n * } else {\n * eqBandIndex = (eqBandIndex + 1) % eq.bands.length;\n * }\n *\n * for (let i = 0; i < eq.bands.length; i++) {\n * eq.bands[i].gain(0);\n * }\n * // filter the band we want to filter\n * eq.bands[eqBandIndex].gain(-40);\n * }\n *
\n */\np5.EQ = function (_eqsize) {\n Effect.call(this);\n\n //p5.EQ can be of size (3) or (8), defaults to 3\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\n\n var factor;\n _eqsize === 3 ? (factor = Math.pow(2, 3)) : (factor = 2);\n\n /**\n * The p5.EQ is built with abstracted p5.Filter objects.\n * To modify any bands, use methods of the \n * p5.Filter API, especially `gain` and `freq`.\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\n * @property {Array} bands\n *\n */\n this.bands = [];\n\n var freq, res;\n for (var i = 0; i < _eqsize; i++) {\n if (i === _eqsize - 1) {\n freq = 21000;\n res = 0.01;\n } else if (i === 0) {\n freq = 100;\n res = 0.1;\n } else if (i === 1) {\n freq = _eqsize === 3 ? 360 * factor : 360;\n res = 1;\n } else {\n freq = this.bands[i - 1].freq() * factor;\n res = 1;\n }\n this.bands[i] = this._newBand(freq, res);\n\n if (i > 0) {\n this.bands[i - 1].connect(this.bands[i].biquad);\n } else {\n this.input.connect(this.bands[i].biquad);\n }\n }\n this.bands[_eqsize - 1].connect(this.output);\n};\np5.EQ.prototype = Object.create(Effect.prototype);\n\n/**\n * Process an input by connecting it to the EQ\n * @method process\n * @param {Object} src Audio source\n */\np5.EQ.prototype.process = function (src) {\n src.connect(this.input);\n};\n\n// /**\n// * Set the frequency and gain of each band in the EQ. This method should be\n// * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\n// * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\n// *\n// * @method set\n// * @for p5.EQ\n// * @param {Number} [freq0] Frequency value for band with index 0\n// * @param {Number} [gain0] Gain value for band with index 0\n// * @param {Number} [freq1] Frequency value for band with index 1\n// * @param {Number} [gain1] Gain value for band with index 1\n// * @param {Number} [freq2] Frequency value for band with index 2\n// * @param {Number} [gain2] Gain value for band with index 2\n// * @param {Number} [freq3] Frequency value for band with index 3\n// * @param {Number} [gain3] Gain value for band with index 3\n// * @param {Number} [freq4] Frequency value for band with index 4\n// * @param {Number} [gain4] Gain value for band with index 4\n// * @param {Number} [freq5] Frequency value for band with index 5\n// * @param {Number} [gain5] Gain value for band with index 5\n// * @param {Number} [freq6] Frequency value for band with index 6\n// * @param {Number} [gain6] Gain value for band with index 6\n// * @param {Number} [freq7] Frequency value for band with index 7\n// * @param {Number} [gain7] Gain value for band with index 7\n// */\np5.EQ.prototype.set = function () {\n if (arguments.length === this.bands.length * 2) {\n for (var i = 0; i < arguments.length; i += 2) {\n this.bands[i / 2].freq(arguments[i]);\n this.bands[i / 2].gain(arguments[i + 1]);\n }\n } else {\n console.error(\n 'Argument mismatch. .set() should be called with ' +\n this.bands.length * 2 +\n ' arguments. (one frequency and gain value pair for each band of the eq)'\n );\n }\n};\n\n/**\n * Add a new band. Creates a p5.Filter and strips away everything but\n * the raw biquad filter. This method returns an abstracted p5.Filter,\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\n * @private\n * @for p5.EQ\n * @method _newBand\n * @param {Number} freq\n * @param {Number} res\n * @return {Object} Abstracted Filter\n */\np5.EQ.prototype._newBand = function (freq, res) {\n return new EQFilter(freq, res);\n};\n\np5.EQ.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n\n if (this.bands) {\n while (this.bands.length > 0) {\n delete this.bands.pop().dispose();\n }\n delete this.bands;\n }\n};\n\nexport default p5.EQ;\n","import Effect from './effect';\n\n/**\n * Panner3D is based on the \n * Web Audio Spatial Panner Node.\n * This panner is a spatial processing node that allows audio to be positioned\n * and oriented in 3D space.\n *\n * The position is relative to an \n * Audio Context Listener, which can be accessed\n * by p5.soundOut.audiocontext.listener\n *\n *\n * @class p5.Panner3D\n * @constructor\n */\n\np5.Panner3D = function () {\n Effect.call(this);\n\n /**\n * \n * Web Audio Spatial Panner Node\n *\n * Properties include
\n * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType)\n * : \"equal power\" or \"HRTF\"
\n * [DistanceModel](https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType)\n * : \"linear\", \"inverse\", or \"exponential\"\n *\n * @property {AudioNode} panner\n *\n */\n this.panner = this.ac.createPanner();\n this.panner.panningModel = 'HRTF';\n this.panner.distanceModel = 'linear';\n this.panner.connect(this.output);\n this.input.connect(this.panner);\n};\n\np5.Panner3D.prototype = Object.create(Effect.prototype);\n\n/**\n * Connect an audio sorce\n *\n * @method process\n * @for p5.Panner3D\n * @param {Object} src Input source\n */\np5.Panner3D.prototype.process = function (src) {\n src.connect(this.input);\n};\n/**\n * Set the X,Y,Z position of the Panner\n * @method set\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\np5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.panner.positionX.value,\n this.panner.positionY.value,\n this.panner.positionZ.value,\n ];\n};\n\n/**\n * Getter and setter methods for position coordinates\n * @method positionX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for position coordinates\n * @method positionY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for position coordinates\n * @method positionZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\np5.Panner3D.prototype.positionX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.positionX.value = xVal;\n this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.panner.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.positionX);\n }\n return this.panner.positionX.value;\n};\np5.Panner3D.prototype.positionY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.positionY.value = yVal;\n this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.panner.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.positionY);\n }\n return this.panner.positionY.value;\n};\np5.Panner3D.prototype.positionZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.positionZ.value = zVal;\n this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.panner.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.positionZ);\n }\n return this.panner.positionZ.value;\n};\n\n/**\n * Set the X,Y,Z position of the Panner\n * @method orient\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\np5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) {\n this.orientX(xVal, time);\n this.orientY(yVal, time);\n this.orientZ(zVal, time);\n return [\n this.panner.orientationX.value,\n this.panner.orientationY.value,\n this.panner.orientationZ.value,\n ];\n};\n\n/**\n * Getter and setter methods for orient coordinates\n * @method orientX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for orient coordinates\n * @method orientY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n/**\n * Getter and setter methods for orient coordinates\n * @method orientZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\np5.Panner3D.prototype.orientX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.orientationX.value = xVal;\n this.panner.orientationX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.orientationX);\n }\n return this.panner.orientationX.value;\n};\np5.Panner3D.prototype.orientY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.orientationY.value = yVal;\n this.panner.orientationY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.orientationY);\n }\n return this.panner.orientationY.value;\n};\np5.Panner3D.prototype.orientZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.orientationZ.value = zVal;\n this.panner.orientationZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.orientationZ);\n }\n return this.panner.orientationZ.value;\n};\n\n/**\n * Set the rolloff factor and max distance\n * @method setFalloff\n * @for p5.Panner3D\n * @param {Number} [maxDistance]\n * @param {Number} [rolloffFactor]\n */\np5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) {\n this.maxDist(maxDistance);\n this.rolloff(rolloffFactor);\n};\n/**\n * Maxium distance between the source and the listener\n * @method maxDist\n * @for p5.Panner3D\n * @param {Number} maxDistance\n * @return {Number} updated value\n */\np5.Panner3D.prototype.maxDist = function (maxDistance) {\n if (typeof maxDistance === 'number') {\n this.panner.maxDistance = maxDistance;\n }\n return this.panner.maxDistance;\n};\n\n/**\n * How quickly the volume is reduced as the source moves away from the listener\n * @method rollof\n * @for p5.Panner3D\n * @param {Number} rolloffFactor\n * @return {Number} updated value\n */\np5.Panner3D.prototype.rolloff = function (rolloffFactor) {\n if (typeof rolloffFactor === 'number') {\n this.panner.rolloffFactor = rolloffFactor;\n }\n return this.panner.rolloffFactor;\n};\n\np5.Panner3D.dispose = function () {\n Effect.prototype.dispose.apply(this);\n if (this.panner) {\n this.panner.disconnect();\n delete this.panner;\n }\n};\n\nexport default p5.Panner3D;\n","import p5sound from './master';\n\n// /**\n// * listener is a class that can construct both a Spatial Panner\n// * and a Spatial Listener. The panner is based on the\n// * Web Audio Spatial Panner Node\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\n// * This panner is a spatial processing node that allows audio to be positioned\n// * and oriented in 3D space.\n// *\n// * The Listener modifies the properties of the Audio Context Listener.\n// * Both objects types use the same methods. The default is a spatial panner.\n// *\n// * p5.Panner3D - Constructs a Spatial Panner
\n// * p5.Listener3D - Constructs a Spatial Listener
\n// *\n// * @class listener\n// * @constructor\n// * @return {Object} p5.Listener3D Object\n// *\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\n// */\n\np5.Listener3D = function (type) {\n this.ac = p5sound.audiocontext;\n this.listener = this.ac.listener;\n};\n\n// /**\n// * Connect an audio sorce\n// * @param {Object} src Input source\n// */\np5.Listener3D.prototype.process = function (src) {\n src.connect(this.input);\n};\n// /**\n// * Set the X,Y,Z position of the Panner\n// * @param {[Number]} xVal\n// * @param {[Number]} yVal\n// * @param {[Number]} zVal\n// * @param {[Number]} time\n// * @return {[Array]} [Updated x, y, z values as an array]\n// */\np5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.listener.positionX.value,\n this.listener.positionY.value,\n this.listener.positionZ.value,\n ];\n};\n\n// /**\n// * Getter and setter methods for position coordinates\n// * @return {Number} [updated coordinate value]\n// */\np5.Listener3D.prototype.positionX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.positionX.value = xVal;\n this.listener.positionX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.positionX);\n }\n return this.listener.positionX.value;\n};\np5.Listener3D.prototype.positionY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.positionY.value = yVal;\n this.listener.positionY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.positionY);\n }\n return this.listener.positionY.value;\n};\np5.Listener3D.prototype.positionZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.positionZ.value = zVal;\n this.listener.positionZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.positionZ);\n }\n return this.listener.positionZ.value;\n};\n\n// cannot define method when class definition is commented\n// /**\n// * Overrides the listener orient() method because Listener has slightly\n// * different params. In human terms, Forward vectors are the direction the\n// * nose is pointing. Up vectors are the direction of the top of the head.\n// *\n// * @method orient\n// * @param {Number} xValF Forward vector X direction\n// * @param {Number} yValF Forward vector Y direction\n// * @param {Number} zValF Forward vector Z direction\n// * @param {Number} xValU Up vector X direction\n// * @param {Number} yValU Up vector Y direction\n// * @param {Number} zValU Up vector Z direction\n// * @param {Number} time\n// * @return {Array} All orienation params\n// */\np5.Listener3D.prototype.orient = function (\n xValF,\n yValF,\n zValF,\n xValU,\n yValU,\n zValU,\n time\n) {\n if (arguments.length === 3 || arguments.length === 4) {\n time = arguments[3];\n this.orientForward(xValF, yValF, zValF, time);\n } else if (arguments.length === 6 || arguments === 7) {\n this.orientForward(xValF, yValF, zValF);\n this.orientUp(xValU, yValU, zValU, time);\n }\n\n return [\n this.listener.forwardX.value,\n this.listener.forwardY.value,\n this.listener.forwardZ.value,\n this.listener.upX.value,\n this.listener.upY.value,\n this.listener.upZ.value,\n ];\n};\n\np5.Listener3D.prototype.orientForward = function (xValF, yValF, zValF, time) {\n this.forwardX(xValF, time);\n this.forwardY(yValF, time);\n this.forwardZ(zValF, time);\n\n return [\n this.listener.forwardX,\n this.listener.forwardY,\n this.listener.forwardZ,\n ];\n};\n\np5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) {\n this.upX(xValU, time);\n this.upY(yValU, time);\n this.upZ(zValU, time);\n\n return [this.listener.upX, this.listener.upY, this.listener.upZ];\n};\n// /**\n// * Getter and setter methods for orient coordinates\n// * @return {Number} [updated coordinate value]\n// */\np5.Listener3D.prototype.forwardX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.forwardX.value = xVal;\n this.listener.forwardX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.forwardX);\n }\n return this.listener.forwardX.value;\n};\np5.Listener3D.prototype.forwardY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.forwardY.value = yVal;\n this.listener.forwardY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.forwardY);\n }\n return this.listener.forwardY.value;\n};\np5.Listener3D.prototype.forwardZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.forwardZ.value = zVal;\n this.listener.forwardZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.forwardZ);\n }\n return this.listener.forwardZ.value;\n};\np5.Listener3D.prototype.upX = function (xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.upX.value = xVal;\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.upX);\n }\n return this.listener.upX.value;\n};\np5.Listener3D.prototype.upY = function (yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.upY.value = yVal;\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.upY);\n }\n return this.listener.upY.value;\n};\np5.Listener3D.prototype.upZ = function (zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.upZ.value = zVal;\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.upZ);\n }\n return this.listener.upZ.value;\n};\n\nexport default p5.Listener3D;\n","import Filter from './filter';\nimport Effect from './effect';\n\n/**\n * Delay is an echo effect. It processes an existing sound source,\n * and outputs a delayed version of that sound. The p5.Delay can\n * produce different effects depending on the delayTime, feedback,\n * filter, and type. In the example below, a feedback of 0.5 (the\n * default value) will produce a looping delay that decreases in\n * volume by 50% each repeat. A filter will cut out the high\n * frequencies so that the delay does not sound as piercing as the\n * original source.\n *\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n * @class p5.Delay\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * osc = new p5.Oscillator('square');\n * osc.amp(0.5);\n * delay = new p5.Delay();\n *\n * // delay.process() accepts 4 parameters:\n * // source, delayTime (in seconds), feedback, filter frequency\n * delay.process(osc, 0.12, .7, 2300);\n *\n * cnv.mousePressed(oscStart);\n * }\n *\n * function oscStart() {\n * osc.start();\n * }\n *\n * function mouseReleased() {\n * osc.stop();\n * }\n *
\n */\np5.Delay = function () {\n Effect.call(this);\n\n this._split = this.ac.createChannelSplitter(2);\n this._merge = this.ac.createChannelMerger(2);\n\n this._leftGain = this.ac.createGain();\n this._rightGain = this.ac.createGain();\n\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n *\n * @for p5.Delay\n * @property {DelayNode} leftDelay\n */\n this.leftDelay = this.ac.createDelay();\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n * @for p5.Delay\n * @property {DelayNode} rightDelay\n */\n this.rightDelay = this.ac.createDelay();\n\n this._leftFilter = new Filter();\n this._rightFilter = new Filter();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\n this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n\n // graph routing\n this.input.connect(this._split);\n this.leftDelay.connect(this._leftGain);\n this.rightDelay.connect(this._rightGain);\n this._leftGain.connect(this._leftFilter.input);\n this._rightGain.connect(this._rightFilter.input);\n this._merge.connect(this.wet);\n\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n\n // default routing\n this.setType(0);\n\n this._maxDelay = this.leftDelay.delayTime.maxValue;\n\n // set initial feedback to 0.5\n this.feedback(0.5);\n};\n\np5.Delay.prototype = Object.create(Effect.prototype);\n/**\n * Add delay to an audio signal according to a set\n * of delay parameters.\n *\n * @method process\n * @for p5.Delay\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\n * Some browsers limit delayTime to\n * 1 second.\n * @param {Number} [feedback] sends the delay back through itself\n * in a loop that decreases in volume\n * each time.\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\n * below the lowPass will be part of the\n * delay.\n */\np5.Delay.prototype.process = function (src, _delayTime, _feedback, _filter) {\n var feedback = _feedback || 0;\n var delayTime = _delayTime || 0;\n if (feedback >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n }\n if (delayTime >= this._maxDelay) {\n throw new Error(\n 'Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.'\n );\n }\n\n src.connect(this.input);\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this._leftGain.gain.value = feedback;\n this._rightGain.gain.value = feedback;\n\n if (_filter) {\n this._leftFilter.freq(_filter);\n this._rightFilter.freq(_filter);\n }\n};\n\n/**\n * Set the delay (echo) time, in seconds. Usually this value will be\n * a floating point number between 0.0 and 1.0.\n *\n * @method delayTime\n * @for p5.Delay\n * @param {Number} delayTime Time (in seconds) of the delay\n */\np5.Delay.prototype.delayTime = function (t) {\n // if t is an audio node...\n if (typeof t !== 'number') {\n t.connect(this.leftDelay.delayTime);\n t.connect(this.rightDelay.delayTime);\n } else {\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n }\n};\n\n/**\n * Feedback occurs when Delay sends its signal back through its input\n * in a loop. The feedback amount determines how much signal to send each\n * time through the loop. A feedback greater than 1.0 is not desirable because\n * it will increase the overall output each time through the loop,\n * creating an infinite feedback loop. The default value is 0.5\n *\n * @method feedback\n * @for p5.Delay\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\n * Oscillator that can be used to\n * modulate this param\n * @returns {Number} Feedback value\n *\n */\np5.Delay.prototype.feedback = function (f) {\n // if f is an audio node...\n if (f && typeof f !== 'number') {\n f.connect(this._leftGain.gain);\n f.connect(this._rightGain.gain);\n } else if (f >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n } else if (typeof f === 'number') {\n this._leftGain.gain.value = f;\n this._rightGain.gain.value = f;\n }\n\n // return value of feedback\n return this._leftGain.gain.value;\n};\n\n/**\n * Set a lowpass filter frequency for the delay. A lowpass filter\n * will cut off any frequencies higher than the filter frequency.\n *\n * @method filter\n * @for p5.Delay\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\n * frequencies higher than the filter frequency.\n * @param {Number|Object} res Resonance of the filter frequency\n * cutoff, or an object (i.e. a p5.Oscillator)\n * that can be used to modulate this parameter.\n * High numbers (i.e. 15) will produce a resonance,\n * low numbers (i.e. .2) will produce a slope.\n */\np5.Delay.prototype.filter = function (freq, q) {\n this._leftFilter.set(freq, q);\n this._rightFilter.set(freq, q);\n};\n\n/**\n * Choose a preset type of delay. 'pingPong' bounces the signal\n * from the left to the right channel to produce a stereo effect.\n * Any other parameter will revert to the default delay setting.\n *\n * @method setType\n * @for p5.Delay\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\n */\np5.Delay.prototype.setType = function (t) {\n if (t === 1) {\n t = 'pingPong';\n }\n this._split.disconnect();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n this._split.connect(this.leftDelay, 0);\n this._split.connect(this.rightDelay, 1);\n switch (t) {\n case 'pingPong':\n this._rightFilter.setType(this._leftFilter.biquad.type);\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.rightDelay);\n this._rightFilter.output.connect(this.leftDelay);\n break;\n default:\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.leftDelay);\n this._rightFilter.output.connect(this.rightDelay);\n }\n};\n\n// DocBlocks for methods inherited from p5.Effect\n/**\n * Set the output level of the delay effect.\n *\n * @method amp\n * @for p5.Delay\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n/**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Delay\n * @param {Object} unit\n */\n/**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Delay\n */\n\np5.Delay.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n\n this._split.disconnect();\n this._leftFilter.dispose();\n this._rightFilter.dispose();\n this._merge.disconnect();\n this._leftGain.disconnect();\n this._rightGain.disconnect();\n this.leftDelay.disconnect();\n this.rightDelay.disconnect();\n\n this._split = undefined;\n this._leftFilter = undefined;\n this._rightFilter = undefined;\n this._merge = undefined;\n this._leftGain = undefined;\n this._rightGain = undefined;\n this.leftDelay = undefined;\n this.rightDelay = undefined;\n};\nexport default p5.Delay;\n","import CustomError from './errorHandler';\nimport Effect from './effect';\n\n/**\n * Reverb adds depth to a sound through a large number of decaying\n * echoes. It creates the perception that sound is occurring in a\n * physical space. The p5.Reverb has paramters for Time (how long does the\n * reverb last) and decayRate (how much the sound decays with each echo)\n * that can be set with the .set() or .process() methods. The p5.Convolver\n * extends p5.Reverb allowing you to recreate the sound of actual physical\n * spaces through convolution.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Reverb\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let soundFile, reverb;\n * function preload() {\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * reverb = new p5.Reverb();\n * soundFile.disconnect(); // so we'll only hear reverb...\n *\n * // connect soundFile to reverb, process w/\n * // 3 second reverbTime, decayRate of 2%\n * reverb.process(soundFile, 3, 2);\n * }\n *\n * function draw() {\n * let dryWet = constrain(map(mouseX, 0, width, 0, 1), 0, 1);\n * // 1 = all reverb, 0 = no reverb\n * reverb.drywet(dryWet);\n *\n * background(220);\n * text('tap to play', 10, 20);\n * text('dry/wet: ' + round(dryWet * 100) + '%', 10, height - 20);\n * }\n *\n * function playSound() {\n * soundFile.play();\n * }\n *
\n */\n\np5.Reverb = function () {\n Effect.call(this);\n\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n // default params\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n};\n\np5.Reverb.prototype = Object.create(Effect.prototype);\n\np5.Reverb.prototype._initConvolverNode = function () {\n this.convolverNode = this.ac.createConvolver();\n this.input.connect(this.convolverNode);\n this.convolverNode.connect(this.wet);\n};\n\np5.Reverb.prototype._teardownConvolverNode = function () {\n if (this.convolverNode) {\n this.convolverNode.disconnect();\n delete this.convolverNode;\n }\n};\n\np5.Reverb.prototype._setBuffer = function (audioBuffer) {\n this._teardownConvolverNode();\n this._initConvolverNode();\n this.convolverNode.buffer = audioBuffer;\n};\n/**\n * Connect a source to the reverb, and assign reverb parameters.\n *\n * @method process\n * @for p5.Reverb\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\np5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) {\n src.connect(this.input);\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n};\n\n/**\n * Set the reverb settings. Similar to .process(), but without\n * assigning a new input.\n *\n * @method set\n * @for p5.Reverb\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\np5.Reverb.prototype.set = function (seconds, decayRate, reverse) {\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n};\n\n// DocBlocks for methods inherited from p5.Effect\n/**\n * Set the output level of the reverb effect.\n *\n * @method amp\n * @for p5.Reverb\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n/**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Reverb\n * @param {Object} unit\n */\n/**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Reverb\n */\n\n/**\n * Inspired by Simple Reverb by Jordan Santell\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\n *\n * Utility function for building an impulse response\n * based on the module parameters.\n *\n * @private\n */\np5.Reverb.prototype._buildImpulse = function () {\n var rate = this.ac.sampleRate;\n var length = rate * this._seconds;\n var decay = this._decay;\n var impulse = this.ac.createBuffer(2, length, rate);\n var impulseL = impulse.getChannelData(0);\n var impulseR = impulse.getChannelData(1);\n var n, i;\n for (i = 0; i < length; i++) {\n n = this._reverse ? length - i : i;\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n }\n this._setBuffer(impulse);\n};\n\np5.Reverb.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n this._teardownConvolverNode();\n};\n\n// =======================================================================\n// *** p5.Convolver ***\n// =======================================================================\n\n/**\n *

p5.Convolver extends p5.Reverb. It can emulate the sound of real\n * physical spaces through a process called \n * convolution.

\n *\n *

Convolution multiplies any audio input by an \"impulse response\"\n * to simulate the dispersion of sound over time. The impulse response is\n * generated from an audio file that you provide. One way to\n * generate an impulse response is to pop a balloon in a reverberant space\n * and record the echo. Convolution can also be used to experiment with\n * sound.

\n *\n *

Use the method createConvolution(path) to instantiate a\n * p5.Convolver with a path to your impulse response audio file.

\n *\n * @class p5.Convolver\n * @extends p5.Effect\n * @constructor\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call when loading succeeds\n * @param {Function} [errorCallback] function to call if loading fails.\n * This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\np5.Convolver = function (path, callback, errorCallback) {\n p5.Reverb.call(this);\n\n /**\n * Internally, the p5.Convolver uses the a\n * \n * Web Audio Convolver Node.\n *\n * @property {ConvolverNode} convolverNode\n */\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n if (path) {\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n } else {\n // parameters\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n }\n};\n\np5.Convolver.prototype = Object.create(p5.Reverb.prototype);\n\np5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\n\n/**\n * Create a p5.Convolver. Accepts a path to a soundfile\n * that will be used to generate an impulse response.\n *\n * @method createConvolver\n * @for p5\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call if loading is successful.\n * The object will be passed in as the argument\n * to the callback function.\n * @param {Function} [errorCallback] function to call if loading is not successful.\n * A custom error will be passed in as the argument\n * to the callback function.\n * @return {p5.Convolver}\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\np5.prototype.createConvolver = function (path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n var self = this;\n var cReverb = new p5.Convolver(\n path,\n function (buffer) {\n if (typeof callback === 'function') {\n callback(buffer);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n errorCallback\n );\n cReverb.impulses = [];\n return cReverb;\n};\n\n/**\n * Private method to load a buffer as an Impulse Response,\n * assign it to the convolverNode, and add to the Array of .impulses.\n *\n * @param {String} path\n * @param {Function} callback\n * @param {Function} errorCallback\n * @private\n */\np5.Convolver.prototype._loadBuffer = function (_path, callback, errorCallback) {\n var path = p5.prototype._checkFileFormats(_path);\n var self = this;\n var errorTrace = new Error().stack;\n var ac = p5.prototype.getAudioContext();\n\n var request = new XMLHttpRequest();\n request.open('GET', path, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on success loading file:\n ac.decodeAudioData(\n request.response,\n function (buff) {\n var buffer = {};\n var chunks = path.split('/');\n buffer.name = chunks[chunks.length - 1];\n buffer.audioBuffer = buff;\n self.impulses.push(buffer);\n self._setBuffer(buffer.audioBuffer);\n if (callback) {\n callback(buffer);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(msg + '\\n The error stack trace includes: \\n' + err.stack);\n }\n };\n request.send();\n};\n\np5.Convolver.prototype.set = null;\n\n/**\n * Connect a source to the convolver.\n *\n * @method process\n * @for p5.Convolver\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *\n *
\n */\np5.Convolver.prototype.process = function (src) {\n src.connect(this.input);\n};\n\n/**\n * If you load multiple impulse files using the .addImpulse method,\n * they will be stored as Objects in this Array. Toggle between them\n * with the toggleImpulse(id) method.\n *\n * @property {Array} impulses\n * @for p5.Convolver\n */\np5.Convolver.prototype.impulses = [];\n\n/**\n * Load and assign a new Impulse Response to the p5.Convolver.\n * The impulse is added to the .impulses array. Previous\n * impulses can be accessed with the .toggleImpulse(id)\n * method.\n *\n * @method addImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\np5.Convolver.prototype.addImpulse = function (path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this._loadBuffer(path, callback, errorCallback);\n};\n\n/**\n * Similar to .addImpulse, except that the .impulses\n * Array is reset to save memory. A new .impulses\n * array is created with this impulse as the only item.\n *\n * @method resetImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\np5.Convolver.prototype.resetImpulse = function (path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n};\n\n/**\n * If you have used .addImpulse() to add multiple impulses\n * to a p5.Convolver, then you can use this method to toggle between\n * the items in the .impulses Array. Accepts a parameter\n * to identify which impulse you wish to use, identified either by its\n * original filename (String) or by its position in the .impulses\n * Array (Number).
\n * You can access the objects in the .impulses Array directly. Each\n * Object has two attributes: an .audioBuffer (type:\n * Web Audio \n * AudioBuffer) and a .name, a String that corresponds\n * with the original filename.\n *\n * @method toggleImpulse\n * @for p5.Convolver\n * @param {String|Number} id Identify the impulse by its original filename\n * (String), or by its position in the\n * .impulses Array (Number).\n */\np5.Convolver.prototype.toggleImpulse = function (id) {\n if (typeof id === 'number' && id < this.impulses.length) {\n this._setBuffer(this.impulses[id].audioBuffer);\n }\n if (typeof id === 'string') {\n for (var i = 0; i < this.impulses.length; i++) {\n if (this.impulses[i].name === id) {\n this._setBuffer(this.impulses[i].audioBuffer);\n break;\n }\n }\n }\n};\n\np5.Convolver.prototype.dispose = function () {\n p5.Reverb.prototype.dispose.apply(this);\n\n // remove all the Impulse Response buffers\n for (var i in this.impulses) {\n if (this.impulses[i]) {\n this.impulses[i] = null;\n }\n }\n};\n","import p5sound from './master';\n// requires the Tone.js library's Clock (MIT license, Yotam Mann)\n// https://github.com/TONEnoTONE/Tone.js/\nimport Clock from 'Tone/core/Clock';\n\np5.Metro = function () {\n this.clock = new Clock({\n callback: this.ontick.bind(this),\n });\n this.syncedParts = [];\n this.bpm = 120; // gets overridden by p5.Part\n this._init();\n\n this.prevTick = 0;\n this.tatumTime = 0;\n\n this.tickCallback = function () {};\n};\n\np5.Metro.prototype.ontick = function (tickTime) {\n var elapsedTime = tickTime - this.prevTick;\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\n if (elapsedTime - this.tatumTime <= -0.02) {\n return;\n } else {\n // console.log('ok', this.syncedParts[0].phrases[0].name);\n this.prevTick = tickTime;\n\n // for all of the active things on the metro:\n var self = this;\n this.syncedParts.forEach(function (thisPart) {\n if (!thisPart.isPlaying) return;\n thisPart.incrementStep(secondsFromNow);\n // each synced source keeps track of its own beat number\n thisPart.phrases.forEach(function (thisPhrase) {\n var phraseArray = thisPhrase.sequence;\n var bNum = self.metroTicks % phraseArray.length;\n if (\n phraseArray[bNum] !== 0 &&\n (self.metroTicks < phraseArray.length || !thisPhrase.looping)\n ) {\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\n }\n });\n });\n this.metroTicks += 1;\n this.tickCallback(secondsFromNow);\n }\n};\n\np5.Metro.prototype.setBPM = function (bpm, rampTime = 0) {\n var beatTime = 60 / (bpm * this.tatums);\n var now = p5sound.audiocontext.currentTime;\n this.tatumTime = beatTime;\n\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\n this.bpm = bpm;\n};\n\np5.Metro.prototype.getBPM = function () {\n return (this.clock.getRate() / this.tatums) * 60;\n};\n\np5.Metro.prototype._init = function () {\n this.metroTicks = 0;\n // this.setBPM(120);\n};\n\n// clear existing synced parts, add only this one\np5.Metro.prototype.resetSync = function (part) {\n this.syncedParts = [part];\n};\n\n// push a new synced part to the array\np5.Metro.prototype.pushSync = function (part) {\n this.syncedParts.push(part);\n};\n\np5.Metro.prototype.start = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.start(now + t);\n this.setBPM(this.bpm);\n};\n\np5.Metro.prototype.stop = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.stop(now + t);\n};\n\np5.Metro.prototype.beatLength = function (tatums) {\n this.tatums = 1 / tatums / 4; // lowest possible division of a beat\n};\n","import p5sound from './master';\n\nvar BPM = 120;\n\n/**\n * Set the global tempo, in beats per minute, for all\n * p5.Parts. This method will impact all active p5.Parts.\n *\n * @method setBPM\n * @for p5\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\np5.prototype.setBPM = function (bpm, rampTime) {\n BPM = bpm;\n for (var i in p5sound.parts) {\n if (p5sound.parts[i]) {\n p5sound.parts[i].setBPM(bpm, rampTime);\n }\n }\n};\n\n/**\n *

A phrase is a pattern of musical events over time, i.e.\n * a series of notes and rests.

\n *\n *

Phrases must be added to a p5.Part for playback, and\n * each part can play multiple phrases at the same time.\n * For example, one Phrase might be a kick drum, another\n * could be a snare, and another could be the bassline.

\n *\n *

The first parameter is a name so that the phrase can be\n * modified or deleted later. The callback is a a function that\n * this phrase will call at every step—for example it might be\n * called playNote(value){}. The array determines\n * which value is passed into the callback at each step of the\n * phrase. It can be numbers, an object with multiple numbers,\n * or a zero (0) indicates a rest so the callback won't be called).

\n *\n * @class p5.Phrase\n * @constructor\n * @param {String} name Name so that you can access the Phrase.\n * @param {Function} callback The name of a function that this phrase\n * will call. Typically it will play a sound,\n * and accept two parameters: a time at which\n * to play the sound (in seconds from now),\n * and a value from the sequence array. The\n * time should be passed into the play() or\n * start() method to ensure precision.\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n * @example\n *
\n * let mySound, myPhrase, myPart;\n * let pattern = [1,0,0,2,0,2,0,0];\n *\n * function preload() {\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * text('tap to play', width/2, height/2);\n * textAlign(CENTER, CENTER);\n *\n * myPhrase = new p5.Phrase('bbox', onEachStep, pattern);\n * myPart = new p5.Part();\n * myPart.addPhrase(myPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function onEachStep(time, playbackRate) {\n * mySound.rate(playbackRate);\n * mySound.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n * myPart.start();\n * }\n *
\n */\np5.Phrase = function (name, callback, sequence) {\n this.phraseStep = 0;\n this.name = name;\n this.callback = callback;\n /**\n * Array of values to pass into the callback\n * at each step of the phrase. Depending on the callback\n * function's requirements, these values may be numbers,\n * strings, or an object with multiple parameters.\n * Zero (0) indicates a rest.\n *\n * @property {Array} sequence\n */\n this.sequence = sequence;\n};\n\n/**\n *

A p5.Part plays back one or more p5.Phrases. Instantiate a part\n * with steps and tatums. By default, each step represents a 1/16th note.

\n *\n *

See p5.Phrase for more about musical timing.

\n *\n * @class p5.Part\n * @constructor\n * @param {Number} [steps] Steps in the part\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)\n * @example\n *
\n * let box, drum, myPart;\n * let boxPat = [1,0,0,2,0,2,0,0];\n * let drumPat = [0,1,1,0,2,0,1,0];\n *\n * function preload() {\n * box = loadSound('assets/beatbox.mp3');\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * textAlign(CENTER, CENTER);\n * text('tap to play', width/2, height/2);\n *\n * let boxPhrase = new p5.Phrase('box', playBox, boxPat);\n * let drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\n * myPart = new p5.Part();\n * myPart.addPhrase(boxPhrase);\n * myPart.addPhrase(drumPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function playBox(time, playbackRate) {\n * box.rate(playbackRate);\n * box.play(time);\n * }\n *\n * function playDrum(time, playbackRate) {\n * drum.rate(playbackRate);\n * drum.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n *\n * myPart.start();\n * }\n *
\n */\np5.Part = function (steps, bLength) {\n this.length = steps || 0; // how many beats\n this.partStep = 0;\n this.phrases = [];\n this.isPlaying = false;\n this.noLoop();\n this.tatums = bLength || 0.0625; // defaults to quarter note\n\n this.metro = new p5.Metro();\n this.metro._init();\n this.metro.beatLength(this.tatums);\n this.metro.setBPM(BPM);\n p5sound.parts.push(this);\n this.callback = function () {};\n};\n\n/**\n * Set the tempo of this part, in Beats Per Minute.\n *\n * @method setBPM\n * @for p5.Part\n * @param {Number} BPM Beats Per Minute\n * @param {Number} [rampTime] Seconds from now\n */\np5.Part.prototype.setBPM = function (tempo, rampTime) {\n this.metro.setBPM(tempo, rampTime);\n};\n\n/**\n * Returns the tempo, in Beats Per Minute, of this part.\n *\n * @method getBPM\n * @for p5.Part\n * @return {Number}\n */\np5.Part.prototype.getBPM = function () {\n return this.metro.getBPM();\n};\n\n/**\n * Start playback of this part. It will play\n * through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method start\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\np5.Part.prototype.start = function (time) {\n if (!this.isPlaying) {\n this.isPlaying = true;\n this.metro.resetSync(this);\n var t = time || 0;\n this.metro.start(t);\n }\n};\n\n/**\n * Loop playback of this part. It will begin\n * looping through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method loop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\np5.Part.prototype.loop = function (time) {\n this.looping = true;\n // rest onended function\n this.onended = function () {\n this.partStep = 0;\n };\n var t = time || 0;\n this.start(t);\n};\n\n/**\n * Tell the part to stop looping.\n *\n * @method noLoop\n * @for p5.Part\n */\np5.Part.prototype.noLoop = function () {\n this.looping = false;\n // rest onended function\n this.onended = function () {\n this.stop();\n };\n};\n\n/**\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\n *\n * @method stop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\np5.Part.prototype.stop = function (time) {\n this.partStep = 0;\n this.pause(time);\n};\n\n/**\n * Pause the part. Playback will resume\n * from the current step.\n *\n * @method pause\n * @for p5.Part\n * @param {Number} time seconds from now\n */\np5.Part.prototype.pause = function (time) {\n this.isPlaying = false;\n var t = time || 0;\n this.metro.stop(t);\n};\n\n/**\n * Add a p5.Phrase to this Part.\n *\n * @method addPhrase\n * @for p5.Part\n * @param {p5.Phrase} phrase reference to a p5.Phrase\n */\np5.Part.prototype.addPhrase = function (name, callback, array) {\n var p;\n if (arguments.length === 3) {\n p = new p5.Phrase(name, callback, array);\n } else if (arguments[0] instanceof p5.Phrase) {\n p = arguments[0];\n } else {\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\n }\n this.phrases.push(p);\n // reset the length if phrase is longer than part's existing length\n if (p.sequence.length > this.length) {\n this.length = p.sequence.length;\n }\n};\n\n/**\n * Remove a phrase from this part, based on the name it was\n * given when it was created.\n *\n * @method removePhrase\n * @for p5.Part\n * @param {String} phraseName\n */\np5.Part.prototype.removePhrase = function (name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases.splice(i, 1);\n }\n }\n};\n\n/**\n * Get a phrase from this part, based on the name it was\n * given when it was created. Now you can modify its array.\n *\n * @method getPhrase\n * @for p5.Part\n * @param {String} phraseName\n */\np5.Part.prototype.getPhrase = function (name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n return this.phrases[i];\n }\n }\n};\n\n/**\n * Find all sequences with the specified name, and replace their patterns with the specified array.\n *\n * @method replaceSequence\n * @for p5.Part\n * @param {String} phraseName\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n */\np5.Part.prototype.replaceSequence = function (name, array) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases[i].sequence = array;\n }\n }\n};\n\np5.Part.prototype.incrementStep = function (time) {\n if (this.partStep < this.length - 1) {\n this.callback(time);\n this.partStep += 1;\n } else {\n if (!this.looping && this.partStep === this.length - 1) {\n // this.callback(time);\n this.onended();\n }\n }\n};\n\n/**\n * Set the function that will be called at every step. This will clear the previous function.\n *\n * @method onStep\n * @for p5.Part\n * @param {Function} callback The name of the callback\n * you want to fire\n * on every beat/tatum.\n */\np5.Part.prototype.onStep = function (callback) {\n this.callback = callback;\n};\n\n// ===============\n// p5.Score\n// ===============\n\n/**\n * A Score consists of a series of Parts. The parts will\n * be played back in order. For example, you could have an\n * A part, a B part, and a C part, and play them back in this order\n * new p5.Score(a, a, b, a, c)\n *\n * @class p5.Score\n * @constructor\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\n */\np5.Score = function () {\n // for all of the arguments\n this.parts = [];\n this.currentPart = 0;\n\n var thisScore = this;\n for (var i in arguments) {\n if (arguments[i] && this.parts[i]) {\n this.parts[i] = arguments[i];\n this.parts[i].nextPart = this.parts[i + 1];\n this.parts[i].onended = function () {\n thisScore.resetPart(i);\n playNextPart(thisScore);\n };\n }\n }\n this.looping = false;\n};\n\np5.Score.prototype.onended = function () {\n if (this.looping) {\n // this.resetParts();\n this.parts[0].start();\n } else {\n this.parts[this.parts.length - 1].onended = function () {\n this.stop();\n this.resetParts();\n };\n }\n this.currentPart = 0;\n};\n\n/**\n * Start playback of the score.\n *\n * @method start\n * @for p5.Score\n */\np5.Score.prototype.start = function () {\n this.parts[this.currentPart].start();\n this.scoreStep = 0;\n};\n\n/**\n * Stop playback of the score.\n *\n * @method stop\n * @for p5.Score\n */\np5.Score.prototype.stop = function () {\n this.parts[this.currentPart].stop();\n this.currentPart = 0;\n this.scoreStep = 0;\n};\n\n/**\n * Pause playback of the score.\n *\n * @method pause\n * @for p5.Score\n */\np5.Score.prototype.pause = function () {\n this.parts[this.currentPart].stop();\n};\n\n/**\n * Loop playback of the score.\n *\n * @method loop\n * @for p5.Score\n */\np5.Score.prototype.loop = function () {\n this.looping = true;\n this.start();\n};\n\n/**\n * Stop looping playback of the score. If it\n * is currently playing, this will go into effect\n * after the current round of playback completes.\n *\n * @method noLoop\n * @for p5.Score\n */\np5.Score.prototype.noLoop = function () {\n this.looping = false;\n};\n\np5.Score.prototype.resetParts = function () {\n var self = this;\n this.parts.forEach(function (part) {\n self.resetParts[part];\n });\n};\n\np5.Score.prototype.resetPart = function (i) {\n this.parts[i].stop();\n this.parts[i].partStep = 0;\n for (var p in this.parts[i].phrases) {\n if (this.parts[i]) {\n this.parts[i].phrases[p].phraseStep = 0;\n }\n }\n};\n\n/**\n * Set the tempo for all parts in the score\n *\n * @method setBPM\n * @for p5.Score\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\np5.Score.prototype.setBPM = function (bpm, rampTime) {\n for (var i in this.parts) {\n if (this.parts[i]) {\n this.parts[i].setBPM(bpm, rampTime);\n }\n }\n};\n\nfunction playNextPart(aScore) {\n aScore.currentPart++;\n if (aScore.currentPart >= aScore.parts.length) {\n aScore.scoreStep = 0;\n aScore.onended();\n } else {\n aScore.scoreStep = 0;\n aScore.parts[aScore.currentPart - 1].stop();\n aScore.parts[aScore.currentPart].start();\n }\n}\n","import p5sound from './master';\nimport Clock from 'Tone/core/Clock';\n\n/**\n * SoundLoop\n *\n * @class p5.SoundLoop\n * @constructor\n *\n * @param {Function} callback this function will be called on each iteration of theloop\n * @param {Number|String} [interval] amount of time (if a number) or beats (if a string, following Tone.Time convention) for each iteration of the loop. Defaults to 1 second.\n *\n * @example\n *
\n * let synth, soundLoop;\n * let notePattern = [60, 62, 64, 67, 69, 72];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * colorMode(HSB);\n * background(0, 0, 86);\n * text('tap to start/stop', 10, 20);\n *\n * //the looper's callback is passed the timeFromNow\n * //this value should be used as a reference point from\n * //which to schedule sounds\n * let intervalInSeconds = 0.2;\n * soundLoop = new p5.SoundLoop(onSoundLoop, intervalInSeconds);\n *\n * synth = new p5.MonoSynth();\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * if (soundLoop.isPlaying) {\n * soundLoop.stop();\n * } else {\n * // start the loop\n * soundLoop.start();\n * }\n * }\n *\n * function onSoundLoop(timeFromNow) {\n * let noteIndex = (soundLoop.iterations - 1) % notePattern.length;\n * let note = midiToFreq(notePattern[noteIndex]);\n * synth.play(note, 0.5, timeFromNow);\n * background(noteIndex * 360 / notePattern.length, 50, 100);\n * }\n *
\n */\np5.SoundLoop = function (callback, interval) {\n this.callback = callback;\n /**\n * musicalTimeMode uses Tone.Time convention\n * true if string, false if number\n * @property {Boolean} musicalTimeMode\n */\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\n\n this._interval = interval || 1;\n\n /**\n * musicalTimeMode variables\n * modify these only when the interval is specified in musicalTime format as a string\n */\n this._timeSignature = 4;\n this._bpm = 60;\n\n this.isPlaying = false;\n\n /**\n * Set a limit to the number of loops to play. defaults to Infinity\n * @property {Number} maxIterations\n */\n this.maxIterations = Infinity;\n var self = this;\n\n this.clock = new Clock({\n callback: function (time) {\n var timeFromNow = time - p5sound.audiocontext.currentTime;\n /**\n * Do not initiate the callback if timeFromNow is < 0\n * This ususually occurs for a few milliseconds when the page\n * is not fully loaded\n *\n * The callback should only be called until maxIterations is reached\n */\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\n self.callback(timeFromNow);\n }\n },\n frequency: this._calcFreq(),\n });\n};\n\n/**\n * Start the loop\n * @method start\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a starting time\n */\np5.SoundLoop.prototype.start = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (!this.isPlaying) {\n this.clock.start(now + t);\n this.isPlaying = true;\n }\n};\n\n/**\n * Stop the loop\n * @method stop\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a stopping time\n */\np5.SoundLoop.prototype.stop = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.stop(now + t);\n this.isPlaying = false;\n }\n};\n/**\n * Pause the loop\n * @method pause\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a pausing time\n */\np5.SoundLoop.prototype.pause = function (timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.pause(now + t);\n this.isPlaying = false;\n }\n};\n\n/**\n * Synchronize loops. Use this method to start two or more loops in synchronization\n * or to start a loop in synchronization with a loop that is already playing\n * This method will schedule the implicit loop in sync with the explicit master loop\n * i.e. loopToStart.syncedStart(loopToSyncWith)\n *\n * @method syncedStart\n * @for p5.SoundLoop\n * @param {Object} otherLoop a p5.SoundLoop to sync with\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\n */\np5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n\n if (!otherLoop.isPlaying) {\n otherLoop.clock.start(now + t);\n otherLoop.isPlaying = true;\n this.clock.start(now + t);\n this.isPlaying = true;\n } else if (otherLoop.isPlaying) {\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\n this.clock.start(now + time);\n this.isPlaying = true;\n }\n};\n\n/**\n * Updates frequency value, reflected in next callback\n * @private\n * @for p5.SoundLoop\n * @method _update\n */\np5.SoundLoop.prototype._update = function () {\n this.clock.frequency.value = this._calcFreq();\n};\n\n/**\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\n * @private\n * @for p5.SoundLoop\n * @method _calcFreq\n * @return {Number} new clock frequency value\n */\np5.SoundLoop.prototype._calcFreq = function () {\n //Seconds mode, bpm / timesignature has no effect\n if (typeof this._interval === 'number') {\n this.musicalTimeMode = false;\n return 1 / this._interval;\n }\n //Musical timing mode, calculate interval based bpm, interval,and time signature\n else if (typeof this._interval === 'string') {\n this.musicalTimeMode = true;\n return (\n (this._bpm / 60 / this._convertNotation(this._interval)) *\n (this._timeSignature / 4)\n );\n }\n};\n\n/**\n * Convert notation from musical time format to seconds\n * Uses Tone.Time convention\n * @private\n * @for p5.SoundLoop\n * @method _convertNotation\n * @param {String} value value to be converted\n * @return {Number} converted value in seconds\n */\np5.SoundLoop.prototype._convertNotation = function (value) {\n var type = value.slice(-1);\n value = Number(value.slice(0, -1));\n switch (type) {\n case 'm':\n return this._measure(value);\n case 'n':\n return this._note(value);\n default:\n console.warn(\n 'Specified interval is not formatted correctly. See Tone.js ' +\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'\n );\n }\n};\n\n/**\n * Helper conversion methods of measure and note\n * @private\n * @for p5.SoundLoop\n * @method _measure\n */\np5.SoundLoop.prototype._measure = function (value) {\n return value * this._timeSignature;\n};\n\n/**\n * @private\n * @method _note\n * @for p5.SoundLoop\n */\np5.SoundLoop.prototype._note = function (value) {\n return this._timeSignature / value;\n};\n\n/**\n * Getters and Setters, setting any paramter will result in a change in the clock's\n * frequency, that will be reflected after the next callback\n * beats per minute (defaults to 60)\n * @property {Number} bpm\n * @for p5.SoundLoop\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'bpm', {\n get: function () {\n return this._bpm;\n },\n set: function (bpm) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the BPM in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._bpm = bpm;\n this._update();\n },\n});\n\n/**\n * number of quarter notes in a measure (defaults to 4)\n * @property {Number} timeSignature\n * @for p5.SoundLoop\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {\n get: function () {\n return this._timeSignature;\n },\n set: function (timeSig) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the timeSignature in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._timeSignature = timeSig;\n this._update();\n },\n});\n\n/**\n * length of the loops interval\n * @property {Number|String} interval\n * @for p5.SoundLoop\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'interval', {\n get: function () {\n return this._interval;\n },\n set: function (interval) {\n this.musicalTimeMode = typeof interval === 'number' ? false : true;\n this._interval = interval;\n this._update();\n },\n});\n\n/**\n * how many times the callback has been called so far\n * @property {Number} iterations\n * @for p5.SoundLoop\n * @readonly\n */\nObject.defineProperty(p5.SoundLoop.prototype, 'iterations', {\n get: function () {\n return this.clock.ticks;\n },\n});\n\nexport default p5.SoundLoop;\n","import Effect from './effect';\n\n/**\n * Compressor is an audio effect class that performs dynamics compression\n * on an audio input source. This is a very commonly used technique in music\n * and sound production. Compression creates an overall louder, richer,\n * and fuller sound by lowering the volume of louds and raising that of softs.\n * Compression can be used to avoid clipping (sound distortion due to\n * peaks in volume) and is especially useful when many sounds are played\n * at once. Compression can be used on indivudal sound sources in addition\n * to the master output.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Compressor\n * @constructor\n * @extends p5.Effect\n *\n *\n */\np5.Compressor = function () {\n Effect.call(this);\n\n /**\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\n * \n * @property {AudioNode} compressor\n */\n\n this.compressor = this.ac.createDynamicsCompressor();\n\n this.input.connect(this.compressor);\n this.compressor.connect(this.wet);\n};\n\np5.Compressor.prototype = Object.create(Effect.prototype);\n\n/**\n * Performs the same function as .connect, but also accepts\n * optional parameters to set compressor's audioParams\n * @method process\n * @for p5.Compressor\n *\n * @param {Object} src Sound source to be connected\n *\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\np5.Compressor.prototype.process = function (\n src,\n attack,\n knee,\n ratio,\n threshold,\n release\n) {\n src.connect(this.input);\n this.set(attack, knee, ratio, threshold, release);\n};\n\n/**\n * Set the paramters of a compressor.\n * @method set\n * @for p5.Compressor\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} knee A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\np5.Compressor.prototype.set = function (\n attack,\n knee,\n ratio,\n threshold,\n release\n) {\n if (typeof attack !== 'undefined') {\n this.attack(attack);\n }\n if (typeof knee !== 'undefined') {\n this.knee(knee);\n }\n if (typeof ratio !== 'undefined') {\n this.ratio(ratio);\n }\n if (typeof threshold !== 'undefined') {\n this.threshold(threshold);\n }\n if (typeof release !== 'undefined') {\n this.release(release);\n }\n};\n\n/**\n * Get current attack or set value w/ time ramp\n *\n *\n * @method attack\n * @for p5.Compressor\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.attack = function (attack, time) {\n var t = time || 0;\n if (typeof attack === 'number') {\n this.compressor.attack.value = attack;\n this.compressor.attack.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.attack.linearRampToValueAtTime(\n attack,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof attack !== 'undefined') {\n attack.connect(this.compressor.attack);\n }\n return this.compressor.attack.value;\n};\n\n/**\n * Get current knee or set value w/ time ramp\n *\n * @method knee\n * @for p5.Compressor\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.knee = function (knee, time) {\n var t = time || 0;\n if (typeof knee === 'number') {\n this.compressor.knee.value = knee;\n this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.compressor.knee.linearRampToValueAtTime(\n knee,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof knee !== 'undefined') {\n knee.connect(this.compressor.knee);\n }\n return this.compressor.knee.value;\n};\n\n/**\n * Get current ratio or set value w/ time ramp\n * @method ratio\n * @for p5.Compressor\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.ratio = function (ratio, time) {\n var t = time || 0;\n if (typeof ratio === 'number') {\n this.compressor.ratio.value = ratio;\n this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.compressor.ratio.linearRampToValueAtTime(\n ratio,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof ratio !== 'undefined') {\n ratio.connect(this.compressor.ratio);\n }\n return this.compressor.ratio.value;\n};\n\n/**\n * Get current threshold or set value w/ time ramp\n * @method threshold\n * @for p5.Compressor\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.threshold = function (threshold, time) {\n var t = time || 0;\n if (typeof threshold === 'number') {\n this.compressor.threshold.value = threshold;\n this.compressor.threshold.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.threshold.linearRampToValueAtTime(\n threshold,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof threshold !== 'undefined') {\n threshold.connect(this.compressor.threshold);\n }\n return this.compressor.threshold.value;\n};\n\n/**\n * Get current release or set value w/ time ramp\n * @method release\n * @for p5.Compressor\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n *\n * @param {Number} [time] Assign time value to schedule the change in value\n */\np5.Compressor.prototype.release = function (release, time) {\n var t = time || 0;\n if (typeof release === 'number') {\n this.compressor.release.value = release;\n this.compressor.release.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.release.linearRampToValueAtTime(\n release,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof number !== 'undefined') {\n release.connect(this.compressor.release);\n }\n return this.compressor.release.value;\n};\n\n/**\n * Return the current reduction value\n *\n * @method reduction\n * @for p5.Compressor\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\n */\np5.Compressor.prototype.reduction = function () {\n return this.compressor.reduction.value;\n};\n\np5.Compressor.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n if (this.compressor) {\n this.compressor.disconnect();\n delete this.compressor;\n }\n};\n","// inspiration: recorder.js, Tone.js & typedarray.org\n\nimport p5sound from './master';\nimport { convertToWav, safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\nconst ac = p5sound.audiocontext;\n\n/**\n *

Record sounds for playback and/or to save as a .wav file.\n * The p5.SoundRecorder records all sound output from your sketch,\n * or can be assigned a specific source with setInput().

\n *

The record() method accepts a p5.SoundFile as a parameter.\n * When playback is stopped (either after the given amount of time,\n * or with the stop() method), the p5.SoundRecorder will send its\n * recording to that p5.SoundFile for playback.

\n *\n * @class p5.SoundRecorder\n * @constructor\n * @example\n *
\n * let mic, recorder, soundFile;\n * let state = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * textAlign(CENTER, CENTER);\n *\n * // create an audio in\n * mic = new p5.AudioIn();\n *\n * // prompts user to enable their browser mic\n * mic.start();\n *\n * // create a sound recorder\n * recorder = new p5.SoundRecorder();\n *\n * // connect the mic to the recorder\n * recorder.setInput(mic);\n *\n * // this sound file will be used to\n * // playback & save the recording\n * soundFile = new p5.SoundFile();\n *\n * text('tap to record', width/2, height/2);\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * // make sure user enabled the mic\n * if (state === 0 && mic.enabled) {\n *\n * // record to our p5.SoundFile\n * recorder.record(soundFile);\n *\n * background(255,0,0);\n * text('Recording!', width/2, height/2);\n * state++;\n * }\n * else if (state === 1) {\n * background(0,255,0);\n *\n * // stop recorder and\n * // send result to soundFile\n * recorder.stop();\n *\n * text('Done! Tap to play and download', width/2, height/2, width - 20);\n * state++;\n * }\n *\n * else if (state === 2) {\n * soundFile.play(); // play the result!\n * save(soundFile, 'mySound.wav');\n * state++;\n * }\n * }\n *
\n */\np5.SoundRecorder = function () {\n this.input = ac.createGain();\n this.output = ac.createGain();\n\n this._inputChannels = 2;\n this._outputChannels = 2; // stereo output, even if input is mono\n\n const workletBufferSize = safeBufferSize(1024);\n\n this._workletNode = new AudioWorkletNode(\n ac,\n processorNames.recorderProcessor,\n {\n outputChannelCount: [this._outputChannels],\n processorOptions: {\n numInputChannels: this._inputChannels,\n bufferSize: workletBufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'buffers') {\n const buffers = [\n new Float32Array(event.data.leftBuffer),\n new Float32Array(event.data.rightBuffer),\n ];\n this._callback(buffers);\n }\n }.bind(this);\n\n /**\n * callback invoked when the recording is over\n * @private\n * @type Function(Float32Array)\n */\n this._callback = function () {};\n\n // connections\n this._workletNode.connect(p5.soundOut._silentNode);\n this.setInput();\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Connect a specific device to the p5.SoundRecorder.\n * If no parameter is given, p5.SoundRecorer will record\n * all audible p5.sound from your sketch.\n *\n * @method setInput\n * @for p5.SoundRecorder\n * @param {Object} [unit] p5.sound object or a web audio unit\n * that outputs sound\n */\np5.SoundRecorder.prototype.setInput = function (unit) {\n this.input.disconnect();\n this.input = null;\n this.input = ac.createGain();\n this.input.connect(this._workletNode);\n this.input.connect(this.output);\n if (unit) {\n unit.connect(this.input);\n } else {\n p5.soundOut.output.connect(this.input);\n }\n};\n\n/**\n * Start recording. To access the recording, provide\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\n * will send its recording to that p5.SoundFile for playback once\n * recording is complete. Optional parameters include duration\n * (in seconds) of the recording, and a callback function that\n * will be called once the complete recording has been\n * transfered to the p5.SoundFile.\n *\n * @method record\n * @for p5.SoundRecorder\n * @param {p5.SoundFile} soundFile p5.SoundFile\n * @param {Number} [duration] Time (in seconds)\n * @param {Function} [callback] The name of a function that will be\n * called once the recording completes\n */\np5.SoundRecorder.prototype.record = function (sFile, duration, callback) {\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\n\n if (sFile && callback) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n callback();\n };\n } else if (sFile) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n };\n }\n};\n\n/**\n * Stop the recording. Once the recording is stopped,\n * the results will be sent to the p5.SoundFile that\n * was given on .record(), and if a callback function\n * was provided on record, that function will be called.\n *\n * @method stop\n * @for p5.SoundRecorder\n */\np5.SoundRecorder.prototype.stop = function () {\n this._workletNode.port.postMessage({ name: 'stop' });\n};\n\np5.SoundRecorder.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this._callback = function () {};\n if (this.input) {\n this.input.disconnect();\n }\n this.input = null;\n this._workletNode = null;\n};\n\n/**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device.\n * For uploading audio to a server, use\n * `p5.SoundFile.saveBlob`.\n *\n * @for p5\n * @method saveSound\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\n * @param {String} fileName name of the resulting .wav file.\n */\n// add to p5.prototype as this is used by the p5 `save()` method.\np5.prototype.saveSound = function (soundFile, fileName) {\n const dataView = convertToWav(soundFile.buffer);\n p5.prototype.writeFile([dataView], fileName, 'wav');\n};\n","import p5sound from './master';\n\n/**\n * A gain node is usefull to set the relative volume of sound.\n * It's typically used to build mixers.\n *\n * @class p5.Gain\n * @constructor\n * @example\n *
\n *\n * // load two soundfile and crossfade beetween them\n * let sound1,sound2;\n * let sound1Gain, sound2Gain, masterGain;\n * function preload(){\n * soundFormats('ogg', 'mp3');\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\n * sound2 = loadSound('assets/beat');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * // create a 'master' gain to which we will connect both soundfiles\n * masterGain = new p5.Gain();\n * masterGain.connect();\n * sound1.disconnect(); // diconnect from p5 output\n * sound1Gain = new p5.Gain(); // setup a gain node\n * sound1Gain.setInput(sound1); // connect the first sound to its input\n * sound1Gain.connect(masterGain); // connect its output to the 'master'\n * sound2.disconnect();\n * sound2Gain = new p5.Gain();\n * sound2Gain.setInput(sound2);\n * sound2Gain.connect(masterGain);\n * }\n * function startSound() {\n * sound1.loop();\n * sound2.loop();\n * loop();\n * }\n * function mouseReleased() {\n * sound1.stop();\n * sound2.stop();\n * }\n * function draw(){\n * background(220);\n * textAlign(CENTER);\n * textSize(11);\n * fill(0);\n * if (!sound1.isPlaying()) {\n * text('tap and drag to play', width/2, height/2);\n * return;\n * }\n * // map the horizontal position of the mouse to values useable for volume * control of sound1\n * var sound1Volume = constrain(map(mouseX,width,0,0,1), 0, 1);\n * var sound2Volume = 1-sound1Volume;\n * sound1Gain.amp(sound1Volume);\n * sound2Gain.amp(sound2Volume);\n * // map the vertical position of the mouse to values useable for 'master * volume control'\n * var masterVolume = constrain(map(mouseY,height,0,0,1), 0, 1);\n * masterGain.amp(masterVolume);\n * text('master', width/2, height - masterVolume * height * 0.9)\n * fill(255, 0, 255);\n * textAlign(LEFT);\n * text('sound1', 5, height - sound1Volume * height * 0.9);\n * textAlign(RIGHT);\n * text('sound2', width - 5, height - sound2Volume * height * 0.9);\n * }\n *
\n */\n\np5.Gain = function () {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n this.input.connect(this.output);\n\n // add to the soundArray\n p5sound.soundArray.push(this);\n};\n\n/**\n * Connect a source to the gain node.\n *\n * @method setInput\n * @for p5.Gain\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n */\n\np5.Gain.prototype.setInput = function (src) {\n src.connect(this.input);\n};\n\n/**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Gain\n * @param {Object} unit\n */\np5.Gain.prototype.connect = function (unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Gain\n */\np5.Gain.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Set the output level of the gain node.\n *\n * @method amp\n * @for p5.Gain\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\np5.Gain.prototype.amp = function (vol, rampTime = 0, tFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n};\n\np5.Gain.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n};\n\nexport default p5.Gain;\n","import p5sound from './master';\n\n/**\n * Base class for monophonic synthesizers. Any extensions of this class\n * should follow the API and implement the methods below in order to\n * remain compatible with p5.PolySynth();\n *\n * @class p5.AudioVoice\n * @constructor\n */\np5.AudioVoice = function () {\n this.ac = p5sound.audiocontext;\n this.output = this.ac.createGain();\n this.connect();\n p5sound.soundArray.push(this);\n};\n\np5.AudioVoice.prototype.play = function (\n note,\n velocity,\n secondsFromNow,\n sustime\n) {};\n\np5.AudioVoice.prototype.triggerAttack = function (\n note,\n velocity,\n secondsFromNow\n) {};\n\np5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {};\n\np5.AudioVoice.prototype.amp = function (vol, rampTime) {};\n\n/**\n * Connect to p5 objects or Web Audio Nodes\n * @method connect\n * @for p5.AudioVoice\n * @param {Object} unit\n */\np5.AudioVoice.prototype.connect = function (unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect from soundOut\n * @method disconnect\n * @for p5.AudioVoice\n */\np5.AudioVoice.prototype.disconnect = function () {\n this.output.disconnect();\n};\n\np5.AudioVoice.prototype.dispose = function () {\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n};\n\nexport default p5.AudioVoice;\n","import Effect from './effect.js';\n\n/*\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n */\nfunction makeDistortionCurve(amount) {\n var k = typeof amount === 'number' ? amount : 50;\n var numSamples = 44100;\n var curve = new Float32Array(numSamples);\n var deg = Math.PI / 180;\n var i = 0;\n var x;\n for (; i < numSamples; ++i) {\n x = (i * 2) / numSamples - 1;\n curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x));\n }\n return curve;\n}\n\n/**\n * A Distortion effect created with a Waveshaper Node,\n * with an approach adapted from\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Distortion\n * @extends p5.Effect\n * @constructor\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n *\n */\np5.Distortion = function (amount, oversample) {\n Effect.call(this);\n\n if (typeof amount === 'undefined') {\n amount = 0.25;\n }\n if (typeof amount !== 'number') {\n throw new Error('amount must be a number');\n }\n if (typeof oversample === 'undefined') {\n oversample = '2x';\n }\n if (typeof oversample !== 'string') {\n throw new Error('oversample must be a String');\n }\n\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n\n /**\n * The p5.Distortion is built with a\n * \n * Web Audio WaveShaper Node.\n *\n * @property {AudioNode} WaveShaperNode\n */\n this.waveShaperNode = this.ac.createWaveShaper();\n\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n this.waveShaperNode.oversample = oversample;\n\n this.input.connect(this.waveShaperNode);\n\n this.waveShaperNode.connect(this.wet);\n};\n\np5.Distortion.prototype = Object.create(Effect.prototype);\n\n/**\n * Process a sound source, optionally specify amount and oversample values.\n *\n * @method process\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\np5.Distortion.prototype.process = function (src, amount, oversample) {\n src.connect(this.input);\n this.set(amount, oversample);\n};\n\n/**\n * Set the amount and oversample of the waveshaper distortion.\n *\n * @method set\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\np5.Distortion.prototype.set = function (amount, oversample) {\n if (amount) {\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n }\n if (oversample) {\n this.waveShaperNode.oversample = oversample;\n }\n};\n\n/**\n * Return the distortion amount, typically between 0-1.\n *\n * @method getAmount\n * @for p5.Distortion\n * @return {Number} Unbounded distortion amount.\n * Normal values range from 0-1.\n */\np5.Distortion.prototype.getAmount = function () {\n return this.amount;\n};\n\n/**\n * Return the oversampling.\n *\n * @method getOversample\n * @for p5.Distortion\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\n */\np5.Distortion.prototype.getOversample = function () {\n return this.waveShaperNode.oversample;\n};\n\np5.Distortion.prototype.dispose = function () {\n Effect.prototype.dispose.apply(this);\n if (this.waveShaperNode) {\n this.waveShaperNode.disconnect();\n this.waveShaperNode = null;\n }\n};\n\nexport default p5.Distortion;\n","import p5sound from './master';\nimport AudioVoice from './audioVoice';\nimport { noteToFreq } from './helpers';\n\nvar DEFAULT_SUSTAIN = 0.15;\n\n/**\n * A MonoSynth is used as a single voice for sound synthesis.\n * This is a class to be used in conjunction with the PolySynth\n * class. Custom synthetisers should be built inheriting from\n * this class.\n *\n * @class p5.MonoSynth\n * @constructor\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n **/\n\np5.MonoSynth = function () {\n AudioVoice.call(this);\n\n this.oscillator = new p5.Oscillator();\n\n this.env = new p5.Envelope();\n this.env.setRange(1, 0);\n this.env.setExp(true);\n\n //set params\n this.setADSR(0.02, 0.25, 0.05, 0.35);\n\n // oscillator --> env --> this.output (gain) --> p5.soundOut\n this.oscillator.disconnect();\n this.oscillator.connect(this.output);\n\n this.env.disconnect();\n this.env.setInput(this.output.gain);\n\n // reset oscillator gain to 1.0\n this.oscillator.output.gain.value = 1.0;\n\n this.oscillator.start();\n this.connect();\n\n p5sound.soundArray.push(this);\n};\n\np5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);\n\n/**\n * Play tells the MonoSynth to start playing a note. This method schedules\n * the calling of .triggerAttack and .triggerRelease.\n *\n * @method play\n * @for p5.MonoSynth\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope. Defaults to 0.15 seconds.\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n *\n */\np5.MonoSynth.prototype.play = function (\n note,\n velocity,\n secondsFromNow,\n susTime\n) {\n this.triggerAttack(note, velocity, ~~secondsFromNow);\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\n};\n\n/**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @method triggerAttack\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\np5.MonoSynth.prototype.triggerAttack = function (\n note,\n velocity,\n secondsFromNow = 0\n) {\n var freq = noteToFreq(note);\n var vel = velocity || 0.1;\n this.oscillator.freq(freq, 0, secondsFromNow);\n this.env.ramp(this.output.gain, secondsFromNow, vel);\n};\n\n/**\n * Trigger the release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @param {Number} secondsFromNow time to trigger the release\n * @method triggerRelease\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\np5.MonoSynth.prototype.triggerRelease = function (secondsFromNow = 0) {\n this.env.ramp(this.output.gain, secondsFromNow, 0);\n};\n\n/**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.MonoSynth\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n */\np5.MonoSynth.prototype.setADSR = function (attack, decay, sustain, release) {\n this.env.setADSR(attack, decay, sustain, release);\n};\n\n/**\n * Getters and Setters\n * @property {Number} attack\n * @for p5.MonoSynth\n */\n/**\n * @property {Number} decay\n * @for p5.MonoSynth\n */\n/**\n * @property {Number} sustain\n * @for p5.MonoSynth\n */\n/**\n * @property {Number} release\n * @for p5.MonoSynth\n */\nObject.defineProperties(p5.MonoSynth.prototype, {\n attack: {\n get: function () {\n return this.env.aTime;\n },\n set: function (attack) {\n this.env.setADSR(\n attack,\n this.env.dTime,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n decay: {\n get: function () {\n return this.env.dTime;\n },\n set: function (decay) {\n this.env.setADSR(\n this.env.aTime,\n decay,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n sustain: {\n get: function () {\n return this.env.sPercent;\n },\n set: function (sustain) {\n this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime);\n },\n },\n release: {\n get: function () {\n return this.env.rTime;\n },\n set: function (release) {\n this.env.setADSR(\n this.env.aTime,\n this.env.dTime,\n this.env.sPercent,\n release\n );\n },\n },\n});\n\n/**\n * MonoSynth amp\n * @method amp\n * @for p5.MonoSynth\n * @param {Number} vol desired volume\n * @param {Number} [rampTime] Time to reach new volume\n * @return {Number} new volume value\n */\np5.MonoSynth.prototype.amp = function (vol, rampTime) {\n var t = rampTime || 0;\n if (typeof vol !== 'undefined') {\n this.oscillator.amp(vol, t);\n }\n return this.oscillator.amp().value;\n};\n\n/**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.MonoSynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\n\np5.MonoSynth.prototype.connect = function (unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.MonoSynth\n */\np5.MonoSynth.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.MonoSynth\n */\np5.MonoSynth.prototype.dispose = function () {\n AudioVoice.prototype.dispose.apply(this);\n\n if (this.env) {\n this.env.dispose();\n }\n if (this.oscillator) {\n this.oscillator.dispose();\n }\n};\n","import p5sound from './master';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\nimport { noteToFreq } from './helpers';\n\n/**\n * An AudioVoice is used as a single voice for sound synthesis.\n * The PolySynth class holds an array of AudioVoice, and deals\n * with voices allocations, with setting notes to be played, and\n * parameters to be set.\n *\n * @class p5.PolySynth\n * @constructor\n *\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\n * the AudioVoice class. Defaults to p5.MonoSynth\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n **/\np5.PolySynth = function (audioVoice, maxVoices) {\n //audiovoices will contain maxVoices many monophonic synths\n this.audiovoices = [];\n\n /**\n * An object that holds information about which notes have been played and\n * which notes are currently being played. New notes are added as keys\n * on the fly. While a note has been attacked, but not released, the value of the\n * key is the audiovoice which is generating that note. When notes are released,\n * the value of the key becomes undefined.\n * @property notes\n */\n this.notes = {};\n\n //indices of the most recently used, and least recently used audiovoice\n this._newest = 0;\n this._oldest = 0;\n\n /**\n * A PolySynth must have at least 1 voice, defaults to 8\n * @property polyvalue\n */\n this.maxVoices = maxVoices || 8;\n\n /**\n * Monosynth that generates the sound for each note that is triggered. The\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\n * @property AudioVoice\n */\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\n\n /**\n * This value must only change as a note is attacked or released. Due to delay\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\n * @private\n * @property {Tone.TimelineSignal} _voicesInUse\n */\n this._voicesInUse = new TimelineSignal(0);\n\n this.output = p5sound.audiocontext.createGain();\n this.connect();\n\n //Construct the appropriate number of audiovoices\n this._allocateVoices();\n p5sound.soundArray.push(this);\n};\n\n/**\n * Construct the appropriate number of audiovoices\n * @private\n * @for p5.PolySynth\n * @method _allocateVoices\n */\np5.PolySynth.prototype._allocateVoices = function () {\n for (var i = 0; i < this.maxVoices; i++) {\n this.audiovoices.push(new this.AudioVoice());\n this.audiovoices[i].disconnect();\n this.audiovoices[i].connect(this.output);\n }\n};\n\n/**\n * Play a note by triggering noteAttack and noteRelease with sustain time\n *\n * @method play\n * @for p5.PolySynth\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n */\np5.PolySynth.prototype.play = function (\n note,\n velocity,\n secondsFromNow,\n susTime = 1\n) {\n this.noteAttack(note, velocity, secondsFromNow);\n this.noteRelease(note, secondsFromNow + susTime);\n};\n\n/**\n * noteADSR sets the envelope for a specific note that has just been triggered.\n * Using this method modifies the envelope of whichever audiovoice is being used\n * to play the desired note. The envelope should be reset before noteRelease is called\n * in order to prevent the modified envelope from being used on other notes.\n *\n * @method noteADSR\n * @for p5.PolySynth\n * @param {Number} [note] Midi note on which ADSR should be set.\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\n\np5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var t = now + timeFromNow;\n this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r);\n};\n\n/**\n * Set the PolySynths global envelope. This method modifies the envelopes of each\n * monosynth so that all notes are played with this envelope.\n *\n * @method setADSR\n * @for p5.PolySynth\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\np5.PolySynth.prototype.setADSR = function (a, d, s, r) {\n this.audiovoices.forEach(function (voice) {\n voice.setADSR(a, d, s, r);\n });\n};\n\n/**\n * Trigger the Attack, and Decay portion of a MonoSynth.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @method noteAttack\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\n * @param {Number} [secondsFromNow] time from now (in seconds)\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n */\np5.PolySynth.prototype.noteAttack = function (\n _note,\n _velocity,\n secondsFromNow = 0\n) {\n //this value is used by this._voicesInUse\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\n\n //Convert note to frequency if necessary. This is because entries into this.notes\n //should be based on frequency for the sake of consistency.\n var note = noteToFreq(_note);\n var velocity = _velocity || 0.1;\n\n var currentVoice;\n\n //Release the note if it is already playing\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\n this.noteRelease(note, 0);\n }\n\n //Check to see how many voices are in use at the time the note will start\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\n }\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\n //with a new note\n else {\n currentVoice = this._oldest;\n\n var oldestNote = p5.prototype.freqToMidi(\n this.audiovoices[this._oldest].oscillator.freq().value\n );\n this.noteRelease(oldestNote);\n this._oldest = (this._oldest + 1) % (this.maxVoices - 1);\n }\n\n //Overrite the entry in the notes object. A note (frequency value)\n //corresponds to the index of the audiovoice that is playing it\n this.notes[note] = new TimelineSignal();\n this.notes[note].setValueAtTime(currentVoice, acTime);\n\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //Add 1 and schedule this value at time 't', when this note will start playing\n var previousVal =\n this._voicesInUse._searchBefore(acTime) === null\n ? 0\n : this._voicesInUse._searchBefore(acTime).value;\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\n\n //Then update all scheduled values that follow to increase by 1\n this._updateAfter(acTime, 1);\n\n this._newest = currentVoice;\n //The audiovoice handles the actual scheduling of the note\n if (typeof velocity === 'number') {\n var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2;\n velocity = velocity > maxRange ? maxRange : velocity;\n }\n\n // use secondsFromNow because this method will add AudioContext currentTime\n this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);\n};\n\n/**\n * Private method to ensure accurate values of this._voicesInUse\n * Any time a new value is scheduled, it is necessary to increment all subsequent\n * scheduledValues after attack, and decrement all subsequent\n * scheduledValues after release\n *\n * @private\n * @for p5.PolySynth\n * @param {[type]} time [description]\n * @param {[type]} value [description]\n * @return {[type]} [description]\n */\np5.PolySynth.prototype._updateAfter = function (time, value) {\n if (this._voicesInUse._searchAfter(time) === null) {\n return;\n } else {\n this._voicesInUse._searchAfter(time).value += value;\n var nextTime = this._voicesInUse._searchAfter(time).time;\n this._updateAfter(nextTime, value);\n }\n};\n\n/**\n * Trigger the Release of an AudioVoice note. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method noteRelease\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * If no value is provided, all notes will be released.\n * @param {Number} [secondsFromNow] time to trigger the release\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n *\n */\np5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n // if a note value is not provided, release all voices\n if (!_note) {\n this.audiovoices.forEach(function (voice) {\n voice.triggerRelease(tFromNow);\n });\n this._voicesInUse.setValueAtTime(0, t);\n for (var n in this.notes) {\n this.notes[n].dispose();\n delete this.notes[n];\n }\n return;\n }\n\n //Make sure note is in frequency inorder to query the this.notes object\n var note = noteToFreq(_note);\n\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\n console.warn('Cannot release a note that is not already playing');\n } else {\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //subtract 1 and schedule this value at time 't', when this note will stop playing\n var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\n if (previousVal > 0) {\n this._updateAfter(t, -1);\n }\n\n this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(\n tFromNow\n );\n this.notes[note].dispose();\n delete this.notes[note];\n\n this._newest =\n this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\n }\n};\n\n/**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.PolySynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\np5.PolySynth.prototype.connect = function (unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n};\n\n/**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.PolySynth\n */\np5.PolySynth.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n/**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.PolySynth\n */\np5.PolySynth.prototype.dispose = function () {\n this.audiovoices.forEach(function (voice) {\n voice.dispose();\n });\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n};\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///../node_modules/tone/Tone/core/Tone.js","webpack:///../node_modules/tone/Tone/signal/Multiply.js","webpack:///../node_modules/tone/Tone/signal/Signal.js","webpack:///./audiocontext.js","webpack:///../node_modules/tone/Tone/signal/Add.js","webpack:///./audioWorklet/processorNames.js","webpack:///../node_modules/tone/Tone/signal/WaveShaper.js","webpack:///../node_modules/tone/Tone/signal/TimelineSignal.js","webpack:///../node_modules/tone/Tone/signal/Scale.js","webpack:///../node_modules/tone/Tone/type/Type.js","webpack:///../node_modules/tone/Tone/core/Gain.js","webpack:///../node_modules/tone/Tone/core/Clock.js","webpack:///../node_modules/tone/Tone/core/Context.js","webpack:///../node_modules/tone/Tone/signal/Subtract.js","webpack:///../node_modules/tone/Tone/core/Emitter.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:///../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/startaudiocontext/StartAudioContext.js","webpack:///../node_modules/tone/Tone/component/CrossFade.js","webpack:///../node_modules/audioworklet-polyfill/dist/audioworklet-polyfill.js","webpack:///./shims.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///./audioWorklet/recorderProcessor.js","webpack:///./audioWorklet/soundFileProcessor.js","webpack:///./audioWorklet/amplitudeProcessor.js","webpack:///../node_modules/tone/Tone/type/Frequency.js","webpack:///../node_modules/tone/Tone/type/TransportTime.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:///../node_modules/tone/Tone/core/TimelineState.js","webpack:///./master.js","webpack:///./helpers.js","webpack:///./errorHandler.js","webpack:///./audioWorklet/index.js","webpack:///./panner.js","webpack:///./soundfile.js","webpack:///./amplitude.js","webpack:///./fft.js","webpack:///./oscillator.js","webpack:///./envelope.js","webpack:///./noise.js","webpack:///./pulse.js","webpack:///./audioin.js","webpack:///./effect.js","webpack:///./filter.js","webpack:///./eqFilter.js","webpack:///./eq.js","webpack:///./listener3d.js","webpack:///./panner3d.js","webpack:///./delay.js","webpack:///./reverb.js","webpack:///./metro.js","webpack:///./looper.js","webpack:///./soundLoop.js","webpack:///./compressor.js","webpack:///./peakDetect.js","webpack:///./soundRecorder.js","webpack:///./distortion.js","webpack:///./gain.js","webpack:///./audioVoice.js","webpack:///./monosynth.js","webpack:///./onsetDetect.js","webpack:///./polysynth.js","webpack:///./deprecations/Signal.js","webpack:///./app.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","Multiply","__WEBPACK_AMD_DEFINE_RESULT__","createInsOuts","_mult","Gain","_param","_gain","getConstant","units","Type","Default","convert","SignalBase","global","audiocontext","AudioContext","getAudioContext","userStartAudio","elements","callback","elt","p5","Element","map","e","StartAudioContext","Add","_sum","recorderProcessor","soundFileProcessor","amplitudeProcessor","WaveShaper","mapping","bufferLen","_shaper","createWaveShaper","_curve","curve","isFinite","Float32Array","setMap","len","normalized","oversample","oversampling","RangeError","TimelineSignal","_events","Timeline","_initial","_fromUnits","Linear","Exponential","Target","Curve","Set","getValueAtTime","_toUnits","convertedVal","cancelScheduledValues","setValueAtTime","startTime","toSeconds","add","type","time","linearRampToValueAtTime","endTime","exponentialRampToValueAtTime","beforeEvent","_searchBefore","_minOutput","setValue","max","sampleTime","setTargetAtTime","timeConstant","constant","setValueCurveAtTime","duration","scaling","floats","segmentTime","after","cancel","setRampPoint","before","_searchAfter","linearRampToValueBetween","start","finish","exponentialRampToValueBetween","getAfter","previouVal","previous","getBefore","_exponentialApproach","_curveInterpolate","_linearInterpolate","_exponentialInterpolate","t0","v0","v1","exp","t1","progress","lowerIndex","floor","upperIndex","ceil","lowerVal","upperVal","Scale","outputMin","outputMax","_outputMin","_outputMax","_scale","_add","_setRange","min","Time","Frequency","TransportTime","Ticks","NormalRange","AudioRange","Decibels","Interval","BPM","Positive","Cents","Degrees","MIDI","BarsBeatsSixteenths","Samples","Hertz","Note","Milliseconds","Seconds","Notation","TimeBase","toFrequency","freq","valueOf","toTicks","Transport","ticks","GainNode","createGainNode","_gainNode","Clock","Emitter","_nextTick","_lastState","frequency","_state","TimelineState","_boundLoop","_loop","on","lookAhead","offset","state","stop","setStateAtTime","pause","loopInterval","updateInterval","lag","currentState","event","tickTime","getStateAtTime","off","Infinity","toneConnect","B","outNum","inNum","nativeConnect","Error","nativeDisconnect","webkitAudioContext","prop","_context","_defineProperty","_latencyHint","_lookAhead","_updateInterval","_computedUpdateInterval","_worker","_createWorker","_constants","mixin","currentTime","URL","webkitURL","blob","Blob","toFixed","blobUrl","createObjectURL","worker","Worker","addEventListener","_lastUpdate","diff","buffer","createBuffer","arr","getChannelData","createBufferSource","channelCount","channelCountMode","loop","lA","blockTime","postMessage","hint","latencyHint","supported","Subtract","_neg","Negate","events","eventName","ev","eventList","args","slice","functions","func","emitterFunc","node","outputNumber","inputNumber","overridden","_plusNow","_unaryExpressions","quantize","regexp","method","rh","nextSubdivision","lh","subdiv","_expr","expr","subdivision","round","addNow","_defaultExpr","_noOp","copy","toNotation","retNotation","_toNotationHelper","retTripletNotation","testNotations","threshold","_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","_timeline","_toRemove","_iterating","memory","index","_search","remove","shift","cancelBefore","beginning","end","midPoint","nextEvent","_iterate","lowerBound","upperBound","forEach","forEachBefore","forEachAfter","forEachFrom","forEachAtTime","_multiply","GreaterThanZero","_thresh","factory","__WEBPACK_AMD_DEFINE_FACTORY__","TapListener","element","_dragged","_element","_bindedMove","_moved","_bindedEnd","_ended","isStarted","source","resume","removeEventListener","promise","Promise","success","checkLoop","requestAnimationFrame","tapListeners","bindTapListener","NodeList","document","querySelectorAll","jquery","toArray","tap","body","then","CrossFade","initialFade","a","b","fade","_equalPowerA","EqualPowerGain","_equalPowerB","_invert","Expr","parameters","bufferSize","fill","processor","realm","exec","inputBuffer","outputBuffer","process","numberOfChannels","$$processors","$$context","AudioWorkletNode","self","createScriptProcessor","outputChannelCount","Map","properties","u","defaultValue","MessageChannel","port2","f","Processor","port","port1","onaudioprocess","$$audioWorklet","AudioWorklet","addModule","fetch","ok","status","text","AudioWorkletProcessor","registerProcessor","parameterDescriptors","createElement","style","cssText","appendChild","contentWindow","createTextNode","$hook","console","documentElement","transpile","String","fixSetTarget","setTargetValueAtTime","createDelay","createDelayNode","createJavaScriptNode","createPeriodicWave","createWaveTable","internal_createGain","internal_createDelay","maxDelayTime","delayTime","internal_createBufferSource","internal_start","when","noteGrainOn","noteOn","internal_stop","noteOff","playbackRate","internal_createDynamicsCompressor","createDynamicsCompressor","knee","ratio","reduction","attack","release","internal_createBiquadFilter","createBiquadFilter","detune","Q","createOscillator","internal_createOscillator","setPeriodicWave","setWaveTable","OfflineAudioContext","webkitOfflineAudioContext","navigator","getUserMedia","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","el","isSupported","canPlayType","isFileSupported","extension","toLowerCase","g","Function","__webpack_exports__","midi","midiToFrequency","note","pitch","octave","noteNumber","noteToScaleIndex","transpose","harmonize","intervals","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","applyBinary","Constructor","_eval","applyUnary","getNumber","literalNumber","_replacements","inputCount","_parseInputs","_nodes","result","tree","_parseTree","_disposeNodes","_Expressions","signal","glue",",","abs","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","initial","p5sound","Master","_classCallCheck","limiter","meter","fftMeter","soundArray","parts","extensions","getMasterVolume","masterVolume","vol","undefined","tFromNow","currentVol","soundOut","_silentNode","freqToMidi","mathlog2","midiToFreq","noteToFreq","A","C","D","E","F","G","toUpperCase","convertToWav","audioBuffer","leftChannel","interleaved","interleave","ArrayBuffer","view","DataView","writeUTFBytes","setUint32","setUint16","lng","setInt16","rightChannel","inputIndex","string","setUint8","charCodeAt","safeBufferSize","idealBufferSize","tempAudioWorkletNode","processorNames","ScriptProcessorNode","CustomError","errorTrace","failedPath","tempStack","splitStack","err","originalStack","stack","filter","ln","moduleSources","require","ac","registerMethod","preload","_incrementPreload","onWorkletModulesLoad","_decrementPreload","all","moduleSrc","objectURL","audioWorklet","panner","createStereoPanner","Panner","panner_classCallCheck","stereoPanner","_createClass","pan","obj","_Panner","numInputChannels","left","right","channelInterpretation","splitter","createChannelSplitter","createChannelMerger","v","rightVal","cos","leftVal","numChannels","Peak","amp","soundfile_classCallCheck","sampleIndex","amplitude","tempos","getPeaksAtThreshold","data","peaksObj","peak","mapTempo","theoreticalTempo","Cue","id","SoundFile","paths","onload","onerror","whileLoading","path","_checkFileFormats","url","soundfile_typeof","File","FileReader","FileList","file","_onended","_looping","_playing","_paused","_pauseTime","_cues","_cueIDCounter","_lastPos","_counterNode","_workletNode","bufferSourceNodes","bufferSourceNode","reversed","pauseTime","startMillis","panPosition","load","_whileLoading","_clearOnEnd","thisBufferSourceNode","target","soundFile","_","reverse","setVolume","errorCallback","request","XMLHttpRequest","evt","_updateProgress","open","responseType","decodeAudioData","response","buff","inputChannels","msg","statusText","message","send","reader","readAsArrayBuffer","lengthComputable","percentComplete","loaded","rate","_cueStart","cueStart","cueEnd","isPlaying","_initSourceNode","_initCounterNode","_arrayIndex","loopStart","loopEnd","str","pTime","play","bool","timeFromNow","stopAll","_time","pval","reverseBuffer","num","newPlaybackRate","_rampTime","_tFromNow","cueTime","cTime","dur","width","sampleSize","sampleStep","channels","peaks","chan","currentPos","curVol","getVolume","jump","buf","size","newBuffer","channelNum","_this","cNode","workletBufferSize","processorOptions","onmessage","_onTimeUpdate","audioBuf","arrayBuffer","_createCounterBuffer","_initThreshold","_minThreshold","_minPeaks","bufLen","allPeaks","minThreshold","minPeaks","offlineContext","startRendering","oncomplete","filteredBuffer","renderedBuffer","bufferData","topTempos","intervalCounts","tempoCounts","intervalCount","some","tempoCount","tempo","count","isNaN","groupNeighborsByTempo","peaksArray","sort","startPeak","endPeak","startPos","countIntervalsBetweenNearbyPeaks","intA","intB","tempoPeaks","bpmVariance","peaksAtTopTempo","intervalBPM","peakTime","getPeaksAtTopTempo","cue","cueLength","playbackTime","callbackTime","_prevUpdateTime","fileName","saveSound","dataView","Amplitude","smoothing","amplitude_classCallCheck","parameterData","normalize","volume","volNorm","stereoVol","stereoVolNorm","channel","FFT","bins","fft_classCallCheck","analyser","createAnalyser","defineProperties","fftSize","configurable","smoothingTimeConstant","smooth","freqDomain","Uint8Array","frequencyBinCount","timeDomain","bass","lowMid","mid","highMid","treble","normalArray","_isSafari","fft","timeToFloat","getFloatTimeDomainData","timeToInt","getByteTimeDomainData","scaled","freqToFloat","getFloatFrequencyData","freqToInt","getByteFrequencyData","frequency1","frequency2","nyquist","swap","lowIndex","highIndex","numFrequencies","freq1","freq2","getEnergy","cumulative_sum","centroid_normalization","mean_freq_index","_N","N","spectrum","spectrumLength","spectrumStep","linearAverages","groupIndex","specIndex","octaveBands","logAverages","octaveIndex","hi","_fCtr0","fCtr0","lastFrequencyBand","lo","ctr","newFrequencyBand","sigChain","mathObj","thisChain","nextChain","chainSource","oscillator","mathOps","Oscillator","oscillator_classCallCheck","started","phaseAmount","_freqMods","connection","freqNode","phase","oscMods","osc2","delayAmt","dNode","Mult","inMin","inMax","outMin","outMax","mapOutMin","mapOutMax","scale","SinOsc","_possibleConstructorReturn","_getPrototypeOf","TriOsc","SawOsc","SqrOsc","Envelope","l1","t2","l2","t3","l3","aTime","aLevel","dTime","dLevel","rTime","rLevel","_rampHighPercentage","_rampLowPercentage","control","_init","isExponential","sourceToClear","wasTriggered","_setRampAD","setADSR","sPercent","setRange","_rampAttackTime","checkExpInput","_rampDecayTime","TCDenominator","_rampAttackTC","_rampDecayTC","setRampPercentages","p1","p2","setInput","setExp","isExp","secondsFromNow","susTime","triggerAttack","triggerRelease","lastAttack","valToSet","ramp","v2","destination1","destination2","AudioIn","Reverb","Noise","Filter","Delay","_mathChain","Env","_whiteNoiseBuffer","whiteBuffer","noiseData","random","_pinkNoiseBuffer","b0","b1","b2","b3","b4","b5","b6","pinkBuffer","white","_brownNoiseBuffer","brownBuffer","lastOut","assignType","noise_classCallCheck","noise_possibleConstructorReturn","noise_getPrototypeOf","noise","createDCOffset","bufferSource","Pulse","w","pulse_classCallCheck","pulse_possibleConstructorReturn","pulse_getPrototypeOf","dcOffset","dcGain","mW","sig","mult1","mult2","mods","currentFreq","freqMod","inputSources","audioin_classCallCheck","stream","mediaStream","currentSource","enabled","MediaStreamTrack","mediaDevices","alert","successCallback","audioSource","constraints","audio","echoCancellation","deviceId","createMediaStreamSource","getTracks","track","getLevel","onSuccess","onError","resolve","reject","enumerateDevices","devices","device","kind","error","active","Effect","effect_classCallCheck","_drywet","wet","filter_classCallCheck","filter_possibleConstructorReturn","filter_getPrototypeOf","biquad","setType","_on","_untoggledType","src","res","_get","LowPass","HighPass","BandPass","EQFilter","eqFilter_classCallCheck","eqFilter_possibleConstructorReturn","eqFilter_getPrototypeOf","EQ","_eqsize","factor","eq_classCallCheck","eq_possibleConstructorReturn","eq_getPrototypeOf","bands","_newBand","eq_get","pop","Listener3D","listener3d_classCallCheck","listener","xVal","yVal","zVal","positionX","positionY","positionZ","xValF","yValF","zValF","xValU","yValU","zValU","orientForward","orientUp","forwardX","forwardY","forwardZ","upX","upY","upZ","Panner3D","panner3d_classCallCheck","panner3d_possibleConstructorReturn","panner3d_getPrototypeOf","createPanner","panningModel","distanceModel","orientX","orientY","orientZ","orientationX","orientationY","orientationZ","maxDistance","rolloffFactor","maxDist","rolloff","panner3d_get","delay_classCallCheck","delay_possibleConstructorReturn","delay_getPrototypeOf","_split","_merge","_leftGain","_rightGain","leftDelay","rightDelay","_leftFilter","_rightFilter","_maxDelay","maxValue","feedback","_delayTime","_feedback","_filter","delay_get","reverb_classCallCheck","reverb_possibleConstructorReturn","reverb_getPrototypeOf","_initConvolverNode","_seconds","_decay","_reverse","_buildImpulse","convolverNode","createConvolver","_teardownConvolverNode","decayRate","rebuild","decay","impulse","impulseL","impulseR","_setBuffer","reverb_get","Convolver","_this2","impulses","_loadBuffer","_path","chunks","location","origin","cordova","Metro","metro_classCallCheck","clock","ontick","syncedParts","prevTick","tatumTime","tickCallback","elapsedTime","thisPart","incrementStep","phrases","thisPhrase","phraseArray","sequence","bNum","metroTicks","looping","beatTime","tatums","getRate","part","setBPM","Phrase","looper_classCallCheck","phraseStep","Part","steps","bLength","partStep","noLoop","metro","beatLength","getBPM","resetSync","onended","array","Score","currentPart","thisScore","nextPart","resetPart","playNextPart","resetParts","scoreStep","aScore","SoundLoop","soundLoop_classCallCheck","_bpm","musicalTimeMode","_update","timeSig","_interval","maxIterations","iterations","_calcFreq","otherLoop","_convertNotation","Number","_measure","_note","Compressor","compressor_classCallCheck","compressor_possibleConstructorReturn","compressor_getPrototypeOf","compressor","number","compressor_get","PeakDetect","_framesPerPeak","peakDetect_classCallCheck","framesPerPeak","framesSinceLastPeak","cutoff","cutoffMult","energy","penergy","currentValue","isDetected","f1","f2","_onPeak","fftObject","nrg","SoundRecorder","soundRecorder_classCallCheck","_inputChannels","_outputChannels","buffers","leftBuffer","rightBuffer","_callback","sFile","setBuffer","makeDistortionCurve","amount","k","deg","Distortion","distortion_classCallCheck","distortion_possibleConstructorReturn","distortion_getPrototypeOf","curveAmount","waveShaperNode","distortion_get","gain_classCallCheck","AudioVoice","audioVoice_classCallCheck","velocity","sustime","MonoSynth","monosynth_classCallCheck","monosynth_possibleConstructorReturn","monosynth_getPrototypeOf","env","monosynth_assertThisInitialized","sustain","vel","monosynth_get","OnsetDetect","freqLow","freqHigh","onsetDetect_classCallCheck","treshold","sensitivity","setTimeout","PolySynth","audioVoice","maxVoices","polysynth_classCallCheck","audiovoices","notes","_newest","_oldest","_voicesInUse","_allocateVoices","noteAttack","noteRelease","voice","_velocity","currentVoice","acTime","oldestNote","previousVal","_updateAfter","maxRange","nextTime","Signal_classCallCheck","soundFormats","disposeSound","extTest","pathSplit","pathCore","_typeof","math","writeFile","loadSound","registerPreloadMethod","listener3D","cReverb","peakDetect"],"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 = 40);\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","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","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});","global.TONE_SILENCE_VERSION_LOGGING = true;\n\nimport StartAudioContext from 'startaudiocontext';\nimport Tone from 'Tone/core/Tone';\nimport 'Tone/core/Context';\n\n// Create the Audio Context\nconst audiocontext = new window.AudioContext();\n\n// Tone and p5.sound share the same audio context\nTone.setContext(audiocontext);\n\n/**\n *

Returns the Audio Context for this sketch. Useful for users\n * who would like to dig deeper into the Web Audio API\n * .

\n *\n *

Some browsers require users to startAudioContext\n * with a user gesture, such as touchStarted in the example below.

\n *\n * @for p5\n * @method getAudioContext\n * @return {Object} AudioContext for this sketch\n * @example\n *
\n * function draw() {\n * background(255);\n * textAlign(CENTER);\n *\n * if (getAudioContext().state !== 'running') {\n * text('click to start audio', width/2, height/2);\n * } else {\n * text('audio is enabled', width/2, height/2);\n * }\n * }\n *\n * function touchStarted() {\n * if (getAudioContext().state !== 'running') {\n * getAudioContext().resume();\n * }\n * var synth = new p5.MonoSynth();\n * synth.play('A4', 0.5, 0, 0.2);\n * }\n *\n *
\n */\nexport function getAudioContext() {\n return audiocontext;\n}\n\n/**\n *

It is not only a good practice to give users control over starting\n * audio. This policy is enforced by many web browsers, including iOS and\n * Google Chrome, which create the Web Audio API's\n * Audio Context\n * in a suspended state.

\n *\n *

In these browser-specific policies, sound will not play until a user\n * interaction event (i.e. mousePressed()) explicitly resumes\n * the AudioContext, or starts an audio node. This can be accomplished by\n * calling start() on a p5.Oscillator,\n * play() on a p5.SoundFile, or simply\n * userStartAudio().

\n *\n *

userStartAudio() starts the AudioContext on a user\n * gesture. The default behavior will enable audio on any\n * mouseUp or touchEnd event. It can also be placed in a specific\n * interaction function, such as mousePressed() as in the\n * example below. This method utilizes\n * StartAudioContext\n * , a library by Yotam Mann (MIT Licence, 2016).

\n * @param {Element|Array} [element(s)] This argument can be an Element,\n * Selector String, NodeList, p5.Element,\n * jQuery Element, or an Array of any of those.\n * @param {Function} [callback] Callback to invoke when the AudioContext\n * has started\n * @return {Promise} Returns a Promise that resolves when\n * the AudioContext state is 'running'\n * @method userStartAudio\n * @for p5\n * @example\n *
\n * function setup() {\n * // mimics the autoplay policy\n * getAudioContext().suspend();\n *\n * let mySynth = new p5.MonoSynth();\n *\n * // This won't play until the context has resumed\n * mySynth.play('A6');\n * }\n * function draw() {\n * background(220);\n * textAlign(CENTER, CENTER);\n * text(getAudioContext().state, width/2, height/2);\n * }\n * function mousePressed() {\n * userStartAudio();\n * }\n *
\n */\nexport function userStartAudio(elements, callback) {\n var elt = elements;\n if (elements instanceof p5.Element) {\n elt = elements.elt;\n } else if (elements instanceof Array && elements[0] instanceof p5.Element) {\n elt = elements.map(function (e) {\n return e.elt;\n });\n }\n return StartAudioContext(audiocontext, elt, callback);\n}\n\nexport default audiocontext;\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});","module.exports = {\n recorderProcessor: 'recorder-processor',\n soundFileProcessor: 'sound-file-processor',\n amplitudeProcessor: 'amplitude-processor',\n};\n","define([\"Tone/core/Tone\", \"Tone/signal/SignalBase\"], function(Tone){\n\n\t\"use strict\";\n\n\t/**\n\t * @class Wraps the native Web Audio API \n\t * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).\n\t *\n\t * @extends {Tone.SignalBase}\n\t * @constructor\n\t * @param {function|Array|Number} mapping The function used to define the values. \n\t * The mapping function should take two arguments: \n\t * the first is the value at the current position \n\t * and the second is the array position. \n\t * If the argument is an array, that array will be\n\t * set as the wave shaping function. The input\n\t * signal is an AudioRange [-1, 1] value and the output\n\t * signal can take on any numerical values. \n\t * \n\t * @param {Number} [bufferLen=1024] The length of the WaveShaperNode buffer.\n\t * @example\n\t * var timesTwo = new Tone.WaveShaper(function(val){\n\t * \treturn val * 2;\n\t * }, 2048);\n\t * @example\n\t * //a waveshaper can also be constructed with an array of values\n\t * var invert = new Tone.WaveShaper([1, -1]);\n\t */\n\tTone.WaveShaper = function(mapping, bufferLen){\n\n\t\t/**\n\t\t * the waveshaper\n\t\t * @type {WaveShaperNode}\n\t\t * @private\n\t\t */\n\t\tthis._shaper = this.input = this.output = this.context.createWaveShaper();\n\n\t\t/**\n\t\t * the waveshapers curve\n\t\t * @type {Float32Array}\n\t\t * @private\n\t\t */\n\t\tthis._curve = null;\n\n\t\tif (Array.isArray(mapping)){\n\t\t\tthis.curve = mapping;\n\t\t} else if (isFinite(mapping) || this.isUndef(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(mapping, 1024));\n\t\t} else if (this.isFunction(mapping)){\n\t\t\tthis._curve = new Float32Array(this.defaultArg(bufferLen, 1024));\n\t\t\tthis.setMap(mapping);\n\t\t} \n\t};\n\n\tTone.extend(Tone.WaveShaper, Tone.SignalBase);\n\n\t/**\n\t * Uses a mapping function to set the value of the curve. \n\t * @param {function} mapping The function used to define the values. \n\t * The mapping function take two arguments: \n\t * the first is the value at the current position \n\t * which goes from -1 to 1 over the number of elements\n\t * in the curve array. The second argument is the array position. \n\t * @returns {Tone.WaveShaper} this\n\t * @example\n\t * //map the input signal from [-1, 1] to [0, 10]\n\t * shaper.setMap(function(val, index){\n\t * \treturn (val + 1) * 5;\n\t * })\n\t */\n\tTone.WaveShaper.prototype.setMap = function(mapping){\n\t\tfor (var i = 0, len = this._curve.length; i < len; i++){\n\t\t\tvar normalized = (i / (len - 1)) * 2 - 1;\n\t\t\tthis._curve[i] = mapping(normalized, i);\n\t\t}\n\t\tthis._shaper.curve = this._curve;\n\t\treturn this;\n\t};\n\n\t/**\n\t * The array to set as the waveshaper curve. For linear curves\n\t * array length does not make much difference, but for complex curves\n\t * longer arrays will provide smoother interpolation. \n\t * @memberOf Tone.WaveShaper#\n\t * @type {Array}\n\t * @name curve\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"curve\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.curve;\n\t\t},\n\t\tset : function(mapping){\n\t\t\tthis._curve = new Float32Array(mapping);\n\t\t\tthis._shaper.curve = this._curve;\n\t\t}\n\t});\n\n\t/**\n\t * Specifies what type of oversampling (if any) should be used when \n\t * applying the shaping curve. Can either be \"none\", \"2x\" or \"4x\". \n\t * @memberOf Tone.WaveShaper#\n\t * @type {string}\n\t * @name oversample\n\t */\n\tObject.defineProperty(Tone.WaveShaper.prototype, \"oversample\", {\n\t\tget : function(){\n\t\t\treturn this._shaper.oversample;\n\t\t},\n\t\tset : function(oversampling){\n\t\t\tif ([\"none\", \"2x\", \"4x\"].indexOf(oversampling) !== -1){\n\t\t\t\tthis._shaper.oversample = oversampling;\n\t\t\t} else {\n\t\t\t\tthrow new RangeError(\"Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'\");\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Clean up.\n\t * @returns {Tone.WaveShaper} this\n\t */\n\tTone.WaveShaper.prototype.dispose = function(){\n\t\tTone.prototype.dispose.call(this);\n\t\tthis._shaper.disconnect();\n\t\tthis._shaper = null;\n\t\tthis._curve = null;\n\t\treturn this;\n\t};\n\n\treturn Tone.WaveShaper;\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});","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/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});","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});","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/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});","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});","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});","/**\n * StartAudioContext.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2016 Yotam Mann\n */\n(function (root, factory) {\n\tif (typeof define === \"function\" && define.amd) {\n\t\tdefine([], factory)\n\t } else if (typeof module === \"object\" && module.exports) {\n module.exports = factory()\n\t} else {\n\t\troot.StartAudioContext = factory()\n }\n}(this, function () {\n\n\t//TAP LISTENER/////////////////////////////////////////////////////////////\n\n\t/**\n\t * @class Listens for non-dragging tap ends on the given element\n\t * @param {Element} element\n\t * @internal\n\t */\n\tvar TapListener = function(element, context){\n\n\t\tthis._dragged = false\n\n\t\tthis._element = element\n\n\t\tthis._bindedMove = this._moved.bind(this)\n\t\tthis._bindedEnd = this._ended.bind(this, context)\n\n\t\telement.addEventListener(\"touchstart\", this._bindedEnd)\n\t\telement.addEventListener(\"touchmove\", this._bindedMove)\n\t\telement.addEventListener(\"touchend\", this._bindedEnd)\n\t\telement.addEventListener(\"mouseup\", this._bindedEnd)\n\t}\n\n\t/**\n\t * drag move event\n\t */\n\tTapListener.prototype._moved = function(e){\n\t\tthis._dragged = true\n\t};\n\n\t/**\n\t * tap ended listener\n\t */\n\tTapListener.prototype._ended = function(context){\n\t\tif (!this._dragged){\n\t\t\tstartContext(context)\n\t\t}\n\t\tthis._dragged = false\n\t};\n\n\t/**\n\t * remove all the bound events\n\t */\n\tTapListener.prototype.dispose = function(){\n\t\tthis._element.removeEventListener(\"touchstart\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"touchmove\", this._bindedMove)\n\t\tthis._element.removeEventListener(\"touchend\", this._bindedEnd)\n\t\tthis._element.removeEventListener(\"mouseup\", this._bindedEnd)\n\t\tthis._bindedMove = null\n\t\tthis._bindedEnd = null\n\t\tthis._element = null\n\t};\n\n\t//END TAP LISTENER/////////////////////////////////////////////////////////\n\n\t/**\n\t * Plays a silent sound and also invoke the \"resume\" method\n\t * @param {AudioContext} context\n\t * @private\n\t */\n\tfunction startContext(context){\n\t\t// this accomplishes the iOS specific requirement\n\t\tvar buffer = context.createBuffer(1, 1, context.sampleRate)\n\t\tvar source = context.createBufferSource()\n\t\tsource.buffer = buffer\n\t\tsource.connect(context.destination)\n\t\tsource.start(0)\n\n\t\t// resume the audio context\n\t\tif (context.resume){\n\t\t\tcontext.resume()\n\t\t}\n\t}\n\n\t/**\n\t * Returns true if the audio context is started\n\t * @param {AudioContext} context\n\t * @return {Boolean}\n\t * @private\n\t */\n\tfunction isStarted(context){\n\t\t return context.state === \"running\"\n\t}\n\n\t/**\n\t * Invokes the callback as soon as the AudioContext\n\t * is started\n\t * @param {AudioContext} context\n\t * @param {Function} callback\n\t */\n\tfunction onStarted(context, callback){\n\n\t\tfunction checkLoop(){\n\t\t\tif (isStarted(context)){\n\t\t\t\tcallback()\n\t\t\t} else {\n\t\t\t\trequestAnimationFrame(checkLoop)\n\t\t\t\tif (context.resume){\n\t\t\t\t\tcontext.resume()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isStarted(context)){\n\t\t\tcallback()\n\t\t} else {\n\t\t\tcheckLoop()\n\t\t}\n\t}\n\n\t/**\n\t * Add a tap listener to the audio context\n\t * @param {Array|Element|String|jQuery} element\n\t * @param {Array} tapListeners\n\t */\n\tfunction bindTapListener(element, tapListeners, context){\n\t\tif (Array.isArray(element) || (NodeList && element instanceof NodeList)){\n\t\t\tfor (var i = 0; i < element.length; i++){\n\t\t\t\tbindTapListener(element[i], tapListeners, context)\n\t\t\t}\n\t\t} else if (typeof element === \"string\"){\n\t\t\tbindTapListener(document.querySelectorAll(element), tapListeners, context)\n\t\t} else if (element.jquery && typeof element.toArray === \"function\"){\n\t\t\tbindTapListener(element.toArray(), tapListeners, context)\n\t\t} else if (Element && element instanceof Element){\n\t\t\t//if it's an element, create a TapListener\n\t\t\tvar tap = new TapListener(element, context)\n\t\t\ttapListeners.push(tap)\n\t\t} \n\t}\n\n\t/**\n\t * @param {AudioContext} context The AudioContext to start.\n\t * @param {Array|String|Element|jQuery=} elements For iOS, the list of elements\n\t * to bind tap event listeners\n\t * which will start the AudioContext. If\n\t * no elements are given, it will bind\n\t * to the document.body.\n\t * @param {Function=} callback The callback to invoke when the AudioContext is started.\n\t * @return {Promise} The promise is invoked when the AudioContext\n\t * is started.\n\t */\n\tfunction StartAudioContext(context, elements, callback){\n\n\t\t//the promise is invoked when the AudioContext is started\n\t\tvar promise = new Promise(function(success) {\n\t\t\tonStarted(context, success)\n\t\t})\n\n\t\t// The TapListeners bound to the elements\n\t\tvar tapListeners = []\n\n\t\t// add all the tap listeners\n\t\tif (!elements){\n\t\t\telements = document.body\n\t\t}\n\t\tbindTapListener(elements, tapListeners, context)\n\n\t\t//dispose all these tap listeners when the context is started\n\t\tpromise.then(function(){\n\t\t\tfor (var i = 0; i < tapListeners.length; i++){\n\t\t\t\ttapListeners[i].dispose()\n\t\t\t}\n\t\t\ttapListeners = null\n\n\t\t\tif (callback){\n\t\t\t\tcallback()\n\t\t\t}\n\t\t})\n\n\t\treturn promise\n\t}\n\n\treturn StartAudioContext\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","!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._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\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.numOutputChannels = options.outputChannelCount || 2;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.bufferSize = processorOptions.bufferSize || 1024;\\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) {\\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 this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\\n\\n if (channel === 0) {\\n this.leftBuffers.push(inputChannelCopy);\\n\\n if (this.numInputChannels === 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n } else if (channel === 1 && this.numInputChannels > 1) {\\n this.rightBuffers.push(inputChannelCopy);\\n }\\n }\\n\\n this.recordedSamples += this.bufferSize;\\n }\\n\\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 var _this2 = this;\\n\\n this.leftBuffers = [];\\n this.rightBuffers = [];\\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this2.bufferSize);\\n });\\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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar SoundFileProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\\n\\n function SoundFileProcessor(options) {\\n var _this;\\n\\n _classCallCheck(this, SoundFileProcessor);\\n\\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\\n var processorOptions = options.processorOptions || {};\\n _this.bufferSize = processorOptions.bufferSize || 256;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\\n return _this;\\n }\\n\\n _createClass(SoundFileProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs) {\\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\\n\\n this.inputRingBuffer.push([input[0]]);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n var inputChannel = this.inputRingBufferArraySequence[0];\\n var position = inputChannel[inputChannel.length - 1] || 0;\\n this.port.postMessage({\\n name: 'position',\\n position: position\\n });\\n }\\n\\n return true;\\n }\\n }]);\\n\\n return SoundFileProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);\"","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 _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\\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\\n// import dependencies via preval.require so that they're available as values at compile time\\nvar processorNames = {\\n \\\"recorderProcessor\\\": \\\"recorder-processor\\\",\\n \\\"soundFileProcessor\\\": \\\"sound-file-processor\\\",\\n \\\"amplitudeProcessor\\\": \\\"amplitude-processor\\\"\\n};\\nvar RingBuffer = {\\n \\\"default\\\":\\n /*#__PURE__*/\\n function () {\\n /**\\n * @constructor\\n * @param {number} length Buffer length in frames.\\n * @param {number} channelCount Buffer channel count.\\n */\\n function RingBuffer(length, channelCount) {\\n _classCallCheck(this, RingBuffer);\\n\\n this._readIndex = 0;\\n this._writeIndex = 0;\\n this._framesAvailable = 0;\\n this._channelCount = channelCount;\\n this._length = length;\\n this._channelData = [];\\n\\n for (var i = 0; i < this._channelCount; ++i) {\\n this._channelData[i] = new Float32Array(length);\\n }\\n }\\n /**\\n * Getter for Available frames in buffer.\\n *\\n * @return {number} Available frames in buffer.\\n */\\n\\n\\n _createClass(RingBuffer, [{\\n key: \\\"push\\\",\\n\\n /**\\n * Push a sequence of Float32Arrays to buffer.\\n *\\n * @param {array} arraySequence A sequence of Float32Arrays.\\n */\\n value: function push(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // Transfer data from the |arraySequence| storage to the internal buffer.\\n var sourceLength = arraySequence[0] ? arraySequence[0].length : 0;\\n\\n for (var i = 0; i < sourceLength; ++i) {\\n var writeIndex = (this._writeIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\\n }\\n }\\n\\n this._writeIndex += sourceLength;\\n\\n if (this._writeIndex >= this._length) {\\n this._writeIndex = 0;\\n } // For excessive frames, the buffer will be overwritten.\\n\\n\\n this._framesAvailable += sourceLength;\\n\\n if (this._framesAvailable > this._length) {\\n this._framesAvailable = this._length;\\n }\\n }\\n /**\\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\\n *\\n * @param {array} arraySequence An array of Float32Arrays.\\n */\\n\\n }, {\\n key: \\\"pull\\\",\\n value: function pull(arraySequence) {\\n // The channel count of arraySequence and the length of each channel must\\n // match with this buffer obejct.\\n // If the FIFO is completely empty, do nothing.\\n if (this._framesAvailable === 0) {\\n return;\\n }\\n\\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\\n\\n for (var i = 0; i < destinationLength; ++i) {\\n var readIndex = (this._readIndex + i) % this._length;\\n\\n for (var channel = 0; channel < this._channelCount; ++channel) {\\n arraySequence[channel][i] = this._channelData[channel][readIndex];\\n }\\n }\\n\\n this._readIndex += destinationLength;\\n\\n if (this._readIndex >= this._length) {\\n this._readIndex = 0;\\n }\\n\\n this._framesAvailable -= destinationLength;\\n\\n if (this._framesAvailable < 0) {\\n this._framesAvailable = 0;\\n }\\n }\\n }, {\\n key: \\\"framesAvailable\\\",\\n get: function get() {\\n return this._framesAvailable;\\n }\\n }]);\\n\\n return RingBuffer;\\n }()\\n}[\\\"default\\\"];\\n\\nvar AmplitudeProcessor =\\n/*#__PURE__*/\\nfunction (_AudioWorkletProcesso) {\\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\\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.numOutputChannels = options.outputChannelCount || 1;\\n _this.numInputChannels = processorOptions.numInputChannels || 2;\\n _this.normalize = processorOptions.normalize || false;\\n _this.smoothing = processorOptions.smoothing || 0;\\n _this.bufferSize = processorOptions.bufferSize || 2048;\\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\\n return new Float32Array(_this.bufferSize);\\n });\\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 } else if (data.name === 'smoothing') {\\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\\n }\\n };\\n\\n return _this;\\n } // TO DO make this stereo / dependent on # of audio channels\\n\\n\\n _createClass(AmplitudeProcessor, [{\\n key: \\\"process\\\",\\n value: function process(inputs, outputs) {\\n var input = inputs[0];\\n var output = outputs[0];\\n var smoothing = this.smoothing;\\n this.inputRingBuffer.push(input);\\n\\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\\n\\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\\n var inputBuffer = this.inputRingBufferArraySequence[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 this.outputRingBuffer.push(this.inputRingBufferArraySequence);\\n } // pull 128 frames out of the ring buffer\\n // if the ring buffer does not have enough frames, the output will be silent\\n\\n\\n this.outputRingBuffer.pull(output);\\n return true;\\n }\\n }]);\\n\\n return AmplitudeProcessor;\\n}(_wrapNativeSuper(AudioWorkletProcessor));\\n\\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);\"","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});","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});","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});","import audiocontext from './audiocontext.js';\n// Master contains the master sound output.\nclass Master {\n constructor() {\n this.input = audiocontext.createGain();\n this.output = audiocontext.createGain();\n\n //put a hard limiter on the output\n this.limiter = audiocontext.createDynamicsCompressor();\n this.limiter.threshold.value = -3;\n this.limiter.ratio.value = 20;\n this.limiter.knee.value = 1;\n\n this.audiocontext = audiocontext;\n\n this.output.disconnect();\n\n // connect input to limiter\n this.input.connect(this.limiter);\n\n // connect limiter to output\n this.limiter.connect(this.output);\n\n // meter is just for global Amplitude / FFT analysis\n this.meter = audiocontext.createGain();\n this.fftMeter = audiocontext.createGain();\n this.output.connect(this.meter);\n this.output.connect(this.fftMeter);\n\n // connect output to destination\n this.output.connect(this.audiocontext.destination);\n\n // an array of all sounds in the sketch\n this.soundArray = [];\n // an array of all musical parts in the sketch\n this.parts = [];\n\n // file extensions to search for\n this.extensions = [];\n }\n}\n\n// create a single instance of the p5Sound / master output for use within this sketch\nconst p5sound = new Master();\n\n/**\n * Returns a number representing the master amplitude (volume) for sound\n * in this sketch.\n *\n * @method getMasterVolume\n * @return {Number} Master amplitude (volume) for sound in this sketch.\n * Should be between 0.0 (silence) and 1.0.\n */\np5.prototype.getMasterVolume = function () {\n return p5sound.output.gain.value;\n};\n\n/**\n *

Scale the output of all sound in this sketch

\n * Scaled between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n *

How This Works: When you load the p5.sound module, it\n * creates a single instance of p5sound. All sound objects in this\n * module output to p5sound before reaching your computer's output.\n * So if you change the amplitude of p5sound, it impacts all of the\n * sound in this module.

\n *\n *

If no value is provided, returns a Web Audio API Gain Node

\n *\n * @method masterVolume\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\np5.prototype.masterVolume = function (vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = p5sound.output.gain.value;\n p5sound.output.gain.cancelScheduledValues(now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(p5sound.output.gain);\n } else {\n // return the Gain Node\n return p5sound.output.gain;\n }\n};\n\n/**\n * `p5.soundOut` is the p5.sound master output. It sends output to\n * the destination of this window's web audio context. It contains\n * Web Audio API nodes including a dyanmicsCompressor (.limiter),\n * and Gain Nodes for .input and .output.\n *\n * @property {Object} soundOut\n */\np5.prototype.soundOut = p5.soundOut = p5sound;\n\n// a silent connection to the DesinationNode\n// which will ensure that anything connected to it\n// will not be garbage collected\np5.soundOut._silentNode = p5sound.audiocontext.createGain();\np5.soundOut._silentNode.gain.value = 0;\np5.soundOut._silentNode.connect(p5sound.audiocontext.destination);\n\nexport default p5sound;\n","import p5sound from './master';\nimport processorNames from './audioWorklet/processorNames';\n/**\n * @for p5\n */\n\n/**\n * Returns a number representing the sample rate, in samples per second,\n * of all sound objects in this audio context. It is determined by the\n * sampling rate of your operating system's sound card, and it is not\n * currently possile to change.\n * It is often 44100, or twice the range of human hearing.\n *\n * @method sampleRate\n * @return {Number} samplerate samples per second\n */\nfunction sampleRate() {\n return p5sound.audiocontext.sampleRate;\n}\n\n/**\n * Returns the closest MIDI note value for\n * a given frequency.\n *\n * @method freqToMidi\n * @param {Number} frequency A freqeuncy, for example, the \"A\"\n * above Middle C is 440Hz\n * @return {Number} MIDI note value\n */\nfunction freqToMidi(f) {\n var mathlog2 = Math.log(f / 440) / Math.log(2);\n var m = Math.round(12 * mathlog2) + 69;\n return m;\n}\n\n/**\n * Returns the frequency value of a MIDI note value.\n * General MIDI treats notes as integers where middle C\n * is 60, C# is 61, D is 62 etc. Useful for generating\n * musical frequencies with oscillators.\n *\n * @method midiToFreq\n * @param {Number} midiNote The number of a MIDI note\n * @return {Number} Frequency value of the given MIDI note\n * @example\n *
\n * let midiNotes = [60, 64, 67, 72];\n * let noteIndex = 0;\n * let midiVal, freq;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * osc = new p5.TriOsc();\n * env = new p5.Envelope();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 10, 20);\n * if (midiVal) {\n * text('MIDI: ' + midiVal, 10, 40);\n * text('Freq: ' + freq, 10, 60);\n * }\n * }\n *\n * function startSound() {\n * // see also: userStartAudio();\n * osc.start();\n *\n * midiVal = midiNotes[noteIndex % midiNotes.length];\n * freq = midiToFreq(midiVal);\n * osc.freq(freq);\n * env.ramp(osc, 0, 1.0, 0);\n *\n * noteIndex++;\n * }\n *
\n */\nfunction midiToFreq(m) {\n return 440 * Math.pow(2, (m - 69) / 12.0);\n}\n\n// This method converts ANSI notes specified as a string \"C4\", \"Eb3\" to a frequency\nfunction noteToFreq(note) {\n if (typeof note !== 'string') {\n return note;\n }\n var wholeNotes = { A: 21, B: 23, C: 24, D: 26, E: 28, F: 29, G: 31 };\n var value = wholeNotes[note[0].toUpperCase()];\n var octave = ~~note.slice(-1);\n value += 12 * (octave - 1);\n\n switch (note[1]) {\n case '#':\n value += 1;\n break;\n case 'b':\n value -= 1;\n break;\n default:\n break;\n }\n return midiToFreq(value);\n}\n\n/**\n * List the SoundFile formats that you will include. LoadSound\n * will search your directory for these extensions, and will pick\n * a format that is compatable with the client's web browser.\n * Here is a free online file\n * converter.\n *\n * @method soundFormats\n * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'\n * @example\n *
\n * function preload() {\n * // set the global sound formats\n * soundFormats('mp3', 'ogg');\n *\n * // load either beatbox.mp3, or .ogg, depending on browser\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('sound loaded! tap to play', 10, 20, width - 20);\n * cnv.mousePressed(function() {\n * mySound.play();\n * });\n * }\n *
\n */\n\nfunction soundFormats() {\n // reset extensions array\n p5sound.extensions = [];\n // add extensions\n for (var i = 0; i < arguments.length; i++) {\n arguments[i] = arguments[i].toLowerCase();\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {\n p5sound.extensions.push(arguments[i]);\n } else {\n throw arguments[i] + ' is not a valid sound format!';\n }\n }\n}\n\nfunction disposeSound() {\n for (var i = 0; i < p5sound.soundArray.length; i++) {\n p5sound.soundArray[i].dispose();\n }\n}\n\nfunction _checkFileFormats(paths) {\n var path;\n // if path is a single string, check to see if extension is provided\n if (typeof paths === 'string') {\n path = paths;\n // see if extension is provided\n var extTest = path.split('.').pop();\n // if an extension is provided...\n if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {\n if (!p5.prototype.isFileSupported(extTest)) {\n var pathSplit = path.split('.');\n var pathCore = pathSplit[pathSplit.length - 1];\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n pathCore = '';\n if (pathSplit.length === 2) {\n pathCore += pathSplit[0];\n }\n for (let i = 1; i <= pathSplit.length - 2; i++) {\n var p = pathSplit[i];\n pathCore += '.' + p;\n }\n path = pathCore += '.';\n path = path += extension;\n break;\n }\n }\n }\n }\n // if no extension is provided...\n else {\n for (let i = 0; i < p5sound.extensions.length; i++) {\n const extension = p5sound.extensions[i];\n const supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n path = path + '.' + extension;\n break;\n }\n }\n }\n } // end 'if string'\n\n // path can either be a single string, or an array\n else if (typeof paths === 'object') {\n for (var i = 0; i < paths.length; i++) {\n var extension = paths[i].split('.').pop();\n var supported = p5.prototype.isFileSupported(extension);\n if (supported) {\n // console.log('.'+extension + ' is ' + supported +\n // ' supported by your browser.');\n path = paths[i];\n break;\n }\n }\n }\n return path;\n}\n\n/**\n * Used by Osc and Envelope to chain signal math\n */\nfunction _mathChain(o, math, thisChain, nextChain, type) {\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n o.mathOps[i].dispose();\n thisChain = i;\n if (thisChain < o.mathOps.length - 1) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n o.mathOps[thisChain - 1].disconnect();\n o.mathOps[thisChain - 1].connect(math);\n math.connect(nextChain);\n o.mathOps[thisChain] = math;\n return o;\n}\n\n// helper methods to convert audio file as .wav format,\n// will use as saving .wav file and saving blob object\n// Thank you to Matt Diamond's RecorderJS (MIT License)\n// https://github.com/mattdiamond/Recorderjs\nfunction convertToWav(audioBuffer) {\n var leftChannel, rightChannel;\n leftChannel = audioBuffer.getChannelData(0);\n\n // handle mono files\n if (audioBuffer.numberOfChannels > 1) {\n rightChannel = audioBuffer.getChannelData(1);\n } else {\n rightChannel = leftChannel;\n }\n\n var interleaved = interleave(leftChannel, rightChannel);\n\n // create the buffer and view to create the .WAV file\n var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);\n var view = new window.DataView(buffer);\n\n // write the WAV container,\n // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf\n\n // RIFF chunk descriptor\n writeUTFBytes(view, 0, 'RIFF');\n view.setUint32(4, 36 + interleaved.length * 2, true);\n writeUTFBytes(view, 8, 'WAVE');\n // FMT sub-chunk\n writeUTFBytes(view, 12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n // stereo (2 channels)\n view.setUint16(22, 2, true);\n view.setUint32(24, p5sound.audiocontext.sampleRate, true);\n view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true);\n view.setUint16(32, 4, true);\n view.setUint16(34, 16, true);\n // data sub-chunk\n writeUTFBytes(view, 36, 'data');\n view.setUint32(40, interleaved.length * 2, true);\n\n // write the PCM samples\n var lng = interleaved.length;\n var index = 44;\n var volume = 1;\n for (var i = 0; i < lng; i++) {\n view.setInt16(index, interleaved[i] * (0x7fff * volume), true);\n index += 2;\n }\n\n return view;\n}\n\n// helper methods to save waves\nfunction interleave(leftChannel, rightChannel) {\n var length = leftChannel.length + rightChannel.length;\n var result = new Float32Array(length);\n\n var inputIndex = 0;\n\n for (var index = 0; index < length; ) {\n result[index++] = leftChannel[inputIndex];\n result[index++] = rightChannel[inputIndex];\n inputIndex++;\n }\n return result;\n}\n\nfunction writeUTFBytes(view, offset, string) {\n var lng = string.length;\n for (var i = 0; i < lng; i++) {\n view.setUint8(offset + i, string.charCodeAt(i));\n }\n}\n\nfunction safeBufferSize(idealBufferSize) {\n let bufferSize = idealBufferSize;\n\n // if the AudioWorkletNode is actually a ScriptProcessorNode created via polyfill,\n // make sure that our chosen buffer size isn't smaller than the buffer size automatically\n // selected by the polyfill\n // reference: https://github.com/GoogleChromeLabs/audioworklet-polyfill/issues/13#issuecomment-425014930\n let tempAudioWorkletNode = new AudioWorkletNode(\n p5sound.audiocontext,\n processorNames.soundFileProcessor\n );\n if (tempAudioWorkletNode instanceof ScriptProcessorNode) {\n bufferSize = tempAudioWorkletNode.bufferSize;\n }\n tempAudioWorkletNode.disconnect();\n tempAudioWorkletNode = null;\n\n return bufferSize;\n}\n\n/**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device.\n * For uploading audio to a server, use\n * `p5.SoundFile.saveBlob`.\n *\n * @for p5\n * @method saveSound\n * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save\n * @param {String} fileName name of the resulting .wav file.\n */\n// add to p5.prototype as this is used by the p5 `save()` method.\nfunction saveSound(soundFile, fileName) {\n const dataView = convertToWav(soundFile.buffer);\n p5.prototype.writeFile([dataView], fileName, 'wav');\n}\n\nexport {\n sampleRate,\n freqToMidi,\n midiToFreq,\n noteToFreq,\n soundFormats,\n disposeSound,\n _checkFileFormats,\n _mathChain,\n convertToWav,\n interleave,\n writeUTFBytes,\n safeBufferSize,\n saveSound,\n};\n","/*\n Helper function to generate an error\n with a custom stack trace that points to the sketch\n and removes other parts of the stack trace.\n\n @private\n @class customError\n @constructor\n @param {String} name custom error name\n @param {String} errorTrace custom error trace\n @param {String} failedPath path to the file that failed to load\n @property {String} name custom error name\n @property {String} message custom error message\n @property {String} stack trace the error back to a line in the user's sketch.\n Note: this edits out stack trace within p5.js and p5.sound.\n @property {String} originalStack unedited, original stack trace\n @property {String} failedPath path to the file that failed to load\n @return {Error} returns a custom Error object\n */\nvar CustomError = function (name, errorTrace, failedPath) {\n var err = new Error();\n var tempStack, splitStack;\n\n err.name = name;\n err.originalStack = err.stack + errorTrace;\n tempStack = err.stack + errorTrace;\n err.failedPath = failedPath;\n\n // only print the part of the stack trace that refers to the user code:\n splitStack = tempStack.split('\\n').filter(function (ln) {\n return !ln.match(/(p5.|native code|globalInit)/g);\n });\n err.stack = splitStack.join('\\n');\n\n return err; // TODO: is this really a constructor?\n};\nexport default CustomError;\n","import p5sound from '../master.js';\nconst moduleSources = [\n require('raw-loader!./recorderProcessor').default,\n require('raw-loader!./soundFileProcessor').default,\n require('raw-loader!./amplitudeProcessor').default,\n];\nconst ac = p5sound.audiocontext;\n\nfunction loadAudioWorkletModules() {\n return Promise.all(\n moduleSources.map(function (moduleSrc) {\n const blob = new Blob([moduleSrc], { type: 'application/javascript' });\n const objectURL = URL.createObjectURL(blob);\n return ac.audioWorklet.addModule(objectURL);\n })\n );\n}\n\np5.prototype.registerMethod('init', function () {\n // ensure that a preload function exists so that p5 will wait for preloads to finish\n if (!this.preload && !window.preload) {\n this.preload = function () {};\n }\n\n // use p5's preload system to load necessary AudioWorklet modules before setup()\n this._incrementPreload();\n const onWorkletModulesLoad = function () {\n this._decrementPreload();\n }.bind(this);\n loadAudioWorkletModules().then(onWorkletModulesLoad);\n});\n","import p5sound from './master';\nvar ac = p5sound.audiocontext;\nvar panner;\n// Stereo panner\n// if there is a stereo panner node use it\nif (typeof ac.createStereoPanner !== 'undefined') {\n class Panner {\n constructor(input, output) {\n this.stereoPanner = this.input = ac.createStereoPanner();\n input.connect(this.stereoPanner);\n this.stereoPanner.connect(output);\n }\n\n pan(val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n\n this.stereoPanner.pan.linearRampToValueAtTime(val, t);\n }\n\n //not implemented because stereopanner\n //node does not require this and will automatically\n //convert single channel or multichannel to stereo.\n //tested with single and stereo, not with (>2) multichannel\n inputChannels() {}\n\n connect(obj) {\n this.stereoPanner.connect(obj);\n }\n\n disconnect() {\n if (this.stereoPanner) {\n this.stereoPanner.disconnect();\n }\n }\n }\n\n panner = Panner;\n} else {\n // if there is no createStereoPanner object\n // such as in safari 7.1.7 at the time of writing this\n // use this method to create the effect\n class Panner {\n constructor(input, output, numInputChannels) {\n this.input = ac.createGain();\n input.connect(this.input);\n\n this.left = ac.createGain();\n this.right = ac.createGain();\n this.left.channelInterpretation = 'discrete';\n this.right.channelInterpretation = 'discrete';\n\n // if input is stereo\n if (numInputChannels > 1) {\n this.splitter = ac.createChannelSplitter(2);\n this.input.connect(this.splitter);\n\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n } else {\n this.input.connect(this.left);\n this.input.connect(this.right);\n }\n\n this.output = ac.createChannelMerger(2);\n this.left.connect(this.output, 0, 1);\n this.right.connect(this.output, 0, 0);\n this.output.connect(output);\n }\n\n // -1 is left, +1 is right\n pan(val, tFromNow) {\n var time = tFromNow || 0;\n var t = ac.currentTime + time;\n var v = (val + 1) / 2;\n var rightVal = Math.cos((v * Math.PI) / 2);\n var leftVal = Math.sin((v * Math.PI) / 2);\n this.left.gain.linearRampToValueAtTime(leftVal, t);\n this.right.gain.linearRampToValueAtTime(rightVal, t);\n }\n\n inputChannels(numChannels) {\n if (numChannels === 1) {\n this.input.disconnect();\n this.input.connect(this.left);\n this.input.connect(this.right);\n } else if (numChannels === 2) {\n if (typeof this.splitter === 'undefined') {\n this.splitter = ac.createChannelSplitter(2);\n }\n this.input.disconnect();\n this.input.connect(this.splitter);\n this.splitter.connect(this.left, 1);\n this.splitter.connect(this.right, 0);\n }\n }\n\n connect(obj) {\n this.output.connect(obj);\n }\n\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n }\n panner = Panner;\n}\n\nexport default panner;\n","import CustomError from './errorHandler';\nimport p5sound from './master';\nimport { midiToFreq, convertToWav, safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\nimport Panner from './panner';\n\nconst ac = p5sound.audiocontext;\n\nvar _createCounterBuffer = function (buffer) {\n const len = buffer.length;\n const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate);\n const arrayBuffer = audioBuf.getChannelData(0);\n for (var index = 0; index < len; index++) {\n arrayBuffer[index] = index;\n }\n return audioBuf;\n};\n\n// process peaks\nclass Peak {\n constructor(amp, i) {\n this.sampleIndex = i;\n this.amplitude = amp;\n this.tempos = [];\n this.intervals = [];\n }\n}\n\n// 1. for processPeaks() Function to identify peaks above a threshold\n// returns an array of peak indexes as frames (samples) of the original soundfile\nfunction getPeaksAtThreshold(data, threshold) {\n var peaksObj = {};\n var length = data.length;\n\n for (var i = 0; i < length; i++) {\n if (data[i] > threshold) {\n var amp = data[i];\n var peak = new Peak(amp, i);\n peaksObj[i] = peak;\n // Skip forward ~ 1/8s to get past this peak.\n i += 6000;\n }\n i++;\n }\n return peaksObj;\n}\n\n// 2. for processPeaks()\nfunction countIntervalsBetweenNearbyPeaks(peaksObj) {\n var intervalCounts = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n for (var index = 0; index < peaksArray.length; index++) {\n // find intervals in comparison to nearby peaks\n for (var i = 0; i < 10; i++) {\n var startPeak = peaksObj[peaksArray[index]];\n var endPeak = peaksObj[peaksArray[index + i]];\n\n if (startPeak && endPeak) {\n var startPos = startPeak.sampleIndex;\n var endPos = endPeak.sampleIndex;\n var interval = endPos - startPos;\n\n // add a sample interval to the startPeak in the allPeaks array\n if (interval > 0) {\n startPeak.intervals.push(interval);\n }\n\n // tally the intervals and return interval counts\n var foundInterval = intervalCounts.some(function (intervalCount) {\n if (intervalCount.interval === interval) {\n intervalCount.count++;\n return intervalCount;\n }\n });\n\n // store with JSON like formatting\n if (!foundInterval) {\n intervalCounts.push({\n interval: interval,\n count: 1,\n });\n }\n }\n }\n }\n\n return intervalCounts;\n}\n\n// 3. for processPeaks --> find tempo\nfunction groupNeighborsByTempo(intervalCounts, sampleRate) {\n var tempoCounts = [];\n\n intervalCounts.forEach(function (intervalCount) {\n try {\n // Convert an interval to tempo\n var theoreticalTempo = Math.abs(\n 60 / (intervalCount.interval / sampleRate)\n );\n\n theoreticalTempo = mapTempo(theoreticalTempo);\n\n var foundTempo = tempoCounts.some(function (tempoCount) {\n if (tempoCount.tempo === theoreticalTempo)\n return (tempoCount.count += intervalCount.count);\n });\n if (!foundTempo) {\n if (isNaN(theoreticalTempo)) {\n return;\n }\n tempoCounts.push({\n tempo: Math.round(theoreticalTempo),\n count: intervalCount.count,\n });\n }\n } catch (e) {\n throw e;\n }\n });\n\n return tempoCounts;\n}\n\n// 4. for processPeaks - get peaks at top tempo\nfunction getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {\n var peaksAtTopTempo = [];\n var peaksArray = Object.keys(peaksObj).sort();\n\n // TO DO: filter out peaks that have the tempo and return\n for (var i = 0; i < peaksArray.length; i++) {\n var key = peaksArray[i];\n var peak = peaksObj[key];\n\n for (var j = 0; j < peak.intervals.length; j++) {\n var intervalBPM = Math.round(\n Math.abs(60 / (peak.intervals[j] / sampleRate))\n );\n\n intervalBPM = mapTempo(intervalBPM);\n\n if (Math.abs(intervalBPM - tempo) < bpmVariance) {\n // convert sampleIndex to seconds\n peaksAtTopTempo.push(peak.sampleIndex / sampleRate);\n }\n }\n }\n\n // filter out peaks that are very close to each other\n peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) {\n var dif = arr[index + 1] - peakTime;\n if (dif > 0.01) {\n return true;\n }\n });\n\n return peaksAtTopTempo;\n}\n\n// helper function for processPeaks\nfunction mapTempo(theoreticalTempo) {\n // these scenarios create infinite while loop\n if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) {\n return;\n }\n\n // Adjust the tempo to fit within the 90-180 BPM range\n while (theoreticalTempo < 90) theoreticalTempo *= 2;\n while (theoreticalTempo > 180 && theoreticalTempo > 90) theoreticalTempo /= 2;\n\n return theoreticalTempo;\n}\n\n/*** SCHEDULE EVENTS ***/\n\n// Cue inspired by JavaScript setTimeout, and the\n// Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org\nclass Cue {\n constructor(callback, time, id, val) {\n this.callback = callback;\n this.time = time;\n this.id = id;\n this.val = val;\n }\n}\n\n// event handler to remove references to the bufferSourceNode when it is done playing\nfunction _clearOnEnd(e) {\n const thisBufferSourceNode = e.target;\n const soundFile = this;\n\n // delete this.bufferSourceNode from the sources array when it is done playing:\n thisBufferSourceNode._playing = false;\n thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd);\n\n // call the onended callback\n soundFile._onended(soundFile);\n\n // delete bufferSourceNode(s) in soundFile.bufferSourceNodes\n // iterate in reverse order because the index changes by splice\n soundFile.bufferSourceNodes\n .map((_, i) => i)\n .reverse()\n .forEach(function (i) {\n const n = soundFile.bufferSourceNodes[i];\n\n if (n._playing === false) {\n soundFile.bufferSourceNodes.splice(i, 1);\n }\n });\n\n if (soundFile.bufferSourceNodes.length === 0) {\n soundFile._playing = false;\n }\n}\n\n/**\n *

SoundFile object with a path to a file.

\n *\n *

The p5.SoundFile may not be available immediately because\n * it loads the file information asynchronously.

\n *\n *

To do something with the sound as soon as it loads\n * pass the name of a function as the second parameter.

\n *\n *

Only one file path is required. However, audio file formats\n * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all\n * web browsers. If you want to ensure compatability, instead of a single\n * file path, you may include an Array of filepaths, and the browser will\n * choose a format that works.

\n *\n * @class p5.SoundFile\n * @constructor\n * @param {String|Array} path path to a sound file (String). Optionally,\n * you may include multiple file formats in\n * an array. Alternately, accepts an object\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if file fails to\n * load. This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @param {Function} [whileLoadingCallback] Name of a function to call while file\n * is loading. That function will\n * receive progress of the request to\n * load the sound file\n * (between 0 and 1) as its first\n * parameter. This progress\n * does not account for the additional\n * time needed to decode the audio data.\n *\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\nclass SoundFile {\n constructor(paths, onload, onerror, whileLoading) {\n if (typeof paths !== 'undefined') {\n if (typeof paths === 'string' || typeof paths[0] === 'string') {\n var path = p5.prototype._checkFileFormats(paths);\n this.url = path;\n } else if (typeof paths === 'object') {\n if (\n !(window.File && window.FileReader && window.FileList && window.Blob)\n ) {\n // The File API isn't supported in this browser\n throw 'Unable to load file because the File API is not supported';\n }\n }\n\n // if type is a p5.File...get the actual file\n if (paths.file) {\n paths = paths.file;\n }\n\n this.file = paths;\n }\n\n // private _onended callback, set by the method: onended(callback)\n this._onended = function () {};\n\n this._looping = false;\n this._playing = false;\n this._paused = false;\n this._pauseTime = 0;\n\n // cues for scheduling events with addCue() removeCue()\n this._cues = [];\n this._cueIDCounter = 0;\n\n // position of the most recently played sample\n this._lastPos = 0;\n this._counterNode = null;\n this._workletNode = null;\n\n // array of sources so that they can all be stopped!\n this.bufferSourceNodes = [];\n\n // current source\n this.bufferSourceNode = null;\n\n this.buffer = null;\n this.playbackRate = 1;\n\n this.input = p5sound.audiocontext.createGain();\n this.output = p5sound.audiocontext.createGain();\n\n this.reversed = false;\n\n // start and end of playback / loop\n this.startTime = 0;\n this.endTime = null;\n this.pauseTime = 0;\n\n // \"restart\" would stop playback before retriggering\n this.mode = 'sustain';\n\n // time that playback was started, in millis\n this.startMillis = null;\n\n // stereo panning\n this.panPosition = 0.0;\n this.panner = new Panner(this.output, p5sound.input, 2);\n\n // it is possible to instantiate a soundfile with no path\n if (this.url || this.file) {\n this.load(onload, onerror);\n }\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n\n if (typeof whileLoading === 'function') {\n this._whileLoading = whileLoading;\n } else {\n this._whileLoading = function () {};\n }\n\n this._clearOnEnd = _clearOnEnd.bind(this);\n\n // same as setVolume, to match Processing Sound\n this.amp = this.setVolume;\n\n // these are the same thing\n this.fade = this.setVolume;\n }\n\n /**\n * This is a helper function that the p5.SoundFile calls to load\n * itself. Accepts a callback (the name of another function)\n * as an optional parameter.\n *\n * @private\n * @for p5.SoundFile\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is an error\n */\n load(callback, errorCallback) {\n var self = this;\n var errorTrace = new Error().stack;\n\n if (this.url !== undefined && this.url !== '') {\n var request = new XMLHttpRequest();\n request.addEventListener(\n 'progress',\n function (evt) {\n self._updateProgress(evt);\n },\n false\n );\n request.open('GET', this.url, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on sucess loading file:\n if (!self.panner) return;\n ac.decodeAudioData(\n request.response,\n // success decoding buffer:\n function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n if (!self.panner) return;\n var err = new CustomError(\n 'decodeAudioData',\n errorTrace,\n self.url\n );\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n if (!self.panner) return;\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadSound', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n };\n\n request.send();\n } else if (this.file !== undefined) {\n var reader = new FileReader();\n reader.onload = function () {\n if (!self.panner) return;\n ac.decodeAudioData(reader.result, function (buff) {\n if (!self.panner) return;\n self.buffer = buff;\n self.panner.inputChannels(buff.numberOfChannels);\n if (callback) {\n callback(self);\n }\n });\n };\n reader.onerror = function (e) {\n if (!self.panner) return;\n if (onerror) {\n onerror(e);\n }\n };\n reader.readAsArrayBuffer(this.file);\n }\n }\n\n // TO DO: use this method to create a loading bar that shows progress during file upload/decode.\n _updateProgress(evt) {\n if (evt.lengthComputable) {\n var percentComplete = (evt.loaded / evt.total) * 0.99;\n this._whileLoading(percentComplete, evt);\n // ...\n } else {\n // Unable to compute progress information since the total size is unknown\n this._whileLoading('size unknown');\n }\n }\n\n /**\n * Returns true if the sound file finished loading successfully.\n *\n * @method isLoaded\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isLoaded() {\n if (this.buffer) {\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Play the p5.SoundFile\n *\n * @method play\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now).\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) amplitude (volume)\n * of playback\n * @param {Number} [cueStart] (optional) cue start time in seconds\n * @param {Number} [duration] (optional) duration of playback in seconds\n */\n play(startTime, rate, amp, _cueStart, duration) {\n if (!this.output) {\n console.warn('SoundFile.play() called after dispose');\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var cueStart, cueEnd;\n var time = startTime || 0;\n if (time < 0) {\n time = 0;\n }\n\n time = time + now;\n\n if (typeof rate !== 'undefined') {\n this.rate(rate);\n }\n\n if (typeof amp !== 'undefined') {\n this.setVolume(amp);\n }\n\n // TO DO: if already playing, create array of buffers for easy stop()\n if (this.buffer) {\n // reset the pause time (if it was paused)\n this._pauseTime = 0;\n\n // handle restart playmode\n if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {\n this.bufferSourceNode.stop(time);\n this._counterNode.stop(time);\n }\n\n //dont create another instance if already playing\n if (this.mode === 'untildone' && this.isPlaying()) {\n return;\n }\n // make a new source and counter. They are automatically assigned playbackRate and buffer\n this.bufferSourceNode = this._initSourceNode();\n\n // garbage collect counterNode and create a new one\n delete this._counterNode;\n this._counterNode = this._initCounterNode();\n\n if (_cueStart) {\n if (_cueStart >= 0 && _cueStart < this.buffer.duration) {\n // this.startTime = cueStart;\n cueStart = _cueStart;\n } else {\n throw 'start time out of range';\n }\n } else {\n cueStart = 0;\n }\n\n if (duration) {\n // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error\n duration =\n duration <= this.buffer.duration - cueStart\n ? duration\n : this.buffer.duration;\n }\n\n // if it was paused, play at the pause position\n if (this._paused) {\n this.bufferSourceNode.start(time, this.pauseTime, duration);\n this._counterNode.start(time, this.pauseTime, duration);\n } else {\n this.bufferSourceNode.start(time, cueStart, duration);\n this._counterNode.start(time, cueStart, duration);\n }\n\n this._playing = true;\n this._paused = false;\n\n // add source to sources array, which is used in stopAll()\n this.bufferSourceNodes.push(this.bufferSourceNode);\n this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;\n\n this.bufferSourceNode.addEventListener('ended', this._clearOnEnd);\n }\n // If soundFile hasn't loaded the buffer yet, throw an error\n else {\n throw 'not ready to play file, buffer has yet to load. Try preload()';\n }\n\n // if looping, will restart at original time\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n\n if (this._looping === true) {\n cueEnd = duration ? duration : cueStart - 0.000000000000001;\n this.bufferSourceNode.loopStart = cueStart;\n this.bufferSourceNode.loopEnd = cueEnd;\n this._counterNode.loopStart = cueStart;\n this._counterNode.loopEnd = cueEnd;\n }\n }\n\n /**\n * p5.SoundFile has two play modes: restart and\n * sustain. Play Mode determines what happens to a\n * p5.SoundFile if it is triggered while in the middle of playback.\n * In sustain mode, playback will continue simultaneous to the\n * new playback. In restart mode, play() will stop playback\n * and start over. With untilDone, a sound will play only if it's\n * not already playing. Sustain is the default mode.\n *\n * @method playMode\n * @for p5.SoundFile\n * @param {String} str 'restart' or 'sustain' or 'untilDone'\n * @example\n *
\n * let mySound;\n * function preload(){\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * noFill();\n * rect(0, height/2, width - 1, height/2 - 1);\n * rect(0, 0, width - 1, height/2);\n * textAlign(CENTER, CENTER);\n * fill(20);\n * text('restart', width/2, 1 * height/4);\n * text('sustain', width/2, 3 * height/4);\n * }\n * function canvasPressed() {\n * if (mouseX < height/2) {\n * mySound.playMode('restart');\n * } else {\n * mySound.playMode('sustain');\n * }\n * mySound.play();\n * }\n *\n *
\n */\n playMode(str) {\n var s = str.toLowerCase();\n\n // if restart, stop all other sounds from playing\n if (s === 'restart' && this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNodes[i].stop(now);\n }\n }\n\n // set play mode to effect future playback\n if (s === 'restart' || s === 'sustain' || s === 'untildone') {\n this.mode = s;\n } else {\n throw 'Invalid play mode. Must be either \"restart\" or \"sustain\"';\n }\n }\n\n /**\n * Pauses a file that is currently playing. If the file is not\n * playing, then nothing will happen.\n *\n * After pausing, .play() will resume from the paused\n * position.\n * If p5.SoundFile had been set to loop before it was paused,\n * it will continue to loop after it is unpaused with .play().\n *\n * @method pause\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @example\n *
\n * let soundFile;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\n pause(startTime) {\n var now = p5sound.audiocontext.currentTime;\n var time = startTime || 0;\n var pTime = time + now;\n\n if (this.isPlaying() && this.buffer && this.bufferSourceNode) {\n this._paused = true;\n this._playing = false;\n\n this.pauseTime = this.currentTime();\n this.bufferSourceNode.stop(pTime);\n this._counterNode.stop(pTime);\n\n this._pauseTime = this.currentTime();\n // TO DO: make sure play() still starts from orig start position\n } else {\n this._pauseTime = 0;\n }\n }\n\n /**\n * Loop the p5.SoundFile. Accepts optional parameters to set the\n * playback rate, playback volume, loopStart, loopEnd.\n *\n * @method loop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * seconds from now\n * @param {Number} [rate] (optional) playback rate\n * @param {Number} [amp] (optional) playback volume\n * @param {Number} [cueLoopStart] (optional) startTime in seconds\n * @param {Number} [duration] (optional) loop duration in seconds\n * @example\n *
\n * let soundFile;\n * let loopStart = 0.5;\n * let loopDuration = 0.2;\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play, release to pause', 10, 20, width - 20);\n * }\n * function canvasPressed() {\n * soundFile.loop();\n * background(0, 200, 50);\n * }\n * function mouseReleased() {\n * soundFile.pause();\n * background(220);\n * }\n * \n *
\n */\n loop(startTime, rate, amp, loopStart, duration) {\n this._looping = true;\n this.play(startTime, rate, amp, loopStart, duration);\n }\n\n /**\n * Set a p5.SoundFile's looping flag to true or false. If the sound\n * is currently playing, this change will take effect when it\n * reaches the end of the current playback.\n *\n * @method setLoop\n * @for p5.SoundFile\n * @param {Boolean} Boolean set looping to true or false\n */\n setLoop(bool) {\n if (bool === true) {\n this._looping = true;\n } else if (bool === false) {\n this._looping = false;\n } else {\n throw 'Error: setLoop accepts either true or false';\n }\n if (this.bufferSourceNode) {\n this.bufferSourceNode.loop = this._looping;\n this._counterNode.loop = this._looping;\n }\n }\n\n /**\n * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.\n *\n * @method isLooping\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isLooping() {\n if (!this.bufferSourceNode) {\n return false;\n }\n if (this._looping === true && this.isPlaying() === true) {\n return true;\n }\n return false;\n }\n\n /**\n * Returns true if a p5.SoundFile is playing, false if not (i.e.\n * paused or stopped).\n *\n * @method isPlaying\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isPlaying() {\n return this._playing;\n }\n\n /**\n * Returns true if a p5.SoundFile is paused, false if not (i.e.\n * playing or stopped).\n *\n * @method isPaused\n * @for p5.SoundFile\n * @return {Boolean}\n */\n isPaused() {\n return this._paused;\n }\n\n /**\n * Stop soundfile playback.\n *\n * @method stop\n * @for p5.SoundFile\n * @param {Number} [startTime] (optional) schedule event to occur\n * in seconds from now\n */\n stop(timeFromNow) {\n var time = timeFromNow || 0;\n\n if (this.mode === 'sustain' || this.mode === 'untildone') {\n this.stopAll(time);\n this._playing = false;\n this.pauseTime = 0;\n this._paused = false;\n } else if (this.buffer && this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n this.pauseTime = 0;\n this.bufferSourceNode.stop(now + t);\n this._counterNode.stop(now + t);\n this._playing = false;\n this._paused = false;\n }\n }\n\n /**\n * Stop playback on all of this soundfile's sources.\n * @private\n */\n stopAll(_time) {\n var now = p5sound.audiocontext.currentTime;\n var time = _time || 0;\n if (this.buffer && this.bufferSourceNode) {\n for (var i in this.bufferSourceNodes) {\n const bufferSourceNode = this.bufferSourceNodes[i];\n if (bufferSourceNode) {\n try {\n bufferSourceNode.stop(now + time);\n } catch (e) {\n // this was throwing errors only on Safari\n }\n }\n }\n this._counterNode.stop(now + time);\n this._onended(this);\n }\n }\n\n getVolume() {\n return this.output.gain.value;\n }\n\n /**\n * Set the stereo panning of a p5.sound object to\n * a floating point number between -1.0 (left) and 1.0 (right).\n * Default is 0.0 (center).\n *\n * @method pan\n * @for p5.SoundFile\n * @param {Number} [panValue] Set the stereo panner\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @example\n *
\n * let ballX = 0;\n * let soundFile;\n *\n * function preload() {\n * soundFormats('ogg', 'mp3');\n * soundFile = loadSound('assets/beatbox.mp3');\n * }\n *\n * function draw() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * ballX = constrain(mouseX, 0, width);\n * ellipse(ballX, height/2, 20, 20);\n * }\n *\n * function canvasPressed(){\n * // map the ball's x location to a panning degree\n * // between -1.0 (left) and 1.0 (right)\n * let panning = map(ballX, 0., width,-1.0, 1.0);\n * soundFile.pan(panning);\n * soundFile.play();\n * }\n *
\n */\n pan(pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n }\n\n /**\n * Returns the current stereo pan position (-1.0 to 1.0)\n *\n * @method getPan\n * @for p5.SoundFile\n * @return {Number} Returns the stereo pan setting of the Oscillator\n * as a number between -1.0 (left) and 1.0 (right).\n * 0.0 is center and default.\n */\n getPan() {\n return this.panPosition;\n }\n\n /**\n * Set the playback rate of a sound file. Will change the speed and the pitch.\n * Values less than zero will reverse the audio buffer.\n *\n * @method rate\n * @for p5.SoundFile\n * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal,\n * .5 is half-speed, 2.0 is twice as fast.\n * Values less than zero play backwards.\n * @example\n *
\n * let mySound;\n *\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * }\n * function canvasPressed() {\n * mySound.loop();\n * }\n * function mouseReleased() {\n * mySound.pause();\n * }\n * function draw() {\n * background(220);\n *\n * // Set the rate to a range between 0.1 and 4\n * // Changing the rate also alters the pitch\n * let playbackRate = map(mouseY, 0.1, height, 2, 0);\n * playbackRate = constrain(playbackRate, 0.01, 4);\n * mySound.rate(playbackRate);\n *\n * line(0, mouseY, width, mouseY);\n * text('rate: ' + round(playbackRate * 100) + '%', 10, 20);\n * }\n *\n * \n *
\n *\n */\n rate(playbackRate) {\n var reverse = false;\n if (typeof playbackRate === 'undefined') {\n return this.playbackRate;\n }\n\n this.playbackRate = playbackRate;\n\n if (playbackRate === 0) {\n playbackRate = 0.0000000000001;\n } else if (playbackRate < 0 && !this.reversed) {\n playbackRate = Math.abs(playbackRate);\n reverse = true;\n } else if (playbackRate > 0 && this.reversed) {\n reverse = true;\n }\n\n if (this.bufferSourceNode) {\n var now = p5sound.audiocontext.currentTime;\n this.bufferSourceNode.playbackRate.cancelScheduledValues(now);\n this.bufferSourceNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n this._counterNode.playbackRate.cancelScheduledValues(now);\n this._counterNode.playbackRate.linearRampToValueAtTime(\n Math.abs(playbackRate),\n now\n );\n }\n\n if (reverse) {\n this.reverseBuffer();\n }\n return this.playbackRate;\n }\n\n // TO DO: document this\n setPitch(num) {\n var newPlaybackRate = midiToFreq(num) / midiToFreq(60);\n this.rate(newPlaybackRate);\n }\n\n getPlaybackRate() {\n return this.playbackRate;\n }\n\n /**\n * Multiply the output volume (amplitude) of a sound file\n * between 0.0 (silence) and 1.0 (full volume).\n * 1.0 is the maximum amplitude of a digital sound, so multiplying\n * by greater than 1.0 may cause digital distortion. To\n * fade, provide a rampTime parameter. For more\n * complex fades, see the Envelope class.\n *\n * Alternately, you can pass in a signal source such as an\n * oscillator to modulate the amplitude with an audio signal.\n *\n * @method setVolume\n * @for p5.SoundFile\n * @param {Number|Object} volume Volume (amplitude) between 0.0\n * and 1.0 or modulating signal/oscillator\n * @param {Number} [rampTime] Fade for t seconds\n * @param {Number} [timeFromNow] Schedule this event to happen at\n * t seconds in the future\n */\n setVolume(vol, _rampTime, _tFromNow) {\n if (typeof vol === 'number') {\n var rampTime = _rampTime || 0;\n var tFromNow = _tFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now + tFromNow);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n }\n /**\n * Returns the duration of a sound file in seconds.\n *\n * @method duration\n * @for p5.SoundFile\n * @return {Number} The duration of the soundFile in seconds.\n */\n duration() {\n // Return Duration\n if (this.buffer) {\n return this.buffer.duration;\n } else {\n return 0;\n }\n }\n\n /**\n * Return the current position of the p5.SoundFile playhead, in seconds.\n * Time is relative to the normal buffer direction, so if `reverseBuffer`\n * has been called, currentTime will count backwards.\n *\n * @method currentTime\n * @for p5.SoundFile\n * @return {Number} currentTime of the soundFile in seconds.\n */\n currentTime() {\n return this.reversed\n ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate\n : this._lastPos / ac.sampleRate;\n }\n\n /**\n * Move the playhead of a soundfile that is currently playing to a\n * new position and a new duration, in seconds.\n * If none are given, will reset the file to play entire duration\n * from start to finish. To set the position of a soundfile that is\n * not currently playing, use the `play` or `loop` methods.\n *\n * @method jump\n * @for p5.SoundFile\n * @param {Number} cueTime cueTime of the soundFile in seconds.\n * @param {Number} duration duration in seconds.\n */\n jump(cueTime, duration) {\n if (cueTime < 0 || cueTime > this.buffer.duration) {\n throw 'jump time out of range';\n }\n if (duration > this.buffer.duration - cueTime) {\n throw 'end time out of range';\n }\n\n var cTime = cueTime || 0;\n var dur = duration || undefined;\n if (this.isPlaying()) {\n this.stop(0);\n this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);\n }\n }\n\n /**\n * Return the number of channels in a sound file.\n * For example, Mono = 1, Stereo = 2.\n *\n * @method channels\n * @for p5.SoundFile\n * @return {Number} [channels]\n */\n channels() {\n return this.buffer.numberOfChannels;\n }\n\n /**\n * Return the sample rate of the sound file.\n *\n * @method sampleRate\n * @for p5.SoundFile\n * @return {Number} [sampleRate]\n */\n sampleRate() {\n return this.buffer.sampleRate;\n }\n\n /**\n * Return the number of samples in a sound file.\n * Equal to sampleRate * duration.\n *\n * @method frames\n * @for p5.SoundFile\n * @return {Number} [sampleCount]\n */\n frames() {\n return this.buffer.length;\n }\n\n /**\n * Returns an array of amplitude peaks in a p5.SoundFile that can be\n * used to draw a static waveform. Scans through the p5.SoundFile's\n * audio buffer to find the greatest amplitudes. Accepts one\n * parameter, 'length', which determines size of the array.\n * Larger arrays result in more precise waveform visualizations.\n *\n * Inspired by Wavesurfer.js.\n *\n * @method getPeaks\n * @for p5.SoundFile\n * @params {Number} [length] length is the size of the returned array.\n * Larger length results in more precision.\n * Defaults to 5*width of the browser window.\n * @returns {Float32Array} Array of peaks.\n */\n getPeaks(length) {\n if (this.buffer) {\n // set length to window's width if no length is provided\n if (!length) {\n length = window.width * 5;\n }\n if (this.buffer) {\n var buffer = this.buffer;\n var sampleSize = buffer.length / length;\n var sampleStep = ~~(sampleSize / 10) || 1;\n var channels = buffer.numberOfChannels;\n var peaks = new Float32Array(Math.round(length));\n\n for (var c = 0; c < channels; c++) {\n var chan = buffer.getChannelData(c);\n for (var i = 0; i < length; i++) {\n var start = ~~(i * sampleSize);\n var end = ~~(start + sampleSize);\n var max = 0;\n for (var j = start; j < end; j += sampleStep) {\n var value = chan[j];\n if (value > max) {\n max = value;\n // faster than Math.abs\n } else if (-value > max) {\n max = value;\n }\n }\n if (c === 0 || Math.abs(max) > peaks[i]) {\n peaks[i] = max;\n }\n }\n }\n\n return peaks;\n }\n } else {\n throw 'Cannot load peaks yet, buffer is not loaded';\n }\n }\n\n /**\n * Reverses the p5.SoundFile's buffer source.\n * Playback must be handled separately (see example).\n *\n * @method reverseBuffer\n * @for p5.SoundFile\n * @example\n *
\n * let drum;\n * function preload() {\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function canvasPressed() {\n * drum.stop();\n * drum.reverseBuffer();\n * drum.play();\n * }\n * \n *
\n */\n reverseBuffer() {\n if (this.buffer) {\n var currentPos = this._lastPos / ac.sampleRate;\n var curVol = this.getVolume();\n this.setVolume(0, 0.001);\n\n const numChannels = this.buffer.numberOfChannels;\n for (var i = 0; i < numChannels; i++) {\n this.buffer.getChannelData(i).reverse();\n }\n // set reversed flag\n this.reversed = !this.reversed;\n\n if (this.isPlaying() && currentPos) {\n this.jump(this.duration() - currentPos);\n }\n this.setVolume(curVol, 0.001);\n } else {\n throw 'SoundFile is not done loading';\n }\n }\n\n /**\n * Schedule an event to be called when the soundfile\n * reaches the end of a buffer. If the soundfile is\n * playing through once, this will be called when it\n * ends. If it is looping, it will be called when\n * stop is called.\n *\n * @method onended\n * @for p5.SoundFile\n * @param {Function} callback function to call when the\n * soundfile has ended.\n */\n onended(callback) {\n this._onended = callback;\n return this;\n }\n\n add() {\n // TO DO\n }\n\n dispose() {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference to soundfile\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop(now);\n if (this.buffer && this.bufferSourceNode) {\n for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {\n if (this.bufferSourceNodes[i] !== null) {\n this.bufferSourceNodes[i].disconnect();\n try {\n this.bufferSourceNodes[i].stop(now);\n } catch (e) {\n console.warn('no buffer source node to dispose');\n }\n this.bufferSourceNodes[i] = null;\n }\n }\n if (this.isPlaying()) {\n try {\n this._counterNode.stop(now);\n } catch (e) {\n console.log(e);\n }\n this._counterNode = null;\n }\n }\n if (this.output) {\n this.output.disconnect();\n this.output = null;\n }\n if (this.panner) {\n this.panner.disconnect();\n this.panner = null;\n }\n }\n\n /**\n * Connects the output of a p5sound object to input of another\n * p5.sound object. For example, you may connect a p5.SoundFile to an\n * FFT or an Effect. If no parameter is given, it will connect to\n * the master output. Most p5sound objects connect to the master\n * output when they are created.\n *\n * @method connect\n * @for p5.SoundFile\n * @param {Object} [object] Audio object that accepts an input\n */\n connect(unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else {\n if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n } else {\n this.panner.connect(unit);\n }\n }\n }\n\n /**\n * Disconnects the output of this p5sound object.\n *\n * @method disconnect\n * @for p5.SoundFile\n */\n disconnect() {\n if (this.panner) {\n this.panner.disconnect();\n }\n }\n\n /**\n */\n getLevel() {\n console.warn(\n 'p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'\n );\n }\n\n /**\n * Reset the source for this SoundFile to a\n * new path (URL).\n *\n * @method setPath\n * @for p5.SoundFile\n * @param {String} path path to audio file\n * @param {Function} callback Callback\n */\n setPath(p, callback) {\n var path = p5.prototype._checkFileFormats(p);\n this.url = path;\n this.load(callback);\n }\n\n /**\n * Replace the current Audio Buffer with a new Buffer.\n *\n * @method setBuffer\n * @for p5.SoundFile\n * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays\n * will create a stereo source. 1 will create\n * a mono source.\n */\n setBuffer(buf) {\n var numChannels = buf.length;\n var size = buf[0].length;\n var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);\n\n if (!(buf[0] instanceof Float32Array)) {\n buf[0] = new Float32Array(buf[0]);\n }\n\n for (var channelNum = 0; channelNum < numChannels; channelNum++) {\n var channel = newBuffer.getChannelData(channelNum);\n channel.set(buf[channelNum]);\n }\n\n this.buffer = newBuffer;\n\n // set numbers of channels on input to the panner\n this.panner.inputChannels(numChannels);\n }\n\n // initialize counterNode, set its initial buffer and playbackRate\n _initCounterNode() {\n var self = this;\n var now = ac.currentTime;\n var cNode = ac.createBufferSource();\n\n const workletBufferSize = safeBufferSize(256);\n\n // dispose of worklet node if it already exists\n if (self._workletNode) {\n self._workletNode.disconnect();\n delete self._workletNode;\n }\n self._workletNode = new AudioWorkletNode(\n ac,\n processorNames.soundFileProcessor,\n {\n processorOptions: { bufferSize: workletBufferSize },\n }\n );\n self._workletNode.port.onmessage = (event) => {\n if (event.data.name === 'position') {\n // event.data.position should only be 0 when paused\n if (event.data.position === 0) {\n return;\n }\n this._lastPos = event.data.position;\n\n // do any callbacks that have been scheduled\n this._onTimeUpdate(self._lastPos);\n }\n };\n\n // create counter buffer of the same length as self.buffer\n cNode.buffer = _createCounterBuffer(self.buffer);\n\n cNode.playbackRate.setValueAtTime(self.playbackRate, now);\n\n cNode.connect(self._workletNode);\n self._workletNode.connect(p5.soundOut._silentNode);\n\n return cNode;\n }\n\n // initialize sourceNode, set its initial buffer and playbackRate\n _initSourceNode() {\n var bufferSourceNode = ac.createBufferSource();\n bufferSourceNode.buffer = this.buffer;\n bufferSourceNode.playbackRate.value = this.playbackRate;\n bufferSourceNode.connect(this.output);\n return bufferSourceNode;\n }\n\n /**\n * processPeaks returns an array of timestamps where it thinks there is a beat.\n *\n * This is an asynchronous function that processes the soundfile in an offline audio context,\n * and sends the results to your callback function.\n *\n * The process involves running the soundfile through a lowpass filter, and finding all of the\n * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\n * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.\n *\n * @method processPeaks\n * @for p5.SoundFile\n * @param {Function} callback a function to call once this data is returned\n * @param {Number} [initThreshold] initial threshold defaults to 0.9\n * @param {Number} [minThreshold] minimum threshold defaults to 0.22\n * @param {Number} [minPeaks] minimum number of peaks defaults to 200\n * @return {Array} Array of timestamped peaks\n */\n processPeaks(callback, _initThreshold, _minThreshold, _minPeaks) {\n var bufLen = this.buffer.length;\n var sampleRate = this.buffer.sampleRate;\n var buffer = this.buffer;\n var allPeaks = [];\n\n var initialThreshold = _initThreshold || 0.9,\n threshold = initialThreshold,\n minThreshold = _minThreshold || 0.22,\n minPeaks = _minPeaks || 200;\n\n // Create offline context\n var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);\n\n // create buffer source\n var source = offlineContext.createBufferSource();\n source.buffer = buffer;\n\n // Create filter. TO DO: allow custom setting of filter\n var filter = offlineContext.createBiquadFilter();\n filter.type = 'lowpass';\n source.connect(filter);\n filter.connect(offlineContext.destination);\n\n // start playing at time:0\n source.start(0);\n offlineContext.startRendering(); // Render the song\n\n // act on the result\n offlineContext.oncomplete = function (e) {\n if (!self.panner) return;\n var filteredBuffer = e.renderedBuffer;\n var bufferData = filteredBuffer.getChannelData(0);\n\n // step 1:\n // create Peak instances, add them to array, with strength and sampleIndex\n do {\n allPeaks = getPeaksAtThreshold(bufferData, threshold);\n threshold -= 0.005;\n } while (\n Object.keys(allPeaks).length < minPeaks &&\n threshold >= minThreshold\n );\n\n // step 2:\n // find intervals for each peak in the sampleIndex, add tempos array\n var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);\n\n // step 3: find top tempos\n var groups = groupNeighborsByTempo(\n intervalCounts,\n filteredBuffer.sampleRate\n );\n\n // sort top intervals\n var topTempos = groups\n .sort(function (intA, intB) {\n return intB.count - intA.count;\n })\n .splice(0, 5);\n\n // set this SoundFile's tempo to the top tempo ??\n this.tempo = topTempos[0].tempo;\n\n // step 4:\n // new array of peaks at top tempo within a bpmVariance\n var bpmVariance = 5;\n var tempoPeaks = getPeaksAtTopTempo(\n allPeaks,\n topTempos[0].tempo,\n filteredBuffer.sampleRate,\n bpmVariance\n );\n\n callback(tempoPeaks);\n };\n }\n\n /**\n * Schedule events to trigger every time a MediaElement\n * (audio/video) reaches a playback cue point.\n *\n * Accepts a callback function, a time (in seconds) at which to trigger\n * the callback, and an optional parameter for the callback.\n *\n * Time will be passed as the first parameter to the callback function,\n * and param will be the second parameter.\n *\n *\n * @method addCue\n * @for p5.SoundFile\n * @param {Number} time Time in seconds, relative to this media\n * element's playback. For example, to trigger\n * an event every time playback reaches two\n * seconds, pass in the number 2. This will be\n * passed as the first parameter to\n * the callback function.\n * @param {Function} callback Name of a function that will be\n * called at the given time. The callback will\n * receive time and (optionally) param as its\n * two parameters.\n * @param {Object} [value] An object to be passed as the\n * second parameter to the\n * callback function.\n * @return {Number} id ID of this cue,\n * useful for removeCue(id)\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to play', 10, 20);\n *\n * // schedule calls to changeText\n * mySound.addCue(0, changeText, \"hello\" );\n * mySound.addCue(0.5, changeText, \"hello,\" );\n * mySound.addCue(1, changeText, \"hello, p5!\");\n * mySound.addCue(1.5, changeText, \"hello, p5!!\");\n * mySound.addCue(2, changeText, \"hello, p5!!!!!\");\n * }\n *\n * function changeText(val) {\n * background(220);\n * text(val, 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.play();\n * }\n *
\n */\n addCue(time, callback, val) {\n var id = this._cueIDCounter++;\n\n var cue = new Cue(callback, time, id, val);\n this._cues.push(cue);\n\n // if (!this.elt.ontimeupdate) {\n // this.elt.ontimeupdate = this._onTimeUpdate.bind(this);\n // }\n\n return id;\n }\n\n /**\n * Remove a callback based on its ID. The ID is returned by the\n * addCue method.\n *\n * @method removeCue\n * @for p5.SoundFile\n * @param {Number} id ID of the cue, as returned by addCue\n */\n removeCue(id) {\n var cueLength = this._cues.length;\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n if (cue.id === id) {\n this._cues.splice(i, 1);\n break;\n }\n }\n\n if (this._cues.length === 0) {\n // TO DO: remove callback\n // this.elt.ontimeupdate = null\n }\n }\n\n /**\n * Remove all of the callbacks that had originally been scheduled\n * via the addCue method.\n *\n * @method clearCues\n */\n clearCues() {\n this._cues = [];\n // this.elt.ontimeupdate = null;\n }\n\n // private method that checks for cues to be fired if events\n // have been scheduled using addCue(callback, time).\n _onTimeUpdate(position) {\n var playbackTime = position / this.buffer.sampleRate;\n var cueLength = this._cues.length;\n\n for (var i = 0; i < cueLength; i++) {\n var cue = this._cues[i];\n var callbackTime = cue.time;\n var val = cue.val;\n var leftLimit = this._prevUpdateTime || 0;\n var rightLimit = playbackTime;\n if (leftLimit <= callbackTime && callbackTime <= rightLimit) {\n // pass the scheduled callbackTime as parameter to the callback\n cue.callback(val);\n }\n }\n\n this._prevUpdateTime = playbackTime;\n }\n\n /**\n * Save a p5.SoundFile as a .wav file. The browser will prompt the user\n * to download the file to their device. To upload a file to a server, see\n * getBlob\n *\n * @method save\n * @for p5.SoundFile\n * @param {String} [fileName] name of the resulting .wav file.\n * @example\n *
\n * let mySound;\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap to download', 10, 20);\n * }\n *\n * function canvasPressed() {\n * mySound.save('my cool filename');\n * }\n *
\n */\n save(fileName) {\n p5.prototype.saveSound(this, fileName, 'wav');\n }\n\n /**\n * This method is useful for sending a SoundFile to a server. It returns the\n * .wav-encoded audio data as a \"Blob\".\n * A Blob is a file-like data object that can be uploaded to a server\n * with an http request. We'll\n * use the `httpDo` options object to send a POST request with some\n * specific options: we encode the request as `multipart/form-data`,\n * and attach the blob as one of the form values using `FormData`.\n *\n *\n * @method getBlob\n * @for p5.SoundFile\n * @returns {Blob} A file-like data object\n * @example\n *
\n * function preload() {\n * mySound = loadSound('assets/doorbell.mp3');\n * }\n *\n * function setup() {\n * noCanvas();\n * let soundBlob = mySound.getBlob();\n *\n * // Now we can send the blob to a server...\n * let serverUrl = 'https://jsonplaceholder.typicode.com/posts';\n * let httpRequestOptions = {\n * method: 'POST',\n * body: new FormData().append('soundBlob', soundBlob),\n * headers: new Headers({\n * 'Content-Type': 'multipart/form-data'\n * })\n * };\n * httpDo(serverUrl, httpRequestOptions);\n *\n * // We can also create an `ObjectURL` pointing to the Blob\n * let blobUrl = URL.createObjectURL(soundBlob);\n *\n * // The `
\n */\n getBlob() {\n const dataView = convertToWav(this.buffer);\n return new Blob([dataView], { type: 'audio/wav' });\n }\n}\n\n/**\n * loadSound() returns a new p5.SoundFile from a specified\n * path. If called during preload(), the p5.SoundFile will be ready\n * to play in time for setup() and draw(). If called outside of\n * preload, the p5.SoundFile will not be ready immediately, so\n * loadSound accepts a callback as the second parameter. Using a\n * \n * local server is recommended when loading external files.\n *\n * @method loadSound\n * @for p5\n * @param {String|Array} path Path to the sound file, or an array with\n * paths to soundfiles in multiple formats\n * i.e. ['sound.ogg', 'sound.mp3'].\n * Alternately, accepts an object: either\n * from the HTML5 File API, or a p5.File.\n * @param {Function} [successCallback] Name of a function to call once file loads\n * @param {Function} [errorCallback] Name of a function to call if there is\n * an error loading the file.\n * @param {Function} [whileLoading] Name of a function to call while file is loading.\n * This function will receive the percentage loaded\n * so far, from 0.0 to 1.0.\n * @return {SoundFile} Returns a p5.SoundFile\n * @example\n *
\n * let mySound;\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * mySound = loadSound('assets/doorbell');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * text('tap here to play', 10, 20);\n * }\n *\n * function canvasPressed() {\n * // playing a sound file on a user gesture\n * // is equivalent to `userStartAudio()`\n * mySound.play();\n * }\n *
\n */\nfunction loadSound(path, callback, onerror, whileLoading) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n window.alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n\n var self = this;\n var s = new SoundFile(\n path,\n function () {\n if (typeof callback === 'function') {\n callback.apply(self, arguments);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n onerror,\n whileLoading\n );\n\n return s;\n}\n\nexport default SoundFile;\nexport { loadSound };\n","import p5sound from './master';\nimport { safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\n/**\n * Amplitude measures volume between 0.0 and 1.0.\n * Listens to all p5sound by default, or use setInput()\n * to listen to a specific sound source. Accepts an optional\n * smoothing value, which defaults to 0.\n *\n * @class p5.Amplitude\n * @constructor\n * @param {Number} [smoothing] between 0.0 and .999 to smooth\n * amplitude readings (defaults to 0)\n * @example\n *
\n * let sound, amplitude;\n *\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function togglePlay() {\n * if (sound.isPlaying() ){\n * sound.pause();\n * } else {\n * sound.loop();\n *\t\tamplitude = new p5.Amplitude();\n *\t\tamplitude.setInput(sound);\n * }\n * }\n *\n *
\n */\nclass Amplitude {\n constructor(smoothing) {\n // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default\n this.bufferSize = safeBufferSize(2048);\n\n // set audio context\n this.audiocontext = p5sound.audiocontext;\n this._workletNode = new AudioWorkletNode(\n this.audiocontext,\n processorNames.amplitudeProcessor,\n {\n outputChannelCount: [1],\n\n parameterData: { smoothing: smoothing || 0 },\n processorOptions: {\n normalize: false,\n smoothing: smoothing || 0,\n numInputChannels: 2,\n bufferSize: this.bufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'amplitude') {\n this.volume = event.data.volume;\n this.volNorm = event.data.volNorm;\n this.stereoVol = event.data.stereoVol;\n this.stereoVolNorm = event.data.stereoVolNorm;\n }\n }.bind(this);\n\n // for connections\n this.input = this._workletNode;\n\n this.output = this.audiocontext.createGain();\n\n // the variables to return\n this.volume = 0;\n this.volNorm = 0;\n this.stereoVol = [0, 0];\n this.stereoVolNorm = [0, 0];\n\n this.normalize = false;\n\n this._workletNode.connect(this.output);\n this.output.gain.value = 0;\n\n // this may only be necessary because of a Chrome bug\n this.output.connect(this.audiocontext.destination);\n\n // connect to p5sound master output by default, unless set by input()\n p5sound.meter.connect(this._workletNode);\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Connects to the p5sound instance (master output) by default.\n * Optionally, you can pass in a specific source (i.e. a soundfile).\n *\n * @method setInput\n * @for p5.Amplitude\n * @param {soundObject|undefined} [snd] set the sound source\n * (optional, defaults to\n * master output)\n * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0\n * to smooth amplitude readings\n * @example\n *
\n * function preload(){\n * sound1 = loadSound('assets/beat.mp3');\n * sound2 = loadSound('assets/drum.mp3');\n * }\n * function setup(){\n * cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n *\n * amplitude = new p5.Amplitude();\n * amplitude.setInput(sound2);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap to play', 20, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound1.isPlaying() && sound2.isPlaying()) {\n * sound1.stop();\n * sound2.stop();\n * } else {\n * sound1.play();\n * sound2.play();\n * }\n * }\n *
\n */\n setInput(source, smoothing) {\n p5sound.meter.disconnect();\n\n if (smoothing) {\n this._workletNode.parameters.get('smoothing').value = smoothing;\n }\n\n // connect to the master out of p5s instance if no snd is provided\n if (source == null) {\n console.log(\n 'Amplitude input source is not ready! Connecting to master output instead'\n );\n p5sound.meter.connect(this._workletNode);\n }\n\n // connect to the sound if it is available\n else if (source) {\n source.connect(this._workletNode);\n this._workletNode.disconnect();\n this._workletNode.connect(this.output);\n }\n\n // otherwise, connect to the master out of p5s instance (default)\n else {\n p5sound.meter.connect(this._workletNode);\n }\n }\n\n connect(unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(this.panner.connect(p5sound.input));\n }\n }\n\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Returns a single Amplitude reading at the moment it is called.\n * For continuous readings, run in the draw loop.\n *\n * @method getLevel\n * @for p5.Amplitude\n * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)\n * @return {Number} Amplitude as a number between 0.0 and 1.0\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mouseClicked(toggleSound);\n * amplitude = new p5.Amplitude();\n * }\n *\n * function draw() {\n * background(220, 150);\n * textAlign(CENTER);\n * text('tap to play', width/2, 20);\n *\n * let level = amplitude.getLevel();\n * let size = map(level, 0, 1, 0, 200);\n * ellipse(width/2, height/2, size, size);\n * }\n *\n * function toggleSound(){\n * if (sound.isPlaying()) {\n * sound.stop();\n * } else {\n * sound.play();\n * }\n * }\n *
\n */\n getLevel(channel) {\n if (typeof channel !== 'undefined') {\n if (this.normalize) {\n return this.stereoVolNorm[channel];\n } else {\n return this.stereoVol[channel];\n }\n } else if (this.normalize) {\n return this.volNorm;\n } else {\n return this.volume;\n }\n }\n\n /**\n * Determines whether the results of Amplitude.process() will be\n * Normalized. To normalize, Amplitude finds the difference the\n * loudest reading it has processed and the maximum amplitude of\n * 1.0. Amplitude adds this difference to all values to produce\n * results that will reliably map between 0.0 and 1.0. However,\n * if a louder moment occurs, the amount that Normalize adds to\n * all the values will change. Accepts an optional boolean parameter\n * (true or false). Normalizing is off by default.\n *\n * @method toggleNormalize\n * @for p5.Amplitude\n * @param {boolean} [boolean] set normalize to true (1) or false (0)\n */\n toggleNormalize(bool) {\n if (typeof bool === 'boolean') {\n this.normalize = bool;\n } else {\n this.normalize = !this.normalize;\n }\n this._workletNode.port.postMessage({\n name: 'toggleNormalize',\n normalize: this.normalize,\n });\n }\n /**\n * Smooth Amplitude analysis by averaging with the last analysis\n * frame. Off by default.\n *\n * @method smooth\n * @for p5.Amplitude\n * @param {Number} set smoothing from 0.0 <= 1\n */\n smooth(s) {\n if (s >= 0 && s < 1) {\n this._workletNode.port.postMessage({ name: 'smoothing', smoothing: s });\n } else {\n console.log('Error: smoothing must be between 0 and 1');\n }\n }\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n this._workletNode.disconnect();\n delete this._workletNode;\n }\n}\n\nexport default Amplitude;\n","import p5sound from './master';\n\n/**\n *

FFT (Fast Fourier Transform) is an analysis algorithm that\n * isolates individual\n * \n * audio frequencies within a waveform.

\n *\n *

Once instantiated, a p5.FFT object can return an array based on\n * two types of analyses:
• FFT.waveform() computes\n * amplitude values along the time domain. The array indices correspond\n * to samples across a brief moment in time. Each value represents\n * amplitude of the waveform at that sample of time.
\n * • FFT.analyze() computes amplitude values along the\n * frequency domain. The array indices correspond to frequencies (i.e.\n * pitches), from the lowest to the highest that humans can hear. Each\n * value represents amplitude at that slice of the frequency spectrum.\n * Use with getEnergy() to measure amplitude at specific\n * frequencies, or within a range of frequencies.

\n *\n *

FFT analyzes a very short snapshot of sound called a sample\n * buffer. It returns an array of amplitude measurements, referred\n * to as bins. The array is 1024 bins long by default.\n * You can change the bin array length, but it must be a power of 2\n * between 16 and 1024 in order for the FFT algorithm to function\n * correctly. The actual size of the FFT buffer is twice the\n * number of bins, so given a standard sample rate, the buffer is\n * 2048/44100 seconds long.

\n *\n *\n * @class p5.FFT\n * @constructor\n * @param {Number} [smoothing] Smooth results of Freq Spectrum.\n * 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n * @param {Number} [bins] Length of resulting array.\n * Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @example\n *
\n * function preload(){\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mouseClicked(togglePlay);\n * fft = new p5.FFT();\n * sound.amp(0.2);\n * }\n *\n * function draw(){\n * background(220);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h )\n * }\n *\n * let waveform = fft.waveform();\n * noFill();\n * beginShape();\n * stroke(20);\n * for (let i = 0; i < waveform.length; i++){\n * let x = map(i, 0, waveform.length, 0, width);\n * let y = map( waveform[i], -1, 1, 0, height);\n * vertex(x,y);\n * }\n * endShape();\n *\n * text('tap to play', 20, 20);\n * }\n *\n * function togglePlay() {\n * if (sound.isPlaying()) {\n * sound.pause();\n * } else {\n * sound.loop();\n * }\n * }\n *
\n */\nclass FFT {\n constructor(smoothing, bins) {\n this.input = this.analyser = p5sound.audiocontext.createAnalyser();\n\n Object.defineProperties(this, {\n bins: {\n get: function () {\n return this.analyser.fftSize / 2;\n },\n set: function (b) {\n this.analyser.fftSize = b * 2;\n },\n configurable: true,\n enumerable: true,\n },\n smoothing: {\n get: function () {\n return this.analyser.smoothingTimeConstant;\n },\n set: function (s) {\n this.analyser.smoothingTimeConstant = s;\n },\n configurable: true,\n enumerable: true,\n },\n });\n\n // set default smoothing and bins\n this.smooth(smoothing);\n this.bins = bins || 1024;\n\n // default connections to p5sound fftMeter\n p5sound.fftMeter.connect(this.analyser);\n\n this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);\n this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);\n\n // predefined frequency ranges, these will be tweakable\n this.bass = [20, 140];\n this.lowMid = [140, 400];\n this.mid = [400, 2600];\n this.highMid = [2600, 5200];\n this.treble = [5200, 14000];\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Set the input source for the FFT analysis. If no source is\n * provided, FFT will analyze all sound in the sketch.\n *\n * @method setInput\n * @for p5.FFT\n * @param {Object} [source] p5.sound object (or web audio API source node)\n */\n setInput(source) {\n if (!source) {\n p5sound.fftMeter.connect(this.analyser);\n } else {\n if (source.output) {\n source.output.connect(this.analyser);\n } else if (source.connect) {\n source.connect(this.analyser);\n }\n p5sound.fftMeter.disconnect();\n }\n }\n\n /**\n * Returns an array of amplitude values (between -1.0 and +1.0) that represent\n * a snapshot of amplitude readings in a single buffer. Length will be\n * equal to bins (defaults to 1024). Can be used to draw the waveform\n * of a sound.\n *\n * @method waveform\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {String} [precision] If any value is provided, will return results\n * in a Float32 Array which is more precise\n * than a regular array.\n * @return {Array} Array Array of amplitude values (-1 to 1)\n * over time. Array length = bins.\n *\n */\n waveform() {\n var bins, mode;\n var normalArray = new Array();\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n bins = arguments[i];\n this.analyser.fftSize = bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n // getFloatFrequencyData doesnt work in Safari as of 5/2015\n if (mode && !p5.prototype._isSafari()) {\n timeToFloat(this, this.timeDomain);\n this.analyser.getFloatTimeDomainData(this.timeDomain);\n return this.timeDomain;\n } else {\n timeToInt(this, this.timeDomain);\n this.analyser.getByteTimeDomainData(this.timeDomain);\n for (var j = 0; j < this.timeDomain.length; j++) {\n var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);\n normalArray.push(scaled);\n }\n return normalArray;\n }\n }\n\n /**\n * Returns an array of amplitude values (between 0 and 255)\n * across the frequency spectrum. Length is equal to FFT bins\n * (1024 by default). The array indices correspond to frequencies\n * (i.e. pitches), from the lowest to the highest that humans can\n * hear. Each value represents amplitude at that slice of the\n * frequency spectrum. Must be called prior to using\n * getEnergy().\n *\n * @method analyze\n * @for p5.FFT\n * @param {Number} [bins] Must be a power of two between\n * 16 and 1024. Defaults to 1024.\n * @param {Number} [scale] If \"dB,\" returns decibel\n * float measurements between\n * -140 and 0 (max).\n * Otherwise returns integers from 0-255.\n * @return {Array} spectrum Array of energy (amplitude/volume)\n * values across the frequency spectrum.\n * Lowest energy (silence) = 0, highest\n * possible is 255.\n * @example\n *
\n * let osc, fft;\n *\n * function setup(){\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(startSound);\n * osc = new p5.Oscillator();\n * osc.amp(0);\n * fft = new p5.FFT();\n * }\n *\n * function draw(){\n * background(220);\n *\n * let freq = map(mouseX, 0, windowWidth, 20, 10000);\n * freq = constrain(freq, 1, 20000);\n * osc.freq(freq);\n *\n * let spectrum = fft.analyze();\n * noStroke();\n * fill(255, 0, 255);\n * for (let i = 0; i< spectrum.length; i++){\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width / spectrum.length, h );\n * }\n *\n * stroke(255);\n * if (!osc.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text(round(freq)+'Hz', 10, 20);\n * }\n * }\n *\n * function startSound() {\n * osc.start();\n * osc.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * osc.amp(0, 0.2);\n * }\n *
\n *\n *\n */\n analyze() {\n var mode;\n\n for (var i = 0; i < arguments.length; i++) {\n if (typeof arguments[i] === 'number') {\n this.bins = arguments[i];\n this.analyser.fftSize = this.bins * 2;\n }\n if (typeof arguments[i] === 'string') {\n mode = arguments[i];\n }\n }\n\n if (mode && mode.toLowerCase() === 'db') {\n freqToFloat(this);\n this.analyser.getFloatFrequencyData(this.freqDomain);\n return this.freqDomain;\n } else {\n freqToInt(this, this.freqDomain);\n this.analyser.getByteFrequencyData(this.freqDomain);\n var normalArray = Array.apply([], this.freqDomain);\n\n return normalArray;\n }\n }\n\n /**\n * Returns the amount of energy (volume) at a specific\n * \n * frequency, or the average amount of energy between two\n * frequencies. Accepts Number(s) corresponding\n * to frequency (in Hz), or a \"string\" corresponding to predefined\n * frequency ranges (\"bass\", \"lowMid\", \"mid\", \"highMid\", \"treble\").\n * Returns a range between 0 (no energy/volume at that frequency) and\n * 255 (maximum energy).\n * NOTE: analyze() must be called prior to getEnergy(). analyze()\n * tells the FFT to analyze frequency data, and getEnergy() uses\n * the results to determine the value at a specific frequency or\n * range of frequencies.

\n *\n * @method getEnergy\n * @for p5.FFT\n * @param {Number|String} frequency1 Will return a value representing\n * energy at this frequency. Alternately,\n * the strings \"bass\", \"lowMid\" \"mid\",\n * \"highMid\", and \"treble\" will return\n * predefined frequency ranges.\n * @param {Number} [frequency2] If a second frequency is given,\n * will return average amount of\n * energy that exists between the\n * two frequencies.\n * @return {Number} Energy Energy (volume/amplitude) from\n * 0 and 255.\n *\n */\n getEnergy(frequency1, frequency2) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n\n if (frequency1 === 'bass') {\n frequency1 = this.bass[0];\n frequency2 = this.bass[1];\n } else if (frequency1 === 'lowMid') {\n frequency1 = this.lowMid[0];\n frequency2 = this.lowMid[1];\n } else if (frequency1 === 'mid') {\n frequency1 = this.mid[0];\n frequency2 = this.mid[1];\n } else if (frequency1 === 'highMid') {\n frequency1 = this.highMid[0];\n frequency2 = this.highMid[1];\n } else if (frequency1 === 'treble') {\n frequency1 = this.treble[0];\n frequency2 = this.treble[1];\n }\n\n if (typeof frequency1 !== 'number') {\n throw 'invalid input for getEnergy()';\n } else if (!frequency2) {\n // if only one parameter:\n var index = Math.round((frequency1 / nyquist) * this.freqDomain.length);\n return this.freqDomain[index];\n } else if (frequency1 && frequency2) {\n // if two parameters:\n // if second is higher than first\n if (frequency1 > frequency2) {\n var swap = frequency2;\n frequency2 = frequency1;\n frequency1 = swap;\n }\n var lowIndex = Math.round(\n (frequency1 / nyquist) * this.freqDomain.length\n );\n var highIndex = Math.round(\n (frequency2 / nyquist) * this.freqDomain.length\n );\n\n var total = 0;\n var numFrequencies = 0;\n // add up all of the values for the frequencies\n for (var i = lowIndex; i <= highIndex; i++) {\n total += this.freqDomain[i];\n numFrequencies += 1;\n }\n // divide by total number of frequencies\n var toReturn = total / numFrequencies;\n return toReturn;\n } else {\n throw 'invalid input for getEnergy()';\n }\n }\n\n // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...\n getFreq(freq1, freq2) {\n console.log('getFreq() is deprecated. Please use getEnergy() instead.');\n var x = this.getEnergy(freq1, freq2);\n return x;\n }\n\n /**\n * Returns the\n * \n * spectral centroid of the input signal.\n * NOTE: analyze() must be called prior to getCentroid(). Analyze()\n * tells the FFT to analyze frequency data, and getCentroid() uses\n * the results determine the spectral centroid.

\n *\n * @method getCentroid\n * @for p5.FFT\n * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz.\n *\n *\n * @example\n *
\n * function setup(){\n * cnv = createCanvas(100,100);\n * cnv.mousePressed(userStartAudio);\n * sound = new p5.AudioIn();\n * sound.start();\n * fft = new p5.FFT();\n * sound.connect(fft);\n *}\n *\n *function draw() {\n * if (getAudioContext().state !== 'running') {\n * background(220);\n * text('tap here and enable mic to begin', 10, 20, width - 20);\n * return;\n * }\n * let centroidplot = 0.0;\n * let spectralCentroid = 0;\n *\n * background(0);\n * stroke(0,255,0);\n * let spectrum = fft.analyze();\n * fill(0,255,0); // spectrum is green\n *\n * //draw the spectrum\n * for (let i = 0; i < spectrum.length; i++){\n * let x = map(log(i), 0, log(spectrum.length), 0, width);\n * let h = map(spectrum[i], 0, 255, 0, height);\n * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\n * rect(x, height, rectangle_width, -h )\n * }\n * let nyquist = 22050;\n *\n * // get the centroid\n * spectralCentroid = fft.getCentroid();\n *\n * // the mean_freq_index calculation is for the display.\n * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\n *\n * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\n *\n * stroke(255,0,0); // the line showing where the centroid is will be red\n *\n * rect(centroidplot, 0, width / spectrum.length, height)\n * noStroke();\n * fill(255,255,255); // text is white\n * text('centroid: ', 10, 20);\n * text(round(spectralCentroid)+' Hz', 10, 40);\n *}\n *
\n */\n getCentroid() {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var cumulative_sum = 0;\n var centroid_normalization = 0;\n\n for (var i = 0; i < this.freqDomain.length; i++) {\n cumulative_sum += i * this.freqDomain[i];\n centroid_normalization += this.freqDomain[i];\n }\n\n var mean_freq_index = 0;\n\n if (centroid_normalization !== 0) {\n mean_freq_index = cumulative_sum / centroid_normalization;\n }\n\n var spec_centroid_freq =\n mean_freq_index * (nyquist / this.freqDomain.length);\n return spec_centroid_freq;\n }\n\n /**\n * Smooth FFT analysis by averaging with the last analysis frame.\n *\n * @method smooth\n * @param {Number} smoothing 0.0 < smoothing < 1.0.\n * Defaults to 0.8.\n */\n smooth(s) {\n if (typeof s !== 'undefined') {\n this.smoothing = s;\n }\n return this.smoothing;\n }\n\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.analyser) {\n this.analyser.disconnect();\n delete this.analyser;\n }\n }\n\n /**\n * Returns an array of average amplitude values for a given number\n * of frequency bands split equally. N defaults to 16.\n * NOTE: analyze() must be called prior to linAverages(). Analyze()\n * tells the FFT to analyze frequency data, and linAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method linAverages\n * @for p5.FFT\n * @param {Number} N Number of returned frequency groups\n * @return {Array} linearAverages Array of average amplitude values for each group\n */\n\n linAverages(_N) {\n var N = _N || 16; // This prevents undefined, null or 0 values of N\n\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n var spectrumStep = Math.floor(spectrumLength / N);\n\n var linearAverages = new Array(N);\n // Keep a second index for the current average group and place the values accordingly\n // with only one loop in the spectrum data\n var groupIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n linearAverages[groupIndex] =\n linearAverages[groupIndex] !== undefined\n ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n\n // Increase the group index when the last element of the group is processed\n if (specIndex % spectrumStep === spectrumStep - 1) {\n groupIndex++;\n }\n }\n\n return linearAverages;\n }\n\n /**\n * Returns an array of average amplitude values of the spectrum, for a given\n * set of \n * Octave Bands\n * NOTE: analyze() must be called prior to logAverages(). Analyze()\n * tells the FFT to analyze frequency data, and logAverages() uses\n * the results to group them into a smaller set of averages.

\n *\n * @method logAverages\n * @for p5.FFT\n * @param {Array} octaveBands Array of Octave Bands objects for grouping\n * @return {Array} logAverages Array of average amplitude values for each group\n */\n logAverages(octaveBands) {\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n var spectrum = this.freqDomain;\n var spectrumLength = spectrum.length;\n\n var logAverages = new Array(octaveBands.length);\n // Keep a second index for the current average group and place the values accordingly\n // With only one loop in the spectrum data\n var octaveIndex = 0;\n\n for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {\n var specIndexFrequency = Math.round(\n (specIndex * nyquist) / this.freqDomain.length\n );\n\n // Increase the group index if the current frequency exceeds the limits of the band\n if (specIndexFrequency > octaveBands[octaveIndex].hi) {\n octaveIndex++;\n }\n\n logAverages[octaveIndex] =\n logAverages[octaveIndex] !== undefined\n ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2\n : spectrum[specIndex];\n }\n\n return logAverages;\n }\n\n /**\n * Calculates and Returns the 1/N\n * Octave Bands\n * N defaults to 3 and minimum central frequency to 15.625Hz.\n * (1/3 Octave Bands ~= 31 Frequency Bands)\n * Setting fCtr0 to a central value of a higher octave will ignore the lower bands\n * and produce less frequency groups.\n *\n * @method getOctaveBands\n * @for p5.FFT\n * @param {Number} N Specifies the 1/N type of generated octave bands\n * @param {Number} fCtr0 Minimum central frequency for the lowest band\n * @return {Array} octaveBands Array of octave band objects with their bounds\n */\n getOctaveBands(_N, _fCtr0) {\n var N = _N || 3; // Default to 1/3 Octave Bands\n var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz\n\n var octaveBands = [];\n var lastFrequencyBand = {\n lo: fCtr0 / Math.pow(2, 1 / (2 * N)),\n ctr: fCtr0,\n hi: fCtr0 * Math.pow(2, 1 / (2 * N)),\n };\n octaveBands.push(lastFrequencyBand);\n\n var nyquist = p5sound.audiocontext.sampleRate / 2;\n while (lastFrequencyBand.hi < nyquist) {\n var newFrequencyBand = {};\n newFrequencyBand.lo = lastFrequencyBand.hi;\n newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);\n newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));\n\n octaveBands.push(newFrequencyBand);\n lastFrequencyBand = newFrequencyBand;\n }\n\n return octaveBands;\n }\n}\n\n// helper methods to convert type from float (dB) to int (0-255)\nfunction freqToFloat(fft) {\n if (fft.freqDomain instanceof Float32Array === false) {\n fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction freqToInt(fft) {\n if (fft.freqDomain instanceof Uint8Array === false) {\n fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToFloat(fft) {\n if (fft.timeDomain instanceof Float32Array === false) {\n fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);\n }\n}\nfunction timeToInt(fft) {\n if (fft.timeDomain instanceof Uint8Array === false) {\n fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);\n }\n}\n\nexport default FFT;\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\nimport Panner from './panner';\n// ========================== //\n// SIGNAL MATH FOR MODULATION //\n// ========================== //\n\n// return sigChain(this, scale, thisChain, nextChain, Scale);\nfunction sigChain(o, mathObj, thisChain, nextChain, type) {\n var chainSource = o.oscillator;\n // if this type of math already exists in the chain, replace it\n for (var i in o.mathOps) {\n if (o.mathOps[i] instanceof type) {\n chainSource.disconnect();\n o.mathOps[i].dispose();\n thisChain = i;\n // assume nextChain is output gain node unless...\n if (thisChain < o.mathOps.length - 2) {\n nextChain = o.mathOps[i + 1];\n }\n }\n }\n if (thisChain === o.mathOps.length - 1) {\n o.mathOps.push(nextChain);\n }\n // assume source is the oscillator unless i > 0\n if (i > 0) {\n chainSource = o.mathOps[i - 1];\n }\n chainSource.disconnect();\n chainSource.connect(mathObj);\n mathObj.connect(nextChain);\n o.mathOps[thisChain] = mathObj;\n return o;\n}\n\n/**\n *

Creates a signal that oscillates between -1.0 and 1.0.\n * By default, the oscillation takes the form of a sinusoidal\n * shape ('sine'). Additional types include 'triangle',\n * 'sawtooth' and 'square'. The frequency defaults to\n * 440 oscillations per second (440Hz, equal to the pitch of an\n * 'A' note).

\n *\n *

Set the type of oscillation with setType(), or by instantiating a\n * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc.\n *

\n *\n * @class p5.Oscillator\n * @constructor\n * @param {Number} [freq] frequency defaults to 440Hz\n * @param {String} [type] type of oscillator. Options:\n * 'sine' (default), 'triangle',\n * 'sawtooth', 'square'\n * @example\n *
\n * let osc, playing, freq, amp;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator('sine');\n * }\n *\n * function draw() {\n * background(220)\n * freq = constrain(map(mouseX, 0, width, 100, 500), 100, 500);\n * amp = constrain(map(mouseY, height, 0, 0, 1), 0, 1);\n *\n * text('tap to play', 20, 20);\n * text('freq: ' + freq, 20, 40);\n * text('amp: ' + amp, 20, 60);\n *\n * if (playing) {\n * // smooth the transitions by 0.1 seconds\n * osc.freq(freq, 0.1);\n * osc.amp(amp, 0.1);\n * }\n * }\n *\n * function playOscillator() {\n * // starting an oscillator on a user gesture will enable audio\n * // in browsers that have a strict autoplay policy.\n * // See also: userStartAudio();\n * osc.start();\n * playing = true;\n * }\n *\n * function mouseReleased() {\n * // ramp amplitude to 0 over 0.5 seconds\n * osc.amp(0, 0.5);\n * playing = false;\n * }\n *
\n */\nclass Oscillator {\n constructor(freq, type) {\n if (typeof freq === 'string') {\n let f = type;\n type = freq;\n freq = f;\n }\n if (typeof type === 'number') {\n let f = type;\n type = freq;\n freq = f;\n }\n this.started = false;\n\n // components\n this.phaseAmount = undefined;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.f = freq || 440.0; // frequency\n this.oscillator.type = type || 'sine';\n this.oscillator.frequency.setValueAtTime(\n this.f,\n p5sound.audiocontext.currentTime\n );\n\n // connections\n this.output = p5sound.audiocontext.createGain();\n\n this._freqMods = []; // modulators connected to this oscillator's frequency\n\n // set default output gain to 0.5\n this.output.gain.value = 0.5;\n this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);\n\n this.oscillator.connect(this.output);\n // stereo panning\n this.panPosition = 0.0;\n this.connection = p5sound.input; // connect to p5sound by default\n this.panner = new Panner(this.output, this.connection, 1);\n\n //array of math operation signal chaining\n this.mathOps = [this.output];\n\n // add to the soundArray so we can dispose of the osc later\n p5sound.soundArray.push(this);\n\n // these methods are now the same thing\n this.fade = this.amp;\n }\n\n /**\n * Start an oscillator.\n *\n * Starting an oscillator on a user gesture will enable audio in browsers\n * that have a strict autoplay policy, including Chrome and most mobile\n * devices. See also: `userStartAudio()`.\n *\n * @method start\n * @for p5.Oscillator\n * @param {Number} [time] startTime in seconds from now.\n * @param {Number} [frequency] frequency in Hz.\n */\n start(time, f) {\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n }\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n\n // set old osc free to be garbage collected (memory)\n if (this.oscillator) {\n this.oscillator.disconnect();\n delete this.oscillator;\n }\n\n // var detune = this.oscillator.frequency.value;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.value = Math.abs(freq);\n this.oscillator.type = type;\n // this.oscillator.detune.value = detune;\n this.oscillator.connect(this.output);\n time = time || 0;\n this.oscillator.start(time + p5sound.audiocontext.currentTime);\n this.freqNode = this.oscillator.frequency;\n\n // if other oscillators are already connected to this osc's freq\n for (var i in this._freqMods) {\n if (typeof this._freqMods[i].connect !== 'undefined') {\n this._freqMods[i].connect(this.oscillator.frequency);\n }\n }\n\n this.started = true;\n }\n }\n\n /**\n * Stop an oscillator. Accepts an optional parameter\n * to determine how long (in seconds from now) until the\n * oscillator stops.\n *\n * @method stop\n * @for p5.Oscillator\n * @param {Number} secondsFromNow Time, in seconds from now.\n */\n stop(time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n this.started = false;\n }\n }\n\n /**\n * Set the amplitude between 0 and 1.0. Or, pass in an object\n * such as an oscillator to modulate amplitude with an audio signal.\n *\n * @method amp\n * @for p5.Oscillator\n * @param {Number|Object} vol between 0 and 1.0\n * or a modulating signal/oscillator\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {AudioParam} gain If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's\n * gain/amplitude/volume)\n */\n amp(vol, rampTime = 0, tFromNow = 0) {\n if (typeof vol === 'number') {\n var now = p5sound.audiocontext.currentTime;\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n } else if (vol) {\n vol.connect(this.output.gain);\n } else {\n // return the Gain Node\n return this.output.gain;\n }\n }\n\n /**\n * Returns the value of output gain\n *\n * @method getAmp\n * @for p5.Oscillator\n *\n * @returns {number} Amplitude value between 0.0 and 1.0\n */\n\n getAmp() {\n return this.output.gain.value;\n }\n\n /**\n * Set frequency of an oscillator to a value. Or, pass in an object\n * such as an oscillator to modulate the frequency with an audio signal.\n *\n * @method freq\n * @for p5.Oscillator\n * @param {Number|Object} Frequency Frequency in Hz\n * or modulating signal/oscillator\n * @param {Number} [rampTime] Ramp time (in seconds)\n * @param {Number} [timeFromNow] Schedule this event to happen\n * at x seconds from now\n * @return {AudioParam} Frequency If no value is provided,\n * returns the Web Audio API\n * AudioParam that controls\n * this oscillator's frequency\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playOscillator);\n * osc = new p5.Oscillator(300);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playOscillator() {\n * osc.start();\n * osc.amp(0.5);\n * // start at 700Hz\n * osc.freq(700);\n * // ramp to 60Hz over 0.7 seconds\n * osc.freq(60, 0.7);\n * osc.amp(0, 0.1, 0.7);\n * }\n *
\n */\n freq(val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number' && !isNaN(val)) {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n\n if (rampTime === 0) {\n this.oscillator.frequency.setValueAtTime(val, tFromNow + now);\n } else {\n if (val > 0) {\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n } else {\n this.oscillator.frequency.linearRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n }\n }\n\n // reset phase if oscillator has a phase\n if (this.phaseAmount) {\n this.phase(this.phaseAmount);\n }\n } else if (val) {\n if (val.output) {\n val = val.output;\n }\n val.connect(this.oscillator.frequency);\n\n // keep track of what is modulating this param\n // so it can be re-connected if\n this._freqMods.push(val);\n } else {\n // return the Frequency Node\n return this.oscillator.frequency;\n }\n }\n /**\n * Returns the value of frequency of oscillator\n *\n * @method getFreq\n * @for p5.Oscillator\n * @returns {number} Frequency of oscillator in Hertz\n */\n\n getFreq() {\n return this.oscillator.frequency.value;\n }\n\n /**\n * Set type to 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method setType\n * @for p5.Oscillator\n * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.\n */\n setType(type) {\n this.oscillator.type = type;\n }\n /**\n * Returns current type of oscillator eg. 'sine', 'triangle', 'sawtooth' or 'square'.\n *\n * @method getType\n * @for p5.Oscillator\n * @returns {String} type of oscillator eg . 'sine', 'triangle', 'sawtooth' or 'square'.\n */\n\n getType() {\n return this.oscillator.type;\n }\n\n /**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.Oscillator\n * @param {Object} unit A p5.sound or Web Audio object\n */\n connect(unit) {\n if (!unit) {\n this.panner.connect(p5sound.input);\n } else if (unit.hasOwnProperty('input')) {\n this.panner.connect(unit.input);\n this.connection = unit.input;\n } else {\n this.panner.connect(unit);\n this.connection = unit;\n }\n }\n\n /**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.Oscillator\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n if (this.output) {\n this.output.connect(this.panner);\n }\n }\n this.oscMods = [];\n }\n\n /**\n * Pan between Left (-1) and Right (1)\n *\n * @method pan\n * @for p5.Oscillator\n * @param {Number} panning Number between -1 and 1\n * @param {Number} timeFromNow schedule this event to happen\n * seconds from now\n */\n pan(pval, tFromNow) {\n this.panPosition = pval;\n this.panner.pan(pval, tFromNow);\n }\n\n /**\n * Returns the current value of panPosition , between Left (-1) and Right (1)\n *\n * @method getPan\n * @for p5.Oscillator\n *\n * @returns {number} panPosition of oscillator , between Left (-1) and Right (1)\n */\n\n getPan() {\n return this.panPosition;\n }\n\n // get rid of the oscillator\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.oscillator) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.disconnect();\n this.panner = null;\n this.oscillator = null;\n }\n // if it is a Pulse\n if (this.osc2) {\n this.osc2.dispose();\n }\n }\n\n /**\n * Set the phase of an oscillator between 0.0 and 1.0.\n * In this implementation, phase is a delay time\n * based on the oscillator's current frequency.\n *\n * @method phase\n * @for p5.Oscillator\n * @param {Number} phase float between 0.0 and 1.0\n */\n phase(p) {\n var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f);\n var now = p5sound.audiocontext.currentTime;\n\n this.phaseAmount = p;\n\n if (!this.dNode) {\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n // put the delay node in between output and panner\n this.oscillator.disconnect();\n this.oscillator.connect(this.dNode);\n this.dNode.connect(this.output);\n }\n\n // set delay time to match phase:\n this.dNode.delayTime.setValueAtTime(delayAmt, now);\n }\n\n /**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method again\n * will override the initial add() with a new value.\n *\n * @method add\n * @for p5.Oscillator\n * @param {Number} number Constant number to add\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n *\n */\n add(num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, add, thisChain, nextChain, Add);\n }\n /**\n * Multiply the p5.Oscillator's output amplitude\n * by a fixed value (i.e. turn it up!). Calling this method\n * again will override the initial mult() with a new value.\n *\n * @method mult\n * @for p5.Oscillator\n * @param {Number} number Constant number to multiply\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with multiplied output\n */\n mult(num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, mult, thisChain, nextChain, Mult);\n }\n\n /**\n * Scale this oscillator's amplitude values to a given\n * range, and return the oscillator. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Oscillator\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Oscillator} Oscillator Returns this oscillator\n * with scaled output\n */\n scale(inMin, inMax, outMin, outMax) {\n var mapOutMin, mapOutMax;\n if (arguments.length === 4) {\n mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; //find a way to get rid of p5.prototype ?\n mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; //find a way to get rid of p5.prototype ?\n } else {\n mapOutMin = arguments[0];\n mapOutMax = arguments[1];\n }\n var scale = new Scale(mapOutMin, mapOutMax);\n var thisChain = this.mathOps.length - 1;\n var nextChain = this.output;\n return sigChain(this, scale, thisChain, nextChain, Scale);\n\n // this.output.disconnect();\n // this.output.connect(scale)\n }\n}\n\n// ============================== //\n// SinOsc, TriOsc, SqrOsc, SawOsc //\n// ============================== //\n\n/**\n * Constructor: new p5.SinOsc().\n * This creates a Sine Wave Oscillator and is\n * equivalent to new p5.Oscillator('sine')\n * or creating a p5.Oscillator and then calling\n * its method setType('sine').\n * See p5.Oscillator for methods.\n *\n * @class p5.SinOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass SinOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'sine');\n }\n}\n\n/**\n * Constructor: new p5.TriOsc().\n * This creates a Triangle Wave Oscillator and is\n * equivalent to new p5.Oscillator('triangle')\n * or creating a p5.Oscillator and then calling\n * its method setType('triangle').\n * See p5.Oscillator for methods.\n *\n * @class p5.TriOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass TriOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'triangle');\n }\n}\n\n/**\n * Constructor: new p5.SawOsc().\n * This creates a SawTooth Wave Oscillator and is\n * equivalent to new p5.Oscillator('sawtooth')\n * or creating a p5.Oscillator and then calling\n * its method setType('sawtooth').\n * See p5.Oscillator for methods.\n *\n * @class p5.SawOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass SawOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'sawtooth');\n }\n}\n\n/**\n * Constructor: new p5.SqrOsc().\n * This creates a Square Wave Oscillator and is\n * equivalent to new p5.Oscillator('square')\n * or creating a p5.Oscillator and then calling\n * its method setType('square').\n * See p5.Oscillator for methods.\n *\n * @class p5.SqrOsc\n * @constructor\n * @extends p5.Oscillator\n * @param {Number} [freq] Set the frequency\n */\nclass SqrOsc extends Oscillator {\n constructor(freq) {\n super(freq, 'square');\n }\n}\n\nexport default Oscillator;\nexport { SinOsc, TriOsc, SawOsc, SqrOsc };\n","import p5sound from './master';\nimport Add from 'Tone/signal/Add';\nimport Mult from 'Tone/signal/Multiply';\nimport Scale from 'Tone/signal/Scale';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\n\n/**\n *

Envelopes are pre-defined amplitude distribution over time.\n * Typically, envelopes are used to control the output volume\n * of an object, a series of fades referred to as Attack, Decay,\n * Sustain and Release (\n * ADSR\n * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\n * control an Oscillator's frequency like this: osc.freq(env).

\n *

Use setRange to change the attack/release level.\n * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

\n *

Use the play method to play the entire envelope,\n * the ramp method for a pingable trigger,\n * or triggerAttack/\n * triggerRelease to trigger noteOn/noteOff.

\n *\n * @class p5.Envelope\n * @constructor\n * @example\n *
\n * let t1 = 0.1; // attack time in seconds\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n *\n * let env;\n * let triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * text('tap to play', 20, 20);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope(t1, l1, t2, l2);\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function playSound() {\n * // starting the oscillator ensures that audio is enabled.\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n */\np5.Envelope = function (t1, l1, t2, l2, t3, l3) {\n /**\n * Time until envelope reaches attackLevel\n * @property attackTime\n */\n this.aTime = t1 || 0.1;\n /**\n * Level once attack is complete.\n * @property attackLevel\n */\n this.aLevel = l1 || 1;\n /**\n * Time until envelope reaches decayLevel.\n * @property decayTime\n */\n this.dTime = t2 || 0.5;\n /**\n * Level after decay. The envelope will sustain here until it is released.\n * @property decayLevel\n */\n this.dLevel = l2 || 0;\n /**\n * Duration of the release portion of the envelope.\n * @property releaseTime\n */\n this.rTime = t3 || 0;\n /**\n * Level at the end of the release.\n * @property releaseLevel\n */\n this.rLevel = l3 || 0;\n\n this._rampHighPercentage = 0.98;\n\n this._rampLowPercentage = 0.02;\n\n this.output = p5sound.audiocontext.createGain();\n\n this.control = new TimelineSignal();\n\n this._init(); // this makes sure the envelope starts at zero\n\n this.control.connect(this.output); // connect to the output\n\n this.connection = null; // store connection\n\n //array of math operation signal chaining\n this.mathOps = [this.control];\n\n //whether envelope should be linear or exponential curve\n this.isExponential = false;\n\n // oscillator or buffer source to clear on env complete\n // to save resources if/when it is retriggered\n this.sourceToClear = null;\n\n // set to true if attack is set, then false on release\n this.wasTriggered = false;\n\n // add to the soundArray so we can dispose of the env later\n p5sound.soundArray.push(this);\n};\n\n// this init function just smooths the starting value to zero and gives a start point for the timeline\n// - it was necessary to remove glitches at the beginning.\np5.Envelope.prototype._init = function () {\n var now = p5sound.audiocontext.currentTime;\n var t = now;\n this.control.setTargetAtTime(0.00001, t, 0.001);\n //also, compute the correct time constants\n this._setRampAD(this.aTime, this.dTime);\n};\n\n/**\n * Reset the envelope with a series of time/value pairs.\n *\n * @method set\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds) before level\n * reaches attackLevel\n * @param {Number} attackLevel Typically an amplitude between\n * 0.0 and 1.0\n * @param {Number} decayTime Time\n * @param {Number} decayLevel Amplitude (In a standard ADSR envelope,\n * decayLevel = sustainLevel)\n * @param {Number} releaseTime Release Time (in seconds)\n * @param {Number} releaseLevel Amplitude\n * @example\n *
\n * let attackTime;\n * let l1 = 0.7; // attack level 0.0 to 1.0\n * let t2 = 0.3; // decay time in seconds\n * let l2 = 0.1; // decay level 0.0 to 1.0\n * let l3 = 0.2; // release time in seconds\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n *\n * attackTime = map(mouseX, 0, width, 0.0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 20);\n * }\n *\n * // mouseClick triggers envelope if over canvas\n * function playSound() {\n * env.set(attackTime, l1, t2, l2, l3);\n *\n * triOsc.start();\n * env.play(triOsc);\n * }\n *
\n *\n */\np5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) {\n this.aTime = t1;\n this.aLevel = l1;\n this.dTime = t2 || 0;\n this.dLevel = l2 || 0;\n this.rTime = t3 || 0;\n this.rLevel = l3 || 0;\n\n // set time constants for ramp\n this._setRampAD(t1, t2);\n};\n\n/**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.Envelope\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) {\n this.aTime = aTime;\n this.dTime = dTime || 0;\n\n // lerp\n this.sPercent = sPercent || 0;\n this.dLevel =\n typeof sPercent !== 'undefined'\n ? sPercent * (this.aLevel - this.rLevel) + this.rLevel\n : 0;\n\n this.rTime = rTime || 0;\n\n // also set time constants for ramp\n this._setRampAD(aTime, dTime);\n};\n\n/**\n * Set max (attackLevel) and min (releaseLevel) of envelope.\n *\n * @method setRange\n * @for p5.Envelope\n * @param {Number} aLevel attack level (defaults to 1)\n * @param {Number} rLevel release level (defaults to 0)\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * triOsc.start();\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.setRange = function (aLevel, rLevel) {\n this.aLevel = aLevel || 1;\n this.rLevel = rLevel || 0;\n\n // not sure if this belongs here:\n\n // {Number} [dLevel] decay/sustain level (optional)\n // if (typeof(dLevel) !== 'undefined') {\n // this.dLevel = dLevel\n // } else if (this.sPercent) {\n // this.dLevel = this.sPercent ? this.sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;\n // }\n};\n\n// private (undocumented) method called when ADSR is set to set time constants for ramp\n//\n// Set the \n// time constants for simple exponential ramps.\n// The larger the time constant value, the slower the\n// transition will be.\n//\n// method _setRampAD\n// param {Number} attackTimeConstant attack time constant\n// param {Number} decayTimeConstant decay time constant\n//\np5.Envelope.prototype._setRampAD = function (t1, t2) {\n this._rampAttackTime = this.checkExpInput(t1);\n this._rampDecayTime = this.checkExpInput(t2);\n\n var TCDenominator = 1.0;\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);\n};\n\n// private method\np5.Envelope.prototype.setRampPercentages = function (p1, p2) {\n //set the percentages that the simple exponential ramps go to\n this._rampHighPercentage = this.checkExpInput(p1);\n this._rampLowPercentage = this.checkExpInput(p2);\n var TCDenominator = 1.0;\n //now re-compute the time constants based on those percentages\n /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)\n TCDenominator = Math.log(\n 1.0 / this.checkExpInput(1.0 - this._rampHighPercentage)\n );\n this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);\n TCDenominator = Math.log(1.0 / this._rampLowPercentage);\n this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);\n};\n\n/**\n * Assign a parameter to be controlled by this envelope.\n * If a p5.Sound object is given, then the p5.Envelope will control its\n * output gain. If multiple inputs are provided, the env will\n * control all of them.\n *\n * @method setInput\n * @for p5.Envelope\n * @param {Object} [...inputs] A p5.sound object or\n * Web Audio Param.\n */\np5.Envelope.prototype.setInput = function () {\n for (var i = 0; i < arguments.length; i++) {\n this.connect(arguments[i]);\n }\n};\n\n/**\n * Set whether the envelope ramp is linear (default) or exponential.\n * Exponential ramps can be useful because we perceive amplitude\n * and frequency logarithmically.\n *\n * @method setExp\n * @for p5.Envelope\n * @param {Boolean} isExp true is exponential, false is linear\n */\np5.Envelope.prototype.setExp = function (isExp) {\n this.isExponential = isExp;\n};\n\n//helper method to protect against zero values being sent to exponential functions\np5.Envelope.prototype.checkExpInput = function (value) {\n if (value <= 0) {\n value = 0.00000001;\n }\n return value;\n};\n\n/**\n *

Play tells the envelope to start acting on a given input.\n * If the input is a p5.sound object (i.e. AudioIn, Oscillator,\n * SoundFile), then Envelope will control its output volume.\n * Envelopes can also be used to control any \n * Web Audio Audio Param.

\n *\n * @method play\n * @for p5.Envelope\n * @param {Object} unit A p5.sound object or\n * Web Audio Param.\n * @param {Number} [startTime] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let attackLevel = 1.0;\n * let releaseLevel = 0;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.2;\n * let releaseTime = 0.5;\n *\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playEnv);\n *\n * env = new p5.Envelope();\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.amp(env);\n * triOsc.freq(220);\n * triOsc.start();\n * }\n *\n * function draw() {\n * background(220);\n * text('tap here to play', 5, 20);\n * attackTime = map(mouseX, 0, width, 0, 1.0);\n * attackLevel = map(mouseY, height, 0, 0, 1.0);\n * text('attack time: ' + attackTime, 5, height - 40);\n * text('attack level: ' + attackLevel, 5, height - 20);\n * }\n *\n * function playEnv() {\n * // ensure that audio is enabled\n * userStartAudio();\n *\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(attackLevel, releaseLevel);\n * env.play();\n * }\n *
\n */\np5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) {\n var tFromNow = secondsFromNow || 0;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n this.triggerAttack(unit, tFromNow);\n\n this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + ~~susTime);\n};\n\n/**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go. Input can be\n * any p5.sound object, or a \n * Web Audio Param.\n *\n * @method triggerAttack\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time from now (in seconds)\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n this.lastAttack = t;\n this.wasTriggered = true;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // after each ramp completes, cancel scheduled values\n // (so they can be overridden in case env has been re-triggered)\n // then, set current value (with linearRamp to avoid click)\n // then, schedule the next automation...\n\n // attack\n t += this.aTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.aLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.aLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // decay to decay level (if using ADSR, then decay level == sustain level)\n t += this.dTime;\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.dLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.dLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n};\n\n/**\n * Trigger the Release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method triggerRelease\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow time to trigger the release\n * @example\n *
\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let susPercent = 0.3;\n * let releaseTime = 0.4;\n * let env, triOsc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * textSize(10);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n * env.setRange(1.0, 0.0);\n * triOsc = new p5.Oscillator('triangle');\n * triOsc.freq(220);\n *\n * cnv.mousePressed(envAttack);\n * }\n *\n * function envAttack() {\n * background(0, 255, 255);\n * text('release to release', width/2, height/2);\n *\n * // ensures audio is enabled. See also: `userStartAudio`\n * triOsc.start();\n *\n * env.triggerAttack(triOsc);\n * }\n *\n * function mouseReleased() {\n * background(220);\n * text('tap to triggerAttack', width/2, height/2);\n *\n * env.triggerRelease(triOsc);\n * }\n *
\n */\np5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) {\n // only trigger a release if an attack was triggered\n if (!this.wasTriggered) {\n // this currently causes a bit of trouble:\n // if a later release has been scheduled (via the play function)\n // a new earlier release won't interrupt it, because\n // this.wasTriggered has already been set to false.\n // If we want new earlier releases to override, then we need to\n // keep track of the last release time, and if the new release time is\n // earlier, then use it.\n return;\n }\n\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n // get and set value (with linear or exponential ramp) to anchor automation\n var valToSet = this.control.getValueAtTime(t);\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);\n } else {\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n // release\n t += this.rTime;\n\n if (this.isExponential === true) {\n this.control.exponentialRampToValueAtTime(\n this.checkExpInput(this.rLevel),\n t\n );\n valToSet = this.checkExpInput(this.control.getValueAtTime(t));\n this.control.cancelScheduledValues(t);\n this.control.exponentialRampToValueAtTime(valToSet, t);\n } else {\n this.control.linearRampToValueAtTime(this.rLevel, t);\n valToSet = this.control.getValueAtTime(t);\n this.control.cancelScheduledValues(t);\n this.control.linearRampToValueAtTime(valToSet, t);\n }\n\n this.wasTriggered = false;\n};\n\n/**\n * Exponentially ramp to a value using the first two\n * values from setADSR(attackTime, decayTime)\n * as \n * time constants for simple exponential ramps.\n * If the value is higher than current value, it uses attackTime,\n * while a decrease uses decayTime.\n *\n * @method ramp\n * @for p5.Envelope\n * @param {Object} unit p5.sound Object or Web Audio Param\n * @param {Number} secondsFromNow When to trigger the ramp\n * @param {Number} v Target value\n * @param {Number} [v2] Second target value\n * @example\n *
\n * let env, osc, amp;\n *\n * let attackTime = 0.001;\n * let decayTime = 0.2;\n * let attackLevel = 1;\n * let decayLevel = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * fill(0,255,0);\n * noStroke();\n *\n * env = new p5.Envelope();\n * env.setADSR(attackTime, decayTime);\n * osc = new p5.Oscillator();\n * osc.amp(env);\n * amp = new p5.Amplitude();\n *\n * cnv.mousePressed(triggerRamp);\n * }\n *\n * function triggerRamp() {\n * // ensures audio is enabled. See also: `userStartAudio`\n * osc.start();\n *\n * env.ramp(osc, 0, attackLevel, decayLevel);\n * }\n *\n * function draw() {\n * background(20);\n * text('tap to play', 10, 20);\n * let h = map(amp.getLevel(), 0, 0.4, 0, height);;\n * rect(0, height, width, -h);\n * }\n *
\n */\np5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n var destination1 = this.checkExpInput(v1);\n var destination2 =\n typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;\n\n // connect env to unit if not already connected\n if (unit) {\n if (this.connection !== unit) {\n this.connect(unit);\n }\n }\n\n //get current value\n var currentVal = this.checkExpInput(this.control.getValueAtTime(t));\n // this.control.cancelScheduledValues(t);\n\n //if it's going up\n if (destination1 > currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampAttackTC);\n t += this._rampAttackTime;\n }\n\n //if it's going down\n else if (destination1 < currentVal) {\n this.control.setTargetAtTime(destination1, t, this._rampDecayTC);\n t += this._rampDecayTime;\n }\n\n // Now the second part of envelope begins\n if (destination2 === undefined) return;\n\n //if it's going up\n if (destination2 > destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampAttackTC);\n }\n\n //if it's going down\n else if (destination2 < destination1) {\n this.control.setTargetAtTime(destination2, t, this._rampDecayTC);\n }\n};\n\np5.Envelope.prototype.connect = function (unit) {\n this.connection = unit;\n\n // assume we're talking about output gain\n // unless given a different audio param\n if (\n unit instanceof p5.Oscillator ||\n unit instanceof p5.SoundFile ||\n unit instanceof p5.AudioIn ||\n unit instanceof p5.Reverb ||\n unit instanceof p5.Noise ||\n unit instanceof p5.Filter ||\n unit instanceof p5.Delay\n ) {\n unit = unit.output.gain;\n }\n if (unit instanceof AudioParam) {\n //set the initial value\n unit.setValueAtTime(0, p5sound.audiocontext.currentTime);\n }\n\n this.output.connect(unit);\n};\n\np5.Envelope.prototype.disconnect = function () {\n if (this.output) {\n this.output.disconnect();\n }\n};\n\n// Signal Math\n\n/**\n * Add a value to the p5.Oscillator's output amplitude,\n * and return the oscillator. Calling this method\n * again will override the initial add() with new values.\n *\n * @method add\n * @for p5.Envelope\n * @param {Number} number Constant number to add\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.add = function (num) {\n var add = new Add(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);\n};\n\n/**\n * Multiply the p5.Envelope's output amplitude\n * by a fixed value. Calling this method\n * again will override the initial mult() with new values.\n *\n * @method mult\n * @for p5.Envelope\n * @param {Number} number Constant number to multiply\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.mult = function (num) {\n var mult = new Mult(num);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);\n};\n\n/**\n * Scale this envelope's amplitude values to a given\n * range, and return the envelope. Calling this method\n * again will override the initial scale() with new values.\n *\n * @method scale\n * @for p5.Envelope\n * @param {Number} inMin input range minumum\n * @param {Number} inMax input range maximum\n * @param {Number} outMin input range minumum\n * @param {Number} outMax input range maximum\n * @return {p5.Envelope} Envelope Returns this envelope\n * with scaled output\n */\np5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) {\n var scale = new Scale(inMin, inMax, outMin, outMax);\n var thisChain = this.mathOps.length;\n var nextChain = this.output;\n return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);\n};\n\n// get rid of the oscillator\np5.Envelope.prototype.dispose = function () {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.disconnect();\n if (this.control) {\n this.control.dispose();\n this.control = null;\n }\n for (var i = 1; i < this.mathOps.length; i++) {\n this.mathOps[i].dispose();\n }\n};\n\n// Different name for backwards compatibility, replicates p5.Envelope class\np5.Env = function (t1, l1, t2, l2, t3, l3) {\n console.warn(\n 'WARNING: p5.Env is now deprecated and may be removed in future versions. ' +\n 'Please use the new p5.Envelope instead.'\n );\n p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);\n};\np5.Env.prototype = Object.create(p5.Envelope.prototype);\n\nconst Envelope = p5.Envelope;\nexport default Envelope;\n","import p5sound from './master';\nimport Oscillator from './oscillator';\n\n// generate noise buffers\nconst _whiteNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var whiteBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = whiteBuffer.getChannelData(0);\n for (var i = 0; i < bufferSize; i++) {\n noiseData[i] = Math.random() * 2 - 1;\n }\n whiteBuffer.type = 'white';\n return whiteBuffer;\n})();\n\nconst _pinkNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var pinkBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = pinkBuffer.getChannelData(0);\n var b0, b1, b2, b3, b4, b5, b6;\n b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n b0 = 0.99886 * b0 + white * 0.0555179;\n b1 = 0.99332 * b1 + white * 0.0750759;\n b2 = 0.969 * b2 + white * 0.153852;\n b3 = 0.8665 * b3 + white * 0.3104856;\n b4 = 0.55 * b4 + white * 0.5329522;\n b5 = -0.7616 * b5 - white * 0.016898;\n noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;\n noiseData[i] *= 0.11; // (roughly) compensate for gain\n b6 = white * 0.115926;\n }\n pinkBuffer.type = 'pink';\n return pinkBuffer;\n})();\n\nconst _brownNoiseBuffer = (function () {\n var bufferSize = 2 * p5sound.audiocontext.sampleRate;\n var brownBuffer = p5sound.audiocontext.createBuffer(\n 1,\n bufferSize,\n p5sound.audiocontext.sampleRate\n );\n var noiseData = brownBuffer.getChannelData(0);\n var lastOut = 0.0;\n for (var i = 0; i < bufferSize; i++) {\n var white = Math.random() * 2 - 1;\n noiseData[i] = (lastOut + 0.02 * white) / 1.02;\n lastOut = noiseData[i];\n noiseData[i] *= 3.5;\n }\n brownBuffer.type = 'brown';\n return brownBuffer;\n})();\n\n/**\n * Noise is a type of oscillator that generates a buffer with random values.\n *\n * @class p5.Noise\n * @extends p5.Oscillator\n * @constructor\n * @param {String} type Type of noise can be 'white' (default),\n * 'brown' or 'pink'.\n */\nclass Noise extends Oscillator {\n constructor(type) {\n super();\n var assignType;\n delete this.f;\n delete this.freq;\n delete this.oscillator;\n\n if (type === 'brown') {\n assignType = _brownNoiseBuffer;\n } else if (type === 'pink') {\n assignType = _pinkNoiseBuffer;\n } else {\n assignType = _whiteNoiseBuffer;\n }\n this.buffer = assignType;\n }\n\n /**\n * Set type of noise to 'white', 'pink' or 'brown'.\n * White is the default.\n *\n * @method setType\n * @param {String} [type] 'white', 'pink' or 'brown'\n */\n setType(type) {\n switch (type) {\n case 'white':\n this.buffer = _whiteNoiseBuffer;\n break;\n case 'pink':\n this.buffer = _pinkNoiseBuffer;\n break;\n case 'brown':\n this.buffer = _brownNoiseBuffer;\n break;\n default:\n this.buffer = _whiteNoiseBuffer;\n }\n if (this.started) {\n var now = p5sound.audiocontext.currentTime;\n this.stop(now);\n this.start(now + 0.01);\n }\n }\n\n getType() {\n return this.buffer.type;\n }\n start() {\n if (this.started) {\n this.stop();\n }\n this.noise = p5sound.audiocontext.createBufferSource();\n this.noise.buffer = this.buffer;\n this.noise.loop = true;\n this.noise.connect(this.output);\n var now = p5sound.audiocontext.currentTime;\n this.noise.start(now);\n this.started = true;\n }\n\n stop() {\n var now = p5sound.audiocontext.currentTime;\n if (this.noise) {\n this.noise.stop(now);\n this.started = false;\n }\n }\n\n dispose() {\n var now = p5sound.audiocontext.currentTime;\n\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.noise) {\n this.noise.disconnect();\n this.stop(now);\n }\n if (this.output) {\n this.output.disconnect();\n }\n if (this.panner) {\n this.panner.disconnect();\n }\n this.output = null;\n this.panner = null;\n this.buffer = null;\n this.noise = null;\n }\n}\n\nexport default Noise;\n","import Signal from 'Tone/signal/Signal';\nimport Multiply from 'Tone/signal/Multiply';\n\nimport p5sound from './master';\nimport Oscillator, { SawOsc } from './oscillator';\n\n/**\n * Creates a Pulse object, an oscillator that implements\n * Pulse Width Modulation.\n * The pulse is created with two oscillators.\n * Accepts a parameter for frequency, and to set the\n * width between the pulses. See \n * p5.Oscillator for a full list of methods.\n *\n * @class p5.Pulse\n * @extends p5.Oscillator\n * @constructor\n * @param {Number} [freq] Frequency in oscillations per second (Hz)\n * @param {Number} [w] Width between the pulses (0 to 1.0,\n * defaults to 0)\n * @example\n *
\n * let pulse;\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startPulse);\n * background(220);\n *\n * pulse = new p5.Pulse();\n * pulse.amp(0.5);\n * pulse.freq(220);\n * }\n * function startPulse() {\n * pulse.start();\n * pulse.amp(0.5, 0.02);\n * }\n * function mouseReleased() {\n * pulse.amp(0, 0.2);\n * }\n * function draw() {\n * background(220);\n * text('tap to play', 5, 20, width - 20);\n * let w = map(mouseX, 0, width, 0, 1);\n * w = constrain(w, 0, 1);\n * pulse.width(w);\n * text('pulse width: ' + w, 5, height - 20);\n * }\n *
\n */\nclass Pulse extends Oscillator {\n constructor(freq, w) {\n super(freq, 'sawtooth');\n\n // width of PWM, should be betw 0 to 1.0\n this.w = w || 0;\n\n // create a second oscillator with inverse frequency\n this.osc2 = new SawOsc(freq);\n\n // create a delay node\n this.dNode = p5sound.audiocontext.createDelay();\n\n // dc offset\n this.dcOffset = createDCOffset();\n this.dcGain = p5sound.audiocontext.createGain();\n this.dcOffset.connect(this.dcGain);\n this.dcGain.connect(this.output);\n // set delay time based on PWM width\n this.f = freq || 440;\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n\n // disconnect osc2 and connect it to delay, which is connected to output\n this.osc2.disconnect();\n this.osc2.panner.disconnect();\n this.osc2.amp(-1); // inverted amplitude\n this.osc2.output.connect(this.dNode);\n this.dNode.connect(this.output);\n\n this.output.gain.value = 1;\n this.output.connect(this.panner);\n }\n\n /**\n * Set the width of a Pulse object (an oscillator that implements\n * Pulse Width Modulation).\n *\n * @method width\n * @param {Number} [width] Width between the pulses (0 to 1.0,\n * defaults to 0)\n */\n width(w) {\n if (typeof w === 'number') {\n if (w <= 1.0 && w >= 0.0) {\n this.w = w;\n // set delay time based on PWM width\n\n // var mW = map(this.w, 0, 1.0, 0, 1/this.f);\n var mW = this.w / this.oscillator.frequency.value;\n this.dNode.delayTime.value = mW;\n }\n\n this.dcGain.gain.value = 1.7 * (0.5 - this.w);\n } else {\n w.connect(this.dNode.delayTime);\n let sig = new Signal(-0.5); //repalce it with tones Signals Method\n w.connect(sig);\n let mult1 = new Multiply(-1);\n let mult2 = new Multiply(1.7);\n sig = sig.connect(mult1).connect(mult2);\n sig.connect(this.dcGain.gain);\n }\n }\n\n start(f, time) {\n var now = p5sound.audiocontext.currentTime;\n var t = time || 0;\n if (!this.started) {\n var freq = f || this.f;\n var type = this.oscillator.type;\n this.oscillator = p5sound.audiocontext.createOscillator();\n this.oscillator.frequency.setValueAtTime(freq, now);\n this.oscillator.type = type;\n this.oscillator.connect(this.output);\n this.oscillator.start(t + now);\n\n // set up osc2\n this.osc2.oscillator = p5sound.audiocontext.createOscillator();\n this.osc2.oscillator.frequency.setValueAtTime(freq, t + now);\n this.osc2.oscillator.type = type;\n this.osc2.oscillator.connect(this.osc2.output);\n this.osc2.start(t + now);\n this.freqNode = [\n this.oscillator.frequency,\n this.osc2.oscillator.frequency,\n ];\n\n // start dcOffset, too\n this.dcOffset = createDCOffset();\n this.dcOffset.connect(this.dcGain);\n this.dcOffset.start(t + now);\n\n // if LFO connections depend on these oscillators\n if (this.mods !== undefined && this.mods.frequency !== undefined) {\n this.mods.frequency.connect(this.freqNode[0]);\n this.mods.frequency.connect(this.freqNode[1]);\n }\n this.started = true;\n this.osc2.started = true;\n }\n }\n\n stop(time) {\n if (this.started) {\n var t = time || 0;\n var now = p5sound.audiocontext.currentTime;\n this.oscillator.stop(t + now);\n if (this.osc2.oscillator) {\n this.osc2.oscillator.stop(t + now);\n }\n this.dcOffset.stop(t + now);\n this.started = false;\n this.osc2.started = false;\n }\n }\n\n freq(val, rampTime = 0, tFromNow = 0) {\n if (typeof val === 'number') {\n this.f = val;\n var now = p5sound.audiocontext.currentTime;\n var currentFreq = this.oscillator.frequency.value;\n this.oscillator.frequency.cancelScheduledValues(now);\n this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);\n this.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n this.osc2.oscillator.frequency.cancelScheduledValues(now);\n this.osc2.oscillator.frequency.setValueAtTime(\n currentFreq,\n now + tFromNow\n );\n this.osc2.oscillator.frequency.exponentialRampToValueAtTime(\n val,\n tFromNow + rampTime + now\n );\n\n if (this.freqMod) {\n this.freqMod.output.disconnect();\n this.freqMod = null;\n }\n } else if (val.output) {\n val.output.disconnect();\n val.output.connect(this.oscillator.frequency);\n val.output.connect(this.osc2.oscillator.frequency);\n this.freqMod = val;\n }\n }\n}\n\n// inspiration: http://webaudiodemos.appspot.com/oscilloscope/\nfunction createDCOffset() {\n var ac = p5sound.audiocontext;\n var buffer = ac.createBuffer(1, 2048, ac.sampleRate);\n var data = buffer.getChannelData(0);\n for (var i = 0; i < 2048; i++) data[i] = 1.0;\n var bufferSource = ac.createBufferSource();\n bufferSource.buffer = buffer;\n bufferSource.loop = true;\n return bufferSource;\n}\n\nexport default Pulse;\n","import p5sound from './master';\nimport Amplitude from './amplitude';\n\n// an array of input sources\np5sound.inputSources = [];\n\n/**\n *

Get audio from an input, i.e. your computer's microphone.

\n *\n *

Turn the mic on/off with the start() and stop() methods. When the mic\n * is on, its volume can be measured with getLevel or by connecting an\n * FFT object.

\n *\n *

If you want to hear the AudioIn, use the .connect() method.\n * AudioIn does not connect to p5.sound output by default to prevent\n * feedback.

\n *\n *

Note: This uses the getUserMedia/\n * Stream API, which is not supported by certain browsers. Access in Chrome browser\n * is limited to localhost and https, but access over http may be limited.

\n *\n * @class p5.AudioIn\n * @constructor\n * @param {Function} [errorCallback] A function to call if there is an error\n * accessing the AudioIn. For example,\n * Safari and iOS devices do not\n * currently allow microphone access.\n * @example\n *
\n * let mic;\n *\n * function setup(){\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(useraudiocontextStartAudio);\n * textAlign(CENTER);\n * mic = new p5.AudioIn();\n * mic.start();\n * }\n *\n * function draw(){\n * background(0);\n * fill(255);\n * text('tap to start', width/2, 20);\n *\n * micLevel = mic.getLevel();\n * let y = height - micLevel * height;\n * ellipse(width/2, y, 10, 10);\n * }\n *
\n */\nclass AudioIn {\n constructor(errorCallback) {\n // set up audio input\n /**\n * @property {GainNode} input\n */\n this.input = p5sound.audiocontext.createGain();\n /**\n * @property {GainNode} output\n */\n this.output = p5sound.audiocontext.createGain();\n\n /**\n * @property {MediaStream|null} stream\n */\n this.stream = null;\n /**\n * @property {MediaStreamAudioSourceNode|null} mediaStream\n */\n this.mediaStream = null;\n /**\n * @property {Number|null} currentSource\n */\n this.currentSource = null;\n\n /**\n * Client must allow browser to access their microphone / audioin source.\n * Default: false. Will become true when the client enables access.\n *\n * @property {Boolean} enabled\n */\n this.enabled = false;\n\n /**\n * Input amplitude, connect to it by default but not to master out\n *\n * @property {p5.Amplitude} amplitude\n */\n this.amplitude = new Amplitude();\n this.output.connect(this.amplitude.input);\n\n if (\n !window.MediaStreamTrack ||\n !window.navigator.mediaDevices ||\n !window.navigator.mediaDevices.getUserMedia\n ) {\n errorCallback\n ? errorCallback()\n : window.alert(\n 'This browser does not support MediaStreamTrack and mediaDevices'\n );\n }\n\n // add to soundArray so we can dispose on close\n p5sound.soundArray.push(this);\n }\n /**\n * Start processing audio input. This enables the use of other\n * AudioIn methods like getLevel(). Note that by default, AudioIn\n * is not connected to p5.sound's output. So you won't hear\n * anything unless you use the connect() method.
\n *\n * Certain browsers limit access to the user's microphone. For example,\n * Chrome only allows access from localhost and over https. For this reason,\n * you may want to include an errorCallback—a function that is called in case\n * the browser won't provide mic access.\n *\n * @method start\n * @for p5.AudioIn\n * @param {Function} [successCallback] Name of a function to call on\n * success.\n * @param {Function} [errorCallback] Name of a function to call if\n * there was an error. For example,\n * some browsers do not support\n * getUserMedia.\n */\n start(successCallback, errorCallback) {\n var self = this;\n\n if (this.stream) {\n this.stop();\n }\n\n // set the audio source\n var audioSource = p5sound.inputSources[self.currentSource];\n var constraints = {\n audio: {\n sampleRate: p5sound.audiocontext.sampleRate,\n echoCancellation: false,\n },\n };\n\n // if developers determine which source to use\n if (p5sound.inputSources[this.currentSource]) {\n constraints.audio.deviceId = audioSource.deviceId;\n }\n\n window.navigator.mediaDevices\n .getUserMedia(constraints)\n .then(function (stream) {\n self.stream = stream;\n self.enabled = true;\n // Wrap a MediaStreamSourceNode around the live input\n self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);\n self.mediaStream.connect(self.output);\n // only send to the Amplitude reader, so we can see it but not hear it.\n self.amplitude.setInput(self.output);\n if (successCallback) successCallback();\n })\n .catch(function (err) {\n if (errorCallback) errorCallback(err);\n else console.error(err);\n });\n }\n\n /**\n * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\n * If re-starting, the user may be prompted for permission access.\n *\n * @method stop\n * @for p5.AudioIn\n */\n stop() {\n if (this.stream) {\n this.stream.getTracks().forEach(function (track) {\n track.stop();\n });\n\n this.mediaStream.disconnect();\n\n delete this.mediaStream;\n delete this.stream;\n }\n }\n\n /**\n * Connect to an audio unit. If no parameter is provided, will\n * connect to the master output (i.e. your speakers).
\n *\n * @method connect\n * @for p5.AudioIn\n * @param {Object} [unit] An object that accepts audio input,\n * such as an FFT\n */\n connect(unit) {\n if (unit) {\n if (unit.hasOwnProperty('input')) {\n this.output.connect(unit.input);\n } else if (unit.hasOwnProperty('analyser')) {\n this.output.connect(unit.analyser);\n } else {\n this.output.connect(unit);\n }\n } else {\n this.output.connect(p5sound.input);\n }\n }\n\n /**\n * Disconnect the AudioIn from all audio units. For example, if\n * connect() had been called, disconnect() will stop sending\n * signal to your speakers.
\n *\n * @method disconnect\n * @for p5.AudioIn\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n // stay connected to amplitude even if not outputting to p5\n this.output.connect(this.amplitude.input);\n }\n }\n\n /**\n * Read the Amplitude (volume level) of an AudioIn. The AudioIn\n * class contains its own instance of the Amplitude class to help\n * make it easy to get a microphone's volume level. Accepts an\n * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must\n * .start() before using .getLevel().
\n *\n * @method getLevel\n * @for p5.AudioIn\n * @param {Number} [smoothing] Smoothing is 0.0 by default.\n * Smooths values based on previous values.\n * @return {Number} Volume level (between 0.0 and 1.0)\n */\n getLevel(smoothing) {\n if (smoothing) {\n this.amplitude.smoothing = smoothing;\n }\n return this.amplitude.getLevel();\n }\n\n /**\n * Set amplitude (volume) of a mic input between 0 and 1.0.
\n *\n * @method amp\n * @for p5.AudioIn\n * @param {Number} vol between 0 and 1.0\n * @param {Number} [time] ramp time (optional)\n */\n amp(vol, t) {\n if (t) {\n var rampTime = t || 0;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(\n currentVol,\n p5sound.audiocontext.currentTime\n );\n this.output.gain.linearRampToValueAtTime(\n vol,\n rampTime + p5sound.audiocontext.currentTime\n );\n } else {\n this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);\n this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);\n }\n }\n\n /**\n * Returns a list of available input sources. This is a wrapper\n * for \n * MediaDevices.enumerateDevices() - Web APIs | MDN\n * and it returns a Promise.\n * @method getSources\n * @for p5.AudioIn\n * @param {Function} [successCallback] This callback function handles the sources when they\n * have been enumerated. The callback function\n * receives the deviceList array as its only argument\n * @param {Function} [errorCallback] This optional callback receives the error\n * message as its argument.\n * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar\n * to the enumerateDevices() method\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\n getSources(onSuccess, onError) {\n return new Promise(function (resolve, reject) {\n window.navigator.mediaDevices\n .enumerateDevices()\n .then(function (devices) {\n p5sound.inputSources = devices.filter(function (device) {\n return device.kind === 'audioinput';\n });\n resolve(p5sound.inputSources);\n if (onSuccess) {\n onSuccess(p5sound.inputSources);\n }\n })\n .catch(function (error) {\n reject(error);\n if (onError) {\n onError(error);\n } else {\n console.error(\n 'This browser does not support MediaStreamTrack.getSources()'\n );\n }\n });\n });\n }\n\n /**\n * Set the input source. Accepts a number representing a\n * position in the array returned by getSources().\n * This is only available in browsers that support\n * \n * navigator.mediaDevices.enumerateDevices()\n *\n * @method setSource\n * @for p5.AudioIn\n * @param {number} num position of input source in the array\n * @example\n *
\n * let audioIn;\n *\n * function setup(){\n * text('getting sources...', 0, 20);\n * audioIn = new p5.AudioIn();\n * audioIn.getSources(gotSources);\n * }\n *\n * function gotSources(deviceList) {\n * if (deviceList.length > 0) {\n * //set the source to the first item in the deviceList array\n * audioIn.setSource(0);\n * let currentSource = deviceList[audioIn.currentSource];\n * text('set source to: ' + currentSource.deviceId, 5, 20, width);\n * }\n * }\n *
\n */\n setSource(num) {\n if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {\n // set the current source\n this.currentSource = num;\n console.log('set source to ', p5sound.inputSources[this.currentSource]);\n } else {\n console.log('unable to set input source');\n }\n\n // restart stream if currently active\n if (this.stream && this.stream.active) {\n this.start();\n }\n }\n\n // private method\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this.stop();\n\n if (this.output) {\n this.output.disconnect();\n }\n if (this.amplitude) {\n this.amplitude.disconnect();\n }\n delete this.amplitude;\n delete this.output;\n }\n}\n\nexport default AudioIn;\n","import p5sound from './master';\nimport CrossFade from 'Tone/component/CrossFade.js';\n\n/**\n * Effect is a base class for audio effects in p5.
\n * This module handles the nodes and methods that are\n * common and useful for current and future effects.\n *\n *\n * This class is extended by p5.Distortion,\n * p5.Compressor,\n * p5.Delay,\n * p5.Filter,\n * p5.Reverb.\n *\n * @class p5.Effect\n * @constructor\n *\n * @param {Object} [ac] Reference to the audio context of the p5 object\n * @param {AudioNode} [input] Gain Node effect wrapper\n * @param {AudioNode} [output] Gain Node effect wrapper\n * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)\n * @param {AudioNode} [wet] Effects that extend this class should connect\n * to the wet signal to this gain node, so that dry and wet\n * signals are mixed properly.\n */\nclass Effect {\n constructor() {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n /**\n *\tThe p5.Effect class is built\n * \tusing Tone.js CrossFade\n * \t@private\n */\n\n this._drywet = new CrossFade(1);\n\n /**\n *\tIn classes that extend\n *\tp5.Effect, connect effect nodes\n *\tto the wet parameter\n */\n this.wet = this.ac.createGain();\n\n this.input.connect(this._drywet.a);\n this.wet.connect(this._drywet.b);\n this._drywet.connect(this.output);\n\n this.connect();\n\n //Add to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Set the output volume of the filter.\n *\n * @method amp\n * @for p5.Effect\n * @param {Number} [vol] amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts until rampTime\n * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds\n */\n amp(vol, rampTime = 0, tFromNow = 0) {\n const now = p5sound.audiocontext.currentTime;\n const startTime = now + tFromNow;\n const endTime = startTime + rampTime + 0.001;\n const currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, startTime + 0.001);\n this.output.gain.linearRampToValueAtTime(vol, endTime);\n }\n\n /**\n * Link effects together in a chain\n * Example usage: filter.chain(reverb, delay, panner);\n * May be used with an open-ended number of arguments\n *\n * @method chain\n * @for p5.Effect\n * @param {Object} [arguments] Chain together multiple sound objects\n */\n chain() {\n if (arguments.length > 0) {\n this.connect(arguments[0]);\n for (var i = 1; i < arguments.length; i += 1) {\n arguments[i - 1].connect(arguments[i]);\n }\n }\n return this;\n }\n\n /**\n * Adjust the dry/wet value.\n *\n * @method drywet\n * @for p5.Effect\n * @param {Number} [fade] The desired drywet value (0 - 1.0)\n */\n drywet() {\n if (typeof fade !== 'undefined') {\n this._drywet.fade.value = fade;\n }\n return this._drywet.fade.value;\n }\n\n /**\n * Send output to a p5.js-sound, Web Audio Node, or use signal to\n * control an AudioParam\n *\n * @method connect\n * @for p5.Effect\n * @param {Object} unit\n */\n connect(unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all output.\n * @method disconnect\n * @for p5.Effect\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n dispose() {\n // remove refernce form soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n\n if (this._drywet) {\n this._drywet.disconnect();\n delete this._drywet;\n }\n\n if (this.wet) {\n this.wet.disconnect();\n delete this.wet;\n }\n\n this.ac = undefined;\n }\n}\n\nexport default Effect;\n","import Effect from './effect';\n\n/**\n *

A p5.Filter uses a Web Audio Biquad Filter to filter\n * the frequency response of an input source. Subclasses\n * include:

\n * p5.LowPass:\n * Allows frequencies below the cutoff frequency to pass through,\n * and attenuates frequencies above the cutoff.
\n * p5.HighPass:\n * The opposite of a lowpass filter.
\n * p5.BandPass:\n * Allows a range of frequencies to pass through and attenuates\n * the frequencies below and above this frequency range.
\n *\n * The .res() method controls either width of the\n * bandpass, or resonance of the low/highpass cutoff frequency.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Filter\n * @extends p5.Effect\n * @constructor\n * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'\n * @example\n *
\n * let fft, noise, filter;\n *\n * function setup() {\n * let cnv = createCanvas(100,100);\n * cnv.mousePressed(makeNoise);\n * fill(255, 0, 255);\n *\n * filter = new p5.BandPass();\n * noise = new p5.Noise();\n * noise.disconnect();\n * noise.connect(filter);\n *\n * fft = new p5.FFT();\n * }\n *\n * function draw() {\n * background(220);\n *\n * // set the BandPass frequency based on mouseX\n * let freq = map(mouseX, 0, width, 20, 10000);\n * freq = constrain(freq, 0, 22050);\n * filter.freq(freq);\n * // give the filter a narrow band (lower res = wider bandpass)\n * filter.res(50);\n *\n * // draw filtered spectrum\n * let spectrum = fft.analyze();\n * noStroke();\n * for (let i = 0; i < spectrum.length; i++) {\n * let x = map(i, 0, spectrum.length, 0, width);\n * let h = -height + map(spectrum[i], 0, 255, height, 0);\n * rect(x, height, width/spectrum.length, h);\n * }\n * if (!noise.started) {\n * text('tap here and drag to change frequency', 10, 20, width - 20);\n * } else {\n * text('Frequency: ' + round(freq)+'Hz', 20, 20, width - 20);\n * }\n * }\n *\n * function makeNoise() {\n * // see also: `userStartAudio()`\n * noise.start();\n * noise.amp(0.5, 0.2);\n * }\n *\n * function mouseReleased() {\n * noise.amp(0, 0.2);\n * }\n *\n *
\n */\nclass Filter extends Effect {\n constructor(type) {\n super();\n //add extend Effect by adding a Biquad Filter\n\n /**\n * The p5.Filter is built with a\n * \n * Web Audio BiquadFilter Node.\n *\n * @property {DelayNode} biquadFilter\n */\n\n this.biquad = this.ac.createBiquadFilter();\n\n this.input.connect(this.biquad);\n\n this.biquad.connect(this.wet);\n\n if (type) {\n this.setType(type);\n }\n\n //Properties useful for the toggle method.\n this._on = true;\n this._untoggledType = this.biquad.type;\n }\n\n /**\n * Filter an audio signal according to a set\n * of filter parameters.\n *\n * @method process\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance/Width of the filter frequency\n * from 0.001 to 1000\n */\n process(src, freq, res, time) {\n src.connect(this.input);\n this.set(freq, res, time);\n }\n\n /**\n * Set the frequency and the resonance of the filter.\n *\n * @method set\n * @param {Number} [freq] Frequency in Hz, from 10 to 22050\n * @param {Number} [res] Resonance (Q) from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n set(freq, res, time) {\n if (freq) {\n this.freq(freq, time);\n }\n if (res) {\n this.res(res, time);\n }\n }\n\n /**\n * Set the filter frequency, in Hz, from 10 to 22050 (the range of\n * human hearing, although in reality most people hear in a narrower\n * range).\n *\n * @method freq\n * @param {Number} freq Filter Frequency\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current frequency value\n */\n freq(freq, time) {\n var t = time || 0;\n if (freq <= 0) {\n freq = 1;\n }\n if (typeof freq === 'number') {\n this.biquad.frequency.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.biquad.frequency.exponentialRampToValueAtTime(\n freq,\n this.ac.currentTime + 0.02 + t\n );\n } else if (freq) {\n freq.connect(this.biquad.frequency);\n }\n return this.biquad.frequency.value;\n }\n\n /**\n * Controls either width of a bandpass frequency,\n * or the resonance of a low/highpass cutoff frequency.\n *\n * @method res\n * @param {Number} res Resonance/Width of filter freq\n * from 0.001 to 1000\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n * @return {Number} value Returns the current res value\n */\n res(res, time) {\n var t = time || 0;\n if (typeof res === 'number') {\n this.biquad.Q.value = res;\n this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.Q.linearRampToValueAtTime(\n res,\n this.ac.currentTime + 0.02 + t\n );\n } else if (res) {\n res.connect(this.biquad.Q);\n }\n return this.biquad.Q.value;\n }\n\n /**\n * Controls the gain attribute of a Biquad Filter.\n * This is distinctly different from .amp() which is inherited from p5.Effect\n * .amp() controls the volume via the output gain node\n * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.\n *\n * @method gain\n * @param {Number} gain\n * @return {Number} Returns the current or updated gain value\n */\n gain(gain, time) {\n var t = time || 0;\n if (typeof gain === 'number') {\n this.biquad.gain.value = gain;\n this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.biquad.gain.linearRampToValueAtTime(\n gain,\n this.ac.currentTime + 0.02 + t\n );\n } else if (gain) {\n gain.connect(this.biquad.gain);\n }\n return this.biquad.gain.value;\n }\n\n /**\n * Toggle function. Switches between the specified type and allpass\n *\n * @method toggle\n * @return {boolean} [Toggle value]\n */\n toggle() {\n this._on = !this._on;\n\n if (this._on === true) {\n this.biquad.type = this._untoggledType;\n } else if (this._on === false) {\n this.biquad.type = 'allpass';\n }\n\n return this._on;\n }\n\n /**\n * Set the type of a p5.Filter. Possible types include:\n * \"lowpass\" (default), \"highpass\", \"bandpass\",\n * \"lowshelf\", \"highshelf\", \"peaking\", \"notch\",\n * \"allpass\".\n *\n * @method setType\n * @param {String} t\n */\n setType(t) {\n this.biquad.type = t;\n this._untoggledType = this.biquad.type;\n }\n\n dispose() {\n // remove reference from soundArray\n super.dispose();\n if (this.biquad) {\n this.biquad.disconnect();\n delete this.biquad;\n }\n }\n}\n\n/**\n * Constructor: new p5.LowPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('lowpass').\n * See p5.Filter for methods.\n *\n * @class p5.LowPass\n * @constructor\n * @extends p5.Filter\n */\nclass LowPass extends Filter {\n constructor() {\n super('lowpass');\n }\n}\n\n/**\n * Constructor: new p5.HighPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('highpass').\n * See p5.Filter for methods.\n *\n * @class p5.HighPass\n * @constructor\n * @extends p5.Filter\n */\nclass HighPass extends Filter {\n constructor() {\n super('highpass');\n }\n}\n\n/**\n * Constructor: new p5.BandPass() Filter.\n * This is the same as creating a p5.Filter and then calling\n * its method setType('bandpass').\n * See p5.Filter for methods.\n *\n * @class p5.BandPass\n * @constructor\n * @extends p5.Filter\n */\nclass BandPass extends Filter {\n constructor() {\n super('bandpass');\n }\n}\nexport default Filter;\nexport { LowPass, HighPass, BandPass };\n","import Filter from './filter';\nimport p5sound from './master';\n\n/**\n * EQFilter extends p5.Filter with constraints\n * necessary for the p5.EQ\n *\n * @private\n */\nclass EQFilter extends Filter {\n constructor(freq, res) {\n super('peaking');\n\n this.disconnect();\n this.set(freq, res);\n this.biquad.gain.value = 0;\n delete this.input;\n delete this.output;\n delete this._drywet;\n delete this.wet;\n }\n\n amp() {\n console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');\n }\n\n drywet() {\n console.warn('`drywet()` is not available for p5.EQ bands.');\n }\n\n connect(unit) {\n var u = unit || p5.soundOut.input;\n if (this.biquad) {\n this.biquad.connect(u.input ? u.input : u);\n } else {\n this.output.connect(u.input ? u.input : u);\n }\n }\n disconnect() {\n if (this.biquad) {\n this.biquad.disconnect();\n }\n }\n\n dispose() {\n // remove reference form soundArray\n const index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n this.disconnect();\n delete this.biquad;\n }\n}\n\nexport default EQFilter;\n","import Effect from './effect';\nimport EQFilter from './eqFilter';\n\n/**\n * p5.EQ is an audio effect that performs the function of a multiband\n * audio equalizer. Equalization is used to adjust the balance of\n * frequency compoenents of an audio signal. This process is commonly used\n * in sound production and recording to change the waveform before it reaches\n * a sound output device. EQ can also be used as an audio effect to create\n * interesting distortions by filtering out parts of the spectrum. p5.EQ is\n * built using a chain of Web Audio Biquad Filter Nodes and can be\n * instantiated with 3 or 8 bands. Bands can be added or removed from\n * the EQ by directly modifying p5.EQ.bands (the array that stores filters).\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.EQ\n * @constructor\n * @extends p5.Effect\n * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3\n * @return {Object} p5.EQ object\n *\n * @example\n *
\n * let eq, soundFile\n * let eqBandIndex = 0;\n * let eqBandNames = ['lows', 'mids', 'highs'];\n *\n * function preload() {\n * soundFormats('mp3', 'ogg');\n * soundFile = loadSound('assets/beat');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(toggleSound);\n *\n * eq = new p5.EQ(eqBandNames.length);\n * soundFile.disconnect();\n * eq.process(soundFile);\n * }\n *\n * function draw() {\n * background(30);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n * text('filtering ', 50, 25);\n *\n * fill(255, 40, 255);\n * textSize(26);\n * text(eqBandNames[eqBandIndex], 50, 55);\n *\n * fill(255);\n * textSize(9);\n *\n * if (!soundFile.isPlaying()) {\n * text('tap to play', 50, 80);\n * } else {\n * text('tap to filter next band', 50, 80)\n * }\n * }\n *\n * function toggleSound() {\n * if (!soundFile.isPlaying()) {\n * soundFile.play();\n * } else {\n * eqBandIndex = (eqBandIndex + 1) % eq.bands.length;\n * }\n *\n * for (let i = 0; i < eq.bands.length; i++) {\n * eq.bands[i].gain(0);\n * }\n * // filter the band we want to filter\n * eq.bands[eqBandIndex].gain(-40);\n * }\n *
\n */\nclass EQ extends Effect {\n constructor(_eqsize) {\n super();\n\n //p5.EQ can be of size (3) or (8), defaults to 3\n _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;\n\n var factor;\n _eqsize === 3 ? (factor = Math.pow(2, 3)) : (factor = 2);\n\n /**\n * The p5.EQ is built with abstracted p5.Filter objects.\n * To modify any bands, use methods of the \n * p5.Filter API, especially `gain` and `freq`.\n * Bands are stored in an array, with indices 0 - 3, or 0 - 7\n * @property {Array} bands\n *\n */\n this.bands = [];\n\n var freq, res;\n for (var i = 0; i < _eqsize; i++) {\n if (i === _eqsize - 1) {\n freq = 21000;\n res = 0.01;\n } else if (i === 0) {\n freq = 100;\n res = 0.1;\n } else if (i === 1) {\n freq = _eqsize === 3 ? 360 * factor : 360;\n res = 1;\n } else {\n freq = this.bands[i - 1].freq() * factor;\n res = 1;\n }\n this.bands[i] = this._newBand(freq, res);\n\n if (i > 0) {\n this.bands[i - 1].connect(this.bands[i].biquad);\n } else {\n this.input.connect(this.bands[i].biquad);\n }\n }\n this.bands[_eqsize - 1].connect(this.output);\n }\n\n /**\n * Process an input by connecting it to the EQ\n * @method process\n * @param {Object} src Audio source\n */\n process(src) {\n src.connect(this.input);\n }\n\n // /**\n // * Set the frequency and gain of each band in the EQ. This method should be\n // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.\n // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);\n // *\n // * @method set\n // * @for p5.EQ\n // * @param {Number} [freq0] Frequency value for band with index 0\n // * @param {Number} [gain0] Gain value for band with index 0\n // * @param {Number} [freq1] Frequency value for band with index 1\n // * @param {Number} [gain1] Gain value for band with index 1\n // * @param {Number} [freq2] Frequency value for band with index 2\n // * @param {Number} [gain2] Gain value for band with index 2\n // * @param {Number} [freq3] Frequency value for band with index 3\n // * @param {Number} [gain3] Gain value for band with index 3\n // * @param {Number} [freq4] Frequency value for band with index 4\n // * @param {Number} [gain4] Gain value for band with index 4\n // * @param {Number} [freq5] Frequency value for band with index 5\n // * @param {Number} [gain5] Gain value for band with index 5\n // * @param {Number} [freq6] Frequency value for band with index 6\n // * @param {Number} [gain6] Gain value for band with index 6\n // * @param {Number} [freq7] Frequency value for band with index 7\n // * @param {Number} [gain7] Gain value for band with index 7\n // */\n set() {\n if (arguments.length === this.bands.length * 2) {\n for (var i = 0; i < arguments.length; i += 2) {\n this.bands[i / 2].freq(arguments[i]);\n this.bands[i / 2].gain(arguments[i + 1]);\n }\n } else {\n console.error(\n 'Argument mismatch. .set() should be called with ' +\n this.bands.length * 2 +\n ' arguments. (one frequency and gain value pair for each band of the eq)'\n );\n }\n }\n\n /**\n * Add a new band. Creates a p5.Filter and strips away everything but\n * the raw biquad filter. This method returns an abstracted p5.Filter,\n * which can be added to p5.EQ.bands, in order to create new EQ bands.\n * @private\n * @for p5.EQ\n * @method _newBand\n * @param {Number} freq\n * @param {Number} res\n * @return {Object} Abstracted Filter\n */\n _newBand(freq, res) {\n return new EQFilter(freq, res);\n }\n\n dispose() {\n super.dispose();\n\n if (this.bands) {\n while (this.bands.length > 0) {\n delete this.bands.pop().dispose();\n }\n delete this.bands;\n }\n }\n}\nexport default EQ;\n","import p5sound from './master';\n\n// /**\n// * listener is a class that can construct both a Spatial Panner\n// * and a Spatial Listener. The panner is based on the\n// * Web Audio Spatial Panner Node\n// * https://www.w3.org/TR/webaudio/#the-listenernode-interface\n// * This panner is a spatial processing node that allows audio to be positioned\n// * and oriented in 3D space.\n// *\n// * The Listener modifies the properties of the Audio Context Listener.\n// * Both objects types use the same methods. The default is a spatial panner.\n// *\n// * p5.Panner3D - Constructs a Spatial Panner
\n// * p5.Listener3D - Constructs a Spatial Listener
\n// *\n// * @class listener\n// * @constructor\n// * @return {Object} p5.Listener3D Object\n// *\n// * @param {Web Audio Node} listener Web Audio Spatial Panning Node\n// * @param {AudioParam} listener.panningModel \"equal power\" or \"HRTF\"\n// * @param {AudioParam} listener.distanceModel \"linear\", \"inverse\", or \"exponential\"\n// * @param {String} [type] [Specify construction of a spatial panner or listener]\n// */\n\nclass Listener3D {\n constructor(type) {\n this.ac = p5sound.audiocontext;\n this.listener = this.ac.listener;\n }\n\n // /**\n // * Connect an audio sorce\n // * @param {Object} src Input source\n // */\n process(src) {\n src.connect(this.input);\n }\n // /**\n // * Set the X,Y,Z position of the Panner\n // * @param {[Number]} xVal\n // * @param {[Number]} yVal\n // * @param {[Number]} zVal\n // * @param {[Number]} time\n // * @return {[Array]} [Updated x, y, z values as an array]\n // */\n position(xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.listener.positionX.value,\n this.listener.positionY.value,\n this.listener.positionZ.value,\n ];\n }\n\n // /**\n // * Getter and setter methods for position coordinates\n // * @return {Number} [updated coordinate value]\n // */\n positionX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.positionX.value = xVal;\n this.listener.positionX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.positionX);\n }\n return this.listener.positionX.value;\n }\n positionY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.positionY.value = yVal;\n this.listener.positionY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.positionY);\n }\n return this.listener.positionY.value;\n }\n positionZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.positionZ.value = zVal;\n this.listener.positionZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.positionZ);\n }\n return this.listener.positionZ.value;\n }\n\n // cannot define method when class definition is commented\n // /**\n // * Overrides the listener orient() method because Listener has slightly\n // * different params. In human terms, Forward vectors are the direction the\n // * nose is pointing. Up vectors are the direction of the top of the head.\n // *\n // * @method orient\n // * @param {Number} xValF Forward vector X direction\n // * @param {Number} yValF Forward vector Y direction\n // * @param {Number} zValF Forward vector Z direction\n // * @param {Number} xValU Up vector X direction\n // * @param {Number} yValU Up vector Y direction\n // * @param {Number} zValU Up vector Z direction\n // * @param {Number} time\n // * @return {Array} All orienation params\n // */\n orient(xValF, yValF, zValF, xValU, yValU, zValU, time) {\n if (arguments.length === 3 || arguments.length === 4) {\n time = arguments[3];\n this.orientForward(xValF, yValF, zValF, time);\n } else if (arguments.length === 6 || arguments === 7) {\n this.orientForward(xValF, yValF, zValF);\n this.orientUp(xValU, yValU, zValU, time);\n }\n\n return [\n this.listener.forwardX.value,\n this.listener.forwardY.value,\n this.listener.forwardZ.value,\n this.listener.upX.value,\n this.listener.upY.value,\n this.listener.upZ.value,\n ];\n }\n\n orientForward(xValF, yValF, zValF, time) {\n this.forwardX(xValF, time);\n this.forwardY(yValF, time);\n this.forwardZ(zValF, time);\n\n return [\n this.listener.forwardX,\n this.listener.forwardY,\n this.listener.forwardZ,\n ];\n }\n\n orientUp(xValU, yValU, zValU, time) {\n this.upX(xValU, time);\n this.upY(yValU, time);\n this.upZ(zValU, time);\n\n return [this.listener.upX, this.listener.upY, this.listener.upZ];\n }\n // /**\n // * Getter and setter methods for orient coordinates\n // * @return {Number} [updated coordinate value]\n // */\n forwardX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.forwardX.value = xVal;\n this.listener.forwardX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.forwardX);\n }\n return this.listener.forwardX.value;\n }\n forwardY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.forwardY.value = yVal;\n this.listener.forwardY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.forwardY);\n }\n return this.listener.forwardY.value;\n }\n forwardZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.forwardZ.value = zVal;\n this.listener.forwardZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.listener.forwardZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.forwardZ);\n }\n return this.listener.forwardZ.value;\n }\n upX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.listener.upX.value = xVal;\n this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.listener.upX);\n }\n return this.listener.upX.value;\n }\n upY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.listener.upY.value = yVal;\n this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.listener.upY);\n }\n return this.listener.upY.value;\n }\n upZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.listener.upZ.value = zVal;\n this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);\n this.listener.upZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.listener.upZ);\n }\n return this.listener.upZ.value;\n }\n}\n\nexport default Listener3D;\n","import Effect from './effect';\n\n/**\n * Panner3D is based on the \n * Web Audio Spatial Panner Node.\n * This panner is a spatial processing node that allows audio to be positioned\n * and oriented in 3D space.\n *\n * The position is relative to an \n * Audio Context Listener, which can be accessed\n * by p5.soundOut.audiocontext.listener\n *\n *\n * @class p5.Panner3D\n * @constructor\n */\n\nclass Panner3D extends Effect {\n constructor() {\n super();\n /**\n * \n * Web Audio Spatial Panner Node\n *\n * Properties include
\n * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType)\n * : \"equal power\" or \"HRTF\"
\n * [DistanceModel](https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType)\n * : \"linear\", \"inverse\", or \"exponential\"\n *\n * @property {AudioNode} panner\n *\n */\n this.panner = this.ac.createPanner();\n this.panner.panningModel = 'HRTF';\n this.panner.distanceModel = 'linear';\n this.panner.connect(this.output);\n this.input.connect(this.panner);\n }\n\n /**\n * Connect an audio sorce\n *\n * @method process\n * @for p5.Panner3D\n * @param {Object} src Input source\n */\n process(src) {\n src.connect(this.input);\n }\n /**\n * Set the X,Y,Z position of the Panner\n * @method set\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\n set(xVal, yVal, zVal, time) {\n this.positionX(xVal, time);\n this.positionY(yVal, time);\n this.positionZ(zVal, time);\n return [\n this.panner.positionX.value,\n this.panner.positionY.value,\n this.panner.positionZ.value,\n ];\n }\n\n /**\n * Getter and setter methods for position coordinates\n * @method positionX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for position coordinates\n * @method positionY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for position coordinates\n * @method positionZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n positionX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.positionX.value = xVal;\n this.panner.positionX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.positionX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.positionX);\n }\n return this.panner.positionX.value;\n }\n positionY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.positionY.value = yVal;\n this.panner.positionY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.positionY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.positionY);\n }\n return this.panner.positionY.value;\n }\n positionZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.positionZ.value = zVal;\n this.panner.positionZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.positionZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.positionZ);\n }\n return this.panner.positionZ.value;\n }\n\n /**\n * Set the X,Y,Z position of the Panner\n * @method orient\n * @for p5.Panner3D\n * @param {Number} xVal\n * @param {Number} yVal\n * @param {Number} zVal\n * @param {Number} time\n * @return {Array} Updated x, y, z values as an array\n */\n orient(xVal, yVal, zVal, time) {\n this.orientX(xVal, time);\n this.orientY(yVal, time);\n this.orientZ(zVal, time);\n return [\n this.panner.orientationX.value,\n this.panner.orientationY.value,\n this.panner.orientationZ.value,\n ];\n }\n\n /**\n * Getter and setter methods for orient coordinates\n * @method orientX\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for orient coordinates\n * @method orientY\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n /**\n * Getter and setter methods for orient coordinates\n * @method orientZ\n * @for p5.Panner3D\n * @return {Number} updated coordinate value\n */\n orientX(xVal, time) {\n var t = time || 0;\n if (typeof xVal === 'number') {\n this.panner.orientationX.value = xVal;\n this.panner.orientationX.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationX.linearRampToValueAtTime(\n xVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (xVal) {\n xVal.connect(this.panner.orientationX);\n }\n return this.panner.orientationX.value;\n }\n orientY(yVal, time) {\n var t = time || 0;\n if (typeof yVal === 'number') {\n this.panner.orientationY.value = yVal;\n this.panner.orientationY.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationY.linearRampToValueAtTime(\n yVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (yVal) {\n yVal.connect(this.panner.orientationY);\n }\n return this.panner.orientationY.value;\n }\n orientZ(zVal, time) {\n var t = time || 0;\n if (typeof zVal === 'number') {\n this.panner.orientationZ.value = zVal;\n this.panner.orientationZ.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.panner.orientationZ.linearRampToValueAtTime(\n zVal,\n this.ac.currentTime + 0.02 + t\n );\n } else if (zVal) {\n zVal.connect(this.panner.orientationZ);\n }\n return this.panner.orientationZ.value;\n }\n\n /**\n * Set the rolloff factor and max distance\n * @method setFalloff\n * @for p5.Panner3D\n * @param {Number} [maxDistance]\n * @param {Number} [rolloffFactor]\n */\n setFalloff(maxDistance, rolloffFactor) {\n this.maxDist(maxDistance);\n this.rolloff(rolloffFactor);\n }\n /**\n * Maxium distance between the source and the listener\n * @method maxDist\n * @for p5.Panner3D\n * @param {Number} maxDistance\n * @return {Number} updated value\n */\n maxDist(maxDistance) {\n if (typeof maxDistance === 'number') {\n this.panner.maxDistance = maxDistance;\n }\n return this.panner.maxDistance;\n }\n\n /**\n * How quickly the volume is reduced as the source moves away from the listener\n * @method rollof\n * @for p5.Panner3D\n * @param {Number} rolloffFactor\n * @return {Number} updated value\n */\n rolloff(rolloffFactor) {\n if (typeof rolloffFactor === 'number') {\n this.panner.rolloffFactor = rolloffFactor;\n }\n return this.panner.rolloffFactor;\n }\n\n dispose() {\n super.dispose();\n if (this.panner) {\n this.panner.disconnect();\n delete this.panner;\n }\n }\n}\n\nexport default Panner3D;\n","import Filter from './filter';\nimport Effect from './effect';\n\n/**\n * Delay is an echo effect. It processes an existing sound source,\n * and outputs a delayed version of that sound. The p5.Delay can\n * produce different effects depending on the delayTime, feedback,\n * filter, and type. In the example below, a feedback of 0.5 (the\n * default value) will produce a looping delay that decreases in\n * volume by 50% each repeat. A filter will cut out the high\n * frequencies so that the delay does not sound as piercing as the\n * original source.\n *\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n * @class p5.Delay\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let osc;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * osc = new p5.Oscillator('square');\n * osc.amp(0.5);\n * delay = new p5.Delay();\n *\n * // delay.process() accepts 4 parameters:\n * // source, delayTime (in seconds), feedback, filter frequency\n * delay.process(osc, 0.12, .7, 2300);\n *\n * cnv.mousePressed(oscStart);\n * }\n *\n * function oscStart() {\n * osc.start();\n * }\n *\n * function mouseReleased() {\n * osc.stop();\n * }\n *
\n */\nclass Delay extends Effect {\n constructor() {\n super();\n\n this._split = this.ac.createChannelSplitter(2);\n this._merge = this.ac.createChannelMerger(2);\n\n this._leftGain = this.ac.createGain();\n this._rightGain = this.ac.createGain();\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n *\n * @for p5.Delay\n * @property {DelayNode} leftDelay\n */\n this.leftDelay = this.ac.createDelay();\n /**\n * The p5.Delay is built with two\n * \n * Web Audio Delay Nodes, one for each stereo channel.\n * @for p5.Delay\n * @property {DelayNode} rightDelay\n */\n this.rightDelay = this.ac.createDelay();\n\n this._leftFilter = new Filter();\n this._rightFilter = new Filter();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n\n this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);\n this._rightFilter.biquad.frequency.setValueAtTime(\n 1200,\n this.ac.currentTime\n );\n this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);\n\n // graph routing\n this.input.connect(this._split);\n this.leftDelay.connect(this._leftGain);\n this.rightDelay.connect(this._rightGain);\n this._leftGain.connect(this._leftFilter.input);\n this._rightGain.connect(this._rightFilter.input);\n this._merge.connect(this.wet);\n\n this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);\n\n // default routing\n this.setType(0);\n\n this._maxDelay = this.leftDelay.delayTime.maxValue;\n\n // set initial feedback to 0.5\n this.feedback(0.5);\n }\n /**\n * Add delay to an audio signal according to a set\n * of delay parameters.\n *\n * @method process\n * @for p5.Delay\n * @param {Object} Signal An object that outputs audio\n * @param {Number} [delayTime] Time (in seconds) of the delay/echo.\n * Some browsers limit delayTime to\n * 1 second.\n * @param {Number} [feedback] sends the delay back through itself\n * in a loop that decreases in volume\n * each time.\n * @param {Number} [lowPass] Cutoff frequency. Only frequencies\n * below the lowPass will be part of the\n * delay.\n */\n process(src, _delayTime, _feedback, _filter) {\n var feedback = _feedback || 0;\n var delayTime = _delayTime || 0;\n if (feedback >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n }\n if (delayTime >= this._maxDelay) {\n throw new Error(\n 'Delay Time exceeds maximum delay time of ' +\n this._maxDelay +\n ' second.'\n );\n }\n\n src.connect(this.input);\n this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);\n this._leftGain.gain.value = feedback;\n this._rightGain.gain.value = feedback;\n\n if (_filter) {\n this._leftFilter.freq(_filter);\n this._rightFilter.freq(_filter);\n }\n }\n\n /**\n * Set the delay (echo) time, in seconds. Usually this value will be\n * a floating point number between 0.0 and 1.0.\n *\n * @method delayTime\n * @for p5.Delay\n * @param {Number} delayTime Time (in seconds) of the delay\n */\n delayTime(t) {\n // if t is an audio node...\n if (typeof t !== 'number') {\n t.connect(this.leftDelay.delayTime);\n t.connect(this.rightDelay.delayTime);\n } else {\n this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);\n this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);\n }\n }\n\n /**\n * Feedback occurs when Delay sends its signal back through its input\n * in a loop. The feedback amount determines how much signal to send each\n * time through the loop. A feedback greater than 1.0 is not desirable because\n * it will increase the overall output each time through the loop,\n * creating an infinite feedback loop. The default value is 0.5\n *\n * @method feedback\n * @for p5.Delay\n * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an\n * Oscillator that can be used to\n * modulate this param\n * @returns {Number} Feedback value\n *\n */\n feedback(f) {\n // if f is an audio node...\n if (f && typeof f !== 'number') {\n f.connect(this._leftGain.gain);\n f.connect(this._rightGain.gain);\n } else if (f >= 1.0) {\n throw new Error('Feedback value will force a positive feedback loop.');\n } else if (typeof f === 'number') {\n this._leftGain.gain.value = f;\n this._rightGain.gain.value = f;\n }\n\n // return value of feedback\n return this._leftGain.gain.value;\n }\n\n /**\n * Set a lowpass filter frequency for the delay. A lowpass filter\n * will cut off any frequencies higher than the filter frequency.\n *\n * @method filter\n * @for p5.Delay\n * @param {Number|Object} cutoffFreq A lowpass filter will cut off any\n * frequencies higher than the filter frequency.\n * @param {Number|Object} res Resonance of the filter frequency\n * cutoff, or an object (i.e. a p5.Oscillator)\n * that can be used to modulate this parameter.\n * High numbers (i.e. 15) will produce a resonance,\n * low numbers (i.e. .2) will produce a slope.\n */\n filter(freq, q) {\n this._leftFilter.set(freq, q);\n this._rightFilter.set(freq, q);\n }\n\n /**\n * Choose a preset type of delay. 'pingPong' bounces the signal\n * from the left to the right channel to produce a stereo effect.\n * Any other parameter will revert to the default delay setting.\n *\n * @method setType\n * @for p5.Delay\n * @param {String|Number} type 'pingPong' (1) or 'default' (0)\n */\n setType(t) {\n if (t === 1) {\n t = 'pingPong';\n }\n this._split.disconnect();\n this._leftFilter.disconnect();\n this._rightFilter.disconnect();\n this._split.connect(this.leftDelay, 0);\n this._split.connect(this.rightDelay, 1);\n switch (t) {\n case 'pingPong':\n this._rightFilter.setType(this._leftFilter.biquad.type);\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.rightDelay);\n this._rightFilter.output.connect(this.leftDelay);\n break;\n default:\n this._leftFilter.output.connect(this._merge, 0, 0);\n this._rightFilter.output.connect(this._merge, 0, 1);\n this._leftFilter.output.connect(this.leftDelay);\n this._rightFilter.output.connect(this.rightDelay);\n }\n }\n\n // DocBlocks for methods inherited from p5.Effect\n /**\n * Set the output level of the delay effect.\n *\n * @method amp\n * @for p5.Delay\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n /**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Delay\n * @param {Object} unit\n */\n /**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Delay\n */\n\n dispose() {\n super.dispose();\n\n this._split.disconnect();\n this._leftFilter.dispose();\n this._rightFilter.dispose();\n this._merge.disconnect();\n this._leftGain.disconnect();\n this._rightGain.disconnect();\n this.leftDelay.disconnect();\n this.rightDelay.disconnect();\n\n this._split = undefined;\n this._leftFilter = undefined;\n this._rightFilter = undefined;\n this._merge = undefined;\n this._leftGain = undefined;\n this._rightGain = undefined;\n this.leftDelay = undefined;\n this.rightDelay = undefined;\n }\n}\n\nexport default Delay;\n","import { getAudioContext } from './audiocontext';\nimport CustomError from './errorHandler';\nimport Effect from './effect';\n\n/**\n * Reverb adds depth to a sound through a large number of decaying\n * echoes. It creates the perception that sound is occurring in a\n * physical space. The p5.Reverb has paramters for Time (how long does the\n * reverb last) and decayRate (how much the sound decays with each echo)\n * that can be set with the .set() or .process() methods. The p5.Convolver\n * extends p5.Reverb allowing you to recreate the sound of actual physical\n * spaces through convolution.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Reverb\n * @extends p5.Effect\n * @constructor\n * @example\n *
\n * let soundFile, reverb;\n * function preload() {\n * soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n *\n * reverb = new p5.Reverb();\n * soundFile.disconnect(); // so we'll only hear reverb...\n *\n * // connect soundFile to reverb, process w/\n * // 3 second reverbTime, decayRate of 2%\n * reverb.process(soundFile, 3, 2);\n * }\n *\n * function draw() {\n * let dryWet = constrain(map(mouseX, 0, width, 0, 1), 0, 1);\n * // 1 = all reverb, 0 = no reverb\n * reverb.drywet(dryWet);\n *\n * background(220);\n * text('tap to play', 10, 20);\n * text('dry/wet: ' + round(dryWet * 100) + '%', 10, height - 20);\n * }\n *\n * function playSound() {\n * soundFile.play();\n * }\n *
\n */\n\nclass Reverb extends Effect {\n constructor() {\n super();\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n // default params\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n }\n\n _initConvolverNode() {\n this.convolverNode = this.ac.createConvolver();\n this.input.connect(this.convolverNode);\n this.convolverNode.connect(this.wet);\n }\n\n _teardownConvolverNode() {\n if (this.convolverNode) {\n this.convolverNode.disconnect();\n delete this.convolverNode;\n }\n }\n\n _setBuffer(audioBuffer) {\n this._teardownConvolverNode();\n this._initConvolverNode();\n this.convolverNode.buffer = audioBuffer;\n }\n /**\n * Connect a source to the reverb, and assign reverb parameters.\n *\n * @method process\n * @for p5.Reverb\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\n process(src, seconds, decayRate, reverse) {\n src.connect(this.input);\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n }\n\n /**\n * Set the reverb settings. Similar to .process(), but without\n * assigning a new input.\n *\n * @method set\n * @for p5.Reverb\n * @param {Number} [seconds] Duration of the reverb, in seconds.\n * Min: 0, Max: 10. Defaults to 3.\n * @param {Number} [decayRate] Percentage of decay with each echo.\n * Min: 0, Max: 100. Defaults to 2.\n * @param {Boolean} [reverse] Play the reverb backwards or forwards.\n */\n set(seconds, decayRate, reverse) {\n var rebuild = false;\n if (seconds) {\n this._seconds = seconds;\n rebuild = true;\n }\n if (decayRate) {\n this._decay = decayRate;\n }\n if (reverse) {\n this._reverse = reverse;\n }\n if (rebuild) {\n this._buildImpulse();\n }\n }\n\n // DocBlocks for methods inherited from p5.Effect\n /**\n * Set the output level of the reverb effect.\n *\n * @method amp\n * @for p5.Reverb\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n /**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Reverb\n * @param {Object} unit\n */\n /**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Reverb\n */\n\n /**\n * Inspired by Simple Reverb by Jordan Santell\n * https://github.com/web-audio-components/simple-reverb/blob/master/index.js\n *\n * Utility function for building an impulse response\n * based on the module parameters.\n *\n * @private\n */\n _buildImpulse() {\n var rate = this.ac.sampleRate;\n var length = rate * this._seconds;\n var decay = this._decay;\n var impulse = this.ac.createBuffer(2, length, rate);\n var impulseL = impulse.getChannelData(0);\n var impulseR = impulse.getChannelData(1);\n var n, i;\n for (i = 0; i < length; i++) {\n n = this._reverse ? length - i : i;\n impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);\n }\n this._setBuffer(impulse);\n }\n\n dispose() {\n super.dispose();\n this._teardownConvolverNode();\n }\n}\n\n// =======================================================================\n// *** p5.Convolver ***\n// =======================================================================\n\n/**\n *

p5.Convolver extends p5.Reverb. It can emulate the sound of real\n * physical spaces through a process called \n * convolution.

\n *\n *

Convolution multiplies any audio input by an \"impulse response\"\n * to simulate the dispersion of sound over time. The impulse response is\n * generated from an audio file that you provide. One way to\n * generate an impulse response is to pop a balloon in a reverberant space\n * and record the echo. Convolution can also be used to experiment with\n * sound.

\n *\n *

Use the method createConvolution(path) to instantiate a\n * p5.Convolver with a path to your impulse response audio file.

\n *\n * @class p5.Convolver\n * @extends p5.Effect\n * @constructor\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call when loading succeeds\n * @param {Function} [errorCallback] function to call if loading fails.\n * This function will receive an error or\n * XMLHttpRequest object with information\n * about what went wrong.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\nclass Convolver extends Reverb {\n constructor(path, callback, errorCallback) {\n super();\n /**\n * Internally, the p5.Convolver uses the a\n * \n * Web Audio Convolver Node.\n *\n * @property {ConvolverNode} convolverNode\n */\n this._initConvolverNode();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n\n if (path) {\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n } else {\n // parameters\n this._seconds = 3;\n this._decay = 2;\n this._reverse = false;\n\n this._buildImpulse();\n }\n\n /**\n * If you load multiple impulse files using the .addImpulse method,\n * they will be stored as Objects in this Array. Toggle between them\n * with the toggleImpulse(id) method.\n *\n * @property {Array} impulses\n * @for p5.Convolver\n */\n this.impulses = [];\n this.set = null;\n }\n\n /**\n * Private method to load a buffer as an Impulse Response,\n * assign it to the convolverNode, and add to the Array of .impulses.\n *\n * @param {String} path\n * @param {Function} callback\n * @param {Function} errorCallback\n * @private\n */\n _loadBuffer(_path, callback, errorCallback) {\n var path = p5.prototype._checkFileFormats(_path);\n var self = this;\n var errorTrace = new Error().stack;\n var ac = getAudioContext();\n\n var request = new XMLHttpRequest();\n request.open('GET', path, true);\n request.responseType = 'arraybuffer';\n\n request.onload = function () {\n if (request.status === 200) {\n // on success loading file:\n ac.decodeAudioData(\n request.response,\n function (buff) {\n var buffer = {};\n var chunks = path.split('/');\n buffer.name = chunks[chunks.length - 1];\n buffer.audioBuffer = buff;\n self.impulses.push(buffer);\n self._setBuffer(buffer.audioBuffer);\n if (callback) {\n callback(buffer);\n }\n },\n // error decoding buffer. \"e\" is undefined in Chrome 11/22/2015\n function () {\n var err = new CustomError('decodeAudioData', errorTrace, self.url);\n var msg = 'AudioContext error at decodeAudioData for ' + self.url;\n if (errorCallback) {\n err.msg = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n );\n }\n // if request status != 200, it failed\n else {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'Unable to load ' +\n self.url +\n '. The request status was: ' +\n request.status +\n ' (' +\n request.statusText +\n ')';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n }\n };\n\n // if there is another error, aside from 404...\n request.onerror = function () {\n var err = new CustomError('loadConvolver', errorTrace, self.url);\n var msg =\n 'There was no response from the server at ' +\n self.url +\n '. Check the url and internet connectivity.';\n\n if (errorCallback) {\n err.message = msg;\n errorCallback(err);\n } else {\n console.error(\n msg + '\\n The error stack trace includes: \\n' + err.stack\n );\n }\n };\n request.send();\n }\n\n /**\n * Connect a source to the convolver.\n *\n * @method process\n * @for p5.Convolver\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *\n *
\n */\n process(src) {\n src.connect(this.input);\n }\n\n /**\n * Load and assign a new Impulse Response to the p5.Convolver.\n * The impulse is added to the .impulses array. Previous\n * impulses can be accessed with the .toggleImpulse(id)\n * method.\n *\n * @method addImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\n addImpulse(path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this._loadBuffer(path, callback, errorCallback);\n }\n\n /**\n * Similar to .addImpulse, except that the .impulses\n * Array is reset to save memory. A new .impulses\n * array is created with this impulse as the only item.\n *\n * @method resetImpulse\n * @for p5.Convolver\n * @param {String} path path to a sound file\n * @param {Function} callback function (optional)\n * @param {Function} errorCallback function (optional)\n */\n resetImpulse(path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n this.impulses = [];\n this._loadBuffer(path, callback, errorCallback);\n }\n\n /**\n * If you have used .addImpulse() to add multiple impulses\n * to a p5.Convolver, then you can use this method to toggle between\n * the items in the .impulses Array. Accepts a parameter\n * to identify which impulse you wish to use, identified either by its\n * original filename (String) or by its position in the .impulses\n * Array (Number).
\n * You can access the objects in the .impulses Array directly. Each\n * Object has two attributes: an .audioBuffer (type:\n * Web Audio \n * AudioBuffer) and a .name, a String that corresponds\n * with the original filename.\n *\n * @method toggleImpulse\n * @for p5.Convolver\n * @param {String|Number} id Identify the impulse by its original filename\n * (String), or by its position in the\n * .impulses Array (Number).\n */\n toggleImpulse(id) {\n if (typeof id === 'number' && id < this.impulses.length) {\n this._setBuffer(this.impulses[id].audioBuffer);\n }\n if (typeof id === 'string') {\n for (var i = 0; i < this.impulses.length; i++) {\n if (this.impulses[i].name === id) {\n this._setBuffer(this.impulses[i].audioBuffer);\n break;\n }\n }\n }\n }\n\n dispose() {\n super.dispose();\n\n // remove all the Impulse Response buffers\n for (var i in this.impulses) {\n if (this.impulses[i]) {\n this.impulses[i] = null;\n }\n }\n }\n}\n\n/**\n * Create a p5.Convolver. Accepts a path to a soundfile\n * that will be used to generate an impulse response.\n *\n * @method createConvolver\n * @for p5\n * @param {String} path path to a sound file\n * @param {Function} [callback] function to call if loading is successful.\n * The object will be passed in as the argument\n * to the callback function.\n * @param {Function} [errorCallback] function to call if loading is not successful.\n * A custom error will be passed in as the argument\n * to the callback function.\n * @return {p5.Convolver}\n * @example\n *
\n * let cVerb, sound;\n * function preload() {\n * // We have both MP3 and OGG versions of all sound assets\n * soundFormats('ogg', 'mp3');\n *\n * // Try replacing 'bx-spring' with other soundfiles like\n * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n * cVerb = createConvolver('assets/bx-spring.mp3');\n *\n * // Try replacing 'Damscray_DancingTiger' with\n * // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n * sound = loadSound('assets/Damscray_DancingTiger.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSound);\n * background(220);\n * text('tap to play', 20, 20);\n *\n * // disconnect from master output...\n * sound.disconnect();\n *\n * // ...and process with cVerb\n * // so that we only hear the convolution\n * cVerb.process(sound);\n * }\n *\n * function playSound() {\n * sound.play();\n * }\n *
\n */\nfunction createConvolver(path, callback, errorCallback) {\n // if loading locally without a server\n if (\n window.location.origin.indexOf('file://') > -1 &&\n window.cordova === 'undefined'\n ) {\n alert(\n 'This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'\n );\n }\n var self = this;\n var cReverb = new Convolver(\n path,\n function (buffer) {\n if (typeof callback === 'function') {\n callback(buffer);\n }\n\n if (typeof self._decrementPreload === 'function') {\n self._decrementPreload();\n }\n },\n errorCallback\n );\n cReverb.impulses = [];\n return cReverb;\n}\n\nexport { Reverb, Convolver, createConvolver };\n","import p5sound from './master';\n// requires the Tone.js library's Clock (MIT license, Yotam Mann)\n// https://github.com/TONEnoTONE/Tone.js/\nimport Clock from 'Tone/core/Clock';\n\nclass Metro {\n constructor() {\n this.clock = new Clock({\n callback: this.ontick.bind(this),\n });\n this.syncedParts = [];\n this.bpm = 120; // gets overridden by p5.Part\n this._init();\n\n this.prevTick = 0;\n this.tatumTime = 0;\n\n this.tickCallback = function () {};\n }\n\n ontick(tickTime) {\n var elapsedTime = tickTime - this.prevTick;\n var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;\n if (elapsedTime - this.tatumTime <= -0.02) {\n return;\n } else {\n // console.log('ok', this.syncedParts[0].phrases[0].name);\n this.prevTick = tickTime;\n\n // for all of the active things on the metro:\n var self = this;\n this.syncedParts.forEach(function (thisPart) {\n if (!thisPart.isPlaying) return;\n thisPart.incrementStep(secondsFromNow);\n // each synced source keeps track of its own beat number\n thisPart.phrases.forEach(function (thisPhrase) {\n var phraseArray = thisPhrase.sequence;\n var bNum = self.metroTicks % phraseArray.length;\n if (\n phraseArray[bNum] !== 0 &&\n (self.metroTicks < phraseArray.length || !thisPhrase.looping)\n ) {\n thisPhrase.callback(secondsFromNow, phraseArray[bNum]);\n }\n });\n });\n this.metroTicks += 1;\n this.tickCallback(secondsFromNow);\n }\n }\n\n setBPM(bpm, rampTime = 0) {\n var beatTime = 60 / (bpm * this.tatums);\n var now = p5sound.audiocontext.currentTime;\n this.tatumTime = beatTime;\n\n this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);\n this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);\n this.bpm = bpm;\n }\n\n getBPM() {\n return (this.clock.getRate() / this.tatums) * 60;\n }\n\n _init() {\n this.metroTicks = 0;\n // this.setBPM(120);\n }\n\n // clear existing synced parts, add only this one\n resetSync(part) {\n this.syncedParts = [part];\n }\n\n // push a new synced part to the array\n pushSync(part) {\n this.syncedParts.push(part);\n }\n\n start(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.start(now + t);\n this.setBPM(this.bpm);\n }\n\n stop(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n this.clock.stop(now + t);\n }\n\n beatLength(tatums) {\n this.tatums = 1 / tatums / 4; // lowest possible division of a beat\n }\n}\nexport default Metro;\n","import p5sound from './master';\nimport Metro from './metro';\n\nvar BPM = 120;\n\n/**\n * Set the global tempo, in beats per minute, for all\n * p5.Parts. This method will impact all active p5.Parts.\n *\n * @method setBPM\n * @for p5\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\np5.prototype.setBPM = function (bpm, rampTime) {\n BPM = bpm;\n for (var i in p5sound.parts) {\n if (p5sound.parts[i]) {\n p5sound.parts[i].setBPM(bpm, rampTime);\n }\n }\n};\n\n/**\n *

A phrase is a pattern of musical events over time, i.e.\n * a series of notes and rests.

\n *\n *

Phrases must be added to a p5.Part for playback, and\n * each part can play multiple phrases at the same time.\n * For example, one Phrase might be a kick drum, another\n * could be a snare, and another could be the bassline.

\n *\n *

The first parameter is a name so that the phrase can be\n * modified or deleted later. The callback is a a function that\n * this phrase will call at every step—for example it might be\n * called playNote(value){}. The array determines\n * which value is passed into the callback at each step of the\n * phrase. It can be numbers, an object with multiple numbers,\n * or a zero (0) indicates a rest so the callback won't be called).

\n *\n * @class p5.Phrase\n * @constructor\n * @param {String} name Name so that you can access the Phrase.\n * @param {Function} callback The name of a function that this phrase\n * will call. Typically it will play a sound,\n * and accept two parameters: a time at which\n * to play the sound (in seconds from now),\n * and a value from the sequence array. The\n * time should be passed into the play() or\n * start() method to ensure precision.\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n * @example\n *
\n * let mySound, myPhrase, myPart;\n * let pattern = [1,0,0,2,0,2,0,0];\n *\n * function preload() {\n * mySound = loadSound('assets/beatbox.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * text('tap to play', width/2, height/2);\n * textAlign(CENTER, CENTER);\n *\n * myPhrase = new p5.Phrase('bbox', onEachStep, pattern);\n * myPart = new p5.Part();\n * myPart.addPhrase(myPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function onEachStep(time, playbackRate) {\n * mySound.rate(playbackRate);\n * mySound.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n * myPart.start();\n * }\n *
\n */\nclass Phrase {\n constructor(name, callback, sequence) {\n this.phraseStep = 0;\n this.name = name;\n this.callback = callback;\n /**\n * Array of values to pass into the callback\n * at each step of the phrase. Depending on the callback\n * function's requirements, these values may be numbers,\n * strings, or an object with multiple parameters.\n * Zero (0) indicates a rest.\n *\n * @property {Array} sequence\n */\n this.sequence = sequence;\n }\n}\n\n/**\n *

A p5.Part plays back one or more p5.Phrases. Instantiate a part\n * with steps and tatums. By default, each step represents a 1/16th note.

\n *\n *

See p5.Phrase for more about musical timing.

\n *\n * @class p5.Part\n * @constructor\n * @param {Number} [steps] Steps in the part\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)\n * @example\n *
\n * let box, drum, myPart;\n * let boxPat = [1,0,0,2,0,2,0,0];\n * let drumPat = [0,1,1,0,2,0,1,0];\n *\n * function preload() {\n * box = loadSound('assets/beatbox.mp3');\n * drum = loadSound('assets/drum.mp3');\n * }\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playMyPart);\n * background(220);\n * textAlign(CENTER, CENTER);\n * text('tap to play', width/2, height/2);\n *\n * let boxPhrase = new p5.Phrase('box', playBox, boxPat);\n * let drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\n * myPart = new p5.Part();\n * myPart.addPhrase(boxPhrase);\n * myPart.addPhrase(drumPhrase);\n * myPart.setBPM(60);\n * }\n *\n * function playBox(time, playbackRate) {\n * box.rate(playbackRate);\n * box.play(time);\n * }\n *\n * function playDrum(time, playbackRate) {\n * drum.rate(playbackRate);\n * drum.play(time);\n * }\n *\n * function playMyPart() {\n * userStartAudio();\n *\n * myPart.start();\n * }\n *
\n */\nclass Part {\n constructor(steps, bLength) {\n this.length = steps || 0; // how many beats\n this.partStep = 0;\n this.phrases = [];\n this.isPlaying = false;\n this.noLoop();\n this.tatums = bLength || 0.0625; // defaults to quarter note\n\n this.metro = new Metro();\n this.metro._init();\n this.metro.beatLength(this.tatums);\n this.metro.setBPM(BPM);\n p5sound.parts.push(this);\n this.callback = function () {};\n }\n\n /**\n * Set the tempo of this part, in Beats Per Minute.\n *\n * @method setBPM\n * @for p5.Part\n * @param {Number} BPM Beats Per Minute\n * @param {Number} [rampTime] Seconds from now\n */\n setBPM(tempo, rampTime) {\n this.metro.setBPM(tempo, rampTime);\n }\n\n /**\n * Returns the tempo, in Beats Per Minute, of this part.\n *\n * @method getBPM\n * @for p5.Part\n * @return {Number}\n */\n getBPM() {\n return this.metro.getBPM();\n }\n\n /**\n * Start playback of this part. It will play\n * through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method start\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\n start(time) {\n if (!this.isPlaying) {\n this.isPlaying = true;\n this.metro.resetSync(this);\n var t = time || 0;\n this.metro.start(t);\n }\n }\n\n /**\n * Loop playback of this part. It will begin\n * looping through all of its phrases at a speed\n * determined by setBPM.\n *\n * @method loop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\n loop(time) {\n this.looping = true;\n // rest onended function\n this.onended = function () {\n this.partStep = 0;\n };\n var t = time || 0;\n this.start(t);\n }\n\n /**\n * Tell the part to stop looping.\n *\n * @method noLoop\n * @for p5.Part\n */\n noLoop() {\n this.looping = false;\n // rest onended function\n this.onended = function () {\n this.stop();\n };\n }\n\n /**\n * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.\n *\n * @method stop\n * @for p5.Part\n * @param {Number} [time] seconds from now\n */\n stop(time) {\n this.partStep = 0;\n this.pause(time);\n }\n\n /**\n * Pause the part. Playback will resume\n * from the current step.\n *\n * @method pause\n * @for p5.Part\n * @param {Number} time seconds from now\n */\n pause(time) {\n this.isPlaying = false;\n var t = time || 0;\n this.metro.stop(t);\n }\n\n /**\n * Add a p5.Phrase to this Part.\n *\n * @method addPhrase\n * @for p5.Part\n * @param {p5.Phrase} phrase reference to a p5.Phrase\n */\n addPhrase(name, callback, array) {\n var p;\n if (arguments.length === 3) {\n p = new Phrase(name, callback, array);\n } else if (arguments[0] instanceof Phrase) {\n p = arguments[0];\n } else {\n throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';\n }\n this.phrases.push(p);\n // reset the length if phrase is longer than part's existing length\n if (p.sequence.length > this.length) {\n this.length = p.sequence.length;\n }\n }\n\n /**\n * Remove a phrase from this part, based on the name it was\n * given when it was created.\n *\n * @method removePhrase\n * @for p5.Part\n * @param {String} phraseName\n */\n removePhrase(name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases.splice(i, 1);\n }\n }\n }\n\n /**\n * Get a phrase from this part, based on the name it was\n * given when it was created. Now you can modify its array.\n *\n * @method getPhrase\n * @for p5.Part\n * @param {String} phraseName\n */\n getPhrase(name) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n return this.phrases[i];\n }\n }\n }\n\n /**\n * Find all sequences with the specified name, and replace their patterns with the specified array.\n *\n * @method replaceSequence\n * @for p5.Part\n * @param {String} phraseName\n * @param {Array} sequence Array of values to pass into the callback\n * at each step of the phrase.\n */\n replaceSequence(name, array) {\n for (var i in this.phrases) {\n if (this.phrases[i].name === name) {\n this.phrases[i].sequence = array;\n }\n }\n }\n\n incrementStep(time) {\n if (this.partStep < this.length - 1) {\n this.callback(time);\n this.partStep += 1;\n } else {\n if (!this.looping && this.partStep === this.length - 1) {\n // this.callback(time);\n this.onended();\n }\n }\n }\n\n /**\n * Set the function that will be called at every step. This will clear the previous function.\n *\n * @method onStep\n * @for p5.Part\n * @param {Function} callback The name of the callback\n * you want to fire\n * on every beat/tatum.\n */\n onStep(callback) {\n this.callback = callback;\n }\n}\n\n// ===============\n// p5.Score\n// ===============\n\n/**\n * A Score consists of a series of Parts. The parts will\n * be played back in order. For example, you could have an\n * A part, a B part, and a C part, and play them back in this order\n * new p5.Score(a, a, b, a, c)\n *\n * @class p5.Score\n * @constructor\n * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.\n */\nclass Score {\n constructor() {\n // for all of the arguments\n this.parts = [];\n this.currentPart = 0;\n\n var thisScore = this;\n for (var i in arguments) {\n if (arguments[i] && this.parts[i]) {\n this.parts[i] = arguments[i];\n this.parts[i].nextPart = this.parts[i + 1];\n this.parts[i].onended = function () {\n thisScore.resetPart(i);\n playNextPart(thisScore);\n };\n }\n }\n this.looping = false;\n }\n\n onended() {\n if (this.looping) {\n // this.resetParts();\n this.parts[0].start();\n } else {\n this.parts[this.parts.length - 1].onended = function () {\n this.stop();\n this.resetParts();\n };\n }\n this.currentPart = 0;\n }\n\n /**\n * Start playback of the score.\n *\n * @method start\n * @for p5.Score\n */\n start() {\n this.parts[this.currentPart].start();\n this.scoreStep = 0;\n }\n\n /**\n * Stop playback of the score.\n *\n * @method stop\n * @for p5.Score\n */\n stop() {\n this.parts[this.currentPart].stop();\n this.currentPart = 0;\n this.scoreStep = 0;\n }\n\n /**\n * Pause playback of the score.\n *\n * @method pause\n * @for p5.Score\n */\n pause() {\n this.parts[this.currentPart].stop();\n }\n\n /**\n * Loop playback of the score.\n *\n * @method loop\n * @for p5.Score\n */\n loop() {\n this.looping = true;\n this.start();\n }\n\n /**\n * Stop looping playback of the score. If it\n * is currently playing, this will go into effect\n * after the current round of playback completes.\n *\n * @method noLoop\n * @for p5.Score\n */\n noLoop() {\n this.looping = false;\n }\n\n resetParts() {\n var self = this;\n this.parts.forEach(function (part) {\n self.resetParts[part];\n });\n }\n\n resetPart(i) {\n this.parts[i].stop();\n this.parts[i].partStep = 0;\n for (var p in this.parts[i].phrases) {\n if (this.parts[i]) {\n this.parts[i].phrases[p].phraseStep = 0;\n }\n }\n }\n\n /**\n * Set the tempo for all parts in the score\n *\n * @method setBPM\n * @for p5.Score\n * @param {Number} BPM Beats Per Minute\n * @param {Number} rampTime Seconds from now\n */\n setBPM(bpm, rampTime) {\n for (var i in this.parts) {\n if (this.parts[i]) {\n this.parts[i].setBPM(bpm, rampTime);\n }\n }\n }\n}\n\nfunction playNextPart(aScore) {\n aScore.currentPart++;\n if (aScore.currentPart >= aScore.parts.length) {\n aScore.scoreStep = 0;\n aScore.onended();\n } else {\n aScore.scoreStep = 0;\n aScore.parts[aScore.currentPart - 1].stop();\n aScore.parts[aScore.currentPart].start();\n }\n}\n\nexport { Phrase, Part, Score };\n","import p5sound from './master';\nimport Clock from 'Tone/core/Clock';\n\n/**\n * SoundLoop\n *\n * @class p5.SoundLoop\n * @constructor\n *\n * @param {Function} callback this function will be called on each iteration of theloop\n * @param {Number|String} [interval] amount of time (if a number) or beats (if a string, following Tone.Time convention) for each iteration of the loop. Defaults to 1 second.\n *\n * @example\n *
\n * let synth, soundLoop;\n * let notePattern = [60, 62, 64, 67, 69, 72];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * colorMode(HSB);\n * background(0, 0, 86);\n * text('tap to start/stop', 10, 20);\n *\n * //the looper's callback is passed the timeFromNow\n * //this value should be used as a reference point from\n * //which to schedule sounds\n * let intervalInSeconds = 0.2;\n * soundLoop = new p5.SoundLoop(onSoundLoop, intervalInSeconds);\n *\n * synth = new p5.MonoSynth();\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * if (soundLoop.isPlaying) {\n * soundLoop.stop();\n * } else {\n * // start the loop\n * soundLoop.start();\n * }\n * }\n *\n * function onSoundLoop(timeFromNow) {\n * let noteIndex = (soundLoop.iterations - 1) % notePattern.length;\n * let note = midiToFreq(notePattern[noteIndex]);\n * synth.play(note, 0.5, timeFromNow);\n * background(noteIndex * 360 / notePattern.length, 50, 100);\n * }\n *
\n */\nclass SoundLoop {\n constructor(callback, interval) {\n /**\n * Getters and Setters, setting any paramter will result in a change in the clock's\n * frequency, that will be reflected after the next callback\n * beats per minute (defaults to 60)\n * @property {Number} bpm\n * @for p5.SoundLoop\n */\n Object.defineProperty(this, 'bpm', {\n get: function () {\n return this._bpm;\n },\n set: function (bpm) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the BPM in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._bpm = bpm;\n this._update();\n },\n });\n\n /**\n * number of quarter notes in a measure (defaults to 4)\n * @property {Number} timeSignature\n * @for p5.SoundLoop\n */\n Object.defineProperty(this, 'timeSignature', {\n get: function () {\n return this._timeSignature;\n },\n set: function (timeSig) {\n if (!this.musicalTimeMode) {\n console.warn(\n 'Changing the timeSignature in \"seconds\" mode has no effect. ' +\n 'BPM is only relevant in musicalTimeMode ' +\n 'when the interval is specified as a string ' +\n '(\"2n\", \"4n\", \"1m\"...etc)'\n );\n }\n this._timeSignature = timeSig;\n this._update();\n },\n });\n\n /**\n * length of the loops interval\n * @property {Number|String} interval\n * @for p5.SoundLoop\n */\n Object.defineProperty(this, 'interval', {\n get: function () {\n return this._interval;\n },\n set: function (interval) {\n this.musicalTimeMode = typeof interval === 'number' ? false : true;\n this._interval = interval;\n this._update();\n },\n });\n\n /**\n * how many times the callback has been called so far\n * @property {Number} iterations\n * @for p5.SoundLoop\n * @readonly\n */\n Object.defineProperty(this, 'iterations', {\n get: function () {\n return this.clock.ticks;\n },\n });\n\n this.callback = callback;\n /**\n * musicalTimeMode uses Tone.Time convention\n * true if string, false if number\n * @property {Boolean} musicalTimeMode\n */\n this.musicalTimeMode = typeof this._interval === 'number' ? false : true;\n\n this._interval = interval || 1;\n\n /**\n * musicalTimeMode variables\n * modify these only when the interval is specified in musicalTime format as a string\n */\n this._timeSignature = 4;\n this._bpm = 60;\n\n this.isPlaying = false;\n\n /**\n * Set a limit to the number of loops to play. defaults to Infinity\n * @property {Number} maxIterations\n */\n this.maxIterations = Infinity;\n var self = this;\n\n this.clock = new Clock({\n callback: function (time) {\n var timeFromNow = time - p5sound.audiocontext.currentTime;\n /**\n * Do not initiate the callback if timeFromNow is < 0\n * This ususually occurs for a few milliseconds when the page\n * is not fully loaded\n *\n * The callback should only be called until maxIterations is reached\n */\n if (timeFromNow > 0 && self.iterations <= self.maxIterations) {\n self.callback(timeFromNow);\n }\n },\n frequency: this._calcFreq(),\n });\n }\n\n /**\n * Start the loop\n * @method start\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a starting time\n */\n start(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (!this.isPlaying) {\n this.clock.start(now + t);\n this.isPlaying = true;\n }\n }\n\n /**\n * Stop the loop\n * @method stop\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a stopping time\n */\n stop(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.stop(now + t);\n this.isPlaying = false;\n }\n }\n\n /**\n * Pause the loop\n * @method pause\n * @for p5.SoundLoop\n * @param {Number} [timeFromNow] schedule a pausing time\n */\n pause(timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n if (this.isPlaying) {\n this.clock.pause(now + t);\n this.isPlaying = false;\n }\n }\n\n /**\n * Synchronize loops. Use this method to start two or more loops in synchronization\n * or to start a loop in synchronization with a loop that is already playing\n * This method will schedule the implicit loop in sync with the explicit master loop\n * i.e. loopToStart.syncedStart(loopToSyncWith)\n *\n * @method syncedStart\n * @for p5.SoundLoop\n * @param {Object} otherLoop a p5.SoundLoop to sync with\n * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds\n */\n syncedStart(otherLoop, timeFromNow) {\n var t = timeFromNow || 0;\n var now = p5sound.audiocontext.currentTime;\n\n if (!otherLoop.isPlaying) {\n otherLoop.clock.start(now + t);\n otherLoop.isPlaying = true;\n this.clock.start(now + t);\n this.isPlaying = true;\n } else if (otherLoop.isPlaying) {\n var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;\n this.clock.start(now + time);\n this.isPlaying = true;\n }\n }\n /**\n * Updates frequency value, reflected in next callback\n * @private\n * @for p5.SoundLoop\n * @method _update\n */\n _update() {\n this.clock.frequency.value = this._calcFreq();\n }\n\n /**\n * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature\n * @private\n * @for p5.SoundLoop\n * @method _calcFreq\n * @return {Number} new clock frequency value\n */\n _calcFreq() {\n //Seconds mode, bpm / timesignature has no effect\n if (typeof this._interval === 'number') {\n this.musicalTimeMode = false;\n return 1 / this._interval;\n }\n //Musical timing mode, calculate interval based bpm, interval,and time signature\n else if (typeof this._interval === 'string') {\n this.musicalTimeMode = true;\n return (\n (this._bpm / 60 / this._convertNotation(this._interval)) *\n (this._timeSignature / 4)\n );\n }\n }\n\n /**\n * Convert notation from musical time format to seconds\n * Uses Tone.Time convention\n * @private\n * @for p5.SoundLoop\n * @method _convertNotation\n * @param {String} value value to be converted\n * @return {Number} converted value in seconds\n */\n _convertNotation(value) {\n var type = value.slice(-1);\n value = Number(value.slice(0, -1));\n switch (type) {\n case 'm':\n return this._measure(value);\n case 'n':\n return this._note(value);\n default:\n console.warn(\n 'Specified interval is not formatted correctly. See Tone.js ' +\n 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'\n );\n }\n }\n\n /**\n * Helper conversion methods of measure and note\n * @private\n * @for p5.SoundLoop\n * @method _measure\n */\n _measure(value) {\n return value * this._timeSignature;\n }\n\n /**\n * @private\n * @method _note\n * @for p5.SoundLoop\n */\n _note(value) {\n return this._timeSignature / value;\n }\n}\n\nexport default SoundLoop;\n","import Effect from './effect';\n\n/**\n * Compressor is an audio effect class that performs dynamics compression\n * on an audio input source. This is a very commonly used technique in music\n * and sound production. Compression creates an overall louder, richer,\n * and fuller sound by lowering the volume of louds and raising that of softs.\n * Compression can be used to avoid clipping (sound distortion due to\n * peaks in volume) and is especially useful when many sounds are played\n * at once. Compression can be used on indivudal sound sources in addition\n * to the master output.\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Compressor\n * @constructor\n * @extends p5.Effect\n *\n *\n */\nclass Compressor extends Effect {\n constructor() {\n super();\n /**\n *\n * The p5.Compressor is built with a Web Audio Dynamics Compressor Node\n * \n * @property {AudioNode} compressor\n */\n\n this.compressor = this.ac.createDynamicsCompressor();\n\n this.input.connect(this.compressor);\n this.compressor.connect(this.wet);\n }\n\n /**\n * Performs the same function as .connect, but also accepts\n * optional parameters to set compressor's audioParams\n * @method process\n * @for p5.Compressor\n *\n * @param {Object} src Sound source to be connected\n *\n * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [threshold] The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\n process(src, attack, knee, ratio, threshold, release) {\n src.connect(this.input);\n this.set(attack, knee, ratio, threshold, release);\n }\n\n /**\n * Set the paramters of a compressor.\n * @method set\n * @for p5.Compressor\n * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} knee A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} ratio The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n */\n set(attack, knee, ratio, threshold, release) {\n if (typeof attack !== 'undefined') {\n this.attack(attack);\n }\n if (typeof knee !== 'undefined') {\n this.knee(knee);\n }\n if (typeof ratio !== 'undefined') {\n this.ratio(ratio);\n }\n if (typeof threshold !== 'undefined') {\n this.threshold(threshold);\n }\n if (typeof release !== 'undefined') {\n this.release(release);\n }\n }\n\n /**\n * Get current attack or set value w/ time ramp\n *\n *\n * @method attack\n * @for p5.Compressor\n * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n * default = .003, range 0 - 1\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n attack(attack, time) {\n var t = time || 0;\n if (typeof attack === 'number') {\n this.compressor.attack.value = attack;\n this.compressor.attack.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.attack.linearRampToValueAtTime(\n attack,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof attack !== 'undefined') {\n attack.connect(this.compressor.attack);\n }\n return this.compressor.attack.value;\n }\n\n /**\n * Get current knee or set value w/ time ramp\n *\n * @method knee\n * @for p5.Compressor\n * @param {Number} [knee] A decibel value representing the range above the\n * threshold where the curve smoothly transitions to the \"ratio\" portion.\n * default = 30, range 0 - 40\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n knee(knee, time) {\n var t = time || 0;\n if (typeof knee === 'number') {\n this.compressor.knee.value = knee;\n this.compressor.knee.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.knee.linearRampToValueAtTime(\n knee,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof knee !== 'undefined') {\n knee.connect(this.compressor.knee);\n }\n return this.compressor.knee.value;\n }\n\n /**\n * Get current ratio or set value w/ time ramp\n * @method ratio\n * @for p5.Compressor\n * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output\n * default = 12, range 1 - 20\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n ratio(ratio, time) {\n var t = time || 0;\n if (typeof ratio === 'number') {\n this.compressor.ratio.value = ratio;\n this.compressor.ratio.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.ratio.linearRampToValueAtTime(\n ratio,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof ratio !== 'undefined') {\n ratio.connect(this.compressor.ratio);\n }\n return this.compressor.ratio.value;\n }\n\n /**\n * Get current threshold or set value w/ time ramp\n * @method threshold\n * @for p5.Compressor\n * @param {Number} threshold The decibel value above which the compression will start taking effect\n * default = -24, range -100 - 0\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n threshold(threshold, time) {\n var t = time || 0;\n if (typeof threshold === 'number') {\n this.compressor.threshold.value = threshold;\n this.compressor.threshold.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.threshold.linearRampToValueAtTime(\n threshold,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof threshold !== 'undefined') {\n threshold.connect(this.compressor.threshold);\n }\n return this.compressor.threshold.value;\n }\n\n /**\n * Get current release or set value w/ time ramp\n * @method release\n * @for p5.Compressor\n * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB\n * default = .25, range 0 - 1\n *\n * @param {Number} [time] Assign time value to schedule the change in value\n */\n release(release, time) {\n var t = time || 0;\n if (typeof release === 'number') {\n this.compressor.release.value = release;\n this.compressor.release.cancelScheduledValues(\n this.ac.currentTime + 0.01 + t\n );\n this.compressor.release.linearRampToValueAtTime(\n release,\n this.ac.currentTime + 0.02 + t\n );\n } else if (typeof number !== 'undefined') {\n release.connect(this.compressor.release);\n }\n return this.compressor.release.value;\n }\n\n /**\n * Return the current reduction value\n *\n * @method reduction\n * @for p5.Compressor\n * @return {Number} Value of the amount of gain reduction that is applied to the signal\n */\n reduction() {\n return this.compressor.reduction.value;\n }\n\n dispose() {\n super.dispose();\n if (this.compressor) {\n this.compressor.disconnect();\n delete this.compressor;\n }\n }\n}\n\nexport default Compressor;\n","/**\n *

PeakDetect works in conjunction with p5.FFT to\n * look for onsets in some or all of the frequency spectrum.\n *

\n *

\n * To use p5.PeakDetect, call update in the draw loop\n * and pass in a p5.FFT object.\n *

\n *

\n * You can listen for a specific part of the frequency spectrum by\n * setting the range between freq1 and freq2.\n *

\n *\n *

threshold is the threshold for detecting a peak,\n * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\n * as 1.0.

\n *\n *

\n * The update method is meant to be run in the draw loop, and\n * frames determines how many loops must pass before\n * another peak can be detected.\n * For example, if the frameRate() = 60, you could detect the beat of a\n * 120 beat-per-minute song with this equation:\n * framesPerPeak = 60 / (estimatedBPM / 60 );\n *

\n *\n *

\n * Based on example contribtued by @b2renger, and a simple beat detection\n * explanation by Felix Turner.\n *

\n *\n * @class p5.PeakDetect\n * @constructor\n * @param {Number} [freq1] lowFrequency - defaults to 20Hz\n * @param {Number} [freq2] highFrequency - defaults to 20000 Hz\n * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1\n * scaled logarithmically where 0.1 is 1/2 the loudness\n * of 1.0. Defaults to 0.35.\n * @param {Number} [framesPerPeak] Defaults to 20.\n * @example\n *
\n *\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 10;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * background(0);\n * noStroke();\n * fill(255);\n * textAlign(CENTER);\n *\n * // p5.PeakDetect requires a p5.FFT\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n * }\n *\n * function draw() {\n * background(0);\n * text('click to play/pause', width/2, height/2);\n *\n * // peakDetect accepts an fft post-analysis\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * if ( peakDetect.isDetected ) {\n * ellipseWidth = 50;\n * } else {\n * ellipseWidth *= 0.95;\n * }\n *\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // toggle play/stop when canvas is clicked\n * function mouseClicked() {\n * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * }\n * }\n *
\n */\nclass PeakDetect {\n // framesPerPeak determines how often to look for a beat.\n // If a beat is provided, try to look for a beat based on bpm\n constructor(freq1, freq2, threshold, _framesPerPeak) {\n this.framesPerPeak = _framesPerPeak || 20;\n this.framesSinceLastPeak = 0;\n this.decayRate = 0.95;\n\n this.threshold = threshold || 0.35;\n this.cutoff = 0;\n\n // how much to increase the cutoff\n // TO DO: document this / figure out how to make it accessible\n this.cutoffMult = 1.5;\n\n this.energy = 0;\n this.penergy = 0;\n\n // TO DO: document this property / figure out how to make it accessible\n this.currentValue = 0;\n\n /**\n * isDetected is set to true when a peak is detected.\n *\n * @attribute isDetected {Boolean}\n * @default false\n */\n this.isDetected = false;\n\n this.f1 = freq1 || 40;\n this.f2 = freq2 || 20000;\n\n // function to call when a peak is detected\n this._onPeak = function () {};\n }\n\n /**\n * The update method is run in the draw loop.\n *\n * Accepts an FFT object. You must call .analyze()\n * on the FFT object prior to updating the peakDetect\n * because it relies on a completed FFT analysis.\n *\n * @method update\n * @param {p5.FFT} fftObject A p5.FFT object\n */\n update(fftObject) {\n var nrg = (this.energy = fftObject.getEnergy(this.f1, this.f2) / 255);\n if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) {\n // trigger callback\n this._onPeak();\n this.isDetected = true;\n\n // debounce\n this.cutoff = nrg * this.cutoffMult;\n this.framesSinceLastPeak = 0;\n } else {\n this.isDetected = false;\n if (this.framesSinceLastPeak <= this.framesPerPeak) {\n this.framesSinceLastPeak++;\n } else {\n this.cutoff *= this.decayRate;\n this.cutoff = Math.max(this.cutoff, this.threshold);\n }\n }\n\n this.currentValue = nrg;\n this.penergy = nrg;\n }\n\n /**\n * onPeak accepts two arguments: a function to call when\n * a peak is detected. The value of the peak,\n * between 0.0 and 1.0, is passed to the callback.\n *\n * @method onPeak\n * @param {Function} callback Name of a function that will\n * be called when a peak is\n * detected.\n * @param {Object} [val] Optional value to pass\n * into the function when\n * a peak is detected.\n * @example\n *
\n * var cnv, soundFile, fft, peakDetect;\n * var ellipseWidth = 0;\n *\n * function preload() {\n * soundFile = loadSound('assets/beat.mp3');\n * }\n *\n * function setup() {\n * cnv = createCanvas(100,100);\n * textAlign(CENTER);\n *\n * fft = new p5.FFT();\n * peakDetect = new p5.PeakDetect();\n *\n * setupSound();\n *\n * // when a beat is detected, call triggerBeat()\n * peakDetect.onPeak(triggerBeat);\n * }\n *\n * function draw() {\n * background(0);\n * fill(255);\n * text('click to play', width/2, height/2);\n *\n * fft.analyze();\n * peakDetect.update(fft);\n *\n * ellipseWidth *= 0.95;\n * ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n * }\n *\n * // this function is called by peakDetect.onPeak\n * function triggerBeat() {\n * ellipseWidth = 50;\n * }\n *\n * // mouseclick starts/stops sound\n * function setupSound() {\n * cnv.mouseClicked( function() {\n * if (soundFile.isPlaying() ) {\n * soundFile.stop();\n * } else {\n * soundFile.play();\n * }\n * });\n * }\n *
\n */\n onPeak(callback, val) {\n var self = this;\n\n self._onPeak = function () {\n callback(self.energy, val);\n };\n }\n}\n\nexport default PeakDetect;\n","// inspiration: recorder.js, Tone.js & typedarray.org\n\nimport p5sound from './master';\nimport { safeBufferSize } from './helpers';\nimport processorNames from './audioWorklet/processorNames';\n\nconst ac = p5sound.audiocontext;\n\n/**\n *

Record sounds for playback and/or to save as a .wav file.\n * The p5.SoundRecorder records all sound output from your sketch,\n * or can be assigned a specific source with setInput().

\n *

The record() method accepts a p5.SoundFile as a parameter.\n * When playback is stopped (either after the given amount of time,\n * or with the stop() method), the p5.SoundRecorder will send its\n * recording to that p5.SoundFile for playback.

\n *\n * @class p5.SoundRecorder\n * @constructor\n * @example\n *
\n * let mic, recorder, soundFile;\n * let state = 0;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(canvasPressed);\n * background(220);\n * textAlign(CENTER, CENTER);\n *\n * // create an audio in\n * mic = new p5.AudioIn();\n *\n * // prompts user to enable their browser mic\n * mic.start();\n *\n * // create a sound recorder\n * recorder = new p5.SoundRecorder();\n *\n * // connect the mic to the recorder\n * recorder.setInput(mic);\n *\n * // this sound file will be used to\n * // playback & save the recording\n * soundFile = new p5.SoundFile();\n *\n * text('tap to record', width/2, height/2);\n * }\n *\n * function canvasPressed() {\n * // ensure audio is enabled\n * userStartAudio();\n *\n * // make sure user enabled the mic\n * if (state === 0 && mic.enabled) {\n *\n * // record to our p5.SoundFile\n * recorder.record(soundFile);\n *\n * background(255,0,0);\n * text('Recording!', width/2, height/2);\n * state++;\n * }\n * else if (state === 1) {\n * background(0,255,0);\n *\n * // stop recorder and\n * // send result to soundFile\n * recorder.stop();\n *\n * text('Done! Tap to play and download', width/2, height/2, width - 20);\n * state++;\n * }\n *\n * else if (state === 2) {\n * soundFile.play(); // play the result!\n * save(soundFile, 'mySound.wav');\n * state++;\n * }\n * }\n *
\n */\nclass SoundRecorder {\n constructor() {\n this.input = ac.createGain();\n this.output = ac.createGain();\n\n this._inputChannels = 2;\n this._outputChannels = 2; // stereo output, even if input is mono\n\n const workletBufferSize = safeBufferSize(1024);\n\n this._workletNode = new AudioWorkletNode(\n ac,\n processorNames.recorderProcessor,\n {\n outputChannelCount: [this._outputChannels],\n processorOptions: {\n numInputChannels: this._inputChannels,\n bufferSize: workletBufferSize,\n },\n }\n );\n\n this._workletNode.port.onmessage = function (event) {\n if (event.data.name === 'buffers') {\n const buffers = [\n new Float32Array(event.data.leftBuffer),\n new Float32Array(event.data.rightBuffer),\n ];\n this._callback(buffers);\n }\n }.bind(this);\n\n /**\n * callback invoked when the recording is over\n * @private\n * @type Function(Float32Array)\n */\n this._callback = function () {};\n\n // connections\n this._workletNode.connect(p5.soundOut._silentNode);\n this.setInput();\n\n // add this p5.SoundFile to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Connect a specific device to the p5.SoundRecorder.\n * If no parameter is given, p5.SoundRecorer will record\n * all audible p5.sound from your sketch.\n *\n * @method setInput\n * @for p5.SoundRecorder\n * @param {Object} [unit] p5.sound object or a web audio unit\n * that outputs sound\n */\n setInput(unit) {\n this.input.disconnect();\n this.input = null;\n this.input = ac.createGain();\n this.input.connect(this._workletNode);\n this.input.connect(this.output);\n if (unit) {\n unit.connect(this.input);\n } else {\n p5.soundOut.output.connect(this.input);\n }\n }\n\n /**\n * Start recording. To access the recording, provide\n * a p5.SoundFile as the first parameter. The p5.SoundRecorder\n * will send its recording to that p5.SoundFile for playback once\n * recording is complete. Optional parameters include duration\n * (in seconds) of the recording, and a callback function that\n * will be called once the complete recording has been\n * transfered to the p5.SoundFile.\n *\n * @method record\n * @for p5.SoundRecorder\n * @param {p5.SoundFile} soundFile p5.SoundFile\n * @param {Number} [duration] Time (in seconds)\n * @param {Function} [callback] The name of a function that will be\n * called once the recording completes\n */\n record(sFile, duration, callback) {\n this._workletNode.port.postMessage({ name: 'start', duration: duration });\n\n if (sFile && callback) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n callback();\n };\n } else if (sFile) {\n this._callback = function (buffer) {\n sFile.setBuffer(buffer);\n };\n }\n }\n\n /**\n * Stop the recording. Once the recording is stopped,\n * the results will be sent to the p5.SoundFile that\n * was given on .record(), and if a callback function\n * was provided on record, that function will be called.\n *\n * @method stop\n * @for p5.SoundRecorder\n */\n stop() {\n this._workletNode.port.postMessage({ name: 'stop' });\n }\n\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n\n this._callback = function () {};\n if (this.input) {\n this.input.disconnect();\n }\n this.input = null;\n this._workletNode = null;\n }\n}\n\nexport default SoundRecorder;\n","import Effect from './effect.js';\n\n/*\n * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n */\nfunction makeDistortionCurve(amount) {\n var k = typeof amount === 'number' ? amount : 50;\n var numSamples = 44100;\n var curve = new Float32Array(numSamples);\n var deg = Math.PI / 180;\n var i = 0;\n var x;\n for (; i < numSamples; ++i) {\n x = (i * 2) / numSamples - 1;\n curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x));\n }\n return curve;\n}\n\n/**\n * A Distortion effect created with a Waveshaper Node,\n * with an approach adapted from\n * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)\n *\n * This class extends p5.Effect.\n * Methods amp(), chain(),\n * drywet(), connect(), and\n * disconnect() are available.\n *\n * @class p5.Distortion\n * @extends p5.Effect\n * @constructor\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n *\n */\nclass Distortion extends Effect {\n constructor(amount, oversample) {\n super();\n if (typeof amount === 'undefined') {\n amount = 0.25;\n }\n if (typeof amount !== 'number') {\n throw new Error('amount must be a number');\n }\n if (typeof oversample === 'undefined') {\n oversample = '2x';\n }\n if (typeof oversample !== 'string') {\n throw new Error('oversample must be a String');\n }\n\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n\n /**\n * The p5.Distortion is built with a\n * \n * Web Audio WaveShaper Node.\n *\n * @property {AudioNode} WaveShaperNode\n */\n this.waveShaperNode = this.ac.createWaveShaper();\n\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n this.waveShaperNode.oversample = oversample;\n\n this.input.connect(this.waveShaperNode);\n\n this.waveShaperNode.connect(this.wet);\n }\n\n /**\n * Process a sound source, optionally specify amount and oversample values.\n *\n * @method process\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\n process(src, amount, oversample) {\n src.connect(this.input);\n this.set(amount, oversample);\n }\n\n /**\n * Set the amount and oversample of the waveshaper distortion.\n *\n * @method set\n * @for p5.Distortion\n * @param {Number} [amount=0.25] Unbounded distortion amount.\n * Normal values range from 0-1.\n * @param {String} [oversample='none'] 'none', '2x', or '4x'.\n */\n set(amount, oversample) {\n if (amount) {\n var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);\n this.amount = curveAmount;\n this.waveShaperNode.curve = makeDistortionCurve(curveAmount);\n }\n if (oversample) {\n this.waveShaperNode.oversample = oversample;\n }\n }\n\n /**\n * Return the distortion amount, typically between 0-1.\n *\n * @method getAmount\n * @for p5.Distortion\n * @return {Number} Unbounded distortion amount.\n * Normal values range from 0-1.\n */\n getAmount() {\n return this.amount;\n }\n\n /**\n * Return the oversampling.\n *\n * @method getOversample\n * @for p5.Distortion\n * @return {String} Oversample can either be 'none', '2x', or '4x'.\n */\n getOversample() {\n return this.waveShaperNode.oversample;\n }\n\n dispose() {\n super.dispose();\n if (this.waveShaperNode) {\n this.waveShaperNode.disconnect();\n this.waveShaperNode = null;\n }\n }\n}\n\nexport default Distortion;\n","import p5sound from './master';\n\n/**\n * A gain node is usefull to set the relative volume of sound.\n * It's typically used to build mixers.\n *\n * @class p5.Gain\n * @constructor\n * @example\n *
\n *\n * // load two soundfile and crossfade beetween them\n * let sound1,sound2;\n * let sound1Gain, sound2Gain, masterGain;\n * function preload(){\n * soundFormats('ogg', 'mp3');\n * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\n * sound2 = loadSound('assets/beat');\n * }\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(startSound);\n * // create a 'master' gain to which we will connect both soundfiles\n * masterGain = new p5.Gain();\n * masterGain.connect();\n * sound1.disconnect(); // diconnect from p5 output\n * sound1Gain = new p5.Gain(); // setup a gain node\n * sound1Gain.setInput(sound1); // connect the first sound to its input\n * sound1Gain.connect(masterGain); // connect its output to the 'master'\n * sound2.disconnect();\n * sound2Gain = new p5.Gain();\n * sound2Gain.setInput(sound2);\n * sound2Gain.connect(masterGain);\n * }\n * function startSound() {\n * sound1.loop();\n * sound2.loop();\n * loop();\n * }\n * function mouseReleased() {\n * sound1.stop();\n * sound2.stop();\n * }\n * function draw(){\n * background(220);\n * textAlign(CENTER);\n * textSize(11);\n * fill(0);\n * if (!sound1.isPlaying()) {\n * text('tap and drag to play', width/2, height/2);\n * return;\n * }\n * // map the horizontal position of the mouse to values useable for volume * control of sound1\n * var sound1Volume = constrain(map(mouseX,width,0,0,1), 0, 1);\n * var sound2Volume = 1-sound1Volume;\n * sound1Gain.amp(sound1Volume);\n * sound2Gain.amp(sound2Volume);\n * // map the vertical position of the mouse to values useable for 'master * volume control'\n * var masterVolume = constrain(map(mouseY,height,0,0,1), 0, 1);\n * masterGain.amp(masterVolume);\n * text('master', width/2, height - masterVolume * height * 0.9)\n * fill(255, 0, 255);\n * textAlign(LEFT);\n * text('sound1', 5, height - sound1Volume * height * 0.9);\n * textAlign(RIGHT);\n * text('sound2', width - 5, height - sound2Volume * height * 0.9);\n * }\n *
\n */\n\nclass Gain {\n constructor() {\n this.ac = p5sound.audiocontext;\n\n this.input = this.ac.createGain();\n this.output = this.ac.createGain();\n\n // otherwise, Safari distorts\n this.input.gain.value = 0.5;\n this.input.connect(this.output);\n\n // add to the soundArray\n p5sound.soundArray.push(this);\n }\n\n /**\n * Connect a source to the gain node.\n *\n * @method setInput\n * @for p5.Gain\n * @param {Object} src p5.sound / Web Audio object with a sound\n * output.\n */\n\n setInput(src) {\n src.connect(this.input);\n }\n\n /**\n * Send output to a p5.sound or web audio object\n *\n * @method connect\n * @for p5.Gain\n * @param {Object} unit\n */\n connect(unit) {\n var u = unit || p5.soundOut.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all output.\n *\n * @method disconnect\n * @for p5.Gain\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Set the output level of the gain node.\n *\n * @method amp\n * @for p5.Gain\n * @param {Number} volume amplitude between 0 and 1.0\n * @param {Number} [rampTime] create a fade that lasts rampTime\n * @param {Number} [timeFromNow] schedule this event to happen\n * seconds from now\n */\n amp(vol, rampTime = 0, tFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var currentVol = this.output.gain.value;\n this.output.gain.cancelScheduledValues(now);\n this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);\n this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);\n }\n\n dispose() {\n // remove reference from soundArray\n var index = p5sound.soundArray.indexOf(this);\n p5sound.soundArray.splice(index, 1);\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n if (this.input) {\n this.input.disconnect();\n delete this.input;\n }\n }\n}\n\nexport default Gain;\n","import p5sound from './master';\n\n/**\n * Base class for monophonic synthesizers. Any extensions of this class\n * should follow the API and implement the methods below in order to\n * remain compatible with p5.PolySynth();\n *\n * @class p5.AudioVoice\n * @constructor\n */\nclass AudioVoice {\n constructor() {\n this.ac = p5sound.audiocontext;\n this.output = this.ac.createGain();\n this.connect();\n p5sound.soundArray.push(this);\n }\n play(note, velocity, secondsFromNow, sustime) {}\n\n triggerAttack(note, velocity, secondsFromNow) {}\n\n triggerRelease(secondsFromNow) {}\n\n amp(vol, rampTime) {}\n\n /**\n * Connect to p5 objects or Web Audio Nodes\n * @method connect\n * @for p5.AudioVoice\n * @param {Object} unit\n */\n connect(unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect from soundOut\n * @method disconnect\n * @for p5.AudioVoice\n */\n disconnect() {\n this.output.disconnect();\n }\n\n dispose() {\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n }\n}\n\nexport default AudioVoice;\n","import AudioVoice from './audioVoice';\nimport Envelope from './envelope';\nimport p5sound from './master';\nimport Oscillator from './oscillator';\nimport { noteToFreq } from './helpers';\n\nvar DEFAULT_SUSTAIN = 0.15;\n\n/**\n * A MonoSynth is used as a single voice for sound synthesis.\n * This is a class to be used in conjunction with the PolySynth\n * class. Custom synthetisers should be built inheriting from\n * this class.\n *\n * @class p5.MonoSynth\n * @constructor\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n **/\n\nclass MonoSynth extends AudioVoice {\n constructor() {\n super();\n this.oscillator = new Oscillator();\n\n this.env = new Envelope(); //to be changed\n this.env.setRange(1, 0);\n this.env.setExp(true);\n\n //set params\n this.setADSR(0.02, 0.25, 0.05, 0.35);\n\n // oscillator --> env --> this.output (gain) --> p5.soundOut\n this.oscillator.disconnect();\n this.oscillator.connect(this.output);\n\n this.env.disconnect();\n this.env.setInput(this.output.gain);\n\n // reset oscillator gain to 1.0\n this.oscillator.output.gain.value = 1.0;\n\n this.oscillator.start();\n this.connect();\n\n p5sound.soundArray.push(this);\n\n /**\n * Getters and Setters\n * @property {Number} attack\n * @for p5.MonoSynth\n */\n /**\n * @property {Number} decay\n * @for p5.MonoSynth\n */\n /**\n * @property {Number} sustain\n * @for p5.MonoSynth\n */\n /**\n * @property {Number} release\n * @for p5.MonoSynth\n */\n Object.defineProperties(this, {\n attack: {\n get: function () {\n return this.env.aTime;\n },\n set: function (attack) {\n this.env.setADSR(\n attack,\n this.env.dTime,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n decay: {\n get: function () {\n return this.env.dTime;\n },\n set: function (decay) {\n this.env.setADSR(\n this.env.aTime,\n decay,\n this.env.sPercent,\n this.env.rTime\n );\n },\n },\n sustain: {\n get: function () {\n return this.env.sPercent;\n },\n set: function (sustain) {\n this.env.setADSR(\n this.env.aTime,\n this.env.dTime,\n sustain,\n this.env.rTime\n );\n },\n },\n release: {\n get: function () {\n return this.env.rTime;\n },\n set: function (release) {\n this.env.setADSR(\n this.env.aTime,\n this.env.dTime,\n this.env.sPercent,\n release\n );\n },\n },\n });\n }\n\n /**\n * Play tells the MonoSynth to start playing a note. This method schedules\n * the calling of .triggerAttack and .triggerRelease.\n *\n * @method play\n * @for p5.MonoSynth\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope. Defaults to 0.15 seconds.\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * textAlign(CENTER);\n * text('tap to play', width/2, height/2);\n *\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * let note = random(['Fb4', 'G4']);\n * // note velocity (volume, from 0 to 1)\n * let velocity = random();\n * // time from now (in seconds)\n * let time = 0;\n * // note duration (in seconds)\n * let dur = 1/6;\n *\n * monoSynth.play(note, velocity, time, dur);\n * }\n *
\n *\n */\n play(note, velocity, secondsFromNow, susTime) {\n this.triggerAttack(note, velocity, ~~secondsFromNow);\n this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));\n }\n\n /**\n * Trigger the Attack, and Decay portion of the Envelope.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @param {String | Number} note the note you want to play, specified as a\n * frequency in Hertz (Number) or as a midi\n * value in Note/Octave format (\"C4\", \"Eb3\"...etc\")\n * See \n * Tone. Defaults to 440 hz\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @method triggerAttack\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\n triggerAttack(note, velocity, secondsFromNow = 0) {\n var freq = noteToFreq(note);\n var vel = velocity || 0.1;\n this.oscillator.freq(freq, 0, secondsFromNow);\n this.env.ramp(this.output.gain, secondsFromNow, vel);\n }\n\n /**\n * Trigger the release of the Envelope. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @param {Number} secondsFromNow time to trigger the release\n * @method triggerRelease\n * @for p5.MonoSynth\n * @example\n *
\n * let monoSynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(triggerAttack);\n * background(220);\n * text('tap here for attack, let go to release', 5, 20, width - 20);\n * monoSynth = new p5.MonoSynth();\n * }\n *\n * function triggerAttack() {\n * userStartAudio();\n *\n * monoSynth.triggerAttack(\"E3\");\n * }\n *\n * function mouseReleased() {\n * monoSynth.triggerRelease();\n * }\n *
\n */\n triggerRelease(secondsFromNow = 0) {\n this.env.ramp(this.output.gain, secondsFromNow, 0);\n }\n\n /**\n * Set values like a traditional\n * \n * ADSR envelope\n * .\n *\n * @method setADSR\n * @for p5.MonoSynth\n * @param {Number} attackTime Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n */\n setADSR(attack, decay, sustain, release) {\n this.env.setADSR(attack, decay, sustain, release);\n }\n\n /**\n * MonoSynth amp\n * @method amp\n * @for p5.MonoSynth\n * @param {Number} vol desired volume\n * @param {Number} [rampTime] Time to reach new volume\n * @return {Number} new volume value\n */\n amp(vol, rampTime) {\n var t = rampTime || 0;\n if (typeof vol !== 'undefined') {\n this.oscillator.amp(vol, t);\n }\n return this.oscillator.amp().value;\n }\n\n /**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.MonoSynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\n\n connect(unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.MonoSynth\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.MonoSynth\n */\n dispose() {\n super.dispose();\n\n if (this.env) {\n this.env.dispose();\n }\n if (this.oscillator) {\n this.oscillator.dispose();\n }\n }\n}\n\nexport default MonoSynth;\n","/**\n * Listen for onsets (a sharp increase in volume) within a given\n * frequency range.\n *\n * @class p5.OnsetDetect\n * @constructor\n * @param {Number} freqLow Low frequency\n * @param {Number} freqHigh High frequency\n * @param {Number} threshold Amplitude threshold between 0 (no energy) and 1 (maximum)\n * @param {Function} callback Function to call when an onset is detected\n */\nclass OnsetDetect {\n constructor(freqLow, freqHigh, threshold, callback) {\n this.isDetected = false;\n this.freqLow = freqLow;\n this.freqHigh = freqHigh;\n this.treshold = threshold;\n this.energy = 0;\n this.penergy = 0;\n\n // speed of decay\n this.sensitivity = 500;\n\n this.callback = callback;\n }\n\n // callback here too?\n update(fftObject, callback) {\n this.energy = fftObject.getEnergy(this.freqLow, this.freqHigh) / 255;\n\n if (this.isDetected === false) {\n if (this.energy - this.penergy > this.treshold) {\n this.isDetected = true;\n\n if (this.callback) {\n this.callback(this.energy);\n } else if (callback) {\n callback(this.energy);\n }\n\n var self = this;\n setTimeout(function () {\n self.isDetected = false;\n }, this.sensitivity);\n }\n }\n\n this.penergy = this.energy;\n }\n}\n\nexport default OnsetDetect;\n","import p5sound from './master';\nimport TimelineSignal from 'Tone/signal/TimelineSignal.js';\nimport { noteToFreq, freqToMidi } from './helpers';\n\n/**\n * An AudioVoice is used as a single voice for sound synthesis.\n * The PolySynth class holds an array of AudioVoice, and deals\n * with voices allocations, with setting notes to be played, and\n * parameters to be set.\n *\n * @class p5.PolySynth\n * @constructor\n *\n * @param {Number} [synthVoice] A monophonic synth voice inheriting\n * the AudioVoice class. Defaults to p5.MonoSynth\n * @param {Number} [maxVoices] Number of voices, defaults to 8;\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n **/\nclass PolySynth {\n constructor(audioVoice, maxVoices) {\n //audiovoices will contain maxVoices many monophonic synths\n this.audiovoices = [];\n\n /**\n * An object that holds information about which notes have been played and\n * which notes are currently being played. New notes are added as keys\n * on the fly. While a note has been attacked, but not released, the value of the\n * key is the audiovoice which is generating that note. When notes are released,\n * the value of the key becomes undefined.\n * @property notes\n */\n this.notes = {};\n\n //indices of the most recently used, and least recently used audiovoice\n this._newest = 0;\n this._oldest = 0;\n\n /**\n * A PolySynth must have at least 1 voice, defaults to 8\n * @property polyvalue\n */\n this.maxVoices = maxVoices || 8;\n\n /**\n * Monosynth that generates the sound for each note that is triggered. The\n * p5.PolySynth defaults to using the p5.MonoSynth as its voice.\n * @property AudioVoice\n */\n this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;\n\n /**\n * This value must only change as a note is attacked or released. Due to delay\n * and sustain times, Tone.TimelineSignal is required to schedule the change in value.\n * @private\n * @property {Tone.TimelineSignal} _voicesInUse\n */\n this._voicesInUse = new TimelineSignal(0);\n\n this.output = p5sound.audiocontext.createGain();\n this.connect();\n\n //Construct the appropriate number of audiovoices\n this._allocateVoices();\n p5sound.soundArray.push(this);\n }\n\n /**\n * Construct the appropriate number of audiovoices\n * @private\n * @for p5.PolySynth\n * @method _allocateVoices\n */\n _allocateVoices() {\n for (var i = 0; i < this.maxVoices; i++) {\n this.audiovoices.push(new this.AudioVoice());\n this.audiovoices[i].disconnect();\n this.audiovoices[i].connect(this.output);\n }\n }\n\n /**\n * Play a note by triggering noteAttack and noteRelease with sustain time\n *\n * @method play\n * @for p5.PolySynth\n * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)\n * @param {Number} [secondsFromNow] time from now (in seconds) at which to play\n * @param {Number} [sustainTime] time to sustain before releasing the envelope\n * @example\n *
\n * let polySynth;\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playSynth);\n * background(220);\n * text('click to play', 20, 20);\n *\n * polySynth = new p5.PolySynth();\n * }\n *\n * function playSynth() {\n * userStartAudio();\n *\n * // note duration (in seconds)\n * let dur = 1.5;\n *\n * // time from now (in seconds)\n * let time = 0;\n *\n * // velocity (volume, from 0 to 1)\n * let vel = 0.1;\n *\n * // notes can overlap with each other\n * polySynth.play('G2', vel, 0, dur);\n * polySynth.play('C3', vel, time += 1/3, dur);\n * polySynth.play('G3', vel, time += 1/3, dur);\n * }\n *
\n */\n play(note, velocity, secondsFromNow, susTime = 1) {\n this.noteAttack(note, velocity, secondsFromNow);\n this.noteRelease(note, secondsFromNow + susTime);\n }\n\n /**\n * noteADSR sets the envelope for a specific note that has just been triggered.\n * Using this method modifies the envelope of whichever audiovoice is being used\n * to play the desired note. The envelope should be reset before noteRelease is called\n * in order to prevent the modified envelope from being used on other notes.\n *\n * @method noteADSR\n * @for p5.PolySynth\n * @param {Number} [note] Midi note on which ADSR should be set.\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\n\n noteADSR(note, a, d, s, r, timeFromNow = 0) {\n var now = p5sound.audiocontext.currentTime;\n var t = now + timeFromNow;\n this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r);\n }\n\n /**\n * Set the PolySynths global envelope. This method modifies the envelopes of each\n * monosynth so that all notes are played with this envelope.\n *\n * @method setADSR\n * @for p5.PolySynth\n * @param {Number} [attackTime] Time (in seconds before envelope\n * reaches Attack Level\n * @param {Number} [decayTime] Time (in seconds) before envelope\n * reaches Decay/Sustain Level\n * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n * where 1.0 = attackLevel, 0.0 = releaseLevel.\n * The susRatio determines the decayLevel and the level at which the\n * sustain portion of the envelope will sustain.\n * For example, if attackLevel is 0.4, releaseLevel is 0,\n * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n * increased to 1.0 (using setRange),\n * then decayLevel would increase proportionally, to become 0.5.\n * @param {Number} [releaseTime] Time in seconds from now (defaults to 0)\n **/\n setADSR(a, d, s, r) {\n this.audiovoices.forEach(function (voice) {\n voice.setADSR(a, d, s, r);\n });\n }\n\n /**\n * Trigger the Attack, and Decay portion of a MonoSynth.\n * Similar to holding down a key on a piano, but it will\n * hold the sustain level until you let go.\n *\n * @method noteAttack\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/\n * @param {Number} [secondsFromNow] time from now (in seconds)\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n */\n noteAttack(_note, _velocity, secondsFromNow = 0) {\n //this value is used by this._voicesInUse\n var acTime = p5sound.audiocontext.currentTime + secondsFromNow;\n\n //Convert note to frequency if necessary. This is because entries into this.notes\n //should be based on frequency for the sake of consistency.\n var note = noteToFreq(_note);\n var velocity = _velocity || 0.1;\n\n var currentVoice;\n\n //Release the note if it is already playing\n if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {\n this.noteRelease(note, 0);\n }\n\n //Check to see how many voices are in use at the time the note will start\n if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {\n currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);\n }\n //If we are exceeding the polyvalue, bump off the oldest notes and replace\n //with a new note\n else {\n currentVoice = this._oldest;\n\n oldestNote = freqToMidi(\n this.audiovoices[this._oldest].oscillator.freq().value\n );\n this.noteRelease(oldestNote);\n this._oldest = (this._oldest + 1) % (this.maxVoices - 1);\n }\n\n //Overrite the entry in the notes object. A note (frequency value)\n //corresponds to the index of the audiovoice that is playing it\n this.notes[note] = new TimelineSignal();\n this.notes[note].setValueAtTime(currentVoice, acTime);\n\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //Add 1 and schedule this value at time 't', when this note will start playing\n var previousVal =\n this._voicesInUse._searchBefore(acTime) === null\n ? 0\n : this._voicesInUse._searchBefore(acTime).value;\n this._voicesInUse.setValueAtTime(previousVal + 1, acTime);\n\n //Then update all scheduled values that follow to increase by 1\n this._updateAfter(acTime, 1);\n\n this._newest = currentVoice;\n //The audiovoice handles the actual scheduling of the note\n if (typeof velocity === 'number') {\n var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2;\n velocity = velocity > maxRange ? maxRange : velocity;\n }\n\n // use secondsFromNow because this method will add AudioContext currentTime\n this.audiovoices[currentVoice].triggerAttack(\n note,\n velocity,\n secondsFromNow\n );\n }\n\n /**\n * Private method to ensure accurate values of this._voicesInUse\n * Any time a new value is scheduled, it is necessary to increment all subsequent\n * scheduledValues after attack, and decrement all subsequent\n * scheduledValues after release\n *\n * @private\n * @for p5.PolySynth\n * @param {[type]} time [description]\n * @param {[type]} value [description]\n * @return {[type]} [description]\n */\n _updateAfter(time, value) {\n if (this._voicesInUse._searchAfter(time) === null) {\n return;\n } else {\n this._voicesInUse._searchAfter(time).value += value;\n var nextTime = this._voicesInUse._searchAfter(time).time;\n this._updateAfter(nextTime, value);\n }\n }\n\n /**\n * Trigger the Release of an AudioVoice note. This is similar to releasing\n * the key on a piano and letting the sound fade according to the\n * release level and release time.\n *\n * @method noteRelease\n * @for p5.PolySynth\n * @param {Number} [note] midi note on which attack should be triggered.\n * If no value is provided, all notes will be released.\n * @param {Number} [secondsFromNow] time to trigger the release\n * @example\n *
\n * let polySynth = new p5.PolySynth();\n * let pitches = ['G', 'D', 'G', 'C'];\n * let octaves = [2, 3, 4];\n *\n * function setup() {\n * let cnv = createCanvas(100, 100);\n * cnv.mousePressed(playChord);\n * background(220);\n * text('tap to play', 20, 20);\n * }\n *\n * function playChord() {\n * userStartAudio();\n *\n * // play a chord: multiple notes at the same time\n * for (let i = 0; i < 4; i++) {\n * let note = random(pitches) + random(octaves);\n * polySynth.noteAttack(note, 0.1);\n * }\n * }\n *\n * function mouseReleased() {\n * // release all voices\n * polySynth.noteRelease();\n * }\n *
\n *\n */\n noteRelease(_note, secondsFromNow) {\n var now = p5sound.audiocontext.currentTime;\n var tFromNow = secondsFromNow || 0;\n var t = now + tFromNow;\n\n // if a note value is not provided, release all voices\n if (!_note) {\n this.audiovoices.forEach(function (voice) {\n voice.triggerRelease(tFromNow);\n });\n this._voicesInUse.setValueAtTime(0, t);\n for (var n in this.notes) {\n this.notes[n].dispose();\n delete this.notes[n];\n }\n return;\n }\n\n //Make sure note is in frequency inorder to query the this.notes object\n var note = noteToFreq(_note);\n\n if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {\n console.warn('Cannot release a note that is not already playing');\n } else {\n //Find the scheduled change in this._voicesInUse that will be previous to this new note\n //subtract 1 and schedule this value at time 't', when this note will stop playing\n var previousVal = Math.max(\n ~~this._voicesInUse.getValueAtTime(t).value,\n 1\n );\n this._voicesInUse.setValueAtTime(previousVal - 1, t);\n //Then update all scheduled values that follow to decrease by 1 but never go below 0\n if (previousVal > 0) {\n this._updateAfter(t, -1);\n }\n\n this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(\n tFromNow\n );\n this.notes[note].dispose();\n delete this.notes[note];\n\n this._newest =\n this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);\n }\n }\n\n /**\n * Connect to a p5.sound / Web Audio object.\n *\n * @method connect\n * @for p5.PolySynth\n * @param {Object} unit A p5.sound or Web Audio object\n */\n connect(unit) {\n var u = unit || p5sound.input;\n this.output.connect(u.input ? u.input : u);\n }\n\n /**\n * Disconnect all outputs\n *\n * @method disconnect\n * @for p5.PolySynth\n */\n disconnect() {\n if (this.output) {\n this.output.disconnect();\n }\n }\n\n /**\n * Get rid of the MonoSynth and free up its resources / memory.\n *\n * @method dispose\n * @for p5.PolySynth\n */\n dispose() {\n this.audiovoices.forEach(function (voice) {\n voice.dispose();\n });\n\n if (this.output) {\n this.output.disconnect();\n delete this.output;\n }\n }\n}\n\nexport default PolySynth;\n","class Signal {\n constructor() {\n console.warn('p5.Signal is deprecated , Use Tone.js Signal instead ');\n }\n}\n\nexport default Signal;\n","import 'audioworklet-polyfill';\nimport './shims';\n\nimport { getAudioContext, userStartAudio } from './audiocontext';\np5.prototype.getAudioContext = getAudioContext;\np5.prototype.userStartAudio = userStartAudio;\n\nimport './master';\n\nimport {\n sampleRate,\n freqToMidi,\n midiToFreq,\n noteToFreq,\n soundFormats,\n disposeSound,\n _checkFileFormats,\n _mathChain,\n convertToWav,\n interleave,\n writeUTFBytes,\n safeBufferSize,\n saveSound,\n} from './helpers';\np5.prototype.sampleRate = sampleRate;\np5.prototype.freqToMidi = freqToMidi;\np5.prototype.midiToFreq = midiToFreq;\np5.prototype.noteToFreq = noteToFreq;\np5.prototype.soundFormats = soundFormats;\np5.prototype.disposeSound = disposeSound;\np5.prototype._checkFileFormats = _checkFileFormats;\np5.prototype._mathChain = _mathChain;\np5.prototype.convertToWav = convertToWav;\np5.prototype.interleave = interleave;\np5.prototype.writeUTFBytes = writeUTFBytes;\np5.prototype.safeBufferSize = safeBufferSize;\np5.prototype.saveSound = saveSound;\n\n// register removeSound to dispose of p5sound SoundFiles, Convolvers,\n// Oscillators etc when sketch ends\np5.prototype.registerMethod('remove', p5.prototype.disposeSound);\n\nimport './errorHandler';\nimport './audioWorklet';\n\nimport Panner from './panner';\np5.Panner = Panner;\n\nimport SoundFile, { loadSound } from './soundfile';\np5.SoundFile = SoundFile;\np5.prototype.loadSound = loadSound;\n// register preload handling of loadSound\np5.prototype.registerPreloadMethod('loadSound', p5.prototype);\n\nimport Amplitude from './amplitude';\np5.Amplitude = Amplitude;\n\nimport FFT from './fft';\np5.FFT = FFT;\n\nimport Oscillator, { SinOsc, TriOsc, SawOsc, SqrOsc } from './oscillator';\np5.Oscillator = Oscillator;\np5.SinOsc = SinOsc;\np5.TriOsc = TriOsc;\np5.SawOsc = SawOsc;\np5.SqrOsc = SqrOsc;\n\nimport './envelope';\n\nimport Noise from './noise';\np5.Noise = Noise;\n\nimport Pulse from './pulse';\np5.Pulse = Pulse;\n\nimport AudioIn from './audioin';\np5.AudioIn = AudioIn;\n\nimport Effect from './effect';\np5.Effect = Effect;\n\nimport Filter, { LowPass, HighPass, BandPass } from './filter';\np5.Filter = Filter;\np5.LowPass = LowPass;\np5.HighPass = HighPass;\np5.BandPass = BandPass;\n\nimport EQ from './eq';\np5.EQ = EQ;\n\nimport listener3D from './listener3d';\np5.listener3D = listener3D;\n\nimport Panner3D from './panner3d';\np5.Panner3D = Panner3D;\n\nimport Delay from './delay';\np5.Delay = Delay;\n\nimport { Reverb, Convolver, createConvolver } from './reverb';\np5.Reverb = Reverb;\np5.Convolver = Convolver;\np5.prototype.createConvolver = createConvolver;\np5.prototype.registerPreloadMethod('createConvolver', p5.prototype);\n\nimport Metro from './metro';\np5.Metro = Metro;\n\nimport { Phrase, Part, Score } from './looper';\np5.Phrase = Phrase;\np5.Part = Part;\np5.Score = Score;\n\nimport SoundLoop from './soundLoop';\np5.SoundLoop = SoundLoop;\n\nimport Compressor from './compressor';\np5.Compressor = Compressor;\n\nimport peakDetect from './peakDetect';\np5.peakDetect = peakDetect;\n\nimport SoundRecorder from './soundRecorder';\np5.SoundRecorder = SoundRecorder;\n\nimport Distortion from './distortion';\np5.Distortion = Distortion;\n\nimport Gain from './gain';\np5.Gain = Gain;\n\nimport AudioVoice from './audioVoice';\np5.AudioVoice = AudioVoice;\n\nimport MonoSynth from './monosynth';\np5.MonoSynth = MonoSynth;\n\nimport OnsetDetect from './onsetDetect';\np5.OnsetDetect = OnsetDetect;\n\nimport PolySynth from './polysynth';\np5.PolySynth = PolySynth;\n\n// Following are the deprecated classes\nimport Signal from './deprecations/Signal';\np5.Signal = Signal;\n"],"sourceRoot":""} \ No newline at end of file diff --git a/package.json b/package.json index bada0db3..34e57c55 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "git", "url": "https://github.com/processing/p5.js-sound.git" }, - "version": "0.3.12", + "version": "1.0.0", "license": "MIT", "devDependencies": { "@babel/core": "^7.4.5",