/** [p5.sound]  Version: 1.0.1 - 2021-05-25 */ 
 /**
 *  <p>p5.sound extends p5 with <a href="http://caniuse.com/audio-api"
 *  target="_blank">Web Audio</a> functionality including audio input,
 *  playback, analysis and synthesis.
 *  </p>
 *  <ul>
 *  <li><a href="#/p5.SoundFile"><b>p5.SoundFile</b></a>: Load and play sound files.</li>
 *  <li><a href="#/p5.Amplitude"><b>p5.Amplitude</b></a>: Get the current volume of a sound.</li>
 *  <li><a href="#/p5.AudioIn"><b>p5.AudioIn</b></a>: Get sound from an input source, typically
 *    a computer microphone.</li>
 *  <li><a href="#/p5.FFT"><b>p5.FFT</b></a>: Analyze the frequency of sound. Returns
 *    results from the frequency spectrum or time domain (waveform).</li>
 *  <li><a href="#/p5.Oscillator"><b>p5.Oscillator</b></a>: Generate Sine,
 *    Triangle, Square and Sawtooth waveforms. Base class of
 *    <li><a href="#/p5.Noise">p5.Noise</a> and <a href="#/p5.Pulse">p5.Pulse</a>.
 *    </li>
 *  <li>
 *    <a href="#/p5.MonoSynth">p5.MonoSynth</a> and <a href="#/p5.PolySynth">p5.PolySynth</a>: Play musical notes
 *  </li>
 *  <li><a href="#/p5.Envelope"><b>p5.Envelope</b></a>: An Envelope is a series
 *    of fades over time. Often used to control an object's
 *    output gain level as an "ADSR Envelope" (Attack, Decay,
 *    Sustain, Release). Can also modulate other parameters.</li>
 *  <li><a href="#/p5.Delay"><b>p5.Delay</b></a>: A delay effect with
 *    parameters for feedback, delayTime, and lowpass filter.</li>
 *  <li><a href="#/p5.Filter"><b>p5.Filter</b></a>: Filter the frequency range of a
 *    sound.
 *  </li>
 *  <li><a href="#/p5.Reverb"><b>p5.Reverb</b></a>: Add reverb to a sound by specifying
 *    duration and decay. </li>
 *  <b><li><a href="#/p5.Convolver">p5.Convolver</a>:</b> Extends
 *  <a href="#/p5.Reverb">p5.Reverb</a> to simulate the sound of real
 *    physical spaces through convolution.</li>
 *  <b><li><a href="#/p5.SoundRecorder">p5.SoundRecorder</a></b>: Record sound for playback
 *    / save the .wav file.
 *  <b><li><a href="#/p5.SoundLoop">p5.SoundLoop</a>, <a href="#/p5.Phrase">p5.Phrase</a></b>, <b><a href="#/p5.Part">p5.Part</a></b> and
 *  <b><a href="#/p5.Score">p5.Score</a></b>: Compose musical sequences.
 *  </li>
 *  <li><a href="#/p5/userStartAudio">userStartAudio</a>: Enable audio in a
 *  browser- and user-friendly way.</a>
 *  <p>p5.sound is on <a href="https://github.com/processing/p5.js-sound/">GitHub</a>.
 *  Download the latest version
 *  <a href="https://github.com/processing/p5.js-sound/blob/master/lib/p5.sound.js">here</a>.</p>
 *
 *  @module p5.sound
 *  @submodule p5.sound
 *  @for p5.sound
 *  @main
 */

/**
 *  p5.sound 
 *  https://p5js.org/reference/#/libraries/p5.sound
 *
 *  From the Processing Foundation and contributors
 *  https://github.com/processing/p5.js-sound/graphs/contributors
 *
 *  MIT License (MIT)
 *  https://github.com/processing/p5.js-sound/blob/master/LICENSE
 *
 *  Some of the many audio libraries & resources that inspire p5.sound:
 *   - TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). https://github.com/TONEnoTONE/Tone.js
 *   - buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). http://buzz.jaysalvat.com/
 *   - Boris Smus Web Audio API book, 2013. Licensed under the Apache License http://www.apache.org/licenses/LICENSE-2.0
 *   - wavesurfer.js https://github.com/katspaugh/wavesurfer.js
 *   - Web Audio Components by Jordan Santell https://github.com/web-audio-components
 *   - Wilm Thoben's Sound library for Processing https://github.com/processing/processing/tree/master/java/libraries/sound
 *
 *   Web Audio API: http://w3.org/TR/webaudio/
 */

 (function(modules) { 
 	var installedModules = {};
 	function __webpack_require__(moduleId) {
 		if(installedModules[moduleId]) {
 			return installedModules[moduleId].exports;
 		}
 		var module = installedModules[moduleId] = {
 			i: moduleId,
 			l: false,
 			exports: {}
 		};
 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
 		module.l = true;
 		return module.exports;
 	}
 	__webpack_require__.m = modules;
 	__webpack_require__.c = installedModules;
 	__webpack_require__.d = function(exports, name, getter) {
 		if(!__webpack_require__.o(exports, name)) {
 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
 		}
 	};
 	__webpack_require__.r = function(exports) {
 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
 		}
 		Object.defineProperty(exports, '__esModule', { value: true });
 	};
 	__webpack_require__.t = function(value, mode) {
 		if(mode & 1) value = __webpack_require__(value);
 		if(mode & 8) return value;
 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
 		var ns = Object.create(null);
 		__webpack_require__.r(ns);
 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
 		return ns;
 	};
 	__webpack_require__.n = function(module) {
 		var getter = module && module.__esModule ?
 			function getDefault() { return module['default']; } :
 			function getModuleExports() { return module; };
 		__webpack_require__.d(getter, 'a', getter);
 		return getter;
 	};
 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 	__webpack_require__.p = "";
 	return __webpack_require__(__webpack_require__.s = 40);
 })
 ([
 (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<t&&(this.input=new Array(t)),this.isUndef(e)||1===e?this.output=this.context.createGain():1<e&&(this.output=new Array(t))}var e;return a.prototype.set=function(t,e,n){if(this.isObject(t))n=e;else if(this.isString(t)){var o={};o[t]=e,t=o}t:for(var i in t){e=t[i];var r=this;if(-1!==i.indexOf(".")){for(var s=i.split("."),u=0;u<s.length-1;u++)if((r=r[s[u]])instanceof a){s.splice(0,u+1);var p=s.join(".");r.set(p,e);continue t}i=s[s.length-1]}var c=r[i];this.isUndef(c)||(a.Signal&&c instanceof a.Signal||a.Param&&c instanceof a.Param?c.value!==e&&(this.isUndef(n)?c.value=e:c.rampTo(e,n)):c instanceof AudioParam?c.value!==e&&(c.value=e):c instanceof a?c.set(e):c!==e&&(r[i]=e))}return this},a.prototype.get=function(t){this.isUndef(t)?t=this._collectDefaults(this.constructor):this.isString(t)&&(t=[t]);for(var e={},n=0;n<t.length;n++){var o=t[n],i=this,r=e;if(-1!==o.indexOf(".")){for(var s=o.split("."),u=0;u<s.length-1;u++){var p=s[u];r[p]=r[p]||{},r=r[p],i=i[p]}o=s[s.length-1]}var c=i[o];this.isObject(t[o])?r[o]=c.get():a.Signal&&c instanceof a.Signal?r[o]=c.value:a.Param&&c instanceof a.Param?r[o]=c.value:c instanceof AudioParam?r[o]=c.value:c instanceof a?r[o]=c.get():this.isFunction(c)||this.isUndef(c)||(r[o]=c)}return e},a.prototype._collectDefaults=function(t){var e=[];if(this.isUndef(t.defaults)||(e=Object.keys(t.defaults)),!this.isUndef(t._super))for(var n=this._collectDefaults(t._super),o=0;o<n.length;o++)-1===e.indexOf(n[o])&&e.push(n[o]);return e},a.prototype.toString=function(){for(var t in a){var e=t[0].match(/^[A-Z]$/),n=a[t]===this.constructor;if(this.isFunction(a[t])&&e&&n)return t}return"Tone"},Object.defineProperty(a.prototype,"numberOfInputs",{get:function(){return this.input?this.isArray(this.input)?this.input.length:1:0}}),Object.defineProperty(a.prototype,"numberOfOutputs",{get:function(){return this.output?this.isArray(this.output)?this.output.length:1:0}}),a.prototype.dispose=function(){return this.isUndef(this.input)||(this.input instanceof AudioNode&&this.input.disconnect(),this.input=null),this.isUndef(this.output)||(this.output instanceof AudioNode&&this.output.disconnect(),this.output=null),this},a.prototype.connect=function(t,e,n){return Array.isArray(this.output)?(e=this.defaultArg(e,0),this.output[e].connect(t,0,n)):this.output.connect(t,e,n),this},a.prototype.disconnect=function(t,e,n){this.isArray(this.output)?this.isNumber(t)?this.output[t].disconnect():(e=this.defaultArg(e,0),this.output[e].disconnect(t,0,n)):this.output.disconnect.apply(this.output,arguments)},a.prototype.connectSeries=function(){if(1<arguments.length)for(var t=arguments[0],e=1;e<arguments.length;e++){var n=arguments[e];t.connect(n),t=n}return this},a.prototype.chain=function(){if(0<arguments.length)for(var t=this,e=0;e<arguments.length;e++){var n=arguments[e];t.connect(n),t=n}return this},a.prototype.fan=function(){if(0<arguments.length)for(var t=0;t<arguments.length;t++)this.connect(arguments[t]);return this},AudioNode.prototype.chain=a.prototype.chain,AudioNode.prototype.fan=a.prototype.fan,a.prototype.defaultArg=function(t,e){if(this.isObject(t)&&this.isObject(e)){var n={};for(var o in t)n[o]=this.defaultArg(e[o],t[o]);for(var i in e)n[i]=this.defaultArg(t[i],e[i]);return n}return this.isUndef(t)?e:t},a.prototype.optionsObject=function(t,e,n){var o={};if(1===t.length&&this.isObject(t[0]))o=t[0];else for(var i=0;i<e.length;i++)o[e[i]]=t[i];return this.isUndef(n)?o:this.defaultArg(o,n)},a.prototype.isUndef=function(t){return void 0===t},a.prototype.isFunction=function(t){return"function"==typeof t},a.prototype.isNumber=function(t){return"number"==typeof t},a.prototype.isObject=function(t){return"[object Object]"===Object.prototype.toString.call(t)&&t.constructor===Object},a.prototype.isBoolean=function(t){return"boolean"==typeof t},a.prototype.isArray=function(t){return Array.isArray(t)},a.prototype.isString=function(t){return"string"==typeof t},a.noOp=function(){},a.prototype._readOnly=function(t){if(Array.isArray(t))for(var e=0;e<t.length;e++)this._readOnly(t[e]);else Object.defineProperty(this,t,{writable:!1,enumerable:!0})},a.prototype._writable=function(t){if(Array.isArray(t))for(var e=0;e<t.length;e++)this._writable(t[e]);else Object.defineProperty(this,t,{writable:!0})},a.State={Started:"started",Stopped:"stopped",Paused:"paused"},a.prototype.equalPowerScale=function(t){var e=.5*Math.PI;return Math.sin(t*e)},a.prototype.dbToGain=function(t){return Math.pow(2,t/6)},a.prototype.gainToDb=function(t){return Math.log(t)/Math.LN10*20},a.prototype.intervalToFrequencyRatio=function(t){return Math.pow(2,t/12)},a.prototype.now=function(){return a.context.now()},a.now=function(){return a.context.now()},a.extend=function(t,e){function n(){}a.prototype.isUndef(e)&&(e=a),n.prototype=e.prototype,t.prototype=new n,(t.prototype.constructor=t)._super=e},Object.defineProperty(a,"context",{get:function(){return e},set:function(t){e=a.Context&&t instanceof a.Context?t:new a.Context(t),a.Context&&a.Context.emit("init",e)}}),Object.defineProperty(a.prototype,"context",{get:function(){return a.context}}),a.setContext=function(t){a.context=t},Object.defineProperty(a.prototype,"blockTime",{get:function(){return 128/this.context.sampleRate}}),Object.defineProperty(a.prototype,"sampleTime",{get:function(){return 1/this.context.sampleRate}}),Object.defineProperty(a,"supported",{get:function(){var t=window.hasOwnProperty("AudioContext")||window.hasOwnProperty("webkitAudioContext"),e=window.hasOwnProperty("Promise"),n=window.hasOwnProperty("Worker");return t&&e&&n}}),a.version="r10",window.TONE_SILENCE_VERSION_LOGGING||console.log("%c * Tone.js "+a.version+" * ","background: #000; color: #fff"),a}).call(exports, __webpack_require__, exports, module),
				__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__(0),__webpack_require__(2),__webpack_require__(10)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.Multiply=function(t){this.createInsOuts(2,0),this._mult=this.input[0]=this.output=new i.Gain,this._param=this.input[1]=this.output.gain,this._param.value=this.defaultArg(t,0)},i.extend(i.Multiply,i.Signal),i.Multiply.prototype.dispose=function(){return i.prototype.dispose.call(this),this._mult.dispose(),this._mult=null,this._param=null,this},i.Multiply}).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__(0),__webpack_require__(6),__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, __webpack_exports__, __webpack_require__) {

"use strict";
(function(global) { __webpack_require__.d(__webpack_exports__, "b", function() { return getAudioContext; });
 __webpack_require__.d(__webpack_exports__, "c", function() { return userStartAudio; });
 var startaudiocontext__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22);
 var startaudiocontext__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(startaudiocontext__WEBPACK_IMPORTED_MODULE_0__);
 var Tone_core_Tone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
 var Tone_core_Tone__WEBPACK_IMPORTED_MODULE_1___default = __webpack_require__.n(Tone_core_Tone__WEBPACK_IMPORTED_MODULE_1__);
 var Tone_core_Context__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12);
 var Tone_core_Context__WEBPACK_IMPORTED_MODULE_2___default = __webpack_require__.n(Tone_core_Context__WEBPACK_IMPORTED_MODULE_2__);
global.TONE_SILENCE_VERSION_LOGGING = true;



var audiocontext = new window.AudioContext(); 

Tone_core_Tone__WEBPACK_IMPORTED_MODULE_1___default.a.setContext(audiocontext);
/**
 * <p>Returns the Audio Context for this sketch. Useful for users
 * who would like to dig deeper into the <a target='_blank' href=
 * 'http://webaudio.github.io/web-audio-api/'>Web Audio API
 * </a>.</p>
 *
 * <p>Some browsers require users to startAudioContext
 * with a user gesture, such as touchStarted in the example below.</p>
 *
 * @for p5
 * @method getAudioContext
 * @return {Object}    AudioContext for this sketch
 * @example
 * <div><code>
 *  function draw() {
 *    background(255);
 *    textAlign(CENTER);
 *
 *    if (getAudioContext().state !== 'running') {
 *      text('click to start audio', width/2, height/2);
 *    } else {
 *      text('audio is enabled', width/2, height/2);
 *    }
 *  }
 *
 *  function touchStarted() {
 *    if (getAudioContext().state !== 'running') {
 *      getAudioContext().resume();
 *    }
 *    var synth = new p5.MonoSynth();
 *    synth.play('A4', 0.5, 0, 0.2);
 *  }
 *
 * </div></code>
 */

function getAudioContext() {
  return audiocontext;
}
/**
 *  <p>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
 *  <a href="https://goo.gl/7K7WLu" title="Google Chrome's autoplay
 *  policy">Google Chrome</a>, which create the Web Audio API's
 *  <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioContext"
 *  title="Audio Context @ MDN">Audio Context</a>
 *  in a suspended state.</p>
 *
 *  <p>In these browser-specific policies, sound will not play until a user
 *  interaction event (i.e. <code>mousePressed()</code>) explicitly resumes
 *  the AudioContext, or starts an audio node. This can be accomplished by
 *  calling <code>start()</code> on a <code>p5.Oscillator</code>,
 *  <code> play()</code> on a <code>p5.SoundFile</code>, or simply
 *  <code>userStartAudio()</code>.</p>
 *
 *  <p><code>userStartAudio()</code> starts the AudioContext on a user
 *  gesture. The default behavior will enable audio on any
 *  mouseUp or touchEnd event. It can also be placed in a specific
 *  interaction function, such as <code>mousePressed()</code> as in the
 *  example below. This method utilizes
 *  <a href="https://github.com/tambien/StartAudioContext">StartAudioContext
 *  </a>, a library by Yotam Mann (MIT Licence, 2016).</p>
 *  @param  {Element|Array}   [element(s)] This argument can be an Element,
 *                                Selector String, NodeList, p5.Element,
 *                                jQuery Element, or an Array of any of those.
 *  @param  {Function} [callback] Callback to invoke when the AudioContext
 *                                has started
 *  @return {Promise}            Returns a Promise that resolves when
 *                                       the AudioContext state is 'running'
 *  @method userStartAudio
 *  @for p5
 *  @example
 *  <div><code>
 *  function setup() {
 *    // mimics the autoplay policy
 *    getAudioContext().suspend();
 *
 *    let mySynth = new p5.MonoSynth();
 *
 *    // This won't play until the context has resumed
 *    mySynth.play('A6');
 *  }
 *  function draw() {
 *    background(220);
 *    textAlign(CENTER, CENTER);
 *    text(getAudioContext().state, width/2, height/2);
 *  }
 *  function mousePressed() {
 *    userStartAudio();
 *  }
 *  </code></div>
 */

function userStartAudio(elements, callback) {
  var elt = elements;

  if (elements instanceof p5.Element) {
    elt = elements.elt;
  } else if (elements instanceof Array && elements[0] instanceof p5.Element) {
    elt = elements.map(function (e) {
      return e.elt;
    });
  }

  return startaudiocontext__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__(0),__webpack_require__(2),__webpack_require__(10)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.Add=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.input[1]=this.output=new i.Gain,this._param=this.input[1]=new i.Signal(t),this._param.connect(this._sum)},i.extend(i.Add,i.Signal),i.Add.prototype.dispose=function(){return i.prototype.dispose.call(this),this._sum.dispose(),this._sum=null,this._param.dispose(),this._param=null,this},i.Add}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

 }),
 (function(module, exports) {

module.exports = {
  recorderProcessor: 'recorder-processor',
  soundFileProcessor: 'sound-file-processor',
  amplitudeProcessor: 'amplitude-processor'
};

 }),
 (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__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;t<r;t++){var s=t/(r-1)*2-1;this._curve[t]=e(s,t)}return this._shaper.curve=this._curve,this},Object.defineProperty(e.WaveShaper.prototype,"curve",{get:function(){return this._shaper.curve},set:function(e){this._curve=new Float32Array(e),this._shaper.curve=this._curve}}),Object.defineProperty(e.WaveShaper.prototype,"oversample",{get:function(){return this._shaper.oversample},set:function(e){if(-1===["none","2x","4x"].indexOf(e))throw new RangeError("Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'");this._shaper.oversample=e}}),e.WaveShaper.prototype.dispose=function(){return e.prototype.dispose.call(this),this._shaper.disconnect(),this._shaper=null,this._curve=null,this},e.WaveShaper}).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__(0),__webpack_require__(2),__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}),e<this._minOutput?(this._param.exponentialRampToValueAtTime(this._minOutput,t-this.sampleTime),this.setValueAtTime(0,t)):this._param.exponentialRampToValueAtTime(e,t),this},o.TimelineSignal.prototype.setTargetAtTime=function(e,t,i){return e=this._fromUnits(e),e=Math.max(this._minOutput,e),i=Math.max(this._minOutput,i),t=this.toSeconds(t),this._events.add({type:o.TimelineSignal.Type.Target,value:e,time:t,constant:i}),this._param.setTargetAtTime(e,t,i),this},o.TimelineSignal.prototype.setValueCurveAtTime=function(e,t,i,n){n=this.defaultArg(n,1);for(var a=new Array(e.length),l=0;l<a.length;l++)a[l]=this._fromUnits(e[l])*n;t=this.toSeconds(t),i=this.toSeconds(i),this._events.add({type:o.TimelineSignal.Type.Curve,value:a,time:t,duration:i}),this._param.setValueAtTime(a[0],t);for(var s=1;s<a.length;s++){var r=t+s/(a.length-1)*i;this._param.linearRampToValueAtTime(a[s],r)}return this},o.TimelineSignal.prototype.cancelScheduledValues=function(e){return e=this.toSeconds(e),this._events.cancel(e),this._param.cancelScheduledValues(e),this},o.TimelineSignal.prototype.setRampPoint=function(e){e=this.toSeconds(e);var t=this._toUnits(this.getValueAtTime(e)),i=this._searchBefore(e);if(i&&i.time===e)this.cancelScheduledValues(e+this.sampleTime);else if(i&&i.type===o.TimelineSignal.Type.Curve&&i.time+i.duration>e)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__(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__(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__(0),__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:1<t&&(this.input=new Array(t)),1===n?this.output=new i.Gain:1<n&&(this.output=new Array(t))},i.Gain}).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__(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__(0),__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;o<n.length;o++)n[o]=t;var i=this._context.createBufferSource();return i.channelCount=1,i.channelCountMode="explicit",i.buffer=e,i.loop=!0,i.start(0),this._constants[t]=i},Object.defineProperty(o.Context.prototype,"lag",{get:function(){var t=this._computedUpdateInterval-this._updateInterval;return t=Math.max(t,0)}}),Object.defineProperty(o.Context.prototype,"lookAhead",{get:function(){return this._lookAhead},set:function(t){this._lookAhead=t}}),Object.defineProperty(o.Context.prototype,"updateInterval",{get:function(){return this._updateInterval},set:function(t){this._updateInterval=Math.max(t,o.prototype.blockTime),this._worker.postMessage(Math.max(1e3*t,1))}}),Object.defineProperty(o.Context.prototype,"latencyHint",{get:function(){return this._latencyHint},set:function(t){var e=t;if(this._latencyHint=t,this.isString(t))switch(t){case"interactive":e=.1,this._context.latencyHint=t;break;case"playback":e=.8,this._context.latencyHint=t;break;case"balanced":e=.25,this._context.latencyHint=t;break;case"fastest":e=.01}this.lookAhead=e,this.updateInterval=e/3}}),o.supported?(i=AudioNode.prototype.connect,r=AudioNode.prototype.disconnect,AudioNode.prototype.connect!==t&&(AudioNode.prototype.connect=t,AudioNode.prototype.disconnect=function(e,t,n){if(e&&e.input&&Array.isArray(e.input))o.prototype.isUndef(n)&&(n=0),this.disconnect(e.input[n],t,n);else if(e&&e.input)this.disconnect(e.input,t,n);else try{r.apply(this,arguments)}catch(t){throw new Error("error disconnecting node: "+e+"\n"+t)}}),o.context=new o.Context):console.warn("This browser does not support Tone.js"),o.Context}).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__(0),__webpack_require__(4),__webpack_require__(20),__webpack_require__(2),__webpack_require__(10)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){"use strict";return n.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new n.Gain,this._neg=new n.Negate,this._param=this.input[1]=new n.Signal(t),this._param.chain(this._neg,this._sum)},n.extend(n.Subtract,n.Signal),n.Subtract.prototype.dispose=function(){return n.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},n.Subtract}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

 }),
 (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){"use strict";return o.Emitter=function(){this._events={}},o.extend(o.Emitter),o.Emitter.prototype.on=function(t,e){for(var i=t.split(/\W+/),r=0;r<i.length;r++){var n=i[r];this._events.hasOwnProperty(n)||(this._events[n]=[]),this._events[n].push(e)}return this},o.Emitter.prototype.off=function(t,e){for(var i=t.split(/\W+/),r=0;r<i.length;r++)if(t=i[r],this._events.hasOwnProperty(t))if(o.prototype.isUndef(e))this._events[t]=[];else for(var n=this._events[t],s=0;s<n.length;s++)n[s]===e&&n.splice(s,1);return this},o.Emitter.prototype.emit=function(t){if(this._events){var e=Array.apply(null,arguments).slice(1);if(this._events.hasOwnProperty(t))for(var i=this._events[t],r=0,n=i.length;r<n;r++)i[r].apply(this,e)}return this},o.Emitter.mixin=function(t){var e=["on","off","emit"];t._events={};for(var i=0;i<e.length;i++){var r=e[i],n=o.Emitter.prototype[r];t[r]=n}},o.Emitter.prototype.dispose=function(){return o.prototype.dispose.call(this),this._events=null,this},o.Emitter}).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__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(c){"use strict";return c.SignalBase=function(){},c.extend(c.SignalBase),c.SignalBase.prototype.connect=function(e,n,a){return c.Signal&&c.Signal===e.constructor||c.Param&&c.Param===e.constructor||c.TimelineSignal&&c.TimelineSignal===e.constructor?(e._param.cancelScheduledValues(0),e._param.value=0,e.overridden=!0):e instanceof AudioParam&&(e.cancelScheduledValues(0),e.value=0),c.prototype.connect.call(this,e,n,a),this},c.SignalBase}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

 }),
 (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(17)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){return o.Time=function(t,e){if(!(this instanceof o.Time))return new o.Time(t,e);this._plusNow=!1,o.TimeBase.call(this,t,e)},o.extend(o.Time,o.TimeBase),o.Time.prototype._unaryExpressions=Object.create(o.TimeBase.prototype._unaryExpressions),o.Time.prototype._unaryExpressions.quantize={regexp:/^@/,method:function(t){return o.Transport.nextSubdivision(t())}},o.Time.prototype._unaryExpressions.now={regexp:/^\+/,method:function(t){return this._plusNow=!0,t()}},o.Time.prototype.quantize=function(t,e){return e=this.defaultArg(e,1),this._expr=function(t,e,o){return t=t(),e=e.toSeconds(),t+(Math.round(t/e)*e-t)*o}.bind(this,this._expr,new this.constructor(t),e),this},o.Time.prototype.addNow=function(){return this._plusNow=!0,this},o.Time.prototype._defaultExpr=function(){return this._plusNow=!0,this._noOp},o.Time.prototype.copy=function(t){return o.TimeBase.prototype.copy.call(this,t),this._plusNow=t._plusNow,this},o.Time.prototype.toNotation=function(){var t=this.toSeconds(),e=this._toNotationHelper(t,["1m","2n","4n","8n","16n","32n","64n","128n"]),o=this._toNotationHelper(t,["1m","2n","2t","4n","4t","8n","8t","16n","16t","32n","32t","64n","64t","128n"]);return o.split("+").length<e.split("+").length?o:e},o.Time.prototype._toNotationHelper=function(t,e){for(var o=this._notationToUnits(e[e.length-1]),n="",i=0;i<e.length;i++){var r=this._notationToUnits(e[i]),s=t/r;if(1-s%1<1e-6&&(s+=1e-6),0<(s=Math.floor(s))){if(n+=1===s?e[i]:s.toString()+"*"+e[i],(t-=s*r)<o)break;n+=" + "}}return""===n&&(n="0"),n},o.Time.prototype._notationToUnits=function(t){for(var e=this._primaryExpressions,o=[e.n,e.t,e.m],n=0;n<o.length;n++){var i=o[n],r=t.match(i.regexp);if(r)return i.method.call(this,r[1])}},o.Time.prototype.toBarsBeatsSixteenths=function(){var t=this._beatsToUnits(1),e=this.toSeconds()/t,o=Math.floor(e/this._timeSignature()),n=e%1*4;return e=Math.floor(e)%this._timeSignature(),3<(n=n.toString()).length&&(n=parseFloat(n).toFixed(3)),[o,e,n].join(":")},o.Time.prototype.toTicks=function(){var t=this._beatsToUnits(1),e=this.valueOf()/t;return Math.floor(e*o.Transport.PPQ)},o.Time.prototype.toSamples=function(){return this.toSeconds()*this.context.sampleRate},o.Time.prototype.toFrequency=function(){return 1/this.toSeconds()},o.Time.prototype.toSeconds=function(){return this.valueOf()},o.Time.prototype.toMilliseconds=function(){return 1e3*this.toSeconds()},o.Time.prototype.valueOf=function(){return this._expr()+(this._plusNow?this.now():0)},o.Time}).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__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){return n.TimeBase=function(e,t){if(!(this instanceof n.TimeBase))return new n.TimeBase(e,t);if(this._expr=this._noOp,e instanceof n.TimeBase)this.copy(e);else if(!this.isUndef(t)||this.isNumber(e)){t=this.defaultArg(t,this._defaultUnits);var r=this._primaryExpressions[t].method;this._expr=r.bind(this,e)}else this.isString(e)?this.set(e):this.isUndef(e)&&(this._expr=this._defaultExpr())},n.extend(n.TimeBase),n.TimeBase.prototype.set=function(e){return this._expr=this._parseExprString(e),this},n.TimeBase.prototype.clone=function(){var e=new this.constructor;return e.copy(this),e},n.TimeBase.prototype.copy=function(e){var t=e._expr();return this.set(t)},n.TimeBase.prototype._primaryExpressions={n:{regexp:/^(\d+)n/i,method:function(e){return 1===(e=parseInt(e))?this._beatsToUnits(this._timeSignature()):this._beatsToUnits(4/e)}},t:{regexp:/^(\d+)t/i,method:function(e){return e=parseInt(e),this._beatsToUnits(8/(3*parseInt(e)))}},m:{regexp:/^(\d+)m/i,method:function(e){return this._beatsToUnits(parseInt(e)*this._timeSignature())}},i:{regexp:/^(\d+)i/i,method:function(e){return this._ticksToUnits(parseInt(e))}},hz:{regexp:/^(\d+(?:\.\d+)?)hz/i,method:function(e){return this._frequencyToUnits(parseFloat(e))}},tr:{regexp:/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,method:function(e,t,r){var n=0;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}},s:{regexp:/^(\d+(?:\.\d+)?s)/,method:function(e){return this._secondsToUnits(parseFloat(e))}},samples:{regexp:/^(\d+)samples/,method:function(e){return parseInt(e)/this.context.sampleRate}},default:{regexp:/^(\d+(?:\.\d+)?)/,method:function(e){return this._primaryExpressions[this._defaultUnits].method.call(this,e)}}},n.TimeBase.prototype._binaryExpressions={"+":{regexp:/^\+/,precedence:2,method:function(e,t){return e()+t()}},"-":{regexp:/^\-/,precedence:2,method:function(e,t){return e()-t()}},"*":{regexp:/^\*/,precedence:1,method:function(e,t){return e()*t()}},"/":{regexp:/^\//,precedence:1,method:function(e,t){return e()/t()}}},n.TimeBase.prototype._unaryExpressions={neg:{regexp:/^\-/,method:function(e){return-e()}}},n.TimeBase.prototype._syntaxGlue={"(":{regexp:/^\(/},")":{regexp:/^\)/}},n.TimeBase.prototype._tokenize=function(e){for(var t=-1,r=[];0<e.length;){var n=i(e=e.trim(),this);r.push(n),e=e.substr(n.value.length)}function i(e,t){for(var r=["_binaryExpressions","_unaryExpressions","_primaryExpressions","_syntaxGlue"],n=0;n<r.length;n++){var i=t[r[n]];for(var s in i){var o=i[s],p=o.regexp,a=e.match(p);if(null!==a)return{method:o.method,precedence:o.precedence,regexp:o.regexp,value:a[0]}}}throw new SyntaxError("Tone.TimeBase: Unexpected token "+e)}return{next:function(){return r[++t]},peek:function(){return r[t+1]}}},n.TimeBase.prototype._matchGroup=function(e,t,r){if(!this.isUndef(e))for(var n in t){var i=t[n];if(i.regexp.test(e.value)){if(this.isUndef(r))return i;if(i.precedence===r)return i}}return!1},n.TimeBase.prototype._parseBinary=function(e,t){var r;this.isUndef(t)&&(t=2),r=t<0?this._parseUnary(e):this._parseBinary(e,t-1);for(var n=e.peek();n&&this._matchGroup(n,this._binaryExpressions,t);)r=(n=e.next()).method.bind(this,r,this._parseBinary(e,t-1)),n=e.peek();return r},n.TimeBase.prototype._parseUnary=function(e){var t,r;t=e.peek();var n=this._matchGroup(t,this._unaryExpressions);return n?(t=e.next(),r=this._parseUnary(e),n.method.bind(this,r)):this._parsePrimary(e)},n.TimeBase.prototype._parsePrimary=function(e){var t,r;if(t=e.peek(),this.isUndef(t))throw new SyntaxError("Tone.TimeBase: Unexpected end of expression");if(this._matchGroup(t,this._primaryExpressions)){var n=(t=e.next()).value.match(t.regexp);return t.method.bind(this,n[1],n[2],n[3])}if(t&&"("===t.value){if(e.next(),r=this._parseBinary(e),!(t=e.next())||")"!==t.value)throw new SyntaxError("Expected )");return r}throw new SyntaxError("Tone.TimeBase: Cannot process token "+t.value)},n.TimeBase.prototype._parseExprString=function(e){this.isString(e)||(e=e.toString());var t=this._tokenize(e);return this._parseBinary(t)},n.TimeBase.prototype._noOp=function(){return 0},n.TimeBase.prototype._defaultExpr=function(){return this._noOp},n.TimeBase.prototype._defaultUnits="s",n.TimeBase.prototype._frequencyToUnits=function(e){return 1/e},n.TimeBase.prototype._beatsToUnits=function(e){return 60/n.Transport.bpm.value*e},n.TimeBase.prototype._secondsToUnits=function(e){return e},n.TimeBase.prototype._ticksToUnits=function(e){return e*(this._beatsToUnits(1)/n.Transport.PPQ)},n.TimeBase.prototype._timeSignature=function(){return n.Transport.timeSignature},n.TimeBase.prototype._pushExpr=function(e,t,r){return e instanceof n.TimeBase||(e=new this.constructor(e,r)),this._expr=this._binaryExpressions[t].method.bind(this,this._expr,e._expr),this},n.TimeBase.prototype.add=function(e,t){return this._pushExpr(e,"+",t)},n.TimeBase.prototype.sub=function(e,t){return this._pushExpr(e,"-",t)},n.TimeBase.prototype.mult=function(e,t){return this._pushExpr(e,"*",t)},n.TimeBase.prototype.div=function(e,t){return this._pushExpr(e,"/",t)},n.TimeBase.prototype.valueOf=function(){return this._expr()},n.TimeBase.prototype.dispose=function(){this._expr=null},n.TimeBase}).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__(0),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(a){"use strict";return a.Param=function(){var t=this.optionsObject(arguments,["param","units","convert"],a.Param.defaults);this._param=this.input=t.param,this.units=t.units,this.convert=t.convert,this.overridden=!1,this._lfo=null,this.isObject(t.lfo)?this.value=t.lfo:this.isUndef(t.value)||(this.value=t.value)},a.extend(a.Param),a.Param.defaults={units:a.Type.Default,convert:!0,param:void 0},Object.defineProperty(a.Param.prototype,"value",{get:function(){return this._toUnits(this._param.value)},set:function(t){if(this.isObject(t)){if(this.isUndef(a.LFO))throw new Error("Include 'Tone.LFO' to use an LFO as a Param value.");this._lfo&&this._lfo.dispose(),this._lfo=new a.LFO(t).start(),this._lfo.connect(this.input)}else{var e=this._fromUnits(t);this._param.cancelScheduledValues(0),this._param.value=e}}}),a.Param.prototype._fromUnits=function(t){if(!this.convert&&!this.isUndef(this.convert))return t;switch(this.units){case a.Type.Time:return this.toSeconds(t);case a.Type.Frequency:return this.toFrequency(t);case a.Type.Decibels:return this.dbToGain(t);case a.Type.NormalRange:return Math.min(Math.max(t,0),1);case a.Type.AudioRange:return Math.min(Math.max(t,-1),1);case a.Type.Positive:return Math.max(t,0);default:return t}},a.Param.prototype._toUnits=function(t){if(!this.convert&&!this.isUndef(this.convert))return t;switch(this.units){case a.Type.Decibels:return this.gainToDb(t);default:return t}},a.Param.prototype._minOutput=1e-5,a.Param.prototype.setValueAtTime=function(t,e){return t=this._fromUnits(t),(e=this.toSeconds(e))<=this.now()+this.blockTime?this._param.value=t:this._param.setValueAtTime(t,e),this},a.Param.prototype.setRampPoint=function(t){t=this.defaultArg(t,this.now());var e=this._param.value;return 0===e&&(e=this._minOutput),this._param.setValueAtTime(e,t),this},a.Param.prototype.linearRampToValueAtTime=function(t,e){return t=this._fromUnits(t),this._param.linearRampToValueAtTime(t,this.toSeconds(e)),this},a.Param.prototype.exponentialRampToValueAtTime=function(t,e){return t=this._fromUnits(t),t=Math.max(this._minOutput,t),this._param.exponentialRampToValueAtTime(t,this.toSeconds(e)),this},a.Param.prototype.exponentialRampToValue=function(t,e,i){return i=this.toSeconds(i),this.setRampPoint(i),this.exponentialRampToValueAtTime(t,i+this.toSeconds(e)),this},a.Param.prototype.linearRampToValue=function(t,e,i){return i=this.toSeconds(i),this.setRampPoint(i),this.linearRampToValueAtTime(t,i+this.toSeconds(e)),this},a.Param.prototype.setTargetAtTime=function(t,e,i){return t=this._fromUnits(t),t=Math.max(this._minOutput,t),i=Math.max(this._minOutput,i),this._param.setTargetAtTime(t,this.toSeconds(e),i),this},a.Param.prototype.setValueCurveAtTime=function(t,e,i){for(var a=0;a<t.length;a++)t[a]=this._fromUnits(t[a]);return this._param.setValueCurveAtTime(t,this.toSeconds(e),this.toSeconds(i)),this},a.Param.prototype.cancelScheduledValues=function(t){return this._param.cancelScheduledValues(this.toSeconds(t)),this},a.Param.prototype.rampTo=function(t,e,i){return e=this.defaultArg(e,0),this.units===a.Type.Frequency||this.units===a.Type.BPM||this.units===a.Type.Decibels?this.exponentialRampToValue(t,e,i):this.linearRampToValue(t,e,i),this},Object.defineProperty(a.Param.prototype,"lfo",{get:function(){return this._lfo}}),a.Param.prototype.dispose=function(){return a.prototype.dispose.call(this),this._param=null,this._lfo&&(this._lfo.dispose(),this._lfo=null),this},a.Param}).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__(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<this._timeline.length?this._timeline[i+1]:null},i.Timeline.prototype.getBefore=function(e){var i=this._timeline.length;if(0<i&&this._timeline[i-1].time<e)return this._timeline[i-1];var t=this._search(e);return 0<=t-1?this._timeline[t-1]:null},i.Timeline.prototype.cancel=function(e){if(1<this._timeline.length){var i=this._search(e);if(0<=i)if(this._timeline[i].time===e){for(var t=i;0<=t&&this._timeline[t].time===e;t--)i=t;this._timeline=this._timeline.slice(0,i)}else this._timeline=this._timeline.slice(0,i+1);else this._timeline=[]}else 1===this._timeline.length&&this._timeline[0].time>=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(0<t&&this._timeline[t-1].time<=e)return t-1;for(;i<n;){var r=Math.floor(i+(n-i)/2),s=this._timeline[r],h=this._timeline[r+1];if(s.time===e){for(var l=r;l<this._timeline.length;l++){this._timeline[l].time===e&&(r=l)}return r}if(s.time<e&&h.time>e)return r;s.time>e?n=r:s.time<e&&(i=r+1)}return-1},i.Timeline.prototype._iterate=function(e,i,t){this._iterating=!0,i=this.defaultArg(i,0),t=this.defaultArg(t,this._timeline.length-1);for(var n=i;n<=t;n++)e(this._timeline[n]);if(this._iterating=!1,0<this._toRemove.length){for(var r=0;r<this._toRemove.length;r++){var s=this._timeline.indexOf(this._toRemove[r]);-1!==s&&this._timeline.splice(s,1)}this._toRemove=[]}},i.Timeline.prototype.forEach=function(e){return this._iterate(e),this},i.Timeline.prototype.forEachBefore=function(e,i){var t=this._search(e);return-1!==t&&this._iterate(i,0,t),this},i.Timeline.prototype.forEachAfter=function(e,i){var t=this._search(e);return this._iterate(i,t+1),this},i.Timeline.prototype.forEachFrom=function(e,i){for(var t=this._search(e);0<=t&&this._timeline[t].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__(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__(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__));

 }),
 (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!function(e,t){ true?!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (t),
				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)):undefined}(this,function(){var r=function(e,t){this._dragged=!1,this._element=e,this._bindedMove=this._moved.bind(this),this._bindedEnd=this._ended.bind(this,t),e.addEventListener("touchstart",this._bindedEnd),e.addEventListener("touchmove",this._bindedMove),e.addEventListener("touchend",this._bindedEnd),e.addEventListener("mouseup",this._bindedEnd)};function o(e){return"running"===e.state}return r.prototype._moved=function(e){this._dragged=!0},r.prototype._ended=function(e){this._dragged||function(e){var t=e.createBuffer(1,1,e.sampleRate),n=e.createBufferSource();n.buffer=t,n.connect(e.destination),n.start(0),e.resume&&e.resume()}(e),this._dragged=!1},r.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(t,e,n){var i=new Promise(function(e){!function(t,n){o(t)?n():function e(){o(t)?n():(requestAnimationFrame(e),t.resume&&t.resume())}()}(t,e)}),d=[];return function e(t,n,i){if(Array.isArray(t)||NodeList&&t instanceof NodeList)for(var d=0;d<t.length;d++)e(t[d],n,i);else if("string"==typeof t)e(document.querySelectorAll(t),n,i);else if(t.jquery&&"function"==typeof t.toArray)e(t.toArray(),n,i);else if(Element&&t instanceof Element){var o=new r(t,i);n.push(o)}}(e=e||document.body,d,t),i.then(function(){for(var e=0;e<d.length;e++)d[e].dispose();d=null,n&&n()}),i}});

 }),
 (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0),__webpack_require__(2),__webpack_require__(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__));

 }),
 (function(module, exports) {

!function(){var l,s=[];function p(e){var o=this,n={},i=-1;this.parameters.forEach(function(e,t){var r=s[++i]||(s[i]=new Float32Array(o.bufferSize));r.fill(e.value),n[t]=r}),this.processor.realm.exec("self.sampleRate=sampleRate="+this.context.sampleRate+";self.currentTime=currentTime="+this.context.currentTime);var t=a(e.inputBuffer),r=a(e.outputBuffer);this.instance.process([t],[r],n)}function a(e){for(var t=[],r=0;r<e.numberOfChannels;r++)t[r]=e.getChannelData(r);return t}function f(e){return e.$$processors||(e.$$processors={})}function e(e){this.$$context=e}"function"!=typeof AudioWorkletNode&&(self.AudioWorkletNode=function(e,t,r){var o=f(e)[t],n=e.createScriptProcessor(void 0,2,r&&r.outputChannelCount?r.outputChannelCount[0]:2);if(n.parameters=new Map,o.properties)for(var i=0;i<o.properties.length;i++){var s=o.properties[i],a=e.createGain().gain;a.value=s.defaultValue,n.parameters.set(s.name,a)}var u=new MessageChannel;l=u.port2;var c=new o.Processor(r||{});return l=null,n.port=u.port1,n.processor=o,n.instance=c,n.onaudioprocess=p,n},Object.defineProperty((self.AudioContext||self.webkitAudioContext).prototype,"audioWorklet",{get:function(){return this.$$audioWorklet||(this.$$audioWorklet=new self.AudioWorklet(this))}}),self.AudioWorklet=(e.prototype.addModule=function(e,t){var n=this;return fetch(e).then(function(e){if(!e.ok)throw Error(e.status);return e.text()}).then(function(e){var r={sampleRate:0,currentTime:0,AudioWorkletProcessor:function(){this.port=l},registerProcessor:function(e,t){f(n.$$context)[e]={realm:o,context:r,Processor:t,properties:t.parameterDescriptors||[]}}},o=new function(e,t){var r=document.createElement("iframe");r.style.cssText="position:absolute;left:0;top:-999px;width:1px;height:1px;",t.appendChild(r);var o=r.contentWindow,n=o.document,i="var window,$hook";for(var s in o)s in e||"eval"===s||(i+=",",i+=s);for(var a in e)i+=",",i+=a,i+="=self.",i+=a;var u=n.createElement("script");u.appendChild(n.createTextNode('function $hook(self,console) {"use strict";\n        '+i+";return function() {return eval(arguments[0])}}")),n.body.appendChild(u),this.exec=o.$hook(e,console)}(r.self=r,document.documentElement);return o.exec((t&&t.transpile||String)(e)),null})},e))}();

 }),
 (function(module, exports) {

/**
 * This module has shims
 */

(function () {
  function fixSetTarget(param) {
    if (!param) 
      return;
    if (!param.setTargetAtTime) param.setTargetAtTime = param.setTargetValueAtTime;
  }

  if (window.hasOwnProperty('webkitAudioContext') && !window.hasOwnProperty('AudioContext')) {
    window.AudioContext = window.webkitAudioContext;
    if (typeof AudioContext.prototype.createGain !== 'function') AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;
    if (typeof AudioContext.prototype.createDelay !== 'function') AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode;
    if (typeof AudioContext.prototype.createScriptProcessor !== 'function') AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode;
    if (typeof AudioContext.prototype.createPeriodicWave !== 'function') AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable;
    AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain;

    AudioContext.prototype.createGain = function () {
      var node = this.internal_createGain();
      fixSetTarget(node.gain);
      return node;
    };

    AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay;

    AudioContext.prototype.createDelay = function (maxDelayTime) {
      var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay();
      fixSetTarget(node.delayTime);
      return node;
    };

    AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource;

    AudioContext.prototype.createBufferSource = function () {
      var node = this.internal_createBufferSource();

      if (!node.start) {
        node.start = function (when, offset, duration) {
          if (offset || duration) this.noteGrainOn(when || 0, offset, duration);else this.noteOn(when || 0);
        };
      } else {
        node.internal_start = node.start;

        node.start = function (when, offset, duration) {
          if (typeof duration !== 'undefined') node.internal_start(when || 0, offset, duration);else node.internal_start(when || 0, offset || 0);
        };
      }

      if (!node.stop) {
        node.stop = function (when) {
          this.noteOff(when || 0);
        };
      } else {
        node.internal_stop = node.stop;

        node.stop = function (when) {
          node.internal_stop(when || 0);
        };
      }

      fixSetTarget(node.playbackRate);
      return node;
    };

    AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor;

    AudioContext.prototype.createDynamicsCompressor = function () {
      var node = this.internal_createDynamicsCompressor();
      fixSetTarget(node.threshold);
      fixSetTarget(node.knee);
      fixSetTarget(node.ratio);
      fixSetTarget(node.reduction);
      fixSetTarget(node.attack);
      fixSetTarget(node.release);
      return node;
    };

    AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter;

    AudioContext.prototype.createBiquadFilter = function () {
      var node = this.internal_createBiquadFilter();
      fixSetTarget(node.frequency);
      fixSetTarget(node.detune);
      fixSetTarget(node.Q);
      fixSetTarget(node.gain);
      return node;
    };

    if (typeof AudioContext.prototype.createOscillator !== 'function') {
      AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator;

      AudioContext.prototype.createOscillator = function () {
        var node = this.internal_createOscillator();

        if (!node.start) {
          node.start = function (when) {
            this.noteOn(when || 0);
          };
        } else {
          node.internal_start = node.start;

          node.start = function (when) {
            node.internal_start(when || 0);
          };
        }

        if (!node.stop) {
          node.stop = function (when) {
            this.noteOff(when || 0);
          };
        } else {
          node.internal_stop = node.stop;

          node.stop = function (when) {
            node.internal_stop(when || 0);
          };
        }

        if (!node.setPeriodicWave) node.setPeriodicWave = node.setWaveTable;
        fixSetTarget(node.frequency);
        fixSetTarget(node.detune);
        return node;
      };
    }
  }

  if (window.hasOwnProperty('webkitOfflineAudioContext') && !window.hasOwnProperty('OfflineAudioContext')) {
    window.OfflineAudioContext = window.webkitOfflineAudioContext;
  }
})(window); 


navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
/**
 * Determine which filetypes are supported (inspired by buzz.js)
 * The audio element (el) will only be used to test browser support for various audio formats
 */

var el = document.createElement('audio');

p5.prototype.isSupported = function () {
  return !!el.canPlayType;
};

var isOGGSupported = function isOGGSupported() {
  return !!el.canPlayType && el.canPlayType('audio/ogg; codecs="vorbis"');
};

var isMP3Supported = function isMP3Supported() {
  return !!el.canPlayType && el.canPlayType('audio/mpeg;');
};

var isWAVSupported = function isWAVSupported() {
  return !!el.canPlayType && el.canPlayType('audio/wav; codecs="1"');
};

var isAACSupported = function isAACSupported() {
  return !!el.canPlayType && (el.canPlayType('audio/x-m4a;') || el.canPlayType('audio/aac;'));
};

var isAIFSupported = function isAIFSupported() {
  return !!el.canPlayType && el.canPlayType('audio/x-aiff;');
};

p5.prototype.isFileSupported = function (extension) {
  switch (extension.toLowerCase()) {
    case 'mp3':
      return isMP3Supported();

    case 'wav':
      return isWAVSupported();

    case 'ogg':
      return isOGGSupported();

    case 'aac':
    case 'm4a':
    case 'mp4':
      return isAACSupported();

    case 'aif':
    case 'aiff':
      return isAIFSupported();

    default:
      return false;
  }
};

 }),
 (function(module, exports) {

var g;g=function(){return this}();try{g=g||new Function("return this")()}catch(t){"object"==typeof window&&(g=window)}module.exports=g;

 }),
 (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] ? 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] ? 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] ? 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__(0),__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;o<t.length;o++)n[o]=r*this.intervalToFrequencyRatio(t[o]);return n}.bind(this,this._expr,e),this},o.Frequency.prototype.toMidi=function(){return this.frequencyToMidi(this.valueOf())},o.Frequency.prototype.toNote=function(){var e=this.valueOf(),t=Math.log(e/o.Frequency.A4)/Math.LN2,r=Math.round(12*t)+57,n=Math.floor(r/12);return n<0&&(r+=-12*n),i[r%12]+n.toString()},o.Frequency.prototype.toSeconds=function(){return 1/this.valueOf()},o.Frequency.prototype.toFrequency=function(){return this.valueOf()},o.Frequency.prototype.toTicks=function(){var e=this._beatsToUnits(1),t=this.valueOf()/e;return Math.floor(t*o.Transport.PPQ)},o.Frequency.prototype._frequencyToUnits=function(e){return e},o.Frequency.prototype._ticksToUnits=function(e){return 1/(60*e/(o.Transport.bpm.value*o.Transport.PPQ))},o.Frequency.prototype._beatsToUnits=function(e){return 1/o.TimeBase.prototype._beatsToUnits.call(this,e)},o.Frequency.prototype._secondsToUnits=function(e){return 1/e},o.Frequency.prototype._defaultUnits="hz";var n={cbb:-2,cb:-1,c:0,"c#":1,cx:2,dbb:0,db:1,d:2,"d#":3,dx:4,ebb:2,eb:3,e:4,"e#":5,ex:6,fbb:3,fb:4,f:5,"f#":6,fx:7,gbb:5,gb:6,g:7,"g#":8,gx:9,abb:7,ab:8,a:9,"a#":10,ax:11,bbb:9,bb:10,b:11,"b#":12,bx:13},i=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];return o.Frequency.A4=440,o.Frequency.prototype.midiToFrequency=function(e){return o.Frequency.A4*Math.pow(2,(e-69)/12)},o.Frequency.prototype.frequencyToMidi=function(e){return 69+12*Math.log(e/o.Frequency.A4)/Math.LN2},o.Frequency}).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__(0),__webpack_require__(16)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(o){return o.TransportTime=function(t,r){if(!(this instanceof o.TransportTime))return new o.TransportTime(t,r);o.Time.call(this,t,r)},o.extend(o.TransportTime,o.Time),o.TransportTime.prototype._unaryExpressions=Object.create(o.Time.prototype._unaryExpressions),o.TransportTime.prototype._unaryExpressions.quantize={regexp:/^@/,method:function(t){var r=this._secondsToTicks(t()),e=Math.ceil(o.Transport.ticks/r);return this._ticksToUnits(e*r)}},o.TransportTime.prototype._secondsToTicks=function(t){var r=t/this._beatsToUnits(1);return Math.round(r*o.Transport.PPQ)},o.TransportTime.prototype.valueOf=function(){return this._secondsToTicks(this._expr())+(this._plusNow?o.Transport.ticks:0)},o.TransportTime.prototype.toTicks=function(){return this.valueOf()},o.TransportTime.prototype.toSeconds=function(){return this._expr()+(this._plusNow?o.Transport.seconds:0)},o.TransportTime.prototype.toFrequency=function(){return 1/this.toSeconds()},o.TransportTime}).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__(0),__webpack_require__(4),__webpack_require__(13),__webpack_require__(1),__webpack_require__(33),__webpack_require__(21),__webpack_require__(34),__webpack_require__(20),__webpack_require__(35),__webpack_require__(36),__webpack_require__(37)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(p){"use strict";function r(e,n,r){var t=new e;return r._eval(n[0]).connect(t,0,0),r._eval(n[1]).connect(t,0,1),t}function t(e,n,r){var t=new e;return r._eval(n[0]).connect(t,0,0),t}function o(e){return e?parseFloat(e):void 0}function i(e){return e&&e.args?parseFloat(e.args):void 0}return p.Expr=function(){var n=this._replacements(Array.prototype.slice.call(arguments)),e=this._parseInputs(n);this._nodes=[],this.input=new Array(e);for(var r=0;r<e;r++)this.input[r]=this.context.createGain();var t,o=this._parseTree(n);try{t=this._eval(o)}catch(e){throw this._disposeNodes(),new Error("Tone.Expr: Could evaluate expression: "+n)}this.output=t},p.extend(p.Expr,p.SignalBase),p.Expr._Expressions={value:{signal:{regexp:/^\d+\.\d+|^\d+/,method:function(e){return new p.Signal(o(e))}},input:{regexp:/^\$\d/,method:function(e,n){return n.input[o(e.substr(1))]}}},glue:{"(":{regexp:/^\(/},")":{regexp:/^\)/},",":{regexp:/^,/}},func:{abs:{regexp:/^abs/,method:t.bind(this,p.Abs)},mod:{regexp:/^mod/,method:function(e,n){var r=i(e[1]),t=new p.Modulo(r);return n._eval(e[0]).connect(t),t}},pow:{regexp:/^pow/,method:function(e,n){var r=i(e[1]),t=new p.Pow(r);return n._eval(e[0]).connect(t),t}},a2g:{regexp:/^a2g/,method:function(e,n){var r=new p.AudioToGain;return n._eval(e[0]).connect(r),r}}},binary:{"+":{regexp:/^\+/,precedence:1,method:r.bind(this,p.Add)},"-":{regexp:/^\-/,precedence:1,method:function(e,n){return 1===e.length?t(p.Negate,e,n):r(p.Subtract,e,n)}},"*":{regexp:/^\*/,precedence:0,method:r.bind(this,p.Multiply)}},unary:{"-":{regexp:/^\-/,method:t.bind(this,p.Negate)},"!":{regexp:/^\!/,method:t.bind(this,p.NOT)}}},p.Expr.prototype._parseInputs=function(e){var n=e.match(/\$\d/g),r=0;if(null!==n)for(var t=0;t<n.length;t++){var o=parseInt(n[t].substr(1))+1;r=Math.max(r,o)}return r},p.Expr.prototype._replacements=function(e){for(var n=e.shift(),r=0;r<e.length;r++)n=n.replace(/\%/i,e[r]);return n},p.Expr.prototype._tokenize=function(e){for(var n=-1,r=[];0<e.length;){var t=o(e=e.trim());r.push(t),e=e.substr(t.value.length)}function o(e){for(var n in p.Expr._Expressions){var r=p.Expr._Expressions[n];for(var t in r){var o=r[t],i=o.regexp,a=e.match(i);if(null!==a)return{type:n,value:a[0],method:o.method}}}throw new SyntaxError("Tone.Expr: Unexpected token "+e)}return{next:function(){return r[++n]},peek:function(){return r[n+1]}}},p.Expr.prototype._parseTree=function(e){var t=this._tokenize(e),a=this.isUndef.bind(this);function r(e,n){return!a(e)&&"glue"===e.type&&e.value===n}function o(e,n,r){var t=p.Expr._Expressions[n];if(!a(e))for(var o in t){var i=t[o];if(i.regexp.test(e.value)){if(a(r))return!0;if(i.precedence===r)return!0}}return!1}function i(e){var n;a(e)&&(e=5),n=e<0?function e(){var n,r;n=t.peek();if(o(n,"unary"))return n=t.next(),r=e(),{operator:n.value,method:n.method,args:[r]};return s()}():i(e-1);for(var r=t.peek();o(r,"binary",e);)n={operator:(r=t.next()).value,method:r.method,args:[n,i(e-1)]},r=t.peek();return n}function s(){var e,n;if(e=t.peek(),a(e))throw new SyntaxError("Tone.Expr: Unexpected termination of expression");if("func"===e.type)return function(e){var n=[];if(!r(t.next(),"("))throw new SyntaxError('Tone.Expr: Expected ( in a function call "'+e.value+'"');r(t.peek(),")")||(n=function(){var e,n=[];for(;e=i(),!a(e)&&(n.push(e),r(t.peek(),","));)t.next();return n}());if(r(t.next(),")"))return{method:e.method,args:n,name:name};throw new SyntaxError('Tone.Expr: Expected ) in a function call "'+e.value+'"')}(e=t.next());if("value"===e.type)return{method:(e=t.next()).method,args:e.value};if(r(e,"(")){if(t.next(),n=i(),!r(e=t.next(),")"))throw new SyntaxError("Expected )");return n}throw new SyntaxError("Tone.Expr: Parse error, cannot process token "+e.value)}return i()},p.Expr.prototype._eval=function(e){if(!this.isUndef(e)){var n=e.method(e.args,this);return this._nodes.push(n),n}},p.Expr.prototype._disposeNodes=function(){for(var e=0;e<this._nodes.length;e++){var n=this._nodes[e];this.isFunction(n.dispose)?n.dispose():this.isFunction(n.disconnect)&&n.disconnect(),n=null,this._nodes[e]=null}this._nodes=null},p.Expr.prototype.dispose=function(){p.prototype.dispose.call(this),this._disposeNodes()},p.Expr}).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__(0),__webpack_require__(21),__webpack_require__(13),__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(e){"use strict";return e.GreaterThan=function(t){this.createInsOuts(2,0),this._param=this.input[0]=new e.Subtract(t),this.input[1]=this._param.input[1],this._gtz=this.output=new e.GreaterThanZero,this._param.connect(this._gtz)},e.extend(e.GreaterThan,e.Signal),e.GreaterThan.prototype.dispose=function(){return e.prototype.dispose.call(this),this._param.dispose(),this._param=null,this._gtz.dispose(),this._gtz=null,this},e.GreaterThan}).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__(0),__webpack_require__(6),__webpack_require__(15)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(s){"use strict";return s.Abs=function(){this._abs=this.input=this.output=new s.WaveShaper(function(s){return 0===s?0:Math.abs(s)},127)},s.extend(s.Abs,s.SignalBase),s.Abs.prototype.dispose=function(){return s.prototype.dispose.call(this),this._abs.dispose(),this._abs=null,this},s.Abs}).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__(0),__webpack_require__(6),__webpack_require__(1),__webpack_require__(13)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(i){"use strict";return i.Modulo=function(t){this.createInsOuts(1,0),this._shaper=new i.WaveShaper(Math.pow(2,16)),this._multiply=new i.Multiply,this._subtract=this.output=new i.Subtract,this._modSignal=new i.Signal(t),this.input.fan(this._shaper,this._subtract),this._modSignal.connect(this._multiply,0,0),this._shaper.connect(this._multiply,0,1),this._multiply.connect(this._subtract,0,1),this._setWaveShaper(t)},i.extend(i.Modulo,i.SignalBase),i.Modulo.prototype._setWaveShaper=function(i){this._shaper.setMap(function(t){return Math.floor((t+1e-4)/i)})},Object.defineProperty(i.Modulo.prototype,"value",{get:function(){return this._modSignal.value},set:function(t){this._modSignal.value=t,this._setWaveShaper(t)}}),i.Modulo.prototype.dispose=function(){return i.prototype.dispose.call(this),this._shaper.dispose(),this._shaper=null,this._multiply.dispose(),this._multiply=null,this._subtract.dispose(),this._subtract=null,this._modSignal.dispose(),this._modSignal=null,this},i.Modulo}).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__(0),__webpack_require__(6)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(t){"use strict";return t.Pow=function(e){this._exp=this.defaultArg(e,1),this._expScaler=this.input=this.output=new t.WaveShaper(this._expFunc(this._exp),8192)},t.extend(t.Pow,t.SignalBase),Object.defineProperty(t.Pow.prototype,"value",{get:function(){return this._exp},set:function(e){this._exp=e,this._expScaler.setMap(this._expFunc(this._exp))}}),t.Pow.prototype._expFunc=function(t){return function(e){return Math.pow(Math.abs(e),t)}},t.Pow.prototype.dispose=function(){return t.prototype.dispose.call(this),this._expScaler.dispose(),this._expScaler=null,this},t.Pow}).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__(0),__webpack_require__(6),__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(n){"use strict";return n.AudioToGain=function(){this._norm=this.input=this.output=new n.WaveShaper(function(n){return(n+1)/2})},n.extend(n.AudioToGain,n.SignalBase),n.AudioToGain.prototype.dispose=function(){return n.prototype.dispose.call(this),this._norm.dispose(),this._norm=null,this},n.AudioToGain}).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__(0),__webpack_require__(6)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(e){"use strict";return e.EqualPowerGain=function(){this._eqPower=this.input=this.output=new e.WaveShaper(function(e){return Math.abs(e)<.001?0:this.equalPowerScale(e)}.bind(this),4096)},e.extend(e.EqualPowerGain,e.SignalBase),e.EqualPowerGain.prototype.dispose=function(){return e.prototype.dispose.call(this),this._eqPower.dispose(),this._eqPower=null,this},e.EqualPowerGain}).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__(0),__webpack_require__(19),__webpack_require__(9)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(t){"use strict";return t.TimelineState=function(e){t.Timeline.call(this),this._initial=e},t.extend(t.TimelineState,t.Timeline),t.TimelineState.prototype.getValueAtTime=function(e){var t=this.get(e);return null!==t?t.state:this._initial},t.TimelineState.prototype.setStateAtTime=function(e,t){this.add({state:e,time:t})},t.TimelineState}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));

 }),
 (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);

var audioworklet_polyfill = __webpack_require__(24);

var shims = __webpack_require__(25);

var audiocontext = __webpack_require__(3);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }


var main_Main = function Main() {
  _classCallCheck(this, Main);

  this.input = audiocontext["a" ].createGain();
  this.output = audiocontext["a" ].createGain(); 

  this.limiter = audiocontext["a" ].createDynamicsCompressor();
  this.limiter.threshold.value = -3;
  this.limiter.ratio.value = 20;
  this.limiter.knee.value = 1;
  this.audiocontext = audiocontext["a" ];
  this.output.disconnect(); 

  this.input.connect(this.limiter); 

  this.limiter.connect(this.output); 

  this.meter = audiocontext["a" ].createGain();
  this.fftMeter = audiocontext["a" ].createGain();
  this.output.connect(this.meter);
  this.output.connect(this.fftMeter); 

  this.output.connect(this.audiocontext.destination); 

  this.soundArray = []; 

  this.parts = []; 

  this.extensions = [];
}; 


var p5sound = new main_Main();
/**
 * Returns a number representing the output volume for sound
 * in this sketch.
 *
 * @method getOutputVolume
 * @return {Number} Output volume for sound in this sketch.
 *                  Should be between 0.0 (silence) and 1.0.
 */

p5.prototype.getOutputVolume = function () {
  return p5sound.output.gain.value;
};
/**
 *  <p>Scale the output of all sound in this sketch</p>
 *  Scaled 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 <code>rampTime</code> 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.
 *
 *  <p><b>How This Works</b>: When you load the p5.sound module, it
 *  creates a single instance of p5sound. All sound objects in this
 *  module output to p5sound before reaching your computer's output.
 *  So if you change the amplitude of p5sound, it impacts all of the
 *  sound in this module.</p>
 *
 *  <p>If no value is provided, returns a Web Audio API Gain Node</p>
 *
 *  @method  outputVolume
 *  @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
 */


p5.prototype.outputVolume = 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 = p5sound.audiocontext.currentTime;
    var currentVol = p5sound.output.gain.value;
    p5sound.output.gain.cancelScheduledValues(now + tFromNow);
    p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);
    p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);
  } else if (vol) {
    vol.connect(p5sound.output.gain);
  } else {
    return p5sound.output.gain;
  }
};
/**
 *  `p5.soundOut` is the p5.sound final output bus. It sends output to
 *  the destination of this window's web audio context. It contains
 *  Web Audio API nodes including a dyanmicsCompressor (<code>.limiter</code>),
 *  and Gain Nodes for <code>.input</code> and <code>.output</code>.
 *
 *  @property {Object} soundOut
 */


p5.prototype.soundOut = p5.soundOut = p5sound; 

p5.soundOut._silentNode = p5sound.audiocontext.createGain();
p5.soundOut._silentNode.gain.value = 0;

p5.soundOut._silentNode.connect(p5sound.audiocontext.destination);

 var main = (p5sound);
var processorNames = __webpack_require__(5);
var processorNames_default = __webpack_require__.n(processorNames);

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); }



/**
 * @for p5
 */

/**
 * Returns a number representing the sample rate, in samples per second,
 * of all sound objects in this audio context. It is determined by the
 * sampling rate of your operating system's sound card, and it is not
 * currently possile to change.
 * It is often 44100, or twice the range of human hearing.
 *
 * @method sampleRate
 * @return {Number} samplerate samples per second
 */

function sampleRate() {
  return main.audiocontext.sampleRate;
}
/**
 *  Returns the closest MIDI note value for
 *  a given frequency.
 *
 *  @method freqToMidi
 *  @param  {Number} frequency A freqeuncy, for example, the "A"
 *                             above Middle C is 440Hz
 *  @return {Number}   MIDI note value
 */


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
 *  is 60, C# is 61, D is 62 etc. Useful for generating
 *  musical frequencies with oscillators.
 *
 *  @method  midiToFreq
 *  @param  {Number} midiNote The number of a MIDI note
 *  @return {Number} Frequency value of the given MIDI note
 *  @example
 *  <div><code>
 *  let midiNotes = [60, 64, 67, 72];
 *  let noteIndex = 0;
 *  let midiVal, freq;
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(startSound);
 *    osc = new p5.TriOsc();
 *    env = new p5.Envelope();
 *  }
 *
 *  function draw() {
 *    background(220);
 *    text('tap to play', 10, 20);
 *    if (midiVal) {
 *      text('MIDI: ' + midiVal, 10, 40);
 *      text('Freq: ' + freq, 10, 60);
 *    }
 *  }
 *
 *  function startSound() {
 *    // see also: userStartAudio();
 *    osc.start();
 *
 *    midiVal = midiNotes[noteIndex % midiNotes.length];
 *    freq = midiToFreq(midiVal);
 *    osc.freq(freq);
 *    env.ramp(osc, 0, 1.0, 0);
 *
 *    noteIndex++;
 *  }
 *  </code></div>
 */


function midiToFreq(m) {
  return 440 * Math.pow(2, (m - 69) / 12.0);
} 


function noteToFreq(note) {
  if (typeof note !== 'string') {
    return note;
  }

  var wholeNotes = {
    A: 21,
    B: 23,
    C: 24,
    D: 26,
    E: 28,
    F: 29,
    G: 31
  };
  var value = wholeNotes[note[0].toUpperCase()];
  var octave = ~~note.slice(-1);
  value += 12 * (octave - 1);

  switch (note[1]) {
    case '#':
      value += 1;
      break;

    case 'b':
      value -= 1;
      break;

    default:
      break;
  }

  return midiToFreq(value);
}
/**
 *  List the SoundFile formats that you will include. LoadSound
 *  will search your directory for these extensions, and will pick
 *  a format that is compatable with the client's web browser.
 *  <a href="http://media.io/">Here</a> is a free online file
 *  converter.
 *
 *  @method soundFormats
 *  @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'
 *  @example
 *  <div><code>
 *  function preload() {
 *    // set the global sound formats
 *    soundFormats('mp3', 'ogg');
 *
 *    // load either beatbox.mp3, or .ogg, depending on browser
 *    mySound = loadSound('assets/beatbox.mp3');
 *  }
 *
 *  function setup() {
 *       let cnv = createCanvas(100, 100);
 *       background(220);
 *       text('sound loaded! tap to play', 10, 20, width - 20);
 *       cnv.mousePressed(function() {
 *         mySound.play();
 *       });
 *     }
 *  </code></div>
 */


function soundFormats() {
  main.extensions = []; 

  for (var i = 0; i < arguments.length; i++) {
    arguments[i] = arguments[i].toLowerCase();

    if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(arguments[i]) > -1) {
      main.extensions.push(arguments[i]);
    } else {
      throw arguments[i] + ' is not a valid sound format!';
    }
  }
}

function disposeSound() {
  for (var i = 0; i < main.soundArray.length; i++) {
    main.soundArray[i].dispose();
  }
}

function _checkFileFormats(paths) {
  var path; 

  if (typeof paths === 'string') {
    path = paths; 

    var extTest = path.split('.').pop(); 

    if (['mp3', 'wav', 'ogg', 'm4a', 'aac'].indexOf(extTest) > -1) {
      if (!p5.prototype.isFileSupported(extTest)) {
        var pathSplit = path.split('.');
        var pathCore = pathSplit[pathSplit.length - 1];

        for (var _i = 0; _i < main.extensions.length; _i++) {
          var _extension = main.extensions[_i];

          var _supported = p5.prototype.isFileSupported(_extension);

          if (_supported) {
            pathCore = '';

            if (pathSplit.length === 2) {
              pathCore += pathSplit[0];
            }

            for (var _i2 = 1; _i2 <= pathSplit.length - 2; _i2++) {
              var p = pathSplit[_i2];
              pathCore += '.' + p;
            }

            path = pathCore += '.';
            path = path += _extension;
            break;
          }
        }
      }
    } 
    else {
        for (var _i3 = 0; _i3 < main.extensions.length; _i3++) {
          var _extension2 = main.extensions[_i3];

          var _supported2 = p5.prototype.isFileSupported(_extension2);

          if (_supported2) {
            path = path + '.' + _extension2;
            break;
          }
        }
      }
  } 
  else if (_typeof(paths) === 'object') {
      for (var i = 0; i < paths.length; i++) {
        var extension = paths[i].split('.').pop();
        var supported = p5.prototype.isFileSupported(extension);

        if (supported) {
          path = paths[i];
          break;
        }
      }
    }

  return path;
}
/**
 *  Used by Osc and Envelope to chain signal math
 */


function _mathChain(o, math, thisChain, nextChain, type) {
  for (var i in o.mathOps) {
    if (o.mathOps[i] instanceof type) {
      o.mathOps[i].dispose();
      thisChain = i;

      if (thisChain < o.mathOps.length - 1) {
        nextChain = o.mathOps[i + 1];
      }
    }
  }

  o.mathOps[thisChain - 1].disconnect();
  o.mathOps[thisChain - 1].connect(math);
  math.connect(nextChain);
  o.mathOps[thisChain] = math;
  return o;
} 


function convertToWav(audioBuffer) {
  var leftChannel, rightChannel;
  leftChannel = audioBuffer.getChannelData(0); 

  if (audioBuffer.numberOfChannels > 1) {
    rightChannel = audioBuffer.getChannelData(1);
  } else {
    rightChannel = leftChannel;
  }

  var interleaved = interleave(leftChannel, rightChannel); 

  var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);
  var view = new window.DataView(buffer); 

  writeUTFBytes(view, 0, 'RIFF');
  view.setUint32(4, 36 + interleaved.length * 2, true);
  writeUTFBytes(view, 8, 'WAVE'); 

  writeUTFBytes(view, 12, 'fmt ');
  view.setUint32(16, 16, true);
  view.setUint16(20, 1, true); 

  view.setUint16(22, 2, true);
  view.setUint32(24, main.audiocontext.sampleRate, true);
  view.setUint32(28, main.audiocontext.sampleRate * 4, true);
  view.setUint16(32, 4, true);
  view.setUint16(34, 16, true); 

  writeUTFBytes(view, 36, 'data');
  view.setUint32(40, interleaved.length * 2, true); 

  var lng = interleaved.length;
  var index = 44;
  var volume = 1;

  for (var i = 0; i < lng; i++) {
    view.setInt16(index, interleaved[i] * (0x7fff * volume), true);
    index += 2;
  }

  return view;
} 


function interleave(leftChannel, rightChannel) {
  var length = leftChannel.length + rightChannel.length;
  var result = new Float32Array(length);
  var inputIndex = 0;

  for (var index = 0; index < length;) {
    result[index++] = leftChannel[inputIndex];
    result[index++] = rightChannel[inputIndex];
    inputIndex++;
  }

  return result;
}

function writeUTFBytes(view, offset, string) {
  var lng = string.length;

  for (var i = 0; i < lng; i++) {
    view.setUint8(offset + i, string.charCodeAt(i));
  }
}

function safeBufferSize(idealBufferSize) {
  var bufferSize = idealBufferSize; 

  var tempAudioWorkletNode = new AudioWorkletNode(main.audiocontext, processorNames_default.a.soundFileProcessor);

  if (tempAudioWorkletNode instanceof ScriptProcessorNode) {
    bufferSize = tempAudioWorkletNode.bufferSize;
  }

  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
 * <a href="/docs/reference/#/p5.SoundFile/saveBlob">`p5.SoundFile.saveBlob`</a>.
 *
 *  @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;
  err.name = name;
  err.originalStack = err.stack + errorTrace;
  tempStack = err.stack + errorTrace;
  err.failedPath = failedPath; 

  splitStack = tempStack.split('\n').filter(function (ln) {
    return !ln.match(/(p5.|native code|globalInit)/g);
  });
  err.stack = splitStack.join('\n');
  return err; 
};

 var errorHandler = (CustomError);

var moduleSources = [__webpack_require__(27)["default"], __webpack_require__(28)["default"], __webpack_require__(29)["default"]];
var audioWorklet_ac = main.audiocontext;
var initializedAudioWorklets = false;

function loadAudioWorkletModules() {
  return Promise.all(moduleSources.map(function (moduleSrc) {
    var blob = new Blob([moduleSrc], {
      type: 'application/javascript'
    });
    var objectURL = URL.createObjectURL(blob);
    return audioWorklet_ac.audioWorklet.addModule(objectURL);
  }));
}

p5.prototype.registerMethod('init', function () {
  if (initializedAudioWorklets) return; 

  if (!this.preload && !window.preload) {
    this.preload = 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"); } }

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); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }


var panner_ac = main.audiocontext;
var panner; 

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);
    }

    _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);
      } 

    }, {
      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 {
  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 = main.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 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; 

  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;
  }
}
/**
 *  <p>SoundFile object with a path to a file.</p>
 *
 *  <p>The p5.SoundFile may not be available immediately because
 *  it loads the file information asynchronously.</p>
 *
 *  <p>To do something with the sound as soon as it loads
 *  pass the name of a function as the second parameter.</p>
 *
 *  <p>Only one file path is required. However, audio file formats
 *  (i.e. mp3, ogg, wav and m4a/aac) are not supported by all
 *  web browsers. If you want to ensure compatability, instead of a single
 *  file path, you may include an Array of filepaths, and the browser will
 *  choose a format that works.</p>
 *
 *  @class p5.SoundFile
 *  @constructor
 *  @param {String|Array} path   path to a sound file (String). Optionally,
 *                               you may include multiple file formats in
 *                               an array. Alternately, accepts an object
 *                               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 file fails to
 *                                      load. This function will receive an error or
 *                                     XMLHttpRequest object with information
 *                                     about what went wrong.
 *  @param {Function} [whileLoadingCallback]   Name of a function to call while file
 *                                             is loading. That function will
 *                                             receive progress of the request to
 *                                             load the sound file
 *                                             (between 0 and 1) as its first
 *                                             parameter. This progress
 *                                             does not account for the additional
 *                                             time needed to decode the audio data.
 *
 *  @example
 *  <div><code>
 *  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();
 *  }
 * </code></div>
 */


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;
    } 


    this._onended = function () {};

    this._looping = false;
    this._playing = false;
    this._paused = false;
    this._pauseTime = 0; 

    this._cues = [];
    this._cueIDCounter = 0; 

    this._lastPos = 0;
    this._counterNode = null;
    this._workletNode = null; 

    this.bufferSourceNodes = []; 

    this.bufferSourceNode = null;
    this.buffer = null;
    this.playbackRate = 1;
    this.input = main.audiocontext.createGain();
    this.output = main.audiocontext.createGain();
    this.reversed = false; 

    this.startTime = 0;
    this.endTime = null;
    this.pauseTime = 0; 

    this.mode = 'sustain'; 

    this.startMillis = null; 

    this.panPosition = 0.0;
    this.panner = new panner_0(this.output, main.input, 2); 

    if (this.url || this.file) {
      this.load(onload, onerror);
    } 


    main.soundArray.push(this);

    if (typeof whileLoading === 'function') {
      this._whileLoading = whileLoading;
    } else {
      this._whileLoading = function () {};
    }

    this._clearOnEnd = _clearOnEnd.bind(this); 

    this.amp = this.setVolume; 

    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
   */


  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);
              }
            }
        }; 


        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.';

          if (errorCallback) {
            err.message = msg;
            errorCallback(err);
          } else {
            console.error(msg + '\n The error stack trace includes: \n' + err.stack);
          }
        };

        request.send();
      } else if (this.file !== undefined) {
        var reader = new FileReader();

        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 (callback) {
              callback(self);
            }
          });
        };

        reader.onerror = function (e) {
          if (!self.panner) return;

          if (onerror) {
            onerror(e);
          }
        };

        reader.readAsArrayBuffer(this.file);
      }
    } 

  }, {
    key: "_updateProgress",
    value: function _updateProgress(evt) {
      if (evt.lengthComputable) {
        var percentComplete = evt.loaded / evt.total * 0.99;

        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}
     */

  }, {
    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;
      }

      var now = main.audiocontext.currentTime;
      var cueStart, cueEnd;
      var time = startTime || 0;

      if (time < 0) {
        time = 0;
      }

      time = time + now;

      if (typeof rate !== 'undefined') {
        this.rate(rate);
      }

      if (typeof amp !== 'undefined') {
        this.setVolume(amp);
      } 


      if (this.buffer) {
        this._pauseTime = 0; 

        if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {
          this.bufferSourceNode.stop(time);

          this._counterNode.stop(time);
        } 


        if (this.mode === 'untildone' && this.isPlaying()) {
          return;
        } 


        this.bufferSourceNode = this._initSourceNode(); 

        delete this._counterNode;
        this._counterNode = this._initCounterNode();

        if (_cueStart) {
          if (_cueStart >= 0 && _cueStart < this.buffer.duration) {
            cueStart = _cueStart;
          } else {
            throw 'start time out of range';
          }
        } else {
          cueStart = 0;
        }

        if (duration) {
          duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration;
        } 


        if (this._paused) {
          this.bufferSourceNode.start(time, this.pauseTime, duration);

          this._counterNode.start(time, this.pauseTime, duration);
        } else {
          this.bufferSourceNode.start(time, cueStart, duration);

          this._counterNode.start(time, cueStart, duration);
        }

        this._playing = true;
        this._paused = false; 

        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.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: <code>restart</code> and
     *  <code>sustain</code>. 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
     *  <div><code>
     *  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();
     *  }
     *
     * </code></div>
     */

  }, {
    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 = main.audiocontext.currentTime;
          this.bufferSourceNodes[i].stop(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
     *  <div><code>
     *  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);
     *  }
     *  </code>
     *  </div>
     */

  }, {
    key: "pause",
    value: function pause(startTime) {
      var now = main.audiocontext.currentTime;
      var time = startTime || 0;
      var pTime = time + now;

      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
     *  <div><code>
     *  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);
     *  }
     *  </code>
     *  </div>
     */

  }, {
    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.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;
      }

      if (this._looping === true && this.isPlaying() === true) {
        return true;
      }

      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 = main.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 = main.audiocontext.currentTime;
      var time = _time || 0;

      if (this.buffer && this.bufferSourceNode) {
        for (var i in this.bufferSourceNodes) {
          var bufferSourceNode = this.bufferSourceNodes[i];

          if (bufferSourceNode) {
            try {
              bufferSourceNode.stop(now + time);
            } catch (e) {
            }
          }
        }

        this._counterNode.stop(now + time);
      }
    }
  }, {
    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
     * <div><code>
     *  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();
     *  }
     *  </div></code>
     */

  }, {
    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
     *  <div><code>
     *  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);
     *  }
     *
     * </code>
     * </div>
     *
     */

  }, {
    key: "rate",
    value: function rate(playbackRate) {
      var reverse = false;

      if (typeof playbackRate === 'undefined') {
        return this.playbackRate;
      }

      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;
      }

      if (this.bufferSourceNode) {
        var now = main.audiocontext.currentTime;
        this.bufferSourceNode.playbackRate.cancelScheduledValues(now);
        this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);

        this._counterNode.playbackRate.cancelScheduledValues(now);

        this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);
      }

      if (reverse) {
        this.reverseBuffer();
      }

      return this.playbackRate;
    } 

  }, {
    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 <code>rampTime</code> 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 = main.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 (duration > this.buffer.duration - cueTime) {
        throw 'end time out of range';
      }

      var cTime = cueTime || 0;
      var dur = duration || undefined;

      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;
              }
            }
          }

          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
     *  <div><code>
     *  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();
     *  }
     * </code>
     * </div>
     */

  }, {
    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();
        } 


        this.reversed = !this.reversed;

        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 = main.audiocontext.currentTime; 

      var index = main.soundArray.indexOf(this);
      main.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');
            }

            this.bufferSourceNodes[i] = null;
          }
        }

        if (this.isPlaying()) {
          try {
            this._counterNode.stop(now);
          } catch (e) {
            console.log(e);
          }

          this._counterNode = null;
        }
      }

      if (this.output) {
        this.output.disconnect();
        this.output = null;
      }

      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 main 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(main.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);

      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]);
      }

      this.buffer = newBuffer; 

      this.panner.inputChannels(numChannels);
    } 

  }, {
    key: "_initCounterNode",
    value: function _initCounterNode() {
      var _this = this;

      var self = this;
      var now = soundfile_ac.currentTime;
      var cNode = soundfile_ac.createBufferSource();
      var workletBufferSize = safeBufferSize(256); 

      if (self._workletNode) {
        self._workletNode.disconnect();

        delete self._workletNode;
      }

      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;
          }

          _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;
    }
  }, {
    key: "processPeaks",
    value: function processPeaks(callback, _initThreshold, _minThreshold, _minPeaks) {
      console.warn('processPeaks is deprecated');
    }
    /**
     *  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
     *  <div><code>
     *  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();
     *  }
     *  </code></div>
     */

  }, {
    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
     * <a href="/reference/#/p5.SoundFile/getBlob">getBlob</a>
     *
     * @method save
     * @for p5.SoundFile
     * @param  {String} [fileName]      name of the resulting .wav file.
     * @example
     *  <div><code>
     *  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');
     *  }
     * </code></div>
     */

  }, {
    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 "<a target="_blank" title="Blob reference at
     * MDN" href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>".
     * A Blob is a file-like data object that can be uploaded to a server
     * with an <a href="/reference/#/p5/httpDo">http</a> 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
     *  <div><code>
     *  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 `<Audio>` Element accepts Object URL's
     *    createAudio(blobUrl).showControls();
     *
     *    createDiv();
     *
     *    // The ObjectURL exists as long as this tab is open
     *    let input = createInput(blobUrl);
     *    input.attribute('readonly', true);
     *    input.mouseClicked(function() { input.elt.select() });
     *  }
     *
     * </code></div>
     */

  }, {
    key: "getBlob",
    value: function getBlob() {
      var dataView = convertToWav(this.buffer);
      return new Blob([dataView], {
        type: 'audio/wav'
      });
    }
  }]);

  return SoundFile;
}();
/**
 *  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
 *  <a href="https://github.com/processing/p5.js/wiki/Local-server">
 *  local server</a> 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
 *  <div><code>
 *  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();
 *  }
 *  </code></div>
 */


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');
  }

  var self = this;
  var s = new soundfile_SoundFile(path, function () {
    if (typeof callback === 'function') {
      callback.apply(self, arguments);
    }

    if (typeof self._decrementPreload === 'function') {
      self._decrementPreload();
    }
  }, onerror, whileLoading);
  return s;
}

 var soundfile = (soundfile_SoundFile);

function amplitude_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

function amplitude_createClass(Constructor, protoProps, staticProps) { if (protoProps) amplitude_defineProperties(Constructor.prototype, protoProps); if (staticProps) amplitude_defineProperties(Constructor, staticProps); return Constructor; }




/**
 *  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.
 *
 *  @class p5.Amplitude
 *  @constructor
 *  @param {Number} [smoothing] between 0.0 and .999 to smooth
 *                             amplitude readings (defaults to 0)
 *  @example
 *  <div><code>
 *  let sound, amplitude;
 *
 *  function preload(){
 *    sound = loadSound('assets/beat.mp3');
 *  }
 *  function setup() {
 *    let cnv = createCanvas(100,100);
 *    cnv.mouseClicked(togglePlay);
 *    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);
 *    }
 *  }
 *
 *  </code></div>
 */

var amplitude_Amplitude =
function () {
  function Amplitude(smoothing) {
    amplitude_classCallCheck(this, Amplitude);

    this.bufferSize = safeBufferSize(2048); 

    this.audiocontext = main.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(); 

    this.volume = 0;
    this.volNorm = 0;
    this.stereoVol = [0, 0];
    this.stereoVolNorm = [0, 0];
    this.normalize = false;

    this._workletNode.connect(this.output);

    this.output.gain.value = 0; 

    this.output.connect(this.audiocontext.destination); 

    main.meter.connect(this._workletNode); 

    main.soundArray.push(this);
  }
  /**
   *  Connects to the p5sound instance (main 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
   *                                       main output)
   *  @param {Number|undefined} [smoothing] a range between 0.0 and 1.0
   *                                        to smooth amplitude readings
   *  @example
   *  <div><code>
   *  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();
   *    }
   *  }
   *  </code></div>
   */


  amplitude_createClass(Amplitude, [{
    key: "setInput",
    value: function setInput(source, smoothing) {
      main.meter.disconnect();

      if (smoothing) {
        this._workletNode.parameters.get('smoothing').value = smoothing;
      } 


      if (source == null) {
        console.log('Amplitude input source is not ready! Connecting to main output instead');
        main.meter.connect(this._workletNode);
      } 
      else if (source) {
          source.connect(this._workletNode);

          this._workletNode.disconnect();

          this._workletNode.connect(this.output);
        } 
        else {
            main.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(main.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
     *  <div><code>
     *  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();
     *    }
     *  }
     *  </code></div>
     */

  }, {
    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;
      }

      this._workletNode.port.postMessage({
        name: 'toggleNormalize',
        normalize: this.normalize
      });
    }
    /**
     *  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 = main.soundArray.indexOf(this);
      main.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; }


/**
 *  <p>FFT (Fast Fourier Transform) is an analysis algorithm that
 *  isolates individual
 *  <a href="https://en.wikipedia.org/wiki/Audio_frequency">
 *  audio frequencies</a> within a waveform.</p>
 *
 *  <p>Once instantiated, a p5.FFT object can return an array based on
 *  two types of analyses: <br> • <code>FFT.waveform()</code> 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.<br>
 *  • <code>FFT.analyze() </code> 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 <code>getEnergy()</code> to measure amplitude at specific
 *  frequencies, or within a range of frequencies. </p>
 *
 *  <p>FFT analyzes a very short snapshot of sound called a sample
 *  buffer. It returns an array of amplitude measurements, referred
 *  to as <code>bins</code>. 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.</p>
 *
 *
 *  @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
 *  <div><code>
 *  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();
 *    }
 *  }
 *  </code></div>
 */

var fft_FFT =
function () {
  function FFT(smoothing, bins) {
    fft_classCallCheck(this, FFT);

    this.input = this.analyser = main.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; 

    main.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]; 

    main.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)
   */


  fft_createClass(FFT, [{
    key: "setInput",
    value: function setInput(source) {
      if (!source) {
        main.fftMeter.connect(this.analyser);
      } else {
        if (source.output) {
          source.output.connect(this.analyser);
        } else if (source.connect) {
          source.connect(this.analyser);
        }

        main.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;
        }

        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
     *  <code>getEnergy()</code>.
     *
     *  @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
     *  <div><code>
     *  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);
     *  }
     *  </code></div>
     *
     *
     */

  }, {
    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 (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
     *  <a href="https://en.wikipedia.org/wiki/Audio_frequency" target="_blank">
     *  frequency</a>, 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).
     *  <em>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.</em></p>
     *
     *  @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 = main.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()';
      }
    } 

  }, {
    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
     *  <a href="http://en.wikipedia.org/wiki/Spectral_centroid" target="_blank">
     *  spectral centroid</a> of the input signal.
     *  <em>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.</em></p>
     *
     *  @method  getCentroid
     *  @for p5.FFT
     *  @return {Number}   Spectral Centroid Frequency  of the spectral centroid in Hz.
     *
     *
     * @example
     *  <div><code>
     * 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);
     *}
     * </code></div>
     */

  }, {
    key: "getCentroid",
    value: function getCentroid() {
      var nyquist = main.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.
     */

  }, {
    key: "smooth",
    value: function smooth(s) {
      if (typeof s !== 'undefined') {
        this.smoothing = s;
      }

      return this.smoothing;
    }
  }, {
    key: "dispose",
    value: function dispose() {
      var index = main.soundArray.indexOf(this);
      main.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.
     *  <em>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.</em></p>
     *
     *  @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++;
        }
      }

      return linearAverages;
    }
    /**
     *  Returns an array of average amplitude values of the spectrum, for a given
     *  set of <a href="https://en.wikipedia.org/wiki/Octave_band" target="_blank">
     *  Octave Bands</a>
     *  <em>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.</em></p>
     *
     *  @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 = main.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
     *  <a href="https://en.wikipedia.org/wiki/Octave_band" target="_blank">Octave Bands</a>
     *  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 = main.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;
    }
  }]);

  return FFT;
}(); 


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 = (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);

var Scale = __webpack_require__(8);
var Scale_default = __webpack_require__.n(Scale);

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); }

function _possibleConstructorReturn(self, call) { if (call && (oscillator_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

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); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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); } }

function oscillator_createClass(Constructor, protoProps, staticProps) { if (protoProps) oscillator_defineProperties(Constructor.prototype, protoProps); if (staticProps) oscillator_defineProperties(Constructor, staticProps); return Constructor; }






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;
}
/**
 *  <p>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).</p>
 *
 *  <p>Set the type of oscillation with setType(), or by instantiating a
 *  specific oscillator: <a href="/reference/#/p5.SinOsc">p5.SinOsc</a>, <a
 *  href="/reference/#/p5.TriOsc">p5.TriOsc</a>, <a
 *  href="/reference/#/p5.SqrOsc">p5.SqrOsc</a>, or <a
 *  href="/reference/#/p5.SawOsc">p5.SawOsc</a>.
 *  </p>
 *
 *  @class p5.Oscillator
 *  @constructor
 *  @param {Number} [freq] frequency defaults to 440Hz
 *  @param {String} [type] type of oscillator. Options:
 *                         'sine' (default), 'triangle',
 *                         'sawtooth', 'square'
 *  @example
 *  <div><code>
 *  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;
 *  }
 *  </code> </div>
 */


var oscillator_Oscillator =
function () {
  function Oscillator(freq, type) {
    oscillator_classCallCheck(this, Oscillator);

    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 = main.audiocontext.createOscillator();
    this.f = freq || 440.0; 

    this.oscillator.type = type || 'sine';
    this.oscillator.frequency.setValueAtTime(this.f, main.audiocontext.currentTime); 

    this.output = main.audiocontext.createGain();
    this._freqMods = []; 

    this.output.gain.value = 0.5;
    this.output.gain.setValueAtTime(0.5, main.audiocontext.currentTime);
    this.oscillator.connect(this.output); 

    this.panPosition = 0.0;
    this.connection = main.input; 

    this.panner = new panner_0(this.output, this.connection, 1); 

    this.mathOps = [this.output]; 

    main.soundArray.push(this); 

    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.
   */


  oscillator_createClass(Oscillator, [{
    key: "start",
    value: function start(time, f) {
      if (this.started) {
        var now = main.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 = main.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 + main.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.
     */

  }, {
    key: "stop",
    value: function stop(time) {
      if (this.started) {
        var t = time || 0;
        var now = main.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 = main.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
     *  <div><code>
     *  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);
     *  }
     *  </code></div>
     */

  }, {
    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 = main.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
     */

  }, {
    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(main.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();

        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
     */

  }, {
    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 = main.soundArray.indexOf(this);
      main.soundArray.splice(index, 1);

      if (this.oscillator) {
        var now = main.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
     */

  }, {
    key: "phase",
    value: function phase(p) {
      var delayAmt = p5.prototype.map(p, 0, 1.0, 0, 1 / this.f);
      var now = main.audiocontext.currentTime;
      this.phaseAmount = p;

      if (!this.dNode) {
        this.dNode = main.audiocontext.createDelay(); 

        this.oscillator.disconnect();
        this.oscillator.connect(this.dNode);
        this.dNode.connect(this.output);
      } 


      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];
      }

      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;
}(); 

/**
 *  Constructor: <code>new p5.SinOsc()</code>.
 *  This creates a Sine Wave Oscillator and is
 *  equivalent to <code> new p5.Oscillator('sine')
 *  </code> or creating a p5.Oscillator and then calling
 *  its method <code>setType('sine')</code>.
 *  See p5.Oscillator for methods.
 *
 *  @class  p5.SinOsc
 *  @constructor
 *  @extends p5.Oscillator
 *  @param {Number} [freq] Set the frequency
 */


var SinOsc =
function (_Oscillator) {
  _inherits(SinOsc, _Oscillator);

  function SinOsc(freq) {
    oscillator_classCallCheck(this, SinOsc);

    return _possibleConstructorReturn(this, _getPrototypeOf(SinOsc).call(this, freq, 'sine'));
  }

  return SinOsc;
}(oscillator_Oscillator);
/**
 *  Constructor: <code>new p5.TriOsc()</code>.
 *  This creates a Triangle Wave Oscillator and is
 *  equivalent to <code>new p5.Oscillator('triangle')
 *  </code> or creating a p5.Oscillator and then calling
 *  its method <code>setType('triangle')</code>.
 *  See p5.Oscillator for methods.
 *
 *  @class  p5.TriOsc
 *  @constructor
 *  @extends p5.Oscillator
 *  @param {Number} [freq] Set the frequency
 */


var TriOsc =
function (_Oscillator2) {
  _inherits(TriOsc, _Oscillator2);

  function TriOsc(freq) {
    oscillator_classCallCheck(this, TriOsc);

    return _possibleConstructorReturn(this, _getPrototypeOf(TriOsc).call(this, freq, 'triangle'));
  }

  return TriOsc;
}(oscillator_Oscillator);
/**
 *  Constructor: <code>new p5.SawOsc()</code>.
 *  This creates a SawTooth Wave Oscillator and is
 *  equivalent to <code> new p5.Oscillator('sawtooth')
 *  </code> or creating a p5.Oscillator and then calling
 *  its method <code>setType('sawtooth')</code>.
 *  See p5.Oscillator for methods.
 *
 *  @class  p5.SawOsc
 *  @constructor
 *  @extends p5.Oscillator
 *  @param {Number} [freq] Set the frequency
 */


var SawOsc =
function (_Oscillator3) {
  _inherits(SawOsc, _Oscillator3);

  function SawOsc(freq) {
    oscillator_classCallCheck(this, SawOsc);

    return _possibleConstructorReturn(this, _getPrototypeOf(SawOsc).call(this, freq, 'sawtooth'));
  }

  return SawOsc;
}(oscillator_Oscillator);
/**
 *  Constructor: <code>new p5.SqrOsc()</code>.
 *  This creates a Square Wave Oscillator and is
 *  equivalent to <code> new p5.Oscillator('square')
 *  </code> or creating a p5.Oscillator and then calling
 *  its method <code>setType('square')</code>.
 *  See p5.Oscillator for methods.
 *
 *  @class  p5.SqrOsc
 *  @constructor
 *  @extends p5.Oscillator
 *  @param {Number} [freq] Set the frequency
 */


var SqrOsc =
function (_Oscillator4) {
  _inherits(SqrOsc, _Oscillator4);

  function SqrOsc(freq) {
    oscillator_classCallCheck(this, SqrOsc);

    return _possibleConstructorReturn(this, _getPrototypeOf(SqrOsc).call(this, freq, 'square'));
  }

  return SqrOsc;
}(oscillator_Oscillator);

 var oscillator = (oscillator_Oscillator);

var TimelineSignal = __webpack_require__(7);
var TimelineSignal_default = __webpack_require__.n(TimelineSignal);






/**
 *  <p>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 (
 *  <a href="https://upload.wikimedia.org/wikipedia/commons/e/ea/ADSR_parameter.svg">ADSR</a>
 *  ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can
 *  control an Oscillator's frequency like this: <code>osc.freq(env)</code>.</p>
 *  <p>Use <code><a href="#/p5.Envelope/setRange">setRange</a></code> to change the attack/release level.
 *  Use <code><a href="#/p5.Envelope/setADSR">setADSR</a></code> to change attackTime, decayTime, sustainPercent and releaseTime.</p>
 *  <p>Use the <code><a href="#/p5.Envelope/play">play</a></code> method to play the entire envelope,
 *  the <code><a href="#/p5.Envelope/ramp">ramp</a></code> method for a pingable trigger,
 *  or <code><a href="#/p5.Envelope/triggerAttack">triggerAttack</a></code>/
 *  <code><a href="#/p5.Envelope/triggerRelease">triggerRelease</a></code> to trigger noteOn/noteOff.</p>
 *
 *  @class p5.Envelope
 *  @constructor
 *  @example
 *  <div><code>
 *  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);
 *  }
 *  </code></div>
 */

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 = main.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; 

  main.soundArray.push(this);
}; 


p5.Envelope.prototype._init = function () {
  var now = main.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
 *  <div><code>
 *  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);
 *  }
 *  </code></div>
 *
 */


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
 *  <a href="https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg">
 *  ADSR envelope
 *  </a>.
 *
 *  @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 <code>setRange</code>),
 *                                then decayLevel would increase proportionally, to become 0.5.
 *  @param {Number} [releaseTime]   Time in seconds from now (defaults to 0)
 *  @example
 *  <div><code>
 *  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();
 *  }
 *  </code></div>
 */


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
 *  <div><code>
 *  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();
 *  }
 *  </code></div>
 */


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);
};
/**
 *  Assign a parameter to be controlled by this envelope.
 *  If a p5.Sound object is given, then the p5.Envelope will control its
 *  output gain. If multiple inputs are provided, the env will
 *  control all of them.
 *
 *  @method  setInput
 *  @for p5.Envelope
 *  @param  {Object} [...inputs]         A p5.sound object or
 *                                Web Audio Param.
 */


p5.Envelope.prototype.setInput = function () {
  for (var i = 0; i < arguments.length; i++) {
    this.connect(arguments[i]);
  }
};
/**
 *  Set whether the envelope ramp is linear (default) or exponential.
 *  Exponential ramps can be useful because we perceive amplitude
 *  and frequency logarithmically.
 *
 *  @method  setExp
 *  @for p5.Envelope
 *  @param {Boolean} isExp true is exponential, false is linear
 */


p5.Envelope.prototype.setExp = function (isExp) {
  this.isExponential = isExp;
}; 


p5.Envelope.prototype.checkExpInput = function (value) {
  if (value <= 0) {
    value = 0.00000001;
  }

  return value;
};
/**
 *  <p>Play tells the envelope to start acting on a given input.
 *  If the input is a p5.sound object (i.e. AudioIn, Oscillator,
 *  SoundFile), then Envelope will control its output volume.
 *  Envelopes can also be used to control any <a href="
 *  http://docs.webplatform.org/wiki/apis/webaudio/AudioParam">
 *  Web Audio Audio Param.</a></p>
 *
 *  @method  play
 *  @for p5.Envelope
 *  @param  {Object} unit         A p5.sound object or
 *                                Web Audio Param.
 *  @param  {Number} [startTime]  time from now (in seconds) at which to play
 *  @param  {Number} [sustainTime] time to sustain before releasing the envelope
 *  @example
 *  <div><code>
 *  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);
 *    triOsc.start();
 *  }
 *
 *  function draw() {
 *    background(220);
 *    text('tap here to play', 5, 20);
 *    attackTime = map(mouseX, 0, width, 0, 1.0);
 *    attackLevel = map(mouseY, height, 0, 0, 1.0);
 *    text('attack time: ' + attackTime, 5, height - 40);
 *    text('attack level: ' + attackLevel, 5, height - 20);
 *  }
 *
 *  function playEnv() {
 *    // ensure that audio is enabled
 *    userStartAudio();
 *
 *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
 *    env.setRange(attackLevel, releaseLevel);
 *    env.play();
 *  }
 *  </code></div>
 */


p5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) {
  var tFromNow = secondsFromNow || 0;

  if (unit) {
    if (this.connection !== unit) {
      this.connect(unit);
    }
  }

  this.triggerAttack(unit, tFromNow);
  this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + ~~susTime);
};
/**
 *  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. Input can be
 *  any p5.sound object, or a <a href="
 *  http://docs.webplatform.org/wiki/apis/webaudio/AudioParam">
 *  Web Audio Param</a>.
 *
 *  @method  triggerAttack
 *  @for p5.Envelope
 *  @param  {Object} unit p5.sound Object or Web Audio Param
 *  @param  {Number} secondsFromNow time from now (in seconds)
 *  @example
 *  <div><code>
 *  let attackTime = 0.001;
 *  let decayTime = 0.2;
 *  let susPercent = 0.3;
 *  let releaseTime = 0.4;
 *  let env, triOsc;
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    background(220);
 *    textAlign(CENTER);
 *    textSize(10);
 *    text('tap to triggerAttack', width/2, height/2);
 *
 *    env = new p5.Envelope();
 *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
 *    env.setRange(1.0, 0.0);
 *    triOsc = new p5.Oscillator('triangle');
 *    triOsc.freq(220);
 *
 *    cnv.mousePressed(envAttack);
 *  }
 *
 *  function envAttack()  {
 *    background(0, 255, 255);
 *    text('release to release', width/2, height/2);
 *
 *    // ensures audio is enabled. See also: `userStartAudio`
 *    triOsc.start();
 *
 *    env.triggerAttack(triOsc);
 *  }
 *
 *  function mouseReleased() {
 *    background(220);
 *    text('tap to triggerAttack', width/2, height/2);
 *
 *    env.triggerRelease(triOsc);
 *  }
 *  </code></div>
 */


p5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) {
  var now = main.audiocontext.currentTime;
  var tFromNow = secondsFromNow || 0;
  var t = now + tFromNow;
  this.lastAttack = t;
  this.wasTriggered = true;

  if (unit) {
    if (this.connection !== unit) {
      this.connect(unit);
    }
  } 


  var valToSet = this.control.getValueAtTime(t);

  if (this.isExponential === true) {
    this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);
  } else {
    this.control.linearRampToValueAtTime(valToSet, t);
  } 


  t += this.aTime;

  if (this.isExponential === true) {
    this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t);
    valToSet = this.checkExpInput(this.control.getValueAtTime(t));
    this.control.cancelScheduledValues(t);
    this.control.exponentialRampToValueAtTime(valToSet, t);
  } else {
    this.control.linearRampToValueAtTime(this.aLevel, t);
    valToSet = this.control.getValueAtTime(t);
    this.control.cancelScheduledValues(t);
    this.control.linearRampToValueAtTime(valToSet, t);
  } 


  t += this.dTime;

  if (this.isExponential === true) {
    this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t);
    valToSet = this.checkExpInput(this.control.getValueAtTime(t));
    this.control.cancelScheduledValues(t);
    this.control.exponentialRampToValueAtTime(valToSet, t);
  } else {
    this.control.linearRampToValueAtTime(this.dLevel, t);
    valToSet = this.control.getValueAtTime(t);
    this.control.cancelScheduledValues(t);
    this.control.linearRampToValueAtTime(valToSet, t);
  }
};
/**
 *  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.
 *
 *  @method  triggerRelease
 *  @for p5.Envelope
 *  @param  {Object} unit p5.sound Object or Web Audio Param
 *  @param  {Number} secondsFromNow time to trigger the release
 *  @example
 *  <div><code>
 *  let attackTime = 0.001;
 *  let decayTime = 0.2;
 *  let susPercent = 0.3;
 *  let releaseTime = 0.4;
 *  let env, triOsc;
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    background(220);
 *    textAlign(CENTER);
 *    textSize(10);
 *    text('tap to triggerAttack', width/2, height/2);
 *
 *    env = new p5.Envelope();
 *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
 *    env.setRange(1.0, 0.0);
 *    triOsc = new p5.Oscillator('triangle');
 *    triOsc.freq(220);
 *
 *    cnv.mousePressed(envAttack);
 *  }
 *
 *  function envAttack()  {
 *    background(0, 255, 255);
 *    text('release to release', width/2, height/2);
 *
 *    // ensures audio is enabled. See also: `userStartAudio`
 *    triOsc.start();
 *
 *    env.triggerAttack(triOsc);
 *  }
 *
 *  function mouseReleased() {
 *    background(220);
 *    text('tap to triggerAttack', width/2, height/2);
 *
 *    env.triggerRelease(triOsc);
 *  }
 *  </code></div>
 */


p5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) {
  if (!this.wasTriggered) {
    return;
  }

  var now = main.audiocontext.currentTime;
  var tFromNow = secondsFromNow || 0;
  var t = now + tFromNow;

  if (unit) {
    if (this.connection !== unit) {
      this.connect(unit);
    }
  } 


  var valToSet = this.control.getValueAtTime(t);

  if (this.isExponential === true) {
    this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);
  } else {
    this.control.linearRampToValueAtTime(valToSet, t);
  } 


  t += this.rTime;

  if (this.isExponential === true) {
    this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t);
    valToSet = this.checkExpInput(this.control.getValueAtTime(t));
    this.control.cancelScheduledValues(t);
    this.control.exponentialRampToValueAtTime(valToSet, t);
  } else {
    this.control.linearRampToValueAtTime(this.rLevel, t);
    valToSet = this.control.getValueAtTime(t);
    this.control.cancelScheduledValues(t);
    this.control.linearRampToValueAtTime(valToSet, t);
  }

  this.wasTriggered = false;
};
/**
 *  Exponentially ramp to a value using the first two
 *  values from <code><a href="#/p5.Envelope/setADSR">setADSR(attackTime, decayTime)</a></code>
 *  as <a href="https://en.wikipedia.org/wiki/RC_time_constant">
 *  time constants</a> for simple exponential ramps.
 *  If the value is higher than current value, it uses attackTime,
 *  while a decrease uses decayTime.
 *
 *  @method  ramp
 *  @for p5.Envelope
 *  @param  {Object} unit           p5.sound Object or Web Audio Param
 *  @param  {Number} secondsFromNow When to trigger the ramp
 *  @param  {Number} v              Target value
 *  @param  {Number} [v2]           Second target value
 *  @example
 *  <div><code>
 *  let env, osc, amp;
 *
 *  let attackTime = 0.001;
 *  let decayTime = 0.2;
 *  let attackLevel = 1;
 *  let decayLevel = 0;
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    fill(0,255,0);
 *    noStroke();
 *
 *    env = new p5.Envelope();
 *    env.setADSR(attackTime, decayTime);
 *    osc = new p5.Oscillator();
 *    osc.amp(env);
 *    amp = new p5.Amplitude();
 *
 *    cnv.mousePressed(triggerRamp);
 *  }
 *
 *  function triggerRamp() {
 *    // ensures audio is enabled. See also: `userStartAudio`
 *    osc.start();
 *
 *    env.ramp(osc, 0, attackLevel, decayLevel);
 *  }
 *
 *  function draw() {
 *    background(20);
 *    text('tap to play', 10, 20);
 *    let h = map(amp.getLevel(), 0, 0.4, 0, height);;
 *    rect(0, height, width, -h);
 *  }
 *  </code></div>
 */


p5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) {
  var now = main.audiocontext.currentTime;
  var tFromNow = secondsFromNow || 0;
  var t = now + tFromNow;
  var destination1 = this.checkExpInput(v1);
  var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined; 

  if (unit) {
    if (this.connection !== unit) {
      this.connect(unit);
    }
  } 


  var currentVal = this.checkExpInput(this.control.getValueAtTime(t)); 

  if (destination1 > currentVal) {
    this.control.setTargetAtTime(destination1, t, this._rampAttackTC);
    t += this._rampAttackTime;
  } 
  else if (destination1 < currentVal) {
      this.control.setTargetAtTime(destination1, t, this._rampDecayTC);
      t += this._rampDecayTime;
    } 


  if (destination2 === undefined) return; 

  if (destination2 > destination1) {
    this.control.setTargetAtTime(destination2, t, this._rampAttackTC);
  } 
  else if (destination2 < destination1) {
      this.control.setTargetAtTime(destination2, t, this._rampDecayTC);
    }
};

p5.Envelope.prototype.connect = function (unit) {
  this.connection = unit; 

  if (unit instanceof p5.Oscillator || unit instanceof p5.SoundFile || unit instanceof p5.AudioIn || unit instanceof p5.Reverb || unit instanceof p5.Noise || unit instanceof p5.Filter || unit instanceof p5.Delay) {
    unit = unit.output.gain;
  }

  if (unit instanceof AudioParam) {
    unit.setValueAtTime(0, main.audiocontext.currentTime);
  }

  this.output.connect(unit);
};

p5.Envelope.prototype.disconnect = function () {
  if (this.output) {
    this.output.disconnect();
  }
}; 

/**
 *  Add a value to the p5.Oscillator's output amplitude,
 *  and return the oscillator. Calling this method
 *  again will override the initial add() with new values.
 *
 *  @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 = main.soundArray.indexOf(this);
  main.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;
 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); }

function noise_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

function noise_createClass(Constructor, protoProps, staticProps) { if (protoProps) noise_defineProperties(Constructor.prototype, protoProps); if (staticProps) noise_defineProperties(Constructor, staticProps); return Constructor; }

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 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); }



var _whiteNoiseBuffer = function () {
  var bufferSize = 2 * main.audiocontext.sampleRate;
  var whiteBuffer = main.audiocontext.createBuffer(1, bufferSize, main.audiocontext.sampleRate);
  var noiseData = whiteBuffer.getChannelData(0);

  for (var i = 0; i < bufferSize; i++) {
    noiseData[i] = Math.random() * 2 - 1;
  }

  whiteBuffer.type = 'white';
  return whiteBuffer;
}();

var _pinkNoiseBuffer = function () {
  var bufferSize = 2 * main.audiocontext.sampleRate;
  var pinkBuffer = main.audiocontext.createBuffer(1, bufferSize, main.audiocontext.sampleRate);
  var noiseData = pinkBuffer.getChannelData(0);
  var b0, b1, b2, b3, b4, b5, b6;
  b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;

  for (var i = 0; i < bufferSize; i++) {
    var white = Math.random() * 2 - 1;
    b0 = 0.99886 * b0 + white * 0.0555179;
    b1 = 0.99332 * b1 + white * 0.0750759;
    b2 = 0.969 * b2 + white * 0.153852;
    b3 = 0.8665 * b3 + white * 0.3104856;
    b4 = 0.55 * b4 + white * 0.5329522;
    b5 = -0.7616 * b5 - white * 0.016898;
    noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
    noiseData[i] *= 0.11; 

    b6 = white * 0.115926;
  }

  pinkBuffer.type = 'pink';
  return pinkBuffer;
}();

var _brownNoiseBuffer = function () {
  var bufferSize = 2 * main.audiocontext.sampleRate;
  var brownBuffer = main.audiocontext.createBuffer(1, bufferSize, main.audiocontext.sampleRate);
  var noiseData = brownBuffer.getChannelData(0);
  var lastOut = 0.0;

  for (var i = 0; i < bufferSize; i++) {
    var white = Math.random() * 2 - 1;
    noiseData[i] = (lastOut + 0.02 * white) / 1.02;
    lastOut = noiseData[i];
    noiseData[i] *= 3.5;
  }

  brownBuffer.type = 'brown';
  return brownBuffer;
}();
/**
 *  Noise is a type of oscillator that generates a buffer with random values.
 *
 *  @class p5.Noise
 *  @extends p5.Oscillator
 *  @constructor
 *  @param {String} type Type of noise can be 'white' (default),
 *                       'brown' or 'pink'.
 */


var noise_Noise =
function (_Oscillator) {
  noise_inherits(Noise, _Oscillator);

  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 = main.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 = main.audiocontext.createBufferSource();
      this.noise.buffer = this.buffer;
      this.noise.loop = true;
      this.noise.connect(this.output);
      var now = main.audiocontext.currentTime;
      this.noise.start(now);
      this.started = true;
    }
  }, {
    key: "stop",
    value: function stop() {
      var now = main.audiocontext.currentTime;

      if (this.noise) {
        this.noise.stop(now);
        this.started = false;
      }
    }
  }, {
    key: "dispose",
    value: function dispose() {
      var now = main.audiocontext.currentTime; 

      var index = main.soundArray.indexOf(this);
      main.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); }





/**
 *  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 <a href="
 *  http://p5js.org/reference/#/p5.Oscillator">
 *  <code>p5.Oscillator</code> 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
 *  <div><code>
 *  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);
 *  }
 *  </code></div>
 */

var pulse_Pulse =
function (_Oscillator) {
  pulse_inherits(Pulse, _Oscillator);

  function Pulse(freq, w) {
    var _this;

    pulse_classCallCheck(this, Pulse);

    _this = pulse_possibleConstructorReturn(this, pulse_getPrototypeOf(Pulse).call(this, freq, 'sawtooth')); 

    _this.w = w || 0; 

    _this.osc2 = new SawOsc(freq); 

    _this.dNode = main.audiocontext.createDelay(); 

    _this.dcOffset = createDCOffset();
    _this.dcGain = main.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);

    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)
   */


  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 = main.audiocontext.currentTime;
      var t = time || 0;

      if (!this.started) {
        var freq = f || this.f;
        var type = this.oscillator.type;
        this.oscillator = main.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 = main.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 = main.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 = main.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 = main.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;
}

 var pulse = (pulse_Pulse);
function audioin_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }



main.inputSources = [];
/**
 *  <p>Get audio from an input, i.e. your computer's microphone.</p>
 *
 *  <p>Turn the mic on/off with the start() and stop() methods. When the mic
 *  is on, its volume can be measured with getLevel or by connecting an
 *  FFT object.</p>
 *
 *  <p>If you want to hear the AudioIn, use the .connect() method.
 *  AudioIn does not connect to p5.sound output by default to prevent
 *  feedback.</p>
 *
 *  <p><em>Note: This uses the <a href="http://caniuse.com/stream">getUserMedia/
 *  Stream</a> API, which is not supported by certain browsers. Access in Chrome browser
 *  is limited to localhost and https, but access over http may be limited.</em></p>
 *
 *  @class p5.AudioIn
 *  @constructor
 *  @param {Function} [errorCallback] A function to call if there is an error
 *                                    accessing the AudioIn. For example,
 *                                    Safari and iOS devices do not
 *                                    currently allow microphone access.
 *  @example
 *  <div><code>
 *  let mic;
 *
 *   function setup(){
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(userStartAudio);
 *    textAlign(CENTER);
 *    mic = new p5.AudioIn();
 *    mic.start();
 *  }
 *
 *  function draw(){
 *    background(0);
 *    fill(255);
 *    text('tap to start', width/2, 20);
 *
 *    micLevel = mic.getLevel();
 *    let y = height - micLevel * height;
 *    ellipse(width/2, y, 10, 10);
 *  }
 *  </code></div>
 */

var audioin_AudioIn =
function () {
  function AudioIn(errorCallback) {
    audioin_classCallCheck(this, AudioIn);


    /**
     * @property {GainNode} input
     */
    this.input = main.audiocontext.createGain();
    /**
     * @property {GainNode} output
     */

    this.output = main.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);

    if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) {
      errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices');
    } 


    main.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.<br/>
   *
   *  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.
   */


  audioin_createClass(AudioIn, [{
    key: "start",
    value: function start(successCallback, errorCallback) {
      var self = this;

      if (this.stream) {
        this.stop();
      } 


      var audioSource = main.inputSources[self.currentSource];
      var constraints = {
        audio: {
          sampleRate: main.audiocontext.sampleRate,
          echoCancellation: false
        }
      }; 

      if (main.inputSources[this.currentSource]) {
        constraints.audio.deviceId = audioSource.deviceId;
      }

      window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
        self.stream = stream;
        self.enabled = true; 

        self.mediaStream = main.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
     */

  }, {
    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;
      }
    }
    /**
     *  Connect to an audio unit. If no parameter is provided, will
     *  connect to the main output (i.e. your speakers).<br/>
     *
     *  @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(main.input);
      }
    }
    /**
     *  Disconnect the AudioIn from all audio units. For example, if
     *  connect() had been called, disconnect() will stop sending
     *  signal to your speakers.<br/>
     *
     *  @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). <em>NOTE: AudioIn must
     *  .start() before using .getLevel().</em><br/>
     *
     *  @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;
      }

      return this.amplitude.getLevel();
    }
    /**
     *  Set amplitude (volume) of a mic input between 0 and 1.0. <br/>
     *
     *  @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(main.audiocontext.currentTime);
        this.output.gain.setValueAtTime(currentVol, main.audiocontext.currentTime);
        this.output.gain.linearRampToValueAtTime(vol, rampTime + main.audiocontext.currentTime);
      } else {
        this.output.gain.cancelScheduledValues(main.audiocontext.currentTime);
        this.output.gain.setValueAtTime(vol, main.audiocontext.currentTime);
      }
    }
    /**
     * Returns a list of available input sources. This is a wrapper
     * for <a href="https://developer.mozilla.org/
     * en-US/docs/Web/API/MediaDevices/enumerateDevices" target="_blank">
     * MediaDevices.enumerateDevices() - Web APIs | MDN</a>
     * 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
     *  <div><code>
     *  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);
     *    }
     *  }
     *  </code></div>
     */

  }, {
    key: "getSources",
    value: function getSources(onSuccess, onError) {
      return new Promise(function (resolve, reject) {
        window.navigator.mediaDevices.enumerateDevices().then(function (devices) {
          main.inputSources = devices.filter(function (device) {
            return device.kind === 'audioinput';
          });
          resolve(main.inputSources);

          if (onSuccess) {
            onSuccess(main.inputSources);
          }
        })["catch"](function (error) {
          reject(error);

          if (onError) {
            onError(error);
          } else {
            console.error('This browser does not support MediaStreamTrack.getSources()');
          }
        });
      });
    }
    /**
     *  Set the input source. Accepts a number representing a
     *  position in the array returned by getSources().
     *  This is only available in browsers that support
     * <a href="https://developer.mozilla.org/
     * en-US/docs/Web/API/MediaDevices/enumerateDevices" target="_blank">
     * navigator.mediaDevices.enumerateDevices()</a>
     *
     *  @method setSource
     *  @for p5.AudioIn
     *  @param {number} num position of input source in the array
     *  @example
     *  <div><code>
     *  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);
     *    }
     *  }
     *  </code></div>
     */

  }, {
    key: "setSource",
    value: function setSource(num) {
      if (main.inputSources.length > 0 && num < main.inputSources.length) {
        this.currentSource = num;
        console.log('set source to ', main.inputSources[this.currentSource]);
      } else {
        console.log('unable to set input source');
      } 


      if (this.stream && this.stream.active) {
        this.start();
      }
    } 

  }, {
    key: "dispose",
    value: function dispose() {
      var index = main.soundArray.indexOf(this);
      main.soundArray.splice(index, 1);
      this.stop();

      if (this.output) {
        this.output.disconnect();
      }

      if (this.amplitude) {
        this.amplitude.disconnect();
      }

      delete this.amplitude;
      delete this.output;
    }
  }]);

  return AudioIn;
}();

 var audioin = (audioin_AudioIn);
var CrossFade = __webpack_require__(23);
var CrossFade_default = __webpack_require__.n(CrossFade);

function effect_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

function effect_createClass(Constructor, protoProps, staticProps) { if (protoProps) effect_defineProperties(Constructor.prototype, protoProps); if (staticProps) effect_defineProperties(Constructor, staticProps); return Constructor; }



/**
 * Effect is a base class for audio effects in p5. <br>
 * This module handles the nodes and methods that are
 * common and useful for current and future effects.
 *
 *
 * This class is extended by <a href="/reference/#/p5.Distortion">p5.Distortion</a>,
 * <a href="/reference/#/p5.Compressor">p5.Compressor</a>,
 * <a href="/reference/#/p5.Delay">p5.Delay</a>,
 * <a href="/reference/#/p5.Filter">p5.Filter</a>,
 * <a href="/reference/#/p5.Reverb">p5.Reverb</a>.
 *
 * @class  p5.Effect
 * @constructor
 *
 * @param {Object} [ac]   Reference to the audio context of the p5 object
 * @param {AudioNode} [input]  Gain Node effect wrapper
 * @param {AudioNode} [output] Gain Node effect wrapper
 * @param {Object} [_drywet]   Tone.JS CrossFade node (defaults to value: 1)
 * @param {AudioNode} [wet]  Effects that extend this class should connect
 *                              to the wet signal to this gain node, so that dry and wet
 *                              signals are mixed properly.
 */

var effect_Effect =
function () {
  function Effect() {
    effect_classCallCheck(this, Effect);

    this.ac = main.audiocontext;
    this.input = this.ac.createGain();
    this.output = this.ac.createGain();
    /**
     *	The p5.Effect class is built
     * 	using Tone.js CrossFade
     * 	@private
     */

    this._drywet = new CrossFade_default.a(1);
    /**
     *	In classes that extend
     *	p5.Effect, connect effect nodes
     *	to the wet parameter
     */

    this.wet = this.ac.createGain();
    this.input.connect(this._drywet.a);
    this.wet.connect(this._drywet.b);

    this._drywet.connect(this.output);

    this.connect(); 

    main.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
   */


  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 = main.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]);
        }
      }

      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(fade) {
      if (typeof fade !== 'undefined') {
        this._drywet.fade.value = fade;
      }

      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 = main.soundArray.indexOf(this);
      main.soundArray.splice(index, 1);

      if (this.input) {
        this.input.disconnect();
        delete this.input;
      }

      if (this.output) {
        this.output.disconnect();
        delete this.output;
      }

      if (this._drywet) {
        this._drywet.disconnect();

        delete this._drywet;
      }

      if (this.wet) {
        this.wet.disconnect();
        delete this.wet;
      }

      this.ac = undefined;
    }
  }]);

  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); }

function filter_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

function filter_createClass(Constructor, protoProps, staticProps) { if (protoProps) filter_defineProperties(Constructor.prototype, protoProps); if (staticProps) filter_defineProperties(Constructor, staticProps); return Constructor; }

function filter_possibleConstructorReturn(self, call) { if (call && (filter_typeof(call) === "object" || typeof call === "function")) { return call; } return filter_assertThisInitialized(self); }

function filter_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

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); }

function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = filter_getPrototypeOf(object); if (object === null) break; } return object; }

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); }


/**
 *  <p>A p5.Filter uses a Web Audio Biquad Filter to filter
 *  the frequency response of an input source. Subclasses
 *  include:</p>
 *  <a href="/reference/#/p5.LowPass"><code>p5.LowPass</code></a>:
 *  Allows frequencies below the cutoff frequency to pass through,
 *  and attenuates frequencies above the cutoff.<br/>
 *  <a href="/reference/#/p5.HighPass"><code>p5.HighPass</code></a>:
 *  The opposite of a lowpass filter. <br/>
 *  <a href="/reference/#/p5.BandPass"><code>p5.BandPass</code></a>:
 *  Allows a range of frequencies to pass through and attenuates
 *  the frequencies below and above this frequency range.<br/>
 *
 *  The <code>.res()</code> method controls either width of the
 *  bandpass, or resonance of the low/highpass cutoff frequency.
 *
 *  This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.
 *  Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
 *  <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
 *  <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
 *
 *  @class p5.Filter
 *  @extends p5.Effect
 *  @constructor
 *  @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'
 *  @example
 *  <div><code>
 *  let fft, noise, filter;
 *
 *  function setup() {
 *    let cnv = createCanvas(100,100);
 *    cnv.mousePressed(makeNoise);
 *    fill(255, 0, 255);
 *
 *    filter = new p5.BandPass();
 *    noise = new p5.Noise();
 *    noise.disconnect();
 *    noise.connect(filter);
 *
 *    fft = new p5.FFT();
 *  }
 *
 *  function draw() {
 *    background(220);
 *
 *    // set the BandPass frequency based on mouseX
 *    let freq = map(mouseX, 0, width, 20, 10000);
 *    freq = constrain(freq, 0, 22050);
 *    filter.freq(freq);
 *    // give the filter a narrow band (lower res = wider bandpass)
 *    filter.res(50);
 *
 *    // draw filtered spectrum
 *    let spectrum = fft.analyze();
 *    noStroke();
 *    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);
 *    }
 *    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);
 *  }
 *
 *  </code></div>
 */

var Filter =
function (_Effect) {
  filter_inherits(Filter, _Effect);

  function Filter(type) {
    var _this;

    filter_classCallCheck(this, Filter);

    _this = filter_possibleConstructorReturn(this, filter_getPrototypeOf(Filter).call(this)); 

    /**
     *  The p5.Filter is built with a
     *  <a href="http://www.w3.org/TR/webaudio/#BiquadFilterNode">
     *  Web Audio BiquadFilter Node</a>.
     *
     *  @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;
    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
   */


  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);
      }

      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 (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.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);
      }

      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';
      }

      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;
      }
    }
  }]);

  return Filter;
}(effect);
/**
 *  Constructor: <code>new p5.LowPass()</code> Filter.
 *  This is the same as creating a p5.Filter and then calling
 *  its method <code>setType('lowpass')</code>.
 *  See p5.Filter for methods.
 *
 *  @class p5.LowPass
 *  @constructor
 *  @extends p5.Filter
 */


var LowPass =
function (_Filter) {
  filter_inherits(LowPass, _Filter);

  function LowPass() {
    filter_classCallCheck(this, LowPass);

    return filter_possibleConstructorReturn(this, filter_getPrototypeOf(LowPass).call(this, 'lowpass'));
  }

  return LowPass;
}(Filter);
/**
 *  Constructor: <code>new p5.HighPass()</code> Filter.
 *  This is the same as creating a p5.Filter and then calling
 *  its method <code>setType('highpass')</code>.
 *  See p5.Filter for methods.
 *
 *  @class p5.HighPass
 *  @constructor
 *  @extends p5.Filter
 */


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: <code>new p5.BandPass()</code> Filter.
 *  This is the same as creating a p5.Filter and then calling
 *  its method <code>setType('bandpass')</code>.
 *  See p5.Filter for methods.
 *
 *  @class p5.BandPass
 *  @constructor
 *  @extends p5.Filter
 */


var BandPass =
function (_Filter3) {
  filter_inherits(BandPass, _Filter3);

  function BandPass() {
    filter_classCallCheck(this, BandPass);

    return filter_possibleConstructorReturn(this, filter_getPrototypeOf(BandPass).call(this, 'bandpass'));
  }

  return BandPass;
}(Filter);

 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); }

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); } }

function eqFilter_createClass(Constructor, protoProps, staticProps) { if (protoProps) eqFilter_defineProperties(Constructor.prototype, protoProps); if (staticProps) eqFilter_defineProperties(Constructor, staticProps); return Constructor; }

function eqFilter_possibleConstructorReturn(self, call) { if (call && (eqFilter_typeof(call) === "object" || typeof call === "function")) { return call; } return eqFilter_assertThisInitialized(self); }

function eqFilter_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function eqFilter_getPrototypeOf(o) { eqFilter_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return eqFilter_getPrototypeOf(o); }

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); }

function eqFilter_setPrototypeOf(o, p) { eqFilter_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return eqFilter_setPrototypeOf(o, p); }



/**
 *  EQFilter extends p5.Filter with constraints
 *  necessary for the p5.EQ
 *
 *  @private
 */

var eqFilter_EQFilter =
function (_Filter) {
  eqFilter_inherits(EQFilter, _Filter);

  function EQFilter(freq, res) {
    var _this;

    eqFilter_classCallCheck(this, EQFilter);

    _this = eqFilter_possibleConstructorReturn(this, eqFilter_getPrototypeOf(EQFilter).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;
    return _this;
  }

  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 (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 = main.soundArray.indexOf(this);
      main.soundArray.splice(index, 1);
      this.disconnect();
      delete this.biquad;
    }
  }]);

  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); }

function eq_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

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); }

function eq_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

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); }

function eq_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = eq_getPrototypeOf(object); if (object === null) break; } return object; }

function eq_getPrototypeOf(o) { eq_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return eq_getPrototypeOf(o); }

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); }

function eq_setPrototypeOf(o, p) { eq_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return eq_setPrototypeOf(o, p); }



/**
 * 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 <a href = "/reference/#/p5.Effect">p5.Effect</a>.
 * Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
 * <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
 * <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> 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
 * <div><code>
 * 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);
 * }
 * </code></div>
 */

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 <a
     *  href="/reference/#/p5.Filter" title="p5.Filter reference">
     *  p5.Filter</a> 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);

      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);

    return _this;
  }
  /**
   * Process an input by connecting it to the EQ
   * @method  process
   * @param  {Object} src Audio source
   */


  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();
        }

        delete this.bands;
      }
    }
  }]);

  return EQ;
}(effect);

 var eq = (eq_EQ);
function listener3d_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }

//   * 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
//   * https://www.w3.org/TR/webaudio/#the-listenernode-interface
//   * This panner is a spatial processing node that allows audio to be positioned
//   * and oriented in 3D space.
//   *
//   * The Listener modifies the properties of the Audio Context Listener.
//   * Both objects types use the same methods. The default is a spatial panner.
//   *
//   * <code>p5.Panner3D</code> - Constructs a Spatial Panner<br/>
//   * <code>p5.Listener3D</code> - Constructs a Spatial Listener<br/>
//   *
//   * @class listener
//   * @constructor
//   * @return {Object} p5.Listener3D Object
//   *
//   * @param {Web Audio Node} listener Web Audio Spatial Panning Node
//   * @param {AudioParam} listener.panningModel "equal power" or "HRTF"
//   * @param {AudioParam} listener.distanceModel "linear", "inverse", or "exponential"
//   * @param {String} [type] [Specify construction of a spatial panner or listener]
//   */

var listener3d_Listener3D =
function () {
  function Listener3D(type) {
    listener3d_classCallCheck(this, Listener3D);

    this.ac = main.audiocontext;
    this.listener = this.ac.listener;
  } 
  //   * Connect an audio sorce
  //   * @param  {Object} src Input source
  //   */


  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);
      }

      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);
      }

      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);
      }

      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.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);
      }

      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);
      }

      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.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);
      }

      return this.listener.upZ.value;
    }
  }]);

  return Listener3D;
}();

 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"); } }

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); } }

function panner3d_createClass(Constructor, protoProps, staticProps) { if (protoProps) panner3d_defineProperties(Constructor.prototype, protoProps); if (staticProps) panner3d_defineProperties(Constructor, staticProps); return Constructor; }

function panner3d_possibleConstructorReturn(self, call) { if (call && (panner3d_typeof(call) === "object" || typeof call === "function")) { return call; } return panner3d_assertThisInitialized(self); }

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); }

function panner3d_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = panner3d_getPrototypeOf(object); if (object === null) break; } return object; }

function panner3d_getPrototypeOf(o) { panner3d_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return panner3d_getPrototypeOf(o); }

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); }

function panner3d_setPrototypeOf(o, p) { panner3d_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return panner3d_setPrototypeOf(o, p); }


/**
 * Panner3D is based on the <a title="Web Audio Panner docs"  href=
 * "https://developer.mozilla.org/en-US/docs/Web/API/PannerNode">
 * Web Audio Spatial Panner Node</a>.
 * This panner is a spatial processing node that allows audio to be positioned
 * and oriented in 3D space.
 *
 * The position is relative to an <a title="Web Audio Listener docs" href=
 * "https://developer.mozilla.org/en-US/docs/Web/API/AudioListener">
 * Audio Context Listener</a>, which can be accessed
 * by <code>p5.soundOut.audiocontext.listener</code>
 *
 *
 * @class p5.Panner3D
 * @constructor
 */

var Panner3D =
function (_Effect) {
  panner3d_inherits(Panner3D, _Effect);

  function Panner3D() {
    var _this;

    panner3d_classCallCheck(this, Panner3D);

    _this = panner3d_possibleConstructorReturn(this, panner3d_getPrototypeOf(Panner3D).call(this));
    /**
     *  <a title="Web Audio Panner docs"  href=
     *  "https://developer.mozilla.org/en-US/docs/Web/API/PannerNode">
     *  Web Audio Spatial Panner Node</a>
     *
     *  Properties include<br>
     * [Panning Model](https://www.w3.org/TR/webaudio/#idl-def-PanningModelType)
     * : "equal power" or "HRTF"<br>
     * [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);

    return _this;
  }
  /**
   * Connect an audio sorce
   *
   * @method  process
   * @for p5.Panner3D
   * @param  {Object} src Input source
   */


  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);
      }

      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.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); }



/**
 *  Delay is an echo effect. It processes an existing sound source,
 *  and outputs a delayed version of that sound. The p5.Delay can
 *  produce different effects depending on the delayTime, feedback,
 *  filter, and type. In the example below, a feedback of 0.5 (the
 *  default value) will produce a looping delay that decreases in
 *  volume by 50% each repeat. A filter will cut out the high
 *  frequencies so that the delay does not sound as piercing as the
 *  original source.
 *
 *
 *  This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.
 *  Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
 *  <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
 *  <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
 *  @class p5.Delay
 *  @extends p5.Effect
 *  @constructor
 *  @example
 *  <div><code>
 *  let osc;
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    background(220);
 *    textAlign(CENTER);
 *    text('tap to play', width/2, height/2);
 *
 *    osc = new p5.Oscillator('square');
 *    osc.amp(0.5);
 *    delay = new p5.Delay();
 *
 *    // delay.process() accepts 4 parameters:
 *    // source, delayTime (in seconds), feedback, filter frequency
 *    delay.process(osc, 0.12, .7, 2300);
 *
 *    cnv.mousePressed(oscStart);
 *  }
 *
 *  function oscStart() {
 *    osc.start();
 *  }
 *
 *  function mouseReleased() {
 *    osc.stop();
 *  }
 *  </code></div>
 */

var delay_Delay =
function (_Effect) {
  delay_inherits(Delay, _Effect);

  function Delay() {
    var _this;

    delay_classCallCheck(this, Delay);

    _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
     *  <a href="http://www.w3.org/TR/webaudio/#DelayNode">
     *  Web Audio Delay Nodes</a>, one for each stereo channel.
     *
     *  @for p5.Delay
     *  @property {DelayNode} leftDelay
     */

    _this.leftDelay = _this.ac.createDelay();
    /**
     *  The p5.Delay is built with two
     *  <a href="http://www.w3.org/TR/webaudio/#DelayNode">
     *  Web Audio Delay Nodes</a>, one for each stereo channel.
     *  @for p5.Delay
     *  @property {DelayNode} rightDelay
     */

    _this.rightDelay = _this.ac.createDelay();
    _this._leftFilter = new filter();
    _this._rightFilter = new filter();

    _this._leftFilter.disconnect();

    _this._rightFilter.disconnect();

    _this._leftFilter.biquad.frequency.setValueAtTime(1200, _this.ac.currentTime);

    _this._rightFilter.biquad.frequency.setValueAtTime(1200, _this.ac.currentTime);

    _this._leftFilter.biquad.Q.setValueAtTime(0.3, _this.ac.currentTime);

    _this._rightFilter.biquad.Q.setValueAtTime(0.3, _this.ac.currentTime); 


    _this.input.connect(_this._split);

    _this.leftDelay.connect(_this._leftGain);

    _this.rightDelay.connect(_this._rightGain);

    _this._leftGain.connect(_this._leftFilter.input);

    _this._rightGain.connect(_this._rightFilter.input);

    _this._merge.connect(_this.wet);

    _this._leftFilter.biquad.gain.setValueAtTime(1, _this.ac.currentTime);

    _this._rightFilter.biquad.gain.setValueAtTime(1, _this.ac.currentTime); 


    _this.setType(0);

    _this._maxDelay = _this.leftDelay.delayTime.maxValue; 

    _this.feedback(0.5);

    return _this;
  }
  /**
   *  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.
   */


  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.');
      }

      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;

      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;
      } 


      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();

      this._leftFilter.disconnect();

      this._rightFilter.disconnect();

      this._split.connect(this.leftDelay, 0);

      this._split.connect(this.rightDelay, 1);

      switch (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);

      }
    } 

    /**
     *  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);

 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); }

function reverb_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }

function reverb_possibleConstructorReturn(self, call) { if (call && (reverb_typeof(call) === "object" || typeof call === "function")) { return call; } return reverb_assertThisInitialized(self); }

function reverb_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

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); }

function reverb_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = reverb_getPrototypeOf(object); if (object === null) break; } return object; }

function reverb_getPrototypeOf(o) { reverb_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return reverb_getPrototypeOf(o); }

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); }

function reverb_setPrototypeOf(o, p) { reverb_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return reverb_setPrototypeOf(o, p); }




/**
 *  Reverb adds depth to a sound through a large number of decaying
 *  echoes. It creates the perception that sound is occurring in a
 *  physical space. The p5.Reverb has paramters for Time (how long does the
 *  reverb last) and decayRate (how much the sound decays with each echo)
 *  that can be set with the .set() or .process() methods. The p5.Convolver
 *  extends p5.Reverb allowing you to recreate the sound of actual physical
 *  spaces through convolution.
 *
 *  This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.
 *  Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
 *  <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
 *  <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
 *
 *  @class p5.Reverb
 *  @extends p5.Effect
 *  @constructor
 *  @example
 *  <div><code>
 *  let soundFile, reverb;
 *  function preload() {
 *    soundFile = loadSound('assets/Damscray_DancingTiger.mp3');
 *  }
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(playSound);
 *
 *    reverb = new p5.Reverb();
 *    soundFile.disconnect(); // so we'll only hear reverb...
 *
 *    // connect soundFile to reverb, process w/
 *    // 3 second reverbTime, decayRate of 2%
 *    reverb.process(soundFile, 3, 2);
 *  }
 *
 *  function draw() {
 *    let dryWet = constrain(map(mouseX, 0, width, 0, 1), 0, 1);
 *    // 1 = all reverb, 0 = no reverb
 *    reverb.drywet(dryWet);
 *
 *    background(220);
 *    text('tap to play', 10, 20);
 *    text('dry/wet: ' + round(dryWet * 100) + '%', 10, height - 20);
 *  }
 *
 *  function playSound() {
 *    soundFile.play();
 *  }
 *  </code></div>
 */

var Reverb =
function (_Effect) {
  reverb_inherits(Reverb, _Effect);

  function Reverb() {
    var _this;

    reverb_classCallCheck(this, Reverb);

    _this = reverb_possibleConstructorReturn(this, reverb_getPrototypeOf(Reverb).call(this));

    _this._initConvolverNode(); 


    _this.input.gain.value = 0.5; 

    _this._seconds = 3;
    _this._decay = 2;
    _this._reverse = false;

    _this._buildImpulse();

    return _this;
  }

  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();

      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.
     */

  }, {
    key: "process",
    value: function process(src, seconds, decayRate, reverse) {
      src.connect(this.input);
      var rebuild = false;

      if (seconds) {
        this._seconds = seconds;
        rebuild = true;
      }

      if (decayRate) {
        this._decay = decayRate;
      }

      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.
     */

  }, {
    key: "set",
    value: function set(seconds, decayRate, reverse) {
      var rebuild = false;

      if (seconds) {
        this._seconds = seconds;
        rebuild = true;
      }

      if (decayRate) {
        this._decay = decayRate;
      }

      if (reverse) {
        this._reverse = reverse;
      }

      if (rebuild) {
        this._buildImpulse();
      }
    } 

    /**
     *  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);
    }
  }, {
    key: "dispose",
    value: function dispose() {
      reverb_get(reverb_getPrototypeOf(Reverb.prototype), "dispose", this).call(this);

      this._teardownConvolverNode();
    }
  }]);

  return Reverb;
}(effect); 

/**
 *  <p>p5.Convolver extends p5.Reverb. It can emulate the sound of real
 *  physical spaces through a process called <a href="
 *  https://en.wikipedia.org/wiki/Convolution_reverb#Real_space_simulation">
 *  convolution</a>.</p>
 *
 *  <p>Convolution multiplies any audio input by an "impulse response"
 *  to simulate the dispersion of sound over time. The impulse response is
 *  generated from an audio file that you provide. One way to
 *  generate an impulse response is to pop a balloon in a reverberant space
 *  and record the echo. Convolution can also be used to experiment with
 *  sound.</p>
 *
 *  <p>Use the method <code>createConvolution(path)</code> to instantiate a
 *  p5.Convolver with a path to your impulse response audio file.</p>
 *
 *  @class p5.Convolver
 *  @extends p5.Effect
 *  @constructor
 *  @param  {String}   path     path to a sound file
 *  @param  {Function} [callback] function to call when loading succeeds
 *  @param  {Function} [errorCallback] function to call if loading fails.
 *                                     This function will receive an error or
 *                                     XMLHttpRequest object with information
 *                                     about what went wrong.
 *  @example
 *  <div><code>
 *  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 main output...
 *    sound.disconnect();
 *
 *    // ...and process with cVerb
 *    // so that we only hear the convolution
 *    cVerb.process(sound);
 *  }
 *
 *  function playSound() {
 *    sound.play();
 *  }
 *  </code></div>
 */


var reverb_Convolver =
function (_Reverb) {
  reverb_inherits(Convolver, _Reverb);

  function Convolver(path, callback, errorCallback) {
    var _this2;

    reverb_classCallCheck(this, Convolver);

    _this2 = reverb_possibleConstructorReturn(this, reverb_getPrototypeOf(Convolver).call(this));
    /**
     *  Internally, the p5.Convolver uses the a
     *  <a href="http://www.w3.org/TR/webaudio/#ConvolverNode">
     *  Web Audio Convolver Node</a>.
     *
     *  @property {ConvolverNode} convolverNode
     */

    _this2._initConvolverNode(); 


    _this2.input.gain.value = 0.5;

    if (path) {
      _this2.impulses = [];

      _this2._loadBuffer(path, callback, errorCallback);
    } else {
      _this2._seconds = 3;
      _this2._decay = 2;
      _this2._reverse = false;

      _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 <code>toggleImpulse(id)</code> method.
     *
     *  @property {Array} impulses
     *  @for p5.Convolver
     */


    _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
   */


  reverb_createClass(Convolver, [{
    key: "_loadBuffer",
    value: function _loadBuffer(_path, callback, errorCallback) {
      var path = p5.prototype._checkFileFormats(_path);

      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 = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';

        if (errorCallback) {
          err.message = msg;
          errorCallback(err);
        } 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
     *  <div><code>
     *  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 main output...
     *    sound.disconnect();
     *
     *    // ...and process with cVerb
     *    // so that we only hear the convolution
     *    cVerb.process(sound);
     *  }
     *
     *  function playSound() {
     *    sound.play();
     *  }
     *
     *  </code></div>
     */

  }, {
    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 <code>.impulses</code> array. Previous
     *  impulses can be accessed with the <code>.toggleImpulse(id)</code>
     *  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 <code>.impulses</code>
     *  Array is reset to save memory. A new <code>.impulses</code>
     *  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');
      }

      this.impulses = [];

      this._loadBuffer(path, callback, errorCallback);
    }
    /**
     *  If you have used <code>.addImpulse()</code> to add multiple impulses
     *  to a p5.Convolver, then you can use this method to toggle between
     *  the items in the <code>.impulses</code> 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 <code>.impulses
     *  </code> Array (Number).<br/>
     *  You can access the objects in the .impulses Array directly. Each
     *  Object has two attributes: an <code>.audioBuffer</code> (type:
     *  Web Audio <a href="
     *  http://webaudio.github.io/web-audio-api/#the-audiobuffer-interface">
     *  AudioBuffer)</a> and a <code>.name</code>, 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
     *                            <code>.impulses</code> Array (Number).
     */

  }, {
    key: "toggleImpulse",
    value: function toggleImpulse(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);

            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;
        }
      }
    }
  }]);

  return Convolver;
}(Reverb);
/**
 *  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
 *  <div><code>
 *  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 main output...
 *    sound.disconnect();
 *
 *    // ...and process with cVerb
 *    // so that we only hear the convolution
 *    cVerb.process(sound);
 *  }
 *
 *  function playSound() {
 *    sound.play();
 *  }
 *  </code></div>
 */


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');
  }

  var self = this;
  var cReverb = new reverb_Convolver(path, function (buffer) {
    if (typeof callback === 'function') {
      callback(buffer);
    }

    if (typeof self._decrementPreload === 'function') {
      self._decrementPreload();
    }
  }, errorCallback);
  cReverb.impulses = [];
  return cReverb;
}


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; }




var metro_Metro =
function () {
  function Metro() {
    metro_classCallCheck(this, Metro);

    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 () {};
  }

  metro_createClass(Metro, [{
    key: "ontick",
    value: function ontick(tickTime) {
      var elapsedTime = tickTime - this.prevTick;
      var secondsFromNow = tickTime - main.audiocontext.currentTime;

      if (elapsedTime - this.tatumTime <= -0.02) {
        return;
      } else {
        this.prevTick = tickTime; 

        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;

            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 = main.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];
    } 

  }, {
    key: "pushSync",
    value: function pushSync(part) {
      this.syncedParts.push(part);
    }
  }, {
    key: "start",
    value: function start(timeFromNow) {
      var t = timeFromNow || 0;
      var now = main.audiocontext.currentTime;
      this.clock.start(now + t);
      this.setBPM(this.bpm);
    }
  }, {
    key: "stop",
    value: function stop(timeFromNow) {
      var t = timeFromNow || 0;
      var now = main.audiocontext.currentTime;
      this.clock.stop(now + t);
    }
  }, {
    key: "beatLength",
    value: function beatLength(tatums) {
      this.tatums = 1 / tatums / 4; 
    }
  }]);

  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"); } }



var BPM = 120;
/**
 *  Set the global tempo, in beats per minute, for all
 *  p5.Parts. This method will impact all active p5.Parts.
 *
 *  @method setBPM
 *  @for p5
 *  @param {Number} BPM      Beats Per Minute
 *  @param {Number} rampTime Seconds from now
 */

p5.prototype.setBPM = function (bpm, rampTime) {
  BPM = bpm;

  for (var i in main.parts) {
    if (main.parts[i]) {
      main.parts[i].setBPM(bpm, rampTime);
    }
  }
};
/**
 *  <p>A phrase is a pattern of musical events over time, i.e.
 *  a series of notes and rests.</p>
 *
 *  <p>Phrases must be added to a p5.Part for playback, and
 *  each part can play multiple phrases at the same time.
 *  For example, one Phrase might be a kick drum, another
 *  could be a snare, and another could be the bassline.</p>
 *
 *  <p>The first parameter is a name so that the phrase can be
 *  modified or deleted later. The callback is a a function that
 *  this phrase will call at every step—for example it might be
 *  called <code>playNote(value){}</code>. The array determines
 *  which value is passed into the callback at each step of the
 *  phrase. It can be numbers, an object with multiple numbers,
 *  or a zero (0) indicates a rest so the callback won't be called).</p>
 *
 *  @class p5.Phrase
 *  @constructor
 *  @param {String}   name     Name so that you can access the Phrase.
 *  @param {Function} callback The name of a function that this phrase
 *                             will call. Typically it will play a sound,
 *                             and accept two parameters: a time at which
 *                             to play the sound (in seconds from now),
 *                             and a value from the sequence array. The
 *                             time should be passed into the play() or
 *                             start() method to ensure precision.
 *  @param {Array}   sequence    Array of values to pass into the callback
 *                            at each step of the phrase.
 *  @example
 *  <div><code>
 *  let mySound, myPhrase, myPart;
 *  let pattern = [1,0,0,2,0,2,0,0];
 *
 *  function preload() {
 *    mySound = loadSound('assets/beatbox.mp3');
 *  }
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(playMyPart);
 *    background(220);
 *    text('tap to play', width/2, height/2);
 *    textAlign(CENTER, CENTER);
 *
 *    myPhrase = new p5.Phrase('bbox', onEachStep, pattern);
 *    myPart = new p5.Part();
 *    myPart.addPhrase(myPhrase);
 *    myPart.setBPM(60);
 *  }
 *
 *  function onEachStep(time, playbackRate) {
 *    mySound.rate(playbackRate);
 *    mySound.play(time);
 *  }
 *
 *  function playMyPart() {
 *    userStartAudio();
 *    myPart.start();
 *  }
 *  </code></div>
 */


var Phrase = function Phrase(name, callback, sequence) {
  looper_classCallCheck(this, Phrase);

  this.phraseStep = 0;
  this.name = name;
  this.callback = callback;
  /**
   * Array of values to pass into the callback
   * at each step of the phrase. Depending on the callback
   * function's requirements, these values may be numbers,
   * strings, or an object with multiple parameters.
   * Zero (0) indicates a rest.
   *
   * @property {Array} sequence
   */

  this.sequence = sequence;
};
/**
 *  <p>A p5.Part plays back one or more p5.Phrases. Instantiate a part
 *  with steps and tatums. By default, each step represents a 1/16th note.</p>
 *
 *  <p>See p5.Phrase for more about musical timing.</p>
 *
 *  @class p5.Part
 *  @constructor
 *  @param {Number} [steps]   Steps in the part
 *  @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)
 *  @example
 *  <div><code>
 *  let box, drum, myPart;
 *  let boxPat = [1,0,0,2,0,2,0,0];
 *  let drumPat = [0,1,1,0,2,0,1,0];
 *
 *  function preload() {
 *    box = loadSound('assets/beatbox.mp3');
 *    drum = loadSound('assets/drum.mp3');
 *  }
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(playMyPart);
 *    background(220);
 *    textAlign(CENTER, CENTER);
 *    text('tap to play', width/2, height/2);
 *
 *    let boxPhrase = new p5.Phrase('box', playBox, boxPat);
 *    let drumPhrase = new p5.Phrase('drum', playDrum, drumPat);
 *    myPart = new p5.Part();
 *    myPart.addPhrase(boxPhrase);
 *    myPart.addPhrase(drumPhrase);
 *    myPart.setBPM(60);
 *  }
 *
 *  function playBox(time, playbackRate) {
 *    box.rate(playbackRate);
 *    box.play(time);
 *  }
 *
 *  function playDrum(time, playbackRate) {
 *    drum.rate(playbackRate);
 *    drum.play(time);
 *  }
 *
 *  function playMyPart() {
 *    userStartAudio();
 *
 *    myPart.start();
 *  }
 *  </code></div>
 */


var looper_Part =
function () {
  function Part(steps, bLength) {
    looper_classCallCheck(this, Part);

    this.length = steps || 0; 

    this.partStep = 0;
    this.phrases = [];
    this.isPlaying = false;
    this.noLoop();
    this.tatums = bLength || 0.0625; 

    this.metro = new metro();

    this.metro._init();

    this.metro.beatLength(this.tatums);
    this.metro.setBPM(BPM);
    main.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
   */


  looper_createClass(Part, [{
    key: "setBPM",
    value: function setBPM(tempo, rampTime) {
      this.metro.setBPM(tempo, rampTime);
    }
    /**
     *  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;
      };

      var t = time || 0;
      this.start(t);
    }
    /**
     *  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); 

      if (p.sequence.length > this.length) {
        this.length = p.sequence.length;
      }
    }
    /**
     *  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);
        }
      }
    }
    /**
     *  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;
    }
  }]);

  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
 *  <code>new p5.Score(a, a, b, a, c)</code>
 *
 *  @class p5.Score
 *  @constructor
 *  @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.
 */


var Score =
function () {
  function Score() {
    looper_classCallCheck(this, Score);

    this.parts = [];
    this.currentPart = new Array(arguments.length);
    ;
    var thisScore = this;

    for (var i in arguments) {
      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;
  }

  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();
        };
      }

      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++;

  if (aScore.currentPart >= aScore.parts.length) {
    aScore.scoreStep = 0;
    aScore.onended();
  } else {
    aScore.scoreStep = 0;
    aScore.parts[aScore.currentPart - 1].stop();
    aScore.parts[aScore.currentPart].start();
  }
}


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
 *
 * @class p5.SoundLoop
 * @constructor
 *
 * @param {Function} callback this function will be called on each iteration of theloop
 * @param {Number|String} [interval] amount of time (if a number) or beats (if a string, following <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> convention) for each iteration of the loop. Defaults to 1 second.
 *
 * @example
 * <div><code>
 *  let synth, soundLoop;
 *  let notePattern = [60, 62, 64, 67, 69, 72];
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(canvasPressed);
 *    colorMode(HSB);
 *    background(0, 0, 86);
 *    text('tap to start/stop', 10, 20);
 *
 *    //the looper's callback is passed the timeFromNow
 *    //this value should be used as a reference point from
 *    //which to schedule sounds
 *    let intervalInSeconds = 0.2;
 *    soundLoop = new p5.SoundLoop(onSoundLoop, intervalInSeconds);
 *
 *    synth = new p5.MonoSynth();
 * }
 *
 * function canvasPressed() {
 *   // ensure audio is enabled
 *   userStartAudio();
 *
 *   if (soundLoop.isPlaying) {
 *     soundLoop.stop();
 *   } else {
 *     // start the loop
 *     soundLoop.start();
 *   }
 * }
 *
 * function onSoundLoop(timeFromNow) {
 *   let noteIndex = (soundLoop.iterations - 1) % notePattern.length;
 *   let note = midiToFreq(notePattern[noteIndex]);
 *   synth.play(note, 0.5, timeFromNow);
 *   background(noteIndex * 360 / notePattern.length, 50, 100);
 * }
 * </code></div>
 */

var soundLoop_SoundLoop =
function () {
  function SoundLoop(callback, interval) {
    soundLoop_classCallCheck(this, SoundLoop);

    /**
     * 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 <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> 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.maxIterations = Infinity;
    var self = this;
    this.clock = new Clock_default.a({
      callback: function callback(time) {
        var timeFromNow = time - main.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 = main.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 = main.audiocontext.currentTime;

      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 = main.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 = main.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 - main.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 <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> 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;
    }
  }]);

  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); }

function compressor_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }

function compressor_possibleConstructorReturn(self, call) { if (call && (compressor_typeof(call) === "object" || typeof call === "function")) { return call; } return compressor_assertThisInitialized(self); }

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); }

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); }


/**
 * 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 main output.
 *
 * This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.
 * Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
 * <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
 * <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
 *
 * @class p5.Compressor
 * @constructor
 * @extends p5.Effect
 *
 *
 */

var Compressor =
function (_Effect) {
  compressor_inherits(Compressor, _Effect);

  function Compressor() {
    var _this;

    compressor_classCallCheck(this, Compressor);

    _this = compressor_possibleConstructorReturn(this, compressor_getPrototypeOf(Compressor).call(this));
    /**
     *
     * The p5.Compressor is built with a <a href="https://www.w3.org/TR/webaudio/#the-dynamicscompressornode-interface"
     *   target="_blank" title="W3 spec for Dynamics Compressor Node">Web Audio Dynamics Compressor Node
     *   </a>
     * @property {AudioNode} compressor
     */

    _this.compressor = _this.ac.createDynamicsCompressor();

    _this.input.connect(_this.compressor);

    _this.compressor.connect(_this.wet);

    return _this;
  }
  /**
   * 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
   */


  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);
      }

      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
     *
     *
     * @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);
      }

      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);
      }

      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);
      }

      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);
      }

      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);
      }

      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;
      }
    }
  }]);

  return Compressor;
}(effect);

 var compressor = (Compressor);
function peakDetect_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }

/**
 *  <p>PeakDetect works in conjunction with p5.FFT to
 *  look for onsets in some or all of the frequency spectrum.
 *  </p>
 *  <p>
 *  To use p5.PeakDetect, call <code>update</code> in the draw loop
 *  and pass in a p5.FFT object.
 *  </p>
 *  <p>
 *  You can listen for a specific part of the frequency spectrum by
 *  setting the range between <code>freq1</code> and <code>freq2</code>.
 *  </p>
 *
 *  <p><code>threshold</code> 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.</p>
 *
 *  <p>
 *  The update method is meant to be run in the draw loop, and
 *  <b>frames</b> 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:
 *  <code> framesPerPeak = 60 / (estimatedBPM / 60 );</code>
 *  </p>
 *
 *  <p>
 *  Based on example contribtued by @b2renger, and a simple beat detection
 *  explanation by <a
 *  href="http://www.airtightinteractive.com/2013/10/making-audio-reactive-visuals/"
 *  target="_blank">Felix Turner</a>.
 *  </p>
 *
 *  @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
 *  <div><code>
 *
 *  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();
 *      }
 *    }
 *  }
 *  </code></div>
 */
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
     */

    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
   */


  peakDetect_createClass(PeakDetect, [{
    key: "update",
    value: function update(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
     *  <div><code>
     *  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();
     *      }
     *    });
     *  }
     *  </code></div>
     */

  }, {
    key: "onPeak",
    value: function onPeak(callback, val) {
      var self = this;

      self._onPeak = function () {
        callback(self.energy, val);
      };
    }
  }]);

  return PeakDetect;
}();

 var peakDetect = (PeakDetect);
function soundRecorder_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

function soundRecorder_createClass(Constructor, protoProps, staticProps) { if (protoProps) soundRecorder_defineProperties(Constructor.prototype, protoProps); if (staticProps) soundRecorder_defineProperties(Constructor, staticProps); return Constructor; }




var soundRecorder_ac = main.audiocontext;
/**
 *  <p>Record sounds for playback and/or to save as a .wav file.
 *  The p5.SoundRecorder records all sound output from your sketch,
 *  or can be assigned a specific source with setInput().</p>
 *  <p>The record() method accepts a p5.SoundFile as a parameter.
 *  When playback is stopped (either after the given amount of time,
 *  or with the stop() method), the p5.SoundRecorder will send its
 *  recording to that p5.SoundFile for playback.</p>
 *
 *  @class p5.SoundRecorder
 *  @constructor
 *  @example
 *  <div><code>
 *  let mic, recorder, soundFile;
 *  let state = 0;
 *
 *  function setup() {
 *    let cnv = createCanvas(100, 100);
 *    cnv.mousePressed(canvasPressed);
 *    background(220);
 *    textAlign(CENTER, CENTER);
 *
 *    // create an audio in
 *    mic = new p5.AudioIn();
 *
 *    // prompts user to enable their browser mic
 *    mic.start();
 *
 *    // create a sound recorder
 *    recorder = new p5.SoundRecorder();
 *
 *    // connect the mic to the recorder
 *    recorder.setInput(mic);
 *
 *    // this sound file will be used to
 *    // playback & save the recording
 *    soundFile = new p5.SoundFile();
 *
 *    text('tap to record', width/2, height/2);
 *  }
 *
 *  function canvasPressed() {
 *    // ensure audio is enabled
 *    userStartAudio();
 *
 *    // make sure user enabled the mic
 *    if (state === 0 && mic.enabled) {
 *
 *      // record to our p5.SoundFile
 *      recorder.record(soundFile);
 *
 *      background(255,0,0);
 *      text('Recording!', width/2, height/2);
 *      state++;
 *    }
 *    else if (state === 1) {
 *      background(0,255,0);
 *
 *      // stop recorder and
 *      // send result to soundFile
 *      recorder.stop();
 *
 *      text('Done! Tap to play and download', width/2, height/2, width - 20);
 *      state++;
 *    }
 *
 *    else if (state === 2) {
 *      soundFile.play(); // play the result!
 *      save(soundFile, 'mySound.wav');
 *      state++;
 *    }
 *  }
 *  </div></code>
 */

var soundRecorder_SoundRecorder =
function () {
  function SoundRecorder() {
    soundRecorder_classCallCheck(this, SoundRecorder);

    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(); 

    main.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
   */


  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
      });

      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 = main.soundArray.indexOf(this);
      main.soundArray.splice(index, 1);

      this._callback = function () {};

      if (this.input) {
        this.input.disconnect();
      }

      this.input = null;
      this._workletNode = null;
    }
  }]);

  return SoundRecorder;
}();

 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;

  for (; i < numSamples; ++i) {
    x = i * 2 / numSamples - 1;
    curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
  }

  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 <a href = "/reference/#/p5.Effect">p5.Effect</a>.
 * Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
 * <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
 * <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> 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'.
 *
 */


var Distortion =
function (_Effect) {
  distortion_inherits(Distortion, _Effect);

  function Distortion(amount, oversample) {
    var _this;

    distortion_classCallCheck(this, Distortion);

    _this = distortion_possibleConstructorReturn(this, distortion_getPrototypeOf(Distortion).call(this));

    if (typeof amount === 'undefined') {
      amount = 0.25;
    }

    if (typeof amount !== 'number') {
      throw new Error('amount must be a number');
    }

    if (typeof oversample === 'undefined') {
      oversample = '2x';
    }

    if (typeof oversample !== 'string') {
      throw new Error('oversample must be a String');
    }

    var curveAmount = p5.prototype.map(amount, 0.0, 1.0, 0, 2000);
    /**
     *  The p5.Distortion is built with a
     *  <a href="http://www.w3.org/TR/webaudio/#WaveShaperNode">
     *  Web Audio WaveShaper Node</a>.
     *
     *  @property {AudioNode} WaveShaperNode
     */

    _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);

    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'.
   */


  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);
      }

      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;
      }
    }
  }]);

  return Distortion;
}(effect);

 var distortion = (Distortion);
function gain_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }


/**
 *  A gain node is usefull to set the relative volume of sound.
 *  It's typically used to build mixers.
 *
 *  @class p5.Gain
 *  @constructor
 *  @example
 *  <div><code>
 *
 *  // load two soundfile and crossfade beetween them
 *  let sound1,sound2;
 *  let sound1Gain, sound2Gain, mixGain;
 *  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 'mix' gain bus to which we will connect both soundfiles
 *    mixGain = new p5.Gain();
 *    mixGain.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(mixGain); // connect its output to the final mix bus
 *    sound2.disconnect();
 *    sound2Gain = new p5.Gain();
 *    sound2Gain.setInput(sound2);
 *    sound2Gain.connect(mixGain);
 *  }
 *  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 'output    *  volume control'
 *    var outputVolume = constrain(map(mouseY,height,0,0,1), 0, 1);
 *    mixGain.amp(outputVolume);
 *    text('output', width/2, height - outputVolume * 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);
 *  }
 *</code></div>
 */

var gain_Gain =
function () {
  function Gain() {
    gain_classCallCheck(this, Gain);

    this.ac = main.audiocontext;
    this.input = this.ac.createGain();
    this.output = this.ac.createGain(); 

    this.input.gain.value = 0.5;
    this.input.connect(this.output); 

    main.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.
   */


  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 = main.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 = main.soundArray.indexOf(this);
      main.soundArray.splice(index, 1);

      if (this.output) {
        this.output.disconnect();
        delete this.output;
      }

      if (this.input) {
        this.input.disconnect();
        delete this.input;
      }
    }
  }]);

  return Gain;
}();

 var gain = (gain_Gain);
function audioVoice_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }


/**
 * 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();
 *
 * @class p5.AudioVoice
 * @constructor
 */

var audioVoice_AudioVoice =
function () {
  function AudioVoice() {
    audioVoice_classCallCheck(this, AudioVoice);

    this.ac = main.audiocontext;
    this.output = this.ac.createGain();
    this.connect();
    main.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 || main.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;
      }
    }
  }]);

  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); }

function monosynth_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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); } }

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; }

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); }

function monosynth_superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = monosynth_getPrototypeOf(object); if (object === null) break; } return object; }

function monosynth_getPrototypeOf(o) { monosynth_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return monosynth_getPrototypeOf(o); }

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); }

function monosynth_setPrototypeOf(o, p) { monosynth_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return monosynth_setPrototypeOf(o, p); }






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
 *  <div><code>
 *  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);
 *  }
 *  </code></div>
 **/

var monosynth_MonoSynth =
function (_AudioVoice) {
  monosynth_inherits(MonoSynth, _AudioVoice);

  function MonoSynth() {
    var _this;

    monosynth_classCallCheck(this, MonoSynth);

    _this = monosynth_possibleConstructorReturn(this, monosynth_getPrototypeOf(MonoSynth).call(this));
    _this.oscillator = new oscillator();
    _this.env = new envelope(); 

    _this.env.setRange(1, 0);

    _this.env.setExp(true); 


    _this.setADSR(0.02, 0.25, 0.05, 0.35); 


    _this.oscillator.disconnect();

    _this.oscillator.connect(_this.output);

    _this.env.disconnect();

    _this.env.setInput(_this.output.gain); 


    _this.oscillator.output.gain.value = 1.0;

    _this.oscillator.start();

    _this.connect();

    main.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 <a href = "https://github.com/Tonejs/Tone.js/wiki/Instruments">
   *                                 Tone</a>. 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
   *  <div><code>
   *  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);
   *  }
   *  </code></div>
   *
   */


  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 <a href = "https://github.com/Tonejs/Tone.js/wiki/Instruments">
     *                                 Tone</a>. 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
     *  <div><code>
     *  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();
     *  }
     *  </code></div>
     */

  }, {
    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
     *  <div><code>
     *  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();
     *  }
     *  </code></div>
     */

  }, {
    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
     *  <a href="https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg">
     *  ADSR envelope
     *  </a>.
     *
     *  @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 <code>setRange</code>),
     *                                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 || main.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; }

/**
 *  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; }




/**
 *  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
 *  <div><code>
 *  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);
 *  }
 *  </code></div>
 **/

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 = main.audiocontext.createGain();
    this.connect(); 

    this._allocateVoices();

    main.soundArray.push(this);
  }
  /**
   * Construct the appropriate number of audiovoices
   * @private
   * @for p5.PolySynth
   * @method  _allocateVoices
   */


  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
     *  <div><code>
     *  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);
     *  }
     *  </code></div>
     */

  }, {
    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 <code>setRange</code>),
     *                                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 = main.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 <code>setRange</code>),
     *                                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
     *  <div><code>
     *  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();
     *  }
     *  </code></div>
     */

  }, {
    key: "noteAttack",
    value: function noteAttack(_note, _velocity) {
      var secondsFromNow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
      var acTime = main.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);
      } 


      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);
        } 


      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;

      this._voicesInUse.setValueAtTime(previousVal + 1, acTime); 


      this._updateAfter(acTime, 1);

      this._newest = currentVoice; 

      if (typeof velocity === 'number') {
        var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2;
        velocity = velocity > maxRange ? maxRange : velocity;
      } 


      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;

        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.
     *
     *  @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
     *  <div><code>
     *  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();
     *  }
     *  </code></div>
     *
     */

  }, {
    key: "noteRelease",
    value: function noteRelease(_note, secondsFromNow) {
      var now = main.audiocontext.currentTime;
      var tFromNow = secondsFromNow || 0;
      var t = now + tFromNow; 

      if (!_note) {
        this.audiovoices.forEach(function (voice) {
          voice.triggerRelease(tFromNow);
        });

        this._voicesInUse.setValueAtTime(0, t);

        for (var n in this.notes) {
          this.notes[n].dispose();
          delete this.notes[n];
        }

        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 (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
     */

  }, {
    key: "connect",
    value: function connect(unit) {
      var u = unit || main.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;
      }
    }
  }]);

  return PolySynth;
}();

 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);

  console.warn('p5.Signal is deprecated , Use Tone.js Signal instead ');
};

 var deprecations_Signal = (Signal_Signal);



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.PeakDetect = peakDetect; 


p5.Signal = deprecations_Signal;

 })
 ]);
