summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore39
-rw-r--r--applause.mp3bin0 -> 5277058 bytes
-rw-r--r--bundle.js23025
-rw-r--r--bundle.js.map1
-rw-r--r--client/index.js115
-rw-r--r--client/lib/color.js31
-rw-r--r--client/lib/kalimba.js55
-rw-r--r--client/lib/keys.js39
-rw-r--r--client/lib/startAudioContext.js181
-rw-r--r--client/lib/util.js63
-rw-r--r--index.html24
-rw-r--r--package-lock.json2579
-rw-r--r--package.json21
-rw-r--r--webpack.config.js24
14 files changed, 26197 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..337b56c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,39 @@
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# Commenting this out is preferred by some people, see
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
+node_modules
+
+# Users Environment Variables
+.lock-wscript
+
+./lib/
+./data/
+
+*~
+*.swp
+
+.DS_Store
+
+*.wav
+
diff --git a/applause.mp3 b/applause.mp3
new file mode 100644
index 0000000..92861b9
--- /dev/null
+++ b/applause.mp3
Binary files differ
diff --git a/bundle.js b/bundle.js
new file mode 100644
index 0000000..ccd988c
--- /dev/null
+++ b/bundle.js
@@ -0,0 +1,23025 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __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;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 4);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_RESULT__;(function(root, factory){
+
+ //UMD
+ if ( true ) {
+ !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+ return factory();
+ }.call(exports, __webpack_require__, exports, module),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof module === "object") {
+ module.exports = factory();
+ } else {
+ root.Tone = factory();
+ }
+
+}(this, function(){
+
+ "use strict";
+
+ var Tone;
+ //constructs the main Tone object
+ function Main(func){
+ Tone = func();
+ }
+ //invokes each of the modules with the main Tone object as the argument
+ function Module(func){
+ func(Tone);
+ } /**
+ * Tone.js
+ * @author Yotam Mann
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @copyright 2014-2017 Yotam Mann
+ */
+ Main(function () {
+
+ ///////////////////////////////////////////////////////////////////////////
+ // TONE
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * @class Tone is the base class of all other classes. It provides
+ * a lot of methods and functionality to all classes that extend
+ * it.
+ *
+ * @constructor
+ * @alias Tone
+ * @param {number} [inputs=1] the number of input nodes
+ * @param {number} [outputs=1] the number of output nodes
+ */
+ var Tone = function (inputs, outputs) {
+ /**
+ * the input node(s)
+ * @type {GainNode|Array}
+ */
+ if (this.isUndef(inputs) || inputs === 1) {
+ this.input = this.context.createGain();
+ } else if (inputs > 1) {
+ this.input = new Array(inputs);
+ }
+ /**
+ * the output node(s)
+ * @type {GainNode|Array}
+ */
+ if (this.isUndef(outputs) || outputs === 1) {
+ this.output = this.context.createGain();
+ } else if (outputs > 1) {
+ this.output = new Array(inputs);
+ }
+ };
+ /**
+ * Set the parameters at once. Either pass in an
+ * object mapping parameters to values, or to set a
+ * single parameter, by passing in a string and value.
+ * The last argument is an optional ramp time which
+ * will ramp any signal values to their destination value
+ * over the duration of the rampTime.
+ * @param {Object|string} params
+ * @param {number=} value
+ * @param {Time=} rampTime
+ * @returns {Tone} this
+ * @example
+ * //set values using an object
+ * filter.set({
+ * "frequency" : 300,
+ * "type" : highpass
+ * });
+ * @example
+ * filter.set("type", "highpass");
+ * @example
+ * //ramp to the value 220 over 3 seconds.
+ * oscillator.set({
+ * "frequency" : 220
+ * }, 3);
+ */
+ Tone.prototype.set = function (params, value, rampTime) {
+ if (this.isObject(params)) {
+ rampTime = value;
+ } else if (this.isString(params)) {
+ var tmpObj = {};
+ tmpObj[params] = value;
+ params = tmpObj;
+ }
+ paramLoop:
+ for (var attr in params) {
+ value = params[attr];
+ var parent = this;
+ if (attr.indexOf('.') !== -1) {
+ var attrSplit = attr.split('.');
+ for (var i = 0; i < attrSplit.length - 1; i++) {
+ parent = parent[attrSplit[i]];
+ if (parent instanceof Tone) {
+ attrSplit.splice(0, i + 1);
+ var innerParam = attrSplit.join('.');
+ parent.set(innerParam, value);
+ continue paramLoop;
+ }
+ }
+ attr = attrSplit[attrSplit.length - 1];
+ }
+ var param = parent[attr];
+ if (this.isUndef(param)) {
+ continue;
+ }
+ if (Tone.Signal && param instanceof Tone.Signal || Tone.Param && param instanceof Tone.Param) {
+ if (param.value !== value) {
+ if (this.isUndef(rampTime)) {
+ param.value = value;
+ } else {
+ param.rampTo(value, rampTime);
+ }
+ }
+ } else if (param instanceof AudioParam) {
+ if (param.value !== value) {
+ param.value = value;
+ }
+ } else if (param instanceof Tone) {
+ param.set(value);
+ } else if (param !== value) {
+ parent[attr] = value;
+ }
+ }
+ return this;
+ };
+ /**
+ * Get the object's attributes. Given no arguments get
+ * will return all available object properties and their corresponding
+ * values. Pass in a single attribute to retrieve or an array
+ * of attributes. The attribute strings can also include a "."
+ * to access deeper properties.
+ * @example
+ * osc.get();
+ * //returns {"type" : "sine", "frequency" : 440, ...etc}
+ * @example
+ * osc.get("type");
+ * //returns { "type" : "sine"}
+ * @example
+ * //use dot notation to access deep properties
+ * synth.get(["envelope.attack", "envelope.release"]);
+ * //returns {"envelope" : {"attack" : 0.2, "release" : 0.4}}
+ * @param {Array=|string|undefined} params the parameters to get, otherwise will return
+ * all available.
+ * @returns {Object}
+ */
+ Tone.prototype.get = function (params) {
+ if (this.isUndef(params)) {
+ params = this._collectDefaults(this.constructor);
+ } else if (this.isString(params)) {
+ params = [params];
+ }
+ var ret = {};
+ for (var i = 0; i < params.length; i++) {
+ var attr = params[i];
+ var parent = this;
+ var subRet = ret;
+ if (attr.indexOf('.') !== -1) {
+ var attrSplit = attr.split('.');
+ for (var j = 0; j < attrSplit.length - 1; j++) {
+ var subAttr = attrSplit[j];
+ subRet[subAttr] = subRet[subAttr] || {};
+ subRet = subRet[subAttr];
+ parent = parent[subAttr];
+ }
+ attr = attrSplit[attrSplit.length - 1];
+ }
+ var param = parent[attr];
+ if (this.isObject(params[attr])) {
+ subRet[attr] = param.get();
+ } else if (Tone.Signal && param instanceof Tone.Signal) {
+ subRet[attr] = param.value;
+ } else if (Tone.Param && param instanceof Tone.Param) {
+ subRet[attr] = param.value;
+ } else if (param instanceof AudioParam) {
+ subRet[attr] = param.value;
+ } else if (param instanceof Tone) {
+ subRet[attr] = param.get();
+ } else if (!this.isFunction(param) && !this.isUndef(param)) {
+ subRet[attr] = param;
+ }
+ }
+ return ret;
+ };
+ /**
+ * collect all of the default attributes in one
+ * @private
+ * @param {function} constr the constructor to find the defaults from
+ * @return {Array} all of the attributes which belong to the class
+ */
+ Tone.prototype._collectDefaults = function (constr) {
+ var ret = [];
+ if (!this.isUndef(constr.defaults)) {
+ ret = Object.keys(constr.defaults);
+ }
+ if (!this.isUndef(constr._super)) {
+ var superDefs = this._collectDefaults(constr._super);
+ //filter out repeats
+ for (var i = 0; i < superDefs.length; i++) {
+ if (ret.indexOf(superDefs[i]) === -1) {
+ ret.push(superDefs[i]);
+ }
+ }
+ }
+ return ret;
+ };
+ /**
+ * @returns {string} returns the name of the class as a string
+ */
+ Tone.prototype.toString = function () {
+ for (var className in Tone) {
+ var isLetter = className[0].match(/^[A-Z]$/);
+ var sameConstructor = Tone[className] === this.constructor;
+ if (this.isFunction(Tone[className]) && isLetter && sameConstructor) {
+ return className;
+ }
+ }
+ return 'Tone';
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // CLASS VARS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * The number of inputs feeding into the AudioNode.
+ * For source nodes, this will be 0.
+ * @memberOf Tone#
+ * @name numberOfInputs
+ * @readOnly
+ */
+ Object.defineProperty(Tone.prototype, 'numberOfInputs', {
+ get: function () {
+ if (this.input) {
+ if (this.isArray(this.input)) {
+ return this.input.length;
+ } else {
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+ }
+ });
+ /**
+ * The number of outputs coming out of the AudioNode.
+ * For source nodes, this will be 0.
+ * @memberOf Tone#
+ * @name numberOfInputs
+ * @readOnly
+ */
+ Object.defineProperty(Tone.prototype, 'numberOfOutputs', {
+ get: function () {
+ if (this.output) {
+ if (this.isArray(this.output)) {
+ return this.output.length;
+ } else {
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+ }
+ });
+ ///////////////////////////////////////////////////////////////////////////
+ // CONNECTIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * disconnect and dispose
+ * @returns {Tone} this
+ */
+ Tone.prototype.dispose = function () {
+ if (!this.isUndef(this.input)) {
+ if (this.input instanceof AudioNode) {
+ this.input.disconnect();
+ }
+ this.input = null;
+ }
+ if (!this.isUndef(this.output)) {
+ if (this.output instanceof AudioNode) {
+ this.output.disconnect();
+ }
+ this.output = null;
+ }
+ return this;
+ };
+ /**
+ * connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode
+ * @param {Tone | AudioParam | AudioNode} unit
+ * @param {number} [outputNum=0] optionally which output to connect from
+ * @param {number} [inputNum=0] optionally which input to connect to
+ * @returns {Tone} this
+ */
+ Tone.prototype.connect = function (unit, outputNum, inputNum) {
+ if (Array.isArray(this.output)) {
+ outputNum = this.defaultArg(outputNum, 0);
+ this.output[outputNum].connect(unit, 0, inputNum);
+ } else {
+ this.output.connect(unit, outputNum, inputNum);
+ }
+ return this;
+ };
+ /**
+ * disconnect the output
+ * @param {Number|AudioNode} output Either the output index to disconnect
+ * if the output is an array, or the
+ * node to disconnect from.
+ * @returns {Tone} this
+ */
+ Tone.prototype.disconnect = function (destination, outputNum, inputNum) {
+ if (this.isArray(this.output)) {
+ if (this.isNumber(destination)) {
+ this.output[destination].disconnect();
+ } else {
+ outputNum = this.defaultArg(outputNum, 0);
+ this.output[outputNum].disconnect(destination, 0, inputNum);
+ }
+ } else {
+ this.output.disconnect.apply(this.output, arguments);
+ }
+ };
+ /**
+ * connect together all of the arguments in series
+ * @param {...AudioParam|Tone|AudioNode} nodes
+ * @returns {Tone} this
+ */
+ Tone.prototype.connectSeries = function () {
+ if (arguments.length > 1) {
+ var currentUnit = arguments[0];
+ for (var i = 1; i < arguments.length; i++) {
+ var toUnit = arguments[i];
+ currentUnit.connect(toUnit);
+ currentUnit = toUnit;
+ }
+ }
+ return this;
+ };
+ /**
+ * Connect the output of this node to the rest of the nodes in series.
+ * @example
+ * //connect a node to an effect, panVol and then to the master output
+ * node.chain(effect, panVol, Tone.Master);
+ * @param {...AudioParam|Tone|AudioNode} nodes
+ * @returns {Tone} this
+ */
+ Tone.prototype.chain = function () {
+ if (arguments.length > 0) {
+ var currentUnit = this;
+ for (var i = 0; i < arguments.length; i++) {
+ var toUnit = arguments[i];
+ currentUnit.connect(toUnit);
+ currentUnit = toUnit;
+ }
+ }
+ return this;
+ };
+ /**
+ * connect the output of this node to the rest of the nodes in parallel.
+ * @param {...AudioParam|Tone|AudioNode} nodes
+ * @returns {Tone} this
+ */
+ Tone.prototype.fan = function () {
+ if (arguments.length > 0) {
+ for (var i = 0; i < arguments.length; i++) {
+ this.connect(arguments[i]);
+ }
+ }
+ return this;
+ };
+ //give native nodes chain and fan methods
+ AudioNode.prototype.chain = Tone.prototype.chain;
+ AudioNode.prototype.fan = Tone.prototype.fan;
+ ///////////////////////////////////////////////////////////////////////////
+ // UTILITIES / HELPERS / MATHS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * If the `given` parameter is undefined, use the `fallback`.
+ * If both `given` and `fallback` are object literals, it will
+ * return a deep copy which includes all of the parameters from both
+ * objects. If a parameter is undefined in given, it will return
+ * the fallback property.
+ * <br><br>
+ * WARNING: if object is self referential, it will go into an an
+ * infinite recursive loop.
+ *
+ * @param {*} given
+ * @param {*} fallback
+ * @return {*}
+ */
+ Tone.prototype.defaultArg = function (given, fallback) {
+ if (this.isObject(given) && this.isObject(fallback)) {
+ var ret = {};
+ //make a deep copy of the given object
+ for (var givenProp in given) {
+ ret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);
+ }
+ for (var fallbackProp in fallback) {
+ ret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);
+ }
+ return ret;
+ } else {
+ return this.isUndef(given) ? fallback : given;
+ }
+ };
+ /**
+ * returns the args as an options object with given arguments
+ * mapped to the names provided.
+ *
+ * if the args given is an array containing only one object, it is assumed
+ * that that's already the options object and will just return it.
+ *
+ * @param {Array} values the 'arguments' object of the function
+ * @param {Array} keys the names of the arguments as they
+ * should appear in the options object
+ * @param {Object=} defaults optional defaults to mixin to the returned
+ * options object
+ * @return {Object} the options object with the names mapped to the arguments
+ */
+ Tone.prototype.optionsObject = function (values, keys, defaults) {
+ var options = {};
+ if (values.length === 1 && this.isObject(values[0])) {
+ options = values[0];
+ } else {
+ for (var i = 0; i < keys.length; i++) {
+ options[keys[i]] = values[i];
+ }
+ }
+ if (!this.isUndef(defaults)) {
+ return this.defaultArg(options, defaults);
+ } else {
+ return options;
+ }
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // TYPE CHECKING
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * test if the arg is undefined
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is undefined
+ * @function
+ */
+ Tone.prototype.isUndef = function (val) {
+ return typeof val === 'undefined';
+ };
+ /**
+ * test if the arg is a function
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is a function
+ * @function
+ */
+ Tone.prototype.isFunction = function (val) {
+ return typeof val === 'function';
+ };
+ /**
+ * Test if the argument is a number.
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is a number
+ */
+ Tone.prototype.isNumber = function (arg) {
+ return typeof arg === 'number';
+ };
+ /**
+ * Test if the given argument is an object literal (i.e. `{}`);
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is an object literal.
+ */
+ Tone.prototype.isObject = function (arg) {
+ return Object.prototype.toString.call(arg) === '[object Object]' && arg.constructor === Object;
+ };
+ /**
+ * Test if the argument is a boolean.
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is a boolean
+ */
+ Tone.prototype.isBoolean = function (arg) {
+ return typeof arg === 'boolean';
+ };
+ /**
+ * Test if the argument is an Array
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is an array
+ */
+ Tone.prototype.isArray = function (arg) {
+ return Array.isArray(arg);
+ };
+ /**
+ * Test if the argument is a string.
+ * @param {*} arg the argument to test
+ * @returns {boolean} true if the arg is a string
+ */
+ Tone.prototype.isString = function (arg) {
+ return typeof arg === 'string';
+ };
+ /**
+ * An empty function.
+ * @static
+ */
+ Tone.noOp = function () {
+ };
+ /**
+ * Make the property not writable. Internal use only.
+ * @private
+ * @param {string} property the property to make not writable
+ */
+ Tone.prototype._readOnly = function (property) {
+ if (Array.isArray(property)) {
+ for (var i = 0; i < property.length; i++) {
+ this._readOnly(property[i]);
+ }
+ } else {
+ Object.defineProperty(this, property, {
+ writable: false,
+ enumerable: true
+ });
+ }
+ };
+ /**
+ * Make an attribute writeable. Interal use only.
+ * @private
+ * @param {string} property the property to make writable
+ */
+ Tone.prototype._writable = function (property) {
+ if (Array.isArray(property)) {
+ for (var i = 0; i < property.length; i++) {
+ this._writable(property[i]);
+ }
+ } else {
+ Object.defineProperty(this, property, { writable: true });
+ }
+ };
+ /**
+ * Possible play states.
+ * @enum {string}
+ */
+ Tone.State = {
+ Started: 'started',
+ Stopped: 'stopped',
+ Paused: 'paused'
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // CONVERSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Equal power gain scale. Good for cross-fading.
+ * @param {NormalRange} percent (0-1)
+ * @return {Number} output gain (0-1)
+ */
+ Tone.prototype.equalPowerScale = function (percent) {
+ var piFactor = 0.5 * Math.PI;
+ return Math.sin(percent * piFactor);
+ };
+ /**
+ * Convert decibels into gain.
+ * @param {Decibels} db
+ * @return {Number}
+ */
+ Tone.prototype.dbToGain = function (db) {
+ return Math.pow(2, db / 6);
+ };
+ /**
+ * Convert gain to decibels.
+ * @param {Number} gain (0-1)
+ * @return {Decibels}
+ */
+ Tone.prototype.gainToDb = function (gain) {
+ return 20 * (Math.log(gain) / Math.LN10);
+ };
+ /**
+ * Convert an interval (in semitones) to a frequency ratio.
+ * @param {Interval} interval the number of semitones above the base note
+ * @return {number} the frequency ratio
+ * @example
+ * tone.intervalToFrequencyRatio(0); // 1
+ * tone.intervalToFrequencyRatio(12); // 2
+ * tone.intervalToFrequencyRatio(-12); // 0.5
+ */
+ Tone.prototype.intervalToFrequencyRatio = function (interval) {
+ return Math.pow(2, interval / 12);
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // TIMING
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Return the current time of the AudioContext clock.
+ * @return {Number} the currentTime from the AudioContext
+ */
+ Tone.prototype.now = function () {
+ return Tone.context.now();
+ };
+ /**
+ * Return the current time of the AudioContext clock.
+ * @return {Number} the currentTime from the AudioContext
+ * @static
+ */
+ Tone.now = function () {
+ return Tone.context.now();
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // INHERITANCE
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * have a child inherit all of Tone's (or a parent's) prototype
+ * to inherit the parent's properties, make sure to call
+ * Parent.call(this) in the child's constructor
+ *
+ * based on closure library's inherit function
+ *
+ * @static
+ * @param {function} child
+ * @param {function=} parent (optional) parent to inherit from
+ * if no parent is supplied, the child
+ * will inherit from Tone
+ */
+ Tone.extend = function (child, parent) {
+ if (Tone.prototype.isUndef(parent)) {
+ parent = Tone;
+ }
+ function TempConstructor() {
+ }
+ TempConstructor.prototype = parent.prototype;
+ child.prototype = new TempConstructor();
+ /** @override */
+ child.prototype.constructor = child;
+ child._super = parent;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // CONTEXT
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * The private audio context shared by all Tone Nodes.
+ * @private
+ * @type {Tone.Context|undefined}
+ */
+ var audioContext;
+ /**
+ * A static pointer to the audio context accessible as Tone.context.
+ * @type {Tone.Context}
+ * @name context
+ * @memberOf Tone
+ */
+ Object.defineProperty(Tone, 'context', {
+ get: function () {
+ return audioContext;
+ },
+ set: function (context) {
+ if (Tone.Context && context instanceof Tone.Context) {
+ audioContext = context;
+ } else {
+ audioContext = new Tone.Context(context);
+ }
+ //initialize the new audio context
+ if (Tone.Context) {
+ Tone.Context.emit('init', audioContext);
+ }
+ }
+ });
+ /**
+ * The AudioContext
+ * @type {Tone.Context}
+ * @name context
+ * @memberOf Tone#
+ * @readOnly
+ */
+ Object.defineProperty(Tone.prototype, 'context', {
+ get: function () {
+ return Tone.context;
+ }
+ });
+ /**
+ * Tone automatically creates a context on init, but if you are working
+ * with other libraries which also create an AudioContext, it can be
+ * useful to set your own. If you are going to set your own context,
+ * be sure to do it at the start of your code, before creating any objects.
+ * @static
+ * @param {AudioContext} ctx The new audio context to set
+ */
+ Tone.setContext = function (ctx) {
+ Tone.context = ctx;
+ };
+ /**
+ * The number of seconds of 1 processing block (128 samples)
+ * @type {Number}
+ * @name blockTime
+ * @memberOf Tone#
+ * @readOnly
+ */
+ Object.defineProperty(Tone.prototype, 'blockTime', {
+ get: function () {
+ return 128 / this.context.sampleRate;
+ }
+ });
+ /**
+ * The duration in seconds of one sample.
+ * @type {Number}
+ * @name sampleTime
+ * @memberOf Tone#
+ * @readOnly
+ */
+ Object.defineProperty(Tone.prototype, 'sampleTime', {
+ get: function () {
+ return 1 / this.context.sampleRate;
+ }
+ });
+ /**
+ * Whether or not all the technologies that Tone.js relies on are supported by the current browser.
+ * @type {Boolean}
+ * @name supported
+ * @memberOf Tone
+ * @readOnly
+ */
+ Object.defineProperty(Tone, 'supported', {
+ get: function () {
+ var hasAudioContext = window.hasOwnProperty('AudioContext') || window.hasOwnProperty('webkitAudioContext');
+ var hasPromises = window.hasOwnProperty('Promise');
+ var hasWorkers = window.hasOwnProperty('Worker');
+ return hasAudioContext && hasPromises && hasWorkers;
+ }
+ });
+ Tone.version = 'r10';
+ // allow optional silencing of this log
+ if (!window.TONE_SILENCE_VERSION_LOGGING) {
+ console.log('%c * Tone.js ' + Tone.version + ' * ', 'background: #000; color: #fff');
+ }
+ return Tone;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Base class for all Signals. Used Internally.
+ *
+ * @constructor
+ * @extends {Tone}
+ */
+ Tone.SignalBase = function () {
+ };
+ Tone.extend(Tone.SignalBase);
+ /**
+ * When signals connect to other signals or AudioParams,
+ * they take over the output value of that signal or AudioParam.
+ * For all other nodes, the behavior is the same as a default <code>connect</code>.
+ *
+ * @override
+ * @param {AudioParam|AudioNode|Tone.Signal|Tone} node
+ * @param {number} [outputNumber=0] The output number to connect from.
+ * @param {number} [inputNumber=0] The input number to connect to.
+ * @returns {Tone.SignalBase} this
+ */
+ Tone.SignalBase.prototype.connect = function (node, outputNumber, inputNumber) {
+ //zero it out so that the signal can have full control
+ if (Tone.Signal && Tone.Signal === node.constructor || Tone.Param && Tone.Param === node.constructor || Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) {
+ //cancel changes
+ node._param.cancelScheduledValues(0);
+ //reset the value
+ node._param.value = 0;
+ //mark the value as overridden
+ node.overridden = true;
+ } else if (node instanceof AudioParam) {
+ node.cancelScheduledValues(0);
+ node.value = 0;
+ }
+ Tone.prototype.connect.call(this, node, outputNumber, inputNumber);
+ return this;
+ };
+ return Tone.SignalBase;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Wraps the native Web Audio API
+ * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @param {function|Array|Number} mapping The function used to define the values.
+ * The mapping function should take two arguments:
+ * the first is the value at the current position
+ * and the second is the array position.
+ * If the argument is an array, that array will be
+ * set as the wave shaping function. The input
+ * signal is an AudioRange [-1, 1] value and the output
+ * signal can take on any numerical values.
+ *
+ * @param {Number} [bufferLen=1024] The length of the WaveShaperNode buffer.
+ * @example
+ * var timesTwo = new Tone.WaveShaper(function(val){
+ * return val * 2;
+ * }, 2048);
+ * @example
+ * //a waveshaper can also be constructed with an array of values
+ * var invert = new Tone.WaveShaper([1, -1]);
+ */
+ Tone.WaveShaper = function (mapping, bufferLen) {
+ /**
+ * the waveshaper
+ * @type {WaveShaperNode}
+ * @private
+ */
+ this._shaper = this.input = this.output = this.context.createWaveShaper();
+ /**
+ * the waveshapers curve
+ * @type {Float32Array}
+ * @private
+ */
+ this._curve = null;
+ if (Array.isArray(mapping)) {
+ this.curve = mapping;
+ } else if (isFinite(mapping) || this.isUndef(mapping)) {
+ this._curve = new Float32Array(this.defaultArg(mapping, 1024));
+ } else if (this.isFunction(mapping)) {
+ this._curve = new Float32Array(this.defaultArg(bufferLen, 1024));
+ this.setMap(mapping);
+ }
+ };
+ Tone.extend(Tone.WaveShaper, Tone.SignalBase);
+ /**
+ * Uses a mapping function to set the value of the curve.
+ * @param {function} mapping The function used to define the values.
+ * The mapping function take two arguments:
+ * the first is the value at the current position
+ * which goes from -1 to 1 over the number of elements
+ * in the curve array. The second argument is the array position.
+ * @returns {Tone.WaveShaper} this
+ * @example
+ * //map the input signal from [-1, 1] to [0, 10]
+ * shaper.setMap(function(val, index){
+ * return (val + 1) * 5;
+ * })
+ */
+ Tone.WaveShaper.prototype.setMap = function (mapping) {
+ for (var i = 0, len = this._curve.length; i < len; i++) {
+ var normalized = i / (len - 1) * 2 - 1;
+ this._curve[i] = mapping(normalized, i);
+ }
+ this._shaper.curve = this._curve;
+ return this;
+ };
+ /**
+ * The array to set as the waveshaper curve. For linear curves
+ * array length does not make much difference, but for complex curves
+ * longer arrays will provide smoother interpolation.
+ * @memberOf Tone.WaveShaper#
+ * @type {Array}
+ * @name curve
+ */
+ Object.defineProperty(Tone.WaveShaper.prototype, 'curve', {
+ get: function () {
+ return this._shaper.curve;
+ },
+ set: function (mapping) {
+ this._curve = new Float32Array(mapping);
+ this._shaper.curve = this._curve;
+ }
+ });
+ /**
+ * Specifies what type of oversampling (if any) should be used when
+ * applying the shaping curve. Can either be "none", "2x" or "4x".
+ * @memberOf Tone.WaveShaper#
+ * @type {string}
+ * @name oversample
+ */
+ Object.defineProperty(Tone.WaveShaper.prototype, 'oversample', {
+ get: function () {
+ return this._shaper.oversample;
+ },
+ set: function (oversampling) {
+ if ([
+ 'none',
+ '2x',
+ '4x'
+ ].indexOf(oversampling) !== -1) {
+ this._shaper.oversample = oversampling;
+ } else {
+ throw new RangeError('Tone.WaveShaper: oversampling must be either \'none\', \'2x\', or \'4x\'');
+ }
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.WaveShaper} this
+ */
+ Tone.WaveShaper.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._shaper.disconnect();
+ this._shaper = null;
+ this._curve = null;
+ return this;
+ };
+ return Tone.WaveShaper;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.TimeBase is a flexible encoding of time
+ * which can be evaluated to and from a string.
+ * Parsing code modified from https://code.google.com/p/tapdigit/
+ * Copyright 2011 2012 Ariya Hidayat, New BSD License
+ * @extends {Tone}
+ * @param {Time} val The time value as a number or string
+ * @param {String=} units Unit values
+ * @example
+ * Tone.TimeBase(4, "n")
+ * Tone.TimeBase(2, "t")
+ * Tone.TimeBase("2t").add("1m")
+ * Tone.TimeBase("2t + 1m");
+ */
+ Tone.TimeBase = function (val, units) {
+ //allows it to be constructed with or without 'new'
+ if (this instanceof Tone.TimeBase) {
+ /**
+ * Any expressions parsed from the Time
+ * @type {Array}
+ * @private
+ */
+ this._expr = this._noOp;
+ if (val instanceof Tone.TimeBase) {
+ this.copy(val);
+ } else if (!this.isUndef(units) || this.isNumber(val)) {
+ //default units
+ units = this.defaultArg(units, this._defaultUnits);
+ var method = this._primaryExpressions[units].method;
+ this._expr = method.bind(this, val);
+ } else if (this.isString(val)) {
+ this.set(val);
+ } else if (this.isUndef(val)) {
+ //default expression
+ this._expr = this._defaultExpr();
+ }
+ } else {
+ return new Tone.TimeBase(val, units);
+ }
+ };
+ Tone.extend(Tone.TimeBase);
+ /**
+ * Repalce the current time value with the value
+ * given by the expression string.
+ * @param {String} exprString
+ * @return {Tone.TimeBase} this
+ */
+ Tone.TimeBase.prototype.set = function (exprString) {
+ this._expr = this._parseExprString(exprString);
+ return this;
+ };
+ /**
+ * Return a clone of the TimeBase object.
+ * @return {Tone.TimeBase} The new cloned Tone.TimeBase
+ */
+ Tone.TimeBase.prototype.clone = function () {
+ var instance = new this.constructor();
+ instance.copy(this);
+ return instance;
+ };
+ /**
+ * Copies the value of time to this Time
+ * @param {Tone.TimeBase} time
+ * @return {TimeBase}
+ */
+ Tone.TimeBase.prototype.copy = function (time) {
+ var val = time._expr();
+ return this.set(val);
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // ABSTRACT SYNTAX TREE PARSER
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * All the primary expressions.
+ * @private
+ * @type {Object}
+ */
+ Tone.TimeBase.prototype._primaryExpressions = {
+ 'n': {
+ regexp: /^(\d+)n/i,
+ method: function (value) {
+ value = parseInt(value);
+ if (value === 1) {
+ return this._beatsToUnits(this._timeSignature());
+ } else {
+ return this._beatsToUnits(4 / value);
+ }
+ }
+ },
+ 't': {
+ regexp: /^(\d+)t/i,
+ method: function (value) {
+ value = parseInt(value);
+ return this._beatsToUnits(8 / (parseInt(value) * 3));
+ }
+ },
+ 'm': {
+ regexp: /^(\d+)m/i,
+ method: function (value) {
+ return this._beatsToUnits(parseInt(value) * this._timeSignature());
+ }
+ },
+ 'i': {
+ regexp: /^(\d+)i/i,
+ method: function (value) {
+ return this._ticksToUnits(parseInt(value));
+ }
+ },
+ 'hz': {
+ regexp: /^(\d+(?:\.\d+)?)hz/i,
+ method: function (value) {
+ return this._frequencyToUnits(parseFloat(value));
+ }
+ },
+ 'tr': {
+ regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,
+ method: function (m, q, s) {
+ var total = 0;
+ if (m && m !== '0') {
+ total += this._beatsToUnits(this._timeSignature() * parseFloat(m));
+ }
+ if (q && q !== '0') {
+ total += this._beatsToUnits(parseFloat(q));
+ }
+ if (s && s !== '0') {
+ total += this._beatsToUnits(parseFloat(s) / 4);
+ }
+ return total;
+ }
+ },
+ 's': {
+ regexp: /^(\d+(?:\.\d+)?s)/,
+ method: function (value) {
+ return this._secondsToUnits(parseFloat(value));
+ }
+ },
+ 'samples': {
+ regexp: /^(\d+)samples/,
+ method: function (value) {
+ return parseInt(value) / this.context.sampleRate;
+ }
+ },
+ 'default': {
+ regexp: /^(\d+(?:\.\d+)?)/,
+ method: function (value) {
+ return this._primaryExpressions[this._defaultUnits].method.call(this, value);
+ }
+ }
+ };
+ /**
+ * All the binary expressions that TimeBase can accept.
+ * @private
+ * @type {Object}
+ */
+ Tone.TimeBase.prototype._binaryExpressions = {
+ '+': {
+ regexp: /^\+/,
+ precedence: 2,
+ method: function (lh, rh) {
+ return lh() + rh();
+ }
+ },
+ '-': {
+ regexp: /^\-/,
+ precedence: 2,
+ method: function (lh, rh) {
+ return lh() - rh();
+ }
+ },
+ '*': {
+ regexp: /^\*/,
+ precedence: 1,
+ method: function (lh, rh) {
+ return lh() * rh();
+ }
+ },
+ '/': {
+ regexp: /^\//,
+ precedence: 1,
+ method: function (lh, rh) {
+ return lh() / rh();
+ }
+ }
+ };
+ /**
+ * All the unary expressions.
+ * @private
+ * @type {Object}
+ */
+ Tone.TimeBase.prototype._unaryExpressions = {
+ 'neg': {
+ regexp: /^\-/,
+ method: function (lh) {
+ return -lh();
+ }
+ }
+ };
+ /**
+ * Syntactic glue which holds expressions together
+ * @private
+ * @type {Object}
+ */
+ Tone.TimeBase.prototype._syntaxGlue = {
+ '(': { regexp: /^\(/ },
+ ')': { regexp: /^\)/ }
+ };
+ /**
+ * tokenize the expression based on the Expressions object
+ * @param {string} expr
+ * @return {Object} returns two methods on the tokenized list, next and peek
+ * @private
+ */
+ Tone.TimeBase.prototype._tokenize = function (expr) {
+ var position = -1;
+ var tokens = [];
+ while (expr.length > 0) {
+ expr = expr.trim();
+ var token = getNextToken(expr, this);
+ tokens.push(token);
+ expr = expr.substr(token.value.length);
+ }
+ function getNextToken(expr, context) {
+ var expressions = [
+ '_binaryExpressions',
+ '_unaryExpressions',
+ '_primaryExpressions',
+ '_syntaxGlue'
+ ];
+ for (var i = 0; i < expressions.length; i++) {
+ var group = context[expressions[i]];
+ for (var opName in group) {
+ var op = group[opName];
+ var reg = op.regexp;
+ var match = expr.match(reg);
+ if (match !== null) {
+ return {
+ method: op.method,
+ precedence: op.precedence,
+ regexp: op.regexp,
+ value: match[0]
+ };
+ }
+ }
+ }
+ throw new SyntaxError('Tone.TimeBase: Unexpected token ' + expr);
+ }
+ return {
+ next: function () {
+ return tokens[++position];
+ },
+ peek: function () {
+ return tokens[position + 1];
+ }
+ };
+ };
+ /**
+ * Given a token, find the value within the groupName
+ * @param {Object} token
+ * @param {String} groupName
+ * @param {Number} precedence
+ * @private
+ */
+ Tone.TimeBase.prototype._matchGroup = function (token, group, prec) {
+ var ret = false;
+ if (!this.isUndef(token)) {
+ for (var opName in group) {
+ var op = group[opName];
+ if (op.regexp.test(token.value)) {
+ if (!this.isUndef(prec)) {
+ if (op.precedence === prec) {
+ return op;
+ }
+ } else {
+ return op;
+ }
+ }
+ }
+ }
+ return ret;
+ };
+ /**
+ * Match a binary expression given the token and the precedence
+ * @param {Lexer} lexer
+ * @param {Number} precedence
+ * @private
+ */
+ Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) {
+ if (this.isUndef(precedence)) {
+ precedence = 2;
+ }
+ var expr;
+ if (precedence < 0) {
+ expr = this._parseUnary(lexer);
+ } else {
+ expr = this._parseBinary(lexer, precedence - 1);
+ }
+ var token = lexer.peek();
+ while (token && this._matchGroup(token, this._binaryExpressions, precedence)) {
+ token = lexer.next();
+ expr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));
+ token = lexer.peek();
+ }
+ return expr;
+ };
+ /**
+ * Match a unary expression.
+ * @param {Lexer} lexer
+ * @private
+ */
+ Tone.TimeBase.prototype._parseUnary = function (lexer) {
+ var token, expr;
+ token = lexer.peek();
+ var op = this._matchGroup(token, this._unaryExpressions);
+ if (op) {
+ token = lexer.next();
+ expr = this._parseUnary(lexer);
+ return op.method.bind(this, expr);
+ }
+ return this._parsePrimary(lexer);
+ };
+ /**
+ * Match a primary expression (a value).
+ * @param {Lexer} lexer
+ * @private
+ */
+ Tone.TimeBase.prototype._parsePrimary = function (lexer) {
+ var token, expr;
+ token = lexer.peek();
+ if (this.isUndef(token)) {
+ throw new SyntaxError('Tone.TimeBase: Unexpected end of expression');
+ }
+ if (this._matchGroup(token, this._primaryExpressions)) {
+ token = lexer.next();
+ var matching = token.value.match(token.regexp);
+ return token.method.bind(this, matching[1], matching[2], matching[3]);
+ }
+ if (token && token.value === '(') {
+ lexer.next();
+ expr = this._parseBinary(lexer);
+ token = lexer.next();
+ if (!(token && token.value === ')')) {
+ throw new SyntaxError('Expected )');
+ }
+ return expr;
+ }
+ throw new SyntaxError('Tone.TimeBase: Cannot process token ' + token.value);
+ };
+ /**
+ * Recursively parse the string expression into a syntax tree.
+ * @param {string} expr
+ * @return {Function} the bound method to be evaluated later
+ * @private
+ */
+ Tone.TimeBase.prototype._parseExprString = function (exprString) {
+ if (!this.isString(exprString)) {
+ exprString = exprString.toString();
+ }
+ var lexer = this._tokenize(exprString);
+ var tree = this._parseBinary(lexer);
+ return tree;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // DEFAULTS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * The initial expression value
+ * @return {Number} The initial value 0
+ * @private
+ */
+ Tone.TimeBase.prototype._noOp = function () {
+ return 0;
+ };
+ /**
+ * The default expression value if no arguments are given
+ * @private
+ */
+ Tone.TimeBase.prototype._defaultExpr = function () {
+ return this._noOp;
+ };
+ /**
+ * The default units if none are given.
+ * @private
+ */
+ Tone.TimeBase.prototype._defaultUnits = 's';
+ ///////////////////////////////////////////////////////////////////////////
+ // UNIT CONVERSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Returns the value of a frequency in the current units
+ * @param {Frequency} freq
+ * @return {Number}
+ * @private
+ */
+ Tone.TimeBase.prototype._frequencyToUnits = function (freq) {
+ return 1 / freq;
+ };
+ /**
+ * Return the value of the beats in the current units
+ * @param {Number} beats
+ * @return {Number}
+ * @private
+ */
+ Tone.TimeBase.prototype._beatsToUnits = function (beats) {
+ return 60 / Tone.Transport.bpm.value * beats;
+ };
+ /**
+ * Returns the value of a second in the current units
+ * @param {Seconds} seconds
+ * @return {Number}
+ * @private
+ */
+ Tone.TimeBase.prototype._secondsToUnits = function (seconds) {
+ return seconds;
+ };
+ /**
+ * Returns the value of a tick in the current time units
+ * @param {Ticks} ticks
+ * @return {Number}
+ * @private
+ */
+ Tone.TimeBase.prototype._ticksToUnits = function (ticks) {
+ return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);
+ };
+ /**
+ * Return the time signature.
+ * @return {Number}
+ * @private
+ */
+ Tone.TimeBase.prototype._timeSignature = function () {
+ return Tone.Transport.timeSignature;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // EXPRESSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Push an expression onto the expression list
+ * @param {Time} val
+ * @param {String} type
+ * @param {String} units
+ * @return {Tone.TimeBase}
+ * @private
+ */
+ Tone.TimeBase.prototype._pushExpr = function (val, name, units) {
+ //create the expression
+ if (!(val instanceof Tone.TimeBase)) {
+ val = new this.constructor(val, units);
+ }
+ this._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);
+ return this;
+ };
+ /**
+ * Add to the current value.
+ * @param {Time} val The value to add
+ * @param {String=} units Optional units to use with the value.
+ * @return {Tone.TimeBase} this
+ * @example
+ * Tone.TimeBase("2m").add("1m"); //"3m"
+ */
+ Tone.TimeBase.prototype.add = function (val, units) {
+ return this._pushExpr(val, '+', units);
+ };
+ /**
+ * Subtract the value from the current time.
+ * @param {Time} val The value to subtract
+ * @param {String=} units Optional units to use with the value.
+ * @return {Tone.TimeBase} this
+ * @example
+ * Tone.TimeBase("2m").sub("1m"); //"1m"
+ */
+ Tone.TimeBase.prototype.sub = function (val, units) {
+ return this._pushExpr(val, '-', units);
+ };
+ /**
+ * Multiply the current value by the given time.
+ * @param {Time} val The value to multiply
+ * @param {String=} units Optional units to use with the value.
+ * @return {Tone.TimeBase} this
+ * @example
+ * Tone.TimeBase("2m").mult("2"); //"4m"
+ */
+ Tone.TimeBase.prototype.mult = function (val, units) {
+ return this._pushExpr(val, '*', units);
+ };
+ /**
+ * Divide the current value by the given time.
+ * @param {Time} val The value to divide by
+ * @param {String=} units Optional units to use with the value.
+ * @return {Tone.TimeBase} this
+ * @example
+ * Tone.TimeBase("2m").div(2); //"1m"
+ */
+ Tone.TimeBase.prototype.div = function (val, units) {
+ return this._pushExpr(val, '/', units);
+ };
+ /**
+ * Evaluate the time value. Returns the time
+ * in seconds.
+ * @return {Seconds}
+ */
+ Tone.TimeBase.prototype.valueOf = function () {
+ return this._expr();
+ };
+ /**
+ * Clean up
+ * @return {Tone.TimeBase} this
+ */
+ Tone.TimeBase.prototype.dispose = function () {
+ this._expr = null;
+ };
+ return Tone.TimeBase;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.Time is a primitive type for encoding Time values.
+ * Eventually all time values are evaluated to seconds
+ * using the `eval` method. Tone.Time can be constructed
+ * with or without the `new` keyword. Tone.Time can be passed
+ * into the parameter of any method which takes time as an argument.
+ * @constructor
+ * @extends {Tone.TimeBase}
+ * @param {String|Number} val The time value.
+ * @param {String=} units The units of the value.
+ * @example
+ * var t = Tone.Time("4n");//encodes a quarter note
+ * t.mult(4); // multiply that value by 4
+ * t.toNotation(); //returns "1m"
+ */
+ Tone.Time = function (val, units) {
+ if (this instanceof Tone.Time) {
+ /**
+ * If the current clock time should
+ * be added to the output
+ * @type {Boolean}
+ * @private
+ */
+ this._plusNow = false;
+ Tone.TimeBase.call(this, val, units);
+ } else {
+ return new Tone.Time(val, units);
+ }
+ };
+ Tone.extend(Tone.Time, Tone.TimeBase);
+ //clone the expressions so that
+ //we can add more without modifying the original
+ Tone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);
+ /*
+ * Adds an additional unary expression
+ * which quantizes values to the next subdivision
+ * @type {Object}
+ * @private
+ */
+ Tone.Time.prototype._unaryExpressions.quantize = {
+ regexp: /^@/,
+ method: function (rh) {
+ return Tone.Transport.nextSubdivision(rh());
+ }
+ };
+ /*
+ * Adds an additional unary expression
+ * which adds the current clock time.
+ * @type {Object}
+ * @private
+ */
+ Tone.Time.prototype._unaryExpressions.now = {
+ regexp: /^\+/,
+ method: function (lh) {
+ this._plusNow = true;
+ return lh();
+ }
+ };
+ /**
+ * Quantize the time by the given subdivision. Optionally add a
+ * percentage which will move the time value towards the ideal
+ * quantized value by that percentage.
+ * @param {Number|Time} val The subdivision to quantize to
+ * @param {NormalRange} [percent=1] Move the time value
+ * towards the quantized value by
+ * a percentage.
+ * @return {Tone.Time} this
+ * @example
+ * Tone.Time(21).quantize(2) //returns 22
+ * Tone.Time(0.6).quantize("4n", 0.5) //returns 0.55
+ */
+ Tone.Time.prototype.quantize = function (subdiv, percent) {
+ percent = this.defaultArg(percent, 1);
+ this._expr = function (expr, subdivision, percent) {
+ expr = expr();
+ subdivision = subdivision.toSeconds();
+ var multiple = Math.round(expr / subdivision);
+ var ideal = multiple * subdivision;
+ var diff = ideal - expr;
+ return expr + diff * percent;
+ }.bind(this, this._expr, new this.constructor(subdiv), percent);
+ return this;
+ };
+ /**
+ * Adds the clock time to the time expression at the
+ * moment of evaluation.
+ * @return {Tone.Time} this
+ */
+ Tone.Time.prototype.addNow = function () {
+ this._plusNow = true;
+ return this;
+ };
+ /**
+ * @override
+ * Override the default value return when no arguments are passed in.
+ * The default value is 'now'
+ * @private
+ */
+ Tone.Time.prototype._defaultExpr = function () {
+ this._plusNow = true;
+ return this._noOp;
+ };
+ /**
+ * Copies the value of time to this Time
+ * @param {Tone.Time} time
+ * @return {Time}
+ */
+ Tone.Time.prototype.copy = function (time) {
+ Tone.TimeBase.prototype.copy.call(this, time);
+ this._plusNow = time._plusNow;
+ return this;
+ };
+ //CONVERSIONS//////////////////////////////////////////////////////////////
+ /**
+ * Convert a Time to Notation. Values will be thresholded to the nearest 128th note.
+ * @return {Notation}
+ * @example
+ * //if the Transport is at 120bpm:
+ * Tone.Time(2).toNotation();//returns "1m"
+ */
+ Tone.Time.prototype.toNotation = function () {
+ var time = this.toSeconds();
+ var testNotations = [
+ '1m',
+ '2n',
+ '4n',
+ '8n',
+ '16n',
+ '32n',
+ '64n',
+ '128n'
+ ];
+ var retNotation = this._toNotationHelper(time, testNotations);
+ //try the same thing but with tripelets
+ var testTripletNotations = [
+ '1m',
+ '2n',
+ '2t',
+ '4n',
+ '4t',
+ '8n',
+ '8t',
+ '16n',
+ '16t',
+ '32n',
+ '32t',
+ '64n',
+ '64t',
+ '128n'
+ ];
+ var retTripletNotation = this._toNotationHelper(time, testTripletNotations);
+ //choose the simpler expression of the two
+ if (retTripletNotation.split('+').length < retNotation.split('+').length) {
+ return retTripletNotation;
+ } else {
+ return retNotation;
+ }
+ };
+ /**
+ * Helper method for Tone.toNotation
+ * @param {Number} units
+ * @param {Array} testNotations
+ * @return {String}
+ * @private
+ */
+ Tone.Time.prototype._toNotationHelper = function (units, testNotations) {
+ //the threshold is the last value in the array
+ var threshold = this._notationToUnits(testNotations[testNotations.length - 1]);
+ var retNotation = '';
+ for (var i = 0; i < testNotations.length; i++) {
+ var notationTime = this._notationToUnits(testNotations[i]);
+ //account for floating point errors (i.e. round up if the value is 0.999999)
+ var multiple = units / notationTime;
+ var floatingPointError = 0.000001;
+ if (1 - multiple % 1 < floatingPointError) {
+ multiple += floatingPointError;
+ }
+ multiple = Math.floor(multiple);
+ if (multiple > 0) {
+ if (multiple === 1) {
+ retNotation += testNotations[i];
+ } else {
+ retNotation += multiple.toString() + '*' + testNotations[i];
+ }
+ units -= multiple * notationTime;
+ if (units < threshold) {
+ break;
+ } else {
+ retNotation += ' + ';
+ }
+ }
+ }
+ if (retNotation === '') {
+ retNotation = '0';
+ }
+ return retNotation;
+ };
+ /**
+ * Convert a notation value to the current units
+ * @param {Notation} notation
+ * @return {Number}
+ * @private
+ */
+ Tone.Time.prototype._notationToUnits = function (notation) {
+ var primaryExprs = this._primaryExpressions;
+ var notationExprs = [
+ primaryExprs.n,
+ primaryExprs.t,
+ primaryExprs.m
+ ];
+ for (var i = 0; i < notationExprs.length; i++) {
+ var expr = notationExprs[i];
+ var match = notation.match(expr.regexp);
+ if (match) {
+ return expr.method.call(this, match[1]);
+ }
+ }
+ };
+ /**
+ * Return the time encoded as Bars:Beats:Sixteenths.
+ * @return {BarsBeatsSixteenths}
+ */
+ Tone.Time.prototype.toBarsBeatsSixteenths = function () {
+ var quarterTime = this._beatsToUnits(1);
+ var quarters = this.toSeconds() / quarterTime;
+ var measures = Math.floor(quarters / this._timeSignature());
+ var sixteenths = quarters % 1 * 4;
+ quarters = Math.floor(quarters) % this._timeSignature();
+ sixteenths = sixteenths.toString();
+ if (sixteenths.length > 3) {
+ sixteenths = parseFloat(sixteenths).toFixed(3);
+ }
+ var progress = [
+ measures,
+ quarters,
+ sixteenths
+ ];
+ return progress.join(':');
+ };
+ /**
+ * Return the time in ticks.
+ * @return {Ticks}
+ */
+ Tone.Time.prototype.toTicks = function () {
+ var quarterTime = this._beatsToUnits(1);
+ var quarters = this.valueOf() / quarterTime;
+ return Math.floor(quarters * Tone.Transport.PPQ);
+ };
+ /**
+ * Return the time in samples
+ * @return {Samples}
+ */
+ Tone.Time.prototype.toSamples = function () {
+ return this.toSeconds() * this.context.sampleRate;
+ };
+ /**
+ * Return the time as a frequency value
+ * @return {Frequency}
+ * @example
+ * Tone.Time(2).toFrequency(); //0.5
+ */
+ Tone.Time.prototype.toFrequency = function () {
+ return 1 / this.toSeconds();
+ };
+ /**
+ * Return the time in seconds.
+ * @return {Seconds}
+ */
+ Tone.Time.prototype.toSeconds = function () {
+ return this.valueOf();
+ };
+ /**
+ * Return the time in milliseconds.
+ * @return {Milliseconds}
+ */
+ Tone.Time.prototype.toMilliseconds = function () {
+ return this.toSeconds() * 1000;
+ };
+ /**
+ * Return the time in seconds.
+ * @return {Seconds}
+ */
+ Tone.Time.prototype.valueOf = function () {
+ var val = this._expr();
+ return val + (this._plusNow ? this.now() : 0);
+ };
+ return Tone.Time;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.Frequency is a primitive type for encoding Frequency values.
+ * Eventually all time values are evaluated to hertz
+ * using the `eval` method.
+ * @constructor
+ * @extends {Tone.TimeBase}
+ * @param {String|Number} val The time value.
+ * @param {String=} units The units of the value.
+ * @example
+ * Tone.Frequency("C3") // 261
+ * Tone.Frequency(38, "midi") //
+ * Tone.Frequency("C3").transpose(4);
+ */
+ Tone.Frequency = function (val, units) {
+ if (this instanceof Tone.Frequency) {
+ Tone.TimeBase.call(this, val, units);
+ } else {
+ return new Tone.Frequency(val, units);
+ }
+ };
+ Tone.extend(Tone.Frequency, Tone.TimeBase);
+ ///////////////////////////////////////////////////////////////////////////
+ // AUGMENT BASE EXPRESSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ //clone the expressions so that
+ //we can add more without modifying the original
+ Tone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);
+ /*
+ * midi type primary expression
+ * @type {Object}
+ * @private
+ */
+ Tone.Frequency.prototype._primaryExpressions.midi = {
+ regexp: /^(\d+(?:\.\d+)?midi)/,
+ method: function (value) {
+ return this.midiToFrequency(value);
+ }
+ };
+ /*
+ * note type primary expression
+ * @type {Object}
+ * @private
+ */
+ Tone.Frequency.prototype._primaryExpressions.note = {
+ regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,
+ method: function (pitch, octave) {
+ var index = noteToScaleIndex[pitch.toLowerCase()];
+ var noteNumber = index + (parseInt(octave) + 1) * 12;
+ return this.midiToFrequency(noteNumber);
+ }
+ };
+ /*
+ * BeatsBarsSixteenths type primary expression
+ * @type {Object}
+ * @private
+ */
+ Tone.Frequency.prototype._primaryExpressions.tr = {
+ regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,
+ method: function (m, q, s) {
+ var total = 1;
+ if (m && m !== '0') {
+ total *= this._beatsToUnits(this._timeSignature() * parseFloat(m));
+ }
+ if (q && q !== '0') {
+ total *= this._beatsToUnits(parseFloat(q));
+ }
+ if (s && s !== '0') {
+ total *= this._beatsToUnits(parseFloat(s) / 4);
+ }
+ return total;
+ }
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // EXPRESSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Transposes the frequency by the given number of semitones.
+ * @param {Interval} interval
+ * @return {Tone.Frequency} this
+ * @example
+ * Tone.Frequency("A4").transpose(3); //"C5"
+ */
+ Tone.Frequency.prototype.transpose = function (interval) {
+ this._expr = function (expr, interval) {
+ var val = expr();
+ return val * this.intervalToFrequencyRatio(interval);
+ }.bind(this, this._expr, interval);
+ return this;
+ };
+ /**
+ * Takes an array of semitone intervals and returns
+ * an array of frequencies transposed by those intervals.
+ * @param {Array} intervals
+ * @return {Tone.Frequency} this
+ * @example
+ * Tone.Frequency("A4").harmonize([0, 3, 7]); //["A4", "C5", "E5"]
+ */
+ Tone.Frequency.prototype.harmonize = function (intervals) {
+ this._expr = function (expr, intervals) {
+ var val = expr();
+ var ret = [];
+ for (var i = 0; i < intervals.length; i++) {
+ ret[i] = val * this.intervalToFrequencyRatio(intervals[i]);
+ }
+ return ret;
+ }.bind(this, this._expr, intervals);
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // UNIT CONVERSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Return the value of the frequency as a MIDI note
+ * @return {MIDI}
+ * @example
+ * Tone.Frequency("C4").toMidi(); //60
+ */
+ Tone.Frequency.prototype.toMidi = function () {
+ return this.frequencyToMidi(this.valueOf());
+ };
+ /**
+ * Return the value of the frequency in Scientific Pitch Notation
+ * @return {Note}
+ * @example
+ * Tone.Frequency(69, "midi").toNote(); //"A4"
+ */
+ Tone.Frequency.prototype.toNote = function () {
+ var freq = this.valueOf();
+ var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;
+ var noteNumber = Math.round(12 * log) + 57;
+ var octave = Math.floor(noteNumber / 12);
+ if (octave < 0) {
+ noteNumber += -12 * octave;
+ }
+ var noteName = scaleIndexToNote[noteNumber % 12];
+ return noteName + octave.toString();
+ };
+ /**
+ * Return the duration of one cycle in seconds.
+ * @return {Seconds}
+ */
+ Tone.Frequency.prototype.toSeconds = function () {
+ return 1 / this.valueOf();
+ };
+ /**
+ * Return the value in Hertz
+ * @return {Frequency}
+ */
+ Tone.Frequency.prototype.toFrequency = function () {
+ return this.valueOf();
+ };
+ /**
+ * Return the duration of one cycle in ticks
+ * @return {Ticks}
+ */
+ Tone.Frequency.prototype.toTicks = function () {
+ var quarterTime = this._beatsToUnits(1);
+ var quarters = this.valueOf() / quarterTime;
+ return Math.floor(quarters * Tone.Transport.PPQ);
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // UNIT CONVERSIONS HELPERS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Returns the value of a frequency in the current units
+ * @param {Frequency} freq
+ * @return {Number}
+ * @private
+ */
+ Tone.Frequency.prototype._frequencyToUnits = function (freq) {
+ return freq;
+ };
+ /**
+ * Returns the value of a tick in the current time units
+ * @param {Ticks} ticks
+ * @return {Number}
+ * @private
+ */
+ Tone.Frequency.prototype._ticksToUnits = function (ticks) {
+ return 1 / (ticks * 60 / (Tone.Transport.bpm.value * Tone.Transport.PPQ));
+ };
+ /**
+ * Return the value of the beats in the current units
+ * @param {Number} beats
+ * @return {Number}
+ * @private
+ */
+ Tone.Frequency.prototype._beatsToUnits = function (beats) {
+ return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);
+ };
+ /**
+ * Returns the value of a second in the current units
+ * @param {Seconds} seconds
+ * @return {Number}
+ * @private
+ */
+ Tone.Frequency.prototype._secondsToUnits = function (seconds) {
+ return 1 / seconds;
+ };
+ /**
+ * The default units if none are given.
+ * @private
+ */
+ Tone.Frequency.prototype._defaultUnits = 'hz';
+ ///////////////////////////////////////////////////////////////////////////
+ // FREQUENCY CONVERSIONS
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Note to scale index
+ * @type {Object}
+ */
+ var noteToScaleIndex = {
+ '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
+ };
+ /**
+ * scale index to note (sharps)
+ * @type {Array}
+ */
+ var scaleIndexToNote = [
+ 'C',
+ 'C#',
+ 'D',
+ 'D#',
+ 'E',
+ 'F',
+ 'F#',
+ 'G',
+ 'G#',
+ 'A',
+ 'A#',
+ 'B'
+ ];
+ /**
+ * The [concert pitch](https://en.wikipedia.org/wiki/Concert_pitch)
+ * A4's values in Hertz.
+ * @type {Frequency}
+ * @static
+ */
+ Tone.Frequency.A4 = 440;
+ /**
+ * Convert a MIDI note to frequency value.
+ * @param {MIDI} midi The midi number to convert.
+ * @return {Frequency} the corresponding frequency value
+ * @example
+ * tone.midiToFrequency(69); // returns 440
+ */
+ Tone.Frequency.prototype.midiToFrequency = function (midi) {
+ return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);
+ };
+ /**
+ * Convert a frequency value to a MIDI note.
+ * @param {Frequency} frequency The value to frequency value to convert.
+ * @returns {MIDI}
+ * @example
+ * tone.midiToFrequency(440); // returns 69
+ */
+ Tone.Frequency.prototype.frequencyToMidi = function (frequency) {
+ return 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;
+ };
+ return Tone.Frequency;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.TransportTime is a the time along the Transport's
+ * timeline. It is similar to Tone.Time, but instead of evaluating
+ * against the AudioContext's clock, it is evaluated against
+ * the Transport's position. See [TransportTime wiki](https://github.com/Tonejs/Tone.js/wiki/TransportTime).
+ * @constructor
+ * @param {Time} val The time value as a number or string
+ * @param {String=} units Unit values
+ * @extends {Tone.Time}
+ */
+ Tone.TransportTime = function (val, units) {
+ if (this instanceof Tone.TransportTime) {
+ Tone.Time.call(this, val, units);
+ } else {
+ return new Tone.TransportTime(val, units);
+ }
+ };
+ Tone.extend(Tone.TransportTime, Tone.Time);
+ //clone the expressions so that
+ //we can add more without modifying the original
+ Tone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);
+ /**
+ * Adds an additional unary expression
+ * which quantizes values to the next subdivision
+ * @type {Object}
+ * @private
+ */
+ Tone.TransportTime.prototype._unaryExpressions.quantize = {
+ regexp: /^@/,
+ method: function (rh) {
+ var subdivision = this._secondsToTicks(rh());
+ var multiple = Math.ceil(Tone.Transport.ticks / subdivision);
+ return this._ticksToUnits(multiple * subdivision);
+ }
+ };
+ /**
+ * Convert seconds into ticks
+ * @param {Seconds} seconds
+ * @return {Ticks}
+ * @private
+ */
+ Tone.TransportTime.prototype._secondsToTicks = function (seconds) {
+ var quarterTime = this._beatsToUnits(1);
+ var quarters = seconds / quarterTime;
+ return Math.round(quarters * Tone.Transport.PPQ);
+ };
+ /**
+ * Evaluate the time expression. Returns values in ticks
+ * @return {Ticks}
+ */
+ Tone.TransportTime.prototype.valueOf = function () {
+ var val = this._secondsToTicks(this._expr());
+ return val + (this._plusNow ? Tone.Transport.ticks : 0);
+ };
+ /**
+ * Return the time in ticks.
+ * @return {Ticks}
+ */
+ Tone.TransportTime.prototype.toTicks = function () {
+ return this.valueOf();
+ };
+ /**
+ * Return the time in seconds.
+ * @return {Seconds}
+ */
+ Tone.TransportTime.prototype.toSeconds = function () {
+ var val = this._expr();
+ return val + (this._plusNow ? Tone.Transport.seconds : 0);
+ };
+ /**
+ * Return the time as a frequency value
+ * @return {Frequency}
+ */
+ Tone.TransportTime.prototype.toFrequency = function () {
+ return 1 / this.toSeconds();
+ };
+ return Tone.TransportTime;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Emitter gives classes which extend it
+ * the ability to listen for and emit events.
+ * Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).
+ * MIT (c) 2011 Jerome Etienne.
+ *
+ * @extends {Tone}
+ */
+ Tone.Emitter = function () {
+ /**
+ * Contains all of the events.
+ * @private
+ * @type {Object}
+ */
+ this._events = {};
+ };
+ Tone.extend(Tone.Emitter);
+ /**
+ * Bind a callback to a specific event.
+ * @param {String} event The name of the event to listen for.
+ * @param {Function} callback The callback to invoke when the
+ * event is emitted
+ * @return {Tone.Emitter} this
+ */
+ Tone.Emitter.prototype.on = function (event, callback) {
+ //split the event
+ var events = event.split(/\W+/);
+ for (var i = 0; i < events.length; i++) {
+ var eventName = events[i];
+ if (!this._events.hasOwnProperty(eventName)) {
+ this._events[eventName] = [];
+ }
+ this._events[eventName].push(callback);
+ }
+ return this;
+ };
+ /**
+ * Remove the event listener.
+ * @param {String} event The event to stop listening to.
+ * @param {Function=} callback The callback which was bound to
+ * the event with Tone.Emitter.on.
+ * If no callback is given, all callbacks
+ * events are removed.
+ * @return {Tone.Emitter} this
+ */
+ Tone.Emitter.prototype.off = function (event, callback) {
+ var events = event.split(/\W+/);
+ for (var ev = 0; ev < events.length; ev++) {
+ event = events[ev];
+ if (this._events.hasOwnProperty(event)) {
+ if (Tone.prototype.isUndef(callback)) {
+ this._events[event] = [];
+ } else {
+ var eventList = this._events[event];
+ for (var i = 0; i < eventList.length; i++) {
+ if (eventList[i] === callback) {
+ eventList.splice(i, 1);
+ }
+ }
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Invoke all of the callbacks bound to the event
+ * with any arguments passed in.
+ * @param {String} event The name of the event.
+ * @param {*...} args The arguments to pass to the functions listening.
+ * @return {Tone.Emitter} this
+ */
+ Tone.Emitter.prototype.emit = function (event) {
+ if (this._events) {
+ var args = Array.apply(null, arguments).slice(1);
+ if (this._events.hasOwnProperty(event)) {
+ var eventList = this._events[event];
+ for (var i = 0, len = eventList.length; i < len; i++) {
+ eventList[i].apply(this, args);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Add Emitter functions (on/off/emit) to the object
+ * @param {Object|Function} object The object or class to extend.
+ */
+ Tone.Emitter.mixin = function (object) {
+ var functions = [
+ 'on',
+ 'off',
+ 'emit'
+ ];
+ object._events = {};
+ for (var i = 0; i < functions.length; i++) {
+ var func = functions[i];
+ var emitterFunc = Tone.Emitter.prototype[func];
+ object[func] = emitterFunc;
+ }
+ };
+ /**
+ * Clean up
+ * @return {Tone.Emitter} this
+ */
+ Tone.Emitter.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._events = null;
+ return this;
+ };
+ return Tone.Emitter;
+ });
+ Module(function (Tone) {
+ /**
+ * shim
+ * @private
+ */
+ if (!window.hasOwnProperty('AudioContext') && window.hasOwnProperty('webkitAudioContext')) {
+ window.AudioContext = window.webkitAudioContext;
+ }
+ /**
+ * @class Wrapper around the native AudioContext.
+ * @extends {Tone.Emitter}
+ * @param {AudioContext=} context optionally pass in a context
+ */
+ Tone.Context = function (context) {
+ Tone.Emitter.call(this);
+ if (!context) {
+ context = new window.AudioContext();
+ }
+ this._context = context;
+ // extend all of the methods
+ for (var prop in this._context) {
+ this._defineProperty(this._context, prop);
+ }
+ ///////////////////////////////////////////////////////////////////////
+ // WORKER
+ ///////////////////////////////////////////////////////////////////////
+ /**
+ * The default latency hint
+ * @type {String}
+ * @private
+ */
+ this._latencyHint = 'interactive';
+ /**
+ * The amount of time events are scheduled
+ * into the future
+ * @type {Number}
+ * @private
+ */
+ this._lookAhead = 0.1;
+ /**
+ * How often the update look runs
+ * @type {Number}
+ * @private
+ */
+ this._updateInterval = this._lookAhead / 3;
+ /**
+ * A reference to the actual computed update interval
+ * @type {Number}
+ * @private
+ */
+ this._computedUpdateInterval = 0;
+ /**
+ * The web worker which is used to update Tone.Clock
+ * @private
+ * @type {WebWorker}
+ */
+ this._worker = this._createWorker();
+ /**
+ * An object containing all of the constants AudioBufferSourceNodes
+ * @type {Object}
+ * @private
+ */
+ this._constants = {};
+ };
+ Tone.extend(Tone.Context, Tone.Emitter);
+ Tone.Emitter.mixin(Tone.Context);
+ /**
+ * Define a property on this Tone.Context.
+ * This is used to extend the native AudioContext
+ * @param {AudioContext} context
+ * @param {String} prop
+ * @private
+ */
+ Tone.Context.prototype._defineProperty = function (context, prop) {
+ if (this.isUndef(this[prop])) {
+ Object.defineProperty(this, prop, {
+ get: function () {
+ if (typeof context[prop] === 'function') {
+ return context[prop].bind(context);
+ } else {
+ return context[prop];
+ }
+ },
+ set: function (val) {
+ context[prop] = val;
+ }
+ });
+ }
+ };
+ /**
+ * The current audio context time
+ * @return {Number}
+ */
+ Tone.Context.prototype.now = function () {
+ return this._context.currentTime;
+ };
+ /**
+ * Generate a web worker
+ * @return {WebWorker}
+ * @private
+ */
+ Tone.Context.prototype._createWorker = function () {
+ //URL Shim
+ window.URL = window.URL || window.webkitURL;
+ var blob = new Blob([//the initial timeout time
+ 'var timeoutTime = ' + (this._updateInterval * 1000).toFixed(1) + ';' + //onmessage callback
+ 'self.onmessage = function(msg){' + '\ttimeoutTime = parseInt(msg.data);' + '};' + //the tick function which posts a message
+ //and schedules a new tick
+ 'function tick(){' + '\tsetTimeout(tick, timeoutTime);' + '\tself.postMessage(\'tick\');' + '}' + //call tick initially
+ 'tick();']);
+ var blobUrl = URL.createObjectURL(blob);
+ var worker = new Worker(blobUrl);
+ worker.addEventListener('message', function () {
+ // tick the clock
+ this.emit('tick');
+ }.bind(this));
+ //lag compensation
+ worker.addEventListener('message', function () {
+ var now = this.now();
+ if (this.isNumber(this._lastUpdate)) {
+ var diff = now - this._lastUpdate;
+ this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);
+ }
+ this._lastUpdate = now;
+ }.bind(this));
+ return worker;
+ };
+ /**
+ * Generate a looped buffer at some constant value.
+ * @param {Number} val
+ * @return {BufferSourceNode}
+ */
+ Tone.Context.prototype.getConstant = function (val) {
+ if (this._constants[val]) {
+ return this._constants[val];
+ } else {
+ var buffer = this._context.createBuffer(1, 128, this._context.sampleRate);
+ var arr = buffer.getChannelData(0);
+ for (var i = 0; i < arr.length; i++) {
+ arr[i] = val;
+ }
+ var constant = this._context.createBufferSource();
+ constant.channelCount = 1;
+ constant.channelCountMode = 'explicit';
+ constant.buffer = buffer;
+ constant.loop = true;
+ constant.start(0);
+ this._constants[val] = constant;
+ return constant;
+ }
+ };
+ /**
+ * This is the time that the clock is falling behind
+ * the scheduled update interval. The Context automatically
+ * adjusts for the lag and schedules further in advance.
+ * @type {Number}
+ * @memberOf Tone.Context
+ * @name lag
+ * @static
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Context.prototype, 'lag', {
+ get: function () {
+ var diff = this._computedUpdateInterval - this._updateInterval;
+ diff = Math.max(diff, 0);
+ return diff;
+ }
+ });
+ /**
+ * The amount of time in advance that events are scheduled.
+ * The lookAhead will adjust slightly in response to the
+ * measured update time to try to avoid clicks.
+ * @type {Number}
+ * @memberOf Tone.Context
+ * @name lookAhead
+ * @static
+ */
+ Object.defineProperty(Tone.Context.prototype, 'lookAhead', {
+ get: function () {
+ return this._lookAhead;
+ },
+ set: function (lA) {
+ this._lookAhead = lA;
+ }
+ });
+ /**
+ * How often the Web Worker callback is invoked.
+ * This number corresponds to how responsive the scheduling
+ * can be. Context.updateInterval + Context.lookAhead gives you the
+ * total latency between scheduling an event and hearing it.
+ * @type {Number}
+ * @memberOf Tone.Context
+ * @name updateInterval
+ * @static
+ */
+ Object.defineProperty(Tone.Context.prototype, 'updateInterval', {
+ get: function () {
+ return this._updateInterval;
+ },
+ set: function (interval) {
+ this._updateInterval = Math.max(interval, Tone.prototype.blockTime);
+ this._worker.postMessage(Math.max(interval * 1000, 1));
+ }
+ });
+ /**
+ * The type of playback, which affects tradeoffs between audio
+ * output latency and responsiveness.
+ *
+ * In addition to setting the value in seconds, the latencyHint also
+ * accepts the strings "interactive" (prioritizes low latency),
+ * "playback" (prioritizes sustained playback), "balanced" (balances
+ * latency and performance), and "fastest" (lowest latency, might glitch more often).
+ * @type {String|Seconds}
+ * @memberOf Tone.Context#
+ * @name latencyHint
+ * @static
+ * @example
+ * //set the lookAhead to 0.3 seconds
+ * Tone.context.latencyHint = 0.3;
+ */
+ Object.defineProperty(Tone.Context.prototype, 'latencyHint', {
+ get: function () {
+ return this._latencyHint;
+ },
+ set: function (hint) {
+ var lookAhead = hint;
+ this._latencyHint = hint;
+ if (this.isString(hint)) {
+ switch (hint) {
+ case 'interactive':
+ lookAhead = 0.1;
+ this._context.latencyHint = hint;
+ break;
+ case 'playback':
+ lookAhead = 0.8;
+ this._context.latencyHint = hint;
+ break;
+ case 'balanced':
+ lookAhead = 0.25;
+ this._context.latencyHint = hint;
+ break;
+ case 'fastest':
+ lookAhead = 0.01;
+ break;
+ }
+ }
+ this.lookAhead = lookAhead;
+ this.updateInterval = lookAhead / 3;
+ }
+ });
+ /**
+ * Shim all connect/disconnect and some deprecated methods which are still in
+ * some older implementations.
+ * @private
+ */
+ function shimConnect() {
+ var nativeConnect = AudioNode.prototype.connect;
+ var nativeDisconnect = AudioNode.prototype.disconnect;
+ //replace the old connect method
+ function toneConnect(B, outNum, inNum) {
+ if (B.input) {
+ if (Array.isArray(B.input)) {
+ if (Tone.prototype.isUndef(inNum)) {
+ inNum = 0;
+ }
+ this.connect(B.input[inNum]);
+ } else {
+ this.connect(B.input, outNum, inNum);
+ }
+ } else {
+ try {
+ if (B instanceof AudioNode) {
+ nativeConnect.call(this, B, outNum, inNum);
+ } else {
+ nativeConnect.call(this, B, outNum);
+ }
+ } catch (e) {
+ throw new Error('error connecting to node: ' + B + '\n' + e);
+ }
+ }
+ }
+ //replace the old disconnect method
+ function toneDisconnect(B, outNum, inNum) {
+ if (B && B.input && Array.isArray(B.input)) {
+ if (Tone.prototype.isUndef(inNum)) {
+ inNum = 0;
+ }
+ this.disconnect(B.input[inNum], outNum, inNum);
+ } else if (B && B.input) {
+ this.disconnect(B.input, outNum, inNum);
+ } else {
+ try {
+ nativeDisconnect.apply(this, arguments);
+ } catch (e) {
+ throw new Error('error disconnecting node: ' + B + '\n' + e);
+ }
+ }
+ }
+ if (AudioNode.prototype.connect !== toneConnect) {
+ AudioNode.prototype.connect = toneConnect;
+ AudioNode.prototype.disconnect = toneDisconnect;
+ }
+ }
+ // set the audio context initially
+ if (Tone.supported) {
+ shimConnect();
+ Tone.context = new Tone.Context();
+ } else {
+ console.warn('This browser does not support Tone.js');
+ }
+ return Tone.Context;
+ });
+ Module(function (Tone) {
+ ///////////////////////////////////////////////////////////////////////////
+ // TYPES
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Units which a value can take on.
+ * @enum {String}
+ */
+ Tone.Type = {
+ /**
+ * Default units
+ * @typedef {Default}
+ */
+ Default: 'number',
+ /**
+ * Time can be described in a number of ways. Read more [Time](https://github.com/Tonejs/Tone.js/wiki/Time).
+ *
+ * <ul>
+ * <li>Numbers, which will be taken literally as the time (in seconds).</li>
+ * <li>Notation, ("4n", "8t") describes time in BPM and time signature relative values.</li>
+ * <li>TransportTime, ("4:3:2") will also provide tempo and time signature relative times
+ * in the form BARS:QUARTERS:SIXTEENTHS.</li>
+ * <li>Frequency, ("8hz") is converted to the length of the cycle in seconds.</li>
+ * <li>Now-Relative, ("+1") prefix any of the above with "+" and it will be interpreted as
+ * "the current time plus whatever expression follows".</li>
+ * <li>Expressions, ("3:0 + 2 - (1m / 7)") any of the above can also be combined
+ * into a mathematical expression which will be evaluated to compute the desired time.</li>
+ * <li>No Argument, for methods which accept time, no argument will be interpreted as
+ * "now" (i.e. the currentTime).</li>
+ * </ul>
+ *
+ * @typedef {Time}
+ */
+ Time: 'time',
+ /**
+ * Frequency can be described similar to time, except ultimately the
+ * values are converted to frequency instead of seconds. A number
+ * is taken literally as the value in hertz. Additionally any of the
+ * Time encodings can be used. Note names in the form
+ * of NOTE OCTAVE (i.e. C4) are also accepted and converted to their
+ * frequency value.
+ * @typedef {Frequency}
+ */
+ Frequency: 'frequency',
+ /**
+ * TransportTime describes a position along the Transport's timeline. It is
+ * similar to Time in that it uses all the same encodings, but TransportTime specifically
+ * pertains to the Transport's timeline, which is startable, stoppable, loopable, and seekable.
+ * [Read more](https://github.com/Tonejs/Tone.js/wiki/TransportTime)
+ * @typedef {TransportTime}
+ */
+ TransportTime: 'transportTime',
+ /**
+ * Ticks are the basic subunit of the Transport. They are
+ * the smallest unit of time that the Transport supports.
+ * @typedef {Ticks}
+ */
+ Ticks: 'ticks',
+ /**
+ * Normal values are within the range [0, 1].
+ * @typedef {NormalRange}
+ */
+ NormalRange: 'normalRange',
+ /**
+ * AudioRange values are between [-1, 1].
+ * @typedef {AudioRange}
+ */
+ AudioRange: 'audioRange',
+ /**
+ * Decibels are a logarithmic unit of measurement which is useful for volume
+ * because of the logarithmic way that we perceive loudness. 0 decibels
+ * means no change in volume. -10db is approximately half as loud and 10db
+ * is twice is loud.
+ * @typedef {Decibels}
+ */
+ Decibels: 'db',
+ /**
+ * Half-step note increments, i.e. 12 is an octave above the root. and 1 is a half-step up.
+ * @typedef {Interval}
+ */
+ Interval: 'interval',
+ /**
+ * Beats per minute.
+ * @typedef {BPM}
+ */
+ BPM: 'bpm',
+ /**
+ * The value must be greater than or equal to 0.
+ * @typedef {Positive}
+ */
+ Positive: 'positive',
+ /**
+ * A cent is a hundredth of a semitone.
+ * @typedef {Cents}
+ */
+ Cents: 'cents',
+ /**
+ * Angle between 0 and 360.
+ * @typedef {Degrees}
+ */
+ Degrees: 'degrees',
+ /**
+ * A number representing a midi note.
+ * @typedef {MIDI}
+ */
+ MIDI: 'midi',
+ /**
+ * A colon-separated representation of time in the form of
+ * Bars:Beats:Sixteenths.
+ * @typedef {BarsBeatsSixteenths}
+ */
+ BarsBeatsSixteenths: 'barsBeatsSixteenths',
+ /**
+ * Sampling is the reduction of a continuous signal to a discrete signal.
+ * Audio is typically sampled 44100 times per second.
+ * @typedef {Samples}
+ */
+ Samples: 'samples',
+ /**
+ * Hertz are a frequency representation defined as one cycle per second.
+ * @typedef {Hertz}
+ */
+ Hertz: 'hertz',
+ /**
+ * A frequency represented by a letter name,
+ * accidental and octave. This system is known as
+ * [Scientific Pitch Notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation).
+ * @typedef {Note}
+ */
+ Note: 'note',
+ /**
+ * One millisecond is a thousandth of a second.
+ * @typedef {Milliseconds}
+ */
+ Milliseconds: 'milliseconds',
+ /**
+ * Seconds are the time unit of the AudioContext. In the end,
+ * all values need to be evaluated to seconds.
+ * @typedef {Seconds}
+ */
+ Seconds: 'seconds',
+ /**
+ * A string representing a duration relative to a measure.
+ * <ul>
+ * <li>"4n" = quarter note</li>
+ * <li>"2m" = two measures</li>
+ * <li>"8t" = eighth-note triplet</li>
+ * </ul>
+ * @typedef {Notation}
+ */
+ Notation: 'notation'
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // AUGMENT TONE's PROTOTYPE
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Convert Time into seconds.
+ *
+ * Unlike the method which it overrides, this takes into account
+ * transporttime and musical notation.
+ *
+ * Time : 1.40
+ * Notation: 4n|1m|2t
+ * Now Relative: +3n
+ * Math: 3n+16n or even complicated expressions ((3n*2)/6 + 1)
+ *
+ * @param {Time} time
+ * @return {Seconds}
+ */
+ Tone.prototype.toSeconds = function (time) {
+ if (this.isNumber(time)) {
+ return time;
+ } else if (this.isUndef(time)) {
+ return this.now();
+ } else if (this.isString(time)) {
+ return new Tone.Time(time).toSeconds();
+ } else if (time instanceof Tone.TimeBase) {
+ return time.toSeconds();
+ }
+ };
+ /**
+ * Convert a frequency representation into a number.
+ * @param {Frequency} freq
+ * @return {Hertz} the frequency in hertz
+ */
+ Tone.prototype.toFrequency = function (freq) {
+ if (this.isNumber(freq)) {
+ return freq;
+ } else if (this.isString(freq) || this.isUndef(freq)) {
+ return new Tone.Frequency(freq).valueOf();
+ } else if (freq instanceof Tone.TimeBase) {
+ return freq.toFrequency();
+ }
+ };
+ /**
+ * Convert a time representation into ticks.
+ * @param {Time} time
+ * @return {Ticks} the time in ticks
+ */
+ Tone.prototype.toTicks = function (time) {
+ if (this.isNumber(time) || this.isString(time)) {
+ return new Tone.TransportTime(time).toTicks();
+ } else if (this.isUndef(time)) {
+ return Tone.Transport.ticks;
+ } else if (time instanceof Tone.TimeBase) {
+ return time.toTicks();
+ }
+ };
+ return Tone;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Param wraps the native Web Audio's AudioParam to provide
+ * additional unit conversion functionality. It also
+ * serves as a base-class for classes which have a single,
+ * automatable parameter.
+ * @extends {Tone}
+ * @param {AudioParam} param The parameter to wrap.
+ * @param {Tone.Type} units The units of the audio param.
+ * @param {Boolean} convert If the param should be converted.
+ */
+ Tone.Param = function () {
+ var options = this.optionsObject(arguments, [
+ 'param',
+ 'units',
+ 'convert'
+ ], Tone.Param.defaults);
+ /**
+ * The native parameter to control
+ * @type {AudioParam}
+ * @private
+ */
+ this._param = this.input = options.param;
+ /**
+ * The units of the parameter
+ * @type {Tone.Type}
+ */
+ this.units = options.units;
+ /**
+ * If the value should be converted or not
+ * @type {Boolean}
+ */
+ this.convert = options.convert;
+ /**
+ * True if the signal value is being overridden by
+ * a connected signal.
+ * @readOnly
+ * @type {boolean}
+ * @private
+ */
+ this.overridden = false;
+ /**
+ * If there is an LFO, this is where it is held.
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfo = null;
+ if (this.isObject(options.lfo)) {
+ this.value = options.lfo;
+ } else if (!this.isUndef(options.value)) {
+ this.value = options.value;
+ }
+ };
+ Tone.extend(Tone.Param);
+ /**
+ * Defaults
+ * @type {Object}
+ * @const
+ */
+ Tone.Param.defaults = {
+ 'units': Tone.Type.Default,
+ 'convert': true,
+ 'param': undefined
+ };
+ /**
+ * The current value of the parameter.
+ * @memberOf Tone.Param#
+ * @type {Number}
+ * @name value
+ */
+ Object.defineProperty(Tone.Param.prototype, 'value', {
+ get: function () {
+ return this._toUnits(this._param.value);
+ },
+ set: function (value) {
+ if (this.isObject(value)) {
+ //throw an error if the LFO needs to be included
+ if (this.isUndef(Tone.LFO)) {
+ throw new Error('Include \'Tone.LFO\' to use an LFO as a Param value.');
+ }
+ //remove the old one
+ if (this._lfo) {
+ this._lfo.dispose();
+ }
+ this._lfo = new Tone.LFO(value).start();
+ this._lfo.connect(this.input);
+ } else {
+ var convertedVal = this._fromUnits(value);
+ this._param.cancelScheduledValues(0);
+ this._param.value = convertedVal;
+ }
+ }
+ });
+ /**
+ * Convert the given value from the type specified by Tone.Param.units
+ * into the destination value (such as Gain or Frequency).
+ * @private
+ * @param {*} val the value to convert
+ * @return {number} the number which the value should be set to
+ */
+ Tone.Param.prototype._fromUnits = function (val) {
+ if (this.convert || this.isUndef(this.convert)) {
+ switch (this.units) {
+ case Tone.Type.Time:
+ return this.toSeconds(val);
+ case Tone.Type.Frequency:
+ return this.toFrequency(val);
+ case Tone.Type.Decibels:
+ return this.dbToGain(val);
+ case Tone.Type.NormalRange:
+ return Math.min(Math.max(val, 0), 1);
+ case Tone.Type.AudioRange:
+ return Math.min(Math.max(val, -1), 1);
+ case Tone.Type.Positive:
+ return Math.max(val, 0);
+ default:
+ return val;
+ }
+ } else {
+ return val;
+ }
+ };
+ /**
+ * Convert the parameters value into the units specified by Tone.Param.units.
+ * @private
+ * @param {number} val the value to convert
+ * @return {number}
+ */
+ Tone.Param.prototype._toUnits = function (val) {
+ if (this.convert || this.isUndef(this.convert)) {
+ switch (this.units) {
+ case Tone.Type.Decibels:
+ return this.gainToDb(val);
+ default:
+ return val;
+ }
+ } else {
+ return val;
+ }
+ };
+ /**
+ * the minimum output value
+ * @type {Number}
+ * @private
+ */
+ Tone.Param.prototype._minOutput = 0.00001;
+ /**
+ * Schedules a parameter value change at the given time.
+ * @param {*} value The value to set the signal.
+ * @param {Time} time The time when the change should occur.
+ * @returns {Tone.Param} this
+ * @example
+ * //set the frequency to "G4" in exactly 1 second from now.
+ * freq.setValueAtTime("G4", "+1");
+ */
+ Tone.Param.prototype.setValueAtTime = function (value, time) {
+ value = this._fromUnits(value);
+ time = this.toSeconds(time);
+ if (time <= this.now() + this.blockTime) {
+ this._param.value = value;
+ } else {
+ this._param.setValueAtTime(value, time);
+ }
+ return this;
+ };
+ /**
+ * Creates a schedule point with the current value at the current time.
+ * This is useful for creating an automation anchor point in order to
+ * schedule changes from the current value.
+ *
+ * @param {number=} now (Optionally) pass the now value in.
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.setRampPoint = function (now) {
+ now = this.defaultArg(now, this.now());
+ var currentVal = this._param.value;
+ // exponentialRampToValueAt cannot ever ramp from or to 0
+ // More info: https://bugzilla.mozilla.org/show_bug.cgi?id=1125600#c2
+ if (currentVal === 0) {
+ currentVal = this._minOutput;
+ }
+ this._param.setValueAtTime(currentVal, now);
+ return this;
+ };
+ /**
+ * Schedules a linear continuous change in parameter value from the
+ * previous scheduled parameter value to the given value.
+ *
+ * @param {number} value
+ * @param {Time} endTime
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) {
+ value = this._fromUnits(value);
+ this._param.linearRampToValueAtTime(value, this.toSeconds(endTime));
+ return this;
+ };
+ /**
+ * Schedules an exponential continuous change in parameter value from
+ * the previous scheduled parameter value to the given value.
+ *
+ * @param {number} value
+ * @param {Time} endTime
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.exponentialRampToValueAtTime = function (value, endTime) {
+ value = this._fromUnits(value);
+ value = Math.max(this._minOutput, value);
+ this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));
+ return this;
+ };
+ /**
+ * Schedules an exponential continuous change in parameter value from
+ * the current time and current value to the given value over the
+ * duration of the rampTime.
+ *
+ * @param {number} value The value to ramp to.
+ * @param {Time} rampTime the time that it takes the
+ * value to ramp from it's current value
+ * @param {Time} [startTime=now] When the ramp should start.
+ * @returns {Tone.Param} this
+ * @example
+ * //exponentially ramp to the value 2 over 4 seconds.
+ * signal.exponentialRampToValue(2, 4);
+ */
+ Tone.Param.prototype.exponentialRampToValue = function (value, rampTime, startTime) {
+ startTime = this.toSeconds(startTime);
+ this.setRampPoint(startTime);
+ this.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));
+ return this;
+ };
+ /**
+ * Schedules an linear continuous change in parameter value from
+ * the current time and current value to the given value over the
+ * duration of the rampTime.
+ *
+ * @param {number} value The value to ramp to.
+ * @param {Time} rampTime the time that it takes the
+ * value to ramp from it's current value
+ * @param {Time} [startTime=now] When the ramp should start.
+ * @returns {Tone.Param} this
+ * @example
+ * //linearly ramp to the value 4 over 3 seconds.
+ * signal.linearRampToValue(4, 3);
+ */
+ Tone.Param.prototype.linearRampToValue = function (value, rampTime, startTime) {
+ startTime = this.toSeconds(startTime);
+ this.setRampPoint(startTime);
+ this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));
+ return this;
+ };
+ /**
+ * Start exponentially approaching the target value at the given time with
+ * a rate having the given time constant.
+ * @param {number} value
+ * @param {Time} startTime
+ * @param {number} timeConstant
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.setTargetAtTime = function (value, startTime, timeConstant) {
+ value = this._fromUnits(value);
+ // The value will never be able to approach without timeConstant > 0.
+ // http://www.w3.org/TR/webaudio/#dfn-setTargetAtTime, where the equation
+ // is described. 0 results in a division by 0.
+ value = Math.max(this._minOutput, value);
+ timeConstant = Math.max(this._minOutput, timeConstant);
+ this._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);
+ return this;
+ };
+ /**
+ * Sets an array of arbitrary parameter values starting at the given time
+ * for the given duration.
+ *
+ * @param {Array} values
+ * @param {Time} startTime
+ * @param {Time} duration
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.setValueCurveAtTime = function (values, startTime, duration) {
+ for (var i = 0; i < values.length; i++) {
+ values[i] = this._fromUnits(values[i]);
+ }
+ this._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));
+ return this;
+ };
+ /**
+ * Cancels all scheduled parameter changes with times greater than or
+ * equal to startTime.
+ *
+ * @param {Time} startTime
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.cancelScheduledValues = function (startTime) {
+ this._param.cancelScheduledValues(this.toSeconds(startTime));
+ return this;
+ };
+ /**
+ * Ramps to the given value over the duration of the rampTime.
+ * Automatically selects the best ramp type (exponential or linear)
+ * depending on the `units` of the signal
+ *
+ * @param {number} value
+ * @param {Time} rampTime The time that it takes the
+ * value to ramp from it's current value
+ * @param {Time} [startTime=now] When the ramp should start.
+ * @returns {Tone.Param} this
+ * @example
+ * //ramp to the value either linearly or exponentially
+ * //depending on the "units" value of the signal
+ * signal.rampTo(0, 10);
+ * @example
+ * //schedule it to ramp starting at a specific time
+ * signal.rampTo(0, 10, 5)
+ */
+ Tone.Param.prototype.rampTo = function (value, rampTime, startTime) {
+ rampTime = this.defaultArg(rampTime, 0);
+ if (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels) {
+ this.exponentialRampToValue(value, rampTime, startTime);
+ } else {
+ this.linearRampToValue(value, rampTime, startTime);
+ }
+ return this;
+ };
+ /**
+ * The LFO created by the signal instance. If none
+ * was created, this is null.
+ * @type {Tone.LFO}
+ * @readOnly
+ * @memberOf Tone.Param#
+ * @name lfo
+ */
+ Object.defineProperty(Tone.Param.prototype, 'lfo', {
+ get: function () {
+ return this._lfo;
+ }
+ });
+ /**
+ * Clean up
+ * @returns {Tone.Param} this
+ */
+ Tone.Param.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._param = null;
+ if (this._lfo) {
+ this._lfo.dispose();
+ this._lfo = null;
+ }
+ return this;
+ };
+ return Tone.Param;
+ });
+ Module(function (Tone) {
+
+ /**
+ * createGain shim
+ * @private
+ */
+ if (window.GainNode && !AudioContext.prototype.createGain) {
+ AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;
+ }
+ /**
+ * @class A thin wrapper around the Native Web Audio GainNode.
+ * The GainNode is a basic building block of the Web Audio
+ * API and is useful for routing audio and adjusting gains.
+ * @extends {Tone}
+ * @param {Number=} gain The initial gain of the GainNode
+ * @param {Tone.Type=} units The units of the gain parameter.
+ */
+ Tone.Gain = function () {
+ var options = this.optionsObject(arguments, [
+ 'gain',
+ 'units'
+ ], Tone.Gain.defaults);
+ /**
+ * The GainNode
+ * @type {GainNode}
+ * @private
+ */
+ this.input = this.output = this._gainNode = this.context.createGain();
+ /**
+ * The gain parameter of the gain node.
+ * @type {Tone.Param}
+ * @signal
+ */
+ this.gain = new Tone.Param({
+ 'param': this._gainNode.gain,
+ 'units': options.units,
+ 'value': options.gain,
+ 'convert': options.convert
+ });
+ this._readOnly('gain');
+ };
+ Tone.extend(Tone.Gain);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.Gain.defaults = {
+ 'gain': 1,
+ 'convert': true
+ };
+ /**
+ * Clean up.
+ * @return {Tone.Gain} this
+ */
+ Tone.Gain.prototype.dispose = function () {
+ Tone.Param.prototype.dispose.call(this);
+ this._gainNode.disconnect();
+ this._gainNode = null;
+ this._writable('gain');
+ this.gain.dispose();
+ this.gain = null;
+ };
+ //STATIC///////////////////////////////////////////////////////////////////
+ /**
+ * Create input and outputs for this object.
+ * @param {Number} input The number of inputs
+ * @param {Number=} outputs The number of outputs
+ * @return {Tone} this
+ * @internal
+ */
+ Tone.prototype.createInsOuts = function (inputs, outputs) {
+ if (inputs === 1) {
+ this.input = new Tone.Gain();
+ } else if (inputs > 1) {
+ this.input = new Array(inputs);
+ }
+ if (outputs === 1) {
+ this.output = new Tone.Gain();
+ } else if (outputs > 1) {
+ this.output = new Array(inputs);
+ }
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ return Tone.Gain;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A signal is an audio-rate value. Tone.Signal is a core component of the library.
+ * Unlike a number, Signals can be scheduled with sample-level accuracy. Tone.Signal
+ * has all of the methods available to native Web Audio
+ * [AudioParam](http://webaudio.github.io/web-audio-api/#the-audioparam-interface)
+ * as well as additional conveniences. Read more about working with signals
+ * [here](https://github.com/Tonejs/Tone.js/wiki/Signals).
+ *
+ * @constructor
+ * @extends {Tone.Param}
+ * @param {Number|AudioParam} [value] Initial value of the signal. If an AudioParam
+ * is passed in, that parameter will be wrapped
+ * and controlled by the Signal.
+ * @param {string} [units=Number] unit The units the signal is in.
+ * @example
+ * var signal = new Tone.Signal(10);
+ */
+ Tone.Signal = function () {
+ var options = this.optionsObject(arguments, [
+ 'value',
+ 'units'
+ ], Tone.Signal.defaults);
+ /**
+ * The node where the constant signal value is scaled.
+ * @type {GainNode}
+ * @private
+ */
+ this.output = this._gain = this.context.createGain();
+ options.param = this._gain.gain;
+ Tone.Param.call(this, options);
+ /**
+ * The node where the value is set.
+ * @type {Tone.Param}
+ * @private
+ */
+ this.input = this._param = this._gain.gain;
+ //connect the const output to the node output
+ this.context.getConstant(1).chain(this._gain);
+ };
+ Tone.extend(Tone.Signal, Tone.Param);
+ /**
+ * The default values
+ * @type {Object}
+ * @static
+ * @const
+ */
+ Tone.Signal.defaults = {
+ 'value': 0,
+ 'units': Tone.Type.Default,
+ 'convert': true
+ };
+ /**
+ * When signals connect to other signals or AudioParams,
+ * they take over the output value of that signal or AudioParam.
+ * For all other nodes, the behavior is the same as a default <code>connect</code>.
+ *
+ * @override
+ * @param {AudioParam|AudioNode|Tone.Signal|Tone} node
+ * @param {number} [outputNumber=0] The output number to connect from.
+ * @param {number} [inputNumber=0] The input number to connect to.
+ * @returns {Tone.SignalBase} this
+ * @method
+ */
+ Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;
+ /**
+ * dispose and disconnect
+ * @returns {Tone.Signal} this
+ */
+ Tone.Signal.prototype.dispose = function () {
+ Tone.Param.prototype.dispose.call(this);
+ this._param = null;
+ this._gain.disconnect();
+ this._gain = null;
+ return this;
+ };
+ return Tone.Signal;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A Timeline class for scheduling and maintaining state
+ * along a timeline. All events must have a "time" property.
+ * Internally, events are stored in time order for fast
+ * retrieval.
+ * @extends {Tone}
+ * @param {Positive} [memory=Infinity] The number of previous events that are retained.
+ */
+ Tone.Timeline = function () {
+ var options = this.optionsObject(arguments, ['memory'], Tone.Timeline.defaults);
+ /**
+ * The array of scheduled timeline events
+ * @type {Array}
+ * @private
+ */
+ this._timeline = [];
+ /**
+ * An array of items to remove from the list.
+ * @type {Array}
+ * @private
+ */
+ this._toRemove = [];
+ /**
+ * Flag if the tieline is mid iteration
+ * @private
+ * @type {Boolean}
+ */
+ this._iterating = false;
+ /**
+ * The memory of the timeline, i.e.
+ * how many events in the past it will retain
+ * @type {Positive}
+ */
+ this.memory = options.memory;
+ };
+ Tone.extend(Tone.Timeline);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ */
+ Tone.Timeline.defaults = { 'memory': Infinity };
+ /**
+ * The number of items in the timeline.
+ * @type {Number}
+ * @memberOf Tone.Timeline#
+ * @name length
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Timeline.prototype, 'length', {
+ get: function () {
+ return this._timeline.length;
+ }
+ });
+ /**
+ * Insert an event object onto the timeline. Events must have a "time" attribute.
+ * @param {Object} event The event object to insert into the
+ * timeline.
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.add = function (event) {
+ //the event needs to have a time attribute
+ if (this.isUndef(event.time)) {
+ throw new Error('Tone.Timeline: events must have a time attribute');
+ }
+ if (this._timeline.length) {
+ var index = this._search(event.time);
+ this._timeline.splice(index + 1, 0, event);
+ } else {
+ this._timeline.push(event);
+ }
+ //if the length is more than the memory, remove the previous ones
+ if (this.length > this.memory) {
+ var diff = this.length - this.memory;
+ this._timeline.splice(0, diff);
+ }
+ return this;
+ };
+ /**
+ * Remove an event from the timeline.
+ * @param {Object} event The event object to remove from the list.
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.remove = function (event) {
+ if (this._iterating) {
+ this._toRemove.push(event);
+ } else {
+ var index = this._timeline.indexOf(event);
+ if (index !== -1) {
+ this._timeline.splice(index, 1);
+ }
+ }
+ return this;
+ };
+ /**
+ * Get the nearest event whose time is less than or equal to the given time.
+ * @param {Number} time The time to query.
+ * @returns {Object} The event object set after that time.
+ */
+ Tone.Timeline.prototype.get = function (time) {
+ var index = this._search(time);
+ if (index !== -1) {
+ return this._timeline[index];
+ } else {
+ return null;
+ }
+ };
+ /**
+ * Return the first event in the timeline without removing it
+ * @returns {Object} The first event object
+ */
+ Tone.Timeline.prototype.peek = function () {
+ return this._timeline[0];
+ };
+ /**
+ * Return the first event in the timeline and remove it
+ * @returns {Object} The first event object
+ */
+ Tone.Timeline.prototype.shift = function () {
+ return this._timeline.shift();
+ };
+ /**
+ * Get the event which is scheduled after the given time.
+ * @param {Number} time The time to query.
+ * @returns {Object} The event object after the given time
+ */
+ Tone.Timeline.prototype.getAfter = function (time) {
+ var index = this._search(time);
+ if (index + 1 < this._timeline.length) {
+ return this._timeline[index + 1];
+ } else {
+ return null;
+ }
+ };
+ /**
+ * Get the event before the event at the given time.
+ * @param {Number} time The time to query.
+ * @returns {Object} The event object before the given time
+ */
+ Tone.Timeline.prototype.getBefore = function (time) {
+ var len = this._timeline.length;
+ //if it's after the last item, return the last item
+ if (len > 0 && this._timeline[len - 1].time < time) {
+ return this._timeline[len - 1];
+ }
+ var index = this._search(time);
+ if (index - 1 >= 0) {
+ return this._timeline[index - 1];
+ } else {
+ return null;
+ }
+ };
+ /**
+ * Cancel events after the given time
+ * @param {Number} time The time to query.
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.cancel = function (after) {
+ if (this._timeline.length > 1) {
+ var index = this._search(after);
+ if (index >= 0) {
+ if (this._timeline[index].time === after) {
+ //get the first item with that time
+ for (var i = index; i >= 0; i--) {
+ if (this._timeline[i].time === after) {
+ index = i;
+ } else {
+ break;
+ }
+ }
+ this._timeline = this._timeline.slice(0, index);
+ } else {
+ this._timeline = this._timeline.slice(0, index + 1);
+ }
+ } else {
+ this._timeline = [];
+ }
+ } else if (this._timeline.length === 1) {
+ //the first item's time
+ if (this._timeline[0].time >= after) {
+ this._timeline = [];
+ }
+ }
+ return this;
+ };
+ /**
+ * Cancel events before or equal to the given time.
+ * @param {Number} time The time to cancel before.
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.cancelBefore = function (time) {
+ if (this._timeline.length) {
+ var index = this._search(time);
+ if (index >= 0) {
+ this._timeline = this._timeline.slice(index + 1);
+ }
+ }
+ return this;
+ };
+ /**
+ * Does a binary serach on the timeline array and returns the
+ * nearest event index whose time is after or equal to the given time.
+ * If a time is searched before the first index in the timeline, -1 is returned.
+ * If the time is after the end, the index of the last item is returned.
+ * @param {Number} time
+ * @return {Number} the index in the timeline array
+ * @private
+ */
+ Tone.Timeline.prototype._search = function (time) {
+ var beginning = 0;
+ var len = this._timeline.length;
+ var end = len;
+ if (len > 0 && this._timeline[len - 1].time <= time) {
+ return len - 1;
+ }
+ while (beginning < end) {
+ // calculate the midpoint for roughly equal partition
+ var midPoint = Math.floor(beginning + (end - beginning) / 2);
+ var event = this._timeline[midPoint];
+ var nextEvent = this._timeline[midPoint + 1];
+ if (event.time === time) {
+ //choose the last one that has the same time
+ for (var i = midPoint; i < this._timeline.length; i++) {
+ var testEvent = this._timeline[i];
+ if (testEvent.time === time) {
+ midPoint = i;
+ }
+ }
+ return midPoint;
+ } else if (event.time < time && nextEvent.time > time) {
+ return midPoint;
+ } else if (event.time > time) {
+ //search lower
+ end = midPoint;
+ } else if (event.time < time) {
+ //search upper
+ beginning = midPoint + 1;
+ }
+ }
+ return -1;
+ };
+ /**
+ * Internal iterator. Applies extra safety checks for
+ * removing items from the array.
+ * @param {Function} callback
+ * @param {Number=} lowerBound
+ * @param {Number=} upperBound
+ * @private
+ */
+ Tone.Timeline.prototype._iterate = function (callback, lowerBound, upperBound) {
+ this._iterating = true;
+ lowerBound = this.defaultArg(lowerBound, 0);
+ upperBound = this.defaultArg(upperBound, this._timeline.length - 1);
+ for (var i = lowerBound; i <= upperBound; i++) {
+ callback(this._timeline[i]);
+ }
+ this._iterating = false;
+ if (this._toRemove.length > 0) {
+ for (var j = 0; j < this._toRemove.length; j++) {
+ var index = this._timeline.indexOf(this._toRemove[j]);
+ if (index !== -1) {
+ this._timeline.splice(index, 1);
+ }
+ }
+ this._toRemove = [];
+ }
+ };
+ /**
+ * Iterate over everything in the array
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.forEach = function (callback) {
+ this._iterate(callback);
+ return this;
+ };
+ /**
+ * Iterate over everything in the array at or before the given time.
+ * @param {Number} time The time to check if items are before
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.forEachBefore = function (time, callback) {
+ //iterate over the items in reverse so that removing an item doesn't break things
+ var upperBound = this._search(time);
+ if (upperBound !== -1) {
+ this._iterate(callback, 0, upperBound);
+ }
+ return this;
+ };
+ /**
+ * Iterate over everything in the array after the given time.
+ * @param {Number} time The time to check if items are before
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.forEachAfter = function (time, callback) {
+ //iterate over the items in reverse so that removing an item doesn't break things
+ var lowerBound = this._search(time);
+ this._iterate(callback, lowerBound + 1);
+ return this;
+ };
+ /**
+ * Iterate over everything in the array at or after the given time. Similar to
+ * forEachAfter, but includes the item(s) at the given time.
+ * @param {Number} time The time to check if items are before
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.forEachFrom = function (time, callback) {
+ //iterate over the items in reverse so that removing an item doesn't break things
+ var lowerBound = this._search(time);
+ //work backwards until the event time is less than time
+ while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) {
+ lowerBound--;
+ }
+ this._iterate(callback, lowerBound + 1);
+ return this;
+ };
+ /**
+ * Iterate over everything in the array at the given time
+ * @param {Number} time The time to check if items are before
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.forEachAtTime = function (time, callback) {
+ //iterate over the items in reverse so that removing an item doesn't break things
+ var upperBound = this._search(time);
+ if (upperBound !== -1) {
+ this._iterate(function (event) {
+ if (event.time === time) {
+ callback(event);
+ }
+ }, 0, upperBound);
+ }
+ return this;
+ };
+ /**
+ * Clean up.
+ * @return {Tone.Timeline} this
+ */
+ Tone.Timeline.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._timeline = null;
+ this._toRemove = null;
+ };
+ return Tone.Timeline;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A signal which adds the method getValueAtTime.
+ * Code and inspiration from https://github.com/jsantell/web-audio-automation-timeline
+ * @extends {Tone.Param}
+ * @param {Number=} value The initial value of the signal
+ * @param {String=} units The conversion units of the signal.
+ */
+ Tone.TimelineSignal = function () {
+ var options = this.optionsObject(arguments, [
+ 'value',
+ 'units'
+ ], Tone.Signal.defaults);
+ /**
+ * The scheduled events
+ * @type {Tone.Timeline}
+ * @private
+ */
+ this._events = new Tone.Timeline(10);
+ //constructors
+ Tone.Signal.apply(this, options);
+ options.param = this._param;
+ Tone.Param.call(this, options);
+ /**
+ * The initial scheduled value
+ * @type {Number}
+ * @private
+ */
+ this._initial = this._fromUnits(this._param.value);
+ };
+ Tone.extend(Tone.TimelineSignal, Tone.Param);
+ /**
+ * The event types of a schedulable signal.
+ * @enum {String}
+ * @private
+ */
+ Tone.TimelineSignal.Type = {
+ Linear: 'linear',
+ Exponential: 'exponential',
+ Target: 'target',
+ Curve: 'curve',
+ Set: 'set'
+ };
+ /**
+ * The current value of the signal.
+ * @memberOf Tone.TimelineSignal#
+ * @type {Number}
+ * @name value
+ */
+ Object.defineProperty(Tone.TimelineSignal.prototype, 'value', {
+ get: function () {
+ var now = this.now();
+ var val = this.getValueAtTime(now);
+ return this._toUnits(val);
+ },
+ set: function (value) {
+ var convertedVal = this._fromUnits(value);
+ this._initial = convertedVal;
+ this.cancelScheduledValues();
+ this._param.value = convertedVal;
+ }
+ });
+ ///////////////////////////////////////////////////////////////////////////
+ // SCHEDULING
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Schedules a parameter value change at the given time.
+ * @param {*} value The value to set the signal.
+ * @param {Time} time The time when the change should occur.
+ * @returns {Tone.TimelineSignal} this
+ * @example
+ * //set the frequency to "G4" in exactly 1 second from now.
+ * freq.setValueAtTime("G4", "+1");
+ */
+ Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {
+ value = this._fromUnits(value);
+ startTime = this.toSeconds(startTime);
+ this._events.add({
+ 'type': Tone.TimelineSignal.Type.Set,
+ 'value': value,
+ 'time': startTime
+ });
+ //invoke the original event
+ this._param.setValueAtTime(value, startTime);
+ return this;
+ };
+ /**
+ * Schedules a linear continuous change in parameter value from the
+ * previous scheduled parameter value to the given value.
+ *
+ * @param {number} value
+ * @param {Time} endTime
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {
+ value = this._fromUnits(value);
+ endTime = this.toSeconds(endTime);
+ this._events.add({
+ 'type': Tone.TimelineSignal.Type.Linear,
+ 'value': value,
+ 'time': endTime
+ });
+ this._param.linearRampToValueAtTime(value, endTime);
+ return this;
+ };
+ /**
+ * Schedules an exponential continuous change in parameter value from
+ * the previous scheduled parameter value to the given value.
+ *
+ * @param {number} value
+ * @param {Time} endTime
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {
+ //get the previous event and make sure it's not starting from 0
+ endTime = this.toSeconds(endTime);
+ var beforeEvent = this._searchBefore(endTime);
+ if (beforeEvent && beforeEvent.value === 0) {
+ //reschedule that event
+ this.setValueAtTime(this._minOutput, beforeEvent.time);
+ }
+ value = this._fromUnits(value);
+ var setValue = Math.max(value, this._minOutput);
+ this._events.add({
+ 'type': Tone.TimelineSignal.Type.Exponential,
+ 'value': setValue,
+ 'time': endTime
+ });
+ //if the ramped to value is 0, make it go to the min output, and then set to 0.
+ if (value < this._minOutput) {
+ this._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);
+ this.setValueAtTime(0, endTime);
+ } else {
+ this._param.exponentialRampToValueAtTime(value, endTime);
+ }
+ return this;
+ };
+ /**
+ * Start exponentially approaching the target value at the given time with
+ * a rate having the given time constant.
+ * @param {number} value
+ * @param {Time} startTime
+ * @param {number} timeConstant
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {
+ value = this._fromUnits(value);
+ value = Math.max(this._minOutput, value);
+ timeConstant = Math.max(this._minOutput, timeConstant);
+ startTime = this.toSeconds(startTime);
+ this._events.add({
+ 'type': Tone.TimelineSignal.Type.Target,
+ 'value': value,
+ 'time': startTime,
+ 'constant': timeConstant
+ });
+ this._param.setTargetAtTime(value, startTime, timeConstant);
+ return this;
+ };
+ /**
+ * Set an array of arbitrary values starting at the given time for the given duration.
+ * @param {Float32Array} values
+ * @param {Time} startTime
+ * @param {Time} duration
+ * @param {NormalRange} [scaling=1] If the values in the curve should be scaled by some value
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {
+ scaling = this.defaultArg(scaling, 1);
+ //copy the array
+ var floats = new Array(values.length);
+ for (var i = 0; i < floats.length; i++) {
+ floats[i] = this._fromUnits(values[i]) * scaling;
+ }
+ startTime = this.toSeconds(startTime);
+ duration = this.toSeconds(duration);
+ this._events.add({
+ 'type': Tone.TimelineSignal.Type.Curve,
+ 'value': floats,
+ 'time': startTime,
+ 'duration': duration
+ });
+ //set the first value
+ this._param.setValueAtTime(floats[0], startTime);
+ //schedule a lienar ramp for each of the segments
+ for (var j = 1; j < floats.length; j++) {
+ var segmentTime = startTime + j / (floats.length - 1) * duration;
+ this._param.linearRampToValueAtTime(floats[j], segmentTime);
+ }
+ return this;
+ };
+ /**
+ * Cancels all scheduled parameter changes with times greater than or
+ * equal to startTime.
+ *
+ * @param {Time} startTime
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) {
+ after = this.toSeconds(after);
+ this._events.cancel(after);
+ this._param.cancelScheduledValues(after);
+ return this;
+ };
+ /**
+ * Sets the computed value at the given time. This provides
+ * a point from which a linear or exponential curve
+ * can be scheduled after. Will cancel events after
+ * the given time and shorten the currently scheduled
+ * linear or exponential ramp so that it ends at `time` .
+ * This is to avoid discontinuities and clicks in envelopes.
+ * @param {Time} time When to set the ramp point
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.setRampPoint = function (time) {
+ time = this.toSeconds(time);
+ //get the value at the given time
+ var val = this._toUnits(this.getValueAtTime(time));
+ //if there is an event at the given time
+ //and that even is not a "set"
+ var before = this._searchBefore(time);
+ if (before && before.time === time) {
+ //remove everything after
+ this.cancelScheduledValues(time + this.sampleTime);
+ } else if (before && before.type === Tone.TimelineSignal.Type.Curve && before.time + before.duration > time) {
+ //if the curve is still playing
+ //cancel the curve
+ this.cancelScheduledValues(time);
+ this.linearRampToValueAtTime(val, time);
+ } else {
+ //reschedule the next event to end at the given time
+ var after = this._searchAfter(time);
+ if (after) {
+ //cancel the next event(s)
+ this.cancelScheduledValues(time);
+ if (after.type === Tone.TimelineSignal.Type.Linear) {
+ this.linearRampToValueAtTime(val, time);
+ } else if (after.type === Tone.TimelineSignal.Type.Exponential) {
+ this.exponentialRampToValueAtTime(val, time);
+ }
+ }
+ this.setValueAtTime(val, time);
+ }
+ return this;
+ };
+ /**
+ * Do a linear ramp to the given value between the start and finish times.
+ * @param {Number} value The value to ramp to.
+ * @param {Time} start The beginning anchor point to do the linear ramp
+ * @param {Time} finish The ending anchor point by which the value of
+ * the signal will equal the given value.
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {
+ this.setRampPoint(start);
+ this.linearRampToValueAtTime(value, finish);
+ return this;
+ };
+ /**
+ * Do a exponential ramp to the given value between the start and finish times.
+ * @param {Number} value The value to ramp to.
+ * @param {Time} start The beginning anchor point to do the exponential ramp
+ * @param {Time} finish The ending anchor point by which the value of
+ * the signal will equal the given value.
+ * @returns {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {
+ this.setRampPoint(start);
+ this.exponentialRampToValueAtTime(value, finish);
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // GETTING SCHEDULED VALUES
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Returns the value before or equal to the given time
+ * @param {Number} time The time to query
+ * @return {Object} The event at or before the given time.
+ * @private
+ */
+ Tone.TimelineSignal.prototype._searchBefore = function (time) {
+ return this._events.get(time);
+ };
+ /**
+ * The event after the given time
+ * @param {Number} time The time to query.
+ * @return {Object} The next event after the given time
+ * @private
+ */
+ Tone.TimelineSignal.prototype._searchAfter = function (time) {
+ return this._events.getAfter(time);
+ };
+ /**
+ * Get the scheduled value at the given time. This will
+ * return the unconverted (raw) value.
+ * @param {Number} time The time in seconds.
+ * @return {Number} The scheduled value at the given time.
+ */
+ Tone.TimelineSignal.prototype.getValueAtTime = function (time) {
+ time = this.toSeconds(time);
+ var after = this._searchAfter(time);
+ var before = this._searchBefore(time);
+ var value = this._initial;
+ //if it was set by
+ if (before === null) {
+ value = this._initial;
+ } else if (before.type === Tone.TimelineSignal.Type.Target) {
+ var previous = this._events.getBefore(before.time);
+ var previouVal;
+ if (previous === null) {
+ previouVal = this._initial;
+ } else {
+ previouVal = previous.value;
+ }
+ value = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);
+ } else if (before.type === Tone.TimelineSignal.Type.Curve) {
+ value = this._curveInterpolate(before.time, before.value, before.duration, time);
+ } else if (after === null) {
+ value = before.value;
+ } else if (after.type === Tone.TimelineSignal.Type.Linear) {
+ value = this._linearInterpolate(before.time, before.value, after.time, after.value, time);
+ } else if (after.type === Tone.TimelineSignal.Type.Exponential) {
+ value = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);
+ } else {
+ value = before.value;
+ }
+ return value;
+ };
+ /**
+ * When signals connect to other signals or AudioParams,
+ * they take over the output value of that signal or AudioParam.
+ * For all other nodes, the behavior is the same as a default <code>connect</code>.
+ *
+ * @override
+ * @param {AudioParam|AudioNode|Tone.Signal|Tone} node
+ * @param {number} [outputNumber=0] The output number to connect from.
+ * @param {number} [inputNumber=0] The input number to connect to.
+ * @returns {Tone.TimelineSignal} this
+ * @method
+ */
+ Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;
+ ///////////////////////////////////////////////////////////////////////////
+ // AUTOMATION CURVE CALCULATIONS
+ // MIT License, copyright (c) 2014 Jordan Santell
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Calculates the the value along the curve produced by setTargetAtTime
+ * @private
+ */
+ Tone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {
+ return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);
+ };
+ /**
+ * Calculates the the value along the curve produced by linearRampToValueAtTime
+ * @private
+ */
+ Tone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {
+ return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+ };
+ /**
+ * Calculates the the value along the curve produced by exponentialRampToValueAtTime
+ * @private
+ */
+ Tone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {
+ v0 = Math.max(this._minOutput, v0);
+ return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));
+ };
+ /**
+ * Calculates the the value along the curve produced by setValueCurveAtTime
+ * @private
+ */
+ Tone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {
+ var len = curve.length;
+ // If time is after duration, return the last curve value
+ if (time >= start + duration) {
+ return curve[len - 1];
+ } else if (time <= start) {
+ return curve[0];
+ } else {
+ var progress = (time - start) / duration;
+ var lowerIndex = Math.floor((len - 1) * progress);
+ var upperIndex = Math.ceil((len - 1) * progress);
+ var lowerVal = curve[lowerIndex];
+ var upperVal = curve[upperIndex];
+ if (upperIndex === lowerIndex) {
+ return lowerVal;
+ } else {
+ return this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));
+ }
+ }
+ };
+ /**
+ * Clean up.
+ * @return {Tone.TimelineSignal} this
+ */
+ Tone.TimelineSignal.prototype.dispose = function () {
+ Tone.Signal.prototype.dispose.call(this);
+ Tone.Param.prototype.dispose.call(this);
+ this._events.dispose();
+ this._events = null;
+ };
+ return Tone.TimelineSignal;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Pow applies an exponent to the incoming signal. The incoming signal
+ * must be AudioRange.
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @param {Positive} exp The exponent to apply to the incoming signal, must be at least 2.
+ * @example
+ * var pow = new Tone.Pow(2);
+ * var sig = new Tone.Signal(0.5).connect(pow);
+ * //output of pow is 0.25.
+ */
+ Tone.Pow = function (exp) {
+ /**
+ * the exponent
+ * @private
+ * @type {number}
+ */
+ this._exp = this.defaultArg(exp, 1);
+ /**
+ * @type {WaveShaperNode}
+ * @private
+ */
+ this._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);
+ };
+ Tone.extend(Tone.Pow, Tone.SignalBase);
+ /**
+ * The value of the exponent.
+ * @memberOf Tone.Pow#
+ * @type {number}
+ * @name value
+ */
+ Object.defineProperty(Tone.Pow.prototype, 'value', {
+ get: function () {
+ return this._exp;
+ },
+ set: function (exp) {
+ this._exp = exp;
+ this._expScaler.setMap(this._expFunc(this._exp));
+ }
+ });
+ /**
+ * the function which maps the waveshaper
+ * @param {number} exp
+ * @return {function}
+ * @private
+ */
+ Tone.Pow.prototype._expFunc = function (exp) {
+ return function (val) {
+ return Math.pow(Math.abs(val), exp);
+ };
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Pow} this
+ */
+ Tone.Pow.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._expScaler.dispose();
+ this._expScaler = null;
+ return this;
+ };
+ return Tone.Pow;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Envelope is an [ADSR](https://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope)
+ * envelope generator. Tone.Envelope outputs a signal which
+ * can be connected to an AudioParam or Tone.Signal.
+ * <img src="https://upload.wikimedia.org/wikipedia/commons/e/ea/ADSR_parameter.svg">
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {Time} [attack] The amount of time it takes for the envelope to go from
+ * 0 to it's maximum value.
+ * @param {Time} [decay] The period of time after the attack that it takes for the envelope
+ * to fall to the sustain value.
+ * @param {NormalRange} [sustain] The percent of the maximum value that the envelope rests at until
+ * the release is triggered.
+ * @param {Time} [release] The amount of time after the release is triggered it takes to reach 0.
+ * @example
+ * //an amplitude envelope
+ * var gainNode = Tone.context.createGain();
+ * var env = new Tone.Envelope({
+ * "attack" : 0.1,
+ * "decay" : 0.2,
+ * "sustain" : 1,
+ * "release" : 0.8,
+ * });
+ * env.connect(gainNode.gain);
+ */
+ Tone.Envelope = function () {
+ //get all of the defaults
+ var options = this.optionsObject(arguments, [
+ 'attack',
+ 'decay',
+ 'sustain',
+ 'release'
+ ], Tone.Envelope.defaults);
+ /**
+ * When triggerAttack is called, the attack time is the amount of
+ * time it takes for the envelope to reach it's maximum value.
+ * @type {Time}
+ */
+ this.attack = options.attack;
+ /**
+ * After the attack portion of the envelope, the value will fall
+ * over the duration of the decay time to it's sustain value.
+ * @type {Time}
+ */
+ this.decay = options.decay;
+ /**
+ * The sustain value is the value
+ * which the envelope rests at after triggerAttack is
+ * called, but before triggerRelease is invoked.
+ * @type {NormalRange}
+ */
+ this.sustain = options.sustain;
+ /**
+ * After triggerRelease is called, the envelope's
+ * value will fall to it's miminum value over the
+ * duration of the release time.
+ * @type {Time}
+ */
+ this.release = options.release;
+ /**
+ * the next time the envelope is at standby
+ * @type {number}
+ * @private
+ */
+ this._attackCurve = 'linear';
+ /**
+ * the next time the envelope is at standby
+ * @type {number}
+ * @private
+ */
+ this._releaseCurve = 'exponential';
+ /**
+ * the signal
+ * @type {Tone.TimelineSignal}
+ * @private
+ */
+ this._sig = this.output = new Tone.TimelineSignal();
+ this._sig.setValueAtTime(0, 0);
+ //set the attackCurve initially
+ this.attackCurve = options.attackCurve;
+ this.releaseCurve = options.releaseCurve;
+ };
+ Tone.extend(Tone.Envelope);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ */
+ Tone.Envelope.defaults = {
+ 'attack': 0.01,
+ 'decay': 0.1,
+ 'sustain': 0.5,
+ 'release': 1,
+ 'attackCurve': 'linear',
+ 'releaseCurve': 'exponential'
+ };
+ /**
+ * Read the current value of the envelope. Useful for
+ * syncronizing visual output to the envelope.
+ * @memberOf Tone.Envelope#
+ * @type {Number}
+ * @name value
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Envelope.prototype, 'value', {
+ get: function () {
+ return this.getValueAtTime(this.now());
+ }
+ });
+ /**
+ * The shape of the attack.
+ * Can be any of these strings:
+ * <ul>
+ * <li>linear</li>
+ * <li>exponential</li>
+ * <li>sine</li>
+ * <li>cosine</li>
+ * <li>bounce</li>
+ * <li>ripple</li>
+ * <li>step</li>
+ * </ul>
+ * Can also be an array which describes the curve. Values
+ * in the array are evenly subdivided and linearly
+ * interpolated over the duration of the attack.
+ * @memberOf Tone.Envelope#
+ * @type {String|Array}
+ * @name attackCurve
+ * @example
+ * env.attackCurve = "linear";
+ * @example
+ * //can also be an array
+ * env.attackCurve = [0, 0.2, 0.3, 0.4, 1]
+ */
+ Object.defineProperty(Tone.Envelope.prototype, 'attackCurve', {
+ get: function () {
+ if (this.isString(this._attackCurve)) {
+ return this._attackCurve;
+ } else if (this.isArray(this._attackCurve)) {
+ //look up the name in the curves array
+ for (var type in Tone.Envelope.Type) {
+ if (Tone.Envelope.Type[type].In === this._attackCurve) {
+ return type;
+ }
+ }
+ //otherwise just return the array
+ return this._attackCurve;
+ }
+ },
+ set: function (curve) {
+ //check if it's a valid type
+ if (Tone.Envelope.Type.hasOwnProperty(curve)) {
+ var curveDef = Tone.Envelope.Type[curve];
+ if (this.isObject(curveDef)) {
+ this._attackCurve = curveDef.In;
+ } else {
+ this._attackCurve = curveDef;
+ }
+ } else if (this.isArray(curve)) {
+ this._attackCurve = curve;
+ } else {
+ throw new Error('Tone.Envelope: invalid curve: ' + curve);
+ }
+ }
+ });
+ /**
+ * The shape of the release. See the attack curve types.
+ * @memberOf Tone.Envelope#
+ * @type {String|Array}
+ * @name releaseCurve
+ * @example
+ * env.releaseCurve = "linear";
+ */
+ Object.defineProperty(Tone.Envelope.prototype, 'releaseCurve', {
+ get: function () {
+ if (this.isString(this._releaseCurve)) {
+ return this._releaseCurve;
+ } else if (this.isArray(this._releaseCurve)) {
+ //look up the name in the curves array
+ for (var type in Tone.Envelope.Type) {
+ if (Tone.Envelope.Type[type].Out === this._releaseCurve) {
+ return type;
+ }
+ }
+ //otherwise just return the array
+ return this._releaseCurve;
+ }
+ },
+ set: function (curve) {
+ //check if it's a valid type
+ if (Tone.Envelope.Type.hasOwnProperty(curve)) {
+ var curveDef = Tone.Envelope.Type[curve];
+ if (this.isObject(curveDef)) {
+ this._releaseCurve = curveDef.Out;
+ } else {
+ this._releaseCurve = curveDef;
+ }
+ } else if (this.isArray(curve)) {
+ this._releaseCurve = curve;
+ } else {
+ throw new Error('Tone.Envelope: invalid curve: ' + curve);
+ }
+ }
+ });
+ /**
+ * Trigger the attack/decay portion of the ADSR envelope.
+ * @param {Time} [time=now] When the attack should start.
+ * @param {NormalRange} [velocity=1] The velocity of the envelope scales the vales.
+ * number between 0-1
+ * @returns {Tone.Envelope} this
+ * @example
+ * //trigger the attack 0.5 seconds from now with a velocity of 0.2
+ * env.triggerAttack("+0.5", 0.2);
+ */
+ Tone.Envelope.prototype.triggerAttack = function (time, velocity) {
+ time = this.toSeconds(time);
+ var originalAttack = this.toSeconds(this.attack);
+ var attack = originalAttack;
+ var decay = this.toSeconds(this.decay);
+ velocity = this.defaultArg(velocity, 1);
+ //check if it's not a complete attack
+ var currentValue = this.getValueAtTime(time);
+ if (currentValue > 0) {
+ //subtract the current value from the attack time
+ var attackRate = 1 / attack;
+ var remainingDistance = 1 - currentValue;
+ //the attack is now the remaining time
+ attack = remainingDistance / attackRate;
+ }
+ //attack
+ if (this._attackCurve === 'linear') {
+ this._sig.linearRampToValue(velocity, attack, time);
+ } else if (this._attackCurve === 'exponential') {
+ this._sig.exponentialRampToValue(velocity, attack, time);
+ } else if (attack > 0) {
+ this._sig.setRampPoint(time);
+ var curve = this._attackCurve;
+ //take only a portion of the curve
+ if (attack < originalAttack) {
+ var percentComplete = 1 - attack / originalAttack;
+ var sliceIndex = Math.floor(percentComplete * this._attackCurve.length);
+ curve = this._attackCurve.slice(sliceIndex);
+ //the first index is the current value
+ curve[0] = currentValue;
+ }
+ this._sig.setValueCurveAtTime(curve, time, attack, velocity);
+ }
+ //decay
+ this._sig.exponentialRampToValue(velocity * this.sustain, decay, attack + time);
+ return this;
+ };
+ /**
+ * Triggers the release of the envelope.
+ * @param {Time} [time=now] When the release portion of the envelope should start.
+ * @returns {Tone.Envelope} this
+ * @example
+ * //trigger release immediately
+ * env.triggerRelease();
+ */
+ Tone.Envelope.prototype.triggerRelease = function (time) {
+ time = this.toSeconds(time);
+ var currentValue = this.getValueAtTime(time);
+ if (currentValue > 0) {
+ var release = this.toSeconds(this.release);
+ if (this._releaseCurve === 'linear') {
+ this._sig.linearRampToValue(0, release, time);
+ } else if (this._releaseCurve === 'exponential') {
+ this._sig.exponentialRampToValue(0, release, time);
+ } else {
+ var curve = this._releaseCurve;
+ if (this.isArray(curve)) {
+ this._sig.setRampPoint(time);
+ this._sig.setValueCurveAtTime(curve, time, release, currentValue);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Get the scheduled value at the given time. This will
+ * return the unconverted (raw) value.
+ * @param {Number} time The time in seconds.
+ * @return {Number} The scheduled value at the given time.
+ */
+ Tone.Envelope.prototype.getValueAtTime = function (time) {
+ return this._sig.getValueAtTime(time);
+ };
+ /**
+ * triggerAttackRelease is shorthand for triggerAttack, then waiting
+ * some duration, then triggerRelease.
+ * @param {Time} duration The duration of the sustain.
+ * @param {Time} [time=now] When the attack should be triggered.
+ * @param {number} [velocity=1] The velocity of the envelope.
+ * @returns {Tone.Envelope} this
+ * @example
+ * //trigger the attack and then the release after 0.6 seconds.
+ * env.triggerAttackRelease(0.6);
+ */
+ Tone.Envelope.prototype.triggerAttackRelease = function (duration, time, velocity) {
+ time = this.toSeconds(time);
+ this.triggerAttack(time, velocity);
+ this.triggerRelease(time + this.toSeconds(duration));
+ return this;
+ };
+ /**
+ * Cancels all scheduled envelope changes after the given time.
+ * @param {Time} after
+ * @returns {Tone.Envelope} this
+ */
+ Tone.Envelope.prototype.cancel = function (after) {
+ this._sig.cancelScheduledValues(after);
+ return this;
+ };
+ /**
+ * Borrows the connect method from Tone.Signal.
+ * @function
+ * @private
+ */
+ Tone.Envelope.prototype.connect = Tone.Signal.prototype.connect;
+ /**
+ * Generate some complex envelope curves.
+ */
+ (function _createCurves() {
+ var curveLen = 128;
+ var i, k;
+ //cosine curve
+ var cosineCurve = [];
+ for (i = 0; i < curveLen; i++) {
+ cosineCurve[i] = Math.sin(i / (curveLen - 1) * (Math.PI / 2));
+ }
+ //ripple curve
+ var rippleCurve = [];
+ var rippleCurveFreq = 6.4;
+ for (i = 0; i < curveLen - 1; i++) {
+ k = i / (curveLen - 1);
+ var sineWave = Math.sin(k * (Math.PI * 2) * rippleCurveFreq - Math.PI / 2) + 1;
+ rippleCurve[i] = sineWave / 10 + k * 0.83;
+ }
+ rippleCurve[curveLen - 1] = 1;
+ //stairs curve
+ var stairsCurve = [];
+ var steps = 5;
+ for (i = 0; i < curveLen; i++) {
+ stairsCurve[i] = Math.ceil(i / (curveLen - 1) * steps) / steps;
+ }
+ //in-out easing curve
+ var sineCurve = [];
+ for (i = 0; i < curveLen; i++) {
+ k = i / (curveLen - 1);
+ sineCurve[i] = 0.5 * (1 - Math.cos(Math.PI * k));
+ }
+ //a bounce curve
+ var bounceCurve = [];
+ for (i = 0; i < curveLen; i++) {
+ k = i / (curveLen - 1);
+ var freq = Math.pow(k, 3) * 4 + 0.2;
+ var val = Math.cos(freq * Math.PI * 2 * k);
+ bounceCurve[i] = Math.abs(val * (1 - k));
+ }
+ /**
+ * Invert a value curve to make it work for the release
+ * @private
+ */
+ function invertCurve(curve) {
+ var out = new Array(curve.length);
+ for (var j = 0; j < curve.length; j++) {
+ out[j] = 1 - curve[j];
+ }
+ return out;
+ }
+ /**
+ * reverse the curve
+ * @private
+ */
+ function reverseCurve(curve) {
+ return curve.slice(0).reverse();
+ }
+ /**
+ * attack and release curve arrays
+ * @type {Object}
+ * @private
+ */
+ Tone.Envelope.Type = {
+ 'linear': 'linear',
+ 'exponential': 'exponential',
+ 'bounce': {
+ In: invertCurve(bounceCurve),
+ Out: bounceCurve
+ },
+ 'cosine': {
+ In: cosineCurve,
+ Out: reverseCurve(cosineCurve)
+ },
+ 'step': {
+ In: stairsCurve,
+ Out: invertCurve(stairsCurve)
+ },
+ 'ripple': {
+ In: rippleCurve,
+ Out: invertCurve(rippleCurve)
+ },
+ 'sine': {
+ In: sineCurve,
+ Out: invertCurve(sineCurve)
+ }
+ };
+ }());
+ /**
+ * Disconnect and dispose.
+ * @returns {Tone.Envelope} this
+ */
+ Tone.Envelope.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._sig.dispose();
+ this._sig = null;
+ this._attackCurve = null;
+ this._releaseCurve = null;
+ return this;
+ };
+ return Tone.Envelope;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.AmplitudeEnvelope is a Tone.Envelope connected to a gain node.
+ * Unlike Tone.Envelope, which outputs the envelope's value, Tone.AmplitudeEnvelope accepts
+ * an audio signal as the input and will apply the envelope to the amplitude
+ * of the signal. Read more about ADSR Envelopes on [Wikipedia](https://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope).
+ *
+ * @constructor
+ * @extends {Tone.Envelope}
+ * @param {Time|Object} [attack] The amount of time it takes for the envelope to go from
+ * 0 to it's maximum value.
+ * @param {Time} [decay] The period of time after the attack that it takes for the envelope
+ * to fall to the sustain value.
+ * @param {NormalRange} [sustain] The percent of the maximum value that the envelope rests at until
+ * the release is triggered.
+ * @param {Time} [release] The amount of time after the release is triggered it takes to reach 0.
+ * @example
+ * var ampEnv = new Tone.AmplitudeEnvelope({
+ * "attack": 0.1,
+ * "decay": 0.2,
+ * "sustain": 1.0,
+ * "release": 0.8
+ * }).toMaster();
+ * //create an oscillator and connect it
+ * var osc = new Tone.Oscillator().connect(ampEnv).start();
+ * //trigger the envelopes attack and release "8t" apart
+ * ampEnv.triggerAttackRelease("8t");
+ */
+ Tone.AmplitudeEnvelope = function () {
+ Tone.Envelope.apply(this, arguments);
+ /**
+ * the input node
+ * @type {GainNode}
+ * @private
+ */
+ this.input = this.output = new Tone.Gain();
+ this._sig.connect(this.output.gain);
+ };
+ Tone.extend(Tone.AmplitudeEnvelope, Tone.Envelope);
+ /**
+ * Clean up
+ * @return {Tone.AmplitudeEnvelope} this
+ */
+ Tone.AmplitudeEnvelope.prototype.dispose = function () {
+ this.input.dispose();
+ this.input = null;
+ Tone.Envelope.prototype.dispose.call(this);
+ return this;
+ };
+ return Tone.AmplitudeEnvelope;
+ });
+ Module(function (Tone) {
+
+ /**
+ * AnalyserNode.getFloatTimeDomainData polyfill
+ * @private
+ */
+ if (window.AnalyserNode && !AnalyserNode.prototype.getFloatTimeDomainData) {
+ //referenced https://github.com/mohayonao/get-float-time-domain-data
+ AnalyserNode.prototype.getFloatTimeDomainData = function (array) {
+ var uint8 = new Uint8Array(array.length);
+ this.getByteTimeDomainData(uint8);
+ for (var i = 0; i < uint8.length; i++) {
+ array[i] = (uint8[i] - 128) / 128;
+ }
+ };
+ }
+ /**
+ * @class Wrapper around the native Web Audio's
+ * [AnalyserNode](http://webaudio.github.io/web-audio-api/#idl-def-AnalyserNode).
+ * Extracts FFT or Waveform data from the incoming signal.
+ * @extends {Tone}
+ * @param {String=} type The return type of the analysis, either "fft", or "waveform".
+ * @param {Number=} size The size of the FFT. Value must be a power of
+ * two in the range 32 to 32768.
+ */
+ Tone.Analyser = function () {
+ var options = this.optionsObject(arguments, [
+ 'type',
+ 'size'
+ ], Tone.Analyser.defaults);
+ /**
+ * The analyser node.
+ * @private
+ * @type {AnalyserNode}
+ */
+ this._analyser = this.input = this.output = this.context.createAnalyser();
+ /**
+ * The analysis type
+ * @type {String}
+ * @private
+ */
+ this._type = options.type;
+ /**
+ * The return type of the analysis
+ * @type {String}
+ * @private
+ */
+ this._returnType = options.returnType;
+ /**
+ * The buffer that the FFT data is written to
+ * @type {TypedArray}
+ * @private
+ */
+ this._buffer = null;
+ //set the values initially
+ this.size = options.size;
+ this.type = options.type;
+ this.returnType = options.returnType;
+ this.minDecibels = options.minDecibels;
+ this.maxDecibels = options.maxDecibels;
+ };
+ Tone.extend(Tone.Analyser);
+ /**
+ * The default values.
+ * @type {Object}
+ * @const
+ */
+ Tone.Analyser.defaults = {
+ 'size': 1024,
+ 'returnType': 'byte',
+ 'type': 'fft',
+ 'smoothing': 0.8,
+ 'maxDecibels': -30,
+ 'minDecibels': -100
+ };
+ /**
+ * Possible return types of Tone.Analyser.analyse()
+ * @enum {String}
+ */
+ Tone.Analyser.Type = {
+ Waveform: 'waveform',
+ FFT: 'fft'
+ };
+ /**
+ * Possible return types of Tone.Analyser.analyse().
+ * byte values are between [0,255]. float values are between
+ * [-1, 1] when the type is set to "waveform" and between
+ * [minDecibels,maxDecibels] when the type is "fft".
+ * @enum {String}
+ */
+ Tone.Analyser.ReturnType = {
+ Byte: 'byte',
+ Float: 'float'
+ };
+ /**
+ * Run the analysis given the current settings and return the
+ * result as a TypedArray.
+ * @returns {TypedArray}
+ */
+ Tone.Analyser.prototype.analyse = function () {
+ if (this._type === Tone.Analyser.Type.FFT) {
+ if (this._returnType === Tone.Analyser.ReturnType.Byte) {
+ this._analyser.getByteFrequencyData(this._buffer);
+ } else {
+ this._analyser.getFloatFrequencyData(this._buffer);
+ }
+ } else if (this._type === Tone.Analyser.Type.Waveform) {
+ if (this._returnType === Tone.Analyser.ReturnType.Byte) {
+ this._analyser.getByteTimeDomainData(this._buffer);
+ } else {
+ this._analyser.getFloatTimeDomainData(this._buffer);
+ }
+ }
+ return this._buffer;
+ };
+ /**
+ * The size of analysis. This must be a power of two in the range 32 to 32768.
+ * @memberOf Tone.Analyser#
+ * @type {Number}
+ * @name size
+ */
+ Object.defineProperty(Tone.Analyser.prototype, 'size', {
+ get: function () {
+ return this._analyser.frequencyBinCount;
+ },
+ set: function (size) {
+ this._analyser.fftSize = size * 2;
+ this.type = this._type;
+ }
+ });
+ /**
+ * The return type of Tone.Analyser.analyse(), either "byte" or "float".
+ * When the type is set to "byte" the range of values returned in the array
+ * are between 0-255. "float" values are between
+ * [-1, 1] when the type is set to "waveform" and between
+ * [minDecibels,maxDecibels] when the type is "fft".
+ * @memberOf Tone.Analyser#
+ * @type {String}
+ * @name type
+ */
+ Object.defineProperty(Tone.Analyser.prototype, 'returnType', {
+ get: function () {
+ return this._returnType;
+ },
+ set: function (type) {
+ if (type === Tone.Analyser.ReturnType.Byte) {
+ this._buffer = new Uint8Array(this._analyser.frequencyBinCount);
+ } else if (type === Tone.Analyser.ReturnType.Float) {
+ this._buffer = new Float32Array(this._analyser.frequencyBinCount);
+ } else {
+ throw new TypeError('Tone.Analayser: invalid return type: ' + type);
+ }
+ this._returnType = type;
+ }
+ });
+ /**
+ * The analysis function returned by Tone.Analyser.analyse(), either "fft" or "waveform".
+ * @memberOf Tone.Analyser#
+ * @type {String}
+ * @name type
+ */
+ Object.defineProperty(Tone.Analyser.prototype, 'type', {
+ get: function () {
+ return this._type;
+ },
+ set: function (type) {
+ if (type !== Tone.Analyser.Type.Waveform && type !== Tone.Analyser.Type.FFT) {
+ throw new TypeError('Tone.Analyser: invalid type: ' + type);
+ }
+ this._type = type;
+ }
+ });
+ /**
+ * 0 represents no time averaging with the last analysis frame.
+ * @memberOf Tone.Analyser#
+ * @type {NormalRange}
+ * @name smoothing
+ */
+ Object.defineProperty(Tone.Analyser.prototype, 'smoothing', {
+ get: function () {
+ return this._analyser.smoothingTimeConstant;
+ },
+ set: function (val) {
+ this._analyser.smoothingTimeConstant = val;
+ }
+ });
+ /**
+ * The smallest decibel value which is analysed by the FFT.
+ * @memberOf Tone.Analyser#
+ * @type {Decibels}
+ * @name minDecibels
+ */
+ Object.defineProperty(Tone.Analyser.prototype, 'minDecibels', {
+ get: function () {
+ return this._analyser.minDecibels;
+ },
+ set: function (val) {
+ this._analyser.minDecibels = val;
+ }
+ });
+ /**
+ * The largest decibel value which is analysed by the FFT.
+ * @memberOf Tone.Analyser#
+ * @type {Decibels}
+ * @name maxDecibels
+ */
+ Object.defineProperty(Tone.Analyser.prototype, 'maxDecibels', {
+ get: function () {
+ return this._analyser.maxDecibels;
+ },
+ set: function (val) {
+ this._analyser.maxDecibels = val;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.Analyser} this
+ */
+ Tone.Analyser.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._analyser.disconnect();
+ this._analyser = null;
+ this._buffer = null;
+ };
+ return Tone.Analyser;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Compressor is a thin wrapper around the Web Audio
+ * [DynamicsCompressorNode](http://webaudio.github.io/web-audio-api/#the-dynamicscompressornode-interface).
+ * Compression reduces the volume of loud sounds or amplifies quiet sounds
+ * by narrowing or "compressing" an audio signal's dynamic range.
+ * Read more on [Wikipedia](https://en.wikipedia.org/wiki/Dynamic_range_compression).
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {Decibels|Object} [threshold] The value above which the compression starts to be applied.
+ * @param {Positive} [ratio] The gain reduction ratio.
+ * @example
+ * var comp = new Tone.Compressor(-30, 3);
+ */
+ Tone.Compressor = function () {
+ var options = this.optionsObject(arguments, [
+ 'threshold',
+ 'ratio'
+ ], Tone.Compressor.defaults);
+ /**
+ * the compressor node
+ * @type {DynamicsCompressorNode}
+ * @private
+ */
+ this._compressor = this.input = this.output = this.context.createDynamicsCompressor();
+ /**
+ * the threshold vaue
+ * @type {Decibels}
+ * @signal
+ */
+ this.threshold = new Tone.Param({
+ 'param': this._compressor.threshold,
+ 'units': Tone.Type.Decibels,
+ 'convert': false
+ });
+ /**
+ * The attack parameter
+ * @type {Time}
+ * @signal
+ */
+ this.attack = new Tone.Param(this._compressor.attack, Tone.Type.Time);
+ /**
+ * The release parameter
+ * @type {Time}
+ * @signal
+ */
+ this.release = new Tone.Param(this._compressor.release, Tone.Type.Time);
+ /**
+ * The knee parameter
+ * @type {Decibels}
+ * @signal
+ */
+ this.knee = new Tone.Param({
+ 'param': this._compressor.knee,
+ 'units': Tone.Type.Decibels,
+ 'convert': false
+ });
+ /**
+ * The ratio value
+ * @type {Number}
+ * @signal
+ */
+ this.ratio = new Tone.Param({
+ 'param': this._compressor.ratio,
+ 'convert': false
+ });
+ //set the defaults
+ this._readOnly([
+ 'knee',
+ 'release',
+ 'attack',
+ 'ratio',
+ 'threshold'
+ ]);
+ this.set(options);
+ };
+ Tone.extend(Tone.Compressor);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Compressor.defaults = {
+ 'ratio': 12,
+ 'threshold': -24,
+ 'release': 0.25,
+ 'attack': 0.003,
+ 'knee': 30
+ };
+ /**
+ * clean up
+ * @returns {Tone.Compressor} this
+ */
+ Tone.Compressor.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'knee',
+ 'release',
+ 'attack',
+ 'ratio',
+ 'threshold'
+ ]);
+ this._compressor.disconnect();
+ this._compressor = null;
+ this.attack.dispose();
+ this.attack = null;
+ this.release.dispose();
+ this.release = null;
+ this.threshold.dispose();
+ this.threshold = null;
+ this.ratio.dispose();
+ this.ratio = null;
+ this.knee.dispose();
+ this.knee = null;
+ return this;
+ };
+ return Tone.Compressor;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Add a signal and a number or two signals. When no value is
+ * passed into the constructor, Tone.Add will sum <code>input[0]</code>
+ * and <code>input[1]</code>. If a value is passed into the constructor,
+ * the it will be added to the input.
+ *
+ * @constructor
+ * @extends {Tone.Signal}
+ * @param {number=} value If no value is provided, Tone.Add will sum the first
+ * and second inputs.
+ * @example
+ * var signal = new Tone.Signal(2);
+ * var add = new Tone.Add(2);
+ * signal.connect(add);
+ * //the output of add equals 4
+ * @example
+ * //if constructed with no arguments
+ * //it will add the first and second inputs
+ * var add = new Tone.Add();
+ * var sig0 = new Tone.Signal(3).connect(add, 0, 0);
+ * var sig1 = new Tone.Signal(4).connect(add, 0, 1);
+ * //the output of add equals 7.
+ */
+ Tone.Add = function (value) {
+ this.createInsOuts(2, 0);
+ /**
+ * the summing node
+ * @type {GainNode}
+ * @private
+ */
+ this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();
+ /**
+ * @private
+ * @type {Tone.Signal}
+ */
+ this._param = this.input[1] = new Tone.Signal(value);
+ this._param.connect(this._sum);
+ };
+ Tone.extend(Tone.Add, Tone.Signal);
+ /**
+ * Clean up.
+ * @returns {Tone.Add} this
+ */
+ Tone.Add.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._sum.dispose();
+ this._sum = null;
+ this._param.dispose();
+ this._param = null;
+ return this;
+ };
+ return Tone.Add;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Multiply two incoming signals. Or, if a number is given in the constructor,
+ * multiplies the incoming signal by that value.
+ *
+ * @constructor
+ * @extends {Tone.Signal}
+ * @param {number=} value Constant value to multiple. If no value is provided,
+ * it will return the product of the first and second inputs
+ * @example
+ * var mult = new Tone.Multiply();
+ * var sigA = new Tone.Signal(3);
+ * var sigB = new Tone.Signal(4);
+ * sigA.connect(mult, 0, 0);
+ * sigB.connect(mult, 0, 1);
+ * //output of mult is 12.
+ * @example
+ * var mult = new Tone.Multiply(10);
+ * var sig = new Tone.Signal(2).connect(mult);
+ * //the output of mult is 20.
+ */
+ Tone.Multiply = function (value) {
+ this.createInsOuts(2, 0);
+ /**
+ * the input node is the same as the output node
+ * it is also the GainNode which handles the scaling of incoming signal
+ *
+ * @type {GainNode}
+ * @private
+ */
+ this._mult = this.input[0] = this.output = new Tone.Gain();
+ /**
+ * the scaling parameter
+ * @type {AudioParam}
+ * @private
+ */
+ this._param = this.input[1] = this.output.gain;
+ this._param.value = this.defaultArg(value, 0);
+ };
+ Tone.extend(Tone.Multiply, Tone.Signal);
+ /**
+ * clean up
+ * @returns {Tone.Multiply} this
+ */
+ Tone.Multiply.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._mult.dispose();
+ this._mult = null;
+ this._param = null;
+ return this;
+ };
+ return Tone.Multiply;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Negate the incoming signal. i.e. an input signal of 10 will output -10
+ *
+ * @constructor
+ * @extends {Tone.SignalBase}
+ * @example
+ * var neg = new Tone.Negate();
+ * var sig = new Tone.Signal(-2).connect(neg);
+ * //output of neg is positive 2.
+ */
+ Tone.Negate = function () {
+ /**
+ * negation is done by multiplying by -1
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._multiply = this.input = this.output = new Tone.Multiply(-1);
+ };
+ Tone.extend(Tone.Negate, Tone.SignalBase);
+ /**
+ * clean up
+ * @returns {Tone.Negate} this
+ */
+ Tone.Negate.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._multiply.dispose();
+ this._multiply = null;
+ return this;
+ };
+ return Tone.Negate;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Subtract the signal connected to <code>input[1]</code> from the signal connected
+ * to <code>input[0]</code>. If an argument is provided in the constructor, the
+ * signals <code>.value</code> will be subtracted from the incoming signal.
+ *
+ * @extends {Tone.Signal}
+ * @constructor
+ * @param {number=} value The value to subtract from the incoming signal. If the value
+ * is omitted, it will subtract the second signal from the first.
+ * @example
+ * var sub = new Tone.Subtract(1);
+ * var sig = new Tone.Signal(4).connect(sub);
+ * //the output of sub is 3.
+ * @example
+ * var sub = new Tone.Subtract();
+ * var sigA = new Tone.Signal(10);
+ * var sigB = new Tone.Signal(2.5);
+ * sigA.connect(sub, 0, 0);
+ * sigB.connect(sub, 0, 1);
+ * //output of sub is 7.5
+ */
+ Tone.Subtract = function (value) {
+ this.createInsOuts(2, 0);
+ /**
+ * the summing node
+ * @type {GainNode}
+ * @private
+ */
+ this._sum = this.input[0] = this.output = new Tone.Gain();
+ /**
+ * negate the input of the second input before connecting it
+ * to the summing node.
+ * @type {Tone.Negate}
+ * @private
+ */
+ this._neg = new Tone.Negate();
+ /**
+ * the node where the value is set
+ * @private
+ * @type {Tone.Signal}
+ */
+ this._param = this.input[1] = new Tone.Signal(value);
+ this._param.chain(this._neg, this._sum);
+ };
+ Tone.extend(Tone.Subtract, Tone.Signal);
+ /**
+ * Clean up.
+ * @returns {Tone.SignalBase} this
+ */
+ Tone.Subtract.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._neg.dispose();
+ this._neg = null;
+ this._sum.disconnect();
+ this._sum = null;
+ this._param.dispose();
+ this._param = null;
+ return this;
+ };
+ return Tone.Subtract;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class GreaterThanZero outputs 1 when the input is strictly greater than zero
+ *
+ * @constructor
+ * @extends {Tone.SignalBase}
+ * @example
+ * var gt0 = new Tone.GreaterThanZero();
+ * var sig = new Tone.Signal(0.01).connect(gt0);
+ * //the output of gt0 is 1.
+ * sig.value = 0;
+ * //the output of gt0 is 0.
+ */
+ Tone.GreaterThanZero = function () {
+ /**
+ * @type {Tone.WaveShaper}
+ * @private
+ */
+ this._thresh = this.output = new Tone.WaveShaper(function (val) {
+ if (val <= 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }, 127);
+ /**
+ * scale the first thresholded signal by a large value.
+ * this will help with values which are very close to 0
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._scale = this.input = new Tone.Multiply(10000);
+ //connections
+ this._scale.connect(this._thresh);
+ };
+ Tone.extend(Tone.GreaterThanZero, Tone.SignalBase);
+ /**
+ * dispose method
+ * @returns {Tone.GreaterThanZero} this
+ */
+ Tone.GreaterThanZero.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._scale.dispose();
+ this._scale = null;
+ this._thresh.dispose();
+ this._thresh = null;
+ return this;
+ };
+ return Tone.GreaterThanZero;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Output 1 if the signal is greater than the value, otherwise outputs 0.
+ * can compare two signals or a signal and a number.
+ *
+ * @constructor
+ * @extends {Tone.Signal}
+ * @param {number} [value=0] the value to compare to the incoming signal
+ * @example
+ * var gt = new Tone.GreaterThan(2);
+ * var sig = new Tone.Signal(4).connect(gt);
+ * //output of gt is equal 1.
+ */
+ Tone.GreaterThan = function (value) {
+ this.createInsOuts(2, 0);
+ /**
+ * subtract the amount from the incoming signal
+ * @type {Tone.Subtract}
+ * @private
+ */
+ this._param = this.input[0] = new Tone.Subtract(value);
+ this.input[1] = this._param.input[1];
+ /**
+ * compare that amount to zero
+ * @type {Tone.GreaterThanZero}
+ * @private
+ */
+ this._gtz = this.output = new Tone.GreaterThanZero();
+ //connect
+ this._param.connect(this._gtz);
+ };
+ Tone.extend(Tone.GreaterThan, Tone.Signal);
+ /**
+ * dispose method
+ * @returns {Tone.GreaterThan} this
+ */
+ Tone.GreaterThan.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._param.dispose();
+ this._param = null;
+ this._gtz.dispose();
+ this._gtz = null;
+ return this;
+ };
+ return Tone.GreaterThan;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Return the absolute value of an incoming signal.
+ *
+ * @constructor
+ * @extends {Tone.SignalBase}
+ * @example
+ * var signal = new Tone.Signal(-1);
+ * var abs = new Tone.Abs();
+ * signal.connect(abs);
+ * //the output of abs is 1.
+ */
+ Tone.Abs = function () {
+ /**
+ * @type {Tone.LessThan}
+ * @private
+ */
+ this._abs = this.input = this.output = new Tone.WaveShaper(function (val) {
+ if (val === 0) {
+ return 0;
+ } else {
+ return Math.abs(val);
+ }
+ }, 127);
+ };
+ Tone.extend(Tone.Abs, Tone.SignalBase);
+ /**
+ * dispose method
+ * @returns {Tone.Abs} this
+ */
+ Tone.Abs.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._abs.dispose();
+ this._abs = null;
+ return this;
+ };
+ return Tone.Abs;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Signal-rate modulo operator. Only works in AudioRange [-1, 1] and for modulus
+ * values in the NormalRange.
+ *
+ * @constructor
+ * @extends {Tone.SignalBase}
+ * @param {NormalRange} modulus The modulus to apply.
+ * @example
+ * var mod = new Tone.Modulo(0.2)
+ * var sig = new Tone.Signal(0.5).connect(mod);
+ * //mod outputs 0.1
+ */
+ Tone.Modulo = function (modulus) {
+ this.createInsOuts(1, 0);
+ /**
+ * A waveshaper gets the integer multiple of
+ * the input signal and the modulus.
+ * @private
+ * @type {Tone.WaveShaper}
+ */
+ this._shaper = new Tone.WaveShaper(Math.pow(2, 16));
+ /**
+ * the integer multiple is multiplied by the modulus
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._multiply = new Tone.Multiply();
+ /**
+ * and subtracted from the input signal
+ * @type {Tone.Subtract}
+ * @private
+ */
+ this._subtract = this.output = new Tone.Subtract();
+ /**
+ * the modulus signal
+ * @type {Tone.Signal}
+ * @private
+ */
+ this._modSignal = new Tone.Signal(modulus);
+ //connections
+ 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(modulus);
+ };
+ Tone.extend(Tone.Modulo, Tone.SignalBase);
+ /**
+ * @param {number} mod the modulus to apply
+ * @private
+ */
+ Tone.Modulo.prototype._setWaveShaper = function (mod) {
+ this._shaper.setMap(function (val) {
+ var multiple = Math.floor((val + 0.0001) / mod);
+ return multiple;
+ });
+ };
+ /**
+ * The modulus value.
+ * @memberOf Tone.Modulo#
+ * @type {NormalRange}
+ * @name value
+ */
+ Object.defineProperty(Tone.Modulo.prototype, 'value', {
+ get: function () {
+ return this._modSignal.value;
+ },
+ set: function (mod) {
+ this._modSignal.value = mod;
+ this._setWaveShaper(mod);
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.Modulo} this
+ */
+ Tone.Modulo.prototype.dispose = function () {
+ Tone.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;
+ return this;
+ };
+ return Tone.Modulo;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class AudioToGain converts an input in AudioRange [-1,1] to NormalRange [0,1].
+ * See Tone.GainToAudio.
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @example
+ * var a2g = new Tone.AudioToGain();
+ */
+ Tone.AudioToGain = function () {
+ /**
+ * @type {WaveShaperNode}
+ * @private
+ */
+ this._norm = this.input = this.output = new Tone.WaveShaper(function (x) {
+ return (x + 1) / 2;
+ });
+ };
+ Tone.extend(Tone.AudioToGain, Tone.SignalBase);
+ /**
+ * clean up
+ * @returns {Tone.AudioToGain} this
+ */
+ Tone.AudioToGain.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._norm.dispose();
+ this._norm = null;
+ return this;
+ };
+ return Tone.AudioToGain;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Evaluate an expression at audio rate. <br><br>
+ * Parsing code modified from https://code.google.com/p/tapdigit/
+ * Copyright 2011 2012 Ariya Hidayat, New BSD License
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @param {string} expr the expression to generate
+ * @example
+ * //adds the signals from input[0] and input[1].
+ * var expr = new Tone.Expr("$0 + $1");
+ */
+ Tone.Expr = function () {
+ var expr = this._replacements(Array.prototype.slice.call(arguments));
+ var inputCount = this._parseInputs(expr);
+ /**
+ * hold onto all of the nodes for disposal
+ * @type {Array}
+ * @private
+ */
+ this._nodes = [];
+ /**
+ * The inputs. The length is determined by the expression.
+ * @type {Array}
+ */
+ this.input = new Array(inputCount);
+ //create a gain for each input
+ for (var i = 0; i < inputCount; i++) {
+ this.input[i] = this.context.createGain();
+ }
+ //parse the syntax tree
+ var tree = this._parseTree(expr);
+ //evaluate the results
+ var result;
+ try {
+ result = this._eval(tree);
+ } catch (e) {
+ this._disposeNodes();
+ throw new Error('Tone.Expr: Could evaluate expression: ' + expr);
+ }
+ /**
+ * The output node is the result of the expression
+ * @type {Tone}
+ */
+ this.output = result;
+ };
+ Tone.extend(Tone.Expr, Tone.SignalBase);
+ //some helpers to cut down the amount of code
+ function applyBinary(Constructor, args, self) {
+ var op = new Constructor();
+ self._eval(args[0]).connect(op, 0, 0);
+ self._eval(args[1]).connect(op, 0, 1);
+ return op;
+ }
+ function applyUnary(Constructor, args, self) {
+ var op = new Constructor();
+ self._eval(args[0]).connect(op, 0, 0);
+ return op;
+ }
+ function getNumber(arg) {
+ return arg ? parseFloat(arg) : undefined;
+ }
+ function literalNumber(arg) {
+ return arg && arg.args ? parseFloat(arg.args) : undefined;
+ }
+ /*
+ * the Expressions that Tone.Expr can parse.
+ *
+ * each expression belongs to a group and contains a regexp
+ * for selecting the operator as well as that operators method
+ *
+ * @type {Object}
+ * @private
+ */
+ Tone.Expr._Expressions = {
+ //values
+ 'value': {
+ 'signal': {
+ regexp: /^\d+\.\d+|^\d+/,
+ method: function (arg) {
+ var sig = new Tone.Signal(getNumber(arg));
+ return sig;
+ }
+ },
+ 'input': {
+ regexp: /^\$\d/,
+ method: function (arg, self) {
+ return self.input[getNumber(arg.substr(1))];
+ }
+ }
+ },
+ //syntactic glue
+ 'glue': {
+ '(': { regexp: /^\(/ },
+ ')': { regexp: /^\)/ },
+ ',': { regexp: /^,/ }
+ },
+ //functions
+ 'func': {
+ 'abs': {
+ regexp: /^abs/,
+ method: applyUnary.bind(this, Tone.Abs)
+ },
+ 'mod': {
+ regexp: /^mod/,
+ method: function (args, self) {
+ var modulus = literalNumber(args[1]);
+ var op = new Tone.Modulo(modulus);
+ self._eval(args[0]).connect(op);
+ return op;
+ }
+ },
+ 'pow': {
+ regexp: /^pow/,
+ method: function (args, self) {
+ var exp = literalNumber(args[1]);
+ var op = new Tone.Pow(exp);
+ self._eval(args[0]).connect(op);
+ return op;
+ }
+ },
+ 'a2g': {
+ regexp: /^a2g/,
+ method: function (args, self) {
+ var op = new Tone.AudioToGain();
+ self._eval(args[0]).connect(op);
+ return op;
+ }
+ }
+ },
+ //binary expressions
+ 'binary': {
+ '+': {
+ regexp: /^\+/,
+ precedence: 1,
+ method: applyBinary.bind(this, Tone.Add)
+ },
+ '-': {
+ regexp: /^\-/,
+ precedence: 1,
+ method: function (args, self) {
+ //both unary and binary op
+ if (args.length === 1) {
+ return applyUnary(Tone.Negate, args, self);
+ } else {
+ return applyBinary(Tone.Subtract, args, self);
+ }
+ }
+ },
+ '*': {
+ regexp: /^\*/,
+ precedence: 0,
+ method: applyBinary.bind(this, Tone.Multiply)
+ }
+ },
+ //unary expressions
+ 'unary': {
+ '-': {
+ regexp: /^\-/,
+ method: applyUnary.bind(this, Tone.Negate)
+ },
+ '!': {
+ regexp: /^\!/,
+ method: applyUnary.bind(this, Tone.NOT)
+ }
+ }
+ };
+ /**
+ * @param {string} expr the expression string
+ * @return {number} the input count
+ * @private
+ */
+ Tone.Expr.prototype._parseInputs = function (expr) {
+ var inputArray = expr.match(/\$\d/g);
+ var inputMax = 0;
+ if (inputArray !== null) {
+ for (var i = 0; i < inputArray.length; i++) {
+ var inputNum = parseInt(inputArray[i].substr(1)) + 1;
+ inputMax = Math.max(inputMax, inputNum);
+ }
+ }
+ return inputMax;
+ };
+ /**
+ * @param {Array} args an array of arguments
+ * @return {string} the results of the replacements being replaced
+ * @private
+ */
+ Tone.Expr.prototype._replacements = function (args) {
+ var expr = args.shift();
+ for (var i = 0; i < args.length; i++) {
+ expr = expr.replace(/\%/i, args[i]);
+ }
+ return expr;
+ };
+ /**
+ * tokenize the expression based on the Expressions object
+ * @param {string} expr
+ * @return {Object} returns two methods on the tokenized list, next and peek
+ * @private
+ */
+ Tone.Expr.prototype._tokenize = function (expr) {
+ var position = -1;
+ var tokens = [];
+ while (expr.length > 0) {
+ expr = expr.trim();
+ var token = getNextToken(expr);
+ tokens.push(token);
+ expr = expr.substr(token.value.length);
+ }
+ function getNextToken(expr) {
+ for (var type in Tone.Expr._Expressions) {
+ var group = Tone.Expr._Expressions[type];
+ for (var opName in group) {
+ var op = group[opName];
+ var reg = op.regexp;
+ var match = expr.match(reg);
+ if (match !== null) {
+ return {
+ type: type,
+ value: match[0],
+ method: op.method
+ };
+ }
+ }
+ }
+ throw new SyntaxError('Tone.Expr: Unexpected token ' + expr);
+ }
+ return {
+ next: function () {
+ return tokens[++position];
+ },
+ peek: function () {
+ return tokens[position + 1];
+ }
+ };
+ };
+ /**
+ * recursively parse the string expression into a syntax tree
+ *
+ * @param {string} expr
+ * @return {Object}
+ * @private
+ */
+ Tone.Expr.prototype._parseTree = function (expr) {
+ var lexer = this._tokenize(expr);
+ var isUndef = this.isUndef.bind(this);
+ function matchSyntax(token, syn) {
+ return !isUndef(token) && token.type === 'glue' && token.value === syn;
+ }
+ function matchGroup(token, groupName, prec) {
+ var ret = false;
+ var group = Tone.Expr._Expressions[groupName];
+ if (!isUndef(token)) {
+ for (var opName in group) {
+ var op = group[opName];
+ if (op.regexp.test(token.value)) {
+ if (!isUndef(prec)) {
+ if (op.precedence === prec) {
+ return true;
+ }
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+ return ret;
+ }
+ function parseExpression(precedence) {
+ if (isUndef(precedence)) {
+ precedence = 5;
+ }
+ var expr;
+ if (precedence < 0) {
+ expr = parseUnary();
+ } else {
+ expr = parseExpression(precedence - 1);
+ }
+ var token = lexer.peek();
+ while (matchGroup(token, 'binary', precedence)) {
+ token = lexer.next();
+ expr = {
+ operator: token.value,
+ method: token.method,
+ args: [
+ expr,
+ parseExpression(precedence - 1)
+ ]
+ };
+ token = lexer.peek();
+ }
+ return expr;
+ }
+ function parseUnary() {
+ var token, expr;
+ token = lexer.peek();
+ if (matchGroup(token, 'unary')) {
+ token = lexer.next();
+ expr = parseUnary();
+ return {
+ operator: token.value,
+ method: token.method,
+ args: [expr]
+ };
+ }
+ return parsePrimary();
+ }
+ function parsePrimary() {
+ var token, expr;
+ token = lexer.peek();
+ if (isUndef(token)) {
+ throw new SyntaxError('Tone.Expr: Unexpected termination of expression');
+ }
+ if (token.type === 'func') {
+ token = lexer.next();
+ return parseFunctionCall(token);
+ }
+ if (token.type === 'value') {
+ token = lexer.next();
+ return {
+ method: token.method,
+ args: token.value
+ };
+ }
+ if (matchSyntax(token, '(')) {
+ lexer.next();
+ expr = parseExpression();
+ token = lexer.next();
+ if (!matchSyntax(token, ')')) {
+ throw new SyntaxError('Expected )');
+ }
+ return expr;
+ }
+ throw new SyntaxError('Tone.Expr: Parse error, cannot process token ' + token.value);
+ }
+ function parseFunctionCall(func) {
+ var token, args = [];
+ token = lexer.next();
+ if (!matchSyntax(token, '(')) {
+ throw new SyntaxError('Tone.Expr: Expected ( in a function call "' + func.value + '"');
+ }
+ token = lexer.peek();
+ if (!matchSyntax(token, ')')) {
+ args = parseArgumentList();
+ }
+ token = lexer.next();
+ if (!matchSyntax(token, ')')) {
+ throw new SyntaxError('Tone.Expr: Expected ) in a function call "' + func.value + '"');
+ }
+ return {
+ method: func.method,
+ args: args,
+ name: name
+ };
+ }
+ function parseArgumentList() {
+ var token, expr, args = [];
+ while (true) {
+ expr = parseExpression();
+ if (isUndef(expr)) {
+ // TODO maybe throw exception?
+ break;
+ }
+ args.push(expr);
+ token = lexer.peek();
+ if (!matchSyntax(token, ',')) {
+ break;
+ }
+ lexer.next();
+ }
+ return args;
+ }
+ return parseExpression();
+ };
+ /**
+ * recursively evaluate the expression tree
+ * @param {Object} tree
+ * @return {AudioNode} the resulting audio node from the expression
+ * @private
+ */
+ Tone.Expr.prototype._eval = function (tree) {
+ if (!this.isUndef(tree)) {
+ var node = tree.method(tree.args, this);
+ this._nodes.push(node);
+ return node;
+ }
+ };
+ /**
+ * dispose all the nodes
+ * @private
+ */
+ Tone.Expr.prototype._disposeNodes = function () {
+ for (var i = 0; i < this._nodes.length; i++) {
+ var node = this._nodes[i];
+ if (this.isFunction(node.dispose)) {
+ node.dispose();
+ } else if (this.isFunction(node.disconnect)) {
+ node.disconnect();
+ }
+ node = null;
+ this._nodes[i] = null;
+ }
+ this._nodes = null;
+ };
+ /**
+ * clean up
+ */
+ Tone.Expr.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._disposeNodes();
+ };
+ return Tone.Expr;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Convert an incoming signal between 0, 1 to an equal power gain scale.
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @example
+ * var eqPowGain = new Tone.EqualPowerGain();
+ */
+ Tone.EqualPowerGain = function () {
+ /**
+ * @type {Tone.WaveShaper}
+ * @private
+ */
+ this._eqPower = this.input = this.output = new Tone.WaveShaper(function (val) {
+ if (Math.abs(val) < 0.001) {
+ //should output 0 when input is 0
+ return 0;
+ } else {
+ return this.equalPowerScale(val);
+ }
+ }.bind(this), 4096);
+ };
+ Tone.extend(Tone.EqualPowerGain, Tone.SignalBase);
+ /**
+ * clean up
+ * @returns {Tone.EqualPowerGain} this
+ */
+ Tone.EqualPowerGain.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._eqPower.dispose();
+ this._eqPower = null;
+ return this;
+ };
+ return Tone.EqualPowerGain;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Crossfade provides equal power fading between two inputs.
+ * More on crossfading technique [here](https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Crossfading).
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {NormalRange} [initialFade=0.5]
+ * @example
+ * var crossFade = new Tone.CrossFade(0.5);
+ * //connect effect A to crossfade from
+ * //effect output 0 to crossfade input 0
+ * effectA.connect(crossFade, 0, 0);
+ * //connect effect B to crossfade from
+ * //effect output 0 to crossfade input 1
+ * effectB.connect(crossFade, 0, 1);
+ * crossFade.fade.value = 0;
+ * // ^ only effectA is output
+ * crossFade.fade.value = 1;
+ * // ^ only effectB is output
+ * crossFade.fade.value = 0.5;
+ * // ^ the two signals are mixed equally.
+ */
+ Tone.CrossFade = function (initialFade) {
+ this.createInsOuts(2, 1);
+ /**
+ * Alias for <code>input[0]</code>.
+ * @type {Tone.Gain}
+ */
+ this.a = this.input[0] = new Tone.Gain();
+ /**
+ * Alias for <code>input[1]</code>.
+ * @type {Tone.Gain}
+ */
+ this.b = this.input[1] = new Tone.Gain();
+ /**
+ * The mix between the two inputs. A fade value of 0
+ * will output 100% <code>input[0]</code> and
+ * a value of 1 will output 100% <code>input[1]</code>.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);
+ /**
+ * equal power gain cross fade
+ * @private
+ * @type {Tone.EqualPowerGain}
+ */
+ this._equalPowerA = new Tone.EqualPowerGain();
+ /**
+ * equal power gain cross fade
+ * @private
+ * @type {Tone.EqualPowerGain}
+ */
+ this._equalPowerB = new Tone.EqualPowerGain();
+ /**
+ * invert the incoming signal
+ * @private
+ * @type {Tone}
+ */
+ this._invert = new Tone.Expr('1 - $0');
+ //connections
+ 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');
+ };
+ Tone.extend(Tone.CrossFade);
+ /**
+ * clean up
+ * @returns {Tone.CrossFade} this
+ */
+ Tone.CrossFade.prototype.dispose = function () {
+ Tone.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;
+ return this;
+ };
+ return Tone.CrossFade;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Filter is a filter which allows for all of the same native methods
+ * as the [BiquadFilterNode](http://webaudio.github.io/web-audio-api/#the-biquadfilternode-interface).
+ * Tone.Filter has the added ability to set the filter rolloff at -12
+ * (default), -24 and -48.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {Frequency|Object} [frequency] The cutoff frequency of the filter.
+ * @param {string=} type The type of filter.
+ * @param {number=} rolloff The drop in decibels per octave after the cutoff frequency.
+ * 3 choices: -12, -24, and -48
+ * @example
+ * var filter = new Tone.Filter(200, "highpass");
+ */
+ Tone.Filter = function () {
+ this.createInsOuts(1, 1);
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'type',
+ 'rolloff'
+ ], Tone.Filter.defaults);
+ /**
+ * the filter(s)
+ * @type {Array}
+ * @private
+ */
+ this._filters = [];
+ /**
+ * The cutoff frequency of the filter.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The detune parameter
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(0, Tone.Type.Cents);
+ /**
+ * The gain of the filter, only used in certain filter types
+ * @type {Number}
+ * @signal
+ */
+ this.gain = new Tone.Signal({
+ 'value': options.gain,
+ 'convert': false
+ });
+ /**
+ * The Q or Quality of the filter
+ * @type {Positive}
+ * @signal
+ */
+ this.Q = new Tone.Signal(options.Q);
+ /**
+ * the type of the filter
+ * @type {string}
+ * @private
+ */
+ this._type = options.type;
+ /**
+ * the rolloff value of the filter
+ * @type {number}
+ * @private
+ */
+ this._rolloff = options.rolloff;
+ //set the rolloff;
+ this.rolloff = options.rolloff;
+ this._readOnly([
+ 'detune',
+ 'frequency',
+ 'gain',
+ 'Q'
+ ]);
+ };
+ Tone.extend(Tone.Filter);
+ /**
+ * the default parameters
+ *
+ * @static
+ * @type {Object}
+ */
+ Tone.Filter.defaults = {
+ 'type': 'lowpass',
+ 'frequency': 350,
+ 'rolloff': -12,
+ 'Q': 1,
+ 'gain': 0
+ };
+ /**
+ * The type of the filter. Types: "lowpass", "highpass",
+ * "bandpass", "lowshelf", "highshelf", "notch", "allpass", or "peaking".
+ * @memberOf Tone.Filter#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.Filter.prototype, 'type', {
+ get: function () {
+ return this._type;
+ },
+ set: function (type) {
+ var types = [
+ 'lowpass',
+ 'highpass',
+ 'bandpass',
+ 'lowshelf',
+ 'highshelf',
+ 'notch',
+ 'allpass',
+ 'peaking'
+ ];
+ if (types.indexOf(type) === -1) {
+ throw new TypeError('Tone.Filter: invalid type ' + type);
+ }
+ this._type = type;
+ for (var i = 0; i < this._filters.length; i++) {
+ this._filters[i].type = type;
+ }
+ }
+ });
+ /**
+ * The rolloff of the filter which is the drop in db
+ * per octave. Implemented internally by cascading filters.
+ * Only accepts the values -12, -24, -48 and -96.
+ * @memberOf Tone.Filter#
+ * @type {number}
+ * @name rolloff
+ */
+ Object.defineProperty(Tone.Filter.prototype, 'rolloff', {
+ get: function () {
+ return this._rolloff;
+ },
+ set: function (rolloff) {
+ rolloff = parseInt(rolloff, 10);
+ var possibilities = [
+ -12,
+ -24,
+ -48,
+ -96
+ ];
+ var cascadingCount = possibilities.indexOf(rolloff);
+ //check the rolloff is valid
+ if (cascadingCount === -1) {
+ throw new RangeError('Tone.Filter: rolloff can only be -12, -24, -48 or -96');
+ }
+ cascadingCount += 1;
+ this._rolloff = rolloff;
+ //first disconnect the filters and throw them away
+ this.input.disconnect();
+ for (var i = 0; i < this._filters.length; i++) {
+ this._filters[i].disconnect();
+ this._filters[i] = null;
+ }
+ this._filters = new Array(cascadingCount);
+ for (var count = 0; count < cascadingCount; count++) {
+ var filter = this.context.createBiquadFilter();
+ filter.type = this._type;
+ this.frequency.connect(filter.frequency);
+ this.detune.connect(filter.detune);
+ this.Q.connect(filter.Q);
+ this.gain.connect(filter.gain);
+ this._filters[count] = filter;
+ }
+ //connect them up
+ var connectionChain = [this.input].concat(this._filters).concat([this.output]);
+ this.connectSeries.apply(this, connectionChain);
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.Filter} this
+ */
+ Tone.Filter.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ for (var i = 0; i < this._filters.length; i++) {
+ this._filters[i].disconnect();
+ this._filters[i] = null;
+ }
+ this._filters = null;
+ this._writable([
+ 'detune',
+ 'frequency',
+ 'gain',
+ 'Q'
+ ]);
+ this.frequency.dispose();
+ this.Q.dispose();
+ this.frequency = null;
+ this.Q = null;
+ this.detune.dispose();
+ this.detune = null;
+ this.gain.dispose();
+ this.gain = null;
+ return this;
+ };
+ return Tone.Filter;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Split the incoming signal into three bands (low, mid, high)
+ * with two crossover frequency controls.
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {Frequency|Object} [lowFrequency] the low/mid crossover frequency
+ * @param {Frequency} [highFrequency] the mid/high crossover frequency
+ */
+ Tone.MultibandSplit = function () {
+ var options = this.optionsObject(arguments, [
+ 'lowFrequency',
+ 'highFrequency'
+ ], Tone.MultibandSplit.defaults);
+ /**
+ * the input
+ * @type {Tone.Gain}
+ * @private
+ */
+ this.input = new Tone.Gain();
+ /**
+ * the outputs
+ * @type {Array}
+ * @private
+ */
+ this.output = new Array(3);
+ /**
+ * The low band. Alias for <code>output[0]</code>
+ * @type {Tone.Filter}
+ */
+ this.low = this.output[0] = new Tone.Filter(0, 'lowpass');
+ /**
+ * the lower filter of the mid band
+ * @type {Tone.Filter}
+ * @private
+ */
+ this._lowMidFilter = new Tone.Filter(0, 'highpass');
+ /**
+ * The mid band output. Alias for <code>output[1]</code>
+ * @type {Tone.Filter}
+ */
+ this.mid = this.output[1] = new Tone.Filter(0, 'lowpass');
+ /**
+ * The high band output. Alias for <code>output[2]</code>
+ * @type {Tone.Filter}
+ */
+ this.high = this.output[2] = new Tone.Filter(0, 'highpass');
+ /**
+ * The low/mid crossover frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.lowFrequency = new Tone.Signal(options.lowFrequency, Tone.Type.Frequency);
+ /**
+ * The mid/high crossover frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.highFrequency = new Tone.Signal(options.highFrequency, Tone.Type.Frequency);
+ /**
+ * The quality of all the filters
+ * @type {Number}
+ * @signal
+ */
+ this.Q = new Tone.Signal(options.Q);
+ this.input.fan(this.low, this.high);
+ this.input.chain(this._lowMidFilter, this.mid);
+ //the frequency control signal
+ this.lowFrequency.connect(this.low.frequency);
+ this.lowFrequency.connect(this._lowMidFilter.frequency);
+ this.highFrequency.connect(this.mid.frequency);
+ this.highFrequency.connect(this.high.frequency);
+ //the Q value
+ this.Q.connect(this.low.Q);
+ this.Q.connect(this._lowMidFilter.Q);
+ this.Q.connect(this.mid.Q);
+ this.Q.connect(this.high.Q);
+ this._readOnly([
+ 'high',
+ 'mid',
+ 'low',
+ 'highFrequency',
+ 'lowFrequency'
+ ]);
+ };
+ Tone.extend(Tone.MultibandSplit);
+ /**
+ * @private
+ * @static
+ * @type {Object}
+ */
+ Tone.MultibandSplit.defaults = {
+ 'lowFrequency': 400,
+ 'highFrequency': 2500,
+ 'Q': 1
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.MultibandSplit} this
+ */
+ Tone.MultibandSplit.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'high',
+ 'mid',
+ 'low',
+ 'highFrequency',
+ 'lowFrequency'
+ ]);
+ this.low.dispose();
+ this.low = null;
+ this._lowMidFilter.dispose();
+ this._lowMidFilter = null;
+ this.mid.dispose();
+ this.mid = null;
+ this.high.dispose();
+ this.high = null;
+ this.lowFrequency.dispose();
+ this.lowFrequency = null;
+ this.highFrequency.dispose();
+ this.highFrequency = null;
+ this.Q.dispose();
+ this.Q = null;
+ return this;
+ };
+ return Tone.MultibandSplit;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.EQ3 is a three band EQ with control over low, mid, and high gain as
+ * well as the low and high crossover frequencies.
+ *
+ * @constructor
+ * @extends {Tone}
+ *
+ * @param {Decibels|Object} [lowLevel] The gain applied to the lows.
+ * @param {Decibels} [midLevel] The gain applied to the mid.
+ * @param {Decibels} [highLevel] The gain applied to the high.
+ * @example
+ * var eq = new Tone.EQ3(-10, 3, -20);
+ */
+ Tone.EQ3 = function () {
+ var options = this.optionsObject(arguments, [
+ 'low',
+ 'mid',
+ 'high'
+ ], Tone.EQ3.defaults);
+ /**
+ * the output node
+ * @type {GainNode}
+ * @private
+ */
+ this.output = new Tone.Gain();
+ /**
+ * the multiband split
+ * @type {Tone.MultibandSplit}
+ * @private
+ */
+ this._multibandSplit = this.input = new Tone.MultibandSplit({
+ 'lowFrequency': options.lowFrequency,
+ 'highFrequency': options.highFrequency
+ });
+ /**
+ * The gain for the lower signals
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._lowGain = new Tone.Gain(options.low, Tone.Type.Decibels);
+ /**
+ * The gain for the mid signals
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._midGain = new Tone.Gain(options.mid, Tone.Type.Decibels);
+ /**
+ * The gain in decibels of the high part
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._highGain = new Tone.Gain(options.high, Tone.Type.Decibels);
+ /**
+ * The gain in decibels of the low part
+ * @type {Decibels}
+ * @signal
+ */
+ this.low = this._lowGain.gain;
+ /**
+ * The gain in decibels of the mid part
+ * @type {Decibels}
+ * @signal
+ */
+ this.mid = this._midGain.gain;
+ /**
+ * The gain in decibels of the high part
+ * @type {Decibels}
+ * @signal
+ */
+ this.high = this._highGain.gain;
+ /**
+ * The Q value for all of the filters.
+ * @type {Positive}
+ * @signal
+ */
+ this.Q = this._multibandSplit.Q;
+ /**
+ * The low/mid crossover frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.lowFrequency = this._multibandSplit.lowFrequency;
+ /**
+ * The mid/high crossover frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.highFrequency = this._multibandSplit.highFrequency;
+ //the frequency bands
+ this._multibandSplit.low.chain(this._lowGain, this.output);
+ this._multibandSplit.mid.chain(this._midGain, this.output);
+ this._multibandSplit.high.chain(this._highGain, this.output);
+ this._readOnly([
+ 'low',
+ 'mid',
+ 'high',
+ 'lowFrequency',
+ 'highFrequency'
+ ]);
+ };
+ Tone.extend(Tone.EQ3);
+ /**
+ * the default values
+ */
+ Tone.EQ3.defaults = {
+ 'low': 0,
+ 'mid': 0,
+ 'high': 0,
+ 'lowFrequency': 400,
+ 'highFrequency': 2500
+ };
+ /**
+ * clean up
+ * @returns {Tone.EQ3} this
+ */
+ Tone.EQ3.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'low',
+ 'mid',
+ 'high',
+ 'lowFrequency',
+ 'highFrequency'
+ ]);
+ this._multibandSplit.dispose();
+ this._multibandSplit = null;
+ this.lowFrequency = null;
+ this.highFrequency = null;
+ this._lowGain.dispose();
+ this._lowGain = null;
+ this._midGain.dispose();
+ this._midGain = null;
+ this._highGain.dispose();
+ this._highGain = null;
+ this.low = null;
+ this.mid = null;
+ this.high = null;
+ this.Q = null;
+ return this;
+ };
+ return Tone.EQ3;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Performs a linear scaling on an input signal.
+ * Scales a NormalRange input to between
+ * outputMin and outputMax.
+ *
+ * @constructor
+ * @extends {Tone.SignalBase}
+ * @param {number} [outputMin=0] The output value when the input is 0.
+ * @param {number} [outputMax=1] The output value when the input is 1.
+ * @example
+ * var scale = new Tone.Scale(50, 100);
+ * var signal = new Tone.Signal(0.5).connect(scale);
+ * //the output of scale equals 75
+ */
+ Tone.Scale = function (outputMin, outputMax) {
+ /**
+ * @private
+ * @type {number}
+ */
+ this._outputMin = this.defaultArg(outputMin, 0);
+ /**
+ * @private
+ * @type {number}
+ */
+ this._outputMax = this.defaultArg(outputMax, 1);
+ /**
+ * @private
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._scale = this.input = new Tone.Multiply(1);
+ /**
+ * @private
+ * @type {Tone.Add}
+ * @private
+ */
+ this._add = this.output = new Tone.Add(0);
+ this._scale.connect(this._add);
+ this._setRange();
+ };
+ Tone.extend(Tone.Scale, Tone.SignalBase);
+ /**
+ * The minimum output value. This number is output when
+ * the value input value is 0.
+ * @memberOf Tone.Scale#
+ * @type {number}
+ * @name min
+ */
+ Object.defineProperty(Tone.Scale.prototype, 'min', {
+ get: function () {
+ return this._outputMin;
+ },
+ set: function (min) {
+ this._outputMin = min;
+ this._setRange();
+ }
+ });
+ /**
+ * The maximum output value. This number is output when
+ * the value input value is 1.
+ * @memberOf Tone.Scale#
+ * @type {number}
+ * @name max
+ */
+ Object.defineProperty(Tone.Scale.prototype, 'max', {
+ get: function () {
+ return this._outputMax;
+ },
+ set: function (max) {
+ this._outputMax = max;
+ this._setRange();
+ }
+ });
+ /**
+ * set the values
+ * @private
+ */
+ Tone.Scale.prototype._setRange = function () {
+ this._add.value = this._outputMin;
+ this._scale.value = this._outputMax - this._outputMin;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Scale} this
+ */
+ Tone.Scale.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._add.dispose();
+ this._add = null;
+ this._scale.dispose();
+ this._scale = null;
+ return this;
+ };
+ return Tone.Scale;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Performs an exponential scaling on an input signal.
+ * Scales a NormalRange value [0,1] exponentially
+ * to the output range of outputMin to outputMax.
+ *
+ * @constructor
+ * @extends {Tone.SignalBase}
+ * @param {number} [outputMin=0] The output value when the input is 0.
+ * @param {number} [outputMax=1] The output value when the input is 1.
+ * @param {number} [exponent=2] The exponent which scales the incoming signal.
+ * @example
+ * var scaleExp = new Tone.ScaleExp(0, 100, 2);
+ * var signal = new Tone.Signal(0.5).connect(scaleExp);
+ */
+ Tone.ScaleExp = function (outputMin, outputMax, exponent) {
+ /**
+ * scale the input to the output range
+ * @type {Tone.Scale}
+ * @private
+ */
+ this._scale = this.output = new Tone.Scale(outputMin, outputMax);
+ /**
+ * @private
+ * @type {Tone.Pow}
+ * @private
+ */
+ this._exp = this.input = new Tone.Pow(this.defaultArg(exponent, 2));
+ this._exp.connect(this._scale);
+ };
+ Tone.extend(Tone.ScaleExp, Tone.SignalBase);
+ /**
+ * Instead of interpolating linearly between the <code>min</code> and
+ * <code>max</code> values, setting the exponent will interpolate between
+ * the two values with an exponential curve.
+ * @memberOf Tone.ScaleExp#
+ * @type {number}
+ * @name exponent
+ */
+ Object.defineProperty(Tone.ScaleExp.prototype, 'exponent', {
+ get: function () {
+ return this._exp.value;
+ },
+ set: function (exp) {
+ this._exp.value = exp;
+ }
+ });
+ /**
+ * The minimum output value. This number is output when
+ * the value input value is 0.
+ * @memberOf Tone.ScaleExp#
+ * @type {number}
+ * @name min
+ */
+ Object.defineProperty(Tone.ScaleExp.prototype, 'min', {
+ get: function () {
+ return this._scale.min;
+ },
+ set: function (min) {
+ this._scale.min = min;
+ }
+ });
+ /**
+ * The maximum output value. This number is output when
+ * the value input value is 1.
+ * @memberOf Tone.ScaleExp#
+ * @type {number}
+ * @name max
+ */
+ Object.defineProperty(Tone.ScaleExp.prototype, 'max', {
+ get: function () {
+ return this._scale.max;
+ },
+ set: function (max) {
+ this._scale.max = max;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.ScaleExp} this
+ */
+ Tone.ScaleExp.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._scale.dispose();
+ this._scale = null;
+ this._exp.dispose();
+ this._exp = null;
+ return this;
+ };
+ return Tone.ScaleExp;
+ });
+ Module(function (Tone) {
+
+ /**
+ * createDelay shim
+ * @private
+ */
+ if (window.DelayNode && !AudioContext.prototype.createDelay) {
+ AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode;
+ }
+ /**
+ * @class Wrapper around Web Audio's native [DelayNode](http://webaudio.github.io/web-audio-api/#the-delaynode-interface).
+ * @extends {Tone}
+ * @param {Time=} delayTime The delay applied to the incoming signal.
+ * @param {Time=} maxDelay The maximum delay time.
+ */
+ Tone.Delay = function () {
+ var options = this.optionsObject(arguments, [
+ 'delayTime',
+ 'maxDelay'
+ ], Tone.Delay.defaults);
+ /**
+ * The native delay node
+ * @type {DelayNode}
+ * @private
+ */
+ this._delayNode = this.input = this.output = this.context.createDelay(this.toSeconds(options.maxDelay));
+ /**
+ * The amount of time the incoming signal is
+ * delayed.
+ * @type {Tone.Param}
+ * @signal
+ */
+ this.delayTime = new Tone.Param({
+ 'param': this._delayNode.delayTime,
+ 'units': Tone.Type.Time,
+ 'value': options.delayTime
+ });
+ this._readOnly('delayTime');
+ };
+ Tone.extend(Tone.Delay);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.Delay.defaults = {
+ 'maxDelay': 1,
+ 'delayTime': 0
+ };
+ /**
+ * Clean up.
+ * @return {Tone.Delay} this
+ */
+ Tone.Delay.prototype.dispose = function () {
+ Tone.Param.prototype.dispose.call(this);
+ this._delayNode.disconnect();
+ this._delayNode = null;
+ this._writable('delayTime');
+ this.delayTime = null;
+ return this;
+ };
+ return Tone.Delay;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Comb filters are basic building blocks for physical modeling. Read more
+ * about comb filters on [CCRMA's website](https://ccrma.stanford.edu/~jos/pasp/Feedback_Comb_Filters.html).
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {Time|Object} [delayTime] The delay time of the filter.
+ * @param {NormalRange=} resonance The amount of feedback the filter has.
+ */
+ Tone.FeedbackCombFilter = function () {
+ var options = this.optionsObject(arguments, [
+ 'delayTime',
+ 'resonance'
+ ], Tone.FeedbackCombFilter.defaults);
+ /**
+ * the delay node
+ * @type {DelayNode}
+ * @private
+ */
+ this._delay = this.input = this.output = new Tone.Delay(options.delayTime);
+ /**
+ * The amount of delay of the comb filter.
+ * @type {Time}
+ * @signal
+ */
+ this.delayTime = this._delay.delayTime;
+ /**
+ * the feedback node
+ * @type {GainNode}
+ * @private
+ */
+ this._feedback = new Tone.Gain(options.resonance, Tone.Type.NormalRange);
+ /**
+ * The amount of feedback of the delayed signal.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.resonance = this._feedback.gain;
+ this._delay.chain(this._feedback, this._delay);
+ this._readOnly([
+ 'resonance',
+ 'delayTime'
+ ]);
+ };
+ Tone.extend(Tone.FeedbackCombFilter);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.FeedbackCombFilter.defaults = {
+ 'delayTime': 0.1,
+ 'resonance': 0.5
+ };
+ /**
+ * clean up
+ * @returns {Tone.FeedbackCombFilter} this
+ */
+ Tone.FeedbackCombFilter.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'resonance',
+ 'delayTime'
+ ]);
+ this._delay.dispose();
+ this._delay = null;
+ this.delayTime = null;
+ this._feedback.dispose();
+ this._feedback = null;
+ this.resonance = null;
+ return this;
+ };
+ return Tone.FeedbackCombFilter;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Follower is a crude envelope follower which will follow
+ * the amplitude of an incoming signal.
+ * Take care with small (< 0.02) attack or decay values
+ * as follower has some ripple which is exaggerated
+ * at these values. Read more about envelope followers (also known
+ * as envelope detectors) on [Wikipedia](https://en.wikipedia.org/wiki/Envelope_detector).
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {Time|Object} [attack] The rate at which the follower rises.
+ * @param {Time=} release The rate at which the folower falls.
+ * @example
+ * var follower = new Tone.Follower(0.2, 0.4);
+ */
+ Tone.Follower = function () {
+ this.createInsOuts(1, 1);
+ var options = this.optionsObject(arguments, [
+ 'attack',
+ 'release'
+ ], Tone.Follower.defaults);
+ /**
+ * @type {Tone.Abs}
+ * @private
+ */
+ this._abs = new Tone.Abs();
+ /**
+ * the lowpass filter which smooths the input
+ * @type {BiquadFilterNode}
+ * @private
+ */
+ this._filter = this.context.createBiquadFilter();
+ this._filter.type = 'lowpass';
+ this._filter.frequency.value = 0;
+ this._filter.Q.value = -100;
+ /**
+ * @type {WaveShaperNode}
+ * @private
+ */
+ this._frequencyValues = new Tone.WaveShaper();
+ /**
+ * @type {Tone.Subtract}
+ * @private
+ */
+ this._sub = new Tone.Subtract();
+ /**
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._delay = new Tone.Delay(this.blockTime);
+ /**
+ * this keeps it far from 0, even for very small differences
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._mult = new Tone.Multiply(10000);
+ /**
+ * @private
+ * @type {number}
+ */
+ this._attack = options.attack;
+ /**
+ * @private
+ * @type {number}
+ */
+ this._release = options.release;
+ //the smoothed signal to get the values
+ this.input.chain(this._abs, this._filter, this.output);
+ //the difference path
+ this._abs.connect(this._sub, 0, 1);
+ this._filter.chain(this._delay, this._sub);
+ //threshold the difference and use the thresh to set the frequency
+ this._sub.chain(this._mult, this._frequencyValues, this._filter.frequency);
+ //set the attack and release values in the table
+ this._setAttackRelease(this._attack, this._release);
+ };
+ Tone.extend(Tone.Follower);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.Follower.defaults = {
+ 'attack': 0.05,
+ 'release': 0.5
+ };
+ /**
+ * sets the attack and release times in the wave shaper
+ * @param {Time} attack
+ * @param {Time} release
+ * @private
+ */
+ Tone.Follower.prototype._setAttackRelease = function (attack, release) {
+ var minTime = this.blockTime;
+ attack = Tone.Time(attack).toFrequency();
+ release = Tone.Time(release).toFrequency();
+ attack = Math.max(attack, minTime);
+ release = Math.max(release, minTime);
+ this._frequencyValues.setMap(function (val) {
+ if (val <= 0) {
+ return attack;
+ } else {
+ return release;
+ }
+ });
+ };
+ /**
+ * The attack time.
+ * @memberOf Tone.Follower#
+ * @type {Time}
+ * @name attack
+ */
+ Object.defineProperty(Tone.Follower.prototype, 'attack', {
+ get: function () {
+ return this._attack;
+ },
+ set: function (attack) {
+ this._attack = attack;
+ this._setAttackRelease(this._attack, this._release);
+ }
+ });
+ /**
+ * The release time.
+ * @memberOf Tone.Follower#
+ * @type {Time}
+ * @name release
+ */
+ Object.defineProperty(Tone.Follower.prototype, 'release', {
+ get: function () {
+ return this._release;
+ },
+ set: function (release) {
+ this._release = release;
+ this._setAttackRelease(this._attack, this._release);
+ }
+ });
+ /**
+ * Borrows the connect method from Signal so that the output can be used
+ * as a Tone.Signal control signal.
+ * @function
+ */
+ Tone.Follower.prototype.connect = Tone.Signal.prototype.connect;
+ /**
+ * dispose
+ * @returns {Tone.Follower} this
+ */
+ Tone.Follower.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._filter.disconnect();
+ this._filter = null;
+ this._frequencyValues.disconnect();
+ this._frequencyValues = null;
+ this._delay.dispose();
+ this._delay = null;
+ this._sub.disconnect();
+ this._sub = null;
+ this._abs.dispose();
+ this._abs = null;
+ this._mult.dispose();
+ this._mult = null;
+ this._curve = null;
+ return this;
+ };
+ return Tone.Follower;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.ScaledEnvelop is an envelope which can be scaled
+ * to any range. It's useful for applying an envelope
+ * to a frequency or any other non-NormalRange signal
+ * parameter.
+ *
+ * @extends {Tone.Envelope}
+ * @constructor
+ * @param {Time|Object} [attack] the attack time in seconds
+ * @param {Time} [decay] the decay time in seconds
+ * @param {number} [sustain] a percentage (0-1) of the full amplitude
+ * @param {Time} [release] the release time in seconds
+ * @example
+ * var scaledEnv = new Tone.ScaledEnvelope({
+ * "attack" : 0.2,
+ * "min" : 200,
+ * "max" : 2000
+ * });
+ * scaledEnv.connect(oscillator.frequency);
+ */
+ Tone.ScaledEnvelope = function () {
+ //get all of the defaults
+ var options = this.optionsObject(arguments, [
+ 'attack',
+ 'decay',
+ 'sustain',
+ 'release'
+ ], Tone.Envelope.defaults);
+ Tone.Envelope.call(this, options);
+ options = this.defaultArg(options, Tone.ScaledEnvelope.defaults);
+ /**
+ * scale the incoming signal by an exponent
+ * @type {Tone.Pow}
+ * @private
+ */
+ this._exp = this.output = new Tone.Pow(options.exponent);
+ /**
+ * scale the signal to the desired range
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._scale = this.output = new Tone.Scale(options.min, options.max);
+ this._sig.chain(this._exp, this._scale);
+ };
+ Tone.extend(Tone.ScaledEnvelope, Tone.Envelope);
+ /**
+ * the default parameters
+ * @static
+ */
+ Tone.ScaledEnvelope.defaults = {
+ 'min': 0,
+ 'max': 1,
+ 'exponent': 1
+ };
+ /**
+ * The envelope's min output value. This is the value which it
+ * starts at.
+ * @memberOf Tone.ScaledEnvelope#
+ * @type {number}
+ * @name min
+ */
+ Object.defineProperty(Tone.ScaledEnvelope.prototype, 'min', {
+ get: function () {
+ return this._scale.min;
+ },
+ set: function (min) {
+ this._scale.min = min;
+ }
+ });
+ /**
+ * The envelope's max output value. In other words, the value
+ * at the peak of the attack portion of the envelope.
+ * @memberOf Tone.ScaledEnvelope#
+ * @type {number}
+ * @name max
+ */
+ Object.defineProperty(Tone.ScaledEnvelope.prototype, 'max', {
+ get: function () {
+ return this._scale.max;
+ },
+ set: function (max) {
+ this._scale.max = max;
+ }
+ });
+ /**
+ * The envelope's exponent value.
+ * @memberOf Tone.ScaledEnvelope#
+ * @type {number}
+ * @name exponent
+ */
+ Object.defineProperty(Tone.ScaledEnvelope.prototype, 'exponent', {
+ get: function () {
+ return this._exp.value;
+ },
+ set: function (exp) {
+ this._exp.value = exp;
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.ScaledEnvelope} this
+ */
+ Tone.ScaledEnvelope.prototype.dispose = function () {
+ Tone.Envelope.prototype.dispose.call(this);
+ this._scale.dispose();
+ this._scale = null;
+ this._exp.dispose();
+ this._exp = null;
+ return this;
+ };
+ return Tone.ScaledEnvelope;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.FrequencyEnvelope is a Tone.ScaledEnvelope, but instead of `min` and `max`
+ * it's got a `baseFrequency` and `octaves` parameter.
+ *
+ * @extends {Tone.Envelope}
+ * @constructor
+ * @param {Time|Object} [attack] the attack time in seconds
+ * @param {Time} [decay] the decay time in seconds
+ * @param {number} [sustain] a percentage (0-1) of the full amplitude
+ * @param {Time} [release] the release time in seconds
+ * @example
+ * var env = new Tone.FrequencyEnvelope({
+ * "attack" : 0.2,
+ * "baseFrequency" : "C2",
+ * "octaves" : 4
+ * });
+ * scaledEnv.connect(oscillator.frequency);
+ */
+ Tone.FrequencyEnvelope = function () {
+ var options = this.optionsObject(arguments, [
+ 'attack',
+ 'decay',
+ 'sustain',
+ 'release'
+ ], Tone.Envelope.defaults);
+ Tone.ScaledEnvelope.call(this, options);
+ options = this.defaultArg(options, Tone.FrequencyEnvelope.defaults);
+ /**
+ * Stores the octave value
+ * @type {Positive}
+ * @private
+ */
+ this._octaves = options.octaves;
+ //setup
+ this.baseFrequency = options.baseFrequency;
+ this.octaves = options.octaves;
+ };
+ Tone.extend(Tone.FrequencyEnvelope, Tone.Envelope);
+ /**
+ * the default parameters
+ * @static
+ */
+ Tone.FrequencyEnvelope.defaults = {
+ 'baseFrequency': 200,
+ 'octaves': 4,
+ 'exponent': 2
+ };
+ /**
+ * The envelope's mininum output value. This is the value which it
+ * starts at.
+ * @memberOf Tone.FrequencyEnvelope#
+ * @type {Frequency}
+ * @name baseFrequency
+ */
+ Object.defineProperty(Tone.FrequencyEnvelope.prototype, 'baseFrequency', {
+ get: function () {
+ return this._scale.min;
+ },
+ set: function (min) {
+ this._scale.min = this.toFrequency(min);
+ //also update the octaves
+ this.octaves = this._octaves;
+ }
+ });
+ /**
+ * The number of octaves above the baseFrequency that the
+ * envelope will scale to.
+ * @memberOf Tone.FrequencyEnvelope#
+ * @type {Positive}
+ * @name octaves
+ */
+ Object.defineProperty(Tone.FrequencyEnvelope.prototype, 'octaves', {
+ get: function () {
+ return this._octaves;
+ },
+ set: function (octaves) {
+ this._octaves = octaves;
+ this._scale.max = this.baseFrequency * Math.pow(2, octaves);
+ }
+ });
+ /**
+ * The envelope's exponent value.
+ * @memberOf Tone.FrequencyEnvelope#
+ * @type {number}
+ * @name exponent
+ */
+ Object.defineProperty(Tone.FrequencyEnvelope.prototype, 'exponent', {
+ get: function () {
+ return this._exp.value;
+ },
+ set: function (exp) {
+ this._exp.value = exp;
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.FrequencyEnvelope} this
+ */
+ Tone.FrequencyEnvelope.prototype.dispose = function () {
+ Tone.ScaledEnvelope.prototype.dispose.call(this);
+ return this;
+ };
+ return Tone.FrequencyEnvelope;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Gate only passes a signal through when the incoming
+ * signal exceeds a specified threshold. To do this, Gate uses
+ * a Tone.Follower to follow the amplitude of the incoming signal.
+ * A common implementation of this class is a [Noise Gate](https://en.wikipedia.org/wiki/Noise_gate).
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {Decibels|Object} [threshold] The threshold above which the gate will open.
+ * @param {Time=} attack The follower's attack time
+ * @param {Time=} release The follower's release time
+ * @example
+ * var gate = new Tone.Gate(-30, 0.2, 0.3).toMaster();
+ * var mic = new Tone.UserMedia().connect(gate);
+ * //the gate will only pass through the incoming
+ * //signal when it's louder than -30db
+ */
+ Tone.Gate = function () {
+ this.createInsOuts(1, 1);
+ var options = this.optionsObject(arguments, [
+ 'threshold',
+ 'attack',
+ 'release'
+ ], Tone.Gate.defaults);
+ /**
+ * @type {Tone.Follower}
+ * @private
+ */
+ this._follower = new Tone.Follower(options.attack, options.release);
+ /**
+ * @type {Tone.GreaterThan}
+ * @private
+ */
+ this._gt = new Tone.GreaterThan(this.dbToGain(options.threshold));
+ //the connections
+ this.input.connect(this.output);
+ //the control signal
+ this.input.chain(this._gt, this._follower, this.output.gain);
+ };
+ Tone.extend(Tone.Gate);
+ /**
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.Gate.defaults = {
+ 'attack': 0.1,
+ 'release': 0.1,
+ 'threshold': -40
+ };
+ /**
+ * The threshold of the gate in decibels
+ * @memberOf Tone.Gate#
+ * @type {Decibels}
+ * @name threshold
+ */
+ Object.defineProperty(Tone.Gate.prototype, 'threshold', {
+ get: function () {
+ return this.gainToDb(this._gt.value);
+ },
+ set: function (thresh) {
+ this._gt.value = this.dbToGain(thresh);
+ }
+ });
+ /**
+ * The attack speed of the gate
+ * @memberOf Tone.Gate#
+ * @type {Time}
+ * @name attack
+ */
+ Object.defineProperty(Tone.Gate.prototype, 'attack', {
+ get: function () {
+ return this._follower.attack;
+ },
+ set: function (attackTime) {
+ this._follower.attack = attackTime;
+ }
+ });
+ /**
+ * The release speed of the gate
+ * @memberOf Tone.Gate#
+ * @type {Time}
+ * @name release
+ */
+ Object.defineProperty(Tone.Gate.prototype, 'release', {
+ get: function () {
+ return this._follower.release;
+ },
+ set: function (releaseTime) {
+ this._follower.release = releaseTime;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Gate} this
+ */
+ Tone.Gate.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._follower.dispose();
+ this._gt.dispose();
+ this._follower = null;
+ this._gt = null;
+ return this;
+ };
+ return Tone.Gate;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A Timeline State. Provides the methods: <code>setStateAtTime("state", time)</code>
+ * and <code>getValueAtTime(time)</code>.
+ *
+ * @extends {Tone.Timeline}
+ * @param {String} initial The initial state of the TimelineState.
+ * Defaults to <code>undefined</code>
+ */
+ Tone.TimelineState = function (initial) {
+ Tone.Timeline.call(this);
+ /**
+ * The initial state
+ * @private
+ * @type {String}
+ */
+ this._initial = initial;
+ };
+ Tone.extend(Tone.TimelineState, Tone.Timeline);
+ /**
+ * Returns the scheduled state scheduled before or at
+ * the given time.
+ * @param {Number} time The time to query.
+ * @return {String} The name of the state input in setStateAtTime.
+ */
+ Tone.TimelineState.prototype.getValueAtTime = function (time) {
+ var event = this.get(time);
+ if (event !== null) {
+ return event.state;
+ } else {
+ return this._initial;
+ }
+ };
+ /**
+ * Returns the scheduled state scheduled before or at
+ * the given time.
+ * @param {String} state The name of the state to set.
+ * @param {Number} time The time to query.
+ */
+ Tone.TimelineState.prototype.setStateAtTime = function (state, time) {
+ this.add({
+ 'state': state,
+ 'time': time
+ });
+ };
+ return Tone.TimelineState;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A sample accurate clock which provides a callback at the given rate.
+ * While the callback is not sample-accurate (it is still susceptible to
+ * loose JS timing), the time passed in as the argument to the callback
+ * is precise. For most applications, it is better to use Tone.Transport
+ * instead of the Clock by itself since you can synchronize multiple callbacks.
+ *
+ * @constructor
+ * @extends {Tone.Emitter}
+ * @param {function} callback The callback to be invoked with the time of the audio event
+ * @param {Frequency} frequency The rate of the callback
+ * @example
+ * //the callback will be invoked approximately once a second
+ * //and will print the time exactly once a second apart.
+ * var clock = new Tone.Clock(function(time){
+ * console.log(time);
+ * }, 1);
+ */
+ Tone.Clock = function () {
+ Tone.Emitter.call(this);
+ var options = this.optionsObject(arguments, [
+ 'callback',
+ 'frequency'
+ ], Tone.Clock.defaults);
+ /**
+ * The callback function to invoke at the scheduled tick.
+ * @type {Function}
+ */
+ this.callback = options.callback;
+ /**
+ * The next time the callback is scheduled.
+ * @type {Number}
+ * @private
+ */
+ this._nextTick = 0;
+ /**
+ * The last state of the clock.
+ * @type {State}
+ * @private
+ */
+ this._lastState = Tone.State.Stopped;
+ /**
+ * The rate the callback function should be invoked.
+ * @type {BPM}
+ * @signal
+ */
+ this.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);
+ this._readOnly('frequency');
+ /**
+ * The number of times the callback was invoked. Starts counting at 0
+ * and increments after the callback was invoked.
+ * @type {Ticks}
+ * @readOnly
+ */
+ this.ticks = 0;
+ /**
+ * The state timeline
+ * @type {Tone.TimelineState}
+ * @private
+ */
+ this._state = new Tone.TimelineState(Tone.State.Stopped);
+ /**
+ * The loop function bound to its context.
+ * This is necessary to remove the event in the end.
+ * @type {Function}
+ * @private
+ */
+ this._boundLoop = this._loop.bind(this);
+ //bind a callback to the worker thread
+ this.context.on('tick', this._boundLoop);
+ };
+ Tone.extend(Tone.Clock, Tone.Emitter);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.Clock.defaults = {
+ 'callback': Tone.noOp,
+ 'frequency': 1,
+ 'lookAhead': 'auto'
+ };
+ /**
+ * Returns the playback state of the source, either "started", "stopped" or "paused".
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.Clock#
+ * @name state
+ */
+ Object.defineProperty(Tone.Clock.prototype, 'state', {
+ get: function () {
+ return this._state.getValueAtTime(this.now());
+ }
+ });
+ /**
+ * Start the clock at the given time. Optionally pass in an offset
+ * of where to start the tick counter from.
+ * @param {Time} time The time the clock should start
+ * @param {Ticks=} offset Where the tick counter starts counting from.
+ * @return {Tone.Clock} this
+ */
+ Tone.Clock.prototype.start = function (time, offset) {
+ time = this.toSeconds(time);
+ if (this._state.getValueAtTime(time) !== Tone.State.Started) {
+ this._state.add({
+ 'state': Tone.State.Started,
+ 'time': time,
+ 'offset': offset
+ });
+ }
+ return this;
+ };
+ /**
+ * Stop the clock. Stopping the clock resets the tick counter to 0.
+ * @param {Time} [time=now] The time when the clock should stop.
+ * @returns {Tone.Clock} this
+ * @example
+ * clock.stop();
+ */
+ Tone.Clock.prototype.stop = function (time) {
+ time = this.toSeconds(time);
+ this._state.cancel(time);
+ this._state.setStateAtTime(Tone.State.Stopped, time);
+ return this;
+ };
+ /**
+ * Pause the clock. Pausing does not reset the tick counter.
+ * @param {Time} [time=now] The time when the clock should stop.
+ * @returns {Tone.Clock} this
+ */
+ Tone.Clock.prototype.pause = function (time) {
+ time = this.toSeconds(time);
+ if (this._state.getValueAtTime(time) === Tone.State.Started) {
+ this._state.setStateAtTime(Tone.State.Paused, time);
+ }
+ return this;
+ };
+ /**
+ * The scheduling loop.
+ * @param {Number} time The current page time starting from 0
+ * when the page was loaded.
+ * @private
+ */
+ Tone.Clock.prototype._loop = function () {
+ //get the frequency value to compute the value of the next loop
+ var now = this.now();
+ //if it's started
+ var lookAhead = this.context.lookAhead;
+ var updateInterval = this.context.updateInterval;
+ var lagCompensation = this.context.lag * 2;
+ var loopInterval = now + lookAhead + updateInterval + lagCompensation;
+ while (loopInterval > this._nextTick && this._state) {
+ var currentState = this._state.getValueAtTime(this._nextTick);
+ if (currentState !== this._lastState) {
+ this._lastState = currentState;
+ var event = this._state.get(this._nextTick);
+ // emit an event
+ if (currentState === Tone.State.Started) {
+ //correct the time
+ this._nextTick = event.time;
+ if (!this.isUndef(event.offset)) {
+ this.ticks = event.offset;
+ }
+ this.emit('start', event.time, this.ticks);
+ } else if (currentState === Tone.State.Stopped) {
+ this.ticks = 0;
+ this.emit('stop', event.time);
+ } else if (currentState === Tone.State.Paused) {
+ this.emit('pause', event.time);
+ }
+ }
+ var tickTime = this._nextTick;
+ if (this.frequency) {
+ this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);
+ if (currentState === Tone.State.Started) {
+ this.callback(tickTime);
+ this.ticks++;
+ }
+ }
+ }
+ };
+ /**
+ * Returns the scheduled state at the given time.
+ * @param {Time} time The time to query.
+ * @return {String} The name of the state input in setStateAtTime.
+ * @example
+ * clock.start("+0.1");
+ * clock.getStateAtTime("+0.1"); //returns "started"
+ */
+ Tone.Clock.prototype.getStateAtTime = function (time) {
+ time = this.toSeconds(time);
+ return this._state.getValueAtTime(time);
+ };
+ /**
+ * Clean up
+ * @returns {Tone.Clock} this
+ */
+ Tone.Clock.prototype.dispose = function () {
+ Tone.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 = Infinity;
+ this.callback = null;
+ this._state.dispose();
+ this._state = null;
+ };
+ return Tone.Clock;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Similar to Tone.Timeline, but all events represent
+ * intervals with both "time" and "duration" times. The
+ * events are placed in a tree structure optimized
+ * for querying an intersection point with the timeline
+ * events. Internally uses an [Interval Tree](https://en.wikipedia.org/wiki/Interval_tree)
+ * to represent the data.
+ * @extends {Tone}
+ */
+ Tone.IntervalTimeline = function () {
+ /**
+ * The root node of the inteval tree
+ * @type {IntervalNode}
+ * @private
+ */
+ this._root = null;
+ /**
+ * Keep track of the length of the timeline.
+ * @type {Number}
+ * @private
+ */
+ this._length = 0;
+ };
+ Tone.extend(Tone.IntervalTimeline);
+ /**
+ * The event to add to the timeline. All events must
+ * have a time and duration value
+ * @param {Object} event The event to add to the timeline
+ * @return {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.add = function (event) {
+ if (this.isUndef(event.time) || this.isUndef(event.duration)) {
+ throw new Error('Tone.IntervalTimeline: events must have time and duration parameters');
+ }
+ var node = new IntervalNode(event.time, event.time + event.duration, event);
+ if (this._root === null) {
+ this._root = node;
+ } else {
+ this._root.insert(node);
+ }
+ this._length++;
+ // Restructure tree to be balanced
+ while (node !== null) {
+ node.updateHeight();
+ node.updateMax();
+ this._rebalance(node);
+ node = node.parent;
+ }
+ return this;
+ };
+ /**
+ * Remove an event from the timeline.
+ * @param {Object} event The event to remove from the timeline
+ * @return {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.remove = function (event) {
+ if (this._root !== null) {
+ var results = [];
+ this._root.search(event.time, results);
+ for (var i = 0; i < results.length; i++) {
+ var node = results[i];
+ if (node.event === event) {
+ this._removeNode(node);
+ this._length--;
+ break;
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * The number of items in the timeline.
+ * @type {Number}
+ * @memberOf Tone.IntervalTimeline#
+ * @name length
+ * @readOnly
+ */
+ Object.defineProperty(Tone.IntervalTimeline.prototype, 'length', {
+ get: function () {
+ return this._length;
+ }
+ });
+ /**
+ * Remove events whose time time is after the given time
+ * @param {Number} time The time to query.
+ * @returns {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.cancel = function (after) {
+ this.forEachAfter(after, function (event) {
+ this.remove(event);
+ }.bind(this));
+ return this;
+ };
+ /**
+ * Set the root node as the given node
+ * @param {IntervalNode} node
+ * @private
+ */
+ Tone.IntervalTimeline.prototype._setRoot = function (node) {
+ this._root = node;
+ if (this._root !== null) {
+ this._root.parent = null;
+ }
+ };
+ /**
+ * Replace the references to the node in the node's parent
+ * with the replacement node.
+ * @param {IntervalNode} node
+ * @param {IntervalNode} replacement
+ * @private
+ */
+ Tone.IntervalTimeline.prototype._replaceNodeInParent = function (node, replacement) {
+ if (node.parent !== null) {
+ if (node.isLeftChild()) {
+ node.parent.left = replacement;
+ } else {
+ node.parent.right = replacement;
+ }
+ this._rebalance(node.parent);
+ } else {
+ this._setRoot(replacement);
+ }
+ };
+ /**
+ * Remove the node from the tree and replace it with
+ * a successor which follows the schema.
+ * @param {IntervalNode} node
+ * @private
+ */
+ Tone.IntervalTimeline.prototype._removeNode = function (node) {
+ if (node.left === null && node.right === null) {
+ this._replaceNodeInParent(node, null);
+ } else if (node.right === null) {
+ this._replaceNodeInParent(node, node.left);
+ } else if (node.left === null) {
+ this._replaceNodeInParent(node, node.right);
+ } else {
+ var balance = node.getBalance();
+ var replacement, temp;
+ if (balance > 0) {
+ if (node.left.right === null) {
+ replacement = node.left;
+ replacement.right = node.right;
+ temp = replacement;
+ } else {
+ replacement = node.left.right;
+ while (replacement.right !== null) {
+ replacement = replacement.right;
+ }
+ replacement.parent.right = replacement.left;
+ temp = replacement.parent;
+ replacement.left = node.left;
+ replacement.right = node.right;
+ }
+ } else {
+ if (node.right.left === null) {
+ replacement = node.right;
+ replacement.left = node.left;
+ temp = replacement;
+ } else {
+ replacement = node.right.left;
+ while (replacement.left !== null) {
+ replacement = replacement.left;
+ }
+ replacement.parent = replacement.parent;
+ replacement.parent.left = replacement.right;
+ temp = replacement.parent;
+ replacement.left = node.left;
+ replacement.right = node.right;
+ }
+ }
+ if (node.parent !== null) {
+ if (node.isLeftChild()) {
+ node.parent.left = replacement;
+ } else {
+ node.parent.right = replacement;
+ }
+ } else {
+ this._setRoot(replacement);
+ }
+ // this._replaceNodeInParent(node, replacement);
+ this._rebalance(temp);
+ }
+ node.dispose();
+ };
+ /**
+ * Rotate the tree to the left
+ * @param {IntervalNode} node
+ * @private
+ */
+ Tone.IntervalTimeline.prototype._rotateLeft = function (node) {
+ var parent = node.parent;
+ var isLeftChild = node.isLeftChild();
+ // Make node.right the new root of this sub tree (instead of node)
+ var pivotNode = node.right;
+ node.right = pivotNode.left;
+ pivotNode.left = node;
+ if (parent !== null) {
+ if (isLeftChild) {
+ parent.left = pivotNode;
+ } else {
+ parent.right = pivotNode;
+ }
+ } else {
+ this._setRoot(pivotNode);
+ }
+ };
+ /**
+ * Rotate the tree to the right
+ * @param {IntervalNode} node
+ * @private
+ */
+ Tone.IntervalTimeline.prototype._rotateRight = function (node) {
+ var parent = node.parent;
+ var isLeftChild = node.isLeftChild();
+ // Make node.left the new root of this sub tree (instead of node)
+ var pivotNode = node.left;
+ node.left = pivotNode.right;
+ pivotNode.right = node;
+ if (parent !== null) {
+ if (isLeftChild) {
+ parent.left = pivotNode;
+ } else {
+ parent.right = pivotNode;
+ }
+ } else {
+ this._setRoot(pivotNode);
+ }
+ };
+ /**
+ * Balance the BST
+ * @param {IntervalNode} node
+ * @private
+ */
+ Tone.IntervalTimeline.prototype._rebalance = function (node) {
+ var balance = node.getBalance();
+ if (balance > 1) {
+ if (node.left.getBalance() < 0) {
+ this._rotateLeft(node.left);
+ } else {
+ this._rotateRight(node);
+ }
+ } else if (balance < -1) {
+ if (node.right.getBalance() > 0) {
+ this._rotateRight(node.right);
+ } else {
+ this._rotateLeft(node);
+ }
+ }
+ };
+ /**
+ * Get an event whose time and duration span the give time. Will
+ * return the match whose "time" value is closest to the given time.
+ * @param {Object} event The event to add to the timeline
+ * @return {Object} The event which spans the desired time
+ */
+ Tone.IntervalTimeline.prototype.get = function (time) {
+ if (this._root !== null) {
+ var results = [];
+ this._root.search(time, results);
+ if (results.length > 0) {
+ var max = results[0];
+ for (var i = 1; i < results.length; i++) {
+ if (results[i].low > max.low) {
+ max = results[i];
+ }
+ }
+ return max.event;
+ }
+ }
+ return null;
+ };
+ /**
+ * Iterate over everything in the timeline.
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.forEach = function (callback) {
+ if (this._root !== null) {
+ var allNodes = [];
+ if (this._root !== null) {
+ this._root.traverse(function (node) {
+ allNodes.push(node);
+ });
+ }
+ for (var i = 0; i < allNodes.length; i++) {
+ var ev = allNodes[i].event;
+ if (ev) {
+ callback(ev);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Iterate over everything in the array in which the given time
+ * overlaps with the time and duration time of the event.
+ * @param {Number} time The time to check if items are overlapping
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.forEachAtTime = function (time, callback) {
+ if (this._root !== null) {
+ var results = [];
+ this._root.search(time, results);
+ for (var i = results.length - 1; i >= 0; i--) {
+ var ev = results[i].event;
+ if (ev) {
+ callback(ev);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Iterate over everything in the array in which the time is greater
+ * than the given time.
+ * @param {Number} time The time to check if items are before
+ * @param {Function} callback The callback to invoke with every item
+ * @returns {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.forEachAfter = function (time, callback) {
+ if (this._root !== null) {
+ var results = [];
+ this._root.searchAfter(time, results);
+ for (var i = results.length - 1; i >= 0; i--) {
+ var ev = results[i].event;
+ if (ev) {
+ callback(ev);
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Clean up
+ * @return {Tone.IntervalTimeline} this
+ */
+ Tone.IntervalTimeline.prototype.dispose = function () {
+ var allNodes = [];
+ if (this._root !== null) {
+ this._root.traverse(function (node) {
+ allNodes.push(node);
+ });
+ }
+ for (var i = 0; i < allNodes.length; i++) {
+ allNodes[i].dispose();
+ }
+ allNodes = null;
+ this._root = null;
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // INTERVAL NODE HELPER
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Represents a node in the binary search tree, with the addition
+ * of a "high" value which keeps track of the highest value of
+ * its children.
+ * References:
+ * https://brooknovak.wordpress.com/2013/12/07/augmented-interval-tree-in-c/
+ * http://www.mif.vu.lt/~valdas/ALGORITMAI/LITERATURA/Cormen/Cormen.pdf
+ * @param {Number} low
+ * @param {Number} high
+ * @private
+ */
+ var IntervalNode = function (low, high, event) {
+ //the event container
+ this.event = event;
+ //the low value
+ this.low = low;
+ //the high value
+ this.high = high;
+ //the high value for this and all child nodes
+ this.max = this.high;
+ //the nodes to the left
+ this._left = null;
+ //the nodes to the right
+ this._right = null;
+ //the parent node
+ this.parent = null;
+ //the number of child nodes
+ this.height = 0;
+ };
+ /**
+ * Insert a node into the correct spot in the tree
+ * @param {IntervalNode} node
+ */
+ IntervalNode.prototype.insert = function (node) {
+ if (node.low <= this.low) {
+ if (this.left === null) {
+ this.left = node;
+ } else {
+ this.left.insert(node);
+ }
+ } else {
+ if (this.right === null) {
+ this.right = node;
+ } else {
+ this.right.insert(node);
+ }
+ }
+ };
+ /**
+ * Search the tree for nodes which overlap
+ * with the given point
+ * @param {Number} point The point to query
+ * @param {Array} results The array to put the results
+ */
+ IntervalNode.prototype.search = function (point, results) {
+ // If p is to the right of the rightmost point of any interval
+ // in this node and all children, there won't be any matches.
+ if (point > this.max) {
+ return;
+ }
+ // Search left children
+ if (this.left !== null) {
+ this.left.search(point, results);
+ }
+ // Check this node
+ if (this.low <= point && this.high > point) {
+ results.push(this);
+ }
+ // If p is to the left of the time of this interval,
+ // then it can't be in any child to the right.
+ if (this.low > point) {
+ return;
+ }
+ // Search right children
+ if (this.right !== null) {
+ this.right.search(point, results);
+ }
+ };
+ /**
+ * Search the tree for nodes which are less
+ * than the given point
+ * @param {Number} point The point to query
+ * @param {Array} results The array to put the results
+ */
+ IntervalNode.prototype.searchAfter = function (point, results) {
+ // Check this node
+ if (this.low >= point) {
+ results.push(this);
+ if (this.left !== null) {
+ this.left.searchAfter(point, results);
+ }
+ }
+ // search the right side
+ if (this.right !== null) {
+ this.right.searchAfter(point, results);
+ }
+ };
+ /**
+ * Invoke the callback on this element and both it's branches
+ * @param {Function} callback
+ */
+ IntervalNode.prototype.traverse = function (callback) {
+ callback(this);
+ if (this.left !== null) {
+ this.left.traverse(callback);
+ }
+ if (this.right !== null) {
+ this.right.traverse(callback);
+ }
+ };
+ /**
+ * Update the height of the node
+ */
+ IntervalNode.prototype.updateHeight = function () {
+ if (this.left !== null && this.right !== null) {
+ this.height = Math.max(this.left.height, this.right.height) + 1;
+ } else if (this.right !== null) {
+ this.height = this.right.height + 1;
+ } else if (this.left !== null) {
+ this.height = this.left.height + 1;
+ } else {
+ this.height = 0;
+ }
+ };
+ /**
+ * Update the height of the node
+ */
+ IntervalNode.prototype.updateMax = function () {
+ this.max = this.high;
+ if (this.left !== null) {
+ this.max = Math.max(this.max, this.left.max);
+ }
+ if (this.right !== null) {
+ this.max = Math.max(this.max, this.right.max);
+ }
+ };
+ /**
+ * The balance is how the leafs are distributed on the node
+ * @return {Number} Negative numbers are balanced to the right
+ */
+ IntervalNode.prototype.getBalance = function () {
+ var balance = 0;
+ if (this.left !== null && this.right !== null) {
+ balance = this.left.height - this.right.height;
+ } else if (this.left !== null) {
+ balance = this.left.height + 1;
+ } else if (this.right !== null) {
+ balance = -(this.right.height + 1);
+ }
+ return balance;
+ };
+ /**
+ * @returns {Boolean} true if this node is the left child
+ * of its parent
+ */
+ IntervalNode.prototype.isLeftChild = function () {
+ return this.parent !== null && this.parent.left === this;
+ };
+ /**
+ * get/set the left node
+ * @type {IntervalNode}
+ */
+ Object.defineProperty(IntervalNode.prototype, 'left', {
+ get: function () {
+ return this._left;
+ },
+ set: function (node) {
+ this._left = node;
+ if (node !== null) {
+ node.parent = this;
+ }
+ this.updateHeight();
+ this.updateMax();
+ }
+ });
+ /**
+ * get/set the right node
+ * @type {IntervalNode}
+ */
+ Object.defineProperty(IntervalNode.prototype, 'right', {
+ get: function () {
+ return this._right;
+ },
+ set: function (node) {
+ this._right = node;
+ if (node !== null) {
+ node.parent = this;
+ }
+ this.updateHeight();
+ this.updateMax();
+ }
+ });
+ /**
+ * null out references.
+ */
+ IntervalNode.prototype.dispose = function () {
+ this.parent = null;
+ this._left = null;
+ this._right = null;
+ this.event = null;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // END INTERVAL NODE HELPER
+ ///////////////////////////////////////////////////////////////////////////
+ return Tone.IntervalTimeline;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Transport for timing musical events.
+ * Supports tempo curves and time changes. Unlike browser-based timing (setInterval, requestAnimationFrame)
+ * Tone.Transport timing events pass in the exact time of the scheduled event
+ * in the argument of the callback function. Pass that time value to the object
+ * you're scheduling. <br><br>
+ * A single transport is created for you when the library is initialized.
+ * <br><br>
+ * The transport emits the events: "start", "stop", "pause", and "loop" which are
+ * called with the time of that event as the argument.
+ *
+ * @extends {Tone.Emitter}
+ * @singleton
+ * @example
+ * //repeated event every 8th note
+ * Tone.Transport.scheduleRepeat(function(time){
+ * //do something with the time
+ * }, "8n");
+ * @example
+ * //schedule an event on the 16th measure
+ * Tone.Transport.schedule(function(time){
+ * //do something with the time
+ * }, "16:0:0");
+ */
+ Tone.Transport = function () {
+ Tone.Emitter.call(this);
+ ///////////////////////////////////////////////////////////////////////
+ // LOOPING
+ //////////////////////////////////////////////////////////////////////
+ /**
+ * If the transport loops or not.
+ * @type {boolean}
+ */
+ this.loop = false;
+ /**
+ * The loop start position in ticks
+ * @type {Ticks}
+ * @private
+ */
+ this._loopStart = 0;
+ /**
+ * The loop end position in ticks
+ * @type {Ticks}
+ * @private
+ */
+ this._loopEnd = 0;
+ ///////////////////////////////////////////////////////////////////////
+ // CLOCK/TEMPO
+ //////////////////////////////////////////////////////////////////////
+ /**
+ * Pulses per quarter is the number of ticks per quarter note.
+ * @private
+ * @type {Number}
+ */
+ this._ppq = TransportConstructor.defaults.PPQ;
+ /**
+ * watches the main oscillator for timing ticks
+ * initially starts at 120bpm
+ * @private
+ * @type {Tone.Clock}
+ */
+ this._clock = new Tone.Clock({
+ 'callback': this._processTick.bind(this),
+ 'frequency': 0
+ });
+ this._bindClockEvents();
+ /**
+ * The Beats Per Minute of the Transport.
+ * @type {BPM}
+ * @signal
+ * @example
+ * Tone.Transport.bpm.value = 80;
+ * //ramp the bpm to 120 over 10 seconds
+ * Tone.Transport.bpm.rampTo(120, 10);
+ */
+ this.bpm = this._clock.frequency;
+ this.bpm._toUnits = this._toUnits.bind(this);
+ this.bpm._fromUnits = this._fromUnits.bind(this);
+ this.bpm.units = Tone.Type.BPM;
+ this.bpm.value = TransportConstructor.defaults.bpm;
+ this._readOnly('bpm');
+ /**
+ * The time signature, or more accurately the numerator
+ * of the time signature over a denominator of 4.
+ * @type {Number}
+ * @private
+ */
+ this._timeSignature = TransportConstructor.defaults.timeSignature;
+ ///////////////////////////////////////////////////////////////////////
+ // TIMELINE EVENTS
+ //////////////////////////////////////////////////////////////////////
+ /**
+ * All the events in an object to keep track by ID
+ * @type {Object}
+ * @private
+ */
+ this._scheduledEvents = {};
+ /**
+ * The event ID counter
+ * @type {Number}
+ * @private
+ */
+ this._eventID = 0;
+ /**
+ * The scheduled events.
+ * @type {Tone.Timeline}
+ * @private
+ */
+ this._timeline = new Tone.Timeline();
+ /**
+ * Repeated events
+ * @type {Array}
+ * @private
+ */
+ this._repeatedEvents = new Tone.IntervalTimeline();
+ /**
+ * Events that occur once
+ * @type {Array}
+ * @private
+ */
+ this._onceEvents = new Tone.Timeline();
+ /**
+ * All of the synced Signals
+ * @private
+ * @type {Array}
+ */
+ this._syncedSignals = [];
+ ///////////////////////////////////////////////////////////////////////
+ // SWING
+ //////////////////////////////////////////////////////////////////////
+ /**
+ * The subdivision of the swing
+ * @type {Ticks}
+ * @private
+ */
+ this._swingTicks = TransportConstructor.defaults.PPQ / 2;
+ //8n
+ /**
+ * The swing amount
+ * @type {NormalRange}
+ * @private
+ */
+ this._swingAmount = 0;
+ };
+ Tone.extend(Tone.Transport, Tone.Emitter);
+ /**
+ * the defaults
+ * @type {Object}
+ * @const
+ * @static
+ */
+ Tone.Transport.defaults = {
+ 'bpm': 120,
+ 'swing': 0,
+ 'swingSubdivision': '8n',
+ 'timeSignature': 4,
+ 'loopStart': 0,
+ 'loopEnd': '4m',
+ 'PPQ': 192
+ };
+ ///////////////////////////////////////////////////////////////////////////////
+ // TICKS
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * called on every tick
+ * @param {number} tickTime clock relative tick time
+ * @private
+ */
+ Tone.Transport.prototype._processTick = function (tickTime) {
+ var ticks = this._clock.ticks;
+ //handle swing
+ if (this._swingAmount > 0 && ticks % this._ppq !== 0 && //not on a downbeat
+ ticks % (this._swingTicks * 2) !== 0) {
+ //add some swing
+ var progress = ticks % (this._swingTicks * 2) / (this._swingTicks * 2);
+ var amount = Math.sin(progress * Math.PI) * this._swingAmount;
+ tickTime += Tone.Time(this._swingTicks * 2 / 3, 'i') * amount;
+ }
+ //do the loop test
+ if (this.loop) {
+ if (ticks === this._loopEnd) {
+ this.emit('loopEnd', tickTime);
+ this._clock.ticks = this._loopStart;
+ ticks = this._loopStart;
+ this.emit('loopStart', tickTime, this.seconds);
+ this.emit('loop', tickTime);
+ }
+ }
+ //process the single occurrence events
+ this._onceEvents.forEachBefore(ticks, function (event) {
+ event.callback(tickTime);
+ //remove the event
+ delete this._scheduledEvents[event.id.toString()];
+ }.bind(this));
+ //and clear the single occurrence timeline
+ this._onceEvents.cancelBefore(ticks);
+ //fire the next tick events if their time has come
+ this._timeline.forEachAtTime(ticks, function (event) {
+ event.callback(tickTime);
+ });
+ //process the repeated events
+ this._repeatedEvents.forEachAtTime(ticks, function (event) {
+ if ((ticks - event.time) % event.interval === 0) {
+ event.callback(tickTime);
+ }
+ });
+ };
+ ///////////////////////////////////////////////////////////////////////////////
+ // SCHEDULABLE EVENTS
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Schedule an event along the timeline.
+ * @param {Function} callback The callback to be invoked at the time.
+ * @param {TransportTime} time The time to invoke the callback at.
+ * @return {Number} The id of the event which can be used for canceling the event.
+ * @example
+ * //trigger the callback when the Transport reaches the desired time
+ * Tone.Transport.schedule(function(time){
+ * envelope.triggerAttack(time);
+ * }, "128i");
+ */
+ Tone.Transport.prototype.schedule = function (callback, time) {
+ var event = {
+ 'time': this.toTicks(time),
+ 'callback': callback
+ };
+ var id = this._eventID++;
+ this._scheduledEvents[id.toString()] = {
+ 'event': event,
+ 'timeline': this._timeline
+ };
+ this._timeline.add(event);
+ return id;
+ };
+ /**
+ * Schedule a repeated event along the timeline. The event will fire
+ * at the `interval` starting at the `startTime` and for the specified
+ * `duration`.
+ * @param {Function} callback The callback to invoke.
+ * @param {Time} interval The duration between successive
+ * callbacks.
+ * @param {TimelinePosition=} startTime When along the timeline the events should
+ * start being invoked.
+ * @param {Time} [duration=Infinity] How long the event should repeat.
+ * @return {Number} The ID of the scheduled event. Use this to cancel
+ * the event.
+ * @example
+ * //a callback invoked every eighth note after the first measure
+ * Tone.Transport.scheduleRepeat(callback, "8n", "1m");
+ */
+ Tone.Transport.prototype.scheduleRepeat = function (callback, interval, startTime, duration) {
+ if (interval <= 0) {
+ throw new Error('Tone.Transport: repeat events must have an interval larger than 0');
+ }
+ var event = {
+ 'time': this.toTicks(startTime),
+ 'duration': this.toTicks(this.defaultArg(duration, Infinity)),
+ 'interval': this.toTicks(interval),
+ 'callback': callback
+ };
+ var id = this._eventID++;
+ this._scheduledEvents[id.toString()] = {
+ 'event': event,
+ 'timeline': this._repeatedEvents
+ };
+ this._repeatedEvents.add(event);
+ return id;
+ };
+ /**
+ * Schedule an event that will be removed after it is invoked.
+ * Note that if the given time is less than the current transport time,
+ * the event will be invoked immediately.
+ * @param {Function} callback The callback to invoke once.
+ * @param {TransportTime} time The time the callback should be invoked.
+ * @returns {Number} The ID of the scheduled event.
+ */
+ Tone.Transport.prototype.scheduleOnce = function (callback, time) {
+ var id = this._eventID++;
+ var event = {
+ 'time': this.toTicks(time),
+ 'callback': callback,
+ 'id': id
+ };
+ this._scheduledEvents[id.toString()] = {
+ 'event': event,
+ 'timeline': this._onceEvents
+ };
+ this._onceEvents.add(event);
+ return id;
+ };
+ /**
+ * Clear the passed in event id from the timeline
+ * @param {Number} eventId The id of the event.
+ * @returns {Tone.Transport} this
+ */
+ Tone.Transport.prototype.clear = function (eventId) {
+ if (this._scheduledEvents.hasOwnProperty(eventId)) {
+ var item = this._scheduledEvents[eventId.toString()];
+ item.timeline.remove(item.event);
+ delete this._scheduledEvents[eventId.toString()];
+ }
+ return this;
+ };
+ /**
+ * Remove scheduled events from the timeline after
+ * the given time. Repeated events will be removed
+ * if their startTime is after the given time
+ * @param {TransportTime} [after=0] Clear all events after
+ * this time.
+ * @returns {Tone.Transport} this
+ */
+ Tone.Transport.prototype.cancel = function (after) {
+ after = this.defaultArg(after, 0);
+ after = this.toTicks(after);
+ this._timeline.cancel(after);
+ this._onceEvents.cancel(after);
+ this._repeatedEvents.cancel(after);
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////////
+ // START/STOP/PAUSE
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Bind start/stop/pause events from the clock and emit them.
+ */
+ Tone.Transport.prototype._bindClockEvents = function () {
+ this._clock.on('start', function (time, offset) {
+ offset = Tone.Time(this._clock.ticks, 'i').toSeconds();
+ this.emit('start', time, offset);
+ }.bind(this));
+ this._clock.on('stop', function (time) {
+ this.emit('stop', time);
+ }.bind(this));
+ this._clock.on('pause', function (time) {
+ this.emit('pause', time);
+ }.bind(this));
+ };
+ /**
+ * Returns the playback state of the source, either "started", "stopped", or "paused"
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.Transport#
+ * @name state
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'state', {
+ get: function () {
+ return this._clock.getStateAtTime(this.now());
+ }
+ });
+ /**
+ * Start the transport and all sources synced to the transport.
+ * @param {Time} [time=now] The time when the transport should start.
+ * @param {TransportTime=} offset The timeline offset to start the transport.
+ * @returns {Tone.Transport} this
+ * @example
+ * //start the transport in one second starting at beginning of the 5th measure.
+ * Tone.Transport.start("+1", "4:0:0");
+ */
+ Tone.Transport.prototype.start = function (time, offset) {
+ //start the clock
+ if (!this.isUndef(offset)) {
+ offset = this.toTicks(offset);
+ }
+ this._clock.start(time, offset);
+ return this;
+ };
+ /**
+ * Stop the transport and all sources synced to the transport.
+ * @param {Time} [time=now] The time when the transport should stop.
+ * @returns {Tone.Transport} this
+ * @example
+ * Tone.Transport.stop();
+ */
+ Tone.Transport.prototype.stop = function (time) {
+ this._clock.stop(time);
+ return this;
+ };
+ /**
+ * Pause the transport and all sources synced to the transport.
+ * @param {Time} [time=now]
+ * @returns {Tone.Transport} this
+ */
+ Tone.Transport.prototype.pause = function (time) {
+ this._clock.pause(time);
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////////
+ // SETTERS/GETTERS
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * The time signature as just the numerator over 4.
+ * For example 4/4 would be just 4 and 6/8 would be 3.
+ * @memberOf Tone.Transport#
+ * @type {Number|Array}
+ * @name timeSignature
+ * @example
+ * //common time
+ * Tone.Transport.timeSignature = 4;
+ * // 7/8
+ * Tone.Transport.timeSignature = [7, 8];
+ * //this will be reduced to a single number
+ * Tone.Transport.timeSignature; //returns 3.5
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'timeSignature', {
+ get: function () {
+ return this._timeSignature;
+ },
+ set: function (timeSig) {
+ if (this.isArray(timeSig)) {
+ timeSig = timeSig[0] / timeSig[1] * 4;
+ }
+ this._timeSignature = timeSig;
+ }
+ });
+ /**
+ * When the Tone.Transport.loop = true, this is the starting position of the loop.
+ * @memberOf Tone.Transport#
+ * @type {TransportTime}
+ * @name loopStart
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'loopStart', {
+ get: function () {
+ return Tone.TransportTime(this._loopStart, 'i').toSeconds();
+ },
+ set: function (startPosition) {
+ this._loopStart = this.toTicks(startPosition);
+ }
+ });
+ /**
+ * When the Tone.Transport.loop = true, this is the ending position of the loop.
+ * @memberOf Tone.Transport#
+ * @type {TransportTime}
+ * @name loopEnd
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'loopEnd', {
+ get: function () {
+ return Tone.TransportTime(this._loopEnd, 'i').toSeconds();
+ },
+ set: function (endPosition) {
+ this._loopEnd = this.toTicks(endPosition);
+ }
+ });
+ /**
+ * Set the loop start and stop at the same time.
+ * @param {TransportTime} startPosition
+ * @param {TransportTime} endPosition
+ * @returns {Tone.Transport} this
+ * @example
+ * //loop over the first measure
+ * Tone.Transport.setLoopPoints(0, "1m");
+ * Tone.Transport.loop = true;
+ */
+ Tone.Transport.prototype.setLoopPoints = function (startPosition, endPosition) {
+ this.loopStart = startPosition;
+ this.loopEnd = endPosition;
+ return this;
+ };
+ /**
+ * The swing value. Between 0-1 where 1 equal to
+ * the note + half the subdivision.
+ * @memberOf Tone.Transport#
+ * @type {NormalRange}
+ * @name swing
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'swing', {
+ get: function () {
+ return this._swingAmount;
+ },
+ set: function (amount) {
+ //scale the values to a normal range
+ this._swingAmount = amount;
+ }
+ });
+ /**
+ * Set the subdivision which the swing will be applied to.
+ * The default value is an 8th note. Value must be less
+ * than a quarter note.
+ *
+ * @memberOf Tone.Transport#
+ * @type {Time}
+ * @name swingSubdivision
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'swingSubdivision', {
+ get: function () {
+ return Tone.Time(this._swingTicks, 'i').toNotation();
+ },
+ set: function (subdivision) {
+ this._swingTicks = this.toTicks(subdivision);
+ }
+ });
+ /**
+ * The Transport's position in Bars:Beats:Sixteenths.
+ * Setting the value will jump to that position right away.
+ * @memberOf Tone.Transport#
+ * @type {BarsBeatsSixteenths}
+ * @name position
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'position', {
+ get: function () {
+ return Tone.TransportTime(this.ticks, 'i').toBarsBeatsSixteenths();
+ },
+ set: function (progress) {
+ var ticks = this.toTicks(progress);
+ this.ticks = ticks;
+ }
+ });
+ /**
+ * The Transport's position in seconds
+ * Setting the value will jump to that position right away.
+ * @memberOf Tone.Transport#
+ * @type {Seconds}
+ * @name seconds
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'seconds', {
+ get: function () {
+ return Tone.TransportTime(this.ticks, 'i').toSeconds();
+ },
+ set: function (progress) {
+ var ticks = this.toTicks(progress);
+ this.ticks = ticks;
+ }
+ });
+ /**
+ * The Transport's loop position as a normalized value. Always
+ * returns 0 if the transport if loop is not true.
+ * @memberOf Tone.Transport#
+ * @name progress
+ * @type {NormalRange}
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'progress', {
+ get: function () {
+ if (this.loop) {
+ return (this.ticks - this._loopStart) / (this._loopEnd - this._loopStart);
+ } else {
+ return 0;
+ }
+ }
+ });
+ /**
+ * The transports current tick position.
+ *
+ * @memberOf Tone.Transport#
+ * @type {Ticks}
+ * @name ticks
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'ticks', {
+ get: function () {
+ return this._clock.ticks;
+ },
+ set: function (t) {
+ if (this._clock.ticks !== t) {
+ var now = this.now();
+ //stop everything synced to the transport
+ if (this.state === Tone.State.Started) {
+ this.emit('stop', now);
+ this._clock.ticks = t;
+ //restart it with the new time
+ this.emit('start', now, this.seconds);
+ } else {
+ this._clock.ticks = t;
+ }
+ }
+ }
+ });
+ /**
+ * Pulses Per Quarter note. This is the smallest resolution
+ * the Transport timing supports. This should be set once
+ * on initialization and not set again. Changing this value
+ * after other objects have been created can cause problems.
+ *
+ * @memberOf Tone.Transport#
+ * @type {Number}
+ * @name PPQ
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'PPQ', {
+ get: function () {
+ return this._ppq;
+ },
+ set: function (ppq) {
+ var bpm = this.bpm.value;
+ this._ppq = ppq;
+ this.bpm.value = bpm;
+ }
+ });
+ /**
+ * The hint to the type of playback. Affects tradeoffs between audio
+ * output latency and responsiveness.
+ *
+ * In addition to setting the value in seconds, the latencyHint also
+ * accepts the strings "interactive" (prioritizes low latency),
+ * "playback" (prioritizes sustained playback), "balanced" (balances
+ * latency and performance), and "fastest" (lowest latency, might glitch more often).
+ * @memberOf Tone.Transport#
+ * @type {Seconds|String}
+ * @name latencyHint
+ */
+ Object.defineProperty(Tone.Transport.prototype, 'latencyHint', {
+ get: function () {
+ return Tone.Clock.latencyHint;
+ },
+ set: function (hint) {
+ Tone.Clock.latencyHint = hint;
+ }
+ });
+ /**
+ * Convert from BPM to frequency (factoring in PPQ)
+ * @param {BPM} bpm The BPM value to convert to frequency
+ * @return {Frequency} The BPM as a frequency with PPQ factored in.
+ * @private
+ */
+ Tone.Transport.prototype._fromUnits = function (bpm) {
+ return 1 / (60 / bpm / this.PPQ);
+ };
+ /**
+ * Convert from frequency (with PPQ) into BPM
+ * @param {Frequency} freq The clocks frequency to convert to BPM
+ * @return {BPM} The frequency value as BPM.
+ * @private
+ */
+ Tone.Transport.prototype._toUnits = function (freq) {
+ return freq / this.PPQ * 60;
+ };
+ ///////////////////////////////////////////////////////////////////////////////
+ // SYNCING
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Returns the time aligned to the next subdivision
+ * of the Transport. If the Transport is not started,
+ * it will return 0.
+ * Note: this will not work precisely during tempo ramps.
+ * @param {Time} subdivision The subdivision to quantize to
+ * @return {Number} The context time of the next subdivision.
+ * @example
+ * Tone.Transport.start(); //the transport must be started
+ * Tone.Transport.nextSubdivision("4n");
+ */
+ Tone.Transport.prototype.nextSubdivision = function (subdivision) {
+ subdivision = this.toSeconds(subdivision);
+ //if the transport's not started, return 0
+ var now;
+ if (this.state === Tone.State.Started) {
+ now = this._clock._nextTick;
+ } else {
+ return 0;
+ }
+ var transportPos = Tone.Time(this.ticks, 'i');
+ var remainingTime = subdivision - transportPos % subdivision;
+ if (remainingTime === 0) {
+ remainingTime = subdivision;
+ }
+ return now + remainingTime;
+ };
+ /**
+ * Attaches the signal to the tempo control signal so that
+ * any changes in the tempo will change the signal in the same
+ * ratio.
+ *
+ * @param {Tone.Signal} signal
+ * @param {number=} ratio Optionally pass in the ratio between
+ * the two signals. Otherwise it will be computed
+ * based on their current values.
+ * @returns {Tone.Transport} this
+ */
+ Tone.Transport.prototype.syncSignal = function (signal, ratio) {
+ if (!ratio) {
+ //get the sync ratio
+ if (signal._param.value !== 0) {
+ ratio = signal._param.value / this.bpm._param.value;
+ } else {
+ ratio = 0;
+ }
+ }
+ var ratioSignal = new Tone.Gain(ratio);
+ this.bpm.chain(ratioSignal, signal._param);
+ this._syncedSignals.push({
+ 'ratio': ratioSignal,
+ 'signal': signal,
+ 'initial': signal._param.value
+ });
+ signal._param.value = 0;
+ return this;
+ };
+ /**
+ * Unsyncs a previously synced signal from the transport's control.
+ * See Tone.Transport.syncSignal.
+ * @param {Tone.Signal} signal
+ * @returns {Tone.Transport} this
+ */
+ Tone.Transport.prototype.unsyncSignal = function (signal) {
+ for (var i = this._syncedSignals.length - 1; i >= 0; i--) {
+ var syncedSignal = this._syncedSignals[i];
+ if (syncedSignal.signal === signal) {
+ syncedSignal.ratio.dispose();
+ syncedSignal.signal._param.value = syncedSignal.initial;
+ this._syncedSignals.splice(i, 1);
+ }
+ }
+ return this;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Transport} this
+ * @private
+ */
+ Tone.Transport.prototype.dispose = function () {
+ Tone.Emitter.prototype.dispose.call(this);
+ this._clock.dispose();
+ this._clock = null;
+ this._writable('bpm');
+ this.bpm = null;
+ this._timeline.dispose();
+ this._timeline = null;
+ this._onceEvents.dispose();
+ this._onceEvents = null;
+ this._repeatedEvents.dispose();
+ this._repeatedEvents = null;
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////////
+ // INITIALIZATION
+ ///////////////////////////////////////////////////////////////////////////////
+ var TransportConstructor = Tone.Transport;
+ Tone.Transport = new TransportConstructor();
+ Tone.Context.on('init', function (context) {
+ if (context.Transport instanceof TransportConstructor) {
+ Tone.Transport = context.Transport;
+ } else {
+ Tone.Transport = new TransportConstructor();
+ //store the Transport on the context so it can be retrieved later
+ context.Transport = Tone.Transport;
+ }
+ });
+ return Tone.Transport;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Volume is a simple volume node, useful for creating a volume fader.
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {Decibels} [volume=0] the initial volume
+ * @example
+ * var vol = new Tone.Volume(-12);
+ * instrument.chain(vol, Tone.Master);
+ */
+ Tone.Volume = function () {
+ var options = this.optionsObject(arguments, ['volume'], Tone.Volume.defaults);
+ /**
+ * the output node
+ * @type {GainNode}
+ * @private
+ */
+ this.output = this.input = new Tone.Gain(options.volume, Tone.Type.Decibels);
+ /**
+ * The unmuted volume
+ * @type {Decibels}
+ * @private
+ */
+ this._unmutedVolume = options.volume;
+ /**
+ * The volume control in decibels.
+ * @type {Decibels}
+ * @signal
+ */
+ this.volume = this.output.gain;
+ this._readOnly('volume');
+ //set the mute initially
+ this.mute = options.mute;
+ };
+ Tone.extend(Tone.Volume);
+ /**
+ * Defaults
+ * @type {Object}
+ * @const
+ * @static
+ */
+ Tone.Volume.defaults = {
+ 'volume': 0,
+ 'mute': false
+ };
+ /**
+ * Mute the output.
+ * @memberOf Tone.Volume#
+ * @type {boolean}
+ * @name mute
+ * @example
+ * //mute the output
+ * volume.mute = true;
+ */
+ Object.defineProperty(Tone.Volume.prototype, 'mute', {
+ get: function () {
+ return this.volume.value === -Infinity;
+ },
+ set: function (mute) {
+ if (!this.mute && mute) {
+ this._unmutedVolume = this.volume.value;
+ //maybe it should ramp here?
+ this.volume.value = -Infinity;
+ } else if (this.mute && !mute) {
+ this.volume.value = this._unmutedVolume;
+ }
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.Volume} this
+ */
+ Tone.Volume.prototype.dispose = function () {
+ this.input.dispose();
+ Tone.prototype.dispose.call(this);
+ this._writable('volume');
+ this.volume.dispose();
+ this.volume = null;
+ return this;
+ };
+ return Tone.Volume;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A single master output which is connected to the
+ * AudioDestinationNode (aka your speakers).
+ * It provides useful conveniences such as the ability
+ * to set the volume and mute the entire application.
+ * It also gives you the ability to apply master effects to your application.
+ * <br><br>
+ * Like Tone.Transport, A single Tone.Master is created
+ * on initialization and you do not need to explicitly construct one.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @singleton
+ * @example
+ * //the audio will go from the oscillator to the speakers
+ * oscillator.connect(Tone.Master);
+ * //a convenience for connecting to the master output is also provided:
+ * oscillator.toMaster();
+ * //the above two examples are equivalent.
+ */
+ Tone.Master = function () {
+ this.createInsOuts(1, 1);
+ /**
+ * The private volume node
+ * @type {Tone.Volume}
+ * @private
+ */
+ this._volume = this.output = new Tone.Volume();
+ /**
+ * The volume of the master output.
+ * @type {Decibels}
+ * @signal
+ */
+ this.volume = this._volume.volume;
+ this._readOnly('volume');
+ //connections
+ this.input.chain(this.output, this.context.destination);
+ };
+ Tone.extend(Tone.Master);
+ /**
+ * @type {Object}
+ * @const
+ */
+ Tone.Master.defaults = {
+ 'volume': 0,
+ 'mute': false
+ };
+ /**
+ * Mute the output.
+ * @memberOf Tone.Master#
+ * @type {boolean}
+ * @name mute
+ * @example
+ * //mute the output
+ * Tone.Master.mute = true;
+ */
+ Object.defineProperty(Tone.Master.prototype, 'mute', {
+ get: function () {
+ return this._volume.mute;
+ },
+ set: function (mute) {
+ this._volume.mute = mute;
+ }
+ });
+ /**
+ * Add a master effects chain. NOTE: this will disconnect any nodes which were previously
+ * chained in the master effects chain.
+ * @param {AudioNode|Tone...} args All arguments will be connected in a row
+ * and the Master will be routed through it.
+ * @return {Tone.Master} this
+ * @example
+ * //some overall compression to keep the levels in check
+ * var masterCompressor = new Tone.Compressor({
+ * "threshold" : -6,
+ * "ratio" : 3,
+ * "attack" : 0.5,
+ * "release" : 0.1
+ * });
+ * //give a little boost to the lows
+ * var lowBump = new Tone.Filter(200, "lowshelf");
+ * //route everything through the filter
+ * //and compressor before going to the speakers
+ * Tone.Master.chain(lowBump, masterCompressor);
+ */
+ Tone.Master.prototype.chain = function () {
+ this.input.disconnect();
+ this.input.chain.apply(this.input, arguments);
+ arguments[arguments.length - 1].connect(this.output);
+ };
+ /**
+ * Clean up
+ * @return {Tone.Master} this
+ */
+ Tone.Master.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable('volume');
+ this._volume.dispose();
+ this._volume = null;
+ this.volume = null;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // AUGMENT TONE's PROTOTYPE
+ ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Connect 'this' to the master output. Shorthand for this.connect(Tone.Master)
+ * @returns {Tone} this
+ * @example
+ * //connect an oscillator to the master output
+ * var osc = new Tone.Oscillator().toMaster();
+ */
+ Tone.prototype.toMaster = function () {
+ this.connect(Tone.Master);
+ return this;
+ };
+ /**
+ * Also augment AudioNode's prototype to include toMaster
+ * as a convenience
+ * @returns {AudioNode} this
+ */
+ AudioNode.prototype.toMaster = function () {
+ this.connect(Tone.Master);
+ return this;
+ };
+ /**
+ * initialize the module and listen for new audio contexts
+ */
+ var MasterConstructor = Tone.Master;
+ Tone.Master = new MasterConstructor();
+ Tone.Context.on('init', function (context) {
+ // if it already exists, just restore it
+ if (context.Master instanceof MasterConstructor) {
+ Tone.Master = context.Master;
+ } else {
+ Tone.Master = new MasterConstructor();
+ }
+ context.Master = Tone.Master;
+ });
+ return Tone.Master;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Base class for sources. Sources have start/stop methods
+ * and the ability to be synced to the
+ * start/stop of Tone.Transport.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @example
+ * //Multiple state change events can be chained together,
+ * //but must be set in the correct order and with ascending times
+ *
+ * // OK
+ * state.start().stop("+0.2");
+ * // AND
+ * state.start().stop("+0.2").start("+0.4").stop("+0.7")
+ *
+ * // BAD
+ * state.stop("+0.2").start();
+ * // OR
+ * state.start("+0.3").stop("+0.2");
+ *
+ */
+ Tone.Source = function (options) {
+ // this.createInsOuts(0, 1);
+ options = this.defaultArg(options, Tone.Source.defaults);
+ /**
+ * The output volume node
+ * @type {Tone.Volume}
+ * @private
+ */
+ this._volume = this.output = new Tone.Volume(options.volume);
+ /**
+ * The volume of the output in decibels.
+ * @type {Decibels}
+ * @signal
+ * @example
+ * source.volume.value = -6;
+ */
+ this.volume = this._volume.volume;
+ this._readOnly('volume');
+ /**
+ * Keep track of the scheduled state.
+ * @type {Tone.TimelineState}
+ * @private
+ */
+ this._state = new Tone.TimelineState(Tone.State.Stopped);
+ this._state.memory = 10;
+ /**
+ * The synced `start` callback function from the transport
+ * @type {Function}
+ * @private
+ */
+ this._synced = false;
+ /**
+ * Keep track of all of the scheduled event ids
+ * @type {Array}
+ * @private
+ */
+ this._scheduled = [];
+ //make the output explicitly stereo
+ this._volume.output.output.channelCount = 2;
+ this._volume.output.output.channelCountMode = 'explicit';
+ //mute initially
+ this.mute = options.mute;
+ };
+ Tone.extend(Tone.Source);
+ /**
+ * The default parameters
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Source.defaults = {
+ 'volume': 0,
+ 'mute': false
+ };
+ /**
+ * Returns the playback state of the source, either "started" or "stopped".
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.Source#
+ * @name state
+ */
+ Object.defineProperty(Tone.Source.prototype, 'state', {
+ get: function () {
+ if (this._synced) {
+ if (Tone.Transport.state === Tone.State.Started) {
+ return this._state.getValueAtTime(Tone.Transport.seconds);
+ } else {
+ return Tone.State.Stopped;
+ }
+ } else {
+ return this._state.getValueAtTime(this.now());
+ }
+ }
+ });
+ /**
+ * Mute the output.
+ * @memberOf Tone.Source#
+ * @type {boolean}
+ * @name mute
+ * @example
+ * //mute the output
+ * source.mute = true;
+ */
+ Object.defineProperty(Tone.Source.prototype, 'mute', {
+ get: function () {
+ return this._volume.mute;
+ },
+ set: function (mute) {
+ this._volume.mute = mute;
+ }
+ });
+ //overwrite these functions
+ Tone.Source.prototype._start = Tone.noOp;
+ Tone.Source.prototype._stop = Tone.noOp;
+ /**
+ * Start the source at the specified time. If no time is given,
+ * start the source now.
+ * @param {Time} [time=now] When the source should be started.
+ * @returns {Tone.Source} this
+ * @example
+ * source.start("+0.5"); //starts the source 0.5 seconds from now
+ */
+ Tone.Source.prototype.start = function (time, offset, duration) {
+ if (this.isUndef(time) && this._synced) {
+ time = Tone.Transport.seconds;
+ } else {
+ time = this.toSeconds(time);
+ }
+ //if it's started, stop it and restart it
+ if (!this.retrigger && this._state.getValueAtTime(time) === Tone.State.Started) {
+ this.stop(time);
+ }
+ this._state.setStateAtTime(Tone.State.Started, time);
+ if (this._synced) {
+ // add the offset time to the event
+ var event = this._state.get(time);
+ event.offset = this.defaultArg(offset, 0);
+ event.duration = duration;
+ var sched = Tone.Transport.schedule(function (t) {
+ this._start(t, offset, duration);
+ }.bind(this), time);
+ this._scheduled.push(sched);
+ } else {
+ this._start.apply(this, arguments);
+ }
+ return this;
+ };
+ /**
+ * Stop the source at the specified time. If no time is given,
+ * stop the source now.
+ * @param {Time} [time=now] When the source should be stopped.
+ * @returns {Tone.Source} this
+ * @example
+ * source.stop(); // stops the source immediately
+ */
+ Tone.Source.prototype.stop = function (time) {
+ if (this.isUndef(time) && this._synced) {
+ time = Tone.Transport.seconds;
+ } else {
+ time = this.toSeconds(time);
+ }
+ this._state.cancel(time);
+ this._state.setStateAtTime(Tone.State.Stopped, time);
+ if (!this._synced) {
+ this._stop.apply(this, arguments);
+ } else {
+ var sched = Tone.Transport.schedule(this._stop.bind(this), time);
+ this._scheduled.push(sched);
+ }
+ return this;
+ };
+ /**
+ * Sync the source to the Transport so that all subsequent
+ * calls to `start` and `stop` are synced to the TransportTime
+ * instead of the AudioContext time.
+ *
+ * @returns {Tone.Source} this
+ * @example
+ * //sync the source so that it plays between 0 and 0.3 on the Transport's timeline
+ * source.sync().start(0).stop(0.3);
+ * //start the transport.
+ * Tone.Transport.start();
+ *
+ * @example
+ * //start the transport with an offset and the sync'ed sources
+ * //will start in the correct position
+ * source.sync().start(0.1);
+ * //the source will be invoked with an offset of 0.4
+ * Tone.Transport.start("+0.5", 0.5);
+ */
+ Tone.Source.prototype.sync = function () {
+ this._synced = true;
+ Tone.Transport.on('start loopStart', function (time, offset) {
+ if (offset > 0) {
+ // get the playback state at that time
+ var stateEvent = this._state.get(offset);
+ // listen for start events which may occur in the middle of the sync'ed time
+ if (stateEvent && stateEvent.state === Tone.State.Started && stateEvent.time !== offset) {
+ // get the offset
+ var startOffset = offset - this.toSeconds(stateEvent.time);
+ var duration;
+ if (stateEvent.duration) {
+ duration = this.toSeconds(stateEvent.duration) - startOffset;
+ }
+ this._start(time, this.toSeconds(stateEvent.offset) + startOffset, duration);
+ }
+ }
+ }.bind(this));
+ Tone.Transport.on('stop pause loopEnd', function (time) {
+ if (this._state.getValueAtTime(Tone.Transport.seconds) === Tone.State.Started) {
+ this._stop(time);
+ }
+ }.bind(this));
+ return this;
+ };
+ /**
+ * Unsync the source to the Transport. See Tone.Source.sync
+ * @returns {Tone.Source} this
+ */
+ Tone.Source.prototype.unsync = function () {
+ this._synced = false;
+ Tone.Transport.off('start stop pause loopEnd loopStart');
+ // clear all of the scheduled ids
+ for (var i = 0; i < this._scheduled.length; i++) {
+ var id = this._scheduled[i];
+ Tone.Transport.clear(id);
+ }
+ this._scheduled = [];
+ this._state.cancel(0);
+ return this;
+ };
+ /**
+ * Clean up.
+ * @return {Tone.Source} this
+ */
+ Tone.Source.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this.unsync();
+ this._scheduled = null;
+ this._writable('volume');
+ this._volume.dispose();
+ this._volume = null;
+ this.volume = null;
+ this._state.dispose();
+ this._state = null;
+ };
+ return Tone.Source;
+ });
+ Module(function (Tone) {
+
+ /**
+ * OscillatorNode shim
+ * @private
+ */
+ if (window.OscillatorNode && !OscillatorNode.prototype.start) {
+ OscillatorNode.prototype.start = OscillatorNode.prototype.noteOn;
+ OscillatorNode.prototype.stop = OscillatorNode.prototype.noteOff;
+ if (!OscillatorNode.prototype.setPeriodicWave) {
+ OscillatorNode.prototype.setPeriodicWave = OscillatorNode.prototype.setWaveTable;
+ }
+ if (!AudioContext.prototype.createPeriodicWave) {
+ AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable;
+ }
+ }
+ /**
+ * @class Tone.Oscillator supports a number of features including
+ * phase rotation, multiple oscillator types (see Tone.Oscillator.type),
+ * and Transport syncing (see Tone.Oscillator.syncFrequency).
+ *
+ * @constructor
+ * @extends {Tone.Source}
+ * @param {Frequency} [frequency] Starting frequency
+ * @param {string} [type] The oscillator type. Read more about type below.
+ * @example
+ * //make and start a 440hz sine tone
+ * var osc = new Tone.Oscillator(440, "sine").toMaster().start();
+ */
+ Tone.Oscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'type'
+ ], Tone.Oscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * the main oscillator
+ * @type {OscillatorNode}
+ * @private
+ */
+ this._oscillator = null;
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The detune control signal.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
+ /**
+ * the periodic wave
+ * @type {PeriodicWave}
+ * @private
+ */
+ this._wave = null;
+ /**
+ * The partials of the oscillator
+ * @type {Array}
+ * @private
+ */
+ this._partials = this.defaultArg(options.partials, [1]);
+ /**
+ * the phase of the oscillator
+ * between 0 - 360
+ * @type {number}
+ * @private
+ */
+ this._phase = options.phase;
+ /**
+ * the type of the oscillator
+ * @type {string}
+ * @private
+ */
+ this._type = null;
+ //setup
+ this.type = options.type;
+ this.phase = this._phase;
+ this._readOnly([
+ 'frequency',
+ 'detune'
+ ]);
+ };
+ Tone.extend(Tone.Oscillator, Tone.Source);
+ /**
+ * the default parameters
+ * @type {Object}
+ */
+ Tone.Oscillator.defaults = {
+ 'type': 'sine',
+ 'frequency': 440,
+ 'detune': 0,
+ 'phase': 0,
+ 'partials': []
+ };
+ /**
+ * The Oscillator types
+ * @enum {String}
+ */
+ Tone.Oscillator.Type = {
+ Sine: 'sine',
+ Triangle: 'triangle',
+ Sawtooth: 'sawtooth',
+ Square: 'square',
+ Custom: 'custom'
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now]
+ * @private
+ */
+ Tone.Oscillator.prototype._start = function (time) {
+ //new oscillator with previous values
+ this._oscillator = this.context.createOscillator();
+ this._oscillator.setPeriodicWave(this._wave);
+ //connect the control signal to the oscillator frequency & detune
+ this._oscillator.connect(this.output);
+ this.frequency.connect(this._oscillator.frequency);
+ this.detune.connect(this._oscillator.detune);
+ //start the oscillator
+ this._oscillator.start(this.toSeconds(time));
+ };
+ /**
+ * stop the oscillator
+ * @private
+ * @param {Time} [time=now] (optional) timing parameter
+ * @returns {Tone.Oscillator} this
+ */
+ Tone.Oscillator.prototype._stop = function (time) {
+ if (this._oscillator) {
+ this._oscillator.stop(this.toSeconds(time));
+ this._oscillator = null;
+ }
+ return this;
+ };
+ /**
+ * Sync the signal to the Transport's bpm. Any changes to the transports bpm,
+ * will also affect the oscillators frequency.
+ * @returns {Tone.Oscillator} this
+ * @example
+ * Tone.Transport.bpm.value = 120;
+ * osc.frequency.value = 440;
+ * //the ration between the bpm and the frequency will be maintained
+ * osc.syncFrequency();
+ * Tone.Transport.bpm.value = 240;
+ * // the frequency of the oscillator is doubled to 880
+ */
+ Tone.Oscillator.prototype.syncFrequency = function () {
+ Tone.Transport.syncSignal(this.frequency);
+ return this;
+ };
+ /**
+ * Unsync the oscillator's frequency from the Transport.
+ * See Tone.Oscillator.syncFrequency
+ * @returns {Tone.Oscillator} this
+ */
+ Tone.Oscillator.prototype.unsyncFrequency = function () {
+ Tone.Transport.unsyncSignal(this.frequency);
+ return this;
+ };
+ /**
+ * The type of the oscillator: either sine, square, triangle, or sawtooth. Also capable of
+ * setting the first x number of partials of the oscillator. For example: "sine4" would
+ * set be the first 4 partials of the sine wave and "triangle8" would set the first
+ * 8 partials of the triangle wave.
+ * <br><br>
+ * Uses PeriodicWave internally even for native types so that it can set the phase.
+ * PeriodicWave equations are from the
+ * [Webkit Web Audio implementation](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp&sq=package:chromium).
+ *
+ * @memberOf Tone.Oscillator#
+ * @type {string}
+ * @name type
+ * @example
+ * //set it to a square wave
+ * osc.type = "square";
+ * @example
+ * //set the first 6 partials of a sawtooth wave
+ * osc.type = "sawtooth6";
+ */
+ Object.defineProperty(Tone.Oscillator.prototype, 'type', {
+ get: function () {
+ return this._type;
+ },
+ set: function (type) {
+ var coefs = this._getRealImaginary(type, this._phase);
+ var periodicWave = this.context.createPeriodicWave(coefs[0], coefs[1]);
+ this._wave = periodicWave;
+ if (this._oscillator !== null) {
+ this._oscillator.setPeriodicWave(this._wave);
+ }
+ this._type = type;
+ }
+ });
+ /**
+ * Returns the real and imaginary components based
+ * on the oscillator type.
+ * @returns {Array} [real, imaginary]
+ * @private
+ */
+ Tone.Oscillator.prototype._getRealImaginary = function (type, phase) {
+ var fftSize = 4096;
+ var periodicWaveSize = fftSize / 2;
+ var real = new Float32Array(periodicWaveSize);
+ var imag = new Float32Array(periodicWaveSize);
+ var partialCount = 1;
+ if (type === Tone.Oscillator.Type.Custom) {
+ partialCount = this._partials.length + 1;
+ periodicWaveSize = partialCount;
+ } else {
+ var partial = /^(sine|triangle|square|sawtooth)(\d+)$/.exec(type);
+ if (partial) {
+ partialCount = parseInt(partial[2]) + 1;
+ type = partial[1];
+ partialCount = Math.max(partialCount, 2);
+ periodicWaveSize = partialCount;
+ }
+ }
+ for (var n = 1; n < periodicWaveSize; ++n) {
+ var piFactor = 2 / (n * Math.PI);
+ var b;
+ switch (type) {
+ case Tone.Oscillator.Type.Sine:
+ b = n <= partialCount ? 1 : 0;
+ break;
+ case Tone.Oscillator.Type.Square:
+ b = n & 1 ? 2 * piFactor : 0;
+ break;
+ case Tone.Oscillator.Type.Sawtooth:
+ b = piFactor * (n & 1 ? 1 : -1);
+ break;
+ case Tone.Oscillator.Type.Triangle:
+ if (n & 1) {
+ b = 2 * (piFactor * piFactor) * (n - 1 >> 1 & 1 ? -1 : 1);
+ } else {
+ b = 0;
+ }
+ break;
+ case Tone.Oscillator.Type.Custom:
+ b = this._partials[n - 1];
+ break;
+ default:
+ throw new TypeError('Tone.Oscillator: invalid type: ' + type);
+ }
+ if (b !== 0) {
+ real[n] = -b * Math.sin(phase * n);
+ imag[n] = b * Math.cos(phase * n);
+ } else {
+ real[n] = 0;
+ imag[n] = 0;
+ }
+ }
+ return [
+ real,
+ imag
+ ];
+ };
+ /**
+ * Compute the inverse FFT for a given phase.
+ * @param {Float32Array} real
+ * @param {Float32Array} imag
+ * @param {NormalRange} phase
+ * @return {AudioRange}
+ * @private
+ */
+ Tone.Oscillator.prototype._inverseFFT = function (real, imag, phase) {
+ var sum = 0;
+ var len = real.length;
+ for (var i = 0; i < len; i++) {
+ sum += real[i] * Math.cos(i * phase) + imag[i] * Math.sin(i * phase);
+ }
+ return sum;
+ };
+ /**
+ * Returns the initial value of the oscillator.
+ * @return {AudioRange}
+ * @private
+ */
+ Tone.Oscillator.prototype._getInitialValue = function () {
+ var coefs = this._getRealImaginary(this._type, 0);
+ var real = coefs[0];
+ var imag = coefs[1];
+ var maxValue = 0;
+ var twoPi = Math.PI * 2;
+ //check for peaks in 8 places
+ for (var i = 0; i < 8; i++) {
+ maxValue = Math.max(this._inverseFFT(real, imag, i / 8 * twoPi), maxValue);
+ }
+ return -this._inverseFFT(real, imag, this._phase) / maxValue;
+ };
+ /**
+ * The partials of the waveform. A partial represents
+ * the amplitude at a harmonic. The first harmonic is the
+ * fundamental frequency, the second is the octave and so on
+ * following the harmonic series.
+ * Setting this value will automatically set the type to "custom".
+ * The value is an empty array when the type is not "custom".
+ * @memberOf Tone.Oscillator#
+ * @type {Array}
+ * @name partials
+ * @example
+ * osc.partials = [1, 0.2, 0.01];
+ */
+ Object.defineProperty(Tone.Oscillator.prototype, 'partials', {
+ get: function () {
+ if (this._type !== Tone.Oscillator.Type.Custom) {
+ return [];
+ } else {
+ return this._partials;
+ }
+ },
+ set: function (partials) {
+ this._partials = partials;
+ this.type = Tone.Oscillator.Type.Custom;
+ }
+ });
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.Oscillator#
+ * @type {Degrees}
+ * @name phase
+ * @example
+ * osc.phase = 180; //flips the phase of the oscillator
+ */
+ Object.defineProperty(Tone.Oscillator.prototype, 'phase', {
+ get: function () {
+ return this._phase * (180 / Math.PI);
+ },
+ set: function (phase) {
+ this._phase = phase * Math.PI / 180;
+ //reset the type
+ this.type = this._type;
+ }
+ });
+ /**
+ * Dispose and disconnect.
+ * @return {Tone.Oscillator} this
+ */
+ Tone.Oscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ if (this._oscillator !== null) {
+ this._oscillator.disconnect();
+ this._oscillator = null;
+ }
+ this._wave = null;
+ this._writable([
+ 'frequency',
+ 'detune'
+ ]);
+ this.frequency.dispose();
+ this.frequency = null;
+ this.detune.dispose();
+ this.detune = null;
+ this._partials = null;
+ return this;
+ };
+ return Tone.Oscillator;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.Zero outputs 0's at audio-rate. The reason this has to be
+ * it's own class is that many browsers optimize out Tone.Signal
+ * with a value of 0 and will not process nodes further down the graph.
+ * @extends {Tone}
+ */
+ Tone.Zero = function () {
+ /**
+ * The gain node
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._gain = this.input = this.output = new Tone.Gain();
+ this.context.getConstant(0).connect(this._gain);
+ };
+ Tone.extend(Tone.Zero);
+ /**
+ * clean up
+ * @return {Tone.Zero} this
+ */
+ Tone.Zero.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._gain.dispose();
+ this._gain = null;
+ return this;
+ };
+ return Tone.Zero;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class LFO stands for low frequency oscillator. Tone.LFO produces an output signal
+ * which can be attached to an AudioParam or Tone.Signal
+ * in order to modulate that parameter with an oscillator. The LFO can
+ * also be synced to the transport to start/stop and change when the tempo changes.
+ *
+ * @constructor
+ * @extends {Tone.Oscillator}
+ * @param {Frequency|Object} [frequency] The frequency of the oscillation. Typically, LFOs will be
+ * in the frequency range of 0.1 to 10 hertz.
+ * @param {number=} min The minimum output value of the LFO.
+ * @param {number=} max The maximum value of the LFO.
+ * @example
+ * var lfo = new Tone.LFO("4n", 400, 4000);
+ * lfo.connect(filter.frequency);
+ */
+ Tone.LFO = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'min',
+ 'max'
+ ], Tone.LFO.defaults);
+ /**
+ * The oscillator.
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._oscillator = new Tone.Oscillator({
+ 'frequency': options.frequency,
+ 'type': options.type
+ });
+ /**
+ * the lfo's frequency
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._oscillator.frequency;
+ /**
+ * The amplitude of the LFO, which controls the output range between
+ * the min and max output. For example if the min is -10 and the max
+ * is 10, setting the amplitude to 0.5 would make the LFO modulate
+ * between -5 and 5.
+ * @type {Number}
+ * @signal
+ */
+ this.amplitude = this._oscillator.volume;
+ this.amplitude.units = Tone.Type.NormalRange;
+ this.amplitude.value = options.amplitude;
+ /**
+ * The signal which is output when the LFO is stopped
+ * @type {Tone.Signal}
+ * @private
+ */
+ this._stoppedSignal = new Tone.Signal(0, Tone.Type.AudioRange);
+ /**
+ * Just outputs zeros.
+ * @type {Tone.Zero}
+ * @private
+ */
+ this._zeros = new Tone.Zero();
+ /**
+ * The value that the LFO outputs when it's stopped
+ * @type {AudioRange}
+ * @private
+ */
+ this._stoppedValue = 0;
+ /**
+ * @type {Tone.AudioToGain}
+ * @private
+ */
+ this._a2g = new Tone.AudioToGain();
+ /**
+ * @type {Tone.Scale}
+ * @private
+ */
+ this._scaler = this.output = new Tone.Scale(options.min, options.max);
+ /**
+ * the units of the LFO (used for converting)
+ * @type {Tone.Type}
+ * @private
+ */
+ this._units = Tone.Type.Default;
+ this.units = options.units;
+ //connect it up
+ this._oscillator.chain(this._a2g, this._scaler);
+ this._zeros.connect(this._a2g);
+ this._stoppedSignal.connect(this._a2g);
+ this._readOnly([
+ 'amplitude',
+ 'frequency'
+ ]);
+ this.phase = options.phase;
+ };
+ Tone.extend(Tone.LFO, Tone.Oscillator);
+ /**
+ * the default parameters
+ *
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.LFO.defaults = {
+ 'type': 'sine',
+ 'min': 0,
+ 'max': 1,
+ 'phase': 0,
+ 'frequency': '4n',
+ 'amplitude': 1,
+ 'units': Tone.Type.Default
+ };
+ /**
+ * Start the LFO.
+ * @param {Time} [time=now] the time the LFO will start
+ * @returns {Tone.LFO} this
+ */
+ Tone.LFO.prototype.start = function (time) {
+ time = this.toSeconds(time);
+ this._stoppedSignal.setValueAtTime(0, time);
+ this._oscillator.start(time);
+ return this;
+ };
+ /**
+ * Stop the LFO.
+ * @param {Time} [time=now] the time the LFO will stop
+ * @returns {Tone.LFO} this
+ */
+ Tone.LFO.prototype.stop = function (time) {
+ time = this.toSeconds(time);
+ this._stoppedSignal.setValueAtTime(this._stoppedValue, time);
+ this._oscillator.stop(time);
+ return this;
+ };
+ /**
+ * Sync the start/stop/pause to the transport
+ * and the frequency to the bpm of the transport
+ * @returns {Tone.LFO} this
+ * @example
+ * lfo.frequency.value = "8n";
+ * lfo.sync().start(0)
+ * //the rate of the LFO will always be an eighth note,
+ * //even as the tempo changes
+ */
+ Tone.LFO.prototype.sync = function () {
+ this._oscillator.sync();
+ this._oscillator.syncFrequency();
+ return this;
+ };
+ /**
+ * unsync the LFO from transport control
+ * @returns {Tone.LFO} this
+ */
+ Tone.LFO.prototype.unsync = function () {
+ this._oscillator.unsync();
+ this._oscillator.unsyncFrequency();
+ return this;
+ };
+ /**
+ * The miniumum output of the LFO.
+ * @memberOf Tone.LFO#
+ * @type {number}
+ * @name min
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'min', {
+ get: function () {
+ return this._toUnits(this._scaler.min);
+ },
+ set: function (min) {
+ min = this._fromUnits(min);
+ this._scaler.min = min;
+ }
+ });
+ /**
+ * The maximum output of the LFO.
+ * @memberOf Tone.LFO#
+ * @type {number}
+ * @name max
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'max', {
+ get: function () {
+ return this._toUnits(this._scaler.max);
+ },
+ set: function (max) {
+ max = this._fromUnits(max);
+ this._scaler.max = max;
+ }
+ });
+ /**
+ * The type of the oscillator: sine, square, sawtooth, triangle.
+ * @memberOf Tone.LFO#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'type', {
+ get: function () {
+ return this._oscillator.type;
+ },
+ set: function (type) {
+ this._oscillator.type = type;
+ this._stoppedValue = this._oscillator._getInitialValue();
+ this._stoppedSignal.value = this._stoppedValue;
+ }
+ });
+ /**
+ * The phase of the LFO.
+ * @memberOf Tone.LFO#
+ * @type {number}
+ * @name phase
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'phase', {
+ get: function () {
+ return this._oscillator.phase;
+ },
+ set: function (phase) {
+ this._oscillator.phase = phase;
+ this._stoppedValue = this._oscillator._getInitialValue();
+ this._stoppedSignal.value = this._stoppedValue;
+ }
+ });
+ /**
+ * The output units of the LFO.
+ * @memberOf Tone.LFO#
+ * @type {Tone.Type}
+ * @name units
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'units', {
+ get: function () {
+ return this._units;
+ },
+ set: function (val) {
+ var currentMin = this.min;
+ var currentMax = this.max;
+ //convert the min and the max
+ this._units = val;
+ this.min = currentMin;
+ this.max = currentMax;
+ }
+ });
+ /**
+ * Mute the output.
+ * @memberOf Tone.LFO#
+ * @type {Boolean}
+ * @name mute
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'mute', {
+ get: function () {
+ return this._oscillator.mute;
+ },
+ set: function (mute) {
+ this._oscillator.mute = mute;
+ }
+ });
+ /**
+ * Returns the playback state of the source, either "started" or "stopped".
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.LFO#
+ * @name state
+ */
+ Object.defineProperty(Tone.LFO.prototype, 'state', {
+ get: function () {
+ return this._oscillator.state;
+ }
+ });
+ /**
+ * Connect the output of the LFO to an AudioParam, AudioNode, or Tone Node.
+ * Tone.LFO will automatically convert to the destination units of the
+ * will get the units from the connected node.
+ * @param {Tone | AudioParam | AudioNode} node
+ * @param {number} [outputNum=0] optionally which output to connect from
+ * @param {number} [inputNum=0] optionally which input to connect to
+ * @returns {Tone.LFO} this
+ * @private
+ */
+ Tone.LFO.prototype.connect = function (node) {
+ if (node.constructor === Tone.Signal || node.constructor === Tone.Param || node.constructor === Tone.TimelineSignal) {
+ this.convert = node.convert;
+ this.units = node.units;
+ }
+ Tone.Signal.prototype.connect.apply(this, arguments);
+ return this;
+ };
+ /**
+ * private method borrowed from Param converts
+ * units from their destination value
+ * @function
+ * @private
+ */
+ Tone.LFO.prototype._fromUnits = Tone.Param.prototype._fromUnits;
+ /**
+ * private method borrowed from Param converts
+ * units to their destination value
+ * @function
+ * @private
+ */
+ Tone.LFO.prototype._toUnits = Tone.Param.prototype._toUnits;
+ /**
+ * disconnect and dispose
+ * @returns {Tone.LFO} this
+ */
+ Tone.LFO.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'amplitude',
+ 'frequency'
+ ]);
+ this._oscillator.dispose();
+ this._oscillator = null;
+ this._stoppedSignal.dispose();
+ this._stoppedSignal = null;
+ this._zeros.dispose();
+ this._zeros = null;
+ this._scaler.dispose();
+ this._scaler = null;
+ this._a2g.dispose();
+ this._a2g = null;
+ this.frequency = null;
+ this.amplitude = null;
+ return this;
+ };
+ return Tone.LFO;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Limiter will limit the loudness of an incoming signal.
+ * It is composed of a Tone.Compressor with a fast attack
+ * and release. Limiters are commonly used to safeguard against
+ * signal clipping. Unlike a compressor, limiters do not provide
+ * smooth gain reduction and almost completely prevent
+ * additional gain above the threshold.
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {number} threshold The theshold above which the limiting is applied.
+ * @example
+ * var limiter = new Tone.Limiter(-6);
+ */
+ Tone.Limiter = function () {
+ var options = this.optionsObject(arguments, ['threshold'], Tone.Limiter.defaults);
+ /**
+ * the compressor
+ * @private
+ * @type {Tone.Compressor}
+ */
+ this._compressor = this.input = this.output = new Tone.Compressor({
+ 'attack': 0.001,
+ 'decay': 0.001,
+ 'threshold': options.threshold
+ });
+ /**
+ * The threshold of of the limiter
+ * @type {Decibel}
+ * @signal
+ */
+ this.threshold = this._compressor.threshold;
+ this._readOnly('threshold');
+ };
+ Tone.extend(Tone.Limiter);
+ /**
+ * The default value
+ * @type {Object}
+ * @const
+ * @static
+ */
+ Tone.Limiter.defaults = { 'threshold': -12 };
+ /**
+ * Clean up.
+ * @returns {Tone.Limiter} this
+ */
+ Tone.Limiter.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._compressor.dispose();
+ this._compressor = null;
+ this._writable('threshold');
+ this.threshold = null;
+ return this;
+ };
+ return Tone.Limiter;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Lowpass is a lowpass feedback comb filter. It is similar to
+ * Tone.FeedbackCombFilter, but includes a lowpass filter.
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {Time|Object} [delayTime] The delay time of the comb filter
+ * @param {NormalRange=} resonance The resonance (feedback) of the comb filter
+ * @param {Frequency=} dampening The cutoff of the lowpass filter dampens the
+ * signal as it is fedback.
+ */
+ Tone.LowpassCombFilter = function () {
+ this.createInsOuts(1, 1);
+ var options = this.optionsObject(arguments, [
+ 'delayTime',
+ 'resonance',
+ 'dampening'
+ ], Tone.LowpassCombFilter.defaults);
+ /**
+ * the delay node
+ * @type {DelayNode}
+ * @private
+ */
+ this._delay = this.input = new Tone.Delay(options.delayTime);
+ /**
+ * The delayTime of the comb filter.
+ * @type {Time}
+ * @signal
+ */
+ this.delayTime = this._delay.delayTime;
+ /**
+ * the lowpass filter
+ * @type {BiquadFilterNode}
+ * @private
+ */
+ this._lowpass = this.output = this.context.createBiquadFilter();
+ this._lowpass.Q.value = -3.0102999566398125;
+ this._lowpass.type = 'lowpass';
+ /**
+ * The dampening control of the feedback
+ * @type {Frequency}
+ * @signal
+ */
+ this.dampening = new Tone.Param({
+ 'param': this._lowpass.frequency,
+ 'units': Tone.Type.Frequency,
+ 'value': options.dampening
+ });
+ /**
+ * the feedback gain
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._feedback = new Tone.Gain(options.resonance, Tone.Type.NormalRange);
+ /**
+ * The amount of feedback of the delayed signal.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.resonance = this._feedback.gain;
+ //connections
+ this._delay.chain(this._lowpass, this._feedback, this._delay);
+ this._readOnly([
+ 'dampening',
+ 'resonance',
+ 'delayTime'
+ ]);
+ };
+ Tone.extend(Tone.LowpassCombFilter);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.LowpassCombFilter.defaults = {
+ 'delayTime': 0.1,
+ 'resonance': 0.5,
+ 'dampening': 3000
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.LowpassCombFilter} this
+ */
+ Tone.LowpassCombFilter.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'dampening',
+ 'resonance',
+ 'delayTime'
+ ]);
+ this.dampening.dispose();
+ this.dampening = null;
+ this.resonance.dispose();
+ this.resonance = null;
+ this._delay.dispose();
+ this._delay = null;
+ this.delayTime = null;
+ this._lowpass.disconnect();
+ this._lowpass = null;
+ this._feedback.disconnect();
+ this._feedback = null;
+ return this;
+ };
+ return Tone.LowpassCombFilter;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Merge brings two signals into the left and right
+ * channels of a single stereo channel.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @example
+ * var merge = new Tone.Merge().toMaster();
+ * //routing a sine tone in the left channel
+ * //and noise in the right channel
+ * var osc = new Tone.Oscillator().connect(merge.left);
+ * var noise = new Tone.Noise().connect(merge.right);
+ * //starting our oscillators
+ * noise.start();
+ * osc.start();
+ */
+ Tone.Merge = function () {
+ this.createInsOuts(2, 0);
+ /**
+ * The left input channel.
+ * Alias for <code>input[0]</code>
+ * @type {GainNode}
+ */
+ this.left = this.input[0] = new Tone.Gain();
+ /**
+ * The right input channel.
+ * Alias for <code>input[1]</code>.
+ * @type {GainNode}
+ */
+ this.right = this.input[1] = new Tone.Gain();
+ /**
+ * the merger node for the two channels
+ * @type {ChannelMergerNode}
+ * @private
+ */
+ this._merger = this.output = this.context.createChannelMerger(2);
+ //connections
+ this.left.connect(this._merger, 0, 0);
+ this.right.connect(this._merger, 0, 1);
+ this.left.channelCount = 1;
+ this.right.channelCount = 1;
+ this.left.channelCountMode = 'explicit';
+ this.right.channelCountMode = 'explicit';
+ };
+ Tone.extend(Tone.Merge);
+ /**
+ * Clean up.
+ * @returns {Tone.Merge} this
+ */
+ Tone.Merge.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this.left.dispose();
+ this.left = null;
+ this.right.dispose();
+ this.right = null;
+ this._merger.disconnect();
+ this._merger = null;
+ return this;
+ };
+ return Tone.Merge;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Meter gets the [RMS](https://en.wikipedia.org/wiki/Root_mean_square)
+ * of an input signal with some averaging applied. It can also get the raw
+ * value of the input signal.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {String} type Either "level" or "signal".
+ * @param {Number} smoothing The amount of smoothing applied between frames.
+ * @example
+ * var meter = new Tone.Meter();
+ * var mic = new Tone.UserMedia().start();
+ * //connect mic to the meter
+ * mic.connect(meter);
+ * //the current level of the mic input
+ * var level = meter.value;
+ */
+ Tone.Meter = function () {
+ var options = this.optionsObject(arguments, [
+ 'type',
+ 'smoothing'
+ ], Tone.Meter.defaults);
+ /**
+ * The type of the meter, either "level" or "signal".
+ * A "level" meter will return the volume level (rms) of the
+ * input signal and a "signal" meter will return
+ * the signal value of the input.
+ * @type {String}
+ */
+ this.type = options.type;
+ /**
+ * The analyser node which computes the levels.
+ * @private
+ * @type {Tone.Analyser}
+ */
+ this.input = this.output = this._analyser = new Tone.Analyser('waveform', 512);
+ this._analyser.returnType = 'float';
+ /**
+ * The amount of carryover between the current and last frame.
+ * Only applied meter for "level" type.
+ * @type {Number}
+ */
+ this.smoothing = options.smoothing;
+ /**
+ * The last computed value
+ * @type {Number}
+ * @private
+ */
+ this._lastValue = 0;
+ };
+ Tone.extend(Tone.Meter);
+ /**
+ * @private
+ * @enum {String}
+ */
+ Tone.Meter.Type = {
+ Level: 'level',
+ Signal: 'signal'
+ };
+ /**
+ * The defaults
+ * @type {Object}
+ * @static
+ * @const
+ */
+ Tone.Meter.defaults = {
+ 'smoothing': 0.8,
+ 'type': Tone.Meter.Type.Level
+ };
+ /**
+ * The current value of the meter. A value of 1 is
+ * "unity".
+ * @memberOf Tone.Meter#
+ * @type {Number}
+ * @name value
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Meter.prototype, 'value', {
+ get: function () {
+ var signal = this._analyser.analyse();
+ if (this.type === Tone.Meter.Type.Level) {
+ //rms
+ var sum = 0;
+ for (var i = 0; i < signal.length; i++) {
+ sum += Math.pow(signal[i], 2);
+ }
+ var rms = Math.sqrt(sum / signal.length);
+ //smooth it
+ rms = Math.max(rms, this._lastValue * this.smoothing);
+ this._lastValue = rms;
+ //scale it
+ var unity = 0.35;
+ var val = rms / unity;
+ //scale the output curve
+ return Math.sqrt(val);
+ } else {
+ return signal[0];
+ }
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Meter} this
+ */
+ Tone.Meter.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._analyser.dispose();
+ this._analyser = null;
+ return this;
+ };
+ return Tone.Meter;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Split splits an incoming signal into left and right channels.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @example
+ * var split = new Tone.Split();
+ * stereoSignal.connect(split);
+ */
+ Tone.Split = function () {
+ this.createInsOuts(0, 2);
+ /**
+ * @type {ChannelSplitterNode}
+ * @private
+ */
+ this._splitter = this.input = this.context.createChannelSplitter(2);
+ /**
+ * Left channel output.
+ * Alias for <code>output[0]</code>
+ * @type {Tone.Gain}
+ */
+ this.left = this.output[0] = new Tone.Gain();
+ /**
+ * Right channel output.
+ * Alias for <code>output[1]</code>
+ * @type {Tone.Gain}
+ */
+ this.right = this.output[1] = new Tone.Gain();
+ //connections
+ this._splitter.connect(this.left, 0, 0);
+ this._splitter.connect(this.right, 1, 0);
+ };
+ Tone.extend(Tone.Split);
+ /**
+ * Clean up.
+ * @returns {Tone.Split} this
+ */
+ Tone.Split.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._splitter.disconnect();
+ this.left.dispose();
+ this.left = null;
+ this.right.dispose();
+ this.right = null;
+ this._splitter = null;
+ return this;
+ };
+ return Tone.Split;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Mid/Side processing separates the the 'mid' signal
+ * (which comes out of both the left and the right channel)
+ * and the 'side' (which only comes out of the the side channels). <br><br>
+ * <code>
+ * Mid = (Left+Right)/sqrt(2); // obtain mid-signal from left and right<br>
+ * Side = (Left-Right)/sqrt(2); // obtain side-signal from left and righ<br>
+ * </code>
+ *
+ * @extends {Tone}
+ * @constructor
+ */
+ Tone.MidSideSplit = function () {
+ this.createInsOuts(0, 2);
+ /**
+ * split the incoming signal into left and right channels
+ * @type {Tone.Split}
+ * @private
+ */
+ this._split = this.input = new Tone.Split();
+ /**
+ * The mid send. Connect to mid processing. Alias for
+ * <code>output[0]</code>
+ * @type {Tone.Expr}
+ */
+ this.mid = this.output[0] = new Tone.Expr('($0 + $1) * $2');
+ /**
+ * The side output. Connect to side processing. Alias for
+ * <code>output[1]</code>
+ * @type {Tone.Expr}
+ */
+ this.side = this.output[1] = new Tone.Expr('($0 - $1) * $2');
+ this._split.connect(this.mid, 0, 0);
+ this._split.connect(this.mid, 1, 1);
+ this._split.connect(this.side, 0, 0);
+ this._split.connect(this.side, 1, 1);
+ this.context.getConstant(Math.SQRT1_2).connect(this.mid, 0, 2);
+ this.context.getConstant(Math.SQRT1_2).connect(this.side, 0, 2);
+ };
+ Tone.extend(Tone.MidSideSplit);
+ /**
+ * clean up
+ * @returns {Tone.MidSideSplit} this
+ */
+ Tone.MidSideSplit.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this.mid.dispose();
+ this.mid = null;
+ this.side.dispose();
+ this.side = null;
+ this._split.dispose();
+ this._split = null;
+ return this;
+ };
+ return Tone.MidSideSplit;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Mid/Side processing separates the the 'mid' signal
+ * (which comes out of both the left and the right channel)
+ * and the 'side' (which only comes out of the the side channels).
+ * MidSideMerge merges the mid and side signal after they've been seperated
+ * by Tone.MidSideSplit.<br><br>
+ * <code>
+ * Left = (Mid+Side)/sqrt(2); // obtain left signal from mid and side<br>
+ * Right = (Mid-Side)/sqrt(2); // obtain right signal from mid and side<br>
+ * </code>
+ *
+ * @extends {Tone.StereoEffect}
+ * @constructor
+ */
+ Tone.MidSideMerge = function () {
+ this.createInsOuts(2, 0);
+ /**
+ * The mid signal input. Alias for
+ * <code>input[0]</code>
+ * @type {Tone.Gain}
+ */
+ this.mid = this.input[0] = new Tone.Gain();
+ /**
+ * recombine the mid/side into Left
+ * @type {Tone.Expr}
+ * @private
+ */
+ this._left = new Tone.Expr('($0 + $1) * $2');
+ /**
+ * The side signal input. Alias for
+ * <code>input[1]</code>
+ * @type {Tone.Gain}
+ */
+ this.side = this.input[1] = new Tone.Gain();
+ /**
+ * recombine the mid/side into Right
+ * @type {Tone.Expr}
+ * @private
+ */
+ this._right = new Tone.Expr('($0 - $1) * $2');
+ /**
+ * Merge the left/right signal back into a stereo signal.
+ * @type {Tone.Merge}
+ * @private
+ */
+ this._merge = this.output = new Tone.Merge();
+ this.mid.connect(this._left, 0, 0);
+ this.side.connect(this._left, 0, 1);
+ this.mid.connect(this._right, 0, 0);
+ this.side.connect(this._right, 0, 1);
+ this._left.connect(this._merge, 0, 0);
+ this._right.connect(this._merge, 0, 1);
+ this.context.getConstant(Math.SQRT1_2).connect(this._left, 0, 2);
+ this.context.getConstant(Math.SQRT1_2).connect(this._right, 0, 2);
+ };
+ Tone.extend(Tone.MidSideMerge);
+ /**
+ * clean up
+ * @returns {Tone.MidSideMerge} this
+ */
+ Tone.MidSideMerge.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this.mid.dispose();
+ this.mid = null;
+ this.side.dispose();
+ this.side = null;
+ this._left.dispose();
+ this._left = null;
+ this._right.dispose();
+ this._right = null;
+ this._merge.dispose();
+ this._merge = null;
+ return this;
+ };
+ return Tone.MidSideMerge;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.MidSideCompressor applies two different compressors to the mid
+ * and side signal components. See Tone.MidSideSplit.
+ *
+ * @extends {Tone}
+ * @param {Object} options The options that are passed to the mid and side
+ * compressors.
+ * @constructor
+ */
+ Tone.MidSideCompressor = function (options) {
+ options = this.defaultArg(options, Tone.MidSideCompressor.defaults);
+ /**
+ * the mid/side split
+ * @type {Tone.MidSideSplit}
+ * @private
+ */
+ this._midSideSplit = this.input = new Tone.MidSideSplit();
+ /**
+ * the mid/side recombination
+ * @type {Tone.MidSideMerge}
+ * @private
+ */
+ this._midSideMerge = this.output = new Tone.MidSideMerge();
+ /**
+ * The compressor applied to the mid signal
+ * @type {Tone.Compressor}
+ */
+ this.mid = new Tone.Compressor(options.mid);
+ /**
+ * The compressor applied to the side signal
+ * @type {Tone.Compressor}
+ */
+ this.side = new Tone.Compressor(options.side);
+ this._midSideSplit.mid.chain(this.mid, this._midSideMerge.mid);
+ this._midSideSplit.side.chain(this.side, this._midSideMerge.side);
+ this._readOnly([
+ 'mid',
+ 'side'
+ ]);
+ };
+ Tone.extend(Tone.MidSideCompressor);
+ /**
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.MidSideCompressor.defaults = {
+ 'mid': {
+ 'ratio': 3,
+ 'threshold': -24,
+ 'release': 0.03,
+ 'attack': 0.02,
+ 'knee': 16
+ },
+ 'side': {
+ 'ratio': 6,
+ 'threshold': -30,
+ 'release': 0.25,
+ 'attack': 0.03,
+ 'knee': 10
+ }
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.MidSideCompressor} this
+ */
+ Tone.MidSideCompressor.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'mid',
+ 'side'
+ ]);
+ this.mid.dispose();
+ this.mid = null;
+ this.side.dispose();
+ this.side = null;
+ this._midSideSplit.dispose();
+ this._midSideSplit = null;
+ this._midSideMerge.dispose();
+ this._midSideMerge = null;
+ return this;
+ };
+ return Tone.MidSideCompressor;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Mono coerces the incoming mono or stereo signal into a mono signal
+ * where both left and right channels have the same value. This can be useful
+ * for [stereo imaging](https://en.wikipedia.org/wiki/Stereo_imaging).
+ *
+ * @extends {Tone}
+ * @constructor
+ */
+ Tone.Mono = function () {
+ this.createInsOuts(1, 0);
+ /**
+ * merge the signal
+ * @type {Tone.Merge}
+ * @private
+ */
+ this._merge = this.output = new Tone.Merge();
+ this.input.connect(this._merge, 0, 0);
+ this.input.connect(this._merge, 0, 1);
+ this.input.gain.value = this.dbToGain(-10);
+ };
+ Tone.extend(Tone.Mono);
+ /**
+ * clean up
+ * @returns {Tone.Mono} this
+ */
+ Tone.Mono.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._merge.dispose();
+ this._merge = null;
+ return this;
+ };
+ return Tone.Mono;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A compressor with seperate controls over low/mid/high dynamics
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {Object} options The low/mid/high compressor settings.
+ * @example
+ * var multiband = new Tone.MultibandCompressor({
+ * "lowFrequency" : 200,
+ * "highFrequency" : 1300
+ * "low" : {
+ * "threshold" : -12
+ * }
+ * })
+ */
+ Tone.MultibandCompressor = function (options) {
+ options = this.defaultArg(arguments, Tone.MultibandCompressor.defaults);
+ /**
+ * split the incoming signal into high/mid/low
+ * @type {Tone.MultibandSplit}
+ * @private
+ */
+ this._splitter = this.input = new Tone.MultibandSplit({
+ 'lowFrequency': options.lowFrequency,
+ 'highFrequency': options.highFrequency
+ });
+ /**
+ * low/mid crossover frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.lowFrequency = this._splitter.lowFrequency;
+ /**
+ * mid/high crossover frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.highFrequency = this._splitter.highFrequency;
+ /**
+ * the output
+ * @type {Tone.Gain}
+ * @private
+ */
+ this.output = new Tone.Gain();
+ /**
+ * The compressor applied to the low frequencies.
+ * @type {Tone.Compressor}
+ */
+ this.low = new Tone.Compressor(options.low);
+ /**
+ * The compressor applied to the mid frequencies.
+ * @type {Tone.Compressor}
+ */
+ this.mid = new Tone.Compressor(options.mid);
+ /**
+ * The compressor applied to the high frequencies.
+ * @type {Tone.Compressor}
+ */
+ this.high = new Tone.Compressor(options.high);
+ //connect the compressor
+ this._splitter.low.chain(this.low, this.output);
+ this._splitter.mid.chain(this.mid, this.output);
+ this._splitter.high.chain(this.high, this.output);
+ this._readOnly([
+ 'high',
+ 'mid',
+ 'low',
+ 'highFrequency',
+ 'lowFrequency'
+ ]);
+ };
+ Tone.extend(Tone.MultibandCompressor);
+ /**
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.MultibandCompressor.defaults = {
+ 'low': Tone.Compressor.defaults,
+ 'mid': Tone.Compressor.defaults,
+ 'high': Tone.Compressor.defaults,
+ 'lowFrequency': 250,
+ 'highFrequency': 2000
+ };
+ /**
+ * clean up
+ * @returns {Tone.MultibandCompressor} this
+ */
+ Tone.MultibandCompressor.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._splitter.dispose();
+ this._writable([
+ 'high',
+ 'mid',
+ 'low',
+ 'highFrequency',
+ 'lowFrequency'
+ ]);
+ this.low.dispose();
+ this.mid.dispose();
+ this.high.dispose();
+ this._splitter = null;
+ this.low = null;
+ this.mid = null;
+ this.high = null;
+ this.lowFrequency = null;
+ this.highFrequency = null;
+ return this;
+ };
+ return Tone.MultibandCompressor;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Panner is an equal power Left/Right Panner and does not
+ * support 3D. Panner uses the StereoPannerNode when available.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {NormalRange} [initialPan=0] The initail panner value (defaults to 0 = center)
+ * @example
+ * //pan the input signal hard right.
+ * var panner = new Tone.Panner(1);
+ */
+ Tone.Panner = function (initialPan) {
+ if (this._hasStereoPanner) {
+ /**
+ * the panner node
+ * @type {StereoPannerNode}
+ * @private
+ */
+ this._panner = this.input = this.output = this.context.createStereoPanner();
+ /**
+ * The pan control. -1 = hard left, 1 = hard right.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.pan = this._panner.pan;
+ } else {
+ /**
+ * the dry/wet knob
+ * @type {Tone.CrossFade}
+ * @private
+ */
+ this._crossFade = new Tone.CrossFade();
+ /**
+ * @type {Tone.Merge}
+ * @private
+ */
+ this._merger = this.output = new Tone.Merge();
+ /**
+ * @type {Tone.Split}
+ * @private
+ */
+ this._splitter = this.input = new Tone.Split();
+ /**
+ * The pan control. -1 = hard left, 1 = hard right.
+ * @type {AudioRange}
+ * @signal
+ */
+ this.pan = new Tone.Signal(0, Tone.Type.AudioRange);
+ /**
+ * always sends 0
+ * @type {Tone.Zero}
+ * @private
+ */
+ this._zero = new Tone.Zero();
+ /**
+ * The analog to gain conversion
+ * @type {Tone.AudioToGain}
+ * @private
+ */
+ this._a2g = new Tone.AudioToGain();
+ //CONNECTIONS:
+ this._zero.connect(this._a2g);
+ this.pan.chain(this._a2g, this._crossFade.fade);
+ //left channel is a, right channel is b
+ this._splitter.connect(this._crossFade, 0, 0);
+ this._splitter.connect(this._crossFade, 1, 1);
+ //merge it back together
+ this._crossFade.a.connect(this._merger, 0, 0);
+ this._crossFade.b.connect(this._merger, 0, 1);
+ }
+ //initial value
+ this.pan.value = this.defaultArg(initialPan, 0);
+ this._readOnly('pan');
+ };
+ Tone.extend(Tone.Panner);
+ /**
+ * indicates if the panner is using the new StereoPannerNode internally
+ * @type {boolean}
+ * @private
+ */
+ Tone.Panner.prototype._hasStereoPanner = Tone.prototype.isFunction(Tone.context.createStereoPanner);
+ /**
+ * Clean up.
+ * @returns {Tone.Panner} this
+ */
+ Tone.Panner.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable('pan');
+ if (this._hasStereoPanner) {
+ this._panner.disconnect();
+ this._panner = null;
+ this.pan = null;
+ } else {
+ this._zero.dispose();
+ this._zero = null;
+ this._crossFade.dispose();
+ this._crossFade = null;
+ this._splitter.dispose();
+ this._splitter = null;
+ this._merger.dispose();
+ this._merger = null;
+ this.pan.dispose();
+ this.pan = null;
+ this._a2g.dispose();
+ this._a2g = null;
+ }
+ return this;
+ };
+ return Tone.Panner;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A spatialized panner node which supports equalpower or HRTF panning.
+ * Tries to normalize the API across various browsers. See Tone.Listener
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {Number} positionX The initial x position.
+ * @param {Number} positionY The initial y position.
+ * @param {Number} positionZ The initial z position.
+ */
+ Tone.Panner3D = function () {
+ var options = this.optionsObject(arguments, [
+ 'positionX',
+ 'positionY',
+ 'positionZ'
+ ], Tone.Panner3D.defaults);
+ /**
+ * The panner node
+ * @type {PannerNode}
+ * @private
+ */
+ this._panner = this.input = this.output = this.context.createPanner();
+ //set some values
+ this._panner.panningModel = options.panningModel;
+ this._panner.maxDistance = options.maxDistance;
+ this._panner.distanceModel = options.distanceModel;
+ this._panner.coneOuterGain = options.coneOuterGain;
+ this._panner.coneOuterAngle = options.coneOuterAngle;
+ this._panner.coneInnerAngle = options.coneInnerAngle;
+ this._panner.refDistance = options.refDistance;
+ this._panner.rolloffFactor = options.rolloffFactor;
+ /**
+ * Holds the current orientation
+ * @type {Array}
+ * @private
+ */
+ this._orientation = [
+ options.orientationX,
+ options.orientationY,
+ options.orientationZ
+ ];
+ /**
+ * Holds the current position
+ * @type {Array}
+ * @private
+ */
+ this._position = [
+ options.positionX,
+ options.positionY,
+ options.positionZ
+ ];
+ // set the default position/orientation
+ this.orientationX = options.orientationX;
+ this.orientationY = options.orientationY;
+ this.orientationZ = options.orientationZ;
+ this.positionX = options.positionX;
+ this.positionY = options.positionY;
+ this.positionZ = options.positionZ;
+ };
+ Tone.extend(Tone.Panner3D);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ * @type {Object}
+ * Defaults according to the specification
+ */
+ Tone.Panner3D.defaults = {
+ 'positionX': 0,
+ 'positionY': 0,
+ 'positionZ': 0,
+ 'orientationX': 0,
+ 'orientationY': 0,
+ 'orientationZ': 0,
+ 'panningModel': 'equalpower',
+ 'maxDistance': 10000,
+ 'distanceModel': 'inverse',
+ 'coneOuterGain': 0,
+ 'coneOuterAngle': 360,
+ 'coneInnerAngle': 360,
+ 'refDistance': 1,
+ 'rolloffFactor': 1
+ };
+ /**
+ * The ramp time which is applied to the setTargetAtTime
+ * @type {Number}
+ * @private
+ */
+ Tone.Panner3D.prototype._rampTimeConstant = 0.01;
+ /**
+ * Sets the position of the source in 3d space.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @return {Tone.Panner3D} this
+ */
+ Tone.Panner3D.prototype.setPosition = function (x, y, z) {
+ if (this._panner.positionX) {
+ var now = this.now();
+ this._panner.positionX.setTargetAtTime(x, now, this._rampTimeConstant);
+ this._panner.positionY.setTargetAtTime(y, now, this._rampTimeConstant);
+ this._panner.positionZ.setTargetAtTime(z, now, this._rampTimeConstant);
+ } else {
+ this._panner.setPosition(x, y, z);
+ }
+ this._position = Array.prototype.slice.call(arguments);
+ return this;
+ };
+ /**
+ * Sets the orientation of the source in 3d space.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @return {Tone.Panner3D} this
+ */
+ Tone.Panner3D.prototype.setOrientation = function (x, y, z) {
+ if (this._panner.orientationX) {
+ var now = this.now();
+ this._panner.orientationX.setTargetAtTime(x, now, this._rampTimeConstant);
+ this._panner.orientationY.setTargetAtTime(y, now, this._rampTimeConstant);
+ this._panner.orientationZ.setTargetAtTime(z, now, this._rampTimeConstant);
+ } else {
+ this._panner.setOrientation(x, y, z);
+ }
+ this._orientation = Array.prototype.slice.call(arguments);
+ return this;
+ };
+ /**
+ * The x position of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name positionX
+ */
+ Object.defineProperty(Tone.Panner3D.prototype, 'positionX', {
+ set: function (pos) {
+ this._position[0] = pos;
+ this.setPosition.apply(this, this._position);
+ },
+ get: function () {
+ return this._position[0];
+ }
+ });
+ /**
+ * The y position of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name positionY
+ */
+ Object.defineProperty(Tone.Panner3D.prototype, 'positionY', {
+ set: function (pos) {
+ this._position[1] = pos;
+ this.setPosition.apply(this, this._position);
+ },
+ get: function () {
+ return this._position[1];
+ }
+ });
+ /**
+ * The z position of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name positionZ
+ */
+ Object.defineProperty(Tone.Panner3D.prototype, 'positionZ', {
+ set: function (pos) {
+ this._position[2] = pos;
+ this.setPosition.apply(this, this._position);
+ },
+ get: function () {
+ return this._position[2];
+ }
+ });
+ /**
+ * The x orientation of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name orientationX
+ */
+ Object.defineProperty(Tone.Panner3D.prototype, 'orientationX', {
+ set: function (pos) {
+ this._orientation[0] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[0];
+ }
+ });
+ /**
+ * The y orientation of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name orientationY
+ */
+ Object.defineProperty(Tone.Panner3D.prototype, 'orientationY', {
+ set: function (pos) {
+ this._orientation[1] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[1];
+ }
+ });
+ /**
+ * The z orientation of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name orientationZ
+ */
+ Object.defineProperty(Tone.Panner3D.prototype, 'orientationZ', {
+ set: function (pos) {
+ this._orientation[2] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[2];
+ }
+ });
+ /**
+ * Proxy a property on the panner to an exposed public propery
+ * @param {String} prop
+ * @private
+ */
+ Tone.Panner3D._aliasProperty = function (prop) {
+ Object.defineProperty(Tone.Panner3D.prototype, prop, {
+ set: function (val) {
+ this._panner[prop] = val;
+ },
+ get: function () {
+ return this._panner[prop];
+ }
+ });
+ };
+ /**
+ * The panning model. Either "equalpower" or "HRTF".
+ * @type {String}
+ * @memberOf Tone.Panner3D#
+ * @name panningModel
+ */
+ Tone.Panner3D._aliasProperty('panningModel');
+ /**
+ * A reference distance for reducing volume as source move further from the listener
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name refDistance
+ */
+ Tone.Panner3D._aliasProperty('refDistance');
+ /**
+ * Describes how quickly the volume is reduced as source moves away from listener.
+ * @type {Number}
+ * @memberOf Tone.Panner3D#
+ * @name rolloffFactor
+ */
+ Tone.Panner3D._aliasProperty('rolloffFactor');
+ /**
+ * The distance model used by, "linear", "inverse", or "exponential".
+ * @type {String}
+ * @memberOf Tone.Panner3D#
+ * @name distanceModel
+ */
+ Tone.Panner3D._aliasProperty('distanceModel');
+ /**
+ * The angle, in degrees, inside of which there will be no volume reduction
+ * @type {Degrees}
+ * @memberOf Tone.Panner3D#
+ * @name coneInnerAngle
+ */
+ Tone.Panner3D._aliasProperty('coneInnerAngle');
+ /**
+ * The angle, in degrees, outside of which the volume will be reduced
+ * to a constant value of coneOuterGain
+ * @type {Degrees}
+ * @memberOf Tone.Panner3D#
+ * @name coneOuterAngle
+ */
+ Tone.Panner3D._aliasProperty('coneOuterAngle');
+ /**
+ * The gain outside of the coneOuterAngle
+ * @type {Gain}
+ * @memberOf Tone.Panner3D#
+ * @name coneOuterGain
+ */
+ Tone.Panner3D._aliasProperty('coneOuterGain');
+ /**
+ * The maximum distance between source and listener,
+ * after which the volume will not be reduced any further.
+ * @type {Positive}
+ * @memberOf Tone.Panner3D#
+ * @name maxDistance
+ */
+ Tone.Panner3D._aliasProperty('maxDistance');
+ /**
+ * Clean up.
+ * @returns {Tone.Panner3D} this
+ */
+ Tone.Panner3D.prototype.dispose = function () {
+ this._panner.disconnect();
+ this._panner = null;
+ this._orientation = null;
+ this._position = null;
+ return this;
+ };
+ return Tone.Panner3D;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.PanVol is a Tone.Panner and Tone.Volume in one.
+ *
+ * @extends {Tone}
+ * @constructor
+ * @param {AudioRange} pan the initial pan
+ * @param {number} volume The output volume.
+ * @example
+ * //pan the incoming signal left and drop the volume
+ * var panVol = new Tone.PanVol(0.25, -12);
+ */
+ Tone.PanVol = function () {
+ var options = this.optionsObject(arguments, [
+ 'pan',
+ 'volume'
+ ], Tone.PanVol.defaults);
+ /**
+ * The panning node
+ * @type {Tone.Panner}
+ * @private
+ */
+ this._panner = this.input = new Tone.Panner(options.pan);
+ /**
+ * The L/R panning control.
+ * @type {AudioRange}
+ * @signal
+ */
+ this.pan = this._panner.pan;
+ /**
+ * The volume node
+ * @type {Tone.Volume}
+ */
+ this._volume = this.output = new Tone.Volume(options.volume);
+ /**
+ * The volume control in decibels.
+ * @type {Decibels}
+ * @signal
+ */
+ this.volume = this._volume.volume;
+ //connections
+ this._panner.connect(this._volume);
+ this._readOnly([
+ 'pan',
+ 'volume'
+ ]);
+ };
+ Tone.extend(Tone.PanVol);
+ /**
+ * The defaults
+ * @type {Object}
+ * @const
+ * @static
+ */
+ Tone.PanVol.defaults = {
+ 'pan': 0.5,
+ 'volume': 0
+ };
+ /**
+ * clean up
+ * @returns {Tone.PanVol} this
+ */
+ Tone.PanVol.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._writable([
+ 'pan',
+ 'volume'
+ ]);
+ this._panner.dispose();
+ this._panner = null;
+ this.pan = null;
+ this._volume.dispose();
+ this._volume = null;
+ this.volume = null;
+ return this;
+ };
+ return Tone.PanVol;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.CtrlInterpolate will interpolate between given values based
+ * on the "index" property. Passing in an array or object literal
+ * will interpolate each of the parameters. Note (i.e. "C3")
+ * and Time (i.e. "4n + 2") can be interpolated. All other values are
+ * assumed to be numbers.
+ * @example
+ * var interp = new Tone.CtrlInterpolate([0, 2, 9, 4]);
+ * interp.index = 0.75;
+ * interp.value; //returns 1.5
+ *
+ * @example
+ * var interp = new Tone.CtrlInterpolate([
+ * [2, 4, 5],
+ * [9, 3, 2],
+ * ]);
+ * @param {Array} values The array of values to interpolate over
+ * @param {Positive} index The initial interpolation index.
+ * @extends {Tone}
+ */
+ Tone.CtrlInterpolate = function () {
+ var options = this.optionsObject(arguments, [
+ 'values',
+ 'index'
+ ], Tone.CtrlInterpolate.defaults);
+ /**
+ * The values to interpolate between
+ * @type {Array}
+ */
+ this.values = options.values;
+ /**
+ * The interpolated index between values. For example: a value of 1.5
+ * would interpolate equally between the value at index 1
+ * and the value at index 2.
+ * @example
+ * interp.index = 0;
+ * interp.value; //returns the value at 0
+ * interp.index = 0.5;
+ * interp.value; //returns the value between indices 0 and 1.
+ * @type {Positive}
+ */
+ this.index = options.index;
+ };
+ Tone.extend(Tone.CtrlInterpolate);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.CtrlInterpolate.defaults = {
+ 'index': 0,
+ 'values': []
+ };
+ /**
+ * The current interpolated value based on the index
+ * @readOnly
+ * @memberOf Tone.CtrlInterpolate#
+ * @type {*}
+ * @name value
+ */
+ Object.defineProperty(Tone.CtrlInterpolate.prototype, 'value', {
+ get: function () {
+ var index = this.index;
+ index = Math.min(index, this.values.length - 1);
+ var lowerPosition = Math.floor(index);
+ var lower = this.values[lowerPosition];
+ var upper = this.values[Math.ceil(index)];
+ return this._interpolate(index - lowerPosition, lower, upper);
+ }
+ });
+ /**
+ * Internal interpolation routine
+ * @param {NormalRange} index The index between the lower and upper
+ * @param {*} lower
+ * @param {*} upper
+ * @return {*} The interpolated value
+ * @private
+ */
+ Tone.CtrlInterpolate.prototype._interpolate = function (index, lower, upper) {
+ if (this.isArray(lower)) {
+ var retArray = [];
+ for (var i = 0; i < lower.length; i++) {
+ retArray[i] = this._interpolate(index, lower[i], upper[i]);
+ }
+ return retArray;
+ } else if (this.isObject(lower)) {
+ var retObj = {};
+ for (var attr in lower) {
+ retObj[attr] = this._interpolate(index, lower[attr], upper[attr]);
+ }
+ return retObj;
+ } else {
+ lower = this._toNumber(lower);
+ upper = this._toNumber(upper);
+ return (1 - index) * lower + index * upper;
+ }
+ };
+ /**
+ * Convert from the given type into a number
+ * @param {Number|String} value
+ * @return {Number}
+ * @private
+ */
+ Tone.CtrlInterpolate.prototype._toNumber = function (val) {
+ if (this.isNumber(val)) {
+ return val;
+ } else {
+ //otherwise assume that it's Time...
+ return this.toSeconds(val);
+ }
+ };
+ /**
+ * Clean up
+ * @return {Tone.CtrlInterpolate} this
+ */
+ Tone.CtrlInterpolate.prototype.dispose = function () {
+ this.values = null;
+ };
+ return Tone.CtrlInterpolate;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.CtrlMarkov represents a Markov Chain where each call
+ * to Tone.CtrlMarkov.next will move to the next state. If the next
+ * state choice is an array, the next state is chosen randomly with
+ * even probability for all of the choices. For a weighted probability
+ * of the next choices, pass in an object with "state" and "probability" attributes.
+ * The probabilities will be normalized and then chosen. If no next options
+ * are given for the current state, the state will stay there.
+ * @extends {Tone}
+ * @example
+ * var chain = new Tone.CtrlMarkov({
+ * "beginning" : ["end", "middle"],
+ * "middle" : "end"
+ * });
+ * chain.value = "beginning";
+ * chain.next(); //returns "end" or "middle" with 50% probability
+ *
+ * @example
+ * var chain = new Tone.CtrlMarkov({
+ * "beginning" : [{"value" : "end", "probability" : 0.8},
+ * {"value" : "middle", "probability" : 0.2}],
+ * "middle" : "end"
+ * });
+ * chain.value = "beginning";
+ * chain.next(); //returns "end" with 80% probability or "middle" with 20%.
+ * @param {Object} values An object with the state names as the keys
+ * and the next state(s) as the values.
+ */
+ Tone.CtrlMarkov = function (values, initial) {
+ /**
+ * The Markov values with states as the keys
+ * and next state(s) as the values.
+ * @type {Object}
+ */
+ this.values = this.defaultArg(values, {});
+ /**
+ * The current state of the Markov values. The next
+ * state will be evaluated and returned when Tone.CtrlMarkov.next
+ * is invoked.
+ * @type {String}
+ */
+ this.value = this.defaultArg(initial, Object.keys(this.values)[0]);
+ };
+ Tone.extend(Tone.CtrlMarkov);
+ /**
+ * Returns the next state of the Markov values.
+ * @return {String}
+ */
+ Tone.CtrlMarkov.prototype.next = function () {
+ if (this.values.hasOwnProperty(this.value)) {
+ var next = this.values[this.value];
+ if (this.isArray(next)) {
+ var distribution = this._getProbDistribution(next);
+ var rand = Math.random();
+ var total = 0;
+ for (var i = 0; i < distribution.length; i++) {
+ var dist = distribution[i];
+ if (rand > total && rand < total + dist) {
+ var chosen = next[i];
+ if (this.isObject(chosen)) {
+ this.value = chosen.value;
+ } else {
+ this.value = chosen;
+ }
+ }
+ total += dist;
+ }
+ } else {
+ this.value = next;
+ }
+ }
+ return this.value;
+ };
+ /**
+ * Choose randomly from an array weighted options in the form
+ * {"state" : string, "probability" : number} or an array of values
+ * @param {Array} options
+ * @return {Array} The randomly selected choice
+ * @private
+ */
+ Tone.CtrlMarkov.prototype._getProbDistribution = function (options) {
+ var distribution = [];
+ var total = 0;
+ var needsNormalizing = false;
+ for (var i = 0; i < options.length; i++) {
+ var option = options[i];
+ if (this.isObject(option)) {
+ needsNormalizing = true;
+ distribution[i] = option.probability;
+ } else {
+ distribution[i] = 1 / options.length;
+ }
+ total += distribution[i];
+ }
+ if (needsNormalizing) {
+ //normalize the values
+ for (var j = 0; j < distribution.length; j++) {
+ distribution[j] = distribution[j] / total;
+ }
+ }
+ return distribution;
+ };
+ /**
+ * Clean up
+ * @return {Tone.CtrlMarkov} this
+ */
+ Tone.CtrlMarkov.prototype.dispose = function () {
+ this.values = null;
+ };
+ return Tone.CtrlMarkov;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Generate patterns from an array of values.
+ * Has a number of arpeggiation and randomized
+ * selection patterns.
+ * <ul>
+ * <li>"up" - cycles upward</li>
+ * <li>"down" - cycles downward</li>
+ * <li>"upDown" - up then and down</li>
+ * <li>"downUp" - cycles down then and up</li>
+ * <li>"alternateUp" - jump up two and down one</li>
+ * <li>"alternateDown" - jump down two and up one</li>
+ * <li>"random" - randomly select an index</li>
+ * <li>"randomWalk" - randomly moves one index away from the current position</li>
+ * <li>"randomOnce" - randomly select an index without repeating until all values have been chosen.</li>
+ * </ul>
+ * @param {Array} values An array of options to choose from.
+ * @param {Tone.CtrlPattern.Type=} type The name of the pattern.
+ * @extends {Tone}
+ */
+ Tone.CtrlPattern = function () {
+ var options = this.optionsObject(arguments, [
+ 'values',
+ 'type'
+ ], Tone.CtrlPattern.defaults);
+ /**
+ * The array of values to arpeggiate over
+ * @type {Array}
+ */
+ this.values = options.values;
+ /**
+ * The current position in the values array
+ * @type {Number}
+ */
+ this.index = 0;
+ /**
+ * The type placeholder
+ * @type {Tone.CtrlPattern.Type}
+ * @private
+ */
+ this._type = null;
+ /**
+ * Shuffled values for the RandomOnce type
+ * @type {Array}
+ * @private
+ */
+ this._shuffled = null;
+ /**
+ * The direction of the movement
+ * @type {String}
+ * @private
+ */
+ this._direction = null;
+ this.type = options.type;
+ };
+ Tone.extend(Tone.CtrlPattern);
+ /**
+ * The Control Patterns
+ * @type {Object}
+ * @static
+ */
+ Tone.CtrlPattern.Type = {
+ Up: 'up',
+ Down: 'down',
+ UpDown: 'upDown',
+ DownUp: 'downUp',
+ AlternateUp: 'alternateUp',
+ AlternateDown: 'alternateDown',
+ Random: 'random',
+ RandomWalk: 'randomWalk',
+ RandomOnce: 'randomOnce'
+ };
+ /**
+ * The default values.
+ * @type {Object}
+ */
+ Tone.CtrlPattern.defaults = {
+ 'type': Tone.CtrlPattern.Type.Up,
+ 'values': []
+ };
+ /**
+ * The value at the current index of the pattern.
+ * @readOnly
+ * @memberOf Tone.CtrlPattern#
+ * @type {*}
+ * @name value
+ */
+ Object.defineProperty(Tone.CtrlPattern.prototype, 'value', {
+ get: function () {
+ //some safeguards
+ if (this.values.length === 0) {
+ return;
+ } else if (this.values.length === 1) {
+ return this.values[0];
+ }
+ this.index = Math.min(this.index, this.values.length - 1);
+ var val = this.values[this.index];
+ if (this.type === Tone.CtrlPattern.Type.RandomOnce) {
+ if (this.values.length !== this._shuffled.length) {
+ this._shuffleValues();
+ }
+ val = this.values[this._shuffled[this.index]];
+ }
+ return val;
+ }
+ });
+ /**
+ * The pattern used to select the next
+ * item from the values array
+ * @memberOf Tone.CtrlPattern#
+ * @type {Tone.CtrlPattern.Type}
+ * @name type
+ */
+ Object.defineProperty(Tone.CtrlPattern.prototype, 'type', {
+ get: function () {
+ return this._type;
+ },
+ set: function (type) {
+ this._type = type;
+ this._shuffled = null;
+ //the first index
+ if (this._type === Tone.CtrlPattern.Type.Up || this._type === Tone.CtrlPattern.Type.UpDown || this._type === Tone.CtrlPattern.Type.RandomOnce || this._type === Tone.CtrlPattern.Type.AlternateUp) {
+ this.index = 0;
+ } else if (this._type === Tone.CtrlPattern.Type.Down || this._type === Tone.CtrlPattern.Type.DownUp || this._type === Tone.CtrlPattern.Type.AlternateDown) {
+ this.index = this.values.length - 1;
+ }
+ //the direction
+ if (this._type === Tone.CtrlPattern.Type.UpDown || this._type === Tone.CtrlPattern.Type.AlternateUp) {
+ this._direction = Tone.CtrlPattern.Type.Up;
+ } else if (this._type === Tone.CtrlPattern.Type.DownUp || this._type === Tone.CtrlPattern.Type.AlternateDown) {
+ this._direction = Tone.CtrlPattern.Type.Down;
+ }
+ //randoms
+ if (this._type === Tone.CtrlPattern.Type.RandomOnce) {
+ this._shuffleValues();
+ } else if (this._type === Tone.CtrlPattern.Random) {
+ this.index = Math.floor(Math.random() * this.values.length);
+ }
+ }
+ });
+ /**
+ * Return the next value given the current position
+ * and pattern.
+ * @return {*} The next value
+ */
+ Tone.CtrlPattern.prototype.next = function () {
+ var type = this.type;
+ //choose the next index
+ if (type === Tone.CtrlPattern.Type.Up) {
+ this.index++;
+ if (this.index >= this.values.length) {
+ this.index = 0;
+ }
+ } else if (type === Tone.CtrlPattern.Type.Down) {
+ this.index--;
+ if (this.index < 0) {
+ this.index = this.values.length - 1;
+ }
+ } else if (type === Tone.CtrlPattern.Type.UpDown || type === Tone.CtrlPattern.Type.DownUp) {
+ if (this._direction === Tone.CtrlPattern.Type.Up) {
+ this.index++;
+ } else {
+ this.index--;
+ }
+ if (this.index < 0) {
+ this.index = 1;
+ this._direction = Tone.CtrlPattern.Type.Up;
+ } else if (this.index >= this.values.length) {
+ this.index = this.values.length - 2;
+ this._direction = Tone.CtrlPattern.Type.Down;
+ }
+ } else if (type === Tone.CtrlPattern.Type.Random) {
+ this.index = Math.floor(Math.random() * this.values.length);
+ } else if (type === Tone.CtrlPattern.Type.RandomWalk) {
+ if (Math.random() < 0.5) {
+ this.index--;
+ this.index = Math.max(this.index, 0);
+ } else {
+ this.index++;
+ this.index = Math.min(this.index, this.values.length - 1);
+ }
+ } else if (type === Tone.CtrlPattern.Type.RandomOnce) {
+ this.index++;
+ if (this.index >= this.values.length) {
+ this.index = 0;
+ //reshuffle the values for next time
+ this._shuffleValues();
+ }
+ } else if (type === Tone.CtrlPattern.Type.AlternateUp) {
+ if (this._direction === Tone.CtrlPattern.Type.Up) {
+ this.index += 2;
+ this._direction = Tone.CtrlPattern.Type.Down;
+ } else {
+ this.index -= 1;
+ this._direction = Tone.CtrlPattern.Type.Up;
+ }
+ if (this.index >= this.values.length) {
+ this.index = 0;
+ this._direction = Tone.CtrlPattern.Type.Up;
+ }
+ } else if (type === Tone.CtrlPattern.Type.AlternateDown) {
+ if (this._direction === Tone.CtrlPattern.Type.Up) {
+ this.index += 1;
+ this._direction = Tone.CtrlPattern.Type.Down;
+ } else {
+ this.index -= 2;
+ this._direction = Tone.CtrlPattern.Type.Up;
+ }
+ if (this.index < 0) {
+ this.index = this.values.length - 1;
+ this._direction = Tone.CtrlPattern.Type.Down;
+ }
+ }
+ return this.value;
+ };
+ /**
+ * Shuffles the values and places the results into the _shuffled
+ * @private
+ */
+ Tone.CtrlPattern.prototype._shuffleValues = function () {
+ var copy = [];
+ this._shuffled = [];
+ for (var i = 0; i < this.values.length; i++) {
+ copy[i] = i;
+ }
+ while (copy.length > 0) {
+ var randVal = copy.splice(Math.floor(copy.length * Math.random()), 1);
+ this._shuffled.push(randVal[0]);
+ }
+ };
+ /**
+ * Clean up
+ * @returns {Tone.CtrlPattern} this
+ */
+ Tone.CtrlPattern.prototype.dispose = function () {
+ this._shuffled = null;
+ this.values = null;
+ };
+ return Tone.CtrlPattern;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Choose a random value.
+ * @extends {Tone}
+ * @example
+ * var randomWalk = new Tone.CtrlRandom({
+ * "min" : 0,
+ * "max" : 10,
+ * "integer" : true
+ * });
+ * randomWalk.eval();
+ *
+ * @param {Number|Time=} min The minimum return value.
+ * @param {Number|Time=} max The maximum return value.
+ */
+ Tone.CtrlRandom = function () {
+ var options = this.optionsObject(arguments, [
+ 'min',
+ 'max'
+ ], Tone.CtrlRandom.defaults);
+ /**
+ * The minimum return value
+ * @type {Number|Time}
+ */
+ this.min = options.min;
+ /**
+ * The maximum return value
+ * @type {Number|Time}
+ */
+ this.max = options.max;
+ /**
+ * If the return value should be an integer
+ * @type {Boolean}
+ */
+ this.integer = options.integer;
+ };
+ Tone.extend(Tone.CtrlRandom);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.CtrlRandom.defaults = {
+ 'min': 0,
+ 'max': 1,
+ 'integer': false
+ };
+ /**
+ * Return a random value between min and max.
+ * @readOnly
+ * @memberOf Tone.CtrlRandom#
+ * @type {*}
+ * @name value
+ */
+ Object.defineProperty(Tone.CtrlRandom.prototype, 'value', {
+ get: function () {
+ var min = this.toSeconds(this.min);
+ var max = this.toSeconds(this.max);
+ var rand = Math.random();
+ var val = rand * min + (1 - rand) * max;
+ if (this.integer) {
+ val = Math.floor(val);
+ }
+ return val;
+ }
+ });
+ return Tone.CtrlRandom;
+ });
+ Module(function (Tone) {
+
+ /**
+ * AudioBuffer.copyToChannel polyfill
+ * @private
+ */
+ if (window.AudioBuffer && !AudioBuffer.prototype.copyToChannel) {
+ AudioBuffer.prototype.copyToChannel = function (src, chanNum, start) {
+ var channel = this.getChannelData(chanNum);
+ start = start || 0;
+ for (var i = 0; i < channel.length; i++) {
+ channel[i + start] = src[i];
+ }
+ };
+ AudioBuffer.prototype.copyFromChannel = function (dest, chanNum, start) {
+ var channel = this.getChannelData(chanNum);
+ start = start || 0;
+ for (var i = 0; i < channel.length; i++) {
+ dest[i] = channel[i + start];
+ }
+ };
+ }
+ /**
+ * @class Buffer loading and storage. Tone.Buffer is used internally by all
+ * classes that make requests for audio files such as Tone.Player,
+ * Tone.Sampler and Tone.Convolver.
+ * <br><br>
+ * Aside from load callbacks from individual buffers, Tone.Buffer
+ * provides static methods which keep track of the loading progress
+ * of all of the buffers. These methods are Tone.Buffer.on("load" / "progress" / "error")
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {AudioBuffer|string} url The url to load, or the audio buffer to set.
+ * @param {Function=} onload A callback which is invoked after the buffer is loaded.
+ * It's recommended to use Tone.Buffer.onload instead
+ * since it will give you a callback when ALL buffers are loaded.
+ * @param {Function=} onerror The callback to invoke if there is an error
+ * @example
+ * var buffer = new Tone.Buffer("path/to/sound.mp3", function(){
+ * //the buffer is now available.
+ * var buff = buffer.get();
+ * });
+ */
+ Tone.Buffer = function () {
+ var options = this.optionsObject(arguments, [
+ 'url',
+ 'onload',
+ 'onerror'
+ ], Tone.Buffer.defaults);
+ /**
+ * stores the loaded AudioBuffer
+ * @type {AudioBuffer}
+ * @private
+ */
+ this._buffer = null;
+ /**
+ * indicates if the buffer should be reversed or not
+ * @type {Boolean}
+ * @private
+ */
+ this._reversed = options.reverse;
+ /**
+ * The XHR
+ * @type {XMLHttpRequest}
+ * @private
+ */
+ this._xhr = null;
+ if (options.url instanceof AudioBuffer || options.url instanceof Tone.Buffer) {
+ this.set(options.url);
+ // invoke the onload callback
+ if (options.onload) {
+ options.onload(this);
+ }
+ } else if (this.isString(options.url)) {
+ this.load(options.url, options.onload, options.onerror);
+ }
+ };
+ Tone.extend(Tone.Buffer);
+ /**
+ * the default parameters
+ * @type {Object}
+ */
+ Tone.Buffer.defaults = {
+ 'url': undefined,
+ 'reverse': false
+ };
+ /**
+ * Pass in an AudioBuffer or Tone.Buffer to set the value
+ * of this buffer.
+ * @param {AudioBuffer|Tone.Buffer} buffer the buffer
+ * @returns {Tone.Buffer} this
+ */
+ Tone.Buffer.prototype.set = function (buffer) {
+ if (buffer instanceof Tone.Buffer) {
+ this._buffer = buffer.get();
+ } else {
+ this._buffer = buffer;
+ }
+ return this;
+ };
+ /**
+ * @return {AudioBuffer} The audio buffer stored in the object.
+ */
+ Tone.Buffer.prototype.get = function () {
+ return this._buffer;
+ };
+ /**
+ * Makes an xhr reqest for the selected url then decodes
+ * the file as an audio buffer. Invokes
+ * the callback once the audio buffer loads.
+ * @param {String} url The url of the buffer to load.
+ * filetype support depends on the
+ * browser.
+ * @returns {Promise} returns a Promise which resolves with the Tone.Buffer
+ */
+ Tone.Buffer.prototype.load = function (url, onload, onerror) {
+ var promise = new Promise(function (load, error) {
+ this._xhr = Tone.Buffer.load(url, //success
+ function (buff) {
+ this._xhr = null;
+ this.set(buff);
+ load(this);
+ if (onload) {
+ onload(this);
+ }
+ }.bind(this), //error
+ function (err) {
+ this._xhr = null;
+ error(err);
+ if (onerror) {
+ onerror(err);
+ }
+ }.bind(this));
+ }.bind(this));
+ return promise;
+ };
+ /**
+ * dispose and disconnect
+ * @returns {Tone.Buffer} this
+ */
+ Tone.Buffer.prototype.dispose = function () {
+ Tone.Emitter.prototype.dispose.call(this);
+ this._buffer = null;
+ if (this._xhr) {
+ Tone.Buffer._currentDownloads--;
+ this._xhr.abort();
+ this._xhr = null;
+ }
+ return this;
+ };
+ /**
+ * If the buffer is loaded or not
+ * @memberOf Tone.Buffer#
+ * @type {Boolean}
+ * @name loaded
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Buffer.prototype, 'loaded', {
+ get: function () {
+ return this.length > 0;
+ }
+ });
+ /**
+ * The duration of the buffer.
+ * @memberOf Tone.Buffer#
+ * @type {Number}
+ * @name duration
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Buffer.prototype, 'duration', {
+ get: function () {
+ if (this._buffer) {
+ return this._buffer.duration;
+ } else {
+ return 0;
+ }
+ }
+ });
+ /**
+ * The length of the buffer in samples
+ * @memberOf Tone.Buffer#
+ * @type {Number}
+ * @name length
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Buffer.prototype, 'length', {
+ get: function () {
+ if (this._buffer) {
+ return this._buffer.length;
+ } else {
+ return 0;
+ }
+ }
+ });
+ /**
+ * The number of discrete audio channels. Returns 0 if no buffer
+ * is loaded.
+ * @memberOf Tone.Buffer#
+ * @type {Number}
+ * @name numberOfChannels
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Buffer.prototype, 'numberOfChannels', {
+ get: function () {
+ if (this._buffer) {
+ return this._buffer.numberOfChannels;
+ } else {
+ return 0;
+ }
+ }
+ });
+ /**
+ * Set the audio buffer from the array
+ * @param {Float32Array} array The array to fill the audio buffer
+ * @param {Number} [channels=1] The number of channels contained in the array.
+ * If the channel is more than 1, the input array
+ * is expected to be a multidimensional array
+ * with dimensions equal to the number of channels.
+ * @return {Tone.Buffer} this
+ */
+ Tone.Buffer.prototype.fromArray = function (array) {
+ var isMultidimensional = array[0].length > 0;
+ var channels = isMultidimensional ? array.length : 1;
+ var len = isMultidimensional ? array[0].length : array.length;
+ var buffer = this.context.createBuffer(channels, len, this.context.sampleRate);
+ if (!isMultidimensional && channels === 1) {
+ array = [array];
+ }
+ for (var c = 0; c < channels; c++) {
+ buffer.copyToChannel(array[c], c);
+ }
+ this._buffer = buffer;
+ return this;
+ };
+ /**
+ * Sums muliple channels into 1 channel
+ * @param {Number=} channel Optionally only copy a single channel from the array.
+ * @return {Array}
+ */
+ Tone.Buffer.prototype.toMono = function (chanNum) {
+ if (this.isNumber(chanNum)) {
+ this.fromArray(this.toArray(chanNum));
+ } else {
+ var outputArray = new Float32Array(this.length);
+ var numChannels = this.numberOfChannels;
+ for (var channel = 0; channel < numChannels; channel++) {
+ var channelArray = this.toArray(channel);
+ for (var i = 0; i < channelArray.length; i++) {
+ outputArray[i] += channelArray[i];
+ }
+ }
+ //divide by the number of channels
+ outputArray = outputArray.map(function (sample) {
+ return sample / numChannels;
+ });
+ this.fromArray(outputArray);
+ }
+ return this;
+ };
+ /**
+ * Get the buffer as an array. Single channel buffers will return a 1-dimensional
+ * Float32Array, and multichannel buffers will return multidimensional arrays.
+ * @param {Number=} channel Optionally only copy a single channel from the array.
+ * @return {Array}
+ */
+ Tone.Buffer.prototype.toArray = function (channel) {
+ if (this.isNumber(channel)) {
+ return this.getChannelData(channel);
+ } else if (this.numberOfChannels === 1) {
+ return this.toArray(0);
+ } else {
+ var ret = [];
+ for (var c = 0; c < this.numberOfChannels; c++) {
+ ret[c] = this.getChannelData(c);
+ }
+ return ret;
+ }
+ };
+ /**
+ * Returns the Float32Array representing the PCM audio data for the specific channel.
+ * @param {Number} channel The channel number to return
+ * @return {Float32Array} The audio as a TypedArray
+ */
+ Tone.Buffer.prototype.getChannelData = function (channel) {
+ return this._buffer.getChannelData(channel);
+ };
+ /**
+ * Cut a subsection of the array and return a buffer of the
+ * subsection. Does not modify the original buffer
+ * @param {Time} start The time to start the slice
+ * @param {Time=} end The end time to slice. If none is given
+ * will default to the end of the buffer
+ * @return {Tone.Buffer} this
+ */
+ Tone.Buffer.prototype.slice = function (start, end) {
+ end = this.defaultArg(end, this.duration);
+ var startSamples = Math.floor(this.context.sampleRate * this.toSeconds(start));
+ var endSamples = Math.floor(this.context.sampleRate * this.toSeconds(end));
+ var replacement = [];
+ for (var i = 0; i < this.numberOfChannels; i++) {
+ replacement[i] = this.toArray(i).slice(startSamples, endSamples);
+ }
+ var retBuffer = new Tone.Buffer().fromArray(replacement);
+ return retBuffer;
+ };
+ /**
+ * Reverse the buffer.
+ * @private
+ * @return {Tone.Buffer} this
+ */
+ Tone.Buffer.prototype._reverse = function () {
+ if (this.loaded) {
+ for (var i = 0; i < this.numberOfChannels; i++) {
+ Array.prototype.reverse.call(this.getChannelData(i));
+ }
+ }
+ return this;
+ };
+ /**
+ * Reverse the buffer.
+ * @memberOf Tone.Buffer#
+ * @type {Boolean}
+ * @name reverse
+ */
+ Object.defineProperty(Tone.Buffer.prototype, 'reverse', {
+ get: function () {
+ return this._reversed;
+ },
+ set: function (rev) {
+ if (this._reversed !== rev) {
+ this._reversed = rev;
+ this._reverse();
+ }
+ }
+ });
+ ///////////////////////////////////////////////////////////////////////////
+ // STATIC METHODS
+ ///////////////////////////////////////////////////////////////////////////
+ //statically inherits Emitter methods
+ Tone.Emitter.mixin(Tone.Buffer);
+ /**
+ * the static queue for all of the xhr requests
+ * @type {Array}
+ * @private
+ */
+ Tone.Buffer._downloadQueue = [];
+ /**
+ * the total number of downloads
+ * @type {Number}
+ * @private
+ */
+ Tone.Buffer._currentDownloads = 0;
+ /**
+ * A path which is prefixed before every url.
+ * @type {String}
+ * @static
+ */
+ Tone.Buffer.baseUrl = '';
+ /**
+ * Loads a url using XMLHttpRequest.
+ * @param {String} url
+ * @param {Function} onload
+ * @param {Function} onerror
+ * @param {Function} onprogress
+ * @return {XMLHttpRequest}
+ */
+ Tone.Buffer.load = function (url, onload, onerror) {
+ //default
+ onload = onload || Tone.noOp;
+ function onError(e) {
+ if (onerror) {
+ onerror(e);
+ Tone.Buffer.emit('error', e);
+ } else {
+ throw new Error(e);
+ }
+ }
+ function onProgress() {
+ //calculate the progress
+ var totalProgress = 0;
+ for (var i = 0; i < Tone.Buffer._downloadQueue.length; i++) {
+ totalProgress += Tone.Buffer._downloadQueue[i].progress;
+ }
+ Tone.Buffer.emit('progress', totalProgress / Tone.Buffer._downloadQueue.length);
+ }
+ var request = new XMLHttpRequest();
+ request.open('GET', Tone.Buffer.baseUrl + url, true);
+ request.responseType = 'arraybuffer';
+ //start out as 0
+ request.progress = 0;
+ Tone.Buffer._currentDownloads++;
+ Tone.Buffer._downloadQueue.push(request);
+ request.addEventListener('load', function () {
+ if (request.status === 200) {
+ Tone.context.decodeAudioData(request.response, function (buff) {
+ request.progress = 1;
+ onProgress();
+ onload(buff);
+ Tone.Buffer._currentDownloads--;
+ if (Tone.Buffer._currentDownloads === 0) {
+ // clear the downloads
+ Tone.Buffer._downloadQueue = [];
+ //emit the event at the end
+ Tone.Buffer.emit('load');
+ }
+ }, function () {
+ onError('Tone.Buffer: could not decode audio data: ' + url);
+ });
+ } else {
+ onError('Tone.Buffer: could not locate file: ' + url);
+ }
+ });
+ request.addEventListener('error', onError);
+ request.addEventListener('progress', function (event) {
+ if (event.lengthComputable) {
+ //only go to 95%, the last 5% is when the audio is decoded
+ request.progress = event.loaded / event.total * 0.95;
+ onProgress();
+ }
+ });
+ request.send();
+ return request;
+ };
+ /**
+ * Stop all of the downloads in progress
+ * @return {Tone.Buffer}
+ * @static
+ */
+ Tone.Buffer.cancelDownloads = function () {
+ Tone.Buffer._downloadQueue.forEach(function (request) {
+ request.abort();
+ });
+ Tone.Buffer._currentDownloads = 0;
+ return Tone.Buffer;
+ };
+ /**
+ * Checks a url's extension to see if the current browser can play that file type.
+ * @param {String} url The url/extension to test
+ * @return {Boolean} If the file extension can be played
+ * @static
+ * @example
+ * Tone.Buffer.supportsType("wav"); //returns true
+ * Tone.Buffer.supportsType("path/to/file.wav"); //returns true
+ */
+ Tone.Buffer.supportsType = function (url) {
+ var extension = url.split('.');
+ extension = extension[extension.length - 1];
+ var response = document.createElement('audio').canPlayType('audio/' + extension);
+ return response !== '';
+ };
+ /**
+ * Returns a Promise which resolves when all of the buffers have loaded
+ * @return {Promise}
+ */
+ Tone.loaded = function () {
+ var onload, onerror;
+ function removeEvents() {
+ //remove the events when it's resolved
+ Tone.Buffer.off('load', onload);
+ Tone.Buffer.off('error', onerror);
+ }
+ return new Promise(function (success, fail) {
+ onload = function () {
+ success();
+ };
+ onerror = function () {
+ fail();
+ };
+ //add the event listeners
+ Tone.Buffer.on('load', onload);
+ Tone.Buffer.on('error', onerror);
+ }).then(removeEvents).catch(function (e) {
+ removeEvents();
+ throw new Error(e);
+ });
+ };
+ return Tone.Buffer;
+ });
+ Module(function (Tone) {
+ /**
+ * @class A data structure for holding multiple buffers.
+ *
+ * @param {Object|Array} urls An object literal or array
+ * of urls to load.
+ * @param {Function=} callback The callback to invoke when
+ * the buffers are loaded.
+ * @extends {Tone}
+ * @example
+ * //load a whole bank of piano samples
+ * var pianoSamples = new Tone.Buffers({
+ * "C4" : "path/to/C4.mp3"
+ * "C#4" : "path/to/C#4.mp3"
+ * "D4" : "path/to/D4.mp3"
+ * "D#4" : "path/to/D#4.mp3"
+ * ...
+ * }, function(){
+ * //play one of the samples when they all load
+ * player.buffer = pianoSamples.get("C4");
+ * player.start();
+ * });
+ *
+ */
+ Tone.Buffers = function (urls, onload, baseUrl) {
+ /**
+ * All of the buffers
+ * @type {Object}
+ * @private
+ */
+ this._buffers = {};
+ /**
+ * A path which is prefixed before every url.
+ * @type {String}
+ */
+ this.baseUrl = this.defaultArg(baseUrl, '');
+ urls = this._flattenUrls(urls);
+ this._loadingCount = 0;
+ //add each one
+ for (var key in urls) {
+ this._loadingCount++;
+ this.add(key, urls[key], this._bufferLoaded.bind(this, onload));
+ }
+ };
+ Tone.extend(Tone.Buffers);
+ /**
+ * True if the buffers object has a buffer by that name.
+ * @param {String|Number} name The key or index of the
+ * buffer.
+ * @return {Boolean}
+ */
+ Tone.Buffers.prototype.has = function (name) {
+ return this._buffers.hasOwnProperty(name);
+ };
+ /**
+ * Get a buffer by name. If an array was loaded,
+ * then use the array index.
+ * @param {String|Number} name The key or index of the
+ * buffer.
+ * @return {Tone.Buffer}
+ */
+ Tone.Buffers.prototype.get = function (name) {
+ if (this.has(name)) {
+ return this._buffers[name];
+ } else {
+ throw new Error('Tone.Buffers: no buffer named ' + name);
+ }
+ };
+ /**
+ * A buffer was loaded. decrement the counter.
+ * @param {Function} callback
+ * @private
+ */
+ Tone.Buffers.prototype._bufferLoaded = function (callback) {
+ this._loadingCount--;
+ if (this._loadingCount === 0 && callback) {
+ callback(this);
+ }
+ };
+ /**
+ * If the buffers are loaded or not
+ * @memberOf Tone.Buffers#
+ * @type {Boolean}
+ * @name loaded
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Buffers.prototype, 'loaded', {
+ get: function () {
+ var isLoaded = true;
+ for (var buffName in this._buffers) {
+ var buff = this.get(buffName);
+ isLoaded = isLoaded && buff.loaded;
+ }
+ return isLoaded;
+ }
+ });
+ /**
+ * Add a buffer by name and url to the Buffers
+ * @param {String} name A unique name to give
+ * the buffer
+ * @param {String|Tone.Buffer|Audiobuffer} url Either the url of the bufer,
+ * or a buffer which will be added
+ * with the given name.
+ * @param {Function=} callback The callback to invoke
+ * when the url is loaded.
+ */
+ Tone.Buffers.prototype.add = function (name, url, callback) {
+ callback = this.defaultArg(callback, Tone.noOp);
+ if (url instanceof Tone.Buffer) {
+ this._buffers[name] = url;
+ callback(this);
+ } else if (url instanceof AudioBuffer) {
+ this._buffers[name] = new Tone.Buffer(url);
+ callback(this);
+ } else if (this.isString(url)) {
+ this._buffers[name] = new Tone.Buffer(this.baseUrl + url, callback);
+ }
+ return this;
+ };
+ /**
+ * Flatten an object into a single depth object.
+ * thanks to https://gist.github.com/penguinboy/762197
+ * @param {Object} ob
+ * @return {Object}
+ * @private
+ */
+ Tone.Buffers.prototype._flattenUrls = function (ob) {
+ var toReturn = {};
+ for (var i in ob) {
+ if (!ob.hasOwnProperty(i))
+ continue;
+ if (this.isObject(ob[i])) {
+ var flatObject = this._flattenUrls(ob[i]);
+ for (var x in flatObject) {
+ if (!flatObject.hasOwnProperty(x))
+ continue;
+ toReturn[i + '.' + x] = flatObject[x];
+ }
+ } else {
+ toReturn[i] = ob[i];
+ }
+ }
+ return toReturn;
+ };
+ /**
+ * Clean up.
+ * @return {Tone.Buffers} this
+ */
+ Tone.Buffers.prototype.dispose = function () {
+ for (var name in this._buffers) {
+ this._buffers[name].dispose();
+ }
+ this._buffers = null;
+ return this;
+ };
+ return Tone.Buffers;
+ });
+ Module(function (Tone) {
+
+ /**
+ * buses are another way of routing audio
+ *
+ * augments Tone.prototype to include send and recieve
+ */
+ /**
+ * All of the routes
+ *
+ * @type {Object}
+ * @static
+ * @private
+ */
+ var Buses = {};
+ /**
+ * Send this signal to the channel name.
+ * @param {string} channelName A named channel to send the signal to.
+ * @param {Decibels} amount The amount of the source to send to the bus.
+ * @return {GainNode} The gain node which connects this node to the desired channel.
+ * Can be used to adjust the levels of the send.
+ * @example
+ * source.send("reverb", -12);
+ */
+ Tone.prototype.send = function (channelName, amount) {
+ if (!Buses.hasOwnProperty(channelName)) {
+ Buses[channelName] = this.context.createGain();
+ }
+ amount = this.defaultArg(amount, 0);
+ var sendKnob = new Tone.Gain(amount, Tone.Type.Decibels);
+ this.output.chain(sendKnob, Buses[channelName]);
+ return sendKnob;
+ };
+ /**
+ * Recieve the input from the desired channelName to the input
+ *
+ * @param {string} channelName A named channel to send the signal to.
+ * @param {AudioNode} [input] If no input is selected, the
+ * input of the current node is
+ * chosen.
+ * @returns {Tone} this
+ * @example
+ * reverbEffect.receive("reverb");
+ */
+ Tone.prototype.receive = function (channelName, input) {
+ if (!Buses.hasOwnProperty(channelName)) {
+ Buses[channelName] = this.context.createGain();
+ }
+ if (this.isUndef(input)) {
+ input = this.input;
+ }
+ Buses[channelName].connect(input);
+ return this;
+ };
+ //remove all the send/receives when a new audio context is passed in
+ Tone.Context.on('init', function (context) {
+ if (context.Buses) {
+ Buses = context.Buses;
+ } else {
+ Buses = {};
+ context.Buses = Buses;
+ }
+ });
+ return Tone;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Draw is useful for synchronizing visuals and audio events.
+ * Callbacks from Tone.Transport or any of the Tone.Event classes
+ * always happen _before_ the scheduled time and are not synchronized
+ * to the animation frame so they are not good for triggering tightly
+ * synchronized visuals and sound. Tone.Draw makes it easy to schedule
+ * callbacks using the AudioContext time and uses requestAnimationFrame.
+ *
+ * @singleton
+ * @extends {Tone}
+ * @example
+ * Tone.Transport.schedule(function(time){
+ * //use the time argument to schedule a callback with Tone.Draw
+ * Tone.Draw.schedule(function(){
+ * //do drawing or DOM manipulation here
+ * }, time)
+ * }, "+0.5")
+ */
+ Tone.Draw = function () {
+ /**
+ * All of the events.
+ * @type {Tone.Timeline}
+ * @private
+ */
+ this._events = new Tone.Timeline();
+ /**
+ * The duration after which events are not invoked.
+ * @type {Number}
+ * @default 0.25
+ */
+ this.expiration = 0.25;
+ /**
+ * The amount of time before the scheduled time
+ * that the callback can be invoked. Default is
+ * half the time of an animation frame (0.008 seconds).
+ * @type {Number}
+ * @default 0.008
+ */
+ this.anticipation = 0.008;
+ /**
+ * The draw loop
+ * @type {Function}
+ * @private
+ */
+ this._boundDrawLoop = this._drawLoop.bind(this);
+ };
+ Tone.extend(Tone.Draw);
+ /**
+ * Schedule a function at the given time to be invoked
+ * on the nearest animation frame.
+ * @param {Function} callback Callback is invoked at the given time.
+ * @param {Time} time The time relative to the AudioContext time
+ * to invoke the callback.
+ * @return {Tone.Draw} this
+ */
+ Tone.Draw.prototype.schedule = function (callback, time) {
+ this._events.add({
+ callback: callback,
+ time: this.toSeconds(time)
+ });
+ //start the draw loop on the first event
+ if (this._events.length === 1) {
+ requestAnimationFrame(this._boundDrawLoop);
+ }
+ return this;
+ };
+ /**
+ * Cancel events scheduled after the given time
+ * @param {Time=} after Time after which scheduled events will
+ * be removed from the scheduling timeline.
+ * @return {Tone.Draw} this
+ */
+ Tone.Draw.prototype.cancel = function (after) {
+ this._events.cancel(this.toSeconds(after));
+ return this;
+ };
+ /**
+ * The draw loop
+ * @private
+ */
+ Tone.Draw.prototype._drawLoop = function () {
+ var now = Tone.now();
+ while (this._events.length && this._events.peek().time - this.anticipation <= now) {
+ var event = this._events.shift();
+ if (now - event.time <= this.expiration) {
+ event.callback();
+ }
+ }
+ if (this._events.length > 0) {
+ requestAnimationFrame(this._boundDrawLoop);
+ }
+ };
+ //make a singleton
+ Tone.Draw = new Tone.Draw();
+ return Tone.Draw;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Both Tone.Panner3D and Tone.Listener have a position in 3D space
+ * using a right-handed cartesian coordinate system.
+ * The units used in the coordinate system are not defined;
+ * these coordinates are independent/invariant of any particular
+ * units such as meters or feet. Tone.Panner3D objects have an forward
+ * vector representing the direction the sound is projecting. Additionally,
+ * they have a sound cone representing how directional the sound is.
+ * For example, the sound could be omnidirectional, in which case it would
+ * be heard anywhere regardless of its forward, or it can be more directional
+ * and heard only if it is facing the listener. Tone.Listener objects
+ * (representing a person's ears) have an forward and up vector
+ * representing in which direction the person is facing. Because both the
+ * source stream and the listener can be moving, they both have a velocity
+ * vector representing both the speed and direction of movement. Taken together,
+ * these two velocities can be used to generate a doppler shift effect which changes the pitch.
+ * <br><br>
+ * Note: the position of the Listener will have no effect on nodes not connected to a Tone.Panner3D
+ *
+ * @constructor
+ * @extends {Tone}
+ * @singleton
+ * @param {Number} positionX The initial x position.
+ * @param {Number} positionY The initial y position.
+ * @param {Number} positionZ The initial z position.
+ */
+ Tone.Listener = function () {
+ var options = this.optionsObject(arguments, [
+ 'positionX',
+ 'positionY',
+ 'positionZ'
+ ], ListenerConstructor.defaults);
+ /**
+ * Holds the current forward orientation
+ * @type {Array}
+ * @private
+ */
+ this._orientation = [
+ options.forwardX,
+ options.forwardY,
+ options.forwardZ,
+ options.upX,
+ options.upY,
+ options.upZ
+ ];
+ /**
+ * Holds the current position
+ * @type {Array}
+ * @private
+ */
+ this._position = [
+ options.positionX,
+ options.positionY,
+ options.positionZ
+ ];
+ // set the default position/forward
+ this.forwardX = options.forwardX;
+ this.forwardY = options.forwardY;
+ this.forwardZ = options.forwardZ;
+ this.upX = options.upX;
+ this.upY = options.upY;
+ this.upZ = options.upZ;
+ this.positionX = options.positionX;
+ this.positionY = options.positionY;
+ this.positionZ = options.positionZ;
+ };
+ Tone.extend(Tone.Listener);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ * @type {Object}
+ * Defaults according to the specification
+ */
+ Tone.Listener.defaults = {
+ 'positionX': 0,
+ 'positionY': 0,
+ 'positionZ': 0,
+ 'forwardX': 0,
+ 'forwardY': 0,
+ 'forwardZ': 1,
+ 'upX': 0,
+ 'upY': 1,
+ 'upZ': 0
+ };
+ /**
+ * The ramp time which is applied to the setTargetAtTime
+ * @type {Number}
+ * @private
+ */
+ Tone.Listener.prototype._rampTimeConstant = 0.01;
+ /**
+ * Sets the position of the listener in 3d space.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @return {Tone.Listener} this
+ */
+ Tone.Listener.prototype.setPosition = function (x, y, z) {
+ if (this.context.listener.positionX) {
+ var now = this.now();
+ this.context.listener.positionX.setTargetAtTime(x, now, this._rampTimeConstant);
+ this.context.listener.positionY.setTargetAtTime(y, now, this._rampTimeConstant);
+ this.context.listener.positionZ.setTargetAtTime(z, now, this._rampTimeConstant);
+ } else {
+ this.context.listener.setPosition(x, y, z);
+ }
+ this._position = Array.prototype.slice.call(arguments);
+ return this;
+ };
+ /**
+ * Sets the orientation of the listener using two vectors, the forward
+ * vector (which direction the listener is facing) and the up vector
+ * (which the up direction of the listener). An up vector
+ * of 0, 0, 1 is equivalent to the listener standing up in the Z direction.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @param {Number} upX
+ * @param {Number} upY
+ * @param {Number} upZ
+ * @return {Tone.Listener} this
+ */
+ Tone.Listener.prototype.setOrientation = function (x, y, z, upX, upY, upZ) {
+ if (this.context.listener.forwardX) {
+ var now = this.now();
+ this.context.listener.forwardX.setTargetAtTime(x, now, this._rampTimeConstant);
+ this.context.listener.forwardY.setTargetAtTime(y, now, this._rampTimeConstant);
+ this.context.listener.forwardZ.setTargetAtTime(z, now, this._rampTimeConstant);
+ this.context.listener.upX.setTargetAtTime(upX, now, this._rampTimeConstant);
+ this.context.listener.upY.setTargetAtTime(upY, now, this._rampTimeConstant);
+ this.context.listener.upZ.setTargetAtTime(upZ, now, this._rampTimeConstant);
+ } else {
+ this.context.listener.setOrientation(x, y, z, upX, upY, upZ);
+ }
+ this._orientation = Array.prototype.slice.call(arguments);
+ return this;
+ };
+ /**
+ * The x position of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name positionX
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'positionX', {
+ set: function (pos) {
+ this._position[0] = pos;
+ this.setPosition.apply(this, this._position);
+ },
+ get: function () {
+ return this._position[0];
+ }
+ });
+ /**
+ * The y position of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name positionY
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'positionY', {
+ set: function (pos) {
+ this._position[1] = pos;
+ this.setPosition.apply(this, this._position);
+ },
+ get: function () {
+ return this._position[1];
+ }
+ });
+ /**
+ * The z position of the panner object.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name positionZ
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'positionZ', {
+ set: function (pos) {
+ this._position[2] = pos;
+ this.setPosition.apply(this, this._position);
+ },
+ get: function () {
+ return this._position[2];
+ }
+ });
+ /**
+ * The x coordinate of the listeners front direction. i.e.
+ * which way they are facing.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name forwardX
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'forwardX', {
+ set: function (pos) {
+ this._orientation[0] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[0];
+ }
+ });
+ /**
+ * The y coordinate of the listeners front direction. i.e.
+ * which way they are facing.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name forwardY
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'forwardY', {
+ set: function (pos) {
+ this._orientation[1] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[1];
+ }
+ });
+ /**
+ * The z coordinate of the listeners front direction. i.e.
+ * which way they are facing.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name forwardZ
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'forwardZ', {
+ set: function (pos) {
+ this._orientation[2] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[2];
+ }
+ });
+ /**
+ * The x coordinate of the listener's up direction. i.e.
+ * the direction the listener is standing in.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name upX
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'upX', {
+ set: function (pos) {
+ this._orientation[3] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[3];
+ }
+ });
+ /**
+ * The y coordinate of the listener's up direction. i.e.
+ * the direction the listener is standing in.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name upY
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'upY', {
+ set: function (pos) {
+ this._orientation[4] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[4];
+ }
+ });
+ /**
+ * The z coordinate of the listener's up direction. i.e.
+ * the direction the listener is standing in.
+ * @type {Number}
+ * @memberOf Tone.Listener#
+ * @name upZ
+ */
+ Object.defineProperty(Tone.Listener.prototype, 'upZ', {
+ set: function (pos) {
+ this._orientation[5] = pos;
+ this.setOrientation.apply(this, this._orientation);
+ },
+ get: function () {
+ return this._orientation[5];
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Listener} this
+ */
+ Tone.Listener.prototype.dispose = function () {
+ this._orientation = null;
+ this._position = null;
+ return this;
+ };
+ //SINGLETON SETUP
+ var ListenerConstructor = Tone.Listener;
+ Tone.Listener = new ListenerConstructor();
+ Tone.Context.on('init', function (context) {
+ if (context.Listener instanceof ListenerConstructor) {
+ //a single listener object
+ Tone.Listener = context.Listener;
+ } else {
+ //make new Listener insides
+ Tone.Listener = new ListenerConstructor();
+ }
+ context.Listener = Tone.Listener;
+ });
+ //END SINGLETON SETUP
+ return Tone.Listener;
+ });
+ Module(function (Tone) {
+ /**
+ * shim
+ * @private
+ */
+ if (!window.hasOwnProperty('OfflineAudioContext') && window.hasOwnProperty('webkitOfflineAudioContext')) {
+ window.OfflineAudioContext = window.webkitOfflineAudioContext;
+ }
+ /**
+ * @class Wrapper around the OfflineAudioContext
+ * @extends {Tone.Context
+ * @param {Number} channels The number of channels to render
+ * @param {Number} duration The duration to render in samples
+ * @param {Number} sampleRate the sample rate to render at
+ */
+ Tone.OfflineContext = function (channels, duration, sampleRate) {
+ /**
+ * The offline context
+ * @private
+ * @type {OfflineAudioContext}
+ */
+ var offlineContext = new OfflineAudioContext(channels, duration * sampleRate, sampleRate);
+ //wrap the methods/members
+ Tone.Context.call(this, offlineContext);
+ /**
+ * A private reference to the duration
+ * @private
+ * @type {Number}
+ */
+ this._duration = duration;
+ /**
+ * An artificial clock source
+ * @type {Number}
+ * @private
+ */
+ this._currentTime = 0;
+ //modify the lookAhead and updateInterval to one block
+ this.lookAhead = this.blockTime;
+ this.updateInterval = this.blockTime;
+ };
+ Tone.extend(Tone.OfflineContext, Tone.Context);
+ /**
+ * Override the now method to point to the internal clock time
+ * @return {Number}
+ */
+ Tone.OfflineContext.prototype.now = function () {
+ return this._currentTime;
+ };
+ /**
+ * Overwrite this method since the worker is not necessary for the offline context
+ * @private
+ */
+ Tone.OfflineContext.prototype._createWorker = function () {
+ //dummy worker that does nothing
+ return {
+ postMessage: function () {
+ }
+ };
+ };
+ /**
+ * Render the output of the OfflineContext
+ * @return {Promise}
+ */
+ Tone.OfflineContext.prototype.render = function () {
+ while (this._duration - this._currentTime >= 0) {
+ //invoke all the callbacks on that time
+ this.emit('tick');
+ //increment the clock
+ this._currentTime += Tone.prototype.blockTime;
+ }
+ //promise returned is not yet implemented in all browsers
+ return new Promise(function (done) {
+ this._context.oncomplete = function (e) {
+ done(e.renderedBuffer);
+ };
+ this._context.startRendering();
+ }.bind(this));
+ };
+ return Tone.OfflineContext;
+ });
+ Module(function (Tone) {
+ /**
+ * Generate a buffer by rendering all of the Tone.js code within the callback using the OfflineAudioContext.
+ * The OfflineAudioContext is capable of rendering much faster than real time in many cases.
+ * The callback function also passes in an offline instance of Tone.Transport which can be used
+ * to schedule events along the Transport.
+ * @param {Function} callback All Tone.js nodes which are created and scheduled within this callback are recorded into the output Buffer.
+ * @param {Time} duration the amount of time to record for.
+ * @return {Promise} The promise which is invoked with the Tone.Buffer of the recorded output.
+ * @example
+ * //render 2 seconds of the oscillator
+ * Tone.Offline(function(){
+ * //only nodes created in this callback will be recorded
+ * var oscillator = new Tone.Oscillator().toMaster().start(0)
+ * //schedule their events
+ * }, 2).then(function(buffer){
+ * //do something with the output buffer
+ * })
+ * @example
+ * //can also schedule events along the Transport
+ * //using the passed in Offline Transport
+ * Tone.Offline(function(Transport){
+ * var osc = new Tone.Oscillator().toMaster()
+ * Transport.schedule(function(time){
+ * osc.start(time).stop(time + 0.1)
+ * }, 1)
+ * Transport.start(0.2)
+ * }, 4).then(function(buffer){
+ * //do something with the output buffer
+ * })
+ */
+ Tone.Offline = function (callback, duration) {
+ //set the OfflineAudioContext
+ var sampleRate = Tone.context.sampleRate;
+ var originalContext = Tone.context;
+ var context = new Tone.OfflineContext(2, duration, sampleRate);
+ Tone.context = context;
+ //invoke the callback/scheduling
+ callback(Tone.Transport);
+ //process the audio
+ var rendered = context.render();
+ //return the original AudioContext
+ Tone.context = originalContext;
+ //return the audio
+ return rendered.then(function (buffer) {
+ //wrap it in a Tone.Buffer
+ return new Tone.Buffer(buffer);
+ });
+ };
+ return Tone.Offline;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Effect is the base class for effects. Connect the effect between
+ * the effectSend and effectReturn GainNodes, then control the amount of
+ * effect which goes to the output using the wet control.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {NormalRange|Object} [wet] The starting wet value.
+ */
+ Tone.Effect = function () {
+ this.createInsOuts(1, 1);
+ //get all of the defaults
+ var options = this.optionsObject(arguments, ['wet'], Tone.Effect.defaults);
+ /**
+ * the drywet knob to control the amount of effect
+ * @type {Tone.CrossFade}
+ * @private
+ */
+ this._dryWet = new Tone.CrossFade(options.wet);
+ /**
+ * The wet control is how much of the effected
+ * will pass through to the output. 1 = 100% effected
+ * signal, 0 = 100% dry signal.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.wet = this._dryWet.fade;
+ /**
+ * connect the effectSend to the input of hte effect
+ * @type {Tone.Gain}
+ * @private
+ */
+ this.effectSend = new Tone.Gain();
+ /**
+ * connect the output of the effect to the effectReturn
+ * @type {Tone.Gain}
+ * @private
+ */
+ this.effectReturn = new Tone.Gain();
+ //connections
+ this.input.connect(this._dryWet.a);
+ this.input.connect(this.effectSend);
+ this.effectReturn.connect(this._dryWet.b);
+ this._dryWet.connect(this.output);
+ this._readOnly(['wet']);
+ };
+ Tone.extend(Tone.Effect);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.Effect.defaults = { 'wet': 1 };
+ /**
+ * chains the effect in between the effectSend and effectReturn
+ * @param {Tone} effect
+ * @private
+ * @returns {Tone.Effect} this
+ */
+ Tone.Effect.prototype.connectEffect = function (effect) {
+ this.effectSend.chain(effect, this.effectReturn);
+ return this;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Effect} this
+ */
+ Tone.Effect.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._dryWet.dispose();
+ this._dryWet = null;
+ this.effectSend.dispose();
+ this.effectSend = null;
+ this.effectReturn.dispose();
+ this.effectReturn = null;
+ this._writable(['wet']);
+ this.wet = null;
+ return this;
+ };
+ return Tone.Effect;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.AutoFilter is a Tone.Filter with a Tone.LFO connected to the filter cutoff frequency.
+ * Setting the LFO rate and depth allows for control over the filter modulation rate
+ * and depth.
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ * @param {Time|Object} [frequency] The rate of the LFO.
+ * @param {Frequency=} baseFrequency The lower value of the LFOs oscillation
+ * @param {Frequency=} octaves The number of octaves above the baseFrequency
+ * @example
+ * //create an autofilter and start it's LFO
+ * var autoFilter = new Tone.AutoFilter("4n").toMaster().start();
+ * //route an oscillator through the filter and start it
+ * var oscillator = new Tone.Oscillator().connect(autoFilter).start();
+ */
+ Tone.AutoFilter = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'baseFrequency',
+ 'octaves'
+ ], Tone.AutoFilter.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * the lfo which drives the filter cutoff
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfo = new Tone.LFO({
+ 'frequency': options.frequency,
+ 'amplitude': options.depth
+ });
+ /**
+ * The range of the filter modulating between the min and max frequency.
+ * 0 = no modulation. 1 = full modulation.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.depth = this._lfo.amplitude;
+ /**
+ * How fast the filter modulates between min and max.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._lfo.frequency;
+ /**
+ * The filter node
+ * @type {Tone.Filter}
+ */
+ this.filter = new Tone.Filter(options.filter);
+ /**
+ * The octaves placeholder
+ * @type {Positive}
+ * @private
+ */
+ this._octaves = 0;
+ //connections
+ this.connectEffect(this.filter);
+ this._lfo.connect(this.filter.frequency);
+ this.type = options.type;
+ this._readOnly([
+ 'frequency',
+ 'depth'
+ ]);
+ this.octaves = options.octaves;
+ this.baseFrequency = options.baseFrequency;
+ };
+ //extend Effect
+ Tone.extend(Tone.AutoFilter, Tone.Effect);
+ /**
+ * defaults
+ * @static
+ * @type {Object}
+ */
+ Tone.AutoFilter.defaults = {
+ 'frequency': 1,
+ 'type': 'sine',
+ 'depth': 1,
+ 'baseFrequency': 200,
+ 'octaves': 2.6,
+ 'filter': {
+ 'type': 'lowpass',
+ 'rolloff': -12,
+ 'Q': 1
+ }
+ };
+ /**
+ * Start the effect.
+ * @param {Time} [time=now] When the LFO will start.
+ * @returns {Tone.AutoFilter} this
+ */
+ Tone.AutoFilter.prototype.start = function (time) {
+ this._lfo.start(time);
+ return this;
+ };
+ /**
+ * Stop the effect.
+ * @param {Time} [time=now] When the LFO will stop.
+ * @returns {Tone.AutoFilter} this
+ */
+ Tone.AutoFilter.prototype.stop = function (time) {
+ this._lfo.stop(time);
+ return this;
+ };
+ /**
+ * Sync the filter to the transport.
+ * @param {Time} [delay=0] Delay time before starting the effect after the
+ * Transport has started.
+ * @returns {Tone.AutoFilter} this
+ */
+ Tone.AutoFilter.prototype.sync = function (delay) {
+ this._lfo.sync(delay);
+ return this;
+ };
+ /**
+ * Unsync the filter from the transport.
+ * @returns {Tone.AutoFilter} this
+ */
+ Tone.AutoFilter.prototype.unsync = function () {
+ this._lfo.unsync();
+ return this;
+ };
+ /**
+ * Type of oscillator attached to the AutoFilter.
+ * Possible values: "sine", "square", "triangle", "sawtooth".
+ * @memberOf Tone.AutoFilter#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.AutoFilter.prototype, 'type', {
+ get: function () {
+ return this._lfo.type;
+ },
+ set: function (type) {
+ this._lfo.type = type;
+ }
+ });
+ /**
+ * The minimum value of the filter's cutoff frequency.
+ * @memberOf Tone.AutoFilter#
+ * @type {Frequency}
+ * @name min
+ */
+ Object.defineProperty(Tone.AutoFilter.prototype, 'baseFrequency', {
+ get: function () {
+ return this._lfo.min;
+ },
+ set: function (freq) {
+ this._lfo.min = this.toFrequency(freq);
+ //and set the max
+ this.octaves = this._octaves;
+ }
+ });
+ /**
+ * The maximum value of the filter's cutoff frequency.
+ * @memberOf Tone.AutoFilter#
+ * @type {Positive}
+ * @name octaves
+ */
+ Object.defineProperty(Tone.AutoFilter.prototype, 'octaves', {
+ get: function () {
+ return this._octaves;
+ },
+ set: function (oct) {
+ this._octaves = oct;
+ this._lfo.max = this.baseFrequency * Math.pow(2, oct);
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.AutoFilter} this
+ */
+ Tone.AutoFilter.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._lfo.dispose();
+ this._lfo = null;
+ this.filter.dispose();
+ this.filter = null;
+ this._writable([
+ 'frequency',
+ 'depth'
+ ]);
+ this.frequency = null;
+ this.depth = null;
+ return this;
+ };
+ return Tone.AutoFilter;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.AutoPanner is a Tone.Panner with an LFO connected to the pan amount.
+ * More on using autopanners [here](https://www.ableton.com/en/blog/autopan-chopper-effect-and-more-liveschool/).
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ * @param {Frequency|Object} [frequency] Rate of left-right oscillation.
+ * @example
+ * //create an autopanner and start it's LFO
+ * var autoPanner = new Tone.AutoPanner("4n").toMaster().start();
+ * //route an oscillator through the panner and start it
+ * var oscillator = new Tone.Oscillator().connect(autoPanner).start();
+ */
+ Tone.AutoPanner = function () {
+ var options = this.optionsObject(arguments, ['frequency'], Tone.AutoPanner.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * the lfo which drives the panning
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfo = new Tone.LFO({
+ 'frequency': options.frequency,
+ 'amplitude': options.depth,
+ 'min': -1,
+ 'max': 1
+ });
+ /**
+ * The amount of panning between left and right.
+ * 0 = always center. 1 = full range between left and right.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.depth = this._lfo.amplitude;
+ /**
+ * the panner node which does the panning
+ * @type {Tone.Panner}
+ * @private
+ */
+ this._panner = new Tone.Panner();
+ /**
+ * How fast the panner modulates between left and right.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._lfo.frequency;
+ //connections
+ this.connectEffect(this._panner);
+ this._lfo.connect(this._panner.pan);
+ this.type = options.type;
+ this._readOnly([
+ 'depth',
+ 'frequency'
+ ]);
+ };
+ //extend Effect
+ Tone.extend(Tone.AutoPanner, Tone.Effect);
+ /**
+ * defaults
+ * @static
+ * @type {Object}
+ */
+ Tone.AutoPanner.defaults = {
+ 'frequency': 1,
+ 'type': 'sine',
+ 'depth': 1
+ };
+ /**
+ * Start the effect.
+ * @param {Time} [time=now] When the LFO will start.
+ * @returns {Tone.AutoPanner} this
+ */
+ Tone.AutoPanner.prototype.start = function (time) {
+ this._lfo.start(time);
+ return this;
+ };
+ /**
+ * Stop the effect.
+ * @param {Time} [time=now] When the LFO will stop.
+ * @returns {Tone.AutoPanner} this
+ */
+ Tone.AutoPanner.prototype.stop = function (time) {
+ this._lfo.stop(time);
+ return this;
+ };
+ /**
+ * Sync the panner to the transport.
+ * @param {Time} [delay=0] Delay time before starting the effect after the
+ * Transport has started.
+ * @returns {Tone.AutoPanner} this
+ */
+ Tone.AutoPanner.prototype.sync = function (delay) {
+ this._lfo.sync(delay);
+ return this;
+ };
+ /**
+ * Unsync the panner from the transport
+ * @returns {Tone.AutoPanner} this
+ */
+ Tone.AutoPanner.prototype.unsync = function () {
+ this._lfo.unsync();
+ return this;
+ };
+ /**
+ * Type of oscillator attached to the AutoFilter.
+ * Possible values: "sine", "square", "triangle", "sawtooth".
+ * @memberOf Tone.AutoFilter#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.AutoPanner.prototype, 'type', {
+ get: function () {
+ return this._lfo.type;
+ },
+ set: function (type) {
+ this._lfo.type = type;
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.AutoPanner} this
+ */
+ Tone.AutoPanner.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._lfo.dispose();
+ this._lfo = null;
+ this._panner.dispose();
+ this._panner = null;
+ this._writable([
+ 'depth',
+ 'frequency'
+ ]);
+ this.frequency = null;
+ this.depth = null;
+ return this;
+ };
+ return Tone.AutoPanner;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.AutoWah connects a Tone.Follower to a bandpass filter (Tone.Filter).
+ * The frequency of the filter is adjusted proportionally to the
+ * incoming signal's amplitude. Inspiration from [Tuna.js](https://github.com/Dinahmoe/tuna).
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ * @param {Frequency|Object} [baseFrequency] The frequency the filter is set
+ * to at the low point of the wah
+ * @param {Positive} [octaves] The number of octaves above the baseFrequency
+ * the filter will sweep to when fully open
+ * @param {Decibels} [sensitivity] The decibel threshold sensitivity for
+ * the incoming signal. Normal range of -40 to 0.
+ * @example
+ * var autoWah = new Tone.AutoWah(50, 6, -30).toMaster();
+ * //initialize the synth and connect to autowah
+ * var synth = new Synth.connect(autoWah);
+ * //Q value influences the effect of the wah - default is 2
+ * autoWah.Q.value = 6;
+ * //more audible on higher notes
+ * synth.triggerAttackRelease("C4", "8n")
+ */
+ Tone.AutoWah = function () {
+ var options = this.optionsObject(arguments, [
+ 'baseFrequency',
+ 'octaves',
+ 'sensitivity'
+ ], Tone.AutoWah.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * The envelope follower. Set the attack/release
+ * timing to adjust how the envelope is followed.
+ * @type {Tone.Follower}
+ * @private
+ */
+ this.follower = new Tone.Follower(options.follower);
+ /**
+ * scales the follower value to the frequency domain
+ * @type {Tone}
+ * @private
+ */
+ this._sweepRange = new Tone.ScaleExp(0, 1, 0.5);
+ /**
+ * @type {number}
+ * @private
+ */
+ this._baseFrequency = options.baseFrequency;
+ /**
+ * @type {number}
+ * @private
+ */
+ this._octaves = options.octaves;
+ /**
+ * the input gain to adjust the sensitivity
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._inputBoost = new Tone.Gain();
+ /**
+ * @type {BiquadFilterNode}
+ * @private
+ */
+ this._bandpass = new Tone.Filter({
+ 'rolloff': -48,
+ 'frequency': 0,
+ 'Q': options.Q
+ });
+ /**
+ * @type {Tone.Filter}
+ * @private
+ */
+ this._peaking = new Tone.Filter(0, 'peaking');
+ this._peaking.gain.value = options.gain;
+ /**
+ * The gain of the filter.
+ * @type {Number}
+ * @signal
+ */
+ this.gain = this._peaking.gain;
+ /**
+ * The quality of the filter.
+ * @type {Positive}
+ * @signal
+ */
+ this.Q = this._bandpass.Q;
+ //the control signal path
+ this.effectSend.chain(this._inputBoost, this.follower, this._sweepRange);
+ this._sweepRange.connect(this._bandpass.frequency);
+ this._sweepRange.connect(this._peaking.frequency);
+ //the filtered path
+ this.effectSend.chain(this._bandpass, this._peaking, this.effectReturn);
+ //set the initial value
+ this._setSweepRange();
+ this.sensitivity = options.sensitivity;
+ this._readOnly([
+ 'gain',
+ 'Q'
+ ]);
+ };
+ Tone.extend(Tone.AutoWah, Tone.Effect);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.AutoWah.defaults = {
+ 'baseFrequency': 100,
+ 'octaves': 6,
+ 'sensitivity': 0,
+ 'Q': 2,
+ 'gain': 2,
+ 'follower': {
+ 'attack': 0.3,
+ 'release': 0.5
+ }
+ };
+ /**
+ * The number of octaves that the filter will sweep above the
+ * baseFrequency.
+ * @memberOf Tone.AutoWah#
+ * @type {Number}
+ * @name octaves
+ */
+ Object.defineProperty(Tone.AutoWah.prototype, 'octaves', {
+ get: function () {
+ return this._octaves;
+ },
+ set: function (octaves) {
+ this._octaves = octaves;
+ this._setSweepRange();
+ }
+ });
+ /**
+ * The base frequency from which the sweep will start from.
+ * @memberOf Tone.AutoWah#
+ * @type {Frequency}
+ * @name baseFrequency
+ */
+ Object.defineProperty(Tone.AutoWah.prototype, 'baseFrequency', {
+ get: function () {
+ return this._baseFrequency;
+ },
+ set: function (baseFreq) {
+ this._baseFrequency = baseFreq;
+ this._setSweepRange();
+ }
+ });
+ /**
+ * The sensitivity to control how responsive to the input signal the filter is.
+ * @memberOf Tone.AutoWah#
+ * @type {Decibels}
+ * @name sensitivity
+ */
+ Object.defineProperty(Tone.AutoWah.prototype, 'sensitivity', {
+ get: function () {
+ return this.gainToDb(1 / this._inputBoost.gain.value);
+ },
+ set: function (sensitivy) {
+ this._inputBoost.gain.value = 1 / this.dbToGain(sensitivy);
+ }
+ });
+ /**
+ * sets the sweep range of the scaler
+ * @private
+ */
+ Tone.AutoWah.prototype._setSweepRange = function () {
+ this._sweepRange.min = this._baseFrequency;
+ this._sweepRange.max = Math.min(this._baseFrequency * Math.pow(2, this._octaves), this.context.sampleRate / 2);
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.AutoWah} this
+ */
+ Tone.AutoWah.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this.follower.dispose();
+ this.follower = null;
+ this._sweepRange.dispose();
+ this._sweepRange = null;
+ this._bandpass.dispose();
+ this._bandpass = null;
+ this._peaking.dispose();
+ this._peaking = null;
+ this._inputBoost.dispose();
+ this._inputBoost = null;
+ this._writable([
+ 'gain',
+ 'Q'
+ ]);
+ this.gain = null;
+ this.Q = null;
+ return this;
+ };
+ return Tone.AutoWah;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Bitcrusher downsamples the incoming signal to a different bitdepth.
+ * Lowering the bitdepth of the signal creates distortion. Read more about Bitcrushing
+ * on [Wikipedia](https://en.wikipedia.org/wiki/Bitcrusher).
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ * @param {Number} bits The number of bits to downsample the signal. Nominal range
+ * of 1 to 8.
+ * @example
+ * //initialize crusher and route a synth through it
+ * var crusher = new Tone.BitCrusher(4).toMaster();
+ * var synth = new Tone.MonoSynth().connect(crusher);
+ */
+ Tone.BitCrusher = function () {
+ var options = this.optionsObject(arguments, ['bits'], Tone.BitCrusher.defaults);
+ Tone.Effect.call(this, options);
+ var invStepSize = 1 / Math.pow(2, options.bits - 1);
+ /**
+ * Subtract the input signal and the modulus of the input signal
+ * @type {Tone.Subtract}
+ * @private
+ */
+ this._subtract = new Tone.Subtract();
+ /**
+ * The mod function
+ * @type {Tone.Modulo}
+ * @private
+ */
+ this._modulo = new Tone.Modulo(invStepSize);
+ /**
+ * keeps track of the bits
+ * @type {number}
+ * @private
+ */
+ this._bits = options.bits;
+ //connect it up
+ this.effectSend.fan(this._subtract, this._modulo);
+ this._modulo.connect(this._subtract, 0, 1);
+ this._subtract.connect(this.effectReturn);
+ };
+ Tone.extend(Tone.BitCrusher, Tone.Effect);
+ /**
+ * the default values
+ * @static
+ * @type {Object}
+ */
+ Tone.BitCrusher.defaults = { 'bits': 4 };
+ /**
+ * The bit depth of the effect. Nominal range of 1-8.
+ * @memberOf Tone.BitCrusher#
+ * @type {number}
+ * @name bits
+ */
+ Object.defineProperty(Tone.BitCrusher.prototype, 'bits', {
+ get: function () {
+ return this._bits;
+ },
+ set: function (bits) {
+ this._bits = bits;
+ var invStepSize = 1 / Math.pow(2, bits - 1);
+ this._modulo.value = invStepSize;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.BitCrusher} this
+ */
+ Tone.BitCrusher.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._subtract.dispose();
+ this._subtract = null;
+ this._modulo.dispose();
+ this._modulo = null;
+ return this;
+ };
+ return Tone.BitCrusher;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.ChebyShev is a Chebyshev waveshaper, an effect which is good
+ * for making different types of distortion sounds.
+ * Note that odd orders sound very different from even ones,
+ * and order = 1 is no change.
+ * Read more at [music.columbia.edu](http://music.columbia.edu/cmc/musicandcomputers/chapter4/04_06.php).
+ *
+ * @extends {Tone.Effect}
+ * @constructor
+ * @param {Positive|Object} [order] The order of the chebyshev polynomial. Normal range between 1-100.
+ * @example
+ * //create a new cheby
+ * var cheby = new Tone.Chebyshev(50);
+ * //create a monosynth connected to our cheby
+ * synth = new Tone.MonoSynth().connect(cheby);
+ */
+ Tone.Chebyshev = function () {
+ var options = this.optionsObject(arguments, ['order'], Tone.Chebyshev.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * @type {WaveShaperNode}
+ * @private
+ */
+ this._shaper = new Tone.WaveShaper(4096);
+ /**
+ * holds onto the order of the filter
+ * @type {number}
+ * @private
+ */
+ this._order = options.order;
+ this.connectEffect(this._shaper);
+ this.order = options.order;
+ this.oversample = options.oversample;
+ };
+ Tone.extend(Tone.Chebyshev, Tone.Effect);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Chebyshev.defaults = {
+ 'order': 1,
+ 'oversample': 'none'
+ };
+ /**
+ * get the coefficient for that degree
+ * @param {number} x the x value
+ * @param {number} degree
+ * @param {Object} memo memoize the computed value.
+ * this speeds up computation greatly.
+ * @return {number} the coefficient
+ * @private
+ */
+ Tone.Chebyshev.prototype._getCoefficient = function (x, degree, memo) {
+ if (memo.hasOwnProperty(degree)) {
+ return memo[degree];
+ } else if (degree === 0) {
+ memo[degree] = 0;
+ } else if (degree === 1) {
+ memo[degree] = x;
+ } else {
+ memo[degree] = 2 * x * this._getCoefficient(x, degree - 1, memo) - this._getCoefficient(x, degree - 2, memo);
+ }
+ return memo[degree];
+ };
+ /**
+ * The order of the Chebyshev polynomial which creates
+ * the equation which is applied to the incoming
+ * signal through a Tone.WaveShaper. The equations
+ * are in the form:<br>
+ * order 2: 2x^2 + 1<br>
+ * order 3: 4x^3 + 3x <br>
+ * @memberOf Tone.Chebyshev#
+ * @type {Positive}
+ * @name order
+ */
+ Object.defineProperty(Tone.Chebyshev.prototype, 'order', {
+ get: function () {
+ return this._order;
+ },
+ set: function (order) {
+ this._order = order;
+ var curve = new Array(4096);
+ var len = curve.length;
+ for (var i = 0; i < len; ++i) {
+ var x = i * 2 / len - 1;
+ if (x === 0) {
+ //should output 0 when input is 0
+ curve[i] = 0;
+ } else {
+ curve[i] = this._getCoefficient(x, order, {});
+ }
+ }
+ this._shaper.curve = curve;
+ }
+ });
+ /**
+ * The oversampling of the effect. Can either be "none", "2x" or "4x".
+ * @memberOf Tone.Chebyshev#
+ * @type {string}
+ * @name oversample
+ */
+ Object.defineProperty(Tone.Chebyshev.prototype, 'oversample', {
+ get: function () {
+ return this._shaper.oversample;
+ },
+ set: function (oversampling) {
+ this._shaper.oversample = oversampling;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Chebyshev} this
+ */
+ Tone.Chebyshev.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._shaper.dispose();
+ this._shaper = null;
+ return this;
+ };
+ return Tone.Chebyshev;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Base class for Stereo effects. Provides effectSendL/R and effectReturnL/R.
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ */
+ Tone.StereoEffect = function () {
+ this.createInsOuts(1, 1);
+ //get the defaults
+ var options = this.optionsObject(arguments, ['wet'], Tone.Effect.defaults);
+ /**
+ * the drywet knob to control the amount of effect
+ * @type {Tone.CrossFade}
+ * @private
+ */
+ this._dryWet = new Tone.CrossFade(options.wet);
+ /**
+ * The wet control, i.e. how much of the effected
+ * will pass through to the output.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.wet = this._dryWet.fade;
+ /**
+ * then split it
+ * @type {Tone.Split}
+ * @private
+ */
+ this._split = new Tone.Split();
+ /**
+ * the effects send LEFT
+ * @type {GainNode}
+ * @private
+ */
+ this.effectSendL = this._split.left;
+ /**
+ * the effects send RIGHT
+ * @type {GainNode}
+ * @private
+ */
+ this.effectSendR = this._split.right;
+ /**
+ * the stereo effect merger
+ * @type {Tone.Merge}
+ * @private
+ */
+ this._merge = new Tone.Merge();
+ /**
+ * the effect return LEFT
+ * @type {GainNode}
+ * @private
+ */
+ this.effectReturnL = this._merge.left;
+ /**
+ * the effect return RIGHT
+ * @type {GainNode}
+ * @private
+ */
+ this.effectReturnR = this._merge.right;
+ //connections
+ this.input.connect(this._split);
+ //dry wet connections
+ this.input.connect(this._dryWet, 0, 0);
+ this._merge.connect(this._dryWet, 0, 1);
+ this._dryWet.connect(this.output);
+ this._readOnly(['wet']);
+ };
+ Tone.extend(Tone.StereoEffect, Tone.Effect);
+ /**
+ * Clean up.
+ * @returns {Tone.StereoEffect} this
+ */
+ Tone.StereoEffect.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._dryWet.dispose();
+ this._dryWet = null;
+ this._split.dispose();
+ this._split = null;
+ this._merge.dispose();
+ this._merge = null;
+ this.effectSendL = null;
+ this.effectSendR = null;
+ this.effectReturnL = null;
+ this.effectReturnR = null;
+ this._writable(['wet']);
+ this.wet = null;
+ return this;
+ };
+ return Tone.StereoEffect;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.FeedbackEffect provides a loop between an
+ * audio source and its own output. This is a base-class
+ * for feedback effects.
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ * @param {NormalRange|Object} [feedback] The initial feedback value.
+ */
+ Tone.FeedbackEffect = function () {
+ var options = this.optionsObject(arguments, ['feedback']);
+ options = this.defaultArg(options, Tone.FeedbackEffect.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * the gain which controls the feedback
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._feedbackGain = new Tone.Gain(options.feedback, Tone.Type.NormalRange);
+ /**
+ * The amount of signal which is fed back into the effect input.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.feedback = this._feedbackGain.gain;
+ //the feedback loop
+ this.effectReturn.chain(this._feedbackGain, this.effectSend);
+ this._readOnly(['feedback']);
+ };
+ Tone.extend(Tone.FeedbackEffect, Tone.Effect);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.FeedbackEffect.defaults = { 'feedback': 0.125 };
+ /**
+ * Clean up.
+ * @returns {Tone.FeedbackEffect} this
+ */
+ Tone.FeedbackEffect.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._writable(['feedback']);
+ this._feedbackGain.dispose();
+ this._feedbackGain = null;
+ this.feedback = null;
+ return this;
+ };
+ return Tone.FeedbackEffect;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Just like a stereo feedback effect, but the feedback is routed from left to right
+ * and right to left instead of on the same channel.
+ *
+ * @constructor
+ * @extends {Tone.FeedbackEffect}
+ */
+ Tone.StereoXFeedbackEffect = function () {
+ var options = this.optionsObject(arguments, ['feedback'], Tone.FeedbackEffect.defaults);
+ Tone.StereoEffect.call(this, options);
+ /**
+ * The amount of feedback from the output
+ * back into the input of the effect (routed
+ * across left and right channels).
+ * @type {NormalRange}
+ * @signal
+ */
+ this.feedback = new Tone.Signal(options.feedback, Tone.Type.NormalRange);
+ /**
+ * the left side feeback
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._feedbackLR = new Tone.Gain();
+ /**
+ * the right side feeback
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._feedbackRL = new Tone.Gain();
+ //connect it up
+ this.effectReturnL.chain(this._feedbackLR, this.effectSendR);
+ this.effectReturnR.chain(this._feedbackRL, this.effectSendL);
+ this.feedback.fan(this._feedbackLR.gain, this._feedbackRL.gain);
+ this._readOnly(['feedback']);
+ };
+ Tone.extend(Tone.StereoXFeedbackEffect, Tone.FeedbackEffect);
+ /**
+ * clean up
+ * @returns {Tone.StereoXFeedbackEffect} this
+ */
+ Tone.StereoXFeedbackEffect.prototype.dispose = function () {
+ Tone.StereoEffect.prototype.dispose.call(this);
+ this._writable(['feedback']);
+ this.feedback.dispose();
+ this.feedback = null;
+ this._feedbackLR.dispose();
+ this._feedbackLR = null;
+ this._feedbackRL.dispose();
+ this._feedbackRL = null;
+ return this;
+ };
+ return Tone.StereoXFeedbackEffect;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Chorus is a stereo chorus effect with feedback composed of
+ * a left and right delay with a Tone.LFO applied to the delayTime of each channel.
+ * Inspiration from [Tuna.js](https://github.com/Dinahmoe/tuna/blob/master/tuna.js).
+ * Read more on the chorus effect on [SoundOnSound](http://www.soundonsound.com/sos/jun04/articles/synthsecrets.htm).
+ *
+ * @constructor
+ * @extends {Tone.StereoXFeedbackEffect}
+ * @param {Frequency|Object} [frequency] The frequency of the LFO.
+ * @param {Milliseconds} [delayTime] The delay of the chorus effect in ms.
+ * @param {NormalRange} [depth] The depth of the chorus.
+ * @example
+ * var chorus = new Tone.Chorus(4, 2.5, 0.5);
+ * var synth = new Tone.PolySynth(4, Tone.MonoSynth).connect(chorus);
+ * synth.triggerAttackRelease(["C3","E3","G3"], "8n");
+ */
+ Tone.Chorus = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'delayTime',
+ 'depth'
+ ], Tone.Chorus.defaults);
+ Tone.StereoXFeedbackEffect.call(this, options);
+ /**
+ * the depth of the chorus
+ * @type {number}
+ * @private
+ */
+ this._depth = options.depth;
+ /**
+ * the delayTime
+ * @type {number}
+ * @private
+ */
+ this._delayTime = options.delayTime / 1000;
+ /**
+ * the lfo which controls the delayTime
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoL = new Tone.LFO({
+ 'frequency': options.frequency,
+ 'min': 0,
+ 'max': 1
+ });
+ /**
+ * another LFO for the right side with a 180 degree phase diff
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoR = new Tone.LFO({
+ 'frequency': options.frequency,
+ 'min': 0,
+ 'max': 1,
+ 'phase': 180
+ });
+ /**
+ * delay for left
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._delayNodeL = new Tone.Delay();
+ /**
+ * delay for right
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._delayNodeR = new Tone.Delay();
+ /**
+ * The frequency of the LFO which modulates the delayTime.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._lfoL.frequency;
+ //connections
+ this.effectSendL.chain(this._delayNodeL, this.effectReturnL);
+ this.effectSendR.chain(this._delayNodeR, this.effectReturnR);
+ //and pass through to make the detune apparent
+ this.effectSendL.connect(this.effectReturnL);
+ this.effectSendR.connect(this.effectReturnR);
+ //lfo setup
+ this._lfoL.connect(this._delayNodeL.delayTime);
+ this._lfoR.connect(this._delayNodeR.delayTime);
+ //start the lfo
+ this._lfoL.start();
+ this._lfoR.start();
+ //have one LFO frequency control the other
+ this._lfoL.frequency.connect(this._lfoR.frequency);
+ //set the initial values
+ this.depth = this._depth;
+ this.frequency.value = options.frequency;
+ this.type = options.type;
+ this._readOnly(['frequency']);
+ this.spread = options.spread;
+ };
+ Tone.extend(Tone.Chorus, Tone.StereoXFeedbackEffect);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.Chorus.defaults = {
+ 'frequency': 1.5,
+ 'delayTime': 3.5,
+ 'depth': 0.7,
+ 'feedback': 0.1,
+ 'type': 'sine',
+ 'spread': 180
+ };
+ /**
+ * The depth of the effect. A depth of 1 makes the delayTime
+ * modulate between 0 and 2*delayTime (centered around the delayTime).
+ * @memberOf Tone.Chorus#
+ * @type {NormalRange}
+ * @name depth
+ */
+ Object.defineProperty(Tone.Chorus.prototype, 'depth', {
+ get: function () {
+ return this._depth;
+ },
+ set: function (depth) {
+ this._depth = depth;
+ var deviation = this._delayTime * depth;
+ this._lfoL.min = Math.max(this._delayTime - deviation, 0);
+ this._lfoL.max = this._delayTime + deviation;
+ this._lfoR.min = Math.max(this._delayTime - deviation, 0);
+ this._lfoR.max = this._delayTime + deviation;
+ }
+ });
+ /**
+ * The delayTime in milliseconds of the chorus. A larger delayTime
+ * will give a more pronounced effect. Nominal range a delayTime
+ * is between 2 and 20ms.
+ * @memberOf Tone.Chorus#
+ * @type {Milliseconds}
+ * @name delayTime
+ */
+ Object.defineProperty(Tone.Chorus.prototype, 'delayTime', {
+ get: function () {
+ return this._delayTime * 1000;
+ },
+ set: function (delayTime) {
+ this._delayTime = delayTime / 1000;
+ this.depth = this._depth;
+ }
+ });
+ /**
+ * The oscillator type of the LFO.
+ * @memberOf Tone.Chorus#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.Chorus.prototype, 'type', {
+ get: function () {
+ return this._lfoL.type;
+ },
+ set: function (type) {
+ this._lfoL.type = type;
+ this._lfoR.type = type;
+ }
+ });
+ /**
+ * Amount of stereo spread. When set to 0, both LFO's will be panned centrally.
+ * When set to 180, LFO's will be panned hard left and right respectively.
+ * @memberOf Tone.Chorus#
+ * @type {Degrees}
+ * @name spread
+ */
+ Object.defineProperty(Tone.Chorus.prototype, 'spread', {
+ get: function () {
+ return this._lfoR.phase - this._lfoL.phase; //180
+ },
+ set: function (spread) {
+ this._lfoL.phase = 90 - spread / 2;
+ this._lfoR.phase = spread / 2 + 90;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Chorus} this
+ */
+ Tone.Chorus.prototype.dispose = function () {
+ Tone.StereoXFeedbackEffect.prototype.dispose.call(this);
+ this._lfoL.dispose();
+ this._lfoL = null;
+ this._lfoR.dispose();
+ this._lfoR = null;
+ this._delayNodeL.dispose();
+ this._delayNodeL = null;
+ this._delayNodeR.dispose();
+ this._delayNodeR = null;
+ this._writable('frequency');
+ this.frequency = null;
+ return this;
+ };
+ return Tone.Chorus;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Convolver is a wrapper around the Native Web Audio
+ * [ConvolverNode](http://webaudio.github.io/web-audio-api/#the-convolvernode-interface).
+ * Convolution is useful for reverb and filter emulation. Read more about convolution reverb on
+ * [Wikipedia](https://en.wikipedia.org/wiki/Convolution_reverb).
+ *
+ * @constructor
+ * @extends {Tone.Effect}
+ * @param {string|Tone.Buffer|Object} [url] The URL of the impulse response or the Tone.Buffer
+ * contianing the impulse response.
+ * @param {Function} onload The callback to invoke when the url is loaded.
+ * @example
+ * //initializing the convolver with an impulse response
+ * var convolver = new Tone.Convolver("./path/to/ir.wav").toMaster();
+ */
+ Tone.Convolver = function () {
+ var options = this.optionsObject(arguments, [
+ 'url',
+ 'onload'
+ ], Tone.Convolver.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * convolver node
+ * @type {ConvolverNode}
+ * @private
+ */
+ this._convolver = this.context.createConvolver();
+ /**
+ * the convolution buffer
+ * @type {Tone.Buffer}
+ * @private
+ */
+ this._buffer = new Tone.Buffer();
+ if (this.isString(options.url)) {
+ this._buffer.load(options.url, function (buffer) {
+ this.buffer = buffer;
+ options.onload();
+ }.bind(this));
+ } else if (options.url) {
+ this.buffer = options.url;
+ options.onload();
+ }
+ this.connectEffect(this._convolver);
+ };
+ Tone.extend(Tone.Convolver, Tone.Effect);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Convolver.defaults = { 'onload': Tone.noOp };
+ /**
+ * The convolver's buffer
+ * @memberOf Tone.Convolver#
+ * @type {AudioBuffer}
+ * @name buffer
+ */
+ Object.defineProperty(Tone.Convolver.prototype, 'buffer', {
+ get: function () {
+ return this._buffer.get();
+ },
+ set: function (buffer) {
+ this._buffer.set(buffer);
+ this._convolver.buffer = this._buffer.get();
+ }
+ });
+ /**
+ * Load an impulse response url as an audio buffer.
+ * Decodes the audio asynchronously and invokes
+ * the callback once the audio buffer loads.
+ * @param {string} url The url of the buffer to load.
+ * filetype support depends on the
+ * browser.
+ * @param {function=} callback
+ * @returns {Promise}
+ */
+ Tone.Convolver.prototype.load = function (url, callback) {
+ return this._buffer.load(url, function (buff) {
+ this.buffer = buff;
+ if (callback) {
+ callback();
+ }
+ }.bind(this));
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Convolver} this
+ */
+ Tone.Convolver.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._convolver.disconnect();
+ this._convolver = null;
+ this._buffer.dispose();
+ this._buffer = null;
+ return this;
+ };
+ return Tone.Convolver;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Distortion is a simple distortion effect using Tone.WaveShaper.
+ * Algorithm from [a stackoverflow answer](http://stackoverflow.com/a/22313408).
+ *
+ * @extends {Tone.Effect}
+ * @constructor
+ * @param {Number|Object} [distortion] The amount of distortion (nominal range of 0-1)
+ * @example
+ * var dist = new Tone.Distortion(0.8).toMaster();
+ * var fm = new Tone.SimpleFM().connect(dist);
+ * //this sounds good on bass notes
+ * fm.triggerAttackRelease("A1", "8n");
+ */
+ Tone.Distortion = function () {
+ var options = this.optionsObject(arguments, ['distortion'], Tone.Distortion.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * @type {Tone.WaveShaper}
+ * @private
+ */
+ this._shaper = new Tone.WaveShaper(4096);
+ /**
+ * holds the distortion amount
+ * @type {number}
+ * @private
+ */
+ this._distortion = options.distortion;
+ this.connectEffect(this._shaper);
+ this.distortion = options.distortion;
+ this.oversample = options.oversample;
+ };
+ Tone.extend(Tone.Distortion, Tone.Effect);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Distortion.defaults = {
+ 'distortion': 0.4,
+ 'oversample': 'none'
+ };
+ /**
+ * The amount of distortion.
+ * @memberOf Tone.Distortion#
+ * @type {NormalRange}
+ * @name distortion
+ */
+ Object.defineProperty(Tone.Distortion.prototype, 'distortion', {
+ get: function () {
+ return this._distortion;
+ },
+ set: function (amount) {
+ this._distortion = amount;
+ var k = amount * 100;
+ var deg = Math.PI / 180;
+ this._shaper.setMap(function (x) {
+ if (Math.abs(x) < 0.001) {
+ //should output 0 when input is 0
+ return 0;
+ } else {
+ return (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
+ }
+ });
+ }
+ });
+ /**
+ * The oversampling of the effect. Can either be "none", "2x" or "4x".
+ * @memberOf Tone.Distortion#
+ * @type {string}
+ * @name oversample
+ */
+ Object.defineProperty(Tone.Distortion.prototype, 'oversample', {
+ get: function () {
+ return this._shaper.oversample;
+ },
+ set: function (oversampling) {
+ this._shaper.oversample = oversampling;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Distortion} this
+ */
+ Tone.Distortion.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._shaper.dispose();
+ this._shaper = null;
+ return this;
+ };
+ return Tone.Distortion;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.FeedbackDelay is a DelayNode in which part of output
+ * signal is fed back into the delay.
+ *
+ * @constructor
+ * @extends {Tone.FeedbackEffect}
+ * @param {Time|Object} [delayTime] The delay applied to the incoming signal.
+ * @param {NormalRange=} feedback The amount of the effected signal which
+ * is fed back through the delay.
+ * @example
+ * var feedbackDelay = new Tone.FeedbackDelay("8n", 0.5).toMaster();
+ * var tom = new Tone.DrumSynth({
+ * "octaves" : 4,
+ * "pitchDecay" : 0.1
+ * }).connect(feedbackDelay);
+ * tom.triggerAttackRelease("A2","32n");
+ */
+ Tone.FeedbackDelay = function () {
+ var options = this.optionsObject(arguments, [
+ 'delayTime',
+ 'feedback'
+ ], Tone.FeedbackDelay.defaults);
+ Tone.FeedbackEffect.call(this, options);
+ /**
+ * the delay node
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._delayNode = new Tone.Delay(options.delayTime);
+ /**
+ * The delayTime of the DelayNode.
+ * @type {Time}
+ * @signal
+ */
+ this.delayTime = this._delayNode.delayTime;
+ // connect it up
+ this.connectEffect(this._delayNode);
+ this._readOnly(['delayTime']);
+ };
+ Tone.extend(Tone.FeedbackDelay, Tone.FeedbackEffect);
+ /**
+ * The default values.
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.FeedbackDelay.defaults = { 'delayTime': 0.25 };
+ /**
+ * clean up
+ * @returns {Tone.FeedbackDelay} this
+ */
+ Tone.FeedbackDelay.prototype.dispose = function () {
+ Tone.FeedbackEffect.prototype.dispose.call(this);
+ this._delayNode.dispose();
+ this._delayNode = null;
+ this._writable(['delayTime']);
+ this.delayTime = null;
+ return this;
+ };
+ return Tone.FeedbackDelay;
+ });
+ Module(function (Tone) {
+
+ /**
+ * an array of comb filter delay values from Freeverb implementation
+ * @static
+ * @private
+ * @type {Array}
+ */
+ var combFilterTunings = [
+ 1557 / 44100,
+ 1617 / 44100,
+ 1491 / 44100,
+ 1422 / 44100,
+ 1277 / 44100,
+ 1356 / 44100,
+ 1188 / 44100,
+ 1116 / 44100
+ ];
+ /**
+ * an array of allpass filter frequency values from Freeverb implementation
+ * @private
+ * @static
+ * @type {Array}
+ */
+ var allpassFilterFrequencies = [
+ 225,
+ 556,
+ 441,
+ 341
+ ];
+ /**
+ * @class Tone.Freeverb is a reverb based on [Freeverb](https://ccrma.stanford.edu/~jos/pasp/Freeverb.html).
+ * Read more on reverb on [SoundOnSound](http://www.soundonsound.com/sos/may00/articles/reverb.htm).
+ *
+ * @extends {Tone.Effect}
+ * @constructor
+ * @param {NormalRange|Object} [roomSize] Correlated to the decay time.
+ * @param {Frequency} [dampening] The cutoff frequency of a lowpass filter as part
+ * of the reverb.
+ * @example
+ * var freeverb = new Tone.Freeverb().toMaster();
+ * freeverb.dampening.value = 1000;
+ * //routing synth through the reverb
+ * var synth = new Tone.AMSynth().connect(freeverb);
+ */
+ Tone.Freeverb = function () {
+ var options = this.optionsObject(arguments, [
+ 'roomSize',
+ 'dampening'
+ ], Tone.Freeverb.defaults);
+ Tone.StereoEffect.call(this, options);
+ /**
+ * The roomSize value between. A larger roomSize
+ * will result in a longer decay.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.roomSize = new Tone.Signal(options.roomSize, Tone.Type.NormalRange);
+ /**
+ * The amount of dampening of the reverberant signal.
+ * @type {Frequency}
+ * @signal
+ */
+ this.dampening = new Tone.Signal(options.dampening, Tone.Type.Frequency);
+ /**
+ * the comb filters
+ * @type {Array}
+ * @private
+ */
+ this._combFilters = [];
+ /**
+ * the allpass filters on the left
+ * @type {Array}
+ * @private
+ */
+ this._allpassFiltersL = [];
+ /**
+ * the allpass filters on the right
+ * @type {Array}
+ * @private
+ */
+ this._allpassFiltersR = [];
+ //make the allpass filters on the right
+ for (var l = 0; l < allpassFilterFrequencies.length; l++) {
+ var allpassL = this.context.createBiquadFilter();
+ allpassL.type = 'allpass';
+ allpassL.frequency.value = allpassFilterFrequencies[l];
+ this._allpassFiltersL.push(allpassL);
+ }
+ //make the allpass filters on the left
+ for (var r = 0; r < allpassFilterFrequencies.length; r++) {
+ var allpassR = this.context.createBiquadFilter();
+ allpassR.type = 'allpass';
+ allpassR.frequency.value = allpassFilterFrequencies[r];
+ this._allpassFiltersR.push(allpassR);
+ }
+ //make the comb filters
+ for (var c = 0; c < combFilterTunings.length; c++) {
+ var lfpf = new Tone.LowpassCombFilter(combFilterTunings[c]);
+ if (c < combFilterTunings.length / 2) {
+ this.effectSendL.chain(lfpf, this._allpassFiltersL[0]);
+ } else {
+ this.effectSendR.chain(lfpf, this._allpassFiltersR[0]);
+ }
+ this.roomSize.connect(lfpf.resonance);
+ this.dampening.connect(lfpf.dampening);
+ this._combFilters.push(lfpf);
+ }
+ //chain the allpass filters togetehr
+ this.connectSeries.apply(this, this._allpassFiltersL);
+ this.connectSeries.apply(this, this._allpassFiltersR);
+ this._allpassFiltersL[this._allpassFiltersL.length - 1].connect(this.effectReturnL);
+ this._allpassFiltersR[this._allpassFiltersR.length - 1].connect(this.effectReturnR);
+ this._readOnly([
+ 'roomSize',
+ 'dampening'
+ ]);
+ };
+ Tone.extend(Tone.Freeverb, Tone.StereoEffect);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.Freeverb.defaults = {
+ 'roomSize': 0.7,
+ 'dampening': 3000
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Freeverb} this
+ */
+ Tone.Freeverb.prototype.dispose = function () {
+ Tone.StereoEffect.prototype.dispose.call(this);
+ for (var al = 0; al < this._allpassFiltersL.length; al++) {
+ this._allpassFiltersL[al].disconnect();
+ this._allpassFiltersL[al] = null;
+ }
+ this._allpassFiltersL = null;
+ for (var ar = 0; ar < this._allpassFiltersR.length; ar++) {
+ this._allpassFiltersR[ar].disconnect();
+ this._allpassFiltersR[ar] = null;
+ }
+ this._allpassFiltersR = null;
+ for (var cf = 0; cf < this._combFilters.length; cf++) {
+ this._combFilters[cf].dispose();
+ this._combFilters[cf] = null;
+ }
+ this._combFilters = null;
+ this._writable([
+ 'roomSize',
+ 'dampening'
+ ]);
+ this.roomSize.dispose();
+ this.roomSize = null;
+ this.dampening.dispose();
+ this.dampening = null;
+ return this;
+ };
+ return Tone.Freeverb;
+ });
+ Module(function (Tone) {
+
+ /**
+ * an array of the comb filter delay time values
+ * @private
+ * @static
+ * @type {Array}
+ */
+ var combFilterDelayTimes = [
+ 1687 / 25000,
+ 1601 / 25000,
+ 2053 / 25000,
+ 2251 / 25000
+ ];
+ /**
+ * the resonances of each of the comb filters
+ * @private
+ * @static
+ * @type {Array}
+ */
+ var combFilterResonances = [
+ 0.773,
+ 0.802,
+ 0.753,
+ 0.733
+ ];
+ /**
+ * the allpass filter frequencies
+ * @private
+ * @static
+ * @type {Array}
+ */
+ var allpassFilterFreqs = [
+ 347,
+ 113,
+ 37
+ ];
+ /**
+ * @class Tone.JCReverb is a simple [Schroeder Reverberator](https://ccrma.stanford.edu/~jos/pasp/Schroeder_Reverberators.html)
+ * tuned by John Chowning in 1970.
+ * It is made up of three allpass filters and four Tone.FeedbackCombFilter.
+ *
+ *
+ * @extends {Tone.Effect}
+ * @constructor
+ * @param {NormalRange|Object} [roomSize] Coorelates to the decay time.
+ * @example
+ * var reverb = new Tone.JCReverb(0.4).connect(Tone.Master);
+ * var delay = new Tone.FeedbackDelay(0.5);
+ * //connecting the synth to reverb through delay
+ * var synth = new Tone.DuoSynth().chain(delay, reverb);
+ * synth.triggerAttackRelease("A4","8n");
+ */
+ Tone.JCReverb = function () {
+ var options = this.optionsObject(arguments, ['roomSize'], Tone.JCReverb.defaults);
+ Tone.StereoEffect.call(this, options);
+ /**
+ * room size control values between [0,1]
+ * @type {NormalRange}
+ * @signal
+ */
+ this.roomSize = new Tone.Signal(options.roomSize, Tone.Type.NormalRange);
+ /**
+ * scale the room size
+ * @type {Tone.Scale}
+ * @private
+ */
+ this._scaleRoomSize = new Tone.Scale(-0.733, 0.197);
+ /**
+ * a series of allpass filters
+ * @type {Array}
+ * @private
+ */
+ this._allpassFilters = [];
+ /**
+ * parallel feedback comb filters
+ * @type {Array}
+ * @private
+ */
+ this._feedbackCombFilters = [];
+ //make the allpass filters
+ for (var af = 0; af < allpassFilterFreqs.length; af++) {
+ var allpass = this.context.createBiquadFilter();
+ allpass.type = 'allpass';
+ allpass.frequency.value = allpassFilterFreqs[af];
+ this._allpassFilters.push(allpass);
+ }
+ //and the comb filters
+ for (var cf = 0; cf < combFilterDelayTimes.length; cf++) {
+ var fbcf = new Tone.FeedbackCombFilter(combFilterDelayTimes[cf], 0.1);
+ this._scaleRoomSize.connect(fbcf.resonance);
+ fbcf.resonance.value = combFilterResonances[cf];
+ this._allpassFilters[this._allpassFilters.length - 1].connect(fbcf);
+ if (cf < combFilterDelayTimes.length / 2) {
+ fbcf.connect(this.effectReturnL);
+ } else {
+ fbcf.connect(this.effectReturnR);
+ }
+ this._feedbackCombFilters.push(fbcf);
+ }
+ //chain the allpass filters together
+ this.roomSize.connect(this._scaleRoomSize);
+ this.connectSeries.apply(this, this._allpassFilters);
+ this.effectSendL.connect(this._allpassFilters[0]);
+ this.effectSendR.connect(this._allpassFilters[0]);
+ this._readOnly(['roomSize']);
+ };
+ Tone.extend(Tone.JCReverb, Tone.StereoEffect);
+ /**
+ * the default values
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.JCReverb.defaults = { 'roomSize': 0.5 };
+ /**
+ * Clean up.
+ * @returns {Tone.JCReverb} this
+ */
+ Tone.JCReverb.prototype.dispose = function () {
+ Tone.StereoEffect.prototype.dispose.call(this);
+ for (var apf = 0; apf < this._allpassFilters.length; apf++) {
+ this._allpassFilters[apf].disconnect();
+ this._allpassFilters[apf] = null;
+ }
+ this._allpassFilters = null;
+ for (var fbcf = 0; fbcf < this._feedbackCombFilters.length; fbcf++) {
+ this._feedbackCombFilters[fbcf].dispose();
+ this._feedbackCombFilters[fbcf] = null;
+ }
+ this._feedbackCombFilters = null;
+ this._writable(['roomSize']);
+ this.roomSize.dispose();
+ this.roomSize = null;
+ this._scaleRoomSize.dispose();
+ this._scaleRoomSize = null;
+ return this;
+ };
+ return Tone.JCReverb;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Mid/Side processing separates the the 'mid' signal
+ * (which comes out of both the left and the right channel)
+ * and the 'side' (which only comes out of the the side channels)
+ * and effects them separately before being recombined.
+ * Applies a Mid/Side seperation and recombination.
+ * Algorithm found in [kvraudio forums](http://www.kvraudio.com/forum/viewtopic.php?t=212587).
+ * <br><br>
+ * This is a base-class for Mid/Side Effects.
+ *
+ * @extends {Tone.Effect}
+ * @constructor
+ */
+ Tone.MidSideEffect = function () {
+ Tone.Effect.apply(this, arguments);
+ /**
+ * The mid/side split
+ * @type {Tone.MidSideSplit}
+ * @private
+ */
+ this._midSideSplit = new Tone.MidSideSplit();
+ /**
+ * The mid/side merge
+ * @type {Tone.MidSideMerge}
+ * @private
+ */
+ this._midSideMerge = new Tone.MidSideMerge();
+ /**
+ * The mid send. Connect to mid processing
+ * @type {Tone.Expr}
+ * @private
+ */
+ this.midSend = this._midSideSplit.mid;
+ /**
+ * The side send. Connect to side processing
+ * @type {Tone.Expr}
+ * @private
+ */
+ this.sideSend = this._midSideSplit.side;
+ /**
+ * The mid return connection
+ * @type {GainNode}
+ * @private
+ */
+ this.midReturn = this._midSideMerge.mid;
+ /**
+ * The side return connection
+ * @type {GainNode}
+ * @private
+ */
+ this.sideReturn = this._midSideMerge.side;
+ //the connections
+ this.effectSend.connect(this._midSideSplit);
+ this._midSideMerge.connect(this.effectReturn);
+ };
+ Tone.extend(Tone.MidSideEffect, Tone.Effect);
+ /**
+ * Clean up.
+ * @returns {Tone.MidSideEffect} this
+ */
+ Tone.MidSideEffect.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._midSideSplit.dispose();
+ this._midSideSplit = null;
+ this._midSideMerge.dispose();
+ this._midSideMerge = null;
+ this.midSend = null;
+ this.sideSend = null;
+ this.midReturn = null;
+ this.sideReturn = null;
+ return this;
+ };
+ return Tone.MidSideEffect;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Phaser is a phaser effect. Phasers work by changing the phase
+ * of different frequency components of an incoming signal. Read more on
+ * [Wikipedia](https://en.wikipedia.org/wiki/Phaser_(effect)).
+ * Inspiration for this phaser comes from [Tuna.js](https://github.com/Dinahmoe/tuna/).
+ *
+ * @extends {Tone.StereoEffect}
+ * @constructor
+ * @param {Frequency|Object} [frequency] The speed of the phasing.
+ * @param {number} [octaves] The octaves of the effect.
+ * @param {Frequency} [baseFrequency] The base frequency of the filters.
+ * @example
+ * var phaser = new Tone.Phaser({
+ * "frequency" : 15,
+ * "octaves" : 5,
+ * "baseFrequency" : 1000
+ * }).toMaster();
+ * var synth = new Tone.FMSynth().connect(phaser);
+ * synth.triggerAttackRelease("E3", "2n");
+ */
+ Tone.Phaser = function () {
+ //set the defaults
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'octaves',
+ 'baseFrequency'
+ ], Tone.Phaser.defaults);
+ Tone.StereoEffect.call(this, options);
+ /**
+ * the lfo which controls the frequency on the left side
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoL = new Tone.LFO(options.frequency, 0, 1);
+ /**
+ * the lfo which controls the frequency on the right side
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoR = new Tone.LFO(options.frequency, 0, 1);
+ this._lfoR.phase = 180;
+ /**
+ * the base modulation frequency
+ * @type {number}
+ * @private
+ */
+ this._baseFrequency = options.baseFrequency;
+ /**
+ * the octaves of the phasing
+ * @type {number}
+ * @private
+ */
+ this._octaves = options.octaves;
+ /**
+ * The quality factor of the filters
+ * @type {Positive}
+ * @signal
+ */
+ this.Q = new Tone.Signal(options.Q, Tone.Type.Positive);
+ /**
+ * the array of filters for the left side
+ * @type {Array}
+ * @private
+ */
+ this._filtersL = this._makeFilters(options.stages, this._lfoL, this.Q);
+ /**
+ * the array of filters for the left side
+ * @type {Array}
+ * @private
+ */
+ this._filtersR = this._makeFilters(options.stages, this._lfoR, this.Q);
+ /**
+ * the frequency of the effect
+ * @type {Tone.Signal}
+ */
+ this.frequency = this._lfoL.frequency;
+ this.frequency.value = options.frequency;
+ //connect them up
+ this.effectSendL.connect(this._filtersL[0]);
+ this.effectSendR.connect(this._filtersR[0]);
+ this._filtersL[options.stages - 1].connect(this.effectReturnL);
+ this._filtersR[options.stages - 1].connect(this.effectReturnR);
+ //control the frequency with one LFO
+ this._lfoL.frequency.connect(this._lfoR.frequency);
+ //set the options
+ this.baseFrequency = options.baseFrequency;
+ this.octaves = options.octaves;
+ //start the lfo
+ this._lfoL.start();
+ this._lfoR.start();
+ this._readOnly([
+ 'frequency',
+ 'Q'
+ ]);
+ };
+ Tone.extend(Tone.Phaser, Tone.StereoEffect);
+ /**
+ * defaults
+ * @static
+ * @type {object}
+ */
+ Tone.Phaser.defaults = {
+ 'frequency': 0.5,
+ 'octaves': 3,
+ 'stages': 10,
+ 'Q': 10,
+ 'baseFrequency': 350
+ };
+ /**
+ * @param {number} stages
+ * @returns {Array} the number of filters all connected together
+ * @private
+ */
+ Tone.Phaser.prototype._makeFilters = function (stages, connectToFreq, Q) {
+ var filters = new Array(stages);
+ //make all the filters
+ for (var i = 0; i < stages; i++) {
+ var filter = this.context.createBiquadFilter();
+ filter.type = 'allpass';
+ Q.connect(filter.Q);
+ connectToFreq.connect(filter.frequency);
+ filters[i] = filter;
+ }
+ this.connectSeries.apply(this, filters);
+ return filters;
+ };
+ /**
+ * The number of octaves the phase goes above
+ * the baseFrequency
+ * @memberOf Tone.Phaser#
+ * @type {Positive}
+ * @name octaves
+ */
+ Object.defineProperty(Tone.Phaser.prototype, 'octaves', {
+ get: function () {
+ return this._octaves;
+ },
+ set: function (octaves) {
+ this._octaves = octaves;
+ var max = this._baseFrequency * Math.pow(2, octaves);
+ this._lfoL.max = max;
+ this._lfoR.max = max;
+ }
+ });
+ /**
+ * The the base frequency of the filters.
+ * @memberOf Tone.Phaser#
+ * @type {number}
+ * @name baseFrequency
+ */
+ Object.defineProperty(Tone.Phaser.prototype, 'baseFrequency', {
+ get: function () {
+ return this._baseFrequency;
+ },
+ set: function (freq) {
+ this._baseFrequency = freq;
+ this._lfoL.min = freq;
+ this._lfoR.min = freq;
+ this.octaves = this._octaves;
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.Phaser} this
+ */
+ Tone.Phaser.prototype.dispose = function () {
+ Tone.StereoEffect.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'Q'
+ ]);
+ this.Q.dispose();
+ this.Q = null;
+ this._lfoL.dispose();
+ this._lfoL = null;
+ this._lfoR.dispose();
+ this._lfoR = null;
+ for (var i = 0; i < this._filtersL.length; i++) {
+ this._filtersL[i].disconnect();
+ this._filtersL[i] = null;
+ }
+ this._filtersL = null;
+ for (var j = 0; j < this._filtersR.length; j++) {
+ this._filtersR[j].disconnect();
+ this._filtersR[j] = null;
+ }
+ this._filtersR = null;
+ this.frequency = null;
+ return this;
+ };
+ return Tone.Phaser;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.PingPongDelay is a feedback delay effect where the echo is heard
+ * first in one channel and next in the opposite channel. In a stereo
+ * system these are the right and left channels.
+ * PingPongDelay in more simplified terms is two Tone.FeedbackDelays
+ * with independent delay values. Each delay is routed to one channel
+ * (left or right), and the channel triggered second will always
+ * trigger at the same interval after the first.
+ *
+ * @constructor
+ * @extends {Tone.StereoXFeedbackEffect}
+ * @param {Time|Object} [delayTime] The delayTime between consecutive echos.
+ * @param {NormalRange=} feedback The amount of the effected signal which
+ * is fed back through the delay.
+ * @example
+ * var pingPong = new Tone.PingPongDelay("4n", 0.2).toMaster();
+ * var drum = new Tone.DrumSynth().connect(pingPong);
+ * drum.triggerAttackRelease("C4", "32n");
+ */
+ Tone.PingPongDelay = function () {
+ var options = this.optionsObject(arguments, [
+ 'delayTime',
+ 'feedback'
+ ], Tone.PingPongDelay.defaults);
+ Tone.StereoXFeedbackEffect.call(this, options);
+ /**
+ * the delay node on the left side
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._leftDelay = new Tone.Delay(0, options.maxDelayTime);
+ /**
+ * the delay node on the right side
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._rightDelay = new Tone.Delay(0, options.maxDelayTime);
+ /**
+ * the predelay on the right side
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._rightPreDelay = new Tone.Delay(0, options.maxDelayTime);
+ /**
+ * the delay time signal
+ * @type {Time}
+ * @signal
+ */
+ this.delayTime = new Tone.Signal(options.delayTime, Tone.Type.Time);
+ //connect it up
+ this.effectSendL.chain(this._leftDelay, this.effectReturnL);
+ this.effectSendR.chain(this._rightPreDelay, this._rightDelay, this.effectReturnR);
+ this.delayTime.fan(this._leftDelay.delayTime, this._rightDelay.delayTime, this._rightPreDelay.delayTime);
+ //rearranged the feedback to be after the rightPreDelay
+ this._feedbackLR.disconnect();
+ this._feedbackLR.connect(this._rightDelay);
+ this._readOnly(['delayTime']);
+ };
+ Tone.extend(Tone.PingPongDelay, Tone.StereoXFeedbackEffect);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.PingPongDelay.defaults = {
+ 'delayTime': 0.25,
+ 'maxDelayTime': 1
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.PingPongDelay} this
+ */
+ Tone.PingPongDelay.prototype.dispose = function () {
+ Tone.StereoXFeedbackEffect.prototype.dispose.call(this);
+ this._leftDelay.dispose();
+ this._leftDelay = null;
+ this._rightDelay.dispose();
+ this._rightDelay = null;
+ this._rightPreDelay.dispose();
+ this._rightPreDelay = null;
+ this._writable(['delayTime']);
+ this.delayTime.dispose();
+ this.delayTime = null;
+ return this;
+ };
+ return Tone.PingPongDelay;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.PitchShift does near-realtime pitch shifting to the incoming signal.
+ * The effect is achieved by speeding up or slowing down the delayTime
+ * of a DelayNode using a sawtooth wave.
+ * Algorithm found in [this pdf](http://dsp-book.narod.ru/soundproc.pdf).
+ * Additional reference by [Miller Pucket](http://msp.ucsd.edu/techniques/v0.11/book-html/node115.html).
+ *
+ * @extends {Tone.FeedbackEffect}
+ * @param {Interval=} pitch The interval to transpose the incoming signal by.
+ */
+ Tone.PitchShift = function () {
+ var options = this.optionsObject(arguments, ['pitch'], Tone.PitchShift.defaults);
+ Tone.FeedbackEffect.call(this, options);
+ /**
+ * The pitch signal
+ * @type {Tone.Signal}
+ * @private
+ */
+ this._frequency = new Tone.Signal(0);
+ /**
+ * Uses two DelayNodes to cover up the jump in
+ * the sawtooth wave.
+ * @type {DelayNode}
+ * @private
+ */
+ this._delayA = new Tone.Delay(0, 1);
+ /**
+ * The first LFO.
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoA = new Tone.LFO({
+ 'min': 0,
+ 'max': 0.1,
+ 'type': 'sawtooth'
+ }).connect(this._delayA.delayTime);
+ /**
+ * The second DelayNode
+ * @type {DelayNode}
+ * @private
+ */
+ this._delayB = new Tone.Delay(0, 1);
+ /**
+ * The first LFO.
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoB = new Tone.LFO({
+ 'min': 0,
+ 'max': 0.1,
+ 'type': 'sawtooth',
+ 'phase': 180
+ }).connect(this._delayB.delayTime);
+ /**
+ * Crossfade quickly between the two delay lines
+ * to cover up the jump in the sawtooth wave
+ * @type {Tone.CrossFade}
+ * @private
+ */
+ this._crossFade = new Tone.CrossFade();
+ /**
+ * LFO which alternates between the two
+ * delay lines to cover up the disparity in the
+ * sawtooth wave.
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._crossFadeLFO = new Tone.LFO({
+ 'min': 0,
+ 'max': 1,
+ 'type': 'triangle',
+ 'phase': 90
+ }).connect(this._crossFade.fade);
+ /**
+ * The delay node
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._feedbackDelay = new Tone.Delay(options.delayTime);
+ /**
+ * The amount of delay on the input signal
+ * @type {Time}
+ * @signal
+ */
+ this.delayTime = this._feedbackDelay.delayTime;
+ this._readOnly('delayTime');
+ /**
+ * Hold the current pitch
+ * @type {Number}
+ * @private
+ */
+ this._pitch = options.pitch;
+ /**
+ * Hold the current windowSize
+ * @type {Number}
+ * @private
+ */
+ this._windowSize = options.windowSize;
+ //connect the two delay lines up
+ this._delayA.connect(this._crossFade.a);
+ this._delayB.connect(this._crossFade.b);
+ //connect the frequency
+ this._frequency.fan(this._lfoA.frequency, this._lfoB.frequency, this._crossFadeLFO.frequency);
+ //route the input
+ this.effectSend.fan(this._delayA, this._delayB);
+ this._crossFade.chain(this._feedbackDelay, this.effectReturn);
+ //start the LFOs at the same time
+ var now = this.now();
+ this._lfoA.start(now);
+ this._lfoB.start(now);
+ this._crossFadeLFO.start(now);
+ //set the initial value
+ this.windowSize = this._windowSize;
+ };
+ Tone.extend(Tone.PitchShift, Tone.FeedbackEffect);
+ /**
+ * default values
+ * @static
+ * @type {Object}
+ * @const
+ */
+ Tone.PitchShift.defaults = {
+ 'pitch': 0,
+ 'windowSize': 0.1,
+ 'delayTime': 0,
+ 'feedback': 0
+ };
+ /**
+ * Repitch the incoming signal by some interval (measured
+ * in semi-tones).
+ * @memberOf Tone.PitchShift#
+ * @type {Interval}
+ * @name pitch
+ * @example
+ * pitchShift.pitch = -12; //down one octave
+ * pitchShift.pitch = 7; //up a fifth
+ */
+ Object.defineProperty(Tone.PitchShift.prototype, 'pitch', {
+ get: function () {
+ return this._pitch;
+ },
+ set: function (interval) {
+ this._pitch = interval;
+ var factor = 0;
+ if (interval < 0) {
+ this._lfoA.min = 0;
+ this._lfoA.max = this._windowSize;
+ this._lfoB.min = 0;
+ this._lfoB.max = this._windowSize;
+ factor = this.intervalToFrequencyRatio(interval - 1) + 1;
+ } else {
+ this._lfoA.min = this._windowSize;
+ this._lfoA.max = 0;
+ this._lfoB.min = this._windowSize;
+ this._lfoB.max = 0;
+ factor = this.intervalToFrequencyRatio(interval) - 1;
+ }
+ this._frequency.value = factor * (1.2 / this._windowSize);
+ }
+ });
+ /**
+ * The window size corresponds roughly to the sample length in a looping sampler.
+ * Smaller values are desirable for a less noticeable delay time of the pitch shifted
+ * signal, but larger values will result in smoother pitch shifting for larger intervals.
+ * A nominal range of 0.03 to 0.1 is recommended.
+ * @memberOf Tone.PitchShift#
+ * @type {Time}
+ * @name windowSize
+ * @example
+ * pitchShift.windowSize = 0.1;
+ */
+ Object.defineProperty(Tone.PitchShift.prototype, 'windowSize', {
+ get: function () {
+ return this._windowSize;
+ },
+ set: function (size) {
+ this._windowSize = this.toSeconds(size);
+ this.pitch = this._pitch;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.PitchShift} this
+ */
+ Tone.PitchShift.prototype.dispose = function () {
+ Tone.FeedbackEffect.prototype.dispose.call(this);
+ this._frequency.dispose();
+ this._frequency = null;
+ this._delayA.disconnect();
+ this._delayA = null;
+ this._delayB.disconnect();
+ this._delayB = null;
+ this._lfoA.dispose();
+ this._lfoA = null;
+ this._lfoB.dispose();
+ this._lfoB = null;
+ this._crossFade.dispose();
+ this._crossFade = null;
+ this._crossFadeLFO.dispose();
+ this._crossFadeLFO = null;
+ this._writable('delayTime');
+ this._feedbackDelay.dispose();
+ this._feedbackDelay = null;
+ this.delayTime = null;
+ return this;
+ };
+ return Tone.PitchShift;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Base class for stereo feedback effects where the effectReturn
+ * is fed back into the same channel.
+ *
+ * @constructor
+ * @extends {Tone.FeedbackEffect}
+ */
+ Tone.StereoFeedbackEffect = function () {
+ var options = this.optionsObject(arguments, ['feedback'], Tone.FeedbackEffect.defaults);
+ Tone.StereoEffect.call(this, options);
+ /**
+ * controls the amount of feedback
+ * @type {NormalRange}
+ * @signal
+ */
+ this.feedback = new Tone.Signal(options.feedback, Tone.Type.NormalRange);
+ /**
+ * the left side feeback
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._feedbackL = new Tone.Gain();
+ /**
+ * the right side feeback
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._feedbackR = new Tone.Gain();
+ //connect it up
+ this.effectReturnL.chain(this._feedbackL, this.effectSendL);
+ this.effectReturnR.chain(this._feedbackR, this.effectSendR);
+ this.feedback.fan(this._feedbackL.gain, this._feedbackR.gain);
+ this._readOnly(['feedback']);
+ };
+ Tone.extend(Tone.StereoFeedbackEffect, Tone.FeedbackEffect);
+ /**
+ * clean up
+ * @returns {Tone.StereoFeedbackEffect} this
+ */
+ Tone.StereoFeedbackEffect.prototype.dispose = function () {
+ Tone.StereoEffect.prototype.dispose.call(this);
+ this._writable(['feedback']);
+ this.feedback.dispose();
+ this.feedback = null;
+ this._feedbackL.dispose();
+ this._feedbackL = null;
+ this._feedbackR.dispose();
+ this._feedbackR = null;
+ return this;
+ };
+ return Tone.StereoFeedbackEffect;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Applies a width factor to the mid/side seperation.
+ * 0 is all mid and 1 is all side.
+ * Algorithm found in [kvraudio forums](http://www.kvraudio.com/forum/viewtopic.php?t=212587).
+ * <br><br>
+ * <code>
+ * Mid *= 2*(1-width)<br>
+ * Side *= 2*width
+ * </code>
+ *
+ * @extends {Tone.MidSideEffect}
+ * @constructor
+ * @param {NormalRange|Object} [width] The stereo width. A width of 0 is mono and 1 is stereo. 0.5 is no change.
+ */
+ Tone.StereoWidener = function () {
+ var options = this.optionsObject(arguments, ['width'], Tone.StereoWidener.defaults);
+ Tone.MidSideEffect.call(this, options);
+ /**
+ * The width control. 0 = 100% mid. 1 = 100% side. 0.5 = no change.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.width = new Tone.Signal(options.width, Tone.Type.NormalRange);
+ /**
+ * Mid multiplier
+ * @type {Tone.Expr}
+ * @private
+ */
+ this._midMult = new Tone.Expr('$0 * ($1 * (1 - $2))');
+ /**
+ * Side multiplier
+ * @type {Tone.Expr}
+ * @private
+ */
+ this._sideMult = new Tone.Expr('$0 * ($1 * $2)');
+ /**
+ * constant output of 2
+ * @type {Tone}
+ * @private
+ */
+ this._two = new Tone.Signal(2);
+ //the mid chain
+ this._two.connect(this._midMult, 0, 1);
+ this.width.connect(this._midMult, 0, 2);
+ //the side chain
+ this._two.connect(this._sideMult, 0, 1);
+ this.width.connect(this._sideMult, 0, 2);
+ //connect it to the effect send/return
+ this.midSend.chain(this._midMult, this.midReturn);
+ this.sideSend.chain(this._sideMult, this.sideReturn);
+ this._readOnly(['width']);
+ };
+ Tone.extend(Tone.StereoWidener, Tone.MidSideEffect);
+ /**
+ * the default values
+ * @static
+ * @type {Object}
+ */
+ Tone.StereoWidener.defaults = { 'width': 0.5 };
+ /**
+ * Clean up.
+ * @returns {Tone.StereoWidener} this
+ */
+ Tone.StereoWidener.prototype.dispose = function () {
+ Tone.MidSideEffect.prototype.dispose.call(this);
+ this._writable(['width']);
+ this.width.dispose();
+ this.width = null;
+ this._midMult.dispose();
+ this._midMult = null;
+ this._sideMult.dispose();
+ this._sideMult = null;
+ this._two.dispose();
+ this._two = null;
+ return this;
+ };
+ return Tone.StereoWidener;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Tremolo modulates the amplitude of an incoming signal using a Tone.LFO.
+ * The type, frequency, and depth of the LFO is controllable.
+ *
+ * @extends {Tone.StereoEffect}
+ * @constructor
+ * @param {Frequency} [frequency] The rate of the effect.
+ * @param {NormalRange} [depth] The depth of the effect.
+ * @example
+ * //create a tremolo and start it's LFO
+ * var tremolo = new Tone.Tremolo(9, 0.75).toMaster().start();
+ * //route an oscillator through the tremolo and start it
+ * var oscillator = new Tone.Oscillator().connect(tremolo).start();
+ */
+ Tone.Tremolo = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'depth'
+ ], Tone.Tremolo.defaults);
+ Tone.StereoEffect.call(this, options);
+ /**
+ * The tremelo LFO in the left channel
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoL = new Tone.LFO({
+ 'phase': options.spread,
+ 'min': 1,
+ 'max': 0
+ });
+ /**
+ * The tremelo LFO in the left channel
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfoR = new Tone.LFO({
+ 'phase': options.spread,
+ 'min': 1,
+ 'max': 0
+ });
+ /**
+ * Where the gain is multiplied
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._amplitudeL = new Tone.Gain();
+ /**
+ * Where the gain is multiplied
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._amplitudeR = new Tone.Gain();
+ /**
+ * The frequency of the tremolo.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The depth of the effect. A depth of 0, has no effect
+ * on the amplitude, and a depth of 1 makes the amplitude
+ * modulate fully between 0 and 1.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.depth = new Tone.Signal(options.depth, Tone.Type.NormalRange);
+ this._readOnly([
+ 'frequency',
+ 'depth'
+ ]);
+ this.effectSendL.chain(this._amplitudeL, this.effectReturnL);
+ this.effectSendR.chain(this._amplitudeR, this.effectReturnR);
+ this._lfoL.connect(this._amplitudeL.gain);
+ this._lfoR.connect(this._amplitudeR.gain);
+ this.frequency.fan(this._lfoL.frequency, this._lfoR.frequency);
+ this.depth.fan(this._lfoR.amplitude, this._lfoL.amplitude);
+ this.type = options.type;
+ this.spread = options.spread;
+ };
+ Tone.extend(Tone.Tremolo, Tone.StereoEffect);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Tremolo.defaults = {
+ 'frequency': 10,
+ 'type': 'sine',
+ 'depth': 0.5,
+ 'spread': 180
+ };
+ /**
+ * Start the tremolo.
+ * @param {Time} [time=now] When the tremolo begins.
+ * @returns {Tone.Tremolo} this
+ */
+ Tone.Tremolo.prototype.start = function (time) {
+ this._lfoL.start(time);
+ this._lfoR.start(time);
+ return this;
+ };
+ /**
+ * Stop the tremolo.
+ * @param {Time} [time=now] When the tremolo stops.
+ * @returns {Tone.Tremolo} this
+ */
+ Tone.Tremolo.prototype.stop = function (time) {
+ this._lfoL.stop(time);
+ this._lfoR.stop(time);
+ return this;
+ };
+ /**
+ * Sync the effect to the transport.
+ * @param {Time} [delay=0] Delay time before starting the effect after the
+ * Transport has started.
+ * @returns {Tone.AutoFilter} this
+ */
+ Tone.Tremolo.prototype.sync = function (delay) {
+ this._lfoL.sync(delay);
+ this._lfoR.sync(delay);
+ return this;
+ };
+ /**
+ * Unsync the filter from the transport
+ * @returns {Tone.Tremolo} this
+ */
+ Tone.Tremolo.prototype.unsync = function () {
+ this._lfoL.unsync();
+ this._lfoR.unsync();
+ return this;
+ };
+ /**
+ * The Tremolo's oscillator type.
+ * @memberOf Tone.Tremolo#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.Tremolo.prototype, 'type', {
+ get: function () {
+ return this._lfoL.type;
+ },
+ set: function (type) {
+ this._lfoL.type = type;
+ this._lfoR.type = type;
+ }
+ });
+ /**
+ * Amount of stereo spread. When set to 0, both LFO's will be panned centrally.
+ * When set to 180, LFO's will be panned hard left and right respectively.
+ * @memberOf Tone.Tremolo#
+ * @type {Degrees}
+ * @name spread
+ */
+ Object.defineProperty(Tone.Tremolo.prototype, 'spread', {
+ get: function () {
+ return this._lfoR.phase - this._lfoL.phase; //180
+ },
+ set: function (spread) {
+ this._lfoL.phase = 90 - spread / 2;
+ this._lfoR.phase = spread / 2 + 90;
+ }
+ });
+ /**
+ * clean up
+ * @returns {Tone.Tremolo} this
+ */
+ Tone.Tremolo.prototype.dispose = function () {
+ Tone.StereoEffect.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'depth'
+ ]);
+ this._lfoL.dispose();
+ this._lfoL = null;
+ this._lfoR.dispose();
+ this._lfoR = null;
+ this._amplitudeL.dispose();
+ this._amplitudeL = null;
+ this._amplitudeR.dispose();
+ this._amplitudeR = null;
+ this.frequency = null;
+ this.depth = null;
+ return this;
+ };
+ return Tone.Tremolo;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A Vibrato effect composed of a Tone.Delay and a Tone.LFO. The LFO
+ * modulates the delayTime of the delay, causing the pitch to rise
+ * and fall.
+ * @extends {Tone.Effect}
+ * @param {Frequency} frequency The frequency of the vibrato.
+ * @param {NormalRange} depth The amount the pitch is modulated.
+ */
+ Tone.Vibrato = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'depth'
+ ], Tone.Vibrato.defaults);
+ Tone.Effect.call(this, options);
+ /**
+ * The delay node used for the vibrato effect
+ * @type {Tone.Delay}
+ * @private
+ */
+ this._delayNode = new Tone.Delay(0, options.maxDelay);
+ /**
+ * The LFO used to control the vibrato
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._lfo = new Tone.LFO({
+ 'type': options.type,
+ 'min': 0,
+ 'max': options.maxDelay,
+ 'frequency': options.frequency,
+ 'phase': -90 //offse the phase so the resting position is in the center
+ }).start().connect(this._delayNode.delayTime);
+ /**
+ * The frequency of the vibrato
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._lfo.frequency;
+ /**
+ * The depth of the vibrato.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.depth = this._lfo.amplitude;
+ this.depth.value = options.depth;
+ this._readOnly([
+ 'frequency',
+ 'depth'
+ ]);
+ this.effectSend.chain(this._delayNode, this.effectReturn);
+ };
+ Tone.extend(Tone.Vibrato, Tone.Effect);
+ /**
+ * The defaults
+ * @type {Object}
+ * @const
+ */
+ Tone.Vibrato.defaults = {
+ 'maxDelay': 0.005,
+ 'frequency': 5,
+ 'depth': 0.1,
+ 'type': 'sine'
+ };
+ /**
+ * Type of oscillator attached to the Vibrato.
+ * @memberOf Tone.Vibrato#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.Vibrato.prototype, 'type', {
+ get: function () {
+ return this._lfo.type;
+ },
+ set: function (type) {
+ this._lfo.type = type;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Vibrato} this
+ */
+ Tone.Vibrato.prototype.dispose = function () {
+ Tone.Effect.prototype.dispose.call(this);
+ this._delayNode.dispose();
+ this._delayNode = null;
+ this._lfo.dispose();
+ this._lfo = null;
+ this._writable([
+ 'frequency',
+ 'depth'
+ ]);
+ this.frequency = null;
+ this.depth = null;
+ };
+ return Tone.Vibrato;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Event abstracts away Tone.Transport.schedule and provides a schedulable
+ * callback for a single or repeatable events along the timeline.
+ *
+ * @extends {Tone}
+ * @param {function} callback The callback to invoke at the time.
+ * @param {*} value The value or values which should be passed to
+ * the callback function on invocation.
+ * @example
+ * var chord = new Tone.Event(function(time, chord){
+ * //the chord as well as the exact time of the event
+ * //are passed in as arguments to the callback function
+ * }, ["D4", "E4", "F4"]);
+ * //start the chord at the beginning of the transport timeline
+ * chord.start();
+ * //loop it every measure for 8 measures
+ * chord.loop = 8;
+ * chord.loopEnd = "1m";
+ */
+ Tone.Event = function () {
+ var options = this.optionsObject(arguments, [
+ 'callback',
+ 'value'
+ ], Tone.Event.defaults);
+ /**
+ * Loop value
+ * @type {Boolean|Positive}
+ * @private
+ */
+ this._loop = options.loop;
+ /**
+ * The callback to invoke.
+ * @type {Function}
+ */
+ this.callback = options.callback;
+ /**
+ * The value which is passed to the
+ * callback function.
+ * @type {*}
+ * @private
+ */
+ this.value = options.value;
+ /**
+ * When the note is scheduled to start.
+ * @type {Number}
+ * @private
+ */
+ this._loopStart = this.toTicks(options.loopStart);
+ /**
+ * When the note is scheduled to start.
+ * @type {Number}
+ * @private
+ */
+ this._loopEnd = this.toTicks(options.loopEnd);
+ /**
+ * Tracks the scheduled events
+ * @type {Tone.TimelineState}
+ * @private
+ */
+ this._state = new Tone.TimelineState(Tone.State.Stopped);
+ /**
+ * The playback speed of the note. A speed of 1
+ * is no change.
+ * @private
+ * @type {Positive}
+ */
+ this._playbackRate = 1;
+ /**
+ * A delay time from when the event is scheduled to start
+ * @type {Ticks}
+ * @private
+ */
+ this._startOffset = 0;
+ /**
+ * The probability that the callback will be invoked
+ * at the scheduled time.
+ * @type {NormalRange}
+ * @example
+ * //the callback will be invoked 50% of the time
+ * event.probability = 0.5;
+ */
+ this.probability = options.probability;
+ /**
+ * If set to true, will apply small (+/-0.02 seconds) random variation
+ * to the callback time. If the value is given as a time, it will randomize
+ * by that amount.
+ * @example
+ * event.humanize = true;
+ * @type {Boolean|Time}
+ */
+ this.humanize = options.humanize;
+ /**
+ * If mute is true, the callback won't be
+ * invoked.
+ * @type {Boolean}
+ */
+ this.mute = options.mute;
+ //set the initial values
+ this.playbackRate = options.playbackRate;
+ };
+ Tone.extend(Tone.Event);
+ /**
+ * The default values
+ * @type {Object}
+ * @const
+ */
+ Tone.Event.defaults = {
+ 'callback': Tone.noOp,
+ 'loop': false,
+ 'loopEnd': '1m',
+ 'loopStart': 0,
+ 'playbackRate': 1,
+ 'value': null,
+ 'probability': 1,
+ 'mute': false,
+ 'humanize': false
+ };
+ /**
+ * Reschedule all of the events along the timeline
+ * with the updated values.
+ * @param {Time} after Only reschedules events after the given time.
+ * @return {Tone.Event} this
+ * @private
+ */
+ Tone.Event.prototype._rescheduleEvents = function (after) {
+ //if no argument is given, schedules all of the events
+ after = this.defaultArg(after, -1);
+ this._state.forEachFrom(after, function (event) {
+ var duration;
+ if (event.state === Tone.State.Started) {
+ if (!this.isUndef(event.id)) {
+ Tone.Transport.clear(event.id);
+ }
+ var startTick = event.time + Math.round(this.startOffset / this._playbackRate);
+ if (this._loop) {
+ duration = Infinity;
+ if (this.isNumber(this._loop)) {
+ duration = this._loop * this._getLoopDuration();
+ }
+ var nextEvent = this._state.getAfter(startTick);
+ if (nextEvent !== null) {
+ duration = Math.min(duration, nextEvent.time - startTick);
+ }
+ if (duration !== Infinity) {
+ //schedule a stop since it's finite duration
+ this._state.setStateAtTime(Tone.State.Stopped, startTick + duration + 1);
+ duration = Tone.Time(duration, 'i');
+ }
+ var interval = Tone.Time(this._getLoopDuration(), 'i');
+ event.id = Tone.Transport.scheduleRepeat(this._tick.bind(this), interval, Tone.TransportTime(startTick, 'i'), duration);
+ } else {
+ event.id = Tone.Transport.schedule(this._tick.bind(this), startTick + 'i');
+ }
+ }
+ }.bind(this));
+ return this;
+ };
+ /**
+ * Returns the playback state of the note, either "started" or "stopped".
+ * @type {String}
+ * @readOnly
+ * @memberOf Tone.Event#
+ * @name state
+ */
+ Object.defineProperty(Tone.Event.prototype, 'state', {
+ get: function () {
+ return this._state.getValueAtTime(Tone.Transport.ticks);
+ }
+ });
+ /**
+ * The start from the scheduled start time
+ * @type {Ticks}
+ * @memberOf Tone.Event#
+ * @name startOffset
+ * @private
+ */
+ Object.defineProperty(Tone.Event.prototype, 'startOffset', {
+ get: function () {
+ return this._startOffset;
+ },
+ set: function (offset) {
+ this._startOffset = offset;
+ }
+ });
+ /**
+ * Start the note at the given time.
+ * @param {TimelinePosition} time When the note should start.
+ * @return {Tone.Event} this
+ */
+ Tone.Event.prototype.start = function (time) {
+ time = this.toTicks(time);
+ if (this._state.getValueAtTime(time) === Tone.State.Stopped) {
+ this._state.add({
+ 'state': Tone.State.Started,
+ 'time': time,
+ 'id': undefined
+ });
+ this._rescheduleEvents(time);
+ }
+ return this;
+ };
+ /**
+ * Stop the Event at the given time.
+ * @param {TimelinePosition} time When the note should stop.
+ * @return {Tone.Event} this
+ */
+ Tone.Event.prototype.stop = function (time) {
+ this.cancel(time);
+ time = this.toTicks(time);
+ if (this._state.getValueAtTime(time) === Tone.State.Started) {
+ this._state.setStateAtTime(Tone.State.Stopped, time);
+ var previousEvent = this._state.getBefore(time);
+ var reschedulTime = time;
+ if (previousEvent !== null) {
+ reschedulTime = previousEvent.time;
+ }
+ this._rescheduleEvents(reschedulTime);
+ }
+ return this;
+ };
+ /**
+ * Cancel all scheduled events greater than or equal to the given time
+ * @param {TimelinePosition} [time=0] The time after which events will be cancel.
+ * @return {Tone.Event} this
+ */
+ Tone.Event.prototype.cancel = function (time) {
+ time = this.defaultArg(time, -Infinity);
+ time = this.toTicks(time);
+ this._state.forEachFrom(time, function (event) {
+ Tone.Transport.clear(event.id);
+ });
+ this._state.cancel(time);
+ return this;
+ };
+ /**
+ * The callback function invoker. Also
+ * checks if the Event is done playing
+ * @param {Number} time The time of the event in seconds
+ * @private
+ */
+ Tone.Event.prototype._tick = function (time) {
+ if (!this.mute && this._state.getValueAtTime(Tone.Transport.ticks) === Tone.State.Started) {
+ if (this.probability < 1 && Math.random() > this.probability) {
+ return;
+ }
+ if (this.humanize) {
+ var variation = 0.02;
+ if (!this.isBoolean(this.humanize)) {
+ variation = this.toSeconds(this.humanize);
+ }
+ time += (Math.random() * 2 - 1) * variation;
+ }
+ this.callback(time, this.value);
+ }
+ };
+ /**
+ * Get the duration of the loop.
+ * @return {Ticks}
+ * @private
+ */
+ Tone.Event.prototype._getLoopDuration = function () {
+ return Math.round((this._loopEnd - this._loopStart) / this._playbackRate);
+ };
+ /**
+ * If the note should loop or not
+ * between Tone.Event.loopStart and
+ * Tone.Event.loopEnd. An integer
+ * value corresponds to the number of
+ * loops the Event does after it starts.
+ * @memberOf Tone.Event#
+ * @type {Boolean|Positive}
+ * @name loop
+ */
+ Object.defineProperty(Tone.Event.prototype, 'loop', {
+ get: function () {
+ return this._loop;
+ },
+ set: function (loop) {
+ this._loop = loop;
+ this._rescheduleEvents();
+ }
+ });
+ /**
+ * The playback rate of the note. Defaults to 1.
+ * @memberOf Tone.Event#
+ * @type {Positive}
+ * @name playbackRate
+ * @example
+ * note.loop = true;
+ * //repeat the note twice as fast
+ * note.playbackRate = 2;
+ */
+ Object.defineProperty(Tone.Event.prototype, 'playbackRate', {
+ get: function () {
+ return this._playbackRate;
+ },
+ set: function (rate) {
+ this._playbackRate = rate;
+ this._rescheduleEvents();
+ }
+ });
+ /**
+ * The loopEnd point is the time the event will loop
+ * if Tone.Event.loop is true.
+ * @memberOf Tone.Event#
+ * @type {TransportTime}
+ * @name loopEnd
+ */
+ Object.defineProperty(Tone.Event.prototype, 'loopEnd', {
+ get: function () {
+ return Tone.TransportTime(this._loopEnd, 'i').toNotation();
+ },
+ set: function (loopEnd) {
+ this._loopEnd = this.toTicks(loopEnd);
+ if (this._loop) {
+ this._rescheduleEvents();
+ }
+ }
+ });
+ /**
+ * The time when the loop should start.
+ * @memberOf Tone.Event#
+ * @type {TransportTime}
+ * @name loopStart
+ */
+ Object.defineProperty(Tone.Event.prototype, 'loopStart', {
+ get: function () {
+ return Tone.TransportTime(this._loopStart, 'i').toNotation();
+ },
+ set: function (loopStart) {
+ this._loopStart = this.toTicks(loopStart);
+ if (this._loop) {
+ this._rescheduleEvents();
+ }
+ }
+ });
+ /**
+ * The current progress of the loop interval.
+ * Returns 0 if the event is not started yet or
+ * it is not set to loop.
+ * @memberOf Tone.Event#
+ * @type {NormalRange}
+ * @name progress
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Event.prototype, 'progress', {
+ get: function () {
+ if (this._loop) {
+ var ticks = Tone.Transport.ticks;
+ var lastEvent = this._state.get(ticks);
+ if (lastEvent !== null && lastEvent.state === Tone.State.Started) {
+ var loopDuration = this._getLoopDuration();
+ var progress = (ticks - lastEvent.time) % loopDuration;
+ return progress / loopDuration;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+ });
+ /**
+ * Clean up
+ * @return {Tone.Event} this
+ */
+ Tone.Event.prototype.dispose = function () {
+ this.cancel();
+ this._state.dispose();
+ this._state = null;
+ this.callback = null;
+ this.value = null;
+ };
+ return Tone.Event;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.Loop creates a looped callback at the
+ * specified interval. The callback can be
+ * started, stopped and scheduled along
+ * the Transport's timeline.
+ * @example
+ * var loop = new Tone.Loop(function(time){
+ * //triggered every eighth note.
+ * console.log(time);
+ * }, "8n").start(0);
+ * Tone.Transport.start();
+ * @extends {Tone}
+ * @param {Function} callback The callback to invoke with the event.
+ * @param {Time} interval The time between successive callback calls.
+ */
+ Tone.Loop = function () {
+ var options = this.optionsObject(arguments, [
+ 'callback',
+ 'interval'
+ ], Tone.Loop.defaults);
+ /**
+ * The event which produces the callbacks
+ */
+ this._event = new Tone.Event({
+ 'callback': this._tick.bind(this),
+ 'loop': true,
+ 'loopEnd': options.interval,
+ 'playbackRate': options.playbackRate,
+ 'probability': options.probability
+ });
+ /**
+ * The callback to invoke with the next event in the pattern
+ * @type {Function}
+ */
+ this.callback = options.callback;
+ //set the iterations
+ this.iterations = options.iterations;
+ };
+ Tone.extend(Tone.Loop);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.Loop.defaults = {
+ 'interval': '4n',
+ 'callback': Tone.noOp,
+ 'playbackRate': 1,
+ 'iterations': Infinity,
+ 'probability': true,
+ 'mute': false
+ };
+ /**
+ * Start the loop at the specified time along the Transport's
+ * timeline.
+ * @param {TimelinePosition=} time When to start the Loop.
+ * @return {Tone.Loop} this
+ */
+ Tone.Loop.prototype.start = function (time) {
+ this._event.start(time);
+ return this;
+ };
+ /**
+ * Stop the loop at the given time.
+ * @param {TimelinePosition=} time When to stop the Arpeggio
+ * @return {Tone.Loop} this
+ */
+ Tone.Loop.prototype.stop = function (time) {
+ this._event.stop(time);
+ return this;
+ };
+ /**
+ * Cancel all scheduled events greater than or equal to the given time
+ * @param {TimelinePosition} [time=0] The time after which events will be cancel.
+ * @return {Tone.Loop} this
+ */
+ Tone.Loop.prototype.cancel = function (time) {
+ this._event.cancel(time);
+ return this;
+ };
+ /**
+ * Internal function called when the notes should be called
+ * @param {Number} time The time the event occurs
+ * @private
+ */
+ Tone.Loop.prototype._tick = function (time) {
+ this.callback(time);
+ };
+ /**
+ * The state of the Loop, either started or stopped.
+ * @memberOf Tone.Loop#
+ * @type {String}
+ * @name state
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'state', {
+ get: function () {
+ return this._event.state;
+ }
+ });
+ /**
+ * The progress of the loop as a value between 0-1. 0, when
+ * the loop is stopped or done iterating.
+ * @memberOf Tone.Loop#
+ * @type {NormalRange}
+ * @name progress
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'progress', {
+ get: function () {
+ return this._event.progress;
+ }
+ });
+ /**
+ * The time between successive callbacks.
+ * @example
+ * loop.interval = "8n"; //loop every 8n
+ * @memberOf Tone.Loop#
+ * @type {Time}
+ * @name interval
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'interval', {
+ get: function () {
+ return this._event.loopEnd;
+ },
+ set: function (interval) {
+ this._event.loopEnd = interval;
+ }
+ });
+ /**
+ * The playback rate of the loop. The normal playback rate is 1 (no change).
+ * A `playbackRate` of 2 would be twice as fast.
+ * @memberOf Tone.Loop#
+ * @type {Time}
+ * @name playbackRate
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'playbackRate', {
+ get: function () {
+ return this._event.playbackRate;
+ },
+ set: function (rate) {
+ this._event.playbackRate = rate;
+ }
+ });
+ /**
+ * Random variation +/-0.01s to the scheduled time.
+ * Or give it a time value which it will randomize by.
+ * @type {Boolean|Time}
+ * @memberOf Tone.Loop#
+ * @name humanize
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'humanize', {
+ get: function () {
+ return this._event.humanize;
+ },
+ set: function (variation) {
+ this._event.humanize = variation;
+ }
+ });
+ /**
+ * The probably of the callback being invoked.
+ * @memberOf Tone.Loop#
+ * @type {NormalRange}
+ * @name probability
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'probability', {
+ get: function () {
+ return this._event.probability;
+ },
+ set: function (prob) {
+ this._event.probability = prob;
+ }
+ });
+ /**
+ * Muting the Loop means that no callbacks are invoked.
+ * @memberOf Tone.Loop#
+ * @type {Boolean}
+ * @name mute
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'mute', {
+ get: function () {
+ return this._event.mute;
+ },
+ set: function (mute) {
+ this._event.mute = mute;
+ }
+ });
+ /**
+ * The number of iterations of the loop. The default
+ * value is Infinity (loop forever).
+ * @memberOf Tone.Loop#
+ * @type {Positive}
+ * @name iterations
+ */
+ Object.defineProperty(Tone.Loop.prototype, 'iterations', {
+ get: function () {
+ if (this._event.loop === true) {
+ return Infinity;
+ } else {
+ return this._event.loop;
+ }
+ return this._pattern.index;
+ },
+ set: function (iters) {
+ if (iters === Infinity) {
+ this._event.loop = true;
+ } else {
+ this._event.loop = iters;
+ }
+ }
+ });
+ /**
+ * Clean up
+ * @return {Tone.Loop} this
+ */
+ Tone.Loop.prototype.dispose = function () {
+ this._event.dispose();
+ this._event = null;
+ this.callback = null;
+ };
+ return Tone.Loop;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Part is a collection Tone.Events which can be
+ * started/stoped and looped as a single unit.
+ *
+ * @extends {Tone.Event}
+ * @param {Function} callback The callback to invoke on each event
+ * @param {Array} events the array of events
+ * @example
+ * var part = new Tone.Part(function(time, note){
+ * //the notes given as the second element in the array
+ * //will be passed in as the second argument
+ * synth.triggerAttackRelease(note, "8n", time);
+ * }, [[0, "C2"], ["0:2", "C3"], ["0:3:2", "G2"]]);
+ * @example
+ * //use an array of objects as long as the object has a "time" attribute
+ * var part = new Tone.Part(function(time, value){
+ * //the value is an object which contains both the note and the velocity
+ * synth.triggerAttackRelease(value.note, "8n", time, value.velocity);
+ * }, [{"time" : 0, "note" : "C3", "velocity": 0.9},
+ * {"time" : "0:2", "note" : "C4", "velocity": 0.5}
+ * ]).start(0);
+ */
+ Tone.Part = function () {
+ var options = this.optionsObject(arguments, [
+ 'callback',
+ 'events'
+ ], Tone.Part.defaults);
+ /**
+ * If the part is looping or not
+ * @type {Boolean|Positive}
+ * @private
+ */
+ this._loop = options.loop;
+ /**
+ * When the note is scheduled to start.
+ * @type {Ticks}
+ * @private
+ */
+ this._loopStart = this.toTicks(options.loopStart);
+ /**
+ * When the note is scheduled to start.
+ * @type {Ticks}
+ * @private
+ */
+ this._loopEnd = this.toTicks(options.loopEnd);
+ /**
+ * The playback rate of the part
+ * @type {Positive}
+ * @private
+ */
+ this._playbackRate = options.playbackRate;
+ /**
+ * private holder of probability value
+ * @type {NormalRange}
+ * @private
+ */
+ this._probability = options.probability;
+ /**
+ * the amount of variation from the
+ * given time.
+ * @type {Boolean|Time}
+ * @private
+ */
+ this._humanize = options.humanize;
+ /**
+ * The start offset
+ * @type {Ticks}
+ * @private
+ */
+ this._startOffset = 0;
+ /**
+ * Keeps track of the current state
+ * @type {Tone.TimelineState}
+ * @private
+ */
+ this._state = new Tone.TimelineState(Tone.State.Stopped);
+ /**
+ * An array of Objects.
+ * @type {Array}
+ * @private
+ */
+ this._events = [];
+ /**
+ * The callback to invoke at all the scheduled events.
+ * @type {Function}
+ */
+ this.callback = options.callback;
+ /**
+ * If mute is true, the callback won't be
+ * invoked.
+ * @type {Boolean}
+ */
+ this.mute = options.mute;
+ //add the events
+ var events = this.defaultArg(options.events, []);
+ if (!this.isUndef(options.events)) {
+ for (var i = 0; i < events.length; i++) {
+ if (Array.isArray(events[i])) {
+ this.add(events[i][0], events[i][1]);
+ } else {
+ this.add(events[i]);
+ }
+ }
+ }
+ };
+ Tone.extend(Tone.Part, Tone.Event);
+ /**
+ * The default values
+ * @type {Object}
+ * @const
+ */
+ Tone.Part.defaults = {
+ 'callback': Tone.noOp,
+ 'loop': false,
+ 'loopEnd': '1m',
+ 'loopStart': 0,
+ 'playbackRate': 1,
+ 'probability': 1,
+ 'humanize': false,
+ 'mute': false
+ };
+ /**
+ * Start the part at the given time.
+ * @param {TransportTime} time When to start the part.
+ * @param {Time=} offset The offset from the start of the part
+ * to begin playing at.
+ * @return {Tone.Part} this
+ */
+ Tone.Part.prototype.start = function (time, offset) {
+ var ticks = this.toTicks(time);
+ if (this._state.getValueAtTime(ticks) !== Tone.State.Started) {
+ if (this._loop) {
+ offset = this.defaultArg(offset, this._loopStart);
+ } else {
+ offset = this.defaultArg(offset, 0);
+ }
+ offset = this.toTicks(offset);
+ this._state.add({
+ 'state': Tone.State.Started,
+ 'time': ticks,
+ 'offset': offset
+ });
+ this._forEach(function (event) {
+ this._startNote(event, ticks, offset);
+ });
+ }
+ return this;
+ };
+ /**
+ * Start the event in the given event at the correct time given
+ * the ticks and offset and looping.
+ * @param {Tone.Event} event
+ * @param {Ticks} ticks
+ * @param {Ticks} offset
+ * @private
+ */
+ Tone.Part.prototype._startNote = function (event, ticks, offset) {
+ ticks -= offset;
+ if (this._loop) {
+ if (event.startOffset >= this._loopStart && event.startOffset < this._loopEnd) {
+ if (event.startOffset < offset) {
+ //start it on the next loop
+ ticks += this._getLoopDuration();
+ }
+ event.start(Tone.TransportTime(ticks, 'i'));
+ } else if (event.startOffset < this._loopStart && event.startOffset >= offset) {
+ event.loop = false;
+ event.start(Tone.TransportTime(ticks, 'i'));
+ }
+ } else {
+ if (event.startOffset >= offset) {
+ event.start(Tone.TransportTime(ticks, 'i'));
+ }
+ }
+ };
+ /**
+ * The start from the scheduled start time
+ * @type {Ticks}
+ * @memberOf Tone.Part#
+ * @name startOffset
+ * @private
+ */
+ Object.defineProperty(Tone.Part.prototype, 'startOffset', {
+ get: function () {
+ return this._startOffset;
+ },
+ set: function (offset) {
+ this._startOffset = offset;
+ this._forEach(function (event) {
+ event.startOffset += this._startOffset;
+ });
+ }
+ });
+ /**
+ * Stop the part at the given time.
+ * @param {TimelinePosition} time When to stop the part.
+ * @return {Tone.Part} this
+ */
+ Tone.Part.prototype.stop = function (time) {
+ var ticks = this.toTicks(time);
+ this._state.cancel(ticks);
+ this._state.setStateAtTime(Tone.State.Stopped, ticks);
+ this._forEach(function (event) {
+ event.stop(time);
+ });
+ return this;
+ };
+ /**
+ * Get/Set an Event's value at the given time.
+ * If a value is passed in and no event exists at
+ * the given time, one will be created with that value.
+ * If two events are at the same time, the first one will
+ * be returned.
+ * @example
+ * part.at("1m"); //returns the part at the first measure
+ *
+ * part.at("2m", "C2"); //set the value at "2m" to C2.
+ * //if an event didn't exist at that time, it will be created.
+ * @param {TransportTime} time The time of the event to get or set.
+ * @param {*=} value If a value is passed in, the value of the
+ * event at the given time will be set to it.
+ * @return {Tone.Event} the event at the time
+ */
+ Tone.Part.prototype.at = function (time, value) {
+ time = Tone.TransportTime(time);
+ var tickTime = Tone.Time(1, 'i').toSeconds();
+ for (var i = 0; i < this._events.length; i++) {
+ var event = this._events[i];
+ if (Math.abs(time.toTicks() - event.startOffset) < tickTime) {
+ if (!this.isUndef(value)) {
+ event.value = value;
+ }
+ return event;
+ }
+ }
+ //if there was no event at that time, create one
+ if (!this.isUndef(value)) {
+ this.add(time, value);
+ //return the new event
+ return this._events[this._events.length - 1];
+ } else {
+ return null;
+ }
+ };
+ /**
+ * Add a an event to the part.
+ * @param {Time} time The time the note should start.
+ * If an object is passed in, it should
+ * have a 'time' attribute and the rest
+ * of the object will be used as the 'value'.
+ * @param {Tone.Event|*} value
+ * @returns {Tone.Part} this
+ * @example
+ * part.add("1m", "C#+11");
+ */
+ Tone.Part.prototype.add = function (time, value) {
+ //extract the parameters
+ if (time.hasOwnProperty('time')) {
+ value = time;
+ time = value.time;
+ }
+ time = this.toTicks(time);
+ var event;
+ if (value instanceof Tone.Event) {
+ event = value;
+ event.callback = this._tick.bind(this);
+ } else {
+ event = new Tone.Event({
+ 'callback': this._tick.bind(this),
+ 'value': value
+ });
+ }
+ //the start offset
+ event.startOffset = time;
+ //initialize the values
+ event.set({
+ 'loopEnd': this.loopEnd,
+ 'loopStart': this.loopStart,
+ 'loop': this.loop,
+ 'humanize': this.humanize,
+ 'playbackRate': this.playbackRate,
+ 'probability': this.probability
+ });
+ this._events.push(event);
+ //start the note if it should be played right now
+ this._restartEvent(event);
+ return this;
+ };
+ /**
+ * Restart the given event
+ * @param {Tone.Event} event
+ * @private
+ */
+ Tone.Part.prototype._restartEvent = function (event) {
+ this._state.forEach(function (stateEvent) {
+ if (stateEvent.state === Tone.State.Started) {
+ this._startNote(event, stateEvent.time, stateEvent.offset);
+ } else {
+ //stop the note
+ event.stop(Tone.TransportTime(stateEvent.time, 'i'));
+ }
+ }.bind(this));
+ };
+ /**
+ * Remove an event from the part. Will recursively iterate
+ * into nested parts to find the event.
+ * @param {Time} time The time of the event
+ * @param {*} value Optionally select only a specific event value
+ * @return {Tone.Part} this
+ */
+ Tone.Part.prototype.remove = function (time, value) {
+ //extract the parameters
+ if (time.hasOwnProperty('time')) {
+ value = time;
+ time = value.time;
+ }
+ time = this.toTicks(time);
+ for (var i = this._events.length - 1; i >= 0; i--) {
+ var event = this._events[i];
+ if (event instanceof Tone.Part) {
+ event.remove(time, value);
+ } else {
+ if (event.startOffset === time) {
+ if (this.isUndef(value) || !this.isUndef(value) && event.value === value) {
+ this._events.splice(i, 1);
+ event.dispose();
+ }
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Remove all of the notes from the group.
+ * @return {Tone.Part} this
+ */
+ Tone.Part.prototype.removeAll = function () {
+ this._forEach(function (event) {
+ event.dispose();
+ });
+ this._events = [];
+ return this;
+ };
+ /**
+ * Cancel scheduled state change events: i.e. "start" and "stop".
+ * @param {TimelinePosition} after The time after which to cancel the scheduled events.
+ * @return {Tone.Part} this
+ */
+ Tone.Part.prototype.cancel = function (after) {
+ after = this.toTicks(after);
+ this._forEach(function (event) {
+ event.cancel(after);
+ });
+ this._state.cancel(after);
+ return this;
+ };
+ /**
+ * Iterate over all of the events
+ * @param {Function} callback
+ * @param {Object} ctx The context
+ * @private
+ */
+ Tone.Part.prototype._forEach = function (callback, ctx) {
+ ctx = this.defaultArg(ctx, this);
+ for (var i = this._events.length - 1; i >= 0; i--) {
+ var e = this._events[i];
+ if (e instanceof Tone.Part) {
+ e._forEach(callback, ctx);
+ } else {
+ callback.call(ctx, e);
+ }
+ }
+ return this;
+ };
+ /**
+ * Set the attribute of all of the events
+ * @param {String} attr the attribute to set
+ * @param {*} value The value to set it to
+ * @private
+ */
+ Tone.Part.prototype._setAll = function (attr, value) {
+ this._forEach(function (event) {
+ event[attr] = value;
+ });
+ };
+ /**
+ * Internal tick method
+ * @param {Number} time The time of the event in seconds
+ * @private
+ */
+ Tone.Part.prototype._tick = function (time, value) {
+ if (!this.mute) {
+ this.callback(time, value);
+ }
+ };
+ /**
+ * Determine if the event should be currently looping
+ * given the loop boundries of this Part.
+ * @param {Tone.Event} event The event to test
+ * @private
+ */
+ Tone.Part.prototype._testLoopBoundries = function (event) {
+ if (event.startOffset < this._loopStart || event.startOffset >= this._loopEnd) {
+ event.cancel(0);
+ } else {
+ //reschedule it if it's stopped
+ if (event.state === Tone.State.Stopped) {
+ this._restartEvent(event);
+ }
+ }
+ };
+ /**
+ * The probability of the notes being triggered.
+ * @memberOf Tone.Part#
+ * @type {NormalRange}
+ * @name probability
+ */
+ Object.defineProperty(Tone.Part.prototype, 'probability', {
+ get: function () {
+ return this._probability;
+ },
+ set: function (prob) {
+ this._probability = prob;
+ this._setAll('probability', prob);
+ }
+ });
+ /**
+ * If set to true, will apply small random variation
+ * to the callback time. If the value is given as a time, it will randomize
+ * by that amount.
+ * @example
+ * event.humanize = true;
+ * @type {Boolean|Time}
+ * @name humanize
+ */
+ Object.defineProperty(Tone.Part.prototype, 'humanize', {
+ get: function () {
+ return this._humanize;
+ },
+ set: function (variation) {
+ this._humanize = variation;
+ this._setAll('humanize', variation);
+ }
+ });
+ /**
+ * If the part should loop or not
+ * between Tone.Part.loopStart and
+ * Tone.Part.loopEnd. An integer
+ * value corresponds to the number of
+ * loops the Part does after it starts.
+ * @memberOf Tone.Part#
+ * @type {Boolean|Positive}
+ * @name loop
+ * @example
+ * //loop the part 8 times
+ * part.loop = 8;
+ */
+ Object.defineProperty(Tone.Part.prototype, 'loop', {
+ get: function () {
+ return this._loop;
+ },
+ set: function (loop) {
+ this._loop = loop;
+ this._forEach(function (event) {
+ event._loopStart = this._loopStart;
+ event._loopEnd = this._loopEnd;
+ event.loop = loop;
+ this._testLoopBoundries(event);
+ });
+ }
+ });
+ /**
+ * The loopEnd point determines when it will
+ * loop if Tone.Part.loop is true.
+ * @memberOf Tone.Part#
+ * @type {TransportTime}
+ * @name loopEnd
+ */
+ Object.defineProperty(Tone.Part.prototype, 'loopEnd', {
+ get: function () {
+ return Tone.TransportTime(this._loopEnd, 'i').toNotation();
+ },
+ set: function (loopEnd) {
+ this._loopEnd = this.toTicks(loopEnd);
+ if (this._loop) {
+ this._forEach(function (event) {
+ event.loopEnd = loopEnd;
+ this._testLoopBoundries(event);
+ });
+ }
+ }
+ });
+ /**
+ * The loopStart point determines when it will
+ * loop if Tone.Part.loop is true.
+ * @memberOf Tone.Part#
+ * @type {TransportTime}
+ * @name loopStart
+ */
+ Object.defineProperty(Tone.Part.prototype, 'loopStart', {
+ get: function () {
+ return Tone.TransportTime(this._loopStart, 'i').toNotation();
+ },
+ set: function (loopStart) {
+ this._loopStart = this.toTicks(loopStart);
+ if (this._loop) {
+ this._forEach(function (event) {
+ event.loopStart = this.loopStart;
+ this._testLoopBoundries(event);
+ });
+ }
+ }
+ });
+ /**
+ * The playback rate of the part
+ * @memberOf Tone.Part#
+ * @type {Positive}
+ * @name playbackRate
+ */
+ Object.defineProperty(Tone.Part.prototype, 'playbackRate', {
+ get: function () {
+ return this._playbackRate;
+ },
+ set: function (rate) {
+ this._playbackRate = rate;
+ this._setAll('playbackRate', rate);
+ }
+ });
+ /**
+ * The number of scheduled notes in the part.
+ * @memberOf Tone.Part#
+ * @type {Positive}
+ * @name length
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Part.prototype, 'length', {
+ get: function () {
+ return this._events.length;
+ }
+ });
+ /**
+ * Clean up
+ * @return {Tone.Part} this
+ */
+ Tone.Part.prototype.dispose = function () {
+ this.removeAll();
+ this._state.dispose();
+ this._state = null;
+ this.callback = null;
+ this._events = null;
+ return this;
+ };
+ return Tone.Part;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.Pattern arpeggiates between the given notes
+ * in a number of patterns. See Tone.CtrlPattern for
+ * a full list of patterns.
+ * @example
+ * var pattern = new Tone.Pattern(function(time, note){
+ * //the order of the notes passed in depends on the pattern
+ * }, ["C2", "D4", "E5", "A6"], "upDown");
+ * @extends {Tone.Loop}
+ * @param {Function} callback The callback to invoke with the
+ * event.
+ * @param {Array} values The values to arpeggiate over.
+ */
+ Tone.Pattern = function () {
+ var options = this.optionsObject(arguments, [
+ 'callback',
+ 'values',
+ 'pattern'
+ ], Tone.Pattern.defaults);
+ Tone.Loop.call(this, options);
+ /**
+ * The pattern manager
+ * @type {Tone.CtrlPattern}
+ * @private
+ */
+ this._pattern = new Tone.CtrlPattern({
+ 'values': options.values,
+ 'type': options.pattern,
+ 'index': options.index
+ });
+ };
+ Tone.extend(Tone.Pattern, Tone.Loop);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.Pattern.defaults = {
+ 'pattern': Tone.CtrlPattern.Type.Up,
+ 'values': []
+ };
+ /**
+ * Internal function called when the notes should be called
+ * @param {Number} time The time the event occurs
+ * @private
+ */
+ Tone.Pattern.prototype._tick = function (time) {
+ this.callback(time, this._pattern.value);
+ this._pattern.next();
+ };
+ /**
+ * The current index in the values array.
+ * @memberOf Tone.Pattern#
+ * @type {Positive}
+ * @name index
+ */
+ Object.defineProperty(Tone.Pattern.prototype, 'index', {
+ get: function () {
+ return this._pattern.index;
+ },
+ set: function (i) {
+ this._pattern.index = i;
+ }
+ });
+ /**
+ * The array of events.
+ * @memberOf Tone.Pattern#
+ * @type {Array}
+ * @name values
+ */
+ Object.defineProperty(Tone.Pattern.prototype, 'values', {
+ get: function () {
+ return this._pattern.values;
+ },
+ set: function (vals) {
+ this._pattern.values = vals;
+ }
+ });
+ /**
+ * The current value of the pattern.
+ * @memberOf Tone.Pattern#
+ * @type {*}
+ * @name value
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Pattern.prototype, 'value', {
+ get: function () {
+ return this._pattern.value;
+ }
+ });
+ /**
+ * The pattern type. See Tone.CtrlPattern for the full list of patterns.
+ * @memberOf Tone.Pattern#
+ * @type {String}
+ * @name pattern
+ */
+ Object.defineProperty(Tone.Pattern.prototype, 'pattern', {
+ get: function () {
+ return this._pattern.type;
+ },
+ set: function (pattern) {
+ this._pattern.type = pattern;
+ }
+ });
+ /**
+ * Clean up
+ * @return {Tone.Pattern} this
+ */
+ Tone.Pattern.prototype.dispose = function () {
+ Tone.Loop.prototype.dispose.call(this);
+ this._pattern.dispose();
+ this._pattern = null;
+ };
+ return Tone.Pattern;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class A sequence is an alternate notation of a part. Instead
+ * of passing in an array of [time, event] pairs, pass
+ * in an array of events which will be spaced at the
+ * given subdivision. Sub-arrays will subdivide that beat
+ * by the number of items are in the array.
+ * Sequence notation inspiration from [Tidal](http://yaxu.org/tidal/)
+ * @param {Function} callback The callback to invoke with every note
+ * @param {Array} events The sequence
+ * @param {Time} subdivision The subdivision between which events are placed.
+ * @extends {Tone.Part}
+ * @example
+ * var seq = new Tone.Sequence(function(time, note){
+ * console.log(note);
+ * //straight quater notes
+ * }, ["C4", "E4", "G4", "A4"], "4n");
+ * @example
+ * var seq = new Tone.Sequence(function(time, note){
+ * console.log(note);
+ * //subdivisions are given as subarrays
+ * }, ["C4", ["E4", "D4", "E4"], "G4", ["A4", "G4"]]);
+ */
+ Tone.Sequence = function () {
+ var options = this.optionsObject(arguments, [
+ 'callback',
+ 'events',
+ 'subdivision'
+ ], Tone.Sequence.defaults);
+ //remove the events
+ var events = options.events;
+ delete options.events;
+ Tone.Part.call(this, options);
+ /**
+ * The subdivison of each note
+ * @type {Ticks}
+ * @private
+ */
+ this._subdivision = this.toTicks(options.subdivision);
+ //if no time was passed in, the loop end is the end of the cycle
+ if (this.isUndef(options.loopEnd) && !this.isUndef(events)) {
+ this._loopEnd = events.length * this._subdivision;
+ }
+ //defaults to looping
+ this._loop = true;
+ //add all of the events
+ if (!this.isUndef(events)) {
+ for (var i = 0; i < events.length; i++) {
+ this.add(i, events[i]);
+ }
+ }
+ };
+ Tone.extend(Tone.Sequence, Tone.Part);
+ /**
+ * The default values.
+ * @type {Object}
+ */
+ Tone.Sequence.defaults = { 'subdivision': '4n' };
+ /**
+ * The subdivision of the sequence. This can only be
+ * set in the constructor. The subdivision is the
+ * interval between successive steps.
+ * @type {Time}
+ * @memberOf Tone.Sequence#
+ * @name subdivision
+ * @readOnly
+ */
+ Object.defineProperty(Tone.Sequence.prototype, 'subdivision', {
+ get: function () {
+ return Tone.Time(this._subdivision, 'i').toNotation();
+ }
+ });
+ /**
+ * Get/Set an index of the sequence. If the index contains a subarray,
+ * a Tone.Sequence representing that sub-array will be returned.
+ * @example
+ * var sequence = new Tone.Sequence(playNote, ["E4", "C4", "F#4", ["A4", "Bb3"]])
+ * sequence.at(0)// => returns "E4"
+ * //set a value
+ * sequence.at(0, "G3");
+ * //get a nested sequence
+ * sequence.at(3).at(1)// => returns "Bb3"
+ * @param {Positive} index The index to get or set
+ * @param {*} value Optionally pass in the value to set at the given index.
+ */
+ Tone.Sequence.prototype.at = function (index, value) {
+ //if the value is an array,
+ if (this.isArray(value)) {
+ //remove the current event at that index
+ this.remove(index);
+ }
+ //call the parent's method
+ return Tone.Part.prototype.at.call(this, this._indexTime(index), value);
+ };
+ /**
+ * Add an event at an index, if there's already something
+ * at that index, overwrite it. If `value` is an array,
+ * it will be parsed as a subsequence.
+ * @param {Number} index The index to add the event to
+ * @param {*} value The value to add at that index
+ * @returns {Tone.Sequence} this
+ */
+ Tone.Sequence.prototype.add = function (index, value) {
+ if (value === null) {
+ return this;
+ }
+ if (this.isArray(value)) {
+ //make a subsequence and add that to the sequence
+ var subSubdivision = Math.round(this._subdivision / value.length);
+ value = new Tone.Sequence(this._tick.bind(this), value, Tone.Time(subSubdivision, 'i'));
+ }
+ Tone.Part.prototype.add.call(this, this._indexTime(index), value);
+ return this;
+ };
+ /**
+ * Remove a value from the sequence by index
+ * @param {Number} index The index of the event to remove
+ * @returns {Tone.Sequence} this
+ */
+ Tone.Sequence.prototype.remove = function (index, value) {
+ Tone.Part.prototype.remove.call(this, this._indexTime(index), value);
+ return this;
+ };
+ /**
+ * Get the time of the index given the Sequence's subdivision
+ * @param {Number} index
+ * @return {Time} The time of that index
+ * @private
+ */
+ Tone.Sequence.prototype._indexTime = function (index) {
+ if (index instanceof Tone.TransportTime) {
+ return index;
+ } else {
+ return Tone.TransportTime(index * this._subdivision + this.startOffset, 'i');
+ }
+ };
+ /**
+ * Clean up.
+ * @return {Tone.Sequence} this
+ */
+ Tone.Sequence.prototype.dispose = function () {
+ Tone.Part.prototype.dispose.call(this);
+ return this;
+ };
+ return Tone.Sequence;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.PulseOscillator is a pulse oscillator with control over pulse width,
+ * also known as the duty cycle. At 50% duty cycle (width = 0.5) the wave is
+ * a square and only odd-numbered harmonics are present. At all other widths
+ * even-numbered harmonics are present. Read more
+ * [here](https://wigglewave.wordpress.com/2014/08/16/pulse-waveforms-and-harmonics/).
+ *
+ * @constructor
+ * @extends {Tone.Oscillator}
+ * @param {Frequency} [frequency] The frequency of the oscillator
+ * @param {NormalRange} [width] The width of the pulse
+ * @example
+ * var pulse = new Tone.PulseOscillator("E5", 0.4).toMaster().start();
+ */
+ Tone.PulseOscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'width'
+ ], Tone.Oscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * The width of the pulse.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.width = new Tone.Signal(options.width, Tone.Type.NormalRange);
+ /**
+ * gate the width amount
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._widthGate = new Tone.Gain();
+ /**
+ * the sawtooth oscillator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._sawtooth = new Tone.Oscillator({
+ frequency: options.frequency,
+ detune: options.detune,
+ type: 'sawtooth',
+ phase: options.phase
+ });
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._sawtooth.frequency;
+ /**
+ * The detune in cents.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = this._sawtooth.detune;
+ /**
+ * Threshold the signal to turn it into a square
+ * @type {Tone.WaveShaper}
+ * @private
+ */
+ this._thresh = new Tone.WaveShaper(function (val) {
+ if (val < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+ });
+ //connections
+ this._sawtooth.chain(this._thresh, this.output);
+ this.width.chain(this._widthGate, this._thresh);
+ this._readOnly([
+ 'width',
+ 'frequency',
+ 'detune'
+ ]);
+ };
+ Tone.extend(Tone.PulseOscillator, Tone.Oscillator);
+ /**
+ * The default parameters.
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.PulseOscillator.defaults = {
+ 'frequency': 440,
+ 'detune': 0,
+ 'phase': 0,
+ 'width': 0.2
+ };
+ /**
+ * start the oscillator
+ * @param {Time} time
+ * @private
+ */
+ Tone.PulseOscillator.prototype._start = function (time) {
+ time = this.toSeconds(time);
+ this._sawtooth.start(time);
+ this._widthGate.gain.setValueAtTime(1, time);
+ };
+ /**
+ * stop the oscillator
+ * @param {Time} time
+ * @private
+ */
+ Tone.PulseOscillator.prototype._stop = function (time) {
+ time = this.toSeconds(time);
+ this._sawtooth.stop(time);
+ //the width is still connected to the output.
+ //that needs to be stopped also
+ this._widthGate.gain.setValueAtTime(0, time);
+ };
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.PulseOscillator#
+ * @type {Degrees}
+ * @name phase
+ */
+ Object.defineProperty(Tone.PulseOscillator.prototype, 'phase', {
+ get: function () {
+ return this._sawtooth.phase;
+ },
+ set: function (phase) {
+ this._sawtooth.phase = phase;
+ }
+ });
+ /**
+ * The type of the oscillator. Always returns "pulse".
+ * @readOnly
+ * @memberOf Tone.PulseOscillator#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.PulseOscillator.prototype, 'type', {
+ get: function () {
+ return 'pulse';
+ }
+ });
+ /**
+ * The partials of the waveform. Cannot set partials for this waveform type
+ * @memberOf Tone.PulseOscillator#
+ * @type {Array}
+ * @name partials
+ * @private
+ */
+ Object.defineProperty(Tone.PulseOscillator.prototype, 'partials', {
+ get: function () {
+ return [];
+ }
+ });
+ /**
+ * Clean up method.
+ * @return {Tone.PulseOscillator} this
+ */
+ Tone.PulseOscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this._sawtooth.dispose();
+ this._sawtooth = null;
+ this._writable([
+ 'width',
+ 'frequency',
+ 'detune'
+ ]);
+ this.width.dispose();
+ this.width = null;
+ this._widthGate.dispose();
+ this._widthGate = null;
+ this._thresh.dispose();
+ this._thresh = null;
+ this.frequency = null;
+ this.detune = null;
+ return this;
+ };
+ return Tone.PulseOscillator;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.PWMOscillator modulates the width of a Tone.PulseOscillator
+ * at the modulationFrequency. This has the effect of continuously
+ * changing the timbre of the oscillator by altering the harmonics
+ * generated.
+ *
+ * @extends {Tone.Oscillator}
+ * @constructor
+ * @param {Frequency} frequency The starting frequency of the oscillator.
+ * @param {Frequency} modulationFrequency The modulation frequency of the width of the pulse.
+ * @example
+ * var pwm = new Tone.PWMOscillator("Ab3", 0.3).toMaster().start();
+ */
+ Tone.PWMOscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'modulationFrequency'
+ ], Tone.PWMOscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * the pulse oscillator
+ * @type {Tone.PulseOscillator}
+ * @private
+ */
+ this._pulse = new Tone.PulseOscillator(options.modulationFrequency);
+ //change the pulse oscillator type
+ this._pulse._sawtooth.type = 'sine';
+ /**
+ * the modulator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._modulator = new Tone.Oscillator({
+ 'frequency': options.frequency,
+ 'detune': options.detune,
+ 'phase': options.phase
+ });
+ /**
+ * Scale the oscillator so it doesn't go silent
+ * at the extreme values.
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._scale = new Tone.Multiply(2);
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._modulator.frequency;
+ /**
+ * The detune of the oscillator.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = this._modulator.detune;
+ /**
+ * The modulation rate of the oscillator.
+ * @type {Frequency}
+ * @signal
+ */
+ this.modulationFrequency = this._pulse.frequency;
+ //connections
+ this._modulator.chain(this._scale, this._pulse.width);
+ this._pulse.connect(this.output);
+ this._readOnly([
+ 'modulationFrequency',
+ 'frequency',
+ 'detune'
+ ]);
+ };
+ Tone.extend(Tone.PWMOscillator, Tone.Oscillator);
+ /**
+ * default values
+ * @static
+ * @type {Object}
+ * @const
+ */
+ Tone.PWMOscillator.defaults = {
+ 'frequency': 440,
+ 'detune': 0,
+ 'phase': 0,
+ 'modulationFrequency': 0.4
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now]
+ * @private
+ */
+ Tone.PWMOscillator.prototype._start = function (time) {
+ time = this.toSeconds(time);
+ this._modulator.start(time);
+ this._pulse.start(time);
+ };
+ /**
+ * stop the oscillator
+ * @param {Time} time (optional) timing parameter
+ * @private
+ */
+ Tone.PWMOscillator.prototype._stop = function (time) {
+ time = this.toSeconds(time);
+ this._modulator.stop(time);
+ this._pulse.stop(time);
+ };
+ /**
+ * The type of the oscillator. Always returns "pwm".
+ * @readOnly
+ * @memberOf Tone.PWMOscillator#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.PWMOscillator.prototype, 'type', {
+ get: function () {
+ return 'pwm';
+ }
+ });
+ /**
+ * The partials of the waveform. Cannot set partials for this waveform type
+ * @memberOf Tone.PWMOscillator#
+ * @type {Array}
+ * @name partials
+ * @private
+ */
+ Object.defineProperty(Tone.PWMOscillator.prototype, 'partials', {
+ get: function () {
+ return [];
+ }
+ });
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.PWMOscillator#
+ * @type {number}
+ * @name phase
+ */
+ Object.defineProperty(Tone.PWMOscillator.prototype, 'phase', {
+ get: function () {
+ return this._modulator.phase;
+ },
+ set: function (phase) {
+ this._modulator.phase = phase;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.PWMOscillator} this
+ */
+ Tone.PWMOscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this._pulse.dispose();
+ this._pulse = null;
+ this._scale.dispose();
+ this._scale = null;
+ this._modulator.dispose();
+ this._modulator = null;
+ this._writable([
+ 'modulationFrequency',
+ 'frequency',
+ 'detune'
+ ]);
+ this.frequency = null;
+ this.detune = null;
+ this.modulationFrequency = null;
+ return this;
+ };
+ return Tone.PWMOscillator;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.FMOscillator
+ *
+ * @extends {Tone.Oscillator}
+ * @constructor
+ * @param {Frequency} frequency The starting frequency of the oscillator.
+ * @param {String} type The type of the carrier oscillator.
+ * @param {String} modulationType The type of the modulator oscillator.
+ * @example
+ * //a sine oscillator frequency-modulated by a square wave
+ * var fmOsc = new Tone.FMOscillator("Ab3", "sine", "square").toMaster().start();
+ */
+ Tone.FMOscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'type',
+ 'modulationType'
+ ], Tone.FMOscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * The carrier oscillator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._carrier = new Tone.Oscillator(options.frequency, options.type);
+ /**
+ * The oscillator's frequency
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The detune control signal.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = this._carrier.detune;
+ this.detune.value = options.detune;
+ /**
+ * The modulation index which is in essence the depth or amount of the modulation. In other terms it is the
+ * ratio of the frequency of the modulating signal (mf) to the amplitude of the
+ * modulating signal (ma) -- as in ma/mf.
+ * @type {Positive}
+ * @signal
+ */
+ this.modulationIndex = new Tone.Multiply(options.modulationIndex);
+ this.modulationIndex.units = Tone.Type.Positive;
+ /**
+ * The modulating oscillator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._modulator = new Tone.Oscillator(options.frequency, options.modulationType);
+ /**
+ * Harmonicity is the frequency ratio between the carrier and the modulator oscillators.
+ * A harmonicity of 1 gives both oscillators the same frequency.
+ * Harmonicity = 2 means a change of an octave.
+ * @type {Positive}
+ * @signal
+ * @example
+ * //pitch the modulator an octave below carrier
+ * synth.harmonicity.value = 0.5;
+ */
+ this.harmonicity = new Tone.Multiply(options.harmonicity);
+ this.harmonicity.units = Tone.Type.Positive;
+ /**
+ * the node where the modulation happens
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._modulationNode = new Tone.Gain(0);
+ //connections
+ this.frequency.connect(this._carrier.frequency);
+ this.frequency.chain(this.harmonicity, this._modulator.frequency);
+ this.frequency.chain(this.modulationIndex, this._modulationNode);
+ this._modulator.connect(this._modulationNode.gain);
+ this._modulationNode.connect(this._carrier.frequency);
+ this._carrier.connect(this.output);
+ this.detune.connect(this._modulator.detune);
+ this.phase = options.phase;
+ this._readOnly([
+ 'modulationIndex',
+ 'frequency',
+ 'detune',
+ 'harmonicity'
+ ]);
+ };
+ Tone.extend(Tone.FMOscillator, Tone.Oscillator);
+ /**
+ * default values
+ * @static
+ * @type {Object}
+ * @const
+ */
+ Tone.FMOscillator.defaults = {
+ 'frequency': 440,
+ 'detune': 0,
+ 'phase': 0,
+ 'modulationIndex': 2,
+ 'modulationType': 'square',
+ 'harmonicity': 1
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now]
+ * @private
+ */
+ Tone.FMOscillator.prototype._start = function (time) {
+ time = this.toSeconds(time);
+ this._modulator.start(time);
+ this._carrier.start(time);
+ };
+ /**
+ * stop the oscillator
+ * @param {Time} time (optional) timing parameter
+ * @private
+ */
+ Tone.FMOscillator.prototype._stop = function (time) {
+ time = this.toSeconds(time);
+ this._modulator.stop(time);
+ this._carrier.stop(time);
+ };
+ /**
+ * The type of the carrier oscillator
+ * @memberOf Tone.FMOscillator#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.FMOscillator.prototype, 'type', {
+ get: function () {
+ return this._carrier.type;
+ },
+ set: function (type) {
+ this._carrier.type = type;
+ }
+ });
+ /**
+ * The type of the modulator oscillator
+ * @memberOf Tone.FMOscillator#
+ * @type {String}
+ * @name modulationType
+ */
+ Object.defineProperty(Tone.FMOscillator.prototype, 'modulationType', {
+ get: function () {
+ return this._modulator.type;
+ },
+ set: function (type) {
+ this._modulator.type = type;
+ }
+ });
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.FMOscillator#
+ * @type {number}
+ * @name phase
+ */
+ Object.defineProperty(Tone.FMOscillator.prototype, 'phase', {
+ get: function () {
+ return this._carrier.phase;
+ },
+ set: function (phase) {
+ this._carrier.phase = phase;
+ this._modulator.phase = phase;
+ }
+ });
+ /**
+ * The partials of the carrier waveform. A partial represents
+ * the amplitude at a harmonic. The first harmonic is the
+ * fundamental frequency, the second is the octave and so on
+ * following the harmonic series.
+ * Setting this value will automatically set the type to "custom".
+ * The value is an empty array when the type is not "custom".
+ * @memberOf Tone.FMOscillator#
+ * @type {Array}
+ * @name partials
+ * @example
+ * osc.partials = [1, 0.2, 0.01];
+ */
+ Object.defineProperty(Tone.FMOscillator.prototype, 'partials', {
+ get: function () {
+ return this._carrier.partials;
+ },
+ set: function (partials) {
+ this._carrier.partials = partials;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.FMOscillator} this
+ */
+ Tone.FMOscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this._writable([
+ 'modulationIndex',
+ 'frequency',
+ 'detune',
+ 'harmonicity'
+ ]);
+ this.frequency.dispose();
+ this.frequency = null;
+ this.detune = null;
+ this.harmonicity.dispose();
+ this.harmonicity = null;
+ this._carrier.dispose();
+ this._carrier = null;
+ this._modulator.dispose();
+ this._modulator = null;
+ this._modulationNode.dispose();
+ this._modulationNode = null;
+ this.modulationIndex.dispose();
+ this.modulationIndex = null;
+ return this;
+ };
+ return Tone.FMOscillator;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.AMOscillator
+ *
+ * @extends {Tone.Oscillator}
+ * @constructor
+ * @param {Frequency} frequency The starting frequency of the oscillator.
+ * @param {String} type The type of the carrier oscillator.
+ * @param {String} modulationType The type of the modulator oscillator.
+ * @example
+ * //a sine oscillator frequency-modulated by a square wave
+ * var fmOsc = new Tone.AMOscillator("Ab3", "sine", "square").toMaster().start();
+ */
+ Tone.AMOscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'type',
+ 'modulationType'
+ ], Tone.AMOscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * The carrier oscillator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._carrier = new Tone.Oscillator(options.frequency, options.type);
+ /**
+ * The oscillator's frequency
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this._carrier.frequency;
+ /**
+ * The detune control signal.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = this._carrier.detune;
+ this.detune.value = options.detune;
+ /**
+ * The modulating oscillator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._modulator = new Tone.Oscillator(options.frequency, options.modulationType);
+ /**
+ * convert the -1,1 output to 0,1
+ * @type {Tone.AudioToGain}
+ * @private
+ */
+ this._modulationScale = new Tone.AudioToGain();
+ /**
+ * Harmonicity is the frequency ratio between the carrier and the modulator oscillators.
+ * A harmonicity of 1 gives both oscillators the same frequency.
+ * Harmonicity = 2 means a change of an octave.
+ * @type {Positive}
+ * @signal
+ * @example
+ * //pitch the modulator an octave below carrier
+ * synth.harmonicity.value = 0.5;
+ */
+ this.harmonicity = new Tone.Multiply(options.harmonicity);
+ this.harmonicity.units = Tone.Type.Positive;
+ /**
+ * the node where the modulation happens
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._modulationNode = new Tone.Gain(0);
+ //connections
+ this.frequency.chain(this.harmonicity, this._modulator.frequency);
+ this.detune.connect(this._modulator.detune);
+ this._modulator.chain(this._modulationScale, this._modulationNode.gain);
+ this._carrier.chain(this._modulationNode, this.output);
+ this.phase = options.phase;
+ this._readOnly([
+ 'frequency',
+ 'detune',
+ 'harmonicity'
+ ]);
+ };
+ Tone.extend(Tone.AMOscillator, Tone.Oscillator);
+ /**
+ * default values
+ * @static
+ * @type {Object}
+ * @const
+ */
+ Tone.AMOscillator.defaults = {
+ 'frequency': 440,
+ 'detune': 0,
+ 'phase': 0,
+ 'modulationType': 'square',
+ 'harmonicity': 1
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now]
+ * @private
+ */
+ Tone.AMOscillator.prototype._start = function (time) {
+ time = this.toSeconds(time);
+ this._modulator.start(time);
+ this._carrier.start(time);
+ };
+ /**
+ * stop the oscillator
+ * @param {Time} time (optional) timing parameter
+ * @private
+ */
+ Tone.AMOscillator.prototype._stop = function (time) {
+ time = this.toSeconds(time);
+ this._modulator.stop(time);
+ this._carrier.stop(time);
+ };
+ /**
+ * The type of the carrier oscillator
+ * @memberOf Tone.AMOscillator#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.AMOscillator.prototype, 'type', {
+ get: function () {
+ return this._carrier.type;
+ },
+ set: function (type) {
+ this._carrier.type = type;
+ }
+ });
+ /**
+ * The type of the modulator oscillator
+ * @memberOf Tone.AMOscillator#
+ * @type {string}
+ * @name modulationType
+ */
+ Object.defineProperty(Tone.AMOscillator.prototype, 'modulationType', {
+ get: function () {
+ return this._modulator.type;
+ },
+ set: function (type) {
+ this._modulator.type = type;
+ }
+ });
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.AMOscillator#
+ * @type {number}
+ * @name phase
+ */
+ Object.defineProperty(Tone.AMOscillator.prototype, 'phase', {
+ get: function () {
+ return this._carrier.phase;
+ },
+ set: function (phase) {
+ this._carrier.phase = phase;
+ this._modulator.phase = phase;
+ }
+ });
+ /**
+ * The partials of the carrier waveform. A partial represents
+ * the amplitude at a harmonic. The first harmonic is the
+ * fundamental frequency, the second is the octave and so on
+ * following the harmonic series.
+ * Setting this value will automatically set the type to "custom".
+ * The value is an empty array when the type is not "custom".
+ * @memberOf Tone.AMOscillator#
+ * @type {Array}
+ * @name partials
+ * @example
+ * osc.partials = [1, 0.2, 0.01];
+ */
+ Object.defineProperty(Tone.AMOscillator.prototype, 'partials', {
+ get: function () {
+ return this._carrier.partials;
+ },
+ set: function (partials) {
+ this._carrier.partials = partials;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.AMOscillator} this
+ */
+ Tone.AMOscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'detune',
+ 'harmonicity'
+ ]);
+ this.frequency = null;
+ this.detune = null;
+ this.harmonicity.dispose();
+ this.harmonicity = null;
+ this._carrier.dispose();
+ this._carrier = null;
+ this._modulator.dispose();
+ this._modulator = null;
+ this._modulationNode.dispose();
+ this._modulationNode = null;
+ this._modulationScale.dispose();
+ this._modulationScale = null;
+ return this;
+ };
+ return Tone.AMOscillator;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.FatOscillator
+ *
+ * @extends {Tone.Oscillator}
+ * @constructor
+ * @param {Frequency} frequency The starting frequency of the oscillator.
+ * @param {String} type The type of the carrier oscillator.
+ * @param {String} modulationType The type of the modulator oscillator.
+ * @example
+ * //a sine oscillator frequency-modulated by a square wave
+ * var fmOsc = new Tone.FatOscillator("Ab3", "sine", "square").toMaster().start();
+ */
+ Tone.FatOscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'type',
+ 'spread'
+ ], Tone.FatOscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * The oscillator's frequency
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The detune control signal.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
+ /**
+ * The array of oscillators
+ * @type {Array}
+ * @private
+ */
+ this._oscillators = [];
+ /**
+ * The total spread of the oscillators
+ * @type {Cents}
+ * @private
+ */
+ this._spread = options.spread;
+ /**
+ * The type of the oscillator
+ * @type {String}
+ * @private
+ */
+ this._type = options.type;
+ /**
+ * The phase of the oscillators
+ * @type {Degrees}
+ * @private
+ */
+ this._phase = options.phase;
+ /**
+ * The partials array
+ * @type {Array}
+ * @private
+ */
+ this._partials = this.defaultArg(options.partials, []);
+ //set the count initially
+ this.count = options.count;
+ this._readOnly([
+ 'frequency',
+ 'detune'
+ ]);
+ };
+ Tone.extend(Tone.FatOscillator, Tone.Oscillator);
+ /**
+ * default values
+ * @static
+ * @type {Object}
+ * @const
+ */
+ Tone.FatOscillator.defaults = {
+ 'frequency': 440,
+ 'detune': 0,
+ 'phase': 0,
+ 'spread': 20,
+ 'count': 3,
+ 'type': 'sawtooth'
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now]
+ * @private
+ */
+ Tone.FatOscillator.prototype._start = function (time) {
+ time = this.toSeconds(time);
+ this._forEach(function (osc) {
+ osc.start(time);
+ });
+ };
+ /**
+ * stop the oscillator
+ * @param {Time} time (optional) timing parameter
+ * @private
+ */
+ Tone.FatOscillator.prototype._stop = function (time) {
+ time = this.toSeconds(time);
+ this._forEach(function (osc) {
+ osc.stop(time);
+ });
+ };
+ /**
+ * Iterate over all of the oscillators
+ * @param {Function} iterator The iterator function
+ * @private
+ */
+ Tone.FatOscillator.prototype._forEach = function (iterator) {
+ for (var i = 0; i < this._oscillators.length; i++) {
+ iterator.call(this, this._oscillators[i], i);
+ }
+ };
+ /**
+ * The type of the carrier oscillator
+ * @memberOf Tone.FatOscillator#
+ * @type {string}
+ * @name type
+ */
+ Object.defineProperty(Tone.FatOscillator.prototype, 'type', {
+ get: function () {
+ return this._type;
+ },
+ set: function (type) {
+ this._type = type;
+ this._forEach(function (osc) {
+ osc.type = type;
+ });
+ }
+ });
+ /**
+ * The detune spread between the oscillators. If "count" is
+ * set to 3 oscillators and the "spread" is set to 40,
+ * the three oscillators would be detuned like this: [-20, 0, 20]
+ * for a total detune spread of 40 cents.
+ * @memberOf Tone.FatOscillator#
+ * @type {Cents}
+ * @name spread
+ */
+ Object.defineProperty(Tone.FatOscillator.prototype, 'spread', {
+ get: function () {
+ return this._spread;
+ },
+ set: function (spread) {
+ this._spread = spread;
+ if (this._oscillators.length > 1) {
+ var start = -spread / 2;
+ var step = spread / (this._oscillators.length - 1);
+ this._forEach(function (osc, i) {
+ osc.detune.value = start + step * i;
+ });
+ }
+ }
+ });
+ /**
+ * The number of detuned oscillators
+ * @memberOf Tone.FatOscillator#
+ * @type {Number}
+ * @name count
+ */
+ Object.defineProperty(Tone.FatOscillator.prototype, 'count', {
+ get: function () {
+ return this._oscillators.length;
+ },
+ set: function (count) {
+ count = Math.max(count, 1);
+ if (this._oscillators.length !== count) {
+ // var partials = this.partials;
+ // var type = this.type;
+ //dispose the previous oscillators
+ this._forEach(function (osc) {
+ osc.dispose();
+ });
+ this._oscillators = [];
+ for (var i = 0; i < count; i++) {
+ var osc = new Tone.Oscillator();
+ if (this.type === Tone.Oscillator.Type.Custom) {
+ osc.partials = this._partials;
+ } else {
+ osc.type = this._type;
+ }
+ osc.phase = this._phase;
+ osc.volume.value = -6 - count;
+ this.frequency.connect(osc.frequency);
+ this.detune.connect(osc.detune);
+ osc.connect(this.output);
+ this._oscillators[i] = osc;
+ }
+ //set the spread
+ this.spread = this._spread;
+ if (this.state === Tone.State.Started) {
+ this._forEach(function (osc) {
+ osc.start();
+ });
+ }
+ }
+ }
+ });
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.FatOscillator#
+ * @type {Number}
+ * @name phase
+ */
+ Object.defineProperty(Tone.FatOscillator.prototype, 'phase', {
+ get: function () {
+ return this._phase;
+ },
+ set: function (phase) {
+ this._phase = phase;
+ this._forEach(function (osc) {
+ osc.phase = phase;
+ });
+ }
+ });
+ /**
+ * The partials of the carrier waveform. A partial represents
+ * the amplitude at a harmonic. The first harmonic is the
+ * fundamental frequency, the second is the octave and so on
+ * following the harmonic series.
+ * Setting this value will automatically set the type to "custom".
+ * The value is an empty array when the type is not "custom".
+ * @memberOf Tone.FatOscillator#
+ * @type {Array}
+ * @name partials
+ * @example
+ * osc.partials = [1, 0.2, 0.01];
+ */
+ Object.defineProperty(Tone.FatOscillator.prototype, 'partials', {
+ get: function () {
+ return this._partials;
+ },
+ set: function (partials) {
+ this._partials = partials;
+ this._type = Tone.Oscillator.Type.Custom;
+ this._forEach(function (osc) {
+ osc.partials = partials;
+ });
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.FatOscillator} this
+ */
+ Tone.FatOscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'detune'
+ ]);
+ this.frequency.dispose();
+ this.frequency = null;
+ this.detune.dispose();
+ this.detune = null;
+ this._forEach(function (osc) {
+ osc.dispose();
+ });
+ this._oscillators = null;
+ this._partials = null;
+ return this;
+ };
+ return Tone.FatOscillator;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.OmniOscillator aggregates Tone.Oscillator, Tone.PulseOscillator,
+ * Tone.PWMOscillator, Tone.FMOscillator, Tone.AMOscillator, and Tone.FatOscillator
+ * into one class. The oscillator class can be changed by setting the `type`.
+ * `omniOsc.type = "pwm"` will set it to the Tone.PWMOscillator. Prefixing
+ * any of the basic types ("sine", "square4", etc.) with "fm", "am", or "fat"
+ * will use the FMOscillator, AMOscillator or FatOscillator respectively.
+ * For example: `omniOsc.type = "fatsawtooth"` will create set the oscillator
+ * to a FatOscillator of type "sawtooth".
+ *
+ * @extends {Tone.Oscillator}
+ * @constructor
+ * @param {Frequency} frequency The initial frequency of the oscillator.
+ * @param {String} type The type of the oscillator.
+ * @example
+ * var omniOsc = new Tone.OmniOscillator("C#4", "pwm");
+ */
+ Tone.OmniOscillator = function () {
+ var options = this.optionsObject(arguments, [
+ 'frequency',
+ 'type'
+ ], Tone.OmniOscillator.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The detune control
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
+ /**
+ * the type of the oscillator source
+ * @type {String}
+ * @private
+ */
+ this._sourceType = undefined;
+ /**
+ * the oscillator
+ * @type {Tone.Oscillator}
+ * @private
+ */
+ this._oscillator = null;
+ //set the oscillator
+ this.type = options.type;
+ this._readOnly([
+ 'frequency',
+ 'detune'
+ ]);
+ //set the options
+ this.set(options);
+ };
+ Tone.extend(Tone.OmniOscillator, Tone.Oscillator);
+ /**
+ * default values
+ * @static
+ * @type {Object}
+ * @const
+ */
+ Tone.OmniOscillator.defaults = {
+ 'frequency': 440,
+ 'detune': 0,
+ 'type': 'sine',
+ 'phase': 0
+ };
+ /**
+ * @enum {String}
+ * @private
+ */
+ var OmniOscType = {
+ Pulse: 'PulseOscillator',
+ PWM: 'PWMOscillator',
+ Osc: 'Oscillator',
+ FM: 'FMOscillator',
+ AM: 'AMOscillator',
+ Fat: 'FatOscillator'
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now] the time to start the oscillator
+ * @private
+ */
+ Tone.OmniOscillator.prototype._start = function (time) {
+ this._oscillator.start(time);
+ };
+ /**
+ * start the oscillator
+ * @param {Time} [time=now] the time to start the oscillator
+ * @private
+ */
+ Tone.OmniOscillator.prototype._stop = function (time) {
+ this._oscillator.stop(time);
+ };
+ /**
+ * The type of the oscillator. Can be any of the basic types: sine, square, triangle, sawtooth. Or
+ * prefix the basic types with "fm", "am", or "fat" to use the FMOscillator, AMOscillator or FatOscillator
+ * types. The oscillator could also be set to "pwm" or "pulse". All of the parameters of the
+ * oscillator's class are accessible when the oscillator is set to that type, but throws an error
+ * when it's not.
+ *
+ * @memberOf Tone.OmniOscillator#
+ * @type {String}
+ * @name type
+ * @example
+ * omniOsc.type = "pwm";
+ * //modulationFrequency is parameter which is available
+ * //only when the type is "pwm".
+ * omniOsc.modulationFrequency.value = 0.5;
+ * @example
+ * //an square wave frequency modulated by a sawtooth
+ * omniOsc.type = "fmsquare";
+ * omniOsc.modulationType = "sawtooth";
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'type', {
+ get: function () {
+ var prefix = '';
+ if (this._sourceType === OmniOscType.FM) {
+ prefix = 'fm';
+ } else if (this._sourceType === OmniOscType.AM) {
+ prefix = 'am';
+ } else if (this._sourceType === OmniOscType.Fat) {
+ prefix = 'fat';
+ }
+ return prefix + this._oscillator.type;
+ },
+ set: function (type) {
+ if (type.substr(0, 2) === 'fm') {
+ this._createNewOscillator(OmniOscType.FM);
+ this._oscillator.type = type.substr(2);
+ } else if (type.substr(0, 2) === 'am') {
+ this._createNewOscillator(OmniOscType.AM);
+ this._oscillator.type = type.substr(2);
+ } else if (type.substr(0, 3) === 'fat') {
+ this._createNewOscillator(OmniOscType.Fat);
+ this._oscillator.type = type.substr(3);
+ } else if (type === 'pwm') {
+ this._createNewOscillator(OmniOscType.PWM);
+ } else if (type === 'pulse') {
+ this._createNewOscillator(OmniOscType.Pulse);
+ } else {
+ this._createNewOscillator(OmniOscType.Osc);
+ this._oscillator.type = type;
+ }
+ }
+ });
+ /**
+ * The partials of the waveform. A partial represents
+ * the amplitude at a harmonic. The first harmonic is the
+ * fundamental frequency, the second is the octave and so on
+ * following the harmonic series.
+ * Setting this value will automatically set the type to "custom".
+ * The value is an empty array when the type is not "custom".
+ * This is not available on "pwm" and "pulse" oscillator types.
+ * @memberOf Tone.OmniOscillator#
+ * @type {Array}
+ * @name partials
+ * @example
+ * osc.partials = [1, 0.2, 0.01];
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'partials', {
+ get: function () {
+ return this._oscillator.partials;
+ },
+ set: function (partials) {
+ this._oscillator.partials = partials;
+ }
+ });
+ /**
+ * Set a member/attribute of the oscillator.
+ * @param {Object|String} params
+ * @param {number=} value
+ * @param {Time=} rampTime
+ * @returns {Tone.OmniOscillator} this
+ */
+ Tone.OmniOscillator.prototype.set = function (params, value) {
+ //make sure the type is set first
+ if (params === 'type') {
+ this.type = value;
+ } else if (this.isObject(params) && params.hasOwnProperty('type')) {
+ this.type = params.type;
+ }
+ //then set the rest
+ Tone.prototype.set.apply(this, arguments);
+ return this;
+ };
+ /**
+ * connect the oscillator to the frequency and detune signals
+ * @private
+ */
+ Tone.OmniOscillator.prototype._createNewOscillator = function (oscType) {
+ if (oscType !== this._sourceType) {
+ this._sourceType = oscType;
+ var OscillatorConstructor = Tone[oscType];
+ //short delay to avoid clicks on the change
+ var now = this.now() + this.blockTime;
+ if (this._oscillator !== null) {
+ var oldOsc = this._oscillator;
+ oldOsc.stop(now);
+ //dispose the old one
+ setTimeout(function () {
+ oldOsc.dispose();
+ oldOsc = null;
+ }, this.blockTime * 1000);
+ }
+ this._oscillator = new OscillatorConstructor();
+ this.frequency.connect(this._oscillator.frequency);
+ this.detune.connect(this._oscillator.detune);
+ this._oscillator.connect(this.output);
+ if (this.state === Tone.State.Started) {
+ this._oscillator.start(now);
+ }
+ }
+ };
+ /**
+ * The phase of the oscillator in degrees.
+ * @memberOf Tone.OmniOscillator#
+ * @type {Degrees}
+ * @name phase
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'phase', {
+ get: function () {
+ return this._oscillator.phase;
+ },
+ set: function (phase) {
+ this._oscillator.phase = phase;
+ }
+ });
+ /**
+ * The width of the oscillator (only if the oscillator is set to "pulse")
+ * @memberOf Tone.OmniOscillator#
+ * @type {NormalRange}
+ * @signal
+ * @name width
+ * @example
+ * var omniOsc = new Tone.OmniOscillator(440, "pulse");
+ * //can access the width attribute only if type === "pulse"
+ * omniOsc.width.value = 0.2;
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'width', {
+ get: function () {
+ if (this._sourceType === OmniOscType.Pulse) {
+ return this._oscillator.width;
+ }
+ }
+ });
+ /**
+ * The number of detuned oscillators
+ * @memberOf Tone.OmniOscillator#
+ * @type {Number}
+ * @name count
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'count', {
+ get: function () {
+ if (this._sourceType === OmniOscType.Fat) {
+ return this._oscillator.count;
+ }
+ },
+ set: function (count) {
+ if (this._sourceType === OmniOscType.Fat) {
+ this._oscillator.count = count;
+ }
+ }
+ });
+ /**
+ * The detune spread between the oscillators. If "count" is
+ * set to 3 oscillators and the "spread" is set to 40,
+ * the three oscillators would be detuned like this: [-20, 0, 20]
+ * for a total detune spread of 40 cents. See Tone.FatOscillator
+ * for more info.
+ * @memberOf Tone.OmniOscillator#
+ * @type {Cents}
+ * @name spread
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'spread', {
+ get: function () {
+ if (this._sourceType === OmniOscType.Fat) {
+ return this._oscillator.spread;
+ }
+ },
+ set: function (spread) {
+ if (this._sourceType === OmniOscType.Fat) {
+ this._oscillator.spread = spread;
+ }
+ }
+ });
+ /**
+ * The type of the modulator oscillator. Only if the oscillator
+ * is set to "am" or "fm" types. see. Tone.AMOscillator or Tone.FMOscillator
+ * for more info.
+ * @memberOf Tone.OmniOscillator#
+ * @type {String}
+ * @name modulationType
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'modulationType', {
+ get: function () {
+ if (this._sourceType === OmniOscType.FM || this._sourceType === OmniOscType.AM) {
+ return this._oscillator.modulationType;
+ }
+ },
+ set: function (mType) {
+ if (this._sourceType === OmniOscType.FM || this._sourceType === OmniOscType.AM) {
+ this._oscillator.modulationType = mType;
+ }
+ }
+ });
+ /**
+ * The modulation index which is in essence the depth or amount of the modulation. In other terms it is the
+ * ratio of the frequency of the modulating signal (mf) to the amplitude of the
+ * modulating signal (ma) -- as in ma/mf.
+ * See Tone.FMOscillator for more info.
+ * @type {Positive}
+ * @signal
+ * @name modulationIndex
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'modulationIndex', {
+ get: function () {
+ if (this._sourceType === OmniOscType.FM) {
+ return this._oscillator.modulationIndex;
+ }
+ }
+ });
+ /**
+ * Harmonicity is the frequency ratio between the carrier and the modulator oscillators.
+ * A harmonicity of 1 gives both oscillators the same frequency.
+ * Harmonicity = 2 means a change of an octave. See Tone.AMOscillator or Tone.FMOscillator
+ * for more info.
+ * @memberOf Tone.OmniOscillator#
+ * @signal
+ * @type {Positive}
+ * @name harmonicity
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'harmonicity', {
+ get: function () {
+ if (this._sourceType === OmniOscType.FM || this._sourceType === OmniOscType.AM) {
+ return this._oscillator.harmonicity;
+ }
+ }
+ });
+ /**
+ * The modulationFrequency Signal of the oscillator
+ * (only if the oscillator type is set to pwm). See
+ * Tone.PWMOscillator for more info.
+ * @memberOf Tone.OmniOscillator#
+ * @type {Frequency}
+ * @signal
+ * @name modulationFrequency
+ * @example
+ * var omniOsc = new Tone.OmniOscillator(440, "pwm");
+ * //can access the modulationFrequency attribute only if type === "pwm"
+ * omniOsc.modulationFrequency.value = 0.2;
+ */
+ Object.defineProperty(Tone.OmniOscillator.prototype, 'modulationFrequency', {
+ get: function () {
+ if (this._sourceType === OmniOscType.PWM) {
+ return this._oscillator.modulationFrequency;
+ }
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.OmniOscillator} this
+ */
+ Tone.OmniOscillator.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'detune'
+ ]);
+ this.detune.dispose();
+ this.detune = null;
+ this.frequency.dispose();
+ this.frequency = null;
+ this._oscillator.dispose();
+ this._oscillator = null;
+ this._sourceType = null;
+ return this;
+ };
+ return Tone.OmniOscillator;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Base-class for all instruments
+ *
+ * @constructor
+ * @extends {Tone}
+ */
+ Tone.Instrument = function (options) {
+ //get the defaults
+ options = this.defaultArg(options, Tone.Instrument.defaults);
+ /**
+ * The output and volume triming node
+ * @type {Tone.Volume}
+ * @private
+ */
+ this._volume = this.output = new Tone.Volume(options.volume);
+ /**
+ * The volume of the output in decibels.
+ * @type {Decibels}
+ * @signal
+ * @example
+ * source.volume.value = -6;
+ */
+ this.volume = this._volume.volume;
+ this._readOnly('volume');
+ };
+ Tone.extend(Tone.Instrument);
+ /**
+ * the default attributes
+ * @type {object}
+ */
+ Tone.Instrument.defaults = {
+ /** the volume of the output in decibels */
+ 'volume': 0
+ };
+ /**
+ * @abstract
+ * @param {string|number} note the note to trigger
+ * @param {Time} [time=now] the time to trigger the ntoe
+ * @param {number} [velocity=1] the velocity to trigger the note
+ */
+ Tone.Instrument.prototype.triggerAttack = Tone.noOp;
+ /**
+ * @abstract
+ * @param {Time} [time=now] when to trigger the release
+ */
+ Tone.Instrument.prototype.triggerRelease = Tone.noOp;
+ /**
+ * Trigger the attack and then the release after the duration.
+ * @param {Frequency} note The note to trigger.
+ * @param {Time} duration How long the note should be held for before
+ * triggering the release. This value must be greater than 0.
+ * @param {Time} [time=now] When the note should be triggered.
+ * @param {NormalRange} [velocity=1] The velocity the note should be triggered at.
+ * @returns {Tone.Instrument} this
+ * @example
+ * //trigger "C4" for the duration of an 8th note
+ * synth.triggerAttackRelease("C4", "8n");
+ */
+ Tone.Instrument.prototype.triggerAttackRelease = function (note, duration, time, velocity) {
+ if (this.isUndef(time)) {
+ time = this.now() + this.blockTime;
+ } else {
+ time = this.toSeconds(time);
+ }
+ duration = this.toSeconds(duration);
+ this.triggerAttack(note, time, velocity);
+ this.triggerRelease(time + duration);
+ return this;
+ };
+ /**
+ * clean up
+ * @returns {Tone.Instrument} this
+ */
+ Tone.Instrument.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._volume.dispose();
+ this._volume = null;
+ this._writable(['volume']);
+ this.volume = null;
+ return this;
+ };
+ return Tone.Instrument;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class This is an abstract base class for other monophonic instruments to
+ * extend. IMPORTANT: It does not make any sound on its own and
+ * shouldn't be directly instantiated.
+ *
+ * @constructor
+ * @abstract
+ * @extends {Tone.Instrument}
+ */
+ Tone.Monophonic = function (options) {
+ //get the defaults
+ options = this.defaultArg(options, Tone.Monophonic.defaults);
+ Tone.Instrument.call(this, options);
+ /**
+ * The glide time between notes.
+ * @type {Time}
+ */
+ this.portamento = options.portamento;
+ };
+ Tone.extend(Tone.Monophonic, Tone.Instrument);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Monophonic.defaults = { 'portamento': 0 };
+ /**
+ * Trigger the attack of the note optionally with a given velocity.
+ *
+ *
+ * @param {Frequency} note The note to trigger.
+ * @param {Time} [time=now] When the note should start.
+ * @param {number} [velocity=1] velocity The velocity scaler
+ * determines how "loud" the note
+ * will be triggered.
+ * @returns {Tone.Monophonic} this
+ * @example
+ * synth.triggerAttack("C4");
+ * @example
+ * //trigger the note a half second from now at half velocity
+ * synth.triggerAttack("C4", "+0.5", 0.5);
+ */
+ Tone.Monophonic.prototype.triggerAttack = function (note, time, velocity) {
+ if (this.isUndef(time)) {
+ time = this.now() + this.blockTime;
+ } else {
+ time = this.toSeconds(time);
+ }
+ this._triggerEnvelopeAttack(time, velocity);
+ this.setNote(note, time);
+ return this;
+ };
+ /**
+ * Trigger the release portion of the envelope
+ * @param {Time} [time=now] If no time is given, the release happens immediatly
+ * @returns {Tone.Monophonic} this
+ * @example
+ * synth.triggerRelease();
+ */
+ Tone.Monophonic.prototype.triggerRelease = function (time) {
+ if (this.isUndef(time)) {
+ time = this.now() + this.blockTime;
+ } else {
+ time = this.toSeconds(time);
+ }
+ this._triggerEnvelopeRelease(time);
+ return this;
+ };
+ /**
+ * override this method with the actual method
+ * @abstract
+ * @private
+ */
+ Tone.Monophonic.prototype._triggerEnvelopeAttack = function () {
+ };
+ /**
+ * override this method with the actual method
+ * @abstract
+ * @private
+ */
+ Tone.Monophonic.prototype._triggerEnvelopeRelease = function () {
+ };
+ /**
+ * Set the note at the given time. If no time is given, the note
+ * will set immediately.
+ * @param {Frequency} note The note to change to.
+ * @param {Time} [time=now] The time when the note should be set.
+ * @returns {Tone.Monophonic} this
+ * @example
+ * //change to F#6 in one quarter note from now.
+ * synth.setNote("F#6", "+4n");
+ * @example
+ * //change to Bb4 right now
+ * synth.setNote("Bb4");
+ */
+ Tone.Monophonic.prototype.setNote = function (note, time) {
+ time = this.toSeconds(time);
+ if (this.portamento > 0) {
+ var currentNote = this.frequency.value;
+ this.frequency.setValueAtTime(currentNote, time);
+ var portTime = this.toSeconds(this.portamento);
+ this.frequency.exponentialRampToValueAtTime(note, time + portTime);
+ } else {
+ this.frequency.setValueAtTime(note, time);
+ }
+ return this;
+ };
+ return Tone.Monophonic;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Synth is composed simply of a Tone.OmniOscillator
+ * routed through a Tone.AmplitudeEnvelope.
+ * <img src="https://docs.google.com/drawings/d/1-1_0YW2Z1J2EPI36P8fNCMcZG7N1w1GZluPs4og4evo/pub?w=1163&h=231">
+ *
+ * @constructor
+ * @extends {Tone.Monophonic}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var synth = new Tone.Synth().toMaster();
+ * synth.triggerAttackRelease("C4", "8n");
+ */
+ Tone.Synth = function (options) {
+ //get the defaults
+ options = this.defaultArg(options, Tone.Synth.defaults);
+ Tone.Monophonic.call(this, options);
+ /**
+ * The oscillator.
+ * @type {Tone.OmniOscillator}
+ */
+ this.oscillator = new Tone.OmniOscillator(options.oscillator);
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this.oscillator.frequency;
+ /**
+ * The detune control.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = this.oscillator.detune;
+ /**
+ * The amplitude envelope.
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.envelope = new Tone.AmplitudeEnvelope(options.envelope);
+ //connect the oscillators to the output
+ this.oscillator.chain(this.envelope, this.output);
+ //start the oscillators
+ this.oscillator.start();
+ this._readOnly([
+ 'oscillator',
+ 'frequency',
+ 'detune',
+ 'envelope'
+ ]);
+ };
+ Tone.extend(Tone.Synth, Tone.Monophonic);
+ /**
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.Synth.defaults = {
+ 'oscillator': { 'type': 'triangle' },
+ 'envelope': {
+ 'attack': 0.005,
+ 'decay': 0.1,
+ 'sustain': 0.3,
+ 'release': 1
+ }
+ };
+ /**
+ * start the attack portion of the envelope
+ * @param {Time} [time=now] the time the attack should start
+ * @param {number} [velocity=1] the velocity of the note (0-1)
+ * @returns {Tone.Synth} this
+ * @private
+ */
+ Tone.Synth.prototype._triggerEnvelopeAttack = function (time, velocity) {
+ //the envelopes
+ this.envelope.triggerAttack(time, velocity);
+ return this;
+ };
+ /**
+ * start the release portion of the envelope
+ * @param {Time} [time=now] the time the release should start
+ * @returns {Tone.Synth} this
+ * @private
+ */
+ Tone.Synth.prototype._triggerEnvelopeRelease = function (time) {
+ this.envelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * clean up
+ * @returns {Tone.Synth} this
+ */
+ Tone.Synth.prototype.dispose = function () {
+ Tone.Monophonic.prototype.dispose.call(this);
+ this._writable([
+ 'oscillator',
+ 'frequency',
+ 'detune',
+ 'envelope'
+ ]);
+ this.oscillator.dispose();
+ this.oscillator = null;
+ this.envelope.dispose();
+ this.envelope = null;
+ this.frequency = null;
+ this.detune = null;
+ return this;
+ };
+ return Tone.Synth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class AMSynth uses the output of one Tone.Synth to modulate the
+ * amplitude of another Tone.Synth. The harmonicity (the ratio between
+ * the two signals) affects the timbre of the output signal greatly.
+ * Read more about Amplitude Modulation Synthesis on
+ * [SoundOnSound](http://www.soundonsound.com/sos/mar00/articles/synthsecrets.htm).
+ * <img src="https://docs.google.com/drawings/d/1TQu8Ed4iFr1YTLKpB3U1_hur-UwBrh5gdBXc8BxfGKw/pub?w=1009&h=457">
+ *
+ * @constructor
+ * @extends {Tone.Monophonic}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var synth = new Tone.AMSynth().toMaster();
+ * synth.triggerAttackRelease("C4", "4n");
+ */
+ Tone.AMSynth = function (options) {
+ options = this.defaultArg(options, Tone.AMSynth.defaults);
+ Tone.Monophonic.call(this, options);
+ /**
+ * The carrier voice.
+ * @type {Tone.Synth}
+ * @private
+ */
+ this._carrier = new Tone.Synth();
+ this._carrier.volume.value = -10;
+ /**
+ * The carrier's oscillator
+ * @type {Tone.Oscillator}
+ */
+ this.oscillator = this._carrier.oscillator;
+ /**
+ * The carrier's envelope
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.envelope = this._carrier.envelope.set(options.envelope);
+ /**
+ * The modulator voice.
+ * @type {Tone.Synth}
+ * @private
+ */
+ this._modulator = new Tone.Synth();
+ this._modulator.volume.value = -10;
+ /**
+ * The modulator's oscillator which is applied
+ * to the amplitude of the oscillator
+ * @type {Tone.Oscillator}
+ */
+ this.modulation = this._modulator.oscillator.set(options.modulation);
+ /**
+ * The modulator's envelope
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.modulationEnvelope = this._modulator.envelope.set(options.modulationEnvelope);
+ /**
+ * The frequency.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(440, Tone.Type.Frequency);
+ /**
+ * The detune in cents
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
+ /**
+ * Harmonicity is the ratio between the two voices. A harmonicity of
+ * 1 is no change. Harmonicity = 2 means a change of an octave.
+ * @type {Positive}
+ * @signal
+ * @example
+ * //pitch voice1 an octave below voice0
+ * synth.harmonicity.value = 0.5;
+ */
+ this.harmonicity = new Tone.Multiply(options.harmonicity);
+ this.harmonicity.units = Tone.Type.Positive;
+ /**
+ * convert the -1,1 output to 0,1
+ * @type {Tone.AudioToGain}
+ * @private
+ */
+ this._modulationScale = new Tone.AudioToGain();
+ /**
+ * the node where the modulation happens
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._modulationNode = new Tone.Gain();
+ //control the two voices frequency
+ this.frequency.connect(this._carrier.frequency);
+ this.frequency.chain(this.harmonicity, this._modulator.frequency);
+ this.detune.fan(this._carrier.detune, this._modulator.detune);
+ this._modulator.chain(this._modulationScale, this._modulationNode.gain);
+ this._carrier.chain(this._modulationNode, this.output);
+ this._readOnly([
+ 'frequency',
+ 'harmonicity',
+ 'oscillator',
+ 'envelope',
+ 'modulation',
+ 'modulationEnvelope',
+ 'detune'
+ ]);
+ };
+ Tone.extend(Tone.AMSynth, Tone.Monophonic);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.AMSynth.defaults = {
+ 'harmonicity': 3,
+ 'detune': 0,
+ 'oscillator': { 'type': 'sine' },
+ 'envelope': {
+ 'attack': 0.01,
+ 'decay': 0.01,
+ 'sustain': 1,
+ 'release': 0.5
+ },
+ 'modulation': { 'type': 'square' },
+ 'modulationEnvelope': {
+ 'attack': 0.5,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.5
+ }
+ };
+ /**
+ * trigger the attack portion of the note
+ *
+ * @param {Time} [time=now] the time the note will occur
+ * @param {NormalRange} [velocity=1] the velocity of the note
+ * @private
+ * @returns {Tone.AMSynth} this
+ */
+ Tone.AMSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {
+ //the port glide
+ time = this.toSeconds(time);
+ //the envelopes
+ this.envelope.triggerAttack(time, velocity);
+ this.modulationEnvelope.triggerAttack(time, velocity);
+ return this;
+ };
+ /**
+ * trigger the release portion of the note
+ *
+ * @param {Time} [time=now] the time the note will release
+ * @private
+ * @returns {Tone.AMSynth} this
+ */
+ Tone.AMSynth.prototype._triggerEnvelopeRelease = function (time) {
+ this.envelope.triggerRelease(time);
+ this.modulationEnvelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * clean up
+ * @returns {Tone.AMSynth} this
+ */
+ Tone.AMSynth.prototype.dispose = function () {
+ Tone.Monophonic.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'harmonicity',
+ 'oscillator',
+ 'envelope',
+ 'modulation',
+ 'modulationEnvelope',
+ 'detune'
+ ]);
+ this._carrier.dispose();
+ this._carrier = null;
+ this._modulator.dispose();
+ this._modulator = null;
+ this.frequency.dispose();
+ this.frequency = null;
+ this.detune.dispose();
+ this.detune = null;
+ this.harmonicity.dispose();
+ this.harmonicity = null;
+ this._modulationScale.dispose();
+ this._modulationScale = null;
+ this._modulationNode.dispose();
+ this._modulationNode = null;
+ this.oscillator = null;
+ this.envelope = null;
+ this.modulationEnvelope = null;
+ this.modulation = null;
+ return this;
+ };
+ return Tone.AMSynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.MonoSynth is composed of one oscillator, one filter, and two envelopes.
+ * The amplitude of the Tone.Oscillator and the cutoff frequency of the
+ * Tone.Filter are controlled by Tone.Envelopes.
+ * <img src="https://docs.google.com/drawings/d/1gaY1DF9_Hzkodqf8JI1Cg2VZfwSElpFQfI94IQwad38/pub?w=924&h=240">
+ *
+ * @constructor
+ * @extends {Tone.Monophonic}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var synth = new Tone.MonoSynth({
+ * "oscillator" : {
+ * "type" : "square"
+ * },
+ * "envelope" : {
+ * "attack" : 0.1
+ * }
+ * }).toMaster();
+ * synth.triggerAttackRelease("C4", "8n");
+ */
+ Tone.MonoSynth = function (options) {
+ //get the defaults
+ options = this.defaultArg(options, Tone.MonoSynth.defaults);
+ Tone.Monophonic.call(this, options);
+ /**
+ * The oscillator.
+ * @type {Tone.OmniOscillator}
+ */
+ this.oscillator = new Tone.OmniOscillator(options.oscillator);
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = this.oscillator.frequency;
+ /**
+ * The detune control.
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = this.oscillator.detune;
+ /**
+ * The filter.
+ * @type {Tone.Filter}
+ */
+ this.filter = new Tone.Filter(options.filter);
+ /**
+ * The filter envelope.
+ * @type {Tone.FrequencyEnvelope}
+ */
+ this.filterEnvelope = new Tone.FrequencyEnvelope(options.filterEnvelope);
+ /**
+ * The amplitude envelope.
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.envelope = new Tone.AmplitudeEnvelope(options.envelope);
+ //connect the oscillators to the output
+ this.oscillator.chain(this.filter, this.envelope, this.output);
+ //start the oscillators
+ this.oscillator.start();
+ //connect the filter envelope
+ this.filterEnvelope.connect(this.filter.frequency);
+ this._readOnly([
+ 'oscillator',
+ 'frequency',
+ 'detune',
+ 'filter',
+ 'filterEnvelope',
+ 'envelope'
+ ]);
+ };
+ Tone.extend(Tone.MonoSynth, Tone.Monophonic);
+ /**
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.MonoSynth.defaults = {
+ 'frequency': 'C4',
+ 'detune': 0,
+ 'oscillator': { 'type': 'square' },
+ 'filter': {
+ 'Q': 6,
+ 'type': 'lowpass',
+ 'rolloff': -24
+ },
+ 'envelope': {
+ 'attack': 0.005,
+ 'decay': 0.1,
+ 'sustain': 0.9,
+ 'release': 1
+ },
+ 'filterEnvelope': {
+ 'attack': 0.06,
+ 'decay': 0.2,
+ 'sustain': 0.5,
+ 'release': 2,
+ 'baseFrequency': 200,
+ 'octaves': 7,
+ 'exponent': 2
+ }
+ };
+ /**
+ * start the attack portion of the envelope
+ * @param {Time} [time=now] the time the attack should start
+ * @param {NormalRange} [velocity=1] the velocity of the note (0-1)
+ * @returns {Tone.MonoSynth} this
+ * @private
+ */
+ Tone.MonoSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {
+ //the envelopes
+ this.envelope.triggerAttack(time, velocity);
+ this.filterEnvelope.triggerAttack(time);
+ return this;
+ };
+ /**
+ * start the release portion of the envelope
+ * @param {Time} [time=now] the time the release should start
+ * @returns {Tone.MonoSynth} this
+ * @private
+ */
+ Tone.MonoSynth.prototype._triggerEnvelopeRelease = function (time) {
+ this.envelope.triggerRelease(time);
+ this.filterEnvelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * clean up
+ * @returns {Tone.MonoSynth} this
+ */
+ Tone.MonoSynth.prototype.dispose = function () {
+ Tone.Monophonic.prototype.dispose.call(this);
+ this._writable([
+ 'oscillator',
+ 'frequency',
+ 'detune',
+ 'filter',
+ 'filterEnvelope',
+ 'envelope'
+ ]);
+ this.oscillator.dispose();
+ this.oscillator = null;
+ this.envelope.dispose();
+ this.envelope = null;
+ this.filterEnvelope.dispose();
+ this.filterEnvelope = null;
+ this.filter.dispose();
+ this.filter = null;
+ this.frequency = null;
+ this.detune = null;
+ return this;
+ };
+ return Tone.MonoSynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.DuoSynth is a monophonic synth composed of two
+ * MonoSynths run in parallel with control over the
+ * frequency ratio between the two voices and vibrato effect.
+ * <img src="https://docs.google.com/drawings/d/1bL4GXvfRMMlqS7XyBm9CjL9KJPSUKbcdBNpqOlkFLxk/pub?w=1012&h=448">
+ *
+ * @constructor
+ * @extends {Tone.Monophonic}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var duoSynth = new Tone.DuoSynth().toMaster();
+ * duoSynth.triggerAttackRelease("C4", "2n");
+ */
+ Tone.DuoSynth = function (options) {
+ options = this.defaultArg(options, Tone.DuoSynth.defaults);
+ Tone.Monophonic.call(this, options);
+ /**
+ * the first voice
+ * @type {Tone.MonoSynth}
+ */
+ this.voice0 = new Tone.MonoSynth(options.voice0);
+ this.voice0.volume.value = -10;
+ /**
+ * the second voice
+ * @type {Tone.MonoSynth}
+ */
+ this.voice1 = new Tone.MonoSynth(options.voice1);
+ this.voice1.volume.value = -10;
+ /**
+ * The vibrato LFO.
+ * @type {Tone.LFO}
+ * @private
+ */
+ this._vibrato = new Tone.LFO(options.vibratoRate, -50, 50);
+ this._vibrato.start();
+ /**
+ * the vibrato frequency
+ * @type {Frequency}
+ * @signal
+ */
+ this.vibratoRate = this._vibrato.frequency;
+ /**
+ * the vibrato gain
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._vibratoGain = new Tone.Gain(options.vibratoAmount, Tone.Type.Positive);
+ /**
+ * The amount of vibrato
+ * @type {Positive}
+ * @signal
+ */
+ this.vibratoAmount = this._vibratoGain.gain;
+ /**
+ * the frequency control
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(440, Tone.Type.Frequency);
+ /**
+ * Harmonicity is the ratio between the two voices. A harmonicity of
+ * 1 is no change. Harmonicity = 2 means a change of an octave.
+ * @type {Positive}
+ * @signal
+ * @example
+ * //pitch voice1 an octave below voice0
+ * duoSynth.harmonicity.value = 0.5;
+ */
+ this.harmonicity = new Tone.Multiply(options.harmonicity);
+ this.harmonicity.units = Tone.Type.Positive;
+ //control the two voices frequency
+ this.frequency.connect(this.voice0.frequency);
+ this.frequency.chain(this.harmonicity, this.voice1.frequency);
+ this._vibrato.connect(this._vibratoGain);
+ this._vibratoGain.fan(this.voice0.detune, this.voice1.detune);
+ this.voice0.connect(this.output);
+ this.voice1.connect(this.output);
+ this._readOnly([
+ 'voice0',
+ 'voice1',
+ 'frequency',
+ 'vibratoAmount',
+ 'vibratoRate'
+ ]);
+ };
+ Tone.extend(Tone.DuoSynth, Tone.Monophonic);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.DuoSynth.defaults = {
+ 'vibratoAmount': 0.5,
+ 'vibratoRate': 5,
+ 'harmonicity': 1.5,
+ 'voice0': {
+ 'volume': -10,
+ 'portamento': 0,
+ 'oscillator': { 'type': 'sine' },
+ 'filterEnvelope': {
+ 'attack': 0.01,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.5
+ },
+ 'envelope': {
+ 'attack': 0.01,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.5
+ }
+ },
+ 'voice1': {
+ 'volume': -10,
+ 'portamento': 0,
+ 'oscillator': { 'type': 'sine' },
+ 'filterEnvelope': {
+ 'attack': 0.01,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.5
+ },
+ 'envelope': {
+ 'attack': 0.01,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.5
+ }
+ }
+ };
+ /**
+ * start the attack portion of the envelopes
+ *
+ * @param {Time} [time=now] the time the attack should start
+ * @param {NormalRange} [velocity=1] the velocity of the note (0-1)
+ * @returns {Tone.DuoSynth} this
+ * @private
+ */
+ Tone.DuoSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {
+ time = this.toSeconds(time);
+ this.voice0.envelope.triggerAttack(time, velocity);
+ this.voice1.envelope.triggerAttack(time, velocity);
+ this.voice0.filterEnvelope.triggerAttack(time);
+ this.voice1.filterEnvelope.triggerAttack(time);
+ return this;
+ };
+ /**
+ * start the release portion of the envelopes
+ *
+ * @param {Time} [time=now] the time the release should start
+ * @returns {Tone.DuoSynth} this
+ * @private
+ */
+ Tone.DuoSynth.prototype._triggerEnvelopeRelease = function (time) {
+ this.voice0.triggerRelease(time);
+ this.voice1.triggerRelease(time);
+ return this;
+ };
+ /**
+ * clean up
+ * @returns {Tone.DuoSynth} this
+ */
+ Tone.DuoSynth.prototype.dispose = function () {
+ Tone.Monophonic.prototype.dispose.call(this);
+ this._writable([
+ 'voice0',
+ 'voice1',
+ 'frequency',
+ 'vibratoAmount',
+ 'vibratoRate'
+ ]);
+ this.voice0.dispose();
+ this.voice0 = null;
+ this.voice1.dispose();
+ this.voice1 = null;
+ this.frequency.dispose();
+ this.frequency = null;
+ this._vibratoGain.dispose();
+ this._vibratoGain = null;
+ this._vibrato = null;
+ this.harmonicity.dispose();
+ this.harmonicity = null;
+ this.vibratoAmount.dispose();
+ this.vibratoAmount = null;
+ this.vibratoRate = null;
+ return this;
+ };
+ return Tone.DuoSynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class FMSynth is composed of two Tone.Synths where one Tone.Synth modulates
+ * the frequency of a second Tone.Synth. A lot of spectral content
+ * can be explored using the modulationIndex parameter. Read more about
+ * frequency modulation synthesis on [SoundOnSound](http://www.soundonsound.com/sos/apr00/articles/synthsecrets.htm).
+ * <img src="https://docs.google.com/drawings/d/1h0PUDZXPgi4Ikx6bVT6oncrYPLluFKy7lj53puxj-DM/pub?w=902&h=462">
+ *
+ * @constructor
+ * @extends {Tone.Monophonic}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var fmSynth = new Tone.FMSynth().toMaster();
+ * fmSynth.triggerAttackRelease("C5", "4n");
+ */
+ Tone.FMSynth = function (options) {
+ options = this.defaultArg(options, Tone.FMSynth.defaults);
+ Tone.Monophonic.call(this, options);
+ /**
+ * The carrier voice.
+ * @type {Tone.Synth}
+ * @private
+ */
+ this._carrier = new Tone.Synth(options.carrier);
+ this._carrier.volume.value = -10;
+ /**
+ * The carrier's oscillator
+ * @type {Tone.Oscillator}
+ */
+ this.oscillator = this._carrier.oscillator;
+ /**
+ * The carrier's envelope
+ * @type {Tone.Oscillator}
+ */
+ this.envelope = this._carrier.envelope.set(options.envelope);
+ /**
+ * The modulator voice.
+ * @type {Tone.Synth}
+ * @private
+ */
+ this._modulator = new Tone.Synth(options.modulator);
+ this._modulator.volume.value = -10;
+ /**
+ * The modulator's oscillator which is applied
+ * to the amplitude of the oscillator
+ * @type {Tone.Oscillator}
+ */
+ this.modulation = this._modulator.oscillator.set(options.modulation);
+ /**
+ * The modulator's envelope
+ * @type {Tone.Oscillator}
+ */
+ this.modulationEnvelope = this._modulator.envelope.set(options.modulationEnvelope);
+ /**
+ * The frequency control.
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(440, Tone.Type.Frequency);
+ /**
+ * The detune in cents
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
+ /**
+ * Harmonicity is the ratio between the two voices. A harmonicity of
+ * 1 is no change. Harmonicity = 2 means a change of an octave.
+ * @type {Positive}
+ * @signal
+ * @example
+ * //pitch voice1 an octave below voice0
+ * synth.harmonicity.value = 0.5;
+ */
+ this.harmonicity = new Tone.Multiply(options.harmonicity);
+ this.harmonicity.units = Tone.Type.Positive;
+ /**
+ * The modulation index which essentially the depth or amount of the modulation. It is the
+ * ratio of the frequency of the modulating signal (mf) to the amplitude of the
+ * modulating signal (ma) -- as in ma/mf.
+ * @type {Positive}
+ * @signal
+ */
+ this.modulationIndex = new Tone.Multiply(options.modulationIndex);
+ this.modulationIndex.units = Tone.Type.Positive;
+ /**
+ * the node where the modulation happens
+ * @type {GainNode}
+ * @private
+ */
+ this._modulationNode = new Tone.Gain(0);
+ //control the two voices frequency
+ this.frequency.connect(this._carrier.frequency);
+ this.frequency.chain(this.harmonicity, this._modulator.frequency);
+ this.frequency.chain(this.modulationIndex, this._modulationNode);
+ this.detune.fan(this._carrier.detune, this._modulator.detune);
+ this._modulator.connect(this._modulationNode.gain);
+ this._modulationNode.connect(this._carrier.frequency);
+ this._carrier.connect(this.output);
+ this._readOnly([
+ 'frequency',
+ 'harmonicity',
+ 'modulationIndex',
+ 'oscillator',
+ 'envelope',
+ 'modulation',
+ 'modulationEnvelope',
+ 'detune'
+ ]);
+ };
+ Tone.extend(Tone.FMSynth, Tone.Monophonic);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.FMSynth.defaults = {
+ 'harmonicity': 3,
+ 'modulationIndex': 10,
+ 'detune': 0,
+ 'oscillator': { 'type': 'sine' },
+ 'envelope': {
+ 'attack': 0.01,
+ 'decay': 0.01,
+ 'sustain': 1,
+ 'release': 0.5
+ },
+ 'modulation': { 'type': 'square' },
+ 'modulationEnvelope': {
+ 'attack': 0.5,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.5
+ }
+ };
+ /**
+ * trigger the attack portion of the note
+ *
+ * @param {Time} [time=now] the time the note will occur
+ * @param {number} [velocity=1] the velocity of the note
+ * @returns {Tone.FMSynth} this
+ * @private
+ */
+ Tone.FMSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {
+ time = this.toSeconds(time);
+ //the envelopes
+ this.envelope.triggerAttack(time, velocity);
+ this.modulationEnvelope.triggerAttack(time);
+ return this;
+ };
+ /**
+ * trigger the release portion of the note
+ *
+ * @param {Time} [time=now] the time the note will release
+ * @returns {Tone.FMSynth} this
+ * @private
+ */
+ Tone.FMSynth.prototype._triggerEnvelopeRelease = function (time) {
+ time = this.toSeconds(time);
+ this.envelope.triggerRelease(time);
+ this.modulationEnvelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * clean up
+ * @returns {Tone.FMSynth} this
+ */
+ Tone.FMSynth.prototype.dispose = function () {
+ Tone.Monophonic.prototype.dispose.call(this);
+ this._writable([
+ 'frequency',
+ 'harmonicity',
+ 'modulationIndex',
+ 'oscillator',
+ 'envelope',
+ 'modulation',
+ 'modulationEnvelope',
+ 'detune'
+ ]);
+ this._carrier.dispose();
+ this._carrier = null;
+ this._modulator.dispose();
+ this._modulator = null;
+ this.frequency.dispose();
+ this.frequency = null;
+ this.detune.dispose();
+ this.detune = null;
+ this.modulationIndex.dispose();
+ this.modulationIndex = null;
+ this.harmonicity.dispose();
+ this.harmonicity = null;
+ this._modulationNode.dispose();
+ this._modulationNode = null;
+ this.oscillator = null;
+ this.envelope = null;
+ this.modulationEnvelope = null;
+ this.modulation = null;
+ return this;
+ };
+ return Tone.FMSynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.MembraneSynth makes kick and tom sounds using a single oscillator
+ * with an amplitude envelope and frequency ramp. A Tone.OmniOscillator
+ * is routed through a Tone.AmplitudeEnvelope to the output. The drum
+ * quality of the sound comes from the frequency envelope applied
+ * during during Tone.MembraneSynth.triggerAttack(note). The frequency
+ * envelope starts at <code>note * .octaves</code> and ramps to
+ * <code>note</code> over the duration of <code>.pitchDecay</code>.
+ *
+ * @constructor
+ * @extends {Tone.Instrument}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var synth = new Tone.MembraneSynth().toMaster();
+ * synth.triggerAttackRelease("C2", "8n");
+ */
+ Tone.MembraneSynth = function (options) {
+ options = this.defaultArg(options, Tone.MembraneSynth.defaults);
+ Tone.Instrument.call(this, options);
+ /**
+ * The oscillator.
+ * @type {Tone.OmniOscillator}
+ */
+ this.oscillator = new Tone.OmniOscillator(options.oscillator).start();
+ /**
+ * The amplitude envelope.
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.envelope = new Tone.AmplitudeEnvelope(options.envelope);
+ /**
+ * The number of octaves the pitch envelope ramps.
+ * @type {Positive}
+ */
+ this.octaves = options.octaves;
+ /**
+ * The amount of time the frequency envelope takes.
+ * @type {Time}
+ */
+ this.pitchDecay = options.pitchDecay;
+ this.oscillator.chain(this.envelope, this.output);
+ this._readOnly([
+ 'oscillator',
+ 'envelope'
+ ]);
+ };
+ Tone.extend(Tone.MembraneSynth, Tone.Instrument);
+ /**
+ * @static
+ * @type {Object}
+ */
+ Tone.MembraneSynth.defaults = {
+ 'pitchDecay': 0.05,
+ 'octaves': 10,
+ 'oscillator': { 'type': 'sine' },
+ 'envelope': {
+ 'attack': 0.001,
+ 'decay': 0.4,
+ 'sustain': 0.01,
+ 'release': 1.4,
+ 'attackCurve': 'exponential'
+ }
+ };
+ /**
+ * Trigger the note at the given time with the given velocity.
+ *
+ * @param {Frequency} note the note
+ * @param {Time} [time=now] the time, if not given is now
+ * @param {number} [velocity=1] velocity defaults to 1
+ * @returns {Tone.MembraneSynth} this
+ * @example
+ * kick.triggerAttack(60);
+ */
+ Tone.MembraneSynth.prototype.triggerAttack = function (note, time, velocity) {
+ time = this.toSeconds(time);
+ note = this.toFrequency(note);
+ var maxNote = note * this.octaves;
+ this.oscillator.frequency.setValueAtTime(maxNote, time);
+ this.oscillator.frequency.exponentialRampToValueAtTime(note, time + this.toSeconds(this.pitchDecay));
+ this.envelope.triggerAttack(time, velocity);
+ return this;
+ };
+ /**
+ * Trigger the release portion of the note.
+ *
+ * @param {Time} [time=now] the time the note will release
+ * @returns {Tone.MembraneSynth} this
+ */
+ Tone.MembraneSynth.prototype.triggerRelease = function (time) {
+ this.envelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.MembraneSynth} this
+ */
+ Tone.MembraneSynth.prototype.dispose = function () {
+ Tone.Instrument.prototype.dispose.call(this);
+ this._writable([
+ 'oscillator',
+ 'envelope'
+ ]);
+ this.oscillator.dispose();
+ this.oscillator = null;
+ this.envelope.dispose();
+ this.envelope = null;
+ return this;
+ };
+ return Tone.MembraneSynth;
+ });
+ Module(function (Tone) {
+ /**
+ * Inharmonic ratio of frequencies based on the Roland TR-808
+ * Taken from https://ccrma.stanford.edu/papers/tr-808-cymbal-physically-informed-circuit-bendable-digital-model
+ * @private
+ * @static
+ * @type {Array}
+ */
+ var inharmRatios = [
+ 1,
+ 1.483,
+ 1.932,
+ 2.546,
+ 2.63,
+ 3.897
+ ];
+ /**
+ * @class A highly inharmonic and spectrally complex source with a highpass filter
+ * and amplitude envelope which is good for making metalophone sounds. Based
+ * on CymbalSynth by [@polyrhythmatic](https://github.com/polyrhythmatic).
+ * Inspiration from [Sound on Sound](http://www.soundonsound.com/sos/jul02/articles/synthsecrets0702.asp).
+ *
+ * @constructor
+ * @extends {Tone.Instrument}
+ * @param {Object} [options] The options availble for the synth
+ * see defaults below
+ */
+ Tone.MetalSynth = function (options) {
+ options = this.defaultArg(options, Tone.MetalSynth.defaults);
+ Tone.Instrument.call(this, options);
+ /**
+ * The frequency of the cymbal
+ * @type {Frequency}
+ * @signal
+ */
+ this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
+ /**
+ * The array of FMOscillators
+ * @type {Array}
+ * @private
+ */
+ this._oscillators = [];
+ /**
+ * The frequency multipliers
+ * @type {Array}
+ * @private
+ */
+ this._freqMultipliers = [];
+ /**
+ * The amplitude for the body
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._amplitue = new Tone.Gain(0).connect(this.output);
+ /**
+ * highpass the output
+ * @type {Tone.Filter}
+ * @private
+ */
+ this._highpass = new Tone.Filter({
+ 'type': 'highpass',
+ 'Q': -3.0102999566398125
+ }).connect(this._amplitue);
+ /**
+ * The number of octaves the highpass
+ * filter frequency ramps
+ * @type {Number}
+ * @private
+ */
+ this._octaves = options.octaves;
+ /**
+ * Scale the body envelope
+ * for the bandpass
+ * @type {Tone.Scale}
+ * @private
+ */
+ this._filterFreqScaler = new Tone.Scale(options.resonance, 7000);
+ /**
+ * The envelope which is connected both to the
+ * amplitude and highpass filter's cutoff frequency
+ * @type {Tone.Envelope}
+ */
+ this.envelope = new Tone.Envelope({
+ 'attack': options.envelope.attack,
+ 'attackCurve': 'linear',
+ 'decay': options.envelope.decay,
+ 'sustain': 0,
+ 'release': options.envelope.release
+ }).chain(this._filterFreqScaler, this._highpass.frequency);
+ this.envelope.connect(this._amplitue.gain);
+ for (var i = 0; i < inharmRatios.length; i++) {
+ var osc = new Tone.FMOscillator({
+ 'type': 'square',
+ 'modulationType': 'square',
+ 'harmonicity': options.harmonicity,
+ 'modulationIndex': options.modulationIndex
+ });
+ osc.connect(this._highpass).start(0);
+ this._oscillators[i] = osc;
+ var mult = new Tone.Multiply(inharmRatios[i]);
+ this._freqMultipliers[i] = mult;
+ this.frequency.chain(mult, osc.frequency);
+ }
+ //set the octaves
+ this.octaves = options.octaves;
+ };
+ Tone.extend(Tone.MetalSynth, Tone.Instrument);
+ /**
+ * default values
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.MetalSynth.defaults = {
+ 'frequency': 200,
+ 'envelope': {
+ 'attack': 0.001,
+ 'decay': 1.4,
+ 'release': 0.2
+ },
+ 'harmonicity': 5.1,
+ 'modulationIndex': 32,
+ 'resonance': 4000,
+ 'octaves': 1.5
+ };
+ /**
+ * Trigger the attack.
+ * @param {Time} time When the attack should be triggered.
+ * @param {NormalRange=1} velocity The velocity that the envelope should be triggered at.
+ * @return {Tone.MetalSynth} this
+ */
+ Tone.MetalSynth.prototype.triggerAttack = function (time, vel) {
+ time = this.toSeconds(time);
+ vel = this.defaultArg(vel, 1);
+ this.envelope.triggerAttack(time, vel);
+ return this;
+ };
+ /**
+ * Trigger the release of the envelope.
+ * @param {Time} time When the release should be triggered.
+ * @return {Tone.MetalSynth} this
+ */
+ Tone.MetalSynth.prototype.triggerRelease = function (time) {
+ time = this.toSeconds(time);
+ this.envelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * Trigger the attack and release of the envelope after the given
+ * duration.
+ * @param {Time} duration The duration before triggering the release
+ * @param {Time} time When the attack should be triggered.
+ * @param {NormalRange=1} velocity The velocity that the envelope should be triggered at.
+ * @return {Tone.MetalSynth} this
+ */
+ Tone.MetalSynth.prototype.triggerAttackRelease = function (duration, time, velocity) {
+ time = this.toSeconds(time);
+ duration = this.toSeconds(duration);
+ this.triggerAttack(time, velocity);
+ this.triggerRelease(time + duration);
+ return this;
+ };
+ /**
+ * The modulationIndex of the oscillators which make up the source.
+ * see Tone.FMOscillator.modulationIndex
+ * @memberOf Tone.MetalSynth#
+ * @type {Positive}
+ * @name modulationIndex
+ */
+ Object.defineProperty(Tone.MetalSynth.prototype, 'modulationIndex', {
+ get: function () {
+ return this._oscillators[0].modulationIndex.value;
+ },
+ set: function (val) {
+ for (var i = 0; i < this._oscillators.length; i++) {
+ this._oscillators[i].modulationIndex.value = val;
+ }
+ }
+ });
+ /**
+ * The harmonicity of the oscillators which make up the source.
+ * see Tone.FMOscillator.harmonicity
+ * @memberOf Tone.MetalSynth#
+ * @type {Positive}
+ * @name harmonicity
+ */
+ Object.defineProperty(Tone.MetalSynth.prototype, 'harmonicity', {
+ get: function () {
+ return this._oscillators[0].harmonicity.value;
+ },
+ set: function (val) {
+ for (var i = 0; i < this._oscillators.length; i++) {
+ this._oscillators[i].harmonicity.value = val;
+ }
+ }
+ });
+ /**
+ * The frequency of the highpass filter attached to the envelope
+ * @memberOf Tone.MetalSynth#
+ * @type {Frequency}
+ * @name resonance
+ */
+ Object.defineProperty(Tone.MetalSynth.prototype, 'resonance', {
+ get: function () {
+ return this._filterFreqScaler.min;
+ },
+ set: function (val) {
+ this._filterFreqScaler.min = val;
+ this.octaves = this._octaves;
+ }
+ });
+ /**
+ * The number of octaves above the "resonance" frequency
+ * that the filter ramps during the attack/decay envelope
+ * @memberOf Tone.MetalSynth#
+ * @type {Number}
+ * @name octaves
+ */
+ Object.defineProperty(Tone.MetalSynth.prototype, 'octaves', {
+ get: function () {
+ return this._octaves;
+ },
+ set: function (octs) {
+ this._octaves = octs;
+ this._filterFreqScaler.max = this._filterFreqScaler.min * Math.pow(2, octs);
+ }
+ });
+ /**
+ * Clean up
+ * @returns {Tone.MetalSynth} this
+ */
+ Tone.MetalSynth.prototype.dispose = function () {
+ Tone.Instrument.prototype.dispose.call(this);
+ for (var i = 0; i < this._oscillators.length; i++) {
+ this._oscillators[i].dispose();
+ this._freqMultipliers[i].dispose();
+ }
+ this._oscillators = null;
+ this._freqMultipliers = null;
+ this.frequency.dispose();
+ this.frequency = null;
+ this._filterFreqScaler.dispose();
+ this._filterFreqScaler = null;
+ this._amplitue.dispose();
+ this._amplitue = null;
+ this.envelope.dispose();
+ this.envelope = null;
+ this._highpass.dispose();
+ this._highpass = null;
+ };
+ return Tone.MetalSynth;
+ });
+ Module(function (Tone) {
+ /**
+ * BufferSource polyfill
+ */
+ if (window.AudioBufferSourceNode && !AudioBufferSourceNode.prototype.start) {
+ AudioBufferSourceNode.prototype.start = AudioBufferSourceNode.prototype.noteGrainOn;
+ AudioBufferSourceNode.prototype.stop = AudioBufferSourceNode.prototype.noteOff;
+ }
+ /**
+ * @class Wrapper around the native BufferSourceNode.
+ * @param {AudioBuffer|Tone.Buffer} buffer The buffer to play
+ * @param {Function} onended The callback to invoke when the
+ * buffer is done playing.
+ */
+ Tone.BufferSource = function () {
+ var options = this.optionsObject(arguments, [
+ 'buffer',
+ 'onended'
+ ], Tone.BufferSource.defaults);
+ /**
+ * The callback to invoke after the
+ * buffer source is done playing.
+ * @type {Function}
+ */
+ this.onended = options.onended;
+ /**
+ * The time that the buffer was started.
+ * @type {Number}
+ * @private
+ */
+ this._startTime = -1;
+ /**
+ * The time that the buffer is scheduled to stop.
+ * @type {Number}
+ * @private
+ */
+ this._stopTime = -1;
+ /**
+ * The gain node which envelopes the BufferSource
+ * @type {Tone.Gain}
+ * @private
+ */
+ this._gainNode = this.output = new Tone.Gain();
+ /**
+ * The buffer source
+ * @type {AudioBufferSourceNode}
+ * @private
+ */
+ this._source = this.context.createBufferSource();
+ this._source.connect(this._gainNode);
+ /**
+ * The playbackRate of the buffer
+ * @type {Positive}
+ * @signal
+ */
+ this.playbackRate = new Tone.Param(this._source.playbackRate, Tone.Type.Positive);
+ /**
+ * The fadeIn time of the amplitude envelope.
+ * @type {Time}
+ */
+ this.fadeIn = options.fadeIn;
+ /**
+ * The fadeOut time of the amplitude envelope.
+ * @type {Time}
+ */
+ this.fadeOut = options.fadeOut;
+ /**
+ * The value that the buffer ramps to
+ * @type {Gain}
+ * @private
+ */
+ this._gain = 1;
+ /**
+ * The onended timeout
+ * @type {Number}
+ * @private
+ */
+ this._onendedTimeout = -1;
+ //set the buffer initially
+ if (!this.isUndef(options.buffer)) {
+ this.buffer = options.buffer;
+ }
+ this.loop = options.loop;
+ };
+ Tone.extend(Tone.BufferSource);
+ /**
+ * The defaults
+ * @const
+ * @type {Object}
+ */
+ Tone.BufferSource.defaults = {
+ 'onended': Tone.noOp,
+ 'fadeIn': 0,
+ 'fadeOut': 0
+ };
+ /**
+ * Returns the playback state of the source, either "started" or "stopped".
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.BufferSource#
+ * @name state
+ */
+ Object.defineProperty(Tone.BufferSource.prototype, 'state', {
+ get: function () {
+ var now = this.now();
+ if (this._startTime !== -1 && now >= this._startTime && now < this._stopTime) {
+ return Tone.State.Started;
+ } else {
+ return Tone.State.Stopped;
+ }
+ }
+ });
+ /**
+ * Start the buffer
+ * @param {Time} [startTime=now] When the player should start.
+ * @param {Time} [offset=0] The offset from the beginning of the sample
+ * to start at.
+ * @param {Time=} duration How long the sample should play. If no duration
+ * is given, it will default to the full length
+ * of the sample (minus any offset)
+ * @param {Gain} [gain=1] The gain to play the buffer back at.
+ * @param {Time=} fadeInTime The optional fadeIn ramp time.
+ * @return {Tone.BufferSource} this
+ */
+ Tone.BufferSource.prototype.start = function (time, offset, duration, gain, fadeInTime) {
+ if (this._startTime !== -1) {
+ throw new Error('Tone.BufferSource: can only be started once.');
+ }
+ if (this.buffer) {
+ time = this.toSeconds(time);
+ //if it's a loop the default offset is the loopstart point
+ if (this.loop) {
+ offset = this.defaultArg(offset, this.loopStart);
+ } else {
+ //otherwise the default offset is 0
+ offset = this.defaultArg(offset, 0);
+ }
+ offset = this.toSeconds(offset);
+ //the values in seconds
+ time = this.toSeconds(time);
+ this._source.start(time, offset);
+ gain = this.defaultArg(gain, 1);
+ this._gain = gain;
+ //the fadeIn time
+ if (this.isUndef(fadeInTime)) {
+ fadeInTime = this.toSeconds(this.fadeIn);
+ } else {
+ fadeInTime = this.toSeconds(fadeInTime);
+ }
+ if (fadeInTime > 0) {
+ this._gainNode.gain.setValueAtTime(0, time);
+ this._gainNode.gain.linearRampToValueAtTime(this._gain, time + fadeInTime);
+ } else {
+ this._gainNode.gain.setValueAtTime(gain, time);
+ }
+ this._startTime = time + fadeInTime;
+ if (!this.isUndef(duration)) {
+ duration = this.defaultArg(duration, this.buffer.duration - offset);
+ duration = this.toSeconds(duration);
+ this.stop(time + duration + fadeInTime, fadeInTime);
+ }
+ }
+ return this;
+ };
+ /**
+ * Stop the buffer. Optionally add a ramp time to fade the
+ * buffer out.
+ * @param {Time=} time The time the buffer should stop.
+ * @param {Time=} fadeOutTime How long the gain should fade out for
+ * @return {Tone.BufferSource} this
+ */
+ Tone.BufferSource.prototype.stop = function (time, fadeOutTime) {
+ if (this.buffer) {
+ time = this.toSeconds(time);
+ //the fadeOut time
+ if (this.isUndef(fadeOutTime)) {
+ fadeOutTime = this.toSeconds(this.fadeOut);
+ } else {
+ fadeOutTime = this.toSeconds(fadeOutTime);
+ }
+ this._stopTime = time + fadeOutTime;
+ //cancel the end curve
+ this._gainNode.gain.cancelScheduledValues(this._startTime + this.sampleTime);
+ //set a new one
+ if (fadeOutTime > 0) {
+ this._gainNode.gain.setValueAtTime(this._gain, time);
+ this._gainNode.gain.linearRampToValueAtTime(0, time + fadeOutTime);
+ time += fadeOutTime;
+ } else {
+ this._gainNode.gain.setValueAtTime(0, time);
+ }
+ // fix for safari bug and old FF
+ if (!this.isNumber(this._source.playbackState) || this._source.playbackState === 2) {
+ this._source.stop(time);
+ }
+ clearTimeout(this._onendedTimeout);
+ this._onendedTimeout = setTimeout(this._onended.bind(this), (this._stopTime - this.now()) * 1000);
+ }
+ return this;
+ };
+ /**
+ * Internal callback when the buffer is ended.
+ * Invokes `onended` and disposes the node.
+ * @private
+ */
+ Tone.BufferSource.prototype._onended = function () {
+ this.onended(this);
+ this.dispose();
+ };
+ /**
+ * If loop is true, the loop will start at this position.
+ * @memberOf Tone.BufferSource#
+ * @type {Time}
+ * @name loopStart
+ */
+ Object.defineProperty(Tone.BufferSource.prototype, 'loopStart', {
+ get: function () {
+ return this._source.loopStart;
+ },
+ set: function (loopStart) {
+ this._source.loopStart = this.toSeconds(loopStart);
+ }
+ });
+ /**
+ * If loop is true, the loop will end at this position.
+ * @memberOf Tone.BufferSource#
+ * @type {Time}
+ * @name loopEnd
+ */
+ Object.defineProperty(Tone.BufferSource.prototype, 'loopEnd', {
+ get: function () {
+ return this._source.loopEnd;
+ },
+ set: function (loopEnd) {
+ this._source.loopEnd = this.toSeconds(loopEnd);
+ }
+ });
+ /**
+ * The audio buffer belonging to the player.
+ * @memberOf Tone.BufferSource#
+ * @type {AudioBuffer}
+ * @name buffer
+ */
+ Object.defineProperty(Tone.BufferSource.prototype, 'buffer', {
+ get: function () {
+ if (this._source) {
+ return this._source.buffer;
+ } else {
+ return null;
+ }
+ },
+ set: function (buffer) {
+ if (buffer instanceof Tone.Buffer) {
+ this._source.buffer = buffer.get();
+ } else {
+ this._source.buffer = buffer;
+ }
+ }
+ });
+ /**
+ * If the buffer should loop once it's over.
+ * @memberOf Tone.BufferSource#
+ * @type {boolean}
+ * @name loop
+ */
+ Object.defineProperty(Tone.BufferSource.prototype, 'loop', {
+ get: function () {
+ return this._source.loop;
+ },
+ set: function (loop) {
+ this._source.loop = loop;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.BufferSource} this
+ */
+ Tone.BufferSource.prototype.dispose = function () {
+ this.onended = null;
+ if (this._source) {
+ this._source.disconnect();
+ this._source = null;
+ }
+ if (this._gainNode) {
+ this._gainNode.dispose();
+ this._gainNode = null;
+ }
+ this._startTime = -1;
+ this.playbackRate = null;
+ this.output = null;
+ clearTimeout(this._onendedTimeout);
+ return this;
+ };
+ return Tone.BufferSource;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Noise is a noise generator. It uses looped noise buffers to save on performance.
+ * Tone.Noise supports the noise types: "pink", "white", and "brown". Read more about
+ * colors of noise on [Wikipedia](https://en.wikipedia.org/wiki/Colors_of_noise).
+ *
+ * @constructor
+ * @extends {Tone.Source}
+ * @param {string} type the noise type (white|pink|brown)
+ * @example
+ * //initialize the noise and start
+ * var noise = new Tone.Noise("pink").start();
+ *
+ * //make an autofilter to shape the noise
+ * var autoFilter = new Tone.AutoFilter({
+ * "frequency" : "8m",
+ * "min" : 800,
+ * "max" : 15000
+ * }).connect(Tone.Master);
+ *
+ * //connect the noise
+ * noise.connect(autoFilter);
+ * //start the autofilter LFO
+ * autoFilter.start()
+ */
+ Tone.Noise = function () {
+ var options = this.optionsObject(arguments, ['type'], Tone.Noise.defaults);
+ Tone.Source.call(this, options);
+ /**
+ * @private
+ * @type {AudioBufferSourceNode}
+ */
+ this._source = null;
+ /**
+ * the buffer
+ * @private
+ * @type {AudioBuffer}
+ */
+ this._type = options.type;
+ /**
+ * The playback rate of the noise. Affects
+ * the "frequency" of the noise.
+ * @type {Positive}
+ * @signal
+ */
+ this._playbackRate = options.playbackRate;
+ };
+ Tone.extend(Tone.Noise, Tone.Source);
+ /**
+ * the default parameters
+ *
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Noise.defaults = {
+ 'type': 'white',
+ 'playbackRate': 1
+ };
+ /**
+ * The type of the noise. Can be "white", "brown", or "pink".
+ * @memberOf Tone.Noise#
+ * @type {string}
+ * @name type
+ * @example
+ * noise.type = "white";
+ */
+ Object.defineProperty(Tone.Noise.prototype, 'type', {
+ get: function () {
+ return this._type;
+ },
+ set: function (type) {
+ if (this._type !== type) {
+ if (type in _noiseBuffers) {
+ this._type = type;
+ //if it's playing, stop and restart it
+ if (this.state === Tone.State.Started) {
+ var now = this.now() + this.blockTime;
+ this._stop(now);
+ this._start(now);
+ }
+ } else {
+ throw new TypeError('Tone.Noise: invalid type: ' + type);
+ }
+ }
+ }
+ });
+ /**
+ * The playback rate of the noise. Affects
+ * the "frequency" of the noise.
+ * @type {Positive}
+ * @signal
+ */
+ Object.defineProperty(Tone.Noise.prototype, 'playbackRate', {
+ get: function () {
+ return this._playbackRate;
+ },
+ set: function (rate) {
+ this._playbackRate = rate;
+ if (this._source) {
+ this._source.playbackRate.value = rate;
+ }
+ }
+ });
+ /**
+ * internal start method
+ *
+ * @param {Time} time
+ * @private
+ */
+ Tone.Noise.prototype._start = function (time) {
+ var buffer = _noiseBuffers[this._type];
+ this._source = new Tone.BufferSource(buffer).connect(this.output);
+ this._source.loop = true;
+ this._source.playbackRate.value = this._playbackRate;
+ this._source.start(this.toSeconds(time), Math.random() * (buffer.duration - 0.001));
+ };
+ /**
+ * internal stop method
+ *
+ * @param {Time} time
+ * @private
+ */
+ Tone.Noise.prototype._stop = function (time) {
+ if (this._source) {
+ this._source.stop(this.toSeconds(time));
+ this._source = null;
+ }
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.Noise} this
+ */
+ Tone.Noise.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ if (this._source !== null) {
+ this._source.disconnect();
+ this._source = null;
+ }
+ this._buffer = null;
+ return this;
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ // THE BUFFERS
+ ///////////////////////////////////////////////////////////////////////////
+ //Noise buffer stats
+ var bufferLength = 44100 * 5;
+ var channels = 2;
+ /**
+ * the noise arrays. only generated once on init
+ * @static
+ * @private
+ * @type {Array}
+ * borrowed heavily from https://github.com/zacharydenton/noise.js
+ * (c) 2013 Zach Denton (MIT)
+ */
+ var _noiseArrays = {
+ 'pink': function () {
+ var buffer = [];
+ for (var channelNum = 0; channelNum < channels; channelNum++) {
+ var channel = new Float32Array(bufferLength);
+ buffer[channelNum] = channel;
+ var b0, b1, b2, b3, b4, b5, b6;
+ b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0;
+ for (var i = 0; i < bufferLength; 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;
+ channel[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
+ channel[i] *= 0.11;
+ // (roughly) compensate for gain
+ b6 = white * 0.115926;
+ }
+ }
+ return buffer;
+ }(),
+ 'brown': function () {
+ var buffer = [];
+ for (var channelNum = 0; channelNum < channels; channelNum++) {
+ var channel = new Float32Array(bufferLength);
+ buffer[channelNum] = channel;
+ var lastOut = 0;
+ for (var i = 0; i < bufferLength; i++) {
+ var white = Math.random() * 2 - 1;
+ channel[i] = (lastOut + 0.02 * white) / 1.02;
+ lastOut = channel[i];
+ channel[i] *= 3.5; // (roughly) compensate for gain
+ }
+ }
+ return buffer;
+ }(),
+ 'white': function () {
+ var buffer = [];
+ for (var channelNum = 0; channelNum < channels; channelNum++) {
+ var channel = new Float32Array(bufferLength);
+ buffer[channelNum] = channel;
+ for (var i = 0; i < bufferLength; i++) {
+ channel[i] = Math.random() * 2 - 1;
+ }
+ }
+ return buffer;
+ }()
+ };
+ /**
+ * static noise buffers
+ * @static
+ * @private
+ * @type {Tone.Buffer}
+ */
+ var _noiseBuffers = {};
+ //create the Tone.Buffers
+ function createBuffers() {
+ for (var type in _noiseArrays) {
+ _noiseBuffers[type] = new Tone.Buffer().fromArray(_noiseArrays[type]);
+ }
+ }
+ createBuffers();
+ Tone.Context.on('init', createBuffers);
+ return Tone.Noise;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.NoiseSynth is composed of a noise generator (Tone.Noise), one filter (Tone.Filter),
+ * and two envelopes (Tone.Envelop). One envelope controls the amplitude
+ * of the noise and the other is controls the cutoff frequency of the filter.
+ * <img src="https://docs.google.com/drawings/d/1rqzuX9rBlhT50MRvD2TKml9bnZhcZmzXF1rf_o7vdnE/pub?w=918&h=242">
+ *
+ * @constructor
+ * @extends {Tone.Instrument}
+ * @param {Object} [options] the options available for the synth
+ * see defaults below
+ * @example
+ * var noiseSynth = new Tone.NoiseSynth().toMaster();
+ * noiseSynth.triggerAttackRelease("8n");
+ */
+ Tone.NoiseSynth = function (options) {
+ //get the defaults
+ options = this.defaultArg(options, Tone.NoiseSynth.defaults);
+ Tone.Instrument.call(this, options);
+ /**
+ * The noise source.
+ * @type {Tone.Noise}
+ * @example
+ * noiseSynth.set("noise.type", "brown");
+ */
+ this.noise = new Tone.Noise();
+ /**
+ * The amplitude envelope.
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.envelope = new Tone.AmplitudeEnvelope(options.envelope);
+ //connect the noise to the output
+ this.noise.chain(this.envelope, this.output);
+ //start the noise
+ this.noise.start();
+ this._readOnly([
+ 'noise',
+ 'envelope'
+ ]);
+ };
+ Tone.extend(Tone.NoiseSynth, Tone.Instrument);
+ /**
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.NoiseSynth.defaults = {
+ 'noise': { 'type': 'white' },
+ 'envelope': {
+ 'attack': 0.005,
+ 'decay': 0.1,
+ 'sustain': 0
+ }
+ };
+ /**
+ * Start the attack portion of the envelopes. Unlike other
+ * instruments, Tone.NoiseSynth doesn't have a note.
+ * @param {Time} [time=now] the time the attack should start
+ * @param {number} [velocity=1] the velocity of the note (0-1)
+ * @returns {Tone.NoiseSynth} this
+ * @example
+ * noiseSynth.triggerAttack();
+ */
+ Tone.NoiseSynth.prototype.triggerAttack = function (time, velocity) {
+ //the envelopes
+ this.envelope.triggerAttack(time, velocity);
+ return this;
+ };
+ /**
+ * Start the release portion of the envelopes.
+ * @param {Time} [time=now] the time the release should start
+ * @returns {Tone.NoiseSynth} this
+ */
+ Tone.NoiseSynth.prototype.triggerRelease = function (time) {
+ this.envelope.triggerRelease(time);
+ return this;
+ };
+ /**
+ * Trigger the attack and then the release.
+ * @param {Time} duration the duration of the note
+ * @param {Time} [time=now] the time of the attack
+ * @param {number} [velocity=1] the velocity
+ * @returns {Tone.NoiseSynth} this
+ */
+ Tone.NoiseSynth.prototype.triggerAttackRelease = function (duration, time, velocity) {
+ time = this.toSeconds(time);
+ duration = this.toSeconds(duration);
+ this.triggerAttack(time, velocity);
+ this.triggerRelease(time + duration);
+ return this;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.NoiseSynth} this
+ */
+ Tone.NoiseSynth.prototype.dispose = function () {
+ Tone.Instrument.prototype.dispose.call(this);
+ this._writable([
+ 'noise',
+ 'envelope'
+ ]);
+ this.noise.dispose();
+ this.noise = null;
+ this.envelope.dispose();
+ this.envelope = null;
+ return this;
+ };
+ return Tone.NoiseSynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Karplus-String string synthesis. Often out of tune.
+ * Will change when the AudioWorkerNode is available across
+ * browsers.
+ *
+ * @constructor
+ * @extends {Tone.Instrument}
+ * @param {Object} [options] see the defaults
+ * @example
+ * var plucky = new Tone.PluckSynth().toMaster();
+ * plucky.triggerAttack("C4");
+ */
+ Tone.PluckSynth = function (options) {
+ options = this.defaultArg(options, Tone.PluckSynth.defaults);
+ Tone.Instrument.call(this, options);
+ /**
+ * @type {Tone.Noise}
+ * @private
+ */
+ this._noise = new Tone.Noise('pink');
+ /**
+ * The amount of noise at the attack.
+ * Nominal range of [0.1, 20]
+ * @type {number}
+ */
+ this.attackNoise = options.attackNoise;
+ /**
+ * the LFCF
+ * @type {Tone.LowpassCombFilter}
+ * @private
+ */
+ this._lfcf = new Tone.LowpassCombFilter({
+ 'resonance': options.resonance,
+ 'dampening': options.dampening
+ });
+ /**
+ * The resonance control.
+ * @type {NormalRange}
+ * @signal
+ */
+ this.resonance = this._lfcf.resonance;
+ /**
+ * The dampening control. i.e. the lowpass filter frequency of the comb filter
+ * @type {Frequency}
+ * @signal
+ */
+ this.dampening = this._lfcf.dampening;
+ //connections
+ this._noise.connect(this._lfcf);
+ this._lfcf.connect(this.output);
+ this._readOnly([
+ 'resonance',
+ 'dampening'
+ ]);
+ };
+ Tone.extend(Tone.PluckSynth, Tone.Instrument);
+ /**
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.PluckSynth.defaults = {
+ 'attackNoise': 1,
+ 'dampening': 4000,
+ 'resonance': 0.9
+ };
+ /**
+ * Trigger the note.
+ * @param {Frequency} note The note to trigger.
+ * @param {Time} [time=now] When the note should be triggered.
+ * @returns {Tone.PluckSynth} this
+ */
+ Tone.PluckSynth.prototype.triggerAttack = function (note, time) {
+ note = this.toFrequency(note);
+ time = this.toSeconds(time);
+ var delayAmount = 1 / note;
+ this._lfcf.delayTime.setValueAtTime(delayAmount, time);
+ this._noise.start(time);
+ this._noise.stop(time + delayAmount * this.attackNoise);
+ return this;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.PluckSynth} this
+ */
+ Tone.PluckSynth.prototype.dispose = function () {
+ Tone.Instrument.prototype.dispose.call(this);
+ this._noise.dispose();
+ this._lfcf.dispose();
+ this._noise = null;
+ this._lfcf = null;
+ this._writable([
+ 'resonance',
+ 'dampening'
+ ]);
+ this.dampening = null;
+ this.resonance = null;
+ return this;
+ };
+ return Tone.PluckSynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.PolySynth handles voice creation and allocation for any
+ * instruments passed in as the second paramter. PolySynth is
+ * not a synthesizer by itself, it merely manages voices of
+ * one of the other types of synths, allowing any of the
+ * monophonic synthesizers to be polyphonic.
+ *
+ * @constructor
+ * @extends {Tone.Instrument}
+ * @param {number|Object} [polyphony=4] The number of voices to create
+ * @param {function} [voice=Tone.Synth] The constructor of the voices
+ * uses Tone.Synth by default.
+ * @example
+ * //a polysynth composed of 6 Voices of Synth
+ * var synth = new Tone.PolySynth(6, Tone.Synth).toMaster();
+ * //set the attributes using the set interface
+ * synth.set("detune", -1200);
+ * //play a chord
+ * synth.triggerAttackRelease(["C4", "E4", "A4"], "4n");
+ */
+ Tone.PolySynth = function () {
+ Tone.Instrument.call(this);
+ var options = this.optionsObject(arguments, [
+ 'polyphony',
+ 'voice'
+ ], Tone.PolySynth.defaults);
+ options = this.defaultArg(options, Tone.Instrument.defaults);
+ //max polyphony
+ options.polyphony = Math.min(Tone.PolySynth.MAX_POLYPHONY, options.polyphony);
+ /**
+ * the array of voices
+ * @type {Array}
+ */
+ this.voices = new Array(options.polyphony);
+ /**
+ * The queue of voices with data about last trigger
+ * and the triggered note
+ * @private
+ * @type {Array}
+ */
+ this._triggers = new Array(options.polyphony);
+ /**
+ * The detune in cents
+ * @type {Cents}
+ * @signal
+ */
+ this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
+ this._readOnly('detune');
+ //create the voices
+ for (var i = 0; i < options.polyphony; i++) {
+ var v = new options.voice(arguments[2], arguments[3]);
+ this.voices[i] = v;
+ v.connect(this.output);
+ if (v.hasOwnProperty('detune')) {
+ this.detune.connect(v.detune);
+ }
+ this._triggers[i] = {
+ release: -1,
+ note: null,
+ voice: v
+ };
+ }
+ //set the volume initially
+ this.volume.value = options.volume;
+ };
+ Tone.extend(Tone.PolySynth, Tone.Instrument);
+ /**
+ * the defaults
+ * @const
+ * @static
+ * @type {Object}
+ */
+ Tone.PolySynth.defaults = {
+ 'polyphony': 4,
+ 'volume': 0,
+ 'detune': 0,
+ 'voice': Tone.Synth
+ };
+ /**
+ * Trigger the attack portion of the note
+ * @param {Frequency|Array} notes The notes to play. Accepts a single
+ * Frequency or an array of frequencies.
+ * @param {Time} [time=now] The start time of the note.
+ * @param {number} [velocity=1] The velocity of the note.
+ * @returns {Tone.PolySynth} this
+ * @example
+ * //trigger a chord immediately with a velocity of 0.2
+ * poly.triggerAttack(["Ab3", "C4", "F5"], undefined, 0.2);
+ */
+ Tone.PolySynth.prototype.triggerAttack = function (notes, time, velocity) {
+ if (!Array.isArray(notes)) {
+ notes = [notes];
+ }
+ time = this.toSeconds(time);
+ for (var i = 0; i < notes.length; i++) {
+ var val = notes[i];
+ //trigger the oldest voice
+ var oldest = this._triggers[0];
+ var oldestIndex = 0;
+ for (var j = 1; j < this._triggers.length; j++) {
+ if (this._triggers[j].release < oldest.release) {
+ oldest = this._triggers[j];
+ oldestIndex = j;
+ }
+ }
+ oldest.release = Infinity;
+ oldest.note = JSON.stringify(val);
+ oldest.voice.triggerAttack(val, time, velocity);
+ }
+ return this;
+ };
+ /**
+ * Trigger the attack and release after the specified duration
+ *
+ * @param {Frequency|Array} notes The notes to play. Accepts a single
+ * Frequency or an array of frequencies.
+ * @param {Time} duration the duration of the note
+ * @param {Time} [time=now] if no time is given, defaults to now
+ * @param {number} [velocity=1] the velocity of the attack (0-1)
+ * @returns {Tone.PolySynth} this
+ * @example
+ * //trigger a chord for a duration of a half note
+ * poly.triggerAttackRelease(["Eb3", "G4", "C5"], "2n");
+ * @example
+ * //can pass in an array of durations as well
+ * poly.triggerAttackRelease(["Eb3", "G4", "C5"], ["2n", "4n", "4n"]);
+ */
+ Tone.PolySynth.prototype.triggerAttackRelease = function (notes, duration, time, velocity) {
+ time = this.toSeconds(time);
+ this.triggerAttack(notes, time, velocity);
+ if (this.isArray(duration) && this.isArray(notes)) {
+ for (var i = 0; i < notes.length; i++) {
+ var d = duration[Math.min(i, duration.length - 1)];
+ this.triggerRelease(notes[i], time + this.toSeconds(d));
+ }
+ } else {
+ this.triggerRelease(notes, time + this.toSeconds(duration));
+ }
+ return this;
+ };
+ /**
+ * Trigger the release of the note. Unlike monophonic instruments,
+ * a note (or array of notes) needs to be passed in as the first argument.
+ * @param {Frequency|Array} notes The notes to play. Accepts a single
+ * Frequency or an array of frequencies.
+ * @param {Time} [time=now] When the release will be triggered.
+ * @returns {Tone.PolySynth} this
+ * @example
+ * poly.triggerRelease(["Ab3", "C4", "F5"], "+2n");
+ */
+ Tone.PolySynth.prototype.triggerRelease = function (notes, time) {
+ if (!Array.isArray(notes)) {
+ notes = [notes];
+ }
+ time = this.toSeconds(time);
+ for (var i = 0; i < notes.length; i++) {
+ //get the voice
+ var stringified = JSON.stringify(notes[i]);
+ for (var v = 0; v < this._triggers.length; v++) {
+ var desc = this._triggers[v];
+ if (desc.note === stringified && desc.release > time) {
+ desc.voice.triggerRelease(time);
+ desc.release = time;
+ }
+ }
+ }
+ return this;
+ };
+ /**
+ * Set a member/attribute of the voices.
+ * @param {Object|string} params
+ * @param {number=} value
+ * @param {Time=} rampTime
+ * @returns {Tone.PolySynth} this
+ * @example
+ * poly.set({
+ * "filter" : {
+ * "type" : "highpass"
+ * },
+ * "envelope" : {
+ * "attack" : 0.25
+ * }
+ * });
+ */
+ Tone.PolySynth.prototype.set = function (params, value, rampTime) {
+ for (var i = 0; i < this.voices.length; i++) {
+ this.voices[i].set(params, value, rampTime);
+ }
+ return this;
+ };
+ /**
+ * Get the synth's attributes. Given no arguments get
+ * will return all available object properties and their corresponding
+ * values. Pass in a single attribute to retrieve or an array
+ * of attributes. The attribute strings can also include a "."
+ * to access deeper properties.
+ * @param {Array=} params the parameters to get, otherwise will return
+ * all available.
+ */
+ Tone.PolySynth.prototype.get = function (params) {
+ return this.voices[0].get(params);
+ };
+ /**
+ * Trigger the release portion of all the currently active voices.
+ * @param {Time} [time=now] When the notes should be released.
+ * @return {Tone.PolySynth} this
+ */
+ Tone.PolySynth.prototype.releaseAll = function (time) {
+ time = this.toSeconds(time);
+ for (var i = 0; i < this._triggers.length; i++) {
+ var desc = this._triggers[i];
+ if (desc.release > time) {
+ desc.release = time;
+ desc.voice.triggerRelease(time);
+ }
+ }
+ return this;
+ };
+ /**
+ * Clean up.
+ * @returns {Tone.PolySynth} this
+ */
+ Tone.PolySynth.prototype.dispose = function () {
+ Tone.Instrument.prototype.dispose.call(this);
+ for (var i = 0; i < this.voices.length; i++) {
+ this.voices[i].dispose();
+ this.voices[i] = null;
+ }
+ this._writable('detune');
+ this.detune.dispose();
+ this.detune = null;
+ this.voices = null;
+ this._triggers = null;
+ return this;
+ };
+ /**
+ * The maximum number of notes that can be allocated
+ * to a polysynth.
+ * @type {Number}
+ * @static
+ */
+ Tone.PolySynth.MAX_POLYPHONY = 20;
+ return Tone.PolySynth;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.Player is an audio file player with start, loop, and stop functions.
+ *
+ * @constructor
+ * @extends {Tone.Source}
+ * @param {string|AudioBuffer} url Either the AudioBuffer or the url from
+ * which to load the AudioBuffer
+ * @param {function=} onload The function to invoke when the buffer is loaded.
+ * Recommended to use Tone.Buffer.on('load') instead.
+ * @example
+ * var player = new Tone.Player("./path/to/sample.mp3").toMaster();
+ * //play as soon as the buffer is loaded
+ * player.autostart = true;
+ */
+ Tone.Player = function (url) {
+ var options;
+ if (url instanceof Tone.Buffer) {
+ url = url.get();
+ options = Tone.Player.defaults;
+ } else {
+ options = this.optionsObject(arguments, [
+ 'url',
+ 'onload'
+ ], Tone.Player.defaults);
+ }
+ Tone.Source.call(this, options);
+ /**
+ * @private
+ * @type {AudioBufferSourceNode}
+ */
+ this._source = null;
+ /**
+ * If the file should play as soon
+ * as the buffer is loaded.
+ * @type {boolean}
+ * @example
+ * //will play as soon as it's loaded
+ * var player = new Tone.Player({
+ * "url" : "./path/to/sample.mp3",
+ * "autostart" : true,
+ * }).toMaster();
+ */
+ this.autostart = options.autostart;
+ /**
+ * the buffer
+ * @private
+ * @type {Tone.Buffer}
+ */
+ this._buffer = new Tone.Buffer({
+ 'url': options.url,
+ 'onload': this._onload.bind(this, options.onload),
+ 'reverse': options.reverse
+ });
+ if (url instanceof AudioBuffer) {
+ this._buffer.set(url);
+ }
+ /**
+ * if the buffer should loop once it's over
+ * @type {boolean}
+ * @private
+ */
+ this._loop = options.loop;
+ /**
+ * if 'loop' is true, the loop will start at this position
+ * @type {Time}
+ * @private
+ */
+ this._loopStart = options.loopStart;
+ /**
+ * if 'loop' is true, the loop will end at this position
+ * @type {Time}
+ * @private
+ */
+ this._loopEnd = options.loopEnd;
+ /**
+ * the playback rate
+ * @private
+ * @type {number}
+ */
+ this._playbackRate = options.playbackRate;
+ /**
+ * Enabling retrigger will allow a player to be restarted
+ * before the the previous 'start' is done playing. Otherwise,
+ * successive calls to Tone.Player.start will only start
+ * the sample if it had played all the way through.
+ * @type {boolean}
+ */
+ this.retrigger = options.retrigger;
+ };
+ Tone.extend(Tone.Player, Tone.Source);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.Player.defaults = {
+ 'onload': Tone.noOp,
+ 'playbackRate': 1,
+ 'loop': false,
+ 'autostart': false,
+ 'loopStart': 0,
+ 'loopEnd': 0,
+ 'retrigger': false,
+ 'reverse': false
+ };
+ /**
+ * Load the audio file as an audio buffer.
+ * Decodes the audio asynchronously and invokes
+ * the callback once the audio buffer loads.
+ * Note: this does not need to be called if a url
+ * was passed in to the constructor. Only use this
+ * if you want to manually load a new url.
+ * @param {string} url The url of the buffer to load.
+ * Filetype support depends on the
+ * browser.
+ * @param {function=} callback The function to invoke once
+ * the sample is loaded.
+ * @returns {Promise}
+ */
+ Tone.Player.prototype.load = function (url, callback) {
+ return this._buffer.load(url, this._onload.bind(this, callback));
+ };
+ /**
+ * Internal callback when the buffer is loaded.
+ * @private
+ */
+ Tone.Player.prototype._onload = function (callback) {
+ callback = this.defaultArg(callback, Tone.noOp);
+ callback(this);
+ if (this.autostart) {
+ this.start();
+ }
+ };
+ /**
+ * Play the buffer at the given startTime. Optionally add an offset
+ * and/or duration which will play the buffer from a position
+ * within the buffer for the given duration.
+ *
+ * @param {Time} [startTime=now] When the player should start.
+ * @param {Time} [offset=0] The offset from the beginning of the sample
+ * to start at.
+ * @param {Time=} duration How long the sample should play. If no duration
+ * is given, it will default to the full length
+ * of the sample (minus any offset)
+ * @returns {Tone.Player} this
+ * @memberOf Tone.Player#
+ * @method start
+ * @name start
+ */
+ /**
+ * Internal start method
+ * @private
+ */
+ Tone.Player.prototype._start = function (startTime, offset, duration) {
+ if (this._buffer.loaded) {
+ //if it's a loop the default offset is the loopstart point
+ if (this._loop) {
+ offset = this.defaultArg(offset, this._loopStart);
+ } else {
+ //otherwise the default offset is 0
+ offset = this.defaultArg(offset, 0);
+ }
+ offset = this.toSeconds(offset);
+ //make sure it has a positive duration
+ duration = this.defaultArg(duration, Math.max(this._buffer.duration - offset, 0));
+ duration = this.toSeconds(duration);
+ //the values in seconds
+ startTime = this.toSeconds(startTime);
+ //make the source
+ this._source = this.context.createBufferSource();
+ this._source.buffer = this._buffer.get();
+ //set the looping properties
+ if (this._loop) {
+ this._source.loop = this._loop;
+ this._source.loopStart = this.toSeconds(this._loopStart);
+ this._source.loopEnd = this.toSeconds(this._loopEnd);
+ } else if (!this._synced) {
+ //if it's not looping, set the state change at the end of the sample
+ this._state.setStateAtTime(Tone.State.Stopped, startTime + duration);
+ }
+ //and other properties
+ this._source.playbackRate.value = this._playbackRate;
+ this._source.connect(this.output);
+ //start it
+ if (this._loop) {
+ //modify the offset if it's greater than the loop time
+ var loopEnd = this._source.loopEnd || this._buffer.duration;
+ var loopStart = this._source.loopStart;
+ var loopDuration = loopEnd - loopStart;
+ if (offset > loopEnd) {
+ //move the offset back
+ while (offset > loopEnd) {
+ offset -= loopDuration;
+ }
+ }
+ this._source.start(startTime, offset);
+ } else {
+ this._source.start(startTime, offset, duration);
+ }
+ } else {
+ throw Error('Tone.Player: tried to start Player before the buffer was loaded');
+ }
+ return this;
+ };
+ /**
+ * Stop playback.
+ * @private
+ * @param {Time} [time=now]
+ * @returns {Tone.Player} this
+ */
+ Tone.Player.prototype._stop = function (time) {
+ if (this._source) {
+ this._source.stop(this.toSeconds(time));
+ this._source = null;
+ }
+ return this;
+ };
+ /**
+ * Seek to a specific time in the player's buffer. If the
+ * source is no longer playing at that time, it will stop.
+ * If you seek to a time that
+ * @param {Time} offset The time to seek to.
+ * @param {Time=} time The time for the seek event to occur.
+ * @return {Tone.Player} this
+ * @example
+ * source.start(0.2);
+ * source.stop(0.4);
+ */
+ Tone.Player.prototype.seek = function (offset, time) {
+ time = this.toSeconds(time);
+ if (this._state.getValueAtTime(time) === Tone.State.Started) {
+ offset = this.toSeconds(offset);
+ // if it's currently playing, stop it
+ this._stop(time);
+ //restart it at the given time
+ this._start(time, offset);
+ }
+ return this;
+ };
+ /**
+ * Set the loop start and end. Will only loop if loop is
+ * set to true.
+ * @param {Time} loopStart The loop end time
+ * @param {Time} loopEnd The loop end time
+ * @returns {Tone.Player} this
+ * @example
+ * //loop 0.1 seconds of the file.
+ * player.setLoopPoints(0.2, 0.3);
+ * player.loop = true;
+ */
+ Tone.Player.prototype.setLoopPoints = function (loopStart, loopEnd) {
+ this.loopStart = loopStart;
+ this.loopEnd = loopEnd;
+ return this;
+ };
+ /**
+ * If loop is true, the loop will start at this position.
+ * @memberOf Tone.Player#
+ * @type {Time}
+ * @name loopStart
+ */
+ Object.defineProperty(Tone.Player.prototype, 'loopStart', {
+ get: function () {
+ return this._loopStart;
+ },
+ set: function (loopStart) {
+ this._loopStart = loopStart;
+ if (this._source) {
+ this._source.loopStart = this.toSeconds(loopStart);
+ }
+ }
+ });
+ /**
+ * If loop is true, the loop will end at this position.
+ * @memberOf Tone.Player#
+ * @type {Time}
+ * @name loopEnd
+ */
+ Object.defineProperty(Tone.Player.prototype, 'loopEnd', {
+ get: function () {
+ return this._loopEnd;
+ },
+ set: function (loopEnd) {
+ this._loopEnd = loopEnd;
+ if (this._source) {
+ this._source.loopEnd = this.toSeconds(loopEnd);
+ }
+ }
+ });
+ /**
+ * The audio buffer belonging to the player.
+ * @memberOf Tone.Player#
+ * @type {Tone.Buffer}
+ * @name buffer
+ */
+ Object.defineProperty(Tone.Player.prototype, 'buffer', {
+ get: function () {
+ return this._buffer;
+ },
+ set: function (buffer) {
+ this._buffer.set(buffer);
+ }
+ });
+ /**
+ * If the buffer should loop once it's over.
+ * @memberOf Tone.Player#
+ * @type {boolean}
+ * @name loop
+ */
+ Object.defineProperty(Tone.Player.prototype, 'loop', {
+ get: function () {
+ return this._loop;
+ },
+ set: function (loop) {
+ this._loop = loop;
+ if (this._source) {
+ this._source.loop = loop;
+ }
+ }
+ });
+ /**
+ * The playback speed. 1 is normal speed. This is not a signal because
+ * Safari and iOS currently don't support playbackRate as a signal.
+ * @memberOf Tone.Player#
+ * @type {number}
+ * @name playbackRate
+ */
+ Object.defineProperty(Tone.Player.prototype, 'playbackRate', {
+ get: function () {
+ return this._playbackRate;
+ },
+ set: function (rate) {
+ this._playbackRate = rate;
+ if (this._source) {
+ this._source.playbackRate.value = rate;
+ }
+ }
+ });
+ /**
+ * The direction the buffer should play in
+ * @memberOf Tone.Player#
+ * @type {boolean}
+ * @name reverse
+ */
+ Object.defineProperty(Tone.Player.prototype, 'reverse', {
+ get: function () {
+ return this._buffer.reverse;
+ },
+ set: function (rev) {
+ this._buffer.reverse = rev;
+ }
+ });
+ /**
+ * Dispose and disconnect.
+ * @return {Tone.Player} this
+ */
+ Tone.Player.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ if (this._source !== null) {
+ this._source.disconnect();
+ this._source = null;
+ }
+ this._buffer.dispose();
+ this._buffer = null;
+ return this;
+ };
+ return Tone.Player;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Sampler wraps Tone.Player in an AmplitudeEnvelope.
+ *
+ * @constructor
+ * @extends {Tone.Instrument}
+ * @param {String} url the url of the audio file
+ * @param {Function=} onload The callback to invoke when the sample is loaded.
+ * @example
+ * var sampler = new Sampler("./audio/casio/A1.mp3", function(){
+ * //repitch the sample down a half step
+ * sampler.triggerAttack(-1);
+ * }).toMaster();
+ */
+ Tone.Sampler = function () {
+ var options = this.optionsObject(arguments, [
+ 'url',
+ 'onload'
+ ], Tone.Sampler.defaults);
+ Tone.Instrument.call(this, options);
+ /**
+ * The sample player.
+ * @type {Tone.Player}
+ */
+ this.player = new Tone.Player(options.url, options.onload);
+ this.player.retrigger = true;
+ /**
+ * The amplitude envelope.
+ * @type {Tone.AmplitudeEnvelope}
+ */
+ this.envelope = new Tone.AmplitudeEnvelope(options.envelope);
+ this.player.chain(this.envelope, this.output);
+ this._readOnly([
+ 'player',
+ 'envelope'
+ ]);
+ this.loop = options.loop;
+ this.reverse = options.reverse;
+ };
+ Tone.extend(Tone.Sampler, Tone.Instrument);
+ /**
+ * the default parameters
+ * @static
+ */
+ Tone.Sampler.defaults = {
+ 'onload': Tone.noOp,
+ 'loop': false,
+ 'reverse': false,
+ 'envelope': {
+ 'attack': 0.001,
+ 'decay': 0,
+ 'sustain': 1,
+ 'release': 0.1
+ }
+ };
+ /**
+ * Trigger the start of the sample.
+ * @param {Interval} [pitch=0] The amount the sample should
+ * be repitched.
+ * @param {Time} [time=now] The time when the sample should start
+ * @param {NormalRange} [velocity=1] The velocity of the note
+ * @returns {Tone.Sampler} this
+ * @example
+ * sampler.triggerAttack(0, "+0.1", 0.5);
+ */
+ Tone.Sampler.prototype.triggerAttack = function (pitch, time, velocity) {
+ time = this.toSeconds(time);
+ pitch = this.defaultArg(pitch, 0);
+ this.player.playbackRate = this.intervalToFrequencyRatio(pitch);
+ this.player.start(time);
+ this.envelope.triggerAttack(time, velocity);
+ return this;
+ };
+ /**
+ * Start the release portion of the sample. Will stop the sample once the
+ * envelope has fully released.
+ *
+ * @param {Time} [time=now] The time when the note should release
+ * @returns {Tone.Sampler} this
+ * @example
+ * sampler.triggerRelease();
+ */
+ Tone.Sampler.prototype.triggerRelease = function (time) {
+ time = this.toSeconds(time);
+ this.envelope.triggerRelease(time);
+ this.player.stop(this.toSeconds(this.envelope.release) + time);
+ return this;
+ };
+ /**
+ * Trigger the attack and then the release after the duration.
+ * @param {Interval} interval The interval in half-steps that the
+ * sample should be pitch shifted.
+ * @param {Time} duration How long the note should be held for before
+ * triggering the release.
+ * @param {Time} [time=now] When the note should be triggered.
+ * @param {NormalRange} [velocity=1] The velocity the note should be triggered at.
+ * @returns {Tone.Sampler} this
+ * @example
+ * //trigger the unpitched note for the duration of an 8th note
+ * synth.triggerAttackRelease(0, "8n");
+ * @memberOf Tone.Sampler#
+ * @name triggerAttackRelease
+ * @method triggerAttackRelease
+ */
+ /**
+ * If the output sample should loop or not.
+ * @memberOf Tone.Sampler#
+ * @type {number|string}
+ * @name loop
+ */
+ Object.defineProperty(Tone.Sampler.prototype, 'loop', {
+ get: function () {
+ return this.player.loop;
+ },
+ set: function (loop) {
+ this.player.loop = loop;
+ }
+ });
+ /**
+ * The direction the buffer should play in
+ * @memberOf Tone.Sampler#
+ * @type {boolean}
+ * @name reverse
+ */
+ Object.defineProperty(Tone.Sampler.prototype, 'reverse', {
+ get: function () {
+ return this.player.reverse;
+ },
+ set: function (rev) {
+ this.player.reverse = rev;
+ }
+ });
+ /**
+ * The buffer to play.
+ * @memberOf Tone.Sampler#
+ * @type {Tone.Buffer}
+ * @name buffer
+ */
+ Object.defineProperty(Tone.Sampler.prototype, 'buffer', {
+ get: function () {
+ return this.player.buffer;
+ },
+ set: function (buff) {
+ this.player.buffer = buff;
+ }
+ });
+ /**
+ * Clean up.
+ * @returns {Tone.Sampler} this
+ */
+ Tone.Sampler.prototype.dispose = function () {
+ Tone.Instrument.prototype.dispose.call(this);
+ this._writable([
+ 'player',
+ 'envelope'
+ ]);
+ this.player.dispose();
+ this.player = null;
+ this.envelope.dispose();
+ this.envelope = null;
+ return this;
+ };
+ return Tone.Sampler;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Maps a NormalRange [0, 1] to an AudioRange [-1, 1].
+ * See also Tone.AudioToGain.
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @example
+ * var g2a = new Tone.GainToAudio();
+ */
+ Tone.GainToAudio = function () {
+ /**
+ * @type {WaveShaperNode}
+ * @private
+ */
+ this._norm = this.input = this.output = new Tone.WaveShaper(function (x) {
+ return Math.abs(x) * 2 - 1;
+ });
+ };
+ Tone.extend(Tone.GainToAudio, Tone.SignalBase);
+ /**
+ * clean up
+ * @returns {Tone.GainToAudio} this
+ */
+ Tone.GainToAudio.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._norm.dispose();
+ this._norm = null;
+ return this;
+ };
+ return Tone.GainToAudio;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Normalize takes an input min and max and maps it linearly to NormalRange [0,1]
+ *
+ * @extends {Tone.SignalBase}
+ * @constructor
+ * @param {number} inputMin the min input value
+ * @param {number} inputMax the max input value
+ * @example
+ * var norm = new Tone.Normalize(2, 4);
+ * var sig = new Tone.Signal(3).connect(norm);
+ * //output of norm is 0.5.
+ */
+ Tone.Normalize = function (inputMin, inputMax) {
+ /**
+ * the min input value
+ * @type {number}
+ * @private
+ */
+ this._inputMin = this.defaultArg(inputMin, 0);
+ /**
+ * the max input value
+ * @type {number}
+ * @private
+ */
+ this._inputMax = this.defaultArg(inputMax, 1);
+ /**
+ * subtract the min from the input
+ * @type {Tone.Add}
+ * @private
+ */
+ this._sub = this.input = new Tone.Add(0);
+ /**
+ * divide by the difference between the input and output
+ * @type {Tone.Multiply}
+ * @private
+ */
+ this._div = this.output = new Tone.Multiply(1);
+ this._sub.connect(this._div);
+ this._setRange();
+ };
+ Tone.extend(Tone.Normalize, Tone.SignalBase);
+ /**
+ * The minimum value the input signal will reach.
+ * @memberOf Tone.Normalize#
+ * @type {number}
+ * @name min
+ */
+ Object.defineProperty(Tone.Normalize.prototype, 'min', {
+ get: function () {
+ return this._inputMin;
+ },
+ set: function (min) {
+ this._inputMin = min;
+ this._setRange();
+ }
+ });
+ /**
+ * The maximum value the input signal will reach.
+ * @memberOf Tone.Normalize#
+ * @type {number}
+ * @name max
+ */
+ Object.defineProperty(Tone.Normalize.prototype, 'max', {
+ get: function () {
+ return this._inputMax;
+ },
+ set: function (max) {
+ this._inputMax = max;
+ this._setRange();
+ }
+ });
+ /**
+ * set the values
+ * @private
+ */
+ Tone.Normalize.prototype._setRange = function () {
+ this._sub.value = -this._inputMin;
+ this._div.value = 1 / (this._inputMax - this._inputMin);
+ };
+ /**
+ * clean up
+ * @returns {Tone.Normalize} this
+ */
+ Tone.Normalize.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._sub.dispose();
+ this._sub = null;
+ this._div.dispose();
+ this._div = null;
+ return this;
+ };
+ return Tone.Normalize;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.MultiPlayer is well suited for one-shots, multi-sampled instruments
+ * or any time you need to play a bunch of audio buffers.
+ * @param {Object|Array|Tone.Buffers} buffers The buffers which are available
+ * to the MultiPlayer
+ * @param {Function} onload The callback to invoke when all of the buffers are loaded.
+ * @extends {Tone}
+ * @example
+ * var multiPlayer = new MultiPlayer({
+ * "kick" : "path/to/kick.mp3",
+ * "snare" : "path/to/snare.mp3",
+ * }, function(){
+ * multiPlayer.start("kick");
+ * });
+ * @example
+ * //can also store the values in an array
+ * var multiPlayer = new MultiPlayer(["path/to/kick.mp3", "path/to/snare.mp3"],
+ * function(){
+ * //if an array is passed in, the samples are referenced to by index
+ * multiPlayer.start(1);
+ * });
+ */
+ Tone.MultiPlayer = function () {
+ var options = this.optionsObject(arguments, [
+ 'urls',
+ 'onload'
+ ], Tone.MultiPlayer.defaults);
+ if (options.urls instanceof Tone.Buffers) {
+ /**
+ * All the buffers belonging to the player.
+ * @type {Tone.Buffers}
+ */
+ this.buffers = options.urls;
+ } else {
+ this.buffers = new Tone.Buffers(options.urls, options.onload);
+ }
+ /**
+ * Keeps track of the currently playing sources.
+ * @type {Object}
+ * @private
+ */
+ this._activeSources = {};
+ /**
+ * The fade in envelope which is applied
+ * to the beginning of the BufferSource
+ * @type {Time}
+ */
+ this.fadeIn = options.fadeIn;
+ /**
+ * The fade out envelope which is applied
+ * to the end of the BufferSource
+ * @type {Time}
+ */
+ this.fadeOut = options.fadeOut;
+ /**
+ * The output volume node
+ * @type {Tone.Volume}
+ * @private
+ */
+ this._volume = this.output = new Tone.Volume(options.volume);
+ /**
+ * The volume of the output in decibels.
+ * @type {Decibels}
+ * @signal
+ * @example
+ * source.volume.value = -6;
+ */
+ this.volume = this._volume.volume;
+ this._readOnly('volume');
+ //make the output explicitly stereo
+ this._volume.output.output.channelCount = 2;
+ this._volume.output.output.channelCountMode = 'explicit';
+ //mute initially
+ this.mute = options.mute;
+ };
+ Tone.extend(Tone.MultiPlayer, Tone.Source);
+ /**
+ * The defaults
+ * @type {Object}
+ */
+ Tone.MultiPlayer.defaults = {
+ 'onload': Tone.noOp,
+ 'fadeIn': 0,
+ 'fadeOut': 0
+ };
+ /**
+ * Make the source from the buffername
+ * @param {String} bufferName
+ * @return {Tone.BufferSource}
+ * @private
+ */
+ Tone.MultiPlayer.prototype._makeSource = function (bufferName) {
+ var buffer;
+ if (this.isString(bufferName) || this.isNumber(bufferName)) {
+ buffer = this.buffers.get(bufferName).get();
+ } else if (bufferName instanceof Tone.Buffer) {
+ buffer = bufferName.get();
+ } else if (bufferName instanceof AudioBuffer) {
+ buffer = bufferName;
+ }
+ var source = new Tone.BufferSource(buffer).connect(this.output);
+ if (!this._activeSources.hasOwnProperty(bufferName)) {
+ this._activeSources[bufferName] = [];
+ }
+ this._activeSources[bufferName].push(source);
+ return source;
+ };
+ /**
+ * Start a buffer by name. The `start` method allows a number of options
+ * to be passed in such as offset, interval, and gain. This is good for multi-sampled
+ * instruments and sound sprites where samples are repitched played back at different velocities.
+ * @param {String} bufferName The name of the buffer to start.
+ * @param {Time} time When to start the buffer.
+ * @param {Time} [offset=0] The offset into the buffer to play from.
+ * @param {Time=} duration How long to play the buffer for.
+ * @param {Interval} [pitch=0] The interval to repitch the buffer.
+ * @param {Gain} [gain=1] The gain to play the sample at.
+ * @return {Tone.MultiPlayer} this
+ */
+ Tone.MultiPlayer.prototype.start = function (bufferName, time, offset, duration, pitch, gain) {
+ time = this.toSeconds(time);
+ var source = this._makeSource(bufferName);
+ source.start(time, offset, duration, this.defaultArg(gain, 1), this.fadeIn);
+ if (duration) {
+ source.stop(time + this.toSeconds(duration), this.fadeOut);
+ }
+ pitch = this.defaultArg(pitch, 0);
+ source.playbackRate.value = this.intervalToFrequencyRatio(pitch);
+ return this;
+ };
+ /**
+ * Start a looping buffer by name. Similar to `start`, but the buffer
+ * is looped instead of played straight through. Can still be stopped with `stop`.
+ * @param {String} bufferName The name of the buffer to start.
+ * @param {Time} time When to start the buffer.
+ * @param {Time} [offset=0] The offset into the buffer to play from.
+ * @param {Time=} loopStart The start of the loop.
+ * @param {Time=} loopEnd The end of the loop.
+ * @param {Interval} [pitch=0] The interval to repitch the buffer.
+ * @param {Gain} [gain=1] The gain to play the sample at.
+ * @return {Tone.MultiPlayer} this
+ */
+ Tone.MultiPlayer.prototype.startLoop = function (bufferName, time, offset, loopStart, loopEnd, pitch, gain) {
+ time = this.toSeconds(time);
+ var source = this._makeSource(bufferName);
+ source.loop = true;
+ source.loopStart = this.toSeconds(this.defaultArg(loopStart, 0));
+ source.loopEnd = this.toSeconds(this.defaultArg(loopEnd, 0));
+ source.start(time, offset, undefined, this.defaultArg(gain, 1), this.fadeIn);
+ pitch = this.defaultArg(pitch, 0);
+ source.playbackRate.value = this.intervalToFrequencyRatio(pitch);
+ return this;
+ };
+ /**
+ * Stop the first played instance of the buffer name.
+ * @param {String} bufferName The buffer to stop.
+ * @param {Time=} time When to stop the buffer
+ * @return {Tone.MultiPlayer} this
+ */
+ Tone.MultiPlayer.prototype.stop = function (bufferName, time) {
+ if (this._activeSources[bufferName] && this._activeSources[bufferName].length) {
+ time = this.toSeconds(time);
+ this._activeSources[bufferName].shift().stop(time, this.fadeOut);
+ } else {
+ throw new Error('Tone.MultiPlayer: cannot stop a buffer that hasn\'t been started or is already stopped');
+ }
+ return this;
+ };
+ /**
+ * Stop all currently playing buffers at the given time.
+ * @param {Time=} time When to stop the buffers.
+ * @return {Tone.MultiPlayer} this
+ */
+ Tone.MultiPlayer.prototype.stopAll = function (time) {
+ time = this.toSeconds(time);
+ for (var bufferName in this._activeSources) {
+ var sources = this._activeSources[bufferName];
+ for (var i = 0; i < sources.length; i++) {
+ sources[i].stop(time);
+ }
+ }
+ return this;
+ };
+ /**
+ * Add another buffer to the available buffers.
+ * @param {String} name The name to that the buffer is refered
+ * to in start/stop methods.
+ * @param {String|Tone.Buffer} url The url of the buffer to load
+ * or the buffer.
+ * @param {Function} callback The function to invoke after the buffer is loaded.
+ */
+ Tone.MultiPlayer.prototype.add = function (name, url, callback) {
+ this.buffers.add(name, url, callback);
+ return this;
+ };
+ /**
+ * Returns the playback state of the source. "started"
+ * if there are any buffers playing. "stopped" otherwise.
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.MultiPlayer#
+ * @name state
+ */
+ Object.defineProperty(Tone.MultiPlayer.prototype, 'state', {
+ get: function () {
+ return this._activeSources.length > 0 ? Tone.State.Started : Tone.State.Stopped;
+ }
+ });
+ /**
+ * Mute the output.
+ * @memberOf Tone.MultiPlayer#
+ * @type {boolean}
+ * @name mute
+ * @example
+ * //mute the output
+ * source.mute = true;
+ */
+ Object.defineProperty(Tone.MultiPlayer.prototype, 'mute', {
+ get: function () {
+ return this._volume.mute;
+ },
+ set: function (mute) {
+ this._volume.mute = mute;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.MultiPlayer} this
+ */
+ Tone.MultiPlayer.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this._volume.dispose();
+ this._volume = null;
+ this._writable('volume');
+ this.volume = null;
+ for (var bufferName in this._activeSources) {
+ this._activeSources[bufferName].forEach(function (source) {
+ source.dispose();
+ });
+ }
+ this.buffers.dispose();
+ this.buffers = null;
+ this._activeSources = null;
+ return this;
+ };
+ return Tone.MultiPlayer;
+ });
+ Module(function (Tone) {
+ /**
+ * @class Tone.GrainPlayer implements [granular synthesis](https://en.wikipedia.org/wiki/Granular_synthesis).
+ * Granular Synthesis enables you to adjust pitch and playback rate independently. The grainSize is the
+ * amount of time each small chunk of audio is played for and the overlap is the
+ * amount of crossfading transition time between successive grains.
+ * @extends {Tone}
+ * @param {String|Tone.Buffer} url The url to load, or the Tone.Buffer to play.
+ * @param {Function=} callback The callback to invoke after the url is loaded.
+ */
+ Tone.GrainPlayer = function () {
+ var options = this.optionsObject(arguments, [
+ 'url',
+ 'onload'
+ ], Tone.GrainPlayer.defaults);
+ Tone.Source.call(this);
+ /**
+ * The audio buffer belonging to the player.
+ * @type {Tone.Buffer}
+ */
+ this.buffer = new Tone.Buffer(options.url, options.onload);
+ /**
+ * Plays the buffer with a small envelope
+ * @type {Tone.MultiPlayer}
+ * @private
+ */
+ this._player = new Tone.MultiPlayer().connect(this.output);
+ /**
+ * Create a repeating tick to schedule
+ * the grains.
+ * @type {Tone.Clock}
+ * @private
+ */
+ this._clock = new Tone.Clock(this._tick.bind(this), 1);
+ /**
+ * @type {Number}
+ * @private
+ */
+ this._loopStart = 0;
+ /**
+ * @type {Number}
+ * @private
+ */
+ this._loopEnd = 0;
+ /**
+ * @type {Number}
+ * @private
+ */
+ this._playbackRate = options.playbackRate;
+ /**
+ * @type {Number}
+ * @private
+ */
+ this._grainSize = options.grainSize;
+ /**
+ * @private
+ * @type {Number}
+ */
+ this._overlap = options.overlap;
+ /**
+ * Adjust the pitch independently of the playbackRate.
+ * @type {Cents}
+ */
+ this.detune = options.detune;
+ /**
+ * The amount of time randomly added
+ * or subtracted from the grain's offset
+ * @type {Time}
+ */
+ this.drift = options.drift;
+ //setup
+ this.overlap = options.overlap;
+ this.loop = options.loop;
+ this.playbackRate = options.playbackRate;
+ this.grainSize = options.grainSize;
+ this.loopStart = options.loopStart;
+ this.loopEnd = options.loopEnd;
+ this.reverse = options.reverse;
+ };
+ Tone.extend(Tone.GrainPlayer, Tone.Source);
+ /**
+ * the default parameters
+ * @static
+ * @const
+ * @type {Object}
+ */
+ Tone.GrainPlayer.defaults = {
+ 'onload': Tone.noOp,
+ 'overlap': 0.1,
+ 'grainSize': 0.2,
+ 'drift': 0,
+ 'playbackRate': 1,
+ 'detune': 0,
+ 'loop': false,
+ 'loopStart': 0,
+ 'loopEnd': 0,
+ 'reverse': false
+ };
+ /**
+ * Play the buffer at the given startTime. Optionally add an offset
+ * and/or duration which will play the buffer from a position
+ * within the buffer for the given duration.
+ *
+ * @param {Time} [startTime=now] When the player should start.
+ * @param {Time} [offset=0] The offset from the beginning of the sample
+ * to start at.
+ * @param {Time=} duration How long the sample should play. If no duration
+ * is given, it will default to the full length
+ * of the sample (minus any offset)
+ * @returns {Tone.GrainPlayer} this
+ * @memberOf Tone.GrainPlayer#
+ * @method start
+ * @name start
+ */
+ /**
+ * Internal start method
+ * @param {Time} time
+ * @param {Time} offset
+ * @private
+ */
+ Tone.GrainPlayer.prototype._start = function (time, offset, duration) {
+ offset = this.defaultArg(offset, 0);
+ offset = this.toSeconds(offset);
+ time = this.toSeconds(time);
+ this._offset = offset;
+ this._clock.start(time);
+ //unmute the player
+ this._player.volume.setValueAtTime(0, time);
+ if (duration) {
+ this._stop(time + this.toSeconds(duration));
+ }
+ };
+ /**
+ * Internal start method
+ * @param {Time} time
+ * @private
+ */
+ Tone.GrainPlayer.prototype._stop = function (time) {
+ this._clock.stop(time);
+ //mute the player
+ this._player.volume.cancelScheduledValues(time);
+ this._player.volume.setValueAtTime(-Infinity, time);
+ };
+ /**
+ * Invoked on each clock tick. scheduled a new
+ * grain at this time.
+ * @param {Time} time
+ * @private
+ */
+ Tone.GrainPlayer.prototype._tick = function (time) {
+ var bufferDuration = this.buffer.duration;
+ if (this.loop && this._loopEnd > 0) {
+ bufferDuration = this._loopEnd;
+ }
+ var drift = (Math.random() * 2 - 1) * this.drift;
+ var offset = this._offset - this._overlap + drift;
+ var detune = this.detune / 100;
+ //keep the offset within the limits of the buffer
+ offset = Math.max(offset, 0);
+ offset = Math.min(offset, bufferDuration);
+ var originalFadeIn = this._player.fadeIn;
+ if (this.loop && this._offset > bufferDuration) {
+ //play the end
+ var endSegmentDuration = this._offset - bufferDuration;
+ this._player.start(this.buffer, time, offset, endSegmentDuration + this._overlap, detune);
+ //and play the beginning
+ offset = this._offset % bufferDuration;
+ this._offset = this._loopStart;
+ this._player.fadeIn = 0;
+ this._player.start(this.buffer, time + endSegmentDuration, this._offset, offset + this._overlap, detune);
+ } else if (this._offset > bufferDuration) {
+ //set the state to stopped.
+ this.stop(time);
+ } else {
+ if (offset === 0) {
+ this._player.fadeIn = 0;
+ }
+ this._player.start(this.buffer, time, offset, this.grainSize + this._overlap, detune);
+ }
+ this._player.fadeIn = originalFadeIn;
+ //increment the offset
+ var duration = this._clock._nextTick - time;
+ this._offset += duration * this._playbackRate;
+ };
+ /**
+ * Jump to a specific time and play it.
+ * @param {Time} offset The offset to jump to.
+ * @param {Time=} time When to make the jump.
+ * @return {[type]} [description]
+ */
+ Tone.GrainPlayer.prototype.scrub = function (offset, time) {
+ this._offset = this.toSeconds(offset);
+ this._tick(this.toSeconds(time));
+ return this;
+ };
+ /**
+ * The playback rate of the sample
+ * @memberOf Tone.GrainPlayer#
+ * @type {Positive}
+ * @name playbackRate
+ */
+ Object.defineProperty(Tone.GrainPlayer.prototype, 'playbackRate', {
+ get: function () {
+ return this._playbackRate;
+ },
+ set: function (rate) {
+ this._playbackRate = rate;
+ this.grainSize = this._grainSize;
+ }
+ });
+ /**
+ * The loop start time.
+ * @memberOf Tone.GrainPlayer#
+ * @type {Time}
+ * @name loopStart
+ */
+ Object.defineProperty(Tone.GrainPlayer.prototype, 'loopStart', {
+ get: function () {
+ return this._loopStart;
+ },
+ set: function (time) {
+ this._loopStart = this.toSeconds(time);
+ }
+ });
+ /**
+ * The loop end time.
+ * @memberOf Tone.GrainPlayer#
+ * @type {Time}
+ * @name loopEnd
+ */
+ Object.defineProperty(Tone.GrainPlayer.prototype, 'loopEnd', {
+ get: function () {
+ return this._loopEnd;
+ },
+ set: function (time) {
+ this._loopEnd = this.toSeconds(time);
+ }
+ });
+ /**
+ * The direction the buffer should play in
+ * @memberOf Tone.GrainPlayer#
+ * @type {boolean}
+ * @name reverse
+ */
+ Object.defineProperty(Tone.GrainPlayer.prototype, 'reverse', {
+ get: function () {
+ return this.buffer.reverse;
+ },
+ set: function (rev) {
+ this.buffer.reverse = rev;
+ }
+ });
+ /**
+ * The size of each chunk of audio that the
+ * buffer is chopped into and played back at.
+ * @memberOf Tone.GrainPlayer#
+ * @type {Time}
+ * @name grainSize
+ */
+ Object.defineProperty(Tone.GrainPlayer.prototype, 'grainSize', {
+ get: function () {
+ return this._grainSize;
+ },
+ set: function (size) {
+ this._grainSize = this.toSeconds(size);
+ this._clock.frequency.value = this._playbackRate / this._grainSize;
+ }
+ });
+ /**
+ * This is the duration of the cross-fade between
+ * sucessive grains.
+ * @memberOf Tone.GrainPlayer#
+ * @type {Time}
+ * @name overlap
+ */
+ Object.defineProperty(Tone.GrainPlayer.prototype, 'overlap', {
+ get: function () {
+ return this._overlap;
+ },
+ set: function (time) {
+ time = this.toSeconds(time);
+ this._overlap = time;
+ if (this._overlap < 0) {
+ this._player.fadeIn = 0.01;
+ this._player.fadeOut = 0.01;
+ } else {
+ this._player.fadeIn = time;
+ this._player.fadeOut = time;
+ }
+ }
+ });
+ /**
+ * Clean up
+ * @return {Tone.GrainPlayer} this
+ */
+ Tone.GrainPlayer.prototype.dispose = function () {
+ Tone.Source.prototype.dispose.call(this);
+ this.buffer.dispose();
+ this.buffer = null;
+ this._player.dispose();
+ this._player = null;
+ this._clock.dispose();
+ this._clock = null;
+ return this;
+ };
+ return Tone.GrainPlayer;
+ });
+ Module(function (Tone) {
+
+ /**
+ * @class Tone.UserMedia uses MediaDevices.getUserMedia to open up
+ * and external microphone or audio input. Check
+ * [MediaDevices API Support](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)
+ * to see which browsers are supported. Access to an external input
+ * is limited to secure (HTTPS) connections.
+ *
+ * @constructor
+ * @extends {Tone}
+ * @param {Decibels=} volume The level of the input
+ * @example
+ * //list the inputs and open the third one
+ * var motu = new Tone.UserMedia();
+ *
+ * //opening the input asks the user to activate their mic
+ * motu.open().then(function(){
+ * //opening is activates the microphone
+ * //starting lets audio through
+ * motu.start(10);
+ * });
+ */
+ Tone.UserMedia = function () {
+ var options = this.optionsObject(arguments, ['volume'], Tone.UserMedia.defaults);
+ /**
+ * The MediaStreamNode
+ * @type {MediaStreamAudioSourceNode}
+ * @private
+ */
+ this._mediaStream = null;
+ /**
+ * The media stream created by getUserMedia.
+ * @type {LocalMediaStream}
+ * @private
+ */
+ this._stream = null;
+ /**
+ * The open device
+ * @type {MediaDeviceInfo}
+ * @private
+ */
+ this._device = null;
+ /**
+ * The output volume node
+ * @type {Tone.Volume}
+ * @private
+ */
+ this._volume = this.output = new Tone.Volume(options.volume);
+ /**
+ * The volume of the output in decibels.
+ * @type {Decibels}
+ * @signal
+ * @example
+ * input.volume.value = -6;
+ */
+ this.volume = this._volume.volume;
+ this._readOnly('volume');
+ this.mute = options.mute;
+ };
+ Tone.extend(Tone.UserMedia);
+ /**
+ * the default parameters
+ * @type {Object}
+ */
+ Tone.UserMedia.defaults = {
+ 'volume': 0,
+ 'mute': false
+ };
+ /**
+ * Open the media stream. If a string is passed in, it is assumed
+ * to be the label or id of the stream, if a number is passed in,
+ * it is the input number of the stream.
+ * @param {String|Number} [labelOrId="default"] The label or id of the audio input media device.
+ * With no argument, the default stream is opened.
+ * @return {Promise} The promise is resolved when the stream is open.
+ */
+ Tone.UserMedia.prototype.open = function (labelOrId) {
+ labelOrId = this.defaultArg(labelOrId, 'default');
+ return this.enumerateDevices().then(function (devices) {
+ var device;
+ if (this.isNumber(labelOrId)) {
+ device = devices[labelOrId];
+ } else {
+ device = devices.find(function (device) {
+ return device.label === labelOrId || device.deviceId === labelOrId;
+ });
+ if (!device) {
+ //otherwise just take the first one
+ device = devices[0];
+ }
+ }
+ //didn't find a matching device
+ if (!device) {
+ throw new Error('Tone.UserMedia: no matching audio inputs.');
+ }
+ this._device = device;
+ //do getUserMedia
+ var constraints = {
+ audio: {
+ 'deviceId': device.deviceId,
+ 'echoCancellation': false,
+ 'sampleRate': this.context.sampleRate
+ }
+ };
+ return navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
+ //start a new source only if the previous one is closed
+ if (!this._stream) {
+ this._stream = stream;
+ //Wrap a MediaStreamSourceNode around the live input stream.
+ this._mediaStream = this.context.createMediaStreamSource(stream);
+ //Connect the MediaStreamSourceNode to a gate gain node
+ this._mediaStream.connect(this.output);
+ }
+ return this;
+ }.bind(this));
+ }.bind(this));
+ };
+ /**
+ * Close the media stream
+ * @return {Tone.UserMedia} this
+ */
+ Tone.UserMedia.prototype.close = function () {
+ if (this._stream) {
+ this._stream.getAudioTracks().forEach(function (track) {
+ track.stop();
+ });
+ this._stream = null;
+ //remove the old media stream
+ this._mediaStream.disconnect();
+ this._mediaStream = null;
+ }
+ this._device = null;
+ return this;
+ };
+ /**
+ * Returns a promise which resolves with the list of audio input devices available.
+ * @return {Promise} The promise that is resolved with the devices
+ * @example
+ * extInput.enumerateDevices().then(function(devices){
+ * console.log(devices)
+ * })
+ */
+ Tone.UserMedia.prototype.enumerateDevices = function () {
+ return navigator.mediaDevices.enumerateDevices().then(function (devices) {
+ return devices.filter(function (device) {
+ return device.kind === 'audioinput';
+ });
+ });
+ };
+ /**
+ * Returns the playback state of the source, "started" when the microphone is open
+ * and "stopped" when the mic is closed.
+ * @type {Tone.State}
+ * @readOnly
+ * @memberOf Tone.UserMedia#
+ * @name state
+ */
+ Object.defineProperty(Tone.UserMedia.prototype, 'state', {
+ get: function () {
+ return this._stream && this._stream.active ? Tone.State.Started : Tone.State.Stopped;
+ }
+ });
+ /**
+ * Returns an identifier for the represented device that is
+ * persisted across sessions. It is un-guessable by other applications and
+ * unique to the origin of the calling application. It is reset when the
+ * user clears cookies (for Private Browsing, a different identifier is
+ * used that is not persisted across sessions). Returns undefined when the
+ * device is not open.
+ * @type {String}
+ * @readOnly
+ * @memberOf Tone.UserMedia#
+ * @name deviceId
+ */
+ Object.defineProperty(Tone.UserMedia.prototype, 'deviceId', {
+ get: function () {
+ if (this._device) {
+ return this._device.deviceId;
+ }
+ }
+ });
+ /**
+ * Returns a group identifier. Two devices have the
+ * same group identifier if they belong to the same physical device.
+ * Returns undefined when the device is not open.
+ * @type {String}
+ * @readOnly
+ * @memberOf Tone.UserMedia#
+ * @name groupId
+ */
+ Object.defineProperty(Tone.UserMedia.prototype, 'groupId', {
+ get: function () {
+ if (this._device) {
+ return this._device.groupId;
+ }
+ }
+ });
+ /**
+ * Returns a label describing this device (for example "Built-in Microphone").
+ * Returns undefined when the device is not open or label is not available
+ * because of permissions.
+ * @type {String}
+ * @readOnly
+ * @memberOf Tone.UserMedia#
+ * @name groupId
+ */
+ Object.defineProperty(Tone.UserMedia.prototype, 'label', {
+ get: function () {
+ if (this._device) {
+ return this._device.label;
+ }
+ }
+ });
+ /**
+ * Mute the output.
+ * @memberOf Tone.UserMedia#
+ * @type {boolean}
+ * @name mute
+ * @example
+ * //mute the output
+ * userMedia.mute = true;
+ */
+ Object.defineProperty(Tone.UserMedia.prototype, 'mute', {
+ get: function () {
+ return this._volume.mute;
+ },
+ set: function (mute) {
+ this._volume.mute = mute;
+ }
+ });
+ /**
+ * Clean up.
+ * @return {Tone.UserMedia} this
+ */
+ Tone.UserMedia.prototype.dispose = function () {
+ Tone.prototype.dispose.call(this);
+ this.close();
+ this._writable('volume');
+ this._volume.dispose();
+ this._volume = null;
+ this.volume = null;
+ return this;
+ };
+ /**
+ * If getUserMedia is supported by the browser.
+ * @type {Boolean}
+ * @memberOf Tone.UserMedia#
+ * @name supported
+ * @static
+ * @readOnly
+ */
+ Object.defineProperty(Tone.UserMedia, 'supported', {
+ get: function () {
+ return !Tone.prototype.isUndef(navigator.mediaDevices) && Tone.prototype.isFunction(navigator.mediaDevices.getUserMedia);
+ }
+ });
+ return Tone.UserMedia;
+ });
+
+ return Tone;
+}));
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var palettes = [[[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.33, 0.67]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.10, 0.20]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.30, 0.20, 0.20]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.80, 0.90, 0.30]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.00, 0.15, 0.20]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.50, 0.20, 0.25]], [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.00, 0.25, 0.25]]];
+
+var palette = palettes[0];
+
+function channel(t, a, b, c, d, add, mul) {
+ return a + b * Math.cos(2 * Math.PI * (c * t + d)) * mul + add;
+}
+
+function color(t, add, mul) {
+ var a = void 0,
+ b = void 0,
+ c = void 0,
+ d = void 0;
+ var rgb = [];
+ for (var i = 0; i < 3; i++) {
+ a = palette[0][i];
+ b = palette[1][i];
+ c = palette[2][i];
+ d = palette[3][i];
+ rgb[i] = Math.round(channel(t, a, b, c, d, add, mul) * 255);
+ }
+ return 'rgb(' + rgb + ')';
+}
+
+exports.default = color;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+var keys = {};
+var key_numbers = {};
+var letters = "zxcvbnmasdfghjklqwertyuiop";
+var numbers = "1234567890";
+
+var callback = function callback() {};
+
+letters.toUpperCase().split("").map(function (k, i) {
+ keys[k.charCodeAt(0)] = i;
+});
+
+numbers.split("").map(function (k, i) {
+ keys[k.charCodeAt(0)] = i + letters.length;
+ key_numbers[k.charCodeAt(0)] = true;
+});
+
+window.addEventListener("keydown", keydown, true);
+function keydown(e) {
+ if (e.altKey || e.ctrlKey || e.metaKey) {
+ e.stopPropagation();
+ return;
+ }
+ if (document.activeElement instanceof HTMLInputElement && e.keyCode in key_numbers) {
+ e.stopPropagation();
+ return;
+ }
+ if (!(e.keyCode in keys)) return;
+ var index = keys[e.keyCode];
+ if (e.shiftKey) index += letters.length;
+ index -= 7;
+ callback(index);
+}
+
+function listen(fn) {
+ callback = fn;
+}
+
+exports.default = { listen: listen };
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.requestAudioContext = exports.firstTouch = exports.browser = exports.clamp = exports.mod = exports.choice = undefined;
+
+var _tone = __webpack_require__(0);
+
+var _tone2 = _interopRequireDefault(_tone);
+
+var _startAudioContext = __webpack_require__(5);
+
+var _startAudioContext2 = _interopRequireDefault(_startAudioContext);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var isIphone = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i);
+var isIpad = navigator.userAgent.match(/iPad/i);
+var isAndroid = navigator.userAgent.match(/Android/i);
+var isMobile = isIphone || isIpad || isAndroid;
+var isDesktop = !isMobile;
+
+document.body.classList.add(isMobile ? 'mobile' : 'desktop');
+
+var browser = { isIphone: isIphone, isIpad: isIpad, isMobile: isMobile, isDesktop: isDesktop };
+
+function clamp(n, a, b) {
+ return n < a ? a : n < b ? n : b;
+}
+function choice(a) {
+ return a[Math.floor(Math.random() * a.length)];
+}
+function mod(n, m) {
+ return n - m * Math.floor(n / m);
+}
+function firstTouch(f) {
+ return function (e) {
+ return f(e.touches[0]);
+ };
+}
+
+function requestAudioContext(fn) {
+ if (isMobile) {
+ var container = document.createElement('div');
+ var button = document.createElement('div');
+ button.innerHTML = 'Tap to start - please unmute your phone';
+ Object.assign(container.style, {
+ display: 'block',
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
+ zIndex: '10000',
+ top: '0px',
+ left: '0px',
+ backgroundColor: 'rgba(0, 0, 0, 0.8)'
+ });
+ Object.assign(button.style, {
+ display: 'block',
+ position: 'absolute',
+ left: '50%',
+ top: '50%',
+ padding: '20px',
+ backgroundColor: '#7F33ED',
+ color: 'white',
+ fontFamily: 'monospace',
+ borderRadius: '3px',
+ transform: 'translate3D(-50%,-50%,0)',
+ textAlign: 'center',
+ lineHeight: '1.5',
+ width: '150px'
+ });
+ container.appendChild(button);
+ document.body.appendChild(container);
+ _startAudioContext2.default.setContext(_tone2.default.context);
+ _startAudioContext2.default.on(button);
+ _startAudioContext2.default.onStarted(function (_) {
+ container.remove();
+ fn();
+ });
+ } else {
+ fn();
+ }
+}
+
+exports.choice = choice;
+exports.mod = mod;
+exports.clamp = clamp;
+exports.browser = browser;
+exports.firstTouch = firstTouch;
+exports.requestAudioContext = requestAudioContext;
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _tone = __webpack_require__(0);
+
+var _tone2 = _interopRequireDefault(_tone);
+
+var _keys = __webpack_require__(2);
+
+var _keys2 = _interopRequireDefault(_keys);
+
+var _color = __webpack_require__(1);
+
+var _color2 = _interopRequireDefault(_color);
+
+var _util = __webpack_require__(3);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var compressor = new _tone2.default.Compressor(-30, 3).toMaster();
+
+var GRAIN_TIME = 1 / 20;
+var SAMPLE_RATE = 44100;
+var GRAIN_SIZE = GRAIN_TIME * SAMPLE_RATE;
+
+(0, _util.requestAudioContext)(function () {
+ var clock = new _tone2.default.Clock(tick, 1 / GRAIN_TIME);
+ clock.start();
+ console.log('ready');
+});
+
+var offsets = [];
+
+var player = new _tone2.default.MultiPlayer({
+ applause: 'applause.mp3'
+}, function () {
+ var data = player.buffers.get('applause').get().getChannelData(0);
+ var intensities = [];
+ for (var i = 0, len = Math.floor(data.length / GRAIN_SIZE); i < len; i++) {
+ var z = 0;
+ for (var j = i * GRAIN_SIZE, max = (i + 1) * GRAIN_SIZE; j < max; j++) {
+ z += Math.abs(data[j]);
+ }
+ intensities[i] = [z / GRAIN_SIZE, i];
+ }
+ offsets = intensities.sort(function (a, b) {
+ return a[0] < b[0] ? -1 : a[0] == b[0] ? 0 : 1;
+ }).map(function (a, i) {
+ return a[1];
+ });
+});
+
+player.fadeIn = 0.25;
+player.fadeOut = 0.25;
+player.connect(compressor);
+
+var intensity = 0,
+ inertialIntensity = 0,
+ inertia = 16;
+
+function tick(time) {
+ if (!offsets.length) return;
+ // let offsetIndex = clamp( Math.floor(mouse.y * offsets.length + Math.cos(time/20)), 0, offsets.length-1 )
+ inertialIntensity = Math.max(intensity, (intensity + inertialIntensity * (inertia - 1)) / inertia);
+ console.log(inertialIntensity);
+ var offsetIndex = Math.floor(inertialIntensity * offsets.length + Math.cos(time));
+ var offset = Math.max((offsets[offsetIndex] || 0) * GRAIN_TIME + 0.25 * Math.sin(time * 17 / 7), 0);
+ // console.log(offset, offsets[offsetIndex] * GRAIN_TIME, ( 0.25 * Math.cos(time*13/7)))
+ player.start('applause', time, offset, GRAIN_TIME * 4);
+}
+
+var mouse = { x: 0, y: 0 };
+var drawing = false;
+var canvas = document.createElement('canvas');
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+var ctx = canvas.getContext('2d');
+document.body.appendChild(canvas);
+
+function down(e) {
+ drawing = true;
+ mouse.x = e.pageX / window.innerWidth;
+ mouse.y = e.pageY / window.innerHeight;
+}
+function move(e) {
+ var x = e.pageX / window.innerWidth;
+ var y = e.pageY / window.innerHeight;
+ var dx = mouse.x - x;
+ var dy = mouse.y - y;
+ var v = Math.sqrt(dx * dx + dy * dy);
+ if (drawing) {
+ intensity = Math.min(0.999, intensity + v * 0.1);
+ inertialIntensity = Math.min(0.999, intensity);
+ if (intensity == 0.999) intensity -= Math.random() * 0.01;
+ if (inertialIntensity == 0.999) inertialIntensity -= Math.random() * 0.01;
+ var gray = Math.floor((0, _util.clamp)(1 - 10 * v, 0, 1) * 255);
+ ctx.fillStyle = 'rgb(' + [gray, gray, gray] + ')';
+ ctx.beginPath();
+ ctx.arc(x * window.innerWidth, y * window.innerHeight, v * 500, 0, Math.PI * 2);
+ ctx.fill();
+ }
+ mouse.x = x;
+ mouse.y = y;
+}
+function up(e) {
+ drawing = false;
+ intensity = 0;
+}
+setInterval(function () {
+ inertialIntensity += 0.1;
+}, 2000);
+
+if (_util.browser.isMobile) {
+ document.body.addEventListener('touchstart', (0, _util.firstTouch)(down));
+ document.body.addEventListener('touchmove', (0, _util.firstTouch)(move));
+ window.addEventListener('touchend', (0, _util.firstTouch)(up));
+} else {
+ document.body.addEventListener('mousedown', down);
+ document.body.addEventListener('mousemove', move);
+ window.addEventListener('mouseup', up);
+}
+
+function animate() {
+ requestAnimationFrame(animate);
+ ctx.save();
+ ctx.fillStyle = 'rgba(255,255,255,0.11)';
+ ctx.globalAlpha = 0.1;
+ ctx.fillRect(0, 0, window.innerWidth, window.innerHeight);
+ ctx.restore();
+}
+animate();
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+/**
+ * StartAudioContext.js
+ * @author Yotam Mann
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @copyright 2016 Yotam Mann
+ */
+(function (root, factory) {
+ if (true) {
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
+ __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__));
+ } else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === 'object' && module.exports) {
+ module.exports = factory();
+ } else {
+ root.StartAudioContext = factory();
+ }
+})(undefined, function () {
+
+ /**
+ * The StartAudioContext object
+ */
+ var StartAudioContext = {
+ /**
+ * The audio context passed in by the user
+ * @type {AudioContext}
+ */
+ context: null,
+ /**
+ * The TapListeners bound to the elements
+ * @type {Array}
+ * @private
+ */
+ _tapListeners: [],
+ /**
+ * Callbacks to invoke when the audio context is started
+ * @type {Array}
+ * @private
+ */
+ _onStarted: []
+ };
+
+ /**
+ * Set the context
+ * @param {AudioContext} ctx
+ * @returns {StartAudioContext}
+ */
+ StartAudioContext.setContext = function (ctx) {
+ StartAudioContext.context = ctx;
+ return StartAudioContext;
+ };
+
+ /**
+ * Add a tap listener to the audio context
+ * @param {Array|Element|String|jQuery} element
+ * @returns {StartAudioContext}
+ */
+ StartAudioContext.on = function (element) {
+ if (Array.isArray(element) || NodeList && element instanceof NodeList) {
+ for (var i = 0; i < element.length; i++) {
+ StartAudioContext.on(element[i]);
+ }
+ } else if (typeof element === "string") {
+ StartAudioContext.on(document.querySelectorAll(element));
+ } else if (element.jquery && typeof element.toArray === "function") {
+ StartAudioContext.on(element.toArray());
+ } else if (Element && element instanceof Element) {
+ //if it's an element, create a TapListener
+ var tap = new TapListener(element, onTap);
+ StartAudioContext._tapListeners.push(tap);
+ }
+ return StartAudioContext;
+ };
+
+ /**
+ * Bind a callback to when the audio context is started.
+ * @param {Function} cb
+ * @return {StartAudioContext}
+ */
+ StartAudioContext.onStarted = function (cb) {
+ //if it's already started, invoke the callback
+ if (StartAudioContext.isStarted()) {
+ cb();
+ } else {
+ StartAudioContext._onStarted.push(cb);
+ }
+ return StartAudioContext;
+ };
+
+ /**
+ * returns true if the context is started
+ * @return {Boolean}
+ */
+ StartAudioContext.isStarted = function () {
+ return StartAudioContext.context !== null && StartAudioContext.context.state === "running";
+ };
+
+ /**
+ * @class Listens for non-dragging tap ends on the given element
+ * @param {Element} element
+ * @internal
+ */
+ var TapListener = function TapListener(element) {
+
+ this._dragged = false;
+
+ this._element = element;
+
+ this._bindedMove = this._moved.bind(this);
+ this._bindedEnd = this._ended.bind(this);
+
+ element.addEventListener("touchmove", this._bindedMove);
+ element.addEventListener("touchend", this._bindedEnd);
+ element.addEventListener("mouseup", this._bindedEnd);
+ };
+
+ /**
+ * drag move event
+ */
+ TapListener.prototype._moved = function (e) {
+ this._dragged = true;
+ };
+
+ /**
+ * tap ended listener
+ */
+ TapListener.prototype._ended = function (e) {
+ if (!this._dragged) {
+ onTap();
+ }
+ this._dragged = false;
+ };
+
+ /**
+ * remove all the bound events
+ */
+ TapListener.prototype.dispose = function () {
+ this._element.removeEventListener("touchmove", this._bindedMove);
+ this._element.removeEventListener("touchend", this._bindedEnd);
+ this._element.removeEventListener("mouseup", this._bindedEnd);
+ this._bindedMove = null;
+ this._bindedEnd = null;
+ this._element = null;
+ };
+
+ /**
+ * Invoked the first time of the elements is tapped.
+ * Creates a silent oscillator when a non-dragging touchend
+ * event has been triggered.
+ */
+ function onTap() {
+ //start the audio context with a silent oscillator
+ if (StartAudioContext.context && !StartAudioContext.isStarted()) {
+ var osc = StartAudioContext.context.createOscillator();
+ var silent = StartAudioContext.context.createGain();
+ silent.gain.value = 0;
+ osc.connect(silent);
+ silent.connect(StartAudioContext.context.destination);
+ var now = StartAudioContext.context.currentTime;
+ osc.start(now);
+ osc.stop(now + 0.5);
+ }
+
+ //dispose all the tap listeners
+ if (StartAudioContext._tapListeners) {
+ for (var i = 0; i < StartAudioContext._tapListeners.length; i++) {
+ StartAudioContext._tapListeners[i].dispose();
+ }
+ StartAudioContext._tapListeners = null;
+ }
+ //the onstarted callbacks
+ if (StartAudioContext._onStarted) {
+ for (var j = 0; j < StartAudioContext._onStarted.length; j++) {
+ StartAudioContext._onStarted[j]();
+ }
+ StartAudioContext._onStarted = null;
+ }
+ }
+
+ return StartAudioContext;
+});
+
+/***/ })
+/******/ ]);
+//# sourceMappingURL=bundle.js.map \ No newline at end of file
diff --git a/bundle.js.map b/bundle.js.map
new file mode 100644
index 0000000..ec62a81
--- /dev/null
+++ b/bundle.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"./bundle.js","sources":["webpack:///webpack/bootstrap d85b3203ae3cf6e2dc5d","webpack:///./~/tone/build/Tone.js","webpack:///./client/lib/color.js","webpack:///./client/lib/keys.js","webpack:///./client/lib/util.js","webpack:///./client/index.js","webpack:///./client/lib/startAudioContext.js"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 4);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap d85b3203ae3cf6e2dc5d","(function(root, factory){\n\n\t//UMD\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\tdefine(function() {\n\t\t\treturn factory();\n\t\t});\n\t} else if (typeof module === \"object\") {\n\t\tmodule.exports = factory();\n \t} else {\n\t\troot.Tone = factory();\n\t}\n\n}(this, function(){\n\n\t\"use strict\";\n\t\n\tvar Tone;\n\t//constructs the main Tone object\n\tfunction Main(func){\n\t\tTone = func();\n\t}\n\t//invokes each of the modules with the main Tone object as the argument\n\tfunction Module(func){\n\t\tfunc(Tone);\n\t}\t/**\n\t * Tone.js\n\t * @author Yotam Mann\n\t * @license http://opensource.org/licenses/MIT MIT License\n\t * @copyright 2014-2017 Yotam Mann\n\t */\n\tMain(function () {\n\t \n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tTONE\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * @class Tone is the base class of all other classes. It provides \n\t\t * a lot of methods and functionality to all classes that extend\n\t\t * it. \n\t\t * \n\t\t * @constructor\n\t\t * @alias Tone\n\t\t * @param {number} [inputs=1] the number of input nodes\n\t\t * @param {number} [outputs=1] the number of output nodes\n\t\t */\n\t var Tone = function (inputs, outputs) {\n\t /**\n\t\t\t * the input node(s)\n\t\t\t * @type {GainNode|Array}\n\t\t\t */\n\t if (this.isUndef(inputs) || inputs === 1) {\n\t this.input = this.context.createGain();\n\t } else if (inputs > 1) {\n\t this.input = new Array(inputs);\n\t }\n\t /**\n\t\t\t * the output node(s)\n\t\t\t * @type {GainNode|Array}\n\t\t\t */\n\t if (this.isUndef(outputs) || outputs === 1) {\n\t this.output = this.context.createGain();\n\t } else if (outputs > 1) {\n\t this.output = new Array(inputs);\n\t }\n\t };\n\t /**\n\t\t * Set the parameters at once. Either pass in an\n\t\t * object mapping parameters to values, or to set a\n\t\t * single parameter, by passing in a string and value.\n\t\t * The last argument is an optional ramp time which \n\t\t * will ramp any signal values to their destination value\n\t\t * over the duration of the rampTime.\n\t\t * @param {Object|string} params\n\t\t * @param {number=} value\n\t\t * @param {Time=} rampTime\n\t\t * @returns {Tone} this\n\t\t * @example\n\t\t * //set values using an object\n\t\t * filter.set({\n\t\t * \t\"frequency\" : 300,\n\t\t * \t\"type\" : highpass\n\t\t * });\n\t\t * @example\n\t\t * filter.set(\"type\", \"highpass\");\n\t\t * @example\n\t\t * //ramp to the value 220 over 3 seconds. \n\t\t * oscillator.set({\n\t\t * \t\"frequency\" : 220\n\t\t * }, 3);\n\t\t */\n\t Tone.prototype.set = function (params, value, rampTime) {\n\t if (this.isObject(params)) {\n\t rampTime = value;\n\t } else if (this.isString(params)) {\n\t var tmpObj = {};\n\t tmpObj[params] = value;\n\t params = tmpObj;\n\t }\n\t paramLoop:\n\t for (var attr in params) {\n\t value = params[attr];\n\t var parent = this;\n\t if (attr.indexOf('.') !== -1) {\n\t var attrSplit = attr.split('.');\n\t for (var i = 0; i < attrSplit.length - 1; i++) {\n\t parent = parent[attrSplit[i]];\n\t if (parent instanceof Tone) {\n\t attrSplit.splice(0, i + 1);\n\t var innerParam = attrSplit.join('.');\n\t parent.set(innerParam, value);\n\t continue paramLoop;\n\t }\n\t }\n\t attr = attrSplit[attrSplit.length - 1];\n\t }\n\t var param = parent[attr];\n\t if (this.isUndef(param)) {\n\t continue;\n\t }\n\t if (Tone.Signal && param instanceof Tone.Signal || Tone.Param && param instanceof Tone.Param) {\n\t if (param.value !== value) {\n\t if (this.isUndef(rampTime)) {\n\t param.value = value;\n\t } else {\n\t param.rampTo(value, rampTime);\n\t }\n\t }\n\t } else if (param instanceof AudioParam) {\n\t if (param.value !== value) {\n\t param.value = value;\n\t }\n\t } else if (param instanceof Tone) {\n\t param.set(value);\n\t } else if (param !== value) {\n\t parent[attr] = value;\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Get the object's attributes. Given no arguments get\n\t\t * will return all available object properties and their corresponding\n\t\t * values. Pass in a single attribute to retrieve or an array\n\t\t * of attributes. The attribute strings can also include a \".\"\n\t\t * to access deeper properties.\n\t\t * @example\n\t\t * osc.get();\n\t\t * //returns {\"type\" : \"sine\", \"frequency\" : 440, ...etc}\n\t\t * @example\n\t\t * osc.get(\"type\");\n\t\t * //returns { \"type\" : \"sine\"}\n\t\t * @example\n\t\t * //use dot notation to access deep properties\n\t\t * synth.get([\"envelope.attack\", \"envelope.release\"]);\n\t\t * //returns {\"envelope\" : {\"attack\" : 0.2, \"release\" : 0.4}}\n\t\t * @param {Array=|string|undefined} params the parameters to get, otherwise will return \n\t\t * \t\t\t\t\t all available.\n\t\t * @returns {Object}\n\t\t */\n\t Tone.prototype.get = function (params) {\n\t if (this.isUndef(params)) {\n\t params = this._collectDefaults(this.constructor);\n\t } else if (this.isString(params)) {\n\t params = [params];\n\t }\n\t var ret = {};\n\t for (var i = 0; i < params.length; i++) {\n\t var attr = params[i];\n\t var parent = this;\n\t var subRet = ret;\n\t if (attr.indexOf('.') !== -1) {\n\t var attrSplit = attr.split('.');\n\t for (var j = 0; j < attrSplit.length - 1; j++) {\n\t var subAttr = attrSplit[j];\n\t subRet[subAttr] = subRet[subAttr] || {};\n\t subRet = subRet[subAttr];\n\t parent = parent[subAttr];\n\t }\n\t attr = attrSplit[attrSplit.length - 1];\n\t }\n\t var param = parent[attr];\n\t if (this.isObject(params[attr])) {\n\t subRet[attr] = param.get();\n\t } else if (Tone.Signal && param instanceof Tone.Signal) {\n\t subRet[attr] = param.value;\n\t } else if (Tone.Param && param instanceof Tone.Param) {\n\t subRet[attr] = param.value;\n\t } else if (param instanceof AudioParam) {\n\t subRet[attr] = param.value;\n\t } else if (param instanceof Tone) {\n\t subRet[attr] = param.get();\n\t } else if (!this.isFunction(param) && !this.isUndef(param)) {\n\t subRet[attr] = param;\n\t }\n\t }\n\t return ret;\n\t };\n\t /**\n\t\t * collect all of the default attributes in one\n\t\t * @private\n\t\t * @param {function} constr the constructor to find the defaults from\n\t\t * @return {Array} all of the attributes which belong to the class\n\t\t */\n\t Tone.prototype._collectDefaults = function (constr) {\n\t var ret = [];\n\t if (!this.isUndef(constr.defaults)) {\n\t ret = Object.keys(constr.defaults);\n\t }\n\t if (!this.isUndef(constr._super)) {\n\t var superDefs = this._collectDefaults(constr._super);\n\t //filter out repeats\n\t for (var i = 0; i < superDefs.length; i++) {\n\t if (ret.indexOf(superDefs[i]) === -1) {\n\t ret.push(superDefs[i]);\n\t }\n\t }\n\t }\n\t return ret;\n\t };\n\t /**\n\t\t * @returns {string} returns the name of the class as a string\n\t\t */\n\t Tone.prototype.toString = function () {\n\t for (var className in Tone) {\n\t var isLetter = className[0].match(/^[A-Z]$/);\n\t var sameConstructor = Tone[className] === this.constructor;\n\t if (this.isFunction(Tone[className]) && isLetter && sameConstructor) {\n\t return className;\n\t }\n\t }\n\t return 'Tone';\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tCLASS VARS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * The number of inputs feeding into the AudioNode. \n\t\t * For source nodes, this will be 0.\n\t\t * @memberOf Tone#\n\t\t * @name numberOfInputs\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.prototype, 'numberOfInputs', {\n\t get: function () {\n\t if (this.input) {\n\t if (this.isArray(this.input)) {\n\t return this.input.length;\n\t } else {\n\t return 1;\n\t }\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The number of outputs coming out of the AudioNode. \n\t\t * For source nodes, this will be 0.\n\t\t * @memberOf Tone#\n\t\t * @name numberOfInputs\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.prototype, 'numberOfOutputs', {\n\t get: function () {\n\t if (this.output) {\n\t if (this.isArray(this.output)) {\n\t return this.output.length;\n\t } else {\n\t return 1;\n\t }\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tCONNECTIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * disconnect and dispose\n\t\t * @returns {Tone} this\n\t\t */\n\t Tone.prototype.dispose = function () {\n\t if (!this.isUndef(this.input)) {\n\t if (this.input instanceof AudioNode) {\n\t this.input.disconnect();\n\t }\n\t this.input = null;\n\t }\n\t if (!this.isUndef(this.output)) {\n\t if (this.output instanceof AudioNode) {\n\t this.output.disconnect();\n\t }\n\t this.output = null;\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode\n\t\t * @param {Tone | AudioParam | AudioNode} unit \n\t\t * @param {number} [outputNum=0] optionally which output to connect from\n\t\t * @param {number} [inputNum=0] optionally which input to connect to\n\t\t * @returns {Tone} this\n\t\t */\n\t Tone.prototype.connect = function (unit, outputNum, inputNum) {\n\t if (Array.isArray(this.output)) {\n\t outputNum = this.defaultArg(outputNum, 0);\n\t this.output[outputNum].connect(unit, 0, inputNum);\n\t } else {\n\t this.output.connect(unit, outputNum, inputNum);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * disconnect the output\n\t\t * @param {Number|AudioNode} output Either the output index to disconnect\n\t\t * if the output is an array, or the\n\t\t * node to disconnect from.\n\t\t * @returns {Tone} this\n\t\t */\n\t Tone.prototype.disconnect = function (destination, outputNum, inputNum) {\n\t if (this.isArray(this.output)) {\n\t if (this.isNumber(destination)) {\n\t this.output[destination].disconnect();\n\t } else {\n\t outputNum = this.defaultArg(outputNum, 0);\n\t this.output[outputNum].disconnect(destination, 0, inputNum);\n\t }\n\t } else {\n\t this.output.disconnect.apply(this.output, arguments);\n\t }\n\t };\n\t /**\n\t\t * connect together all of the arguments in series\n\t\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t\t * @returns {Tone} this\n\t\t */\n\t Tone.prototype.connectSeries = function () {\n\t if (arguments.length > 1) {\n\t var currentUnit = arguments[0];\n\t for (var i = 1; i < arguments.length; i++) {\n\t var toUnit = arguments[i];\n\t currentUnit.connect(toUnit);\n\t currentUnit = toUnit;\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Connect the output of this node to the rest of the nodes in series.\n\t\t * @example\n\t\t * //connect a node to an effect, panVol and then to the master output\n\t\t * node.chain(effect, panVol, Tone.Master);\n\t\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t\t * @returns {Tone} this\n\t\t */\n\t Tone.prototype.chain = function () {\n\t if (arguments.length > 0) {\n\t var currentUnit = this;\n\t for (var i = 0; i < arguments.length; i++) {\n\t var toUnit = arguments[i];\n\t currentUnit.connect(toUnit);\n\t currentUnit = toUnit;\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * connect the output of this node to the rest of the nodes in parallel.\n\t\t * @param {...AudioParam|Tone|AudioNode} nodes\n\t\t * @returns {Tone} this\n\t\t */\n\t Tone.prototype.fan = function () {\n\t if (arguments.length > 0) {\n\t for (var i = 0; i < arguments.length; i++) {\n\t this.connect(arguments[i]);\n\t }\n\t }\n\t return this;\n\t };\n\t //give native nodes chain and fan methods\n\t AudioNode.prototype.chain = Tone.prototype.chain;\n\t AudioNode.prototype.fan = Tone.prototype.fan;\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tUTILITIES / HELPERS / MATHS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * If the `given` parameter is undefined, use the `fallback`. \n\t\t * If both `given` and `fallback` are object literals, it will\n\t\t * return a deep copy which includes all of the parameters from both \n\t\t * objects. If a parameter is undefined in given, it will return\n\t\t * the fallback property. \n\t\t * <br><br>\n\t\t * WARNING: if object is self referential, it will go into an an \n\t\t * infinite recursive loop.\n\t\t * \n\t\t * @param {*} given \n\t\t * @param {*} fallback \n\t\t * @return {*} \n\t\t */\n\t Tone.prototype.defaultArg = function (given, fallback) {\n\t if (this.isObject(given) && this.isObject(fallback)) {\n\t var ret = {};\n\t //make a deep copy of the given object\n\t for (var givenProp in given) {\n\t ret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);\n\t }\n\t for (var fallbackProp in fallback) {\n\t ret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);\n\t }\n\t return ret;\n\t } else {\n\t return this.isUndef(given) ? fallback : given;\n\t }\n\t };\n\t /**\n\t\t * returns the args as an options object with given arguments\n\t\t * mapped to the names provided. \n\t\t *\n\t\t * if the args given is an array containing only one object, it is assumed\n\t\t * that that's already the options object and will just return it. \n\t\t * \n\t\t * @param {Array} values the 'arguments' object of the function\n\t\t * @param {Array} keys the names of the arguments as they\n\t\t * should appear in the options object\n\t\t * @param {Object=} defaults optional defaults to mixin to the returned \n\t\t * options object \n\t\t * @return {Object} the options object with the names mapped to the arguments\n\t\t */\n\t Tone.prototype.optionsObject = function (values, keys, defaults) {\n\t var options = {};\n\t if (values.length === 1 && this.isObject(values[0])) {\n\t options = values[0];\n\t } else {\n\t for (var i = 0; i < keys.length; i++) {\n\t options[keys[i]] = values[i];\n\t }\n\t }\n\t if (!this.isUndef(defaults)) {\n\t return this.defaultArg(options, defaults);\n\t } else {\n\t return options;\n\t }\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t // TYPE CHECKING\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * test if the arg is undefined\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is undefined\n\t\t * @function\n\t\t */\n\t Tone.prototype.isUndef = function (val) {\n\t return typeof val === 'undefined';\n\t };\n\t /**\n\t\t * test if the arg is a function\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is a function\n\t\t * @function\n\t\t */\n\t Tone.prototype.isFunction = function (val) {\n\t return typeof val === 'function';\n\t };\n\t /**\n\t\t * Test if the argument is a number.\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is a number\n\t\t */\n\t Tone.prototype.isNumber = function (arg) {\n\t return typeof arg === 'number';\n\t };\n\t /**\n\t\t * Test if the given argument is an object literal (i.e. `{}`);\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is an object literal.\n\t\t */\n\t Tone.prototype.isObject = function (arg) {\n\t return Object.prototype.toString.call(arg) === '[object Object]' && arg.constructor === Object;\n\t };\n\t /**\n\t\t * Test if the argument is a boolean.\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is a boolean\n\t\t */\n\t Tone.prototype.isBoolean = function (arg) {\n\t return typeof arg === 'boolean';\n\t };\n\t /**\n\t\t * Test if the argument is an Array\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is an array\n\t\t */\n\t Tone.prototype.isArray = function (arg) {\n\t return Array.isArray(arg);\n\t };\n\t /**\n\t\t * Test if the argument is a string.\n\t\t * @param {*} arg the argument to test\n\t\t * @returns {boolean} true if the arg is a string\n\t\t */\n\t Tone.prototype.isString = function (arg) {\n\t return typeof arg === 'string';\n\t };\n\t /**\n\t\t * An empty function.\n\t\t * @static\n\t\t */\n\t Tone.noOp = function () {\n\t };\n\t /**\n\t\t * Make the property not writable. Internal use only. \n\t\t * @private\n\t\t * @param {string} property the property to make not writable\n\t\t */\n\t Tone.prototype._readOnly = function (property) {\n\t if (Array.isArray(property)) {\n\t for (var i = 0; i < property.length; i++) {\n\t this._readOnly(property[i]);\n\t }\n\t } else {\n\t Object.defineProperty(this, property, {\n\t writable: false,\n\t enumerable: true\n\t });\n\t }\n\t };\n\t /**\n\t\t * Make an attribute writeable. Interal use only. \n\t\t * @private\n\t\t * @param {string} property the property to make writable\n\t\t */\n\t Tone.prototype._writable = function (property) {\n\t if (Array.isArray(property)) {\n\t for (var i = 0; i < property.length; i++) {\n\t this._writable(property[i]);\n\t }\n\t } else {\n\t Object.defineProperty(this, property, { writable: true });\n\t }\n\t };\n\t /**\n\t\t * Possible play states. \n\t\t * @enum {string}\n\t\t */\n\t Tone.State = {\n\t Started: 'started',\n\t Stopped: 'stopped',\n\t Paused: 'paused'\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t // CONVERSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Equal power gain scale. Good for cross-fading.\n\t\t * @param {NormalRange} percent (0-1)\n\t\t * @return {Number} output gain (0-1)\n\t\t */\n\t Tone.prototype.equalPowerScale = function (percent) {\n\t var piFactor = 0.5 * Math.PI;\n\t return Math.sin(percent * piFactor);\n\t };\n\t /**\n\t\t * Convert decibels into gain.\n\t\t * @param {Decibels} db\n\t\t * @return {Number} \n\t\t */\n\t Tone.prototype.dbToGain = function (db) {\n\t return Math.pow(2, db / 6);\n\t };\n\t /**\n\t\t * Convert gain to decibels.\n\t\t * @param {Number} gain (0-1)\n\t\t * @return {Decibels} \n\t\t */\n\t Tone.prototype.gainToDb = function (gain) {\n\t return 20 * (Math.log(gain) / Math.LN10);\n\t };\n\t /**\n\t\t * Convert an interval (in semitones) to a frequency ratio.\n\t\t * @param {Interval} interval the number of semitones above the base note\n\t\t * @return {number} the frequency ratio\n\t\t * @example\n\t\t * tone.intervalToFrequencyRatio(0); // 1\n\t\t * tone.intervalToFrequencyRatio(12); // 2\n\t\t * tone.intervalToFrequencyRatio(-12); // 0.5\n\t\t */\n\t Tone.prototype.intervalToFrequencyRatio = function (interval) {\n\t return Math.pow(2, interval / 12);\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tTIMING\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Return the current time of the AudioContext clock.\n\t\t * @return {Number} the currentTime from the AudioContext\n\t\t */\n\t Tone.prototype.now = function () {\n\t return Tone.context.now();\n\t };\n\t /**\n\t\t * Return the current time of the AudioContext clock.\n\t\t * @return {Number} the currentTime from the AudioContext\n\t\t * @static\n\t\t */\n\t Tone.now = function () {\n\t return Tone.context.now();\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tINHERITANCE\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * have a child inherit all of Tone's (or a parent's) prototype\n\t\t * to inherit the parent's properties, make sure to call \n\t\t * Parent.call(this) in the child's constructor\n\t\t *\n\t\t * based on closure library's inherit function\n\t\t *\n\t\t * @static\n\t\t * @param {function} \tchild \n\t\t * @param {function=} parent (optional) parent to inherit from\n\t\t * if no parent is supplied, the child\n\t\t * will inherit from Tone\n\t\t */\n\t Tone.extend = function (child, parent) {\n\t if (Tone.prototype.isUndef(parent)) {\n\t parent = Tone;\n\t }\n\t function TempConstructor() {\n\t }\n\t TempConstructor.prototype = parent.prototype;\n\t child.prototype = new TempConstructor();\n\t /** @override */\n\t child.prototype.constructor = child;\n\t child._super = parent;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tCONTEXT\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * The private audio context shared by all Tone Nodes. \n\t\t * @private\n\t\t * @type {Tone.Context|undefined}\n\t\t */\n\t var audioContext;\n\t /**\n\t\t * A static pointer to the audio context accessible as Tone.context. \n\t\t * @type {Tone.Context}\n\t\t * @name context\n\t\t * @memberOf Tone\n\t\t */\n\t Object.defineProperty(Tone, 'context', {\n\t get: function () {\n\t return audioContext;\n\t },\n\t set: function (context) {\n\t if (Tone.Context && context instanceof Tone.Context) {\n\t audioContext = context;\n\t } else {\n\t audioContext = new Tone.Context(context);\n\t }\n\t //initialize the new audio context\n\t if (Tone.Context) {\n\t Tone.Context.emit('init', audioContext);\n\t }\n\t }\n\t });\n\t /**\n\t\t * The AudioContext\n\t\t * @type {Tone.Context}\n\t\t * @name context\n\t\t * @memberOf Tone#\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.prototype, 'context', {\n\t get: function () {\n\t return Tone.context;\n\t }\n\t });\n\t /**\n\t\t * Tone automatically creates a context on init, but if you are working\n\t\t * with other libraries which also create an AudioContext, it can be\n\t\t * useful to set your own. If you are going to set your own context, \n\t\t * be sure to do it at the start of your code, before creating any objects.\n\t\t * @static\n\t\t * @param {AudioContext} ctx The new audio context to set\n\t\t */\n\t Tone.setContext = function (ctx) {\n\t Tone.context = ctx;\n\t };\n\t /**\n\t\t * The number of seconds of 1 processing block (128 samples)\n\t\t * @type {Number}\n\t\t * @name blockTime\n\t\t * @memberOf Tone#\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.prototype, 'blockTime', {\n\t get: function () {\n\t return 128 / this.context.sampleRate;\n\t }\n\t });\n\t /**\n\t\t * The duration in seconds of one sample.\n\t\t * @type {Number}\n\t\t * @name sampleTime\n\t\t * @memberOf Tone#\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.prototype, 'sampleTime', {\n\t get: function () {\n\t return 1 / this.context.sampleRate;\n\t }\n\t });\n\t /**\n\t\t * Whether or not all the technologies that Tone.js relies on are supported by the current browser. \n\t\t * @type {Boolean}\n\t\t * @name supported\n\t\t * @memberOf Tone\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone, 'supported', {\n\t get: function () {\n\t var hasAudioContext = window.hasOwnProperty('AudioContext') || window.hasOwnProperty('webkitAudioContext');\n\t var hasPromises = window.hasOwnProperty('Promise');\n\t var hasWorkers = window.hasOwnProperty('Worker');\n\t return hasAudioContext && hasPromises && hasWorkers;\n\t }\n\t });\n\t Tone.version = 'r10';\n\t // allow optional silencing of this log\n\t if (!window.TONE_SILENCE_VERSION_LOGGING) {\n\t console.log('%c * Tone.js ' + Tone.version + ' * ', 'background: #000; color: #fff');\n\t }\n\t return Tone;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Base class for all Signals. Used Internally. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t */\n\t Tone.SignalBase = function () {\n\t };\n\t Tone.extend(Tone.SignalBase);\n\t /**\n\t\t * When signals connect to other signals or AudioParams, \n\t\t * they take over the output value of that signal or AudioParam. \n\t\t * For all other nodes, the behavior is the same as a default <code>connect</code>. \n\t\t *\n\t\t * @override\n\t\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t\t * @param {number} [outputNumber=0] The output number to connect from.\n\t\t * @param {number} [inputNumber=0] The input number to connect to.\n\t\t * @returns {Tone.SignalBase} this\n\t\t */\n\t Tone.SignalBase.prototype.connect = function (node, outputNumber, inputNumber) {\n\t //zero it out so that the signal can have full control\n\t if (Tone.Signal && Tone.Signal === node.constructor || Tone.Param && Tone.Param === node.constructor || Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) {\n\t //cancel changes\n\t node._param.cancelScheduledValues(0);\n\t //reset the value\n\t node._param.value = 0;\n\t //mark the value as overridden\n\t node.overridden = true;\n\t } else if (node instanceof AudioParam) {\n\t node.cancelScheduledValues(0);\n\t node.value = 0;\n\t }\n\t Tone.prototype.connect.call(this, node, outputNumber, inputNumber);\n\t return this;\n\t };\n\t return Tone.SignalBase;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Wraps the native Web Audio API \n\t\t * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).\n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @param {function|Array|Number} mapping The function used to define the values. \n\t\t * The mapping function should take two arguments: \n\t\t * the first is the value at the current position \n\t\t * and the second is the array position. \n\t\t * If the argument is an array, that array will be\n\t\t * set as the wave shaping function. The input\n\t\t * signal is an AudioRange [-1, 1] value and the output\n\t\t * signal can take on any numerical values. \n\t\t * \n\t\t * @param {Number} [bufferLen=1024] The length of the WaveShaperNode buffer.\n\t\t * @example\n\t\t * var timesTwo = new Tone.WaveShaper(function(val){\n\t\t * \treturn val * 2;\n\t\t * }, 2048);\n\t\t * @example\n\t\t * //a waveshaper can also be constructed with an array of values\n\t\t * var invert = new Tone.WaveShaper([1, -1]);\n\t\t */\n\t Tone.WaveShaper = function (mapping, bufferLen) {\n\t /**\n\t\t\t * the waveshaper\n\t\t\t * @type {WaveShaperNode}\n\t\t\t * @private\n\t\t\t */\n\t this._shaper = this.input = this.output = this.context.createWaveShaper();\n\t /**\n\t\t\t * the waveshapers curve\n\t\t\t * @type {Float32Array}\n\t\t\t * @private\n\t\t\t */\n\t this._curve = null;\n\t if (Array.isArray(mapping)) {\n\t this.curve = mapping;\n\t } else if (isFinite(mapping) || this.isUndef(mapping)) {\n\t this._curve = new Float32Array(this.defaultArg(mapping, 1024));\n\t } else if (this.isFunction(mapping)) {\n\t this._curve = new Float32Array(this.defaultArg(bufferLen, 1024));\n\t this.setMap(mapping);\n\t }\n\t };\n\t Tone.extend(Tone.WaveShaper, Tone.SignalBase);\n\t /**\n\t\t * Uses a mapping function to set the value of the curve. \n\t\t * @param {function} mapping The function used to define the values. \n\t\t * The mapping function take two arguments: \n\t\t * the first is the value at the current position \n\t\t * which goes from -1 to 1 over the number of elements\n\t\t * in the curve array. The second argument is the array position. \n\t\t * @returns {Tone.WaveShaper} this\n\t\t * @example\n\t\t * //map the input signal from [-1, 1] to [0, 10]\n\t\t * shaper.setMap(function(val, index){\n\t\t * \treturn (val + 1) * 5;\n\t\t * })\n\t\t */\n\t Tone.WaveShaper.prototype.setMap = function (mapping) {\n\t for (var i = 0, len = this._curve.length; i < len; i++) {\n\t var normalized = i / (len - 1) * 2 - 1;\n\t this._curve[i] = mapping(normalized, i);\n\t }\n\t this._shaper.curve = this._curve;\n\t return this;\n\t };\n\t /**\n\t\t * The array to set as the waveshaper curve. For linear curves\n\t\t * array length does not make much difference, but for complex curves\n\t\t * longer arrays will provide smoother interpolation. \n\t\t * @memberOf Tone.WaveShaper#\n\t\t * @type {Array}\n\t\t * @name curve\n\t\t */\n\t Object.defineProperty(Tone.WaveShaper.prototype, 'curve', {\n\t get: function () {\n\t return this._shaper.curve;\n\t },\n\t set: function (mapping) {\n\t this._curve = new Float32Array(mapping);\n\t this._shaper.curve = this._curve;\n\t }\n\t });\n\t /**\n\t\t * Specifies what type of oversampling (if any) should be used when \n\t\t * applying the shaping curve. Can either be \"none\", \"2x\" or \"4x\". \n\t\t * @memberOf Tone.WaveShaper#\n\t\t * @type {string}\n\t\t * @name oversample\n\t\t */\n\t Object.defineProperty(Tone.WaveShaper.prototype, 'oversample', {\n\t get: function () {\n\t return this._shaper.oversample;\n\t },\n\t set: function (oversampling) {\n\t if ([\n\t 'none',\n\t '2x',\n\t '4x'\n\t ].indexOf(oversampling) !== -1) {\n\t this._shaper.oversample = oversampling;\n\t } else {\n\t throw new RangeError('Tone.WaveShaper: oversampling must be either \\'none\\', \\'2x\\', or \\'4x\\'');\n\t }\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.WaveShaper} this\n\t\t */\n\t Tone.WaveShaper.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._shaper.disconnect();\n\t this._shaper = null;\n\t this._curve = null;\n\t return this;\n\t };\n\t return Tone.WaveShaper;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.TimeBase is a flexible encoding of time\n\t\t * which can be evaluated to and from a string.\n\t\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t\t * @extends {Tone}\n\t\t * @param {Time} val The time value as a number or string\n\t\t * @param {String=} units Unit values\n\t\t * @example\n\t\t * Tone.TimeBase(4, \"n\")\n\t\t * Tone.TimeBase(2, \"t\")\n\t\t * Tone.TimeBase(\"2t\").add(\"1m\")\n\t\t * Tone.TimeBase(\"2t + 1m\");\n\t\t */\n\t Tone.TimeBase = function (val, units) {\n\t //allows it to be constructed with or without 'new'\n\t if (this instanceof Tone.TimeBase) {\n\t /**\n\t\t\t\t * Any expressions parsed from the Time\n\t\t\t\t * @type {Array}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._expr = this._noOp;\n\t if (val instanceof Tone.TimeBase) {\n\t this.copy(val);\n\t } else if (!this.isUndef(units) || this.isNumber(val)) {\n\t //default units\n\t units = this.defaultArg(units, this._defaultUnits);\n\t var method = this._primaryExpressions[units].method;\n\t this._expr = method.bind(this, val);\n\t } else if (this.isString(val)) {\n\t this.set(val);\n\t } else if (this.isUndef(val)) {\n\t //default expression\n\t this._expr = this._defaultExpr();\n\t }\n\t } else {\n\t return new Tone.TimeBase(val, units);\n\t }\n\t };\n\t Tone.extend(Tone.TimeBase);\n\t /**\n\t\t * Repalce the current time value with the value\n\t\t * given by the expression string.\n\t\t * @param {String} exprString\n\t\t * @return {Tone.TimeBase} this\n\t\t */\n\t Tone.TimeBase.prototype.set = function (exprString) {\n\t this._expr = this._parseExprString(exprString);\n\t return this;\n\t };\n\t /**\n\t\t * Return a clone of the TimeBase object.\n\t\t * @return {Tone.TimeBase} The new cloned Tone.TimeBase\n\t\t */\n\t Tone.TimeBase.prototype.clone = function () {\n\t var instance = new this.constructor();\n\t instance.copy(this);\n\t return instance;\n\t };\n\t /**\n\t\t * Copies the value of time to this Time\n\t\t * @param {Tone.TimeBase} time\n\t\t * @return {TimeBase}\n\t\t */\n\t Tone.TimeBase.prototype.copy = function (time) {\n\t var val = time._expr();\n\t return this.set(val);\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tABSTRACT SYNTAX TREE PARSER\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * All the primary expressions.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t Tone.TimeBase.prototype._primaryExpressions = {\n\t 'n': {\n\t regexp: /^(\\d+)n/i,\n\t method: function (value) {\n\t value = parseInt(value);\n\t if (value === 1) {\n\t return this._beatsToUnits(this._timeSignature());\n\t } else {\n\t return this._beatsToUnits(4 / value);\n\t }\n\t }\n\t },\n\t 't': {\n\t regexp: /^(\\d+)t/i,\n\t method: function (value) {\n\t value = parseInt(value);\n\t return this._beatsToUnits(8 / (parseInt(value) * 3));\n\t }\n\t },\n\t 'm': {\n\t regexp: /^(\\d+)m/i,\n\t method: function (value) {\n\t return this._beatsToUnits(parseInt(value) * this._timeSignature());\n\t }\n\t },\n\t 'i': {\n\t regexp: /^(\\d+)i/i,\n\t method: function (value) {\n\t return this._ticksToUnits(parseInt(value));\n\t }\n\t },\n\t 'hz': {\n\t regexp: /^(\\d+(?:\\.\\d+)?)hz/i,\n\t method: function (value) {\n\t return this._frequencyToUnits(parseFloat(value));\n\t }\n\t },\n\t 'tr': {\n\t regexp: /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t method: function (m, q, s) {\n\t var total = 0;\n\t if (m && m !== '0') {\n\t total += this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t }\n\t if (q && q !== '0') {\n\t total += this._beatsToUnits(parseFloat(q));\n\t }\n\t if (s && s !== '0') {\n\t total += this._beatsToUnits(parseFloat(s) / 4);\n\t }\n\t return total;\n\t }\n\t },\n\t 's': {\n\t regexp: /^(\\d+(?:\\.\\d+)?s)/,\n\t method: function (value) {\n\t return this._secondsToUnits(parseFloat(value));\n\t }\n\t },\n\t 'samples': {\n\t regexp: /^(\\d+)samples/,\n\t method: function (value) {\n\t return parseInt(value) / this.context.sampleRate;\n\t }\n\t },\n\t 'default': {\n\t regexp: /^(\\d+(?:\\.\\d+)?)/,\n\t method: function (value) {\n\t return this._primaryExpressions[this._defaultUnits].method.call(this, value);\n\t }\n\t }\n\t };\n\t /**\n\t\t * All the binary expressions that TimeBase can accept.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t Tone.TimeBase.prototype._binaryExpressions = {\n\t '+': {\n\t regexp: /^\\+/,\n\t precedence: 2,\n\t method: function (lh, rh) {\n\t return lh() + rh();\n\t }\n\t },\n\t '-': {\n\t regexp: /^\\-/,\n\t precedence: 2,\n\t method: function (lh, rh) {\n\t return lh() - rh();\n\t }\n\t },\n\t '*': {\n\t regexp: /^\\*/,\n\t precedence: 1,\n\t method: function (lh, rh) {\n\t return lh() * rh();\n\t }\n\t },\n\t '/': {\n\t regexp: /^\\//,\n\t precedence: 1,\n\t method: function (lh, rh) {\n\t return lh() / rh();\n\t }\n\t }\n\t };\n\t /**\n\t\t * All the unary expressions.\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t Tone.TimeBase.prototype._unaryExpressions = {\n\t 'neg': {\n\t regexp: /^\\-/,\n\t method: function (lh) {\n\t return -lh();\n\t }\n\t }\n\t };\n\t /**\n\t\t * Syntactic glue which holds expressions together\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t Tone.TimeBase.prototype._syntaxGlue = {\n\t '(': { regexp: /^\\(/ },\n\t ')': { regexp: /^\\)/ }\n\t };\n\t /**\n\t\t * tokenize the expression based on the Expressions object\n\t\t * @param {string} expr \n\t\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._tokenize = function (expr) {\n\t var position = -1;\n\t var tokens = [];\n\t while (expr.length > 0) {\n\t expr = expr.trim();\n\t var token = getNextToken(expr, this);\n\t tokens.push(token);\n\t expr = expr.substr(token.value.length);\n\t }\n\t function getNextToken(expr, context) {\n\t var expressions = [\n\t '_binaryExpressions',\n\t '_unaryExpressions',\n\t '_primaryExpressions',\n\t '_syntaxGlue'\n\t ];\n\t for (var i = 0; i < expressions.length; i++) {\n\t var group = context[expressions[i]];\n\t for (var opName in group) {\n\t var op = group[opName];\n\t var reg = op.regexp;\n\t var match = expr.match(reg);\n\t if (match !== null) {\n\t return {\n\t method: op.method,\n\t precedence: op.precedence,\n\t regexp: op.regexp,\n\t value: match[0]\n\t };\n\t }\n\t }\n\t }\n\t throw new SyntaxError('Tone.TimeBase: Unexpected token ' + expr);\n\t }\n\t return {\n\t next: function () {\n\t return tokens[++position];\n\t },\n\t peek: function () {\n\t return tokens[position + 1];\n\t }\n\t };\n\t };\n\t /**\n\t\t * Given a token, find the value within the groupName\n\t\t * @param {Object} token\n\t\t * @param {String} groupName\n\t\t * @param {Number} precedence\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._matchGroup = function (token, group, prec) {\n\t var ret = false;\n\t if (!this.isUndef(token)) {\n\t for (var opName in group) {\n\t var op = group[opName];\n\t if (op.regexp.test(token.value)) {\n\t if (!this.isUndef(prec)) {\n\t if (op.precedence === prec) {\n\t return op;\n\t }\n\t } else {\n\t return op;\n\t }\n\t }\n\t }\n\t }\n\t return ret;\n\t };\n\t /**\n\t\t * Match a binary expression given the token and the precedence\n\t\t * @param {Lexer} lexer\n\t\t * @param {Number} precedence\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) {\n\t if (this.isUndef(precedence)) {\n\t precedence = 2;\n\t }\n\t var expr;\n\t if (precedence < 0) {\n\t expr = this._parseUnary(lexer);\n\t } else {\n\t expr = this._parseBinary(lexer, precedence - 1);\n\t }\n\t var token = lexer.peek();\n\t while (token && this._matchGroup(token, this._binaryExpressions, precedence)) {\n\t token = lexer.next();\n\t expr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));\n\t token = lexer.peek();\n\t }\n\t return expr;\n\t };\n\t /**\n\t\t * Match a unary expression.\n\t\t * @param {Lexer} lexer\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._parseUnary = function (lexer) {\n\t var token, expr;\n\t token = lexer.peek();\n\t var op = this._matchGroup(token, this._unaryExpressions);\n\t if (op) {\n\t token = lexer.next();\n\t expr = this._parseUnary(lexer);\n\t return op.method.bind(this, expr);\n\t }\n\t return this._parsePrimary(lexer);\n\t };\n\t /**\n\t\t * Match a primary expression (a value).\n\t\t * @param {Lexer} lexer\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._parsePrimary = function (lexer) {\n\t var token, expr;\n\t token = lexer.peek();\n\t if (this.isUndef(token)) {\n\t throw new SyntaxError('Tone.TimeBase: Unexpected end of expression');\n\t }\n\t if (this._matchGroup(token, this._primaryExpressions)) {\n\t token = lexer.next();\n\t var matching = token.value.match(token.regexp);\n\t return token.method.bind(this, matching[1], matching[2], matching[3]);\n\t }\n\t if (token && token.value === '(') {\n\t lexer.next();\n\t expr = this._parseBinary(lexer);\n\t token = lexer.next();\n\t if (!(token && token.value === ')')) {\n\t throw new SyntaxError('Expected )');\n\t }\n\t return expr;\n\t }\n\t throw new SyntaxError('Tone.TimeBase: Cannot process token ' + token.value);\n\t };\n\t /**\n\t\t * Recursively parse the string expression into a syntax tree.\n\t\t * @param {string} expr \n\t\t * @return {Function} the bound method to be evaluated later\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._parseExprString = function (exprString) {\n\t if (!this.isString(exprString)) {\n\t exprString = exprString.toString();\n\t }\n\t var lexer = this._tokenize(exprString);\n\t var tree = this._parseBinary(lexer);\n\t return tree;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tDEFAULTS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * The initial expression value\n\t\t * @return {Number} The initial value 0\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._noOp = function () {\n\t return 0;\n\t };\n\t /**\n\t\t * The default expression value if no arguments are given\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._defaultExpr = function () {\n\t return this._noOp;\n\t };\n\t /**\n\t\t * The default units if none are given.\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._defaultUnits = 's';\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tUNIT CONVERSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Returns the value of a frequency in the current units\n\t\t * @param {Frequency} freq\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._frequencyToUnits = function (freq) {\n\t return 1 / freq;\n\t };\n\t /**\n\t\t * Return the value of the beats in the current units\n\t\t * @param {Number} beats\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._beatsToUnits = function (beats) {\n\t return 60 / Tone.Transport.bpm.value * beats;\n\t };\n\t /**\n\t\t * Returns the value of a second in the current units\n\t\t * @param {Seconds} seconds\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._secondsToUnits = function (seconds) {\n\t return seconds;\n\t };\n\t /**\n\t\t * Returns the value of a tick in the current time units\n\t\t * @param {Ticks} ticks\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._ticksToUnits = function (ticks) {\n\t return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);\n\t };\n\t /**\n\t\t * Return the time signature.\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._timeSignature = function () {\n\t return Tone.Transport.timeSignature;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tEXPRESSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Push an expression onto the expression list\n\t\t * @param {Time} val\n\t\t * @param {String} type\n\t\t * @param {String} units\n\t\t * @return {Tone.TimeBase} \n\t\t * @private\n\t\t */\n\t Tone.TimeBase.prototype._pushExpr = function (val, name, units) {\n\t //create the expression\n\t if (!(val instanceof Tone.TimeBase)) {\n\t val = new this.constructor(val, units);\n\t }\n\t this._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);\n\t return this;\n\t };\n\t /**\n\t\t * Add to the current value.\n\t\t * @param {Time} val The value to add\n\t\t * @param {String=} units Optional units to use with the value.\n\t\t * @return {Tone.TimeBase} this\n\t\t * @example\n\t\t * Tone.TimeBase(\"2m\").add(\"1m\"); //\"3m\"\n\t\t */\n\t Tone.TimeBase.prototype.add = function (val, units) {\n\t return this._pushExpr(val, '+', units);\n\t };\n\t /**\n\t\t * Subtract the value from the current time.\n\t\t * @param {Time} val The value to subtract\n\t\t * @param {String=} units Optional units to use with the value.\n\t\t * @return {Tone.TimeBase} this\n\t\t * @example\n\t\t * Tone.TimeBase(\"2m\").sub(\"1m\"); //\"1m\"\n\t\t */\n\t Tone.TimeBase.prototype.sub = function (val, units) {\n\t return this._pushExpr(val, '-', units);\n\t };\n\t /**\n\t\t * Multiply the current value by the given time.\n\t\t * @param {Time} val The value to multiply\n\t\t * @param {String=} units Optional units to use with the value.\n\t\t * @return {Tone.TimeBase} this\n\t\t * @example\n\t\t * Tone.TimeBase(\"2m\").mult(\"2\"); //\"4m\"\n\t\t */\n\t Tone.TimeBase.prototype.mult = function (val, units) {\n\t return this._pushExpr(val, '*', units);\n\t };\n\t /**\n\t\t * Divide the current value by the given time.\n\t\t * @param {Time} val The value to divide by\n\t\t * @param {String=} units Optional units to use with the value.\n\t\t * @return {Tone.TimeBase} this\n\t\t * @example\n\t\t * Tone.TimeBase(\"2m\").div(2); //\"1m\"\n\t\t */\n\t Tone.TimeBase.prototype.div = function (val, units) {\n\t return this._pushExpr(val, '/', units);\n\t };\n\t /**\n\t\t * Evaluate the time value. Returns the time\n\t\t * in seconds.\n\t\t * @return {Seconds} \n\t\t */\n\t Tone.TimeBase.prototype.valueOf = function () {\n\t return this._expr();\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.TimeBase} this\n\t\t */\n\t Tone.TimeBase.prototype.dispose = function () {\n\t this._expr = null;\n\t };\n\t return Tone.TimeBase;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.Time is a primitive type for encoding Time values. \n\t\t * Eventually all time values are evaluated to seconds\n\t\t * using the `eval` method. Tone.Time can be constructed\n\t\t * with or without the `new` keyword. Tone.Time can be passed\n\t\t * into the parameter of any method which takes time as an argument. \n\t\t * @constructor\n\t\t * @extends {Tone.TimeBase}\n\t\t * @param {String|Number} val The time value.\n\t\t * @param {String=} units The units of the value.\n\t\t * @example\n\t\t * var t = Tone.Time(\"4n\");//encodes a quarter note\n\t\t * t.mult(4); // multiply that value by 4\n\t\t * t.toNotation(); //returns \"1m\"\n\t\t */\n\t Tone.Time = function (val, units) {\n\t if (this instanceof Tone.Time) {\n\t /**\n\t\t\t\t * If the current clock time should\n\t\t\t\t * be added to the output\n\t\t\t\t * @type {Boolean}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._plusNow = false;\n\t Tone.TimeBase.call(this, val, units);\n\t } else {\n\t return new Tone.Time(val, units);\n\t }\n\t };\n\t Tone.extend(Tone.Time, Tone.TimeBase);\n\t //clone the expressions so that \n\t //we can add more without modifying the original\n\t Tone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);\n\t /*\n\t\t * Adds an additional unary expression\n\t\t * which quantizes values to the next subdivision\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.Time.prototype._unaryExpressions.quantize = {\n\t regexp: /^@/,\n\t method: function (rh) {\n\t return Tone.Transport.nextSubdivision(rh());\n\t }\n\t };\n\t /*\n\t\t * Adds an additional unary expression\n\t\t * which adds the current clock time.\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.Time.prototype._unaryExpressions.now = {\n\t regexp: /^\\+/,\n\t method: function (lh) {\n\t this._plusNow = true;\n\t return lh();\n\t }\n\t };\n\t /**\n\t\t * Quantize the time by the given subdivision. Optionally add a\n\t\t * percentage which will move the time value towards the ideal\n\t\t * quantized value by that percentage. \n\t\t * @param {Number|Time} val The subdivision to quantize to\n\t\t * @param {NormalRange} [percent=1] Move the time value\n\t\t * towards the quantized value by\n\t\t * a percentage.\n\t\t * @return {Tone.Time} this\n\t\t * @example\n\t\t * Tone.Time(21).quantize(2) //returns 22\n\t\t * Tone.Time(0.6).quantize(\"4n\", 0.5) //returns 0.55\n\t\t */\n\t Tone.Time.prototype.quantize = function (subdiv, percent) {\n\t percent = this.defaultArg(percent, 1);\n\t this._expr = function (expr, subdivision, percent) {\n\t expr = expr();\n\t subdivision = subdivision.toSeconds();\n\t var multiple = Math.round(expr / subdivision);\n\t var ideal = multiple * subdivision;\n\t var diff = ideal - expr;\n\t return expr + diff * percent;\n\t }.bind(this, this._expr, new this.constructor(subdiv), percent);\n\t return this;\n\t };\n\t /**\n\t\t * Adds the clock time to the time expression at the \n\t\t * moment of evaluation. \n\t\t * @return {Tone.Time} this\n\t\t */\n\t Tone.Time.prototype.addNow = function () {\n\t this._plusNow = true;\n\t return this;\n\t };\n\t /**\n\t\t * @override\n\t\t * Override the default value return when no arguments are passed in.\n\t\t * The default value is 'now'\n\t\t * @private\n\t\t */\n\t Tone.Time.prototype._defaultExpr = function () {\n\t this._plusNow = true;\n\t return this._noOp;\n\t };\n\t /**\n\t\t * Copies the value of time to this Time\n\t\t * @param {Tone.Time} time\n\t\t * @return {Time}\n\t\t */\n\t Tone.Time.prototype.copy = function (time) {\n\t Tone.TimeBase.prototype.copy.call(this, time);\n\t this._plusNow = time._plusNow;\n\t return this;\n\t };\n\t //CONVERSIONS//////////////////////////////////////////////////////////////\n\t /**\n\t\t * Convert a Time to Notation. Values will be thresholded to the nearest 128th note. \n\t\t * @return {Notation} \n\t\t * @example\n\t\t * //if the Transport is at 120bpm:\n\t\t * Tone.Time(2).toNotation();//returns \"1m\"\n\t\t */\n\t Tone.Time.prototype.toNotation = function () {\n\t var time = this.toSeconds();\n\t var testNotations = [\n\t '1m',\n\t '2n',\n\t '4n',\n\t '8n',\n\t '16n',\n\t '32n',\n\t '64n',\n\t '128n'\n\t ];\n\t var retNotation = this._toNotationHelper(time, testNotations);\n\t //try the same thing but with tripelets\n\t var testTripletNotations = [\n\t '1m',\n\t '2n',\n\t '2t',\n\t '4n',\n\t '4t',\n\t '8n',\n\t '8t',\n\t '16n',\n\t '16t',\n\t '32n',\n\t '32t',\n\t '64n',\n\t '64t',\n\t '128n'\n\t ];\n\t var retTripletNotation = this._toNotationHelper(time, testTripletNotations);\n\t //choose the simpler expression of the two\n\t if (retTripletNotation.split('+').length < retNotation.split('+').length) {\n\t return retTripletNotation;\n\t } else {\n\t return retNotation;\n\t }\n\t };\n\t /**\n\t\t * Helper method for Tone.toNotation\n\t\t * @param {Number} units \n\t\t * @param {Array} testNotations\n\t\t * @return {String}\n\t\t * @private\n\t\t */\n\t Tone.Time.prototype._toNotationHelper = function (units, testNotations) {\n\t //the threshold is the last value in the array\n\t var threshold = this._notationToUnits(testNotations[testNotations.length - 1]);\n\t var retNotation = '';\n\t for (var i = 0; i < testNotations.length; i++) {\n\t var notationTime = this._notationToUnits(testNotations[i]);\n\t //account for floating point errors (i.e. round up if the value is 0.999999)\n\t var multiple = units / notationTime;\n\t var floatingPointError = 0.000001;\n\t if (1 - multiple % 1 < floatingPointError) {\n\t multiple += floatingPointError;\n\t }\n\t multiple = Math.floor(multiple);\n\t if (multiple > 0) {\n\t if (multiple === 1) {\n\t retNotation += testNotations[i];\n\t } else {\n\t retNotation += multiple.toString() + '*' + testNotations[i];\n\t }\n\t units -= multiple * notationTime;\n\t if (units < threshold) {\n\t break;\n\t } else {\n\t retNotation += ' + ';\n\t }\n\t }\n\t }\n\t if (retNotation === '') {\n\t retNotation = '0';\n\t }\n\t return retNotation;\n\t };\n\t /**\n\t\t * Convert a notation value to the current units\n\t\t * @param {Notation} notation \n\t\t * @return {Number} \n\t\t * @private\n\t\t */\n\t Tone.Time.prototype._notationToUnits = function (notation) {\n\t var primaryExprs = this._primaryExpressions;\n\t var notationExprs = [\n\t primaryExprs.n,\n\t primaryExprs.t,\n\t primaryExprs.m\n\t ];\n\t for (var i = 0; i < notationExprs.length; i++) {\n\t var expr = notationExprs[i];\n\t var match = notation.match(expr.regexp);\n\t if (match) {\n\t return expr.method.call(this, match[1]);\n\t }\n\t }\n\t };\n\t /**\n\t\t * Return the time encoded as Bars:Beats:Sixteenths.\n\t\t * @return {BarsBeatsSixteenths}\n\t\t */\n\t Tone.Time.prototype.toBarsBeatsSixteenths = function () {\n\t var quarterTime = this._beatsToUnits(1);\n\t var quarters = this.toSeconds() / quarterTime;\n\t var measures = Math.floor(quarters / this._timeSignature());\n\t var sixteenths = quarters % 1 * 4;\n\t quarters = Math.floor(quarters) % this._timeSignature();\n\t sixteenths = sixteenths.toString();\n\t if (sixteenths.length > 3) {\n\t sixteenths = parseFloat(sixteenths).toFixed(3);\n\t }\n\t var progress = [\n\t measures,\n\t quarters,\n\t sixteenths\n\t ];\n\t return progress.join(':');\n\t };\n\t /**\n\t\t * Return the time in ticks.\n\t\t * @return {Ticks}\n\t\t */\n\t Tone.Time.prototype.toTicks = function () {\n\t var quarterTime = this._beatsToUnits(1);\n\t var quarters = this.valueOf() / quarterTime;\n\t return Math.floor(quarters * Tone.Transport.PPQ);\n\t };\n\t /**\n\t\t * Return the time in samples\n\t\t * @return {Samples} \n\t\t */\n\t Tone.Time.prototype.toSamples = function () {\n\t return this.toSeconds() * this.context.sampleRate;\n\t };\n\t /**\n\t\t * Return the time as a frequency value\n\t\t * @return {Frequency} \n\t\t * @example\n\t\t * Tone.Time(2).toFrequency(); //0.5\n\t\t */\n\t Tone.Time.prototype.toFrequency = function () {\n\t return 1 / this.toSeconds();\n\t };\n\t /**\n\t\t * Return the time in seconds.\n\t\t * @return {Seconds} \n\t\t */\n\t Tone.Time.prototype.toSeconds = function () {\n\t return this.valueOf();\n\t };\n\t /**\n\t\t * Return the time in milliseconds.\n\t\t * @return {Milliseconds} \n\t\t */\n\t Tone.Time.prototype.toMilliseconds = function () {\n\t return this.toSeconds() * 1000;\n\t };\n\t /**\n\t\t * Return the time in seconds.\n\t\t * @return {Seconds} \n\t\t */\n\t Tone.Time.prototype.valueOf = function () {\n\t var val = this._expr();\n\t return val + (this._plusNow ? this.now() : 0);\n\t };\n\t return Tone.Time;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.Frequency is a primitive type for encoding Frequency values. \n\t\t * Eventually all time values are evaluated to hertz\n\t\t * using the `eval` method. \n\t\t * @constructor\n\t\t * @extends {Tone.TimeBase}\n\t\t * @param {String|Number} val The time value.\n\t\t * @param {String=} units The units of the value.\n\t\t * @example\n\t\t * Tone.Frequency(\"C3\") // 261\n\t\t * Tone.Frequency(38, \"midi\") //\n\t\t * Tone.Frequency(\"C3\").transpose(4);\n\t\t */\n\t Tone.Frequency = function (val, units) {\n\t if (this instanceof Tone.Frequency) {\n\t Tone.TimeBase.call(this, val, units);\n\t } else {\n\t return new Tone.Frequency(val, units);\n\t }\n\t };\n\t Tone.extend(Tone.Frequency, Tone.TimeBase);\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tAUGMENT BASE EXPRESSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t //clone the expressions so that \n\t //we can add more without modifying the original\n\t Tone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);\n\t /*\n\t\t * midi type primary expression\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._primaryExpressions.midi = {\n\t regexp: /^(\\d+(?:\\.\\d+)?midi)/,\n\t method: function (value) {\n\t return this.midiToFrequency(value);\n\t }\n\t };\n\t /*\n\t\t * note type primary expression\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._primaryExpressions.note = {\n\t regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,\n\t method: function (pitch, octave) {\n\t var index = noteToScaleIndex[pitch.toLowerCase()];\n\t var noteNumber = index + (parseInt(octave) + 1) * 12;\n\t return this.midiToFrequency(noteNumber);\n\t }\n\t };\n\t /*\n\t\t * BeatsBarsSixteenths type primary expression\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._primaryExpressions.tr = {\n\t regexp: /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?):?(\\d+(?:\\.\\d+)?)?/,\n\t method: function (m, q, s) {\n\t var total = 1;\n\t if (m && m !== '0') {\n\t total *= this._beatsToUnits(this._timeSignature() * parseFloat(m));\n\t }\n\t if (q && q !== '0') {\n\t total *= this._beatsToUnits(parseFloat(q));\n\t }\n\t if (s && s !== '0') {\n\t total *= this._beatsToUnits(parseFloat(s) / 4);\n\t }\n\t return total;\n\t }\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tEXPRESSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Transposes the frequency by the given number of semitones.\n\t\t * @param {Interval} interval\n\t\t * @return {Tone.Frequency} this\n\t\t * @example\n\t\t * Tone.Frequency(\"A4\").transpose(3); //\"C5\"\n\t\t */\n\t Tone.Frequency.prototype.transpose = function (interval) {\n\t this._expr = function (expr, interval) {\n\t var val = expr();\n\t return val * this.intervalToFrequencyRatio(interval);\n\t }.bind(this, this._expr, interval);\n\t return this;\n\t };\n\t /**\n\t\t * Takes an array of semitone intervals and returns\n\t\t * an array of frequencies transposed by those intervals.\n\t\t * @param {Array} intervals\n\t\t * @return {Tone.Frequency} this\n\t\t * @example\n\t\t * Tone.Frequency(\"A4\").harmonize([0, 3, 7]); //[\"A4\", \"C5\", \"E5\"]\n\t\t */\n\t Tone.Frequency.prototype.harmonize = function (intervals) {\n\t this._expr = function (expr, intervals) {\n\t var val = expr();\n\t var ret = [];\n\t for (var i = 0; i < intervals.length; i++) {\n\t ret[i] = val * this.intervalToFrequencyRatio(intervals[i]);\n\t }\n\t return ret;\n\t }.bind(this, this._expr, intervals);\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tUNIT CONVERSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Return the value of the frequency as a MIDI note\n\t\t * @return {MIDI}\n\t\t * @example\n\t\t * Tone.Frequency(\"C4\").toMidi(); //60\n\t\t */\n\t Tone.Frequency.prototype.toMidi = function () {\n\t return this.frequencyToMidi(this.valueOf());\n\t };\n\t /**\n\t\t * Return the value of the frequency in Scientific Pitch Notation\n\t\t * @return {Note}\n\t\t * @example\n\t\t * Tone.Frequency(69, \"midi\").toNote(); //\"A4\"\n\t\t */\n\t Tone.Frequency.prototype.toNote = function () {\n\t var freq = this.valueOf();\n\t var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;\n\t var noteNumber = Math.round(12 * log) + 57;\n\t var octave = Math.floor(noteNumber / 12);\n\t if (octave < 0) {\n\t noteNumber += -12 * octave;\n\t }\n\t var noteName = scaleIndexToNote[noteNumber % 12];\n\t return noteName + octave.toString();\n\t };\n\t /**\n\t\t * Return the duration of one cycle in seconds.\n\t\t * @return {Seconds}\n\t\t */\n\t Tone.Frequency.prototype.toSeconds = function () {\n\t return 1 / this.valueOf();\n\t };\n\t /**\n\t\t * Return the value in Hertz\n\t\t * @return {Frequency}\n\t\t */\n\t Tone.Frequency.prototype.toFrequency = function () {\n\t return this.valueOf();\n\t };\n\t /**\n\t\t * Return the duration of one cycle in ticks\n\t\t * @return {Ticks}\n\t\t */\n\t Tone.Frequency.prototype.toTicks = function () {\n\t var quarterTime = this._beatsToUnits(1);\n\t var quarters = this.valueOf() / quarterTime;\n\t return Math.floor(quarters * Tone.Transport.PPQ);\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tUNIT CONVERSIONS HELPERS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Returns the value of a frequency in the current units\n\t\t * @param {Frequency} freq\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._frequencyToUnits = function (freq) {\n\t return freq;\n\t };\n\t /**\n\t\t * Returns the value of a tick in the current time units\n\t\t * @param {Ticks} ticks\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._ticksToUnits = function (ticks) {\n\t return 1 / (ticks * 60 / (Tone.Transport.bpm.value * Tone.Transport.PPQ));\n\t };\n\t /**\n\t\t * Return the value of the beats in the current units\n\t\t * @param {Number} beats\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._beatsToUnits = function (beats) {\n\t return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);\n\t };\n\t /**\n\t\t * Returns the value of a second in the current units\n\t\t * @param {Seconds} seconds\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._secondsToUnits = function (seconds) {\n\t return 1 / seconds;\n\t };\n\t /**\n\t\t * The default units if none are given.\n\t\t * @private\n\t\t */\n\t Tone.Frequency.prototype._defaultUnits = 'hz';\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tFREQUENCY CONVERSIONS\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Note to scale index\n\t\t * @type {Object}\n\t\t */\n\t var noteToScaleIndex = {\n\t 'cbb': -2,\n\t 'cb': -1,\n\t 'c': 0,\n\t 'c#': 1,\n\t 'cx': 2,\n\t 'dbb': 0,\n\t 'db': 1,\n\t 'd': 2,\n\t 'd#': 3,\n\t 'dx': 4,\n\t 'ebb': 2,\n\t 'eb': 3,\n\t 'e': 4,\n\t 'e#': 5,\n\t 'ex': 6,\n\t 'fbb': 3,\n\t 'fb': 4,\n\t 'f': 5,\n\t 'f#': 6,\n\t 'fx': 7,\n\t 'gbb': 5,\n\t 'gb': 6,\n\t 'g': 7,\n\t 'g#': 8,\n\t 'gx': 9,\n\t 'abb': 7,\n\t 'ab': 8,\n\t 'a': 9,\n\t 'a#': 10,\n\t 'ax': 11,\n\t 'bbb': 9,\n\t 'bb': 10,\n\t 'b': 11,\n\t 'b#': 12,\n\t 'bx': 13\n\t };\n\t /**\n\t\t * scale index to note (sharps)\n\t\t * @type {Array}\n\t\t */\n\t var scaleIndexToNote = [\n\t 'C',\n\t 'C#',\n\t 'D',\n\t 'D#',\n\t 'E',\n\t 'F',\n\t 'F#',\n\t 'G',\n\t 'G#',\n\t 'A',\n\t 'A#',\n\t 'B'\n\t ];\n\t /**\n\t\t * The [concert pitch](https://en.wikipedia.org/wiki/Concert_pitch)\n\t\t * A4's values in Hertz. \n\t\t * @type {Frequency}\n\t\t * @static\n\t\t */\n\t Tone.Frequency.A4 = 440;\n\t /**\n\t\t * Convert a MIDI note to frequency value. \n\t\t * @param {MIDI} midi The midi number to convert.\n\t\t * @return {Frequency} the corresponding frequency value\n\t\t * @example\n\t\t * tone.midiToFrequency(69); // returns 440\n\t\t */\n\t Tone.Frequency.prototype.midiToFrequency = function (midi) {\n\t return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);\n\t };\n\t /**\n\t\t * Convert a frequency value to a MIDI note.\n\t\t * @param {Frequency} frequency The value to frequency value to convert.\n\t\t * @returns {MIDI}\n\t\t * @example\n\t\t * tone.midiToFrequency(440); // returns 69\n\t\t */\n\t Tone.Frequency.prototype.frequencyToMidi = function (frequency) {\n\t return 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;\n\t };\n\t return Tone.Frequency;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.TransportTime is a the time along the Transport's\n\t\t * timeline. It is similar to Tone.Time, but instead of evaluating\n\t\t * against the AudioContext's clock, it is evaluated against\n\t\t * the Transport's position. See [TransportTime wiki](https://github.com/Tonejs/Tone.js/wiki/TransportTime).\n\t\t * @constructor\n\t\t * @param {Time} val The time value as a number or string\n\t\t * @param {String=} units Unit values\n\t\t * @extends {Tone.Time}\n\t\t */\n\t Tone.TransportTime = function (val, units) {\n\t if (this instanceof Tone.TransportTime) {\n\t Tone.Time.call(this, val, units);\n\t } else {\n\t return new Tone.TransportTime(val, units);\n\t }\n\t };\n\t Tone.extend(Tone.TransportTime, Tone.Time);\n\t //clone the expressions so that \n\t //we can add more without modifying the original\n\t Tone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);\n\t /**\n\t\t * Adds an additional unary expression\n\t\t * which quantizes values to the next subdivision\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.TransportTime.prototype._unaryExpressions.quantize = {\n\t regexp: /^@/,\n\t method: function (rh) {\n\t var subdivision = this._secondsToTicks(rh());\n\t var multiple = Math.ceil(Tone.Transport.ticks / subdivision);\n\t return this._ticksToUnits(multiple * subdivision);\n\t }\n\t };\n\t /**\n\t\t * Convert seconds into ticks\n\t\t * @param {Seconds} seconds\n\t\t * @return {Ticks}\n\t\t * @private\n\t\t */\n\t Tone.TransportTime.prototype._secondsToTicks = function (seconds) {\n\t var quarterTime = this._beatsToUnits(1);\n\t var quarters = seconds / quarterTime;\n\t return Math.round(quarters * Tone.Transport.PPQ);\n\t };\n\t /**\n\t\t * Evaluate the time expression. Returns values in ticks\n\t\t * @return {Ticks}\n\t\t */\n\t Tone.TransportTime.prototype.valueOf = function () {\n\t var val = this._secondsToTicks(this._expr());\n\t return val + (this._plusNow ? Tone.Transport.ticks : 0);\n\t };\n\t /**\n\t\t * Return the time in ticks.\n\t\t * @return {Ticks}\n\t\t */\n\t Tone.TransportTime.prototype.toTicks = function () {\n\t return this.valueOf();\n\t };\n\t /**\n\t\t * Return the time in seconds.\n\t\t * @return {Seconds}\n\t\t */\n\t Tone.TransportTime.prototype.toSeconds = function () {\n\t var val = this._expr();\n\t return val + (this._plusNow ? Tone.Transport.seconds : 0);\n\t };\n\t /**\n\t\t * Return the time as a frequency value\n\t\t * @return {Frequency} \n\t\t */\n\t Tone.TransportTime.prototype.toFrequency = function () {\n\t return 1 / this.toSeconds();\n\t };\n\t return Tone.TransportTime;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Emitter gives classes which extend it\n\t\t * the ability to listen for and emit events. \n\t\t * Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).\n\t\t * MIT (c) 2011 Jerome Etienne.\n\t\t * \n\t\t * @extends {Tone}\n\t\t */\n\t Tone.Emitter = function () {\n\t /**\n\t\t\t * Contains all of the events.\n\t\t\t * @private\n\t\t\t * @type {Object}\n\t\t\t */\n\t this._events = {};\n\t };\n\t Tone.extend(Tone.Emitter);\n\t /**\n\t\t * Bind a callback to a specific event.\n\t\t * @param {String} event The name of the event to listen for.\n\t\t * @param {Function} callback The callback to invoke when the\n\t\t * event is emitted\n\t\t * @return {Tone.Emitter} this\n\t\t */\n\t Tone.Emitter.prototype.on = function (event, callback) {\n\t //split the event\n\t var events = event.split(/\\W+/);\n\t for (var i = 0; i < events.length; i++) {\n\t var eventName = events[i];\n\t if (!this._events.hasOwnProperty(eventName)) {\n\t this._events[eventName] = [];\n\t }\n\t this._events[eventName].push(callback);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Remove the event listener.\n\t\t * @param {String} event The event to stop listening to.\n\t\t * @param {Function=} callback The callback which was bound to \n\t\t * the event with Tone.Emitter.on.\n\t\t * If no callback is given, all callbacks\n\t\t * events are removed.\n\t\t * @return {Tone.Emitter} this\n\t\t */\n\t Tone.Emitter.prototype.off = function (event, callback) {\n\t var events = event.split(/\\W+/);\n\t for (var ev = 0; ev < events.length; ev++) {\n\t event = events[ev];\n\t if (this._events.hasOwnProperty(event)) {\n\t if (Tone.prototype.isUndef(callback)) {\n\t this._events[event] = [];\n\t } else {\n\t var eventList = this._events[event];\n\t for (var i = 0; i < eventList.length; i++) {\n\t if (eventList[i] === callback) {\n\t eventList.splice(i, 1);\n\t }\n\t }\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Invoke all of the callbacks bound to the event\n\t\t * with any arguments passed in. \n\t\t * @param {String} event The name of the event.\n\t\t * @param {*...} args The arguments to pass to the functions listening.\n\t\t * @return {Tone.Emitter} this\n\t\t */\n\t Tone.Emitter.prototype.emit = function (event) {\n\t if (this._events) {\n\t var args = Array.apply(null, arguments).slice(1);\n\t if (this._events.hasOwnProperty(event)) {\n\t var eventList = this._events[event];\n\t for (var i = 0, len = eventList.length; i < len; i++) {\n\t eventList[i].apply(this, args);\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Add Emitter functions (on/off/emit) to the object\n\t\t * @param {Object|Function} object The object or class to extend.\n\t\t */\n\t Tone.Emitter.mixin = function (object) {\n\t var functions = [\n\t 'on',\n\t 'off',\n\t 'emit'\n\t ];\n\t object._events = {};\n\t for (var i = 0; i < functions.length; i++) {\n\t var func = functions[i];\n\t var emitterFunc = Tone.Emitter.prototype[func];\n\t object[func] = emitterFunc;\n\t }\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.Emitter} this\n\t\t */\n\t Tone.Emitter.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._events = null;\n\t return this;\n\t };\n\t return Tone.Emitter;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * shim\n\t\t * @private\n\t\t */\n\t if (!window.hasOwnProperty('AudioContext') && window.hasOwnProperty('webkitAudioContext')) {\n\t window.AudioContext = window.webkitAudioContext;\n\t }\n\t /**\n\t\t * @class Wrapper around the native AudioContext.\n\t\t * @extends {Tone.Emitter}\n\t\t * @param {AudioContext=} context optionally pass in a context\n\t\t */\n\t Tone.Context = function (context) {\n\t Tone.Emitter.call(this);\n\t if (!context) {\n\t context = new window.AudioContext();\n\t }\n\t this._context = context;\n\t // extend all of the methods\n\t for (var prop in this._context) {\n\t this._defineProperty(this._context, prop);\n\t }\n\t ///////////////////////////////////////////////////////////////////////\n\t // WORKER\n\t ///////////////////////////////////////////////////////////////////////\n\t /**\n\t\t\t * The default latency hint\n\t\t\t * @type {String}\n\t\t\t * @private\n\t\t\t */\n\t this._latencyHint = 'interactive';\n\t /**\n\t\t\t * The amount of time events are scheduled\n\t\t\t * into the future\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._lookAhead = 0.1;\n\t /**\n\t\t\t * How often the update look runs\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._updateInterval = this._lookAhead / 3;\n\t /**\n\t\t\t * A reference to the actual computed update interval\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._computedUpdateInterval = 0;\n\t /**\n\t\t\t * The web worker which is used to update Tone.Clock\n\t\t\t * @private\n\t\t\t * @type {WebWorker}\n\t\t\t */\n\t this._worker = this._createWorker();\n\t /**\n\t\t\t * An object containing all of the constants AudioBufferSourceNodes\n\t\t\t * @type {Object}\n\t\t\t * @private\n\t\t\t */\n\t this._constants = {};\n\t };\n\t Tone.extend(Tone.Context, Tone.Emitter);\n\t Tone.Emitter.mixin(Tone.Context);\n\t /**\n\t\t * Define a property on this Tone.Context. \n\t\t * This is used to extend the native AudioContext\n\t\t * @param {AudioContext} context\n\t\t * @param {String} prop \n\t\t * @private\n\t\t */\n\t Tone.Context.prototype._defineProperty = function (context, prop) {\n\t if (this.isUndef(this[prop])) {\n\t Object.defineProperty(this, prop, {\n\t get: function () {\n\t if (typeof context[prop] === 'function') {\n\t return context[prop].bind(context);\n\t } else {\n\t return context[prop];\n\t }\n\t },\n\t set: function (val) {\n\t context[prop] = val;\n\t }\n\t });\n\t }\n\t };\n\t /**\n\t\t * The current audio context time\n\t\t * @return {Number}\n\t\t */\n\t Tone.Context.prototype.now = function () {\n\t return this._context.currentTime;\n\t };\n\t /**\n\t\t * Generate a web worker\n\t\t * @return {WebWorker}\n\t\t * @private\n\t\t */\n\t Tone.Context.prototype._createWorker = function () {\n\t //URL Shim\n\t window.URL = window.URL || window.webkitURL;\n\t var blob = new Blob([//the initial timeout time\n\t 'var timeoutTime = ' + (this._updateInterval * 1000).toFixed(1) + ';' + //onmessage callback\n\t 'self.onmessage = function(msg){' + '\\ttimeoutTime = parseInt(msg.data);' + '};' + //the tick function which posts a message\n\t //and schedules a new tick\n\t 'function tick(){' + '\\tsetTimeout(tick, timeoutTime);' + '\\tself.postMessage(\\'tick\\');' + '}' + //call tick initially\n\t 'tick();']);\n\t var blobUrl = URL.createObjectURL(blob);\n\t var worker = new Worker(blobUrl);\n\t worker.addEventListener('message', function () {\n\t // tick the clock\n\t this.emit('tick');\n\t }.bind(this));\n\t //lag compensation\n\t worker.addEventListener('message', function () {\n\t var now = this.now();\n\t if (this.isNumber(this._lastUpdate)) {\n\t var diff = now - this._lastUpdate;\n\t this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);\n\t }\n\t this._lastUpdate = now;\n\t }.bind(this));\n\t return worker;\n\t };\n\t /**\n\t\t * Generate a looped buffer at some constant value.\n\t\t * @param {Number} val\n\t\t * @return {BufferSourceNode}\n\t\t */\n\t Tone.Context.prototype.getConstant = function (val) {\n\t if (this._constants[val]) {\n\t return this._constants[val];\n\t } else {\n\t var buffer = this._context.createBuffer(1, 128, this._context.sampleRate);\n\t var arr = buffer.getChannelData(0);\n\t for (var i = 0; i < arr.length; i++) {\n\t arr[i] = val;\n\t }\n\t var constant = this._context.createBufferSource();\n\t constant.channelCount = 1;\n\t constant.channelCountMode = 'explicit';\n\t constant.buffer = buffer;\n\t constant.loop = true;\n\t constant.start(0);\n\t this._constants[val] = constant;\n\t return constant;\n\t }\n\t };\n\t /**\n\t\t * This is the time that the clock is falling behind\n\t\t * the scheduled update interval. The Context automatically\n\t\t * adjusts for the lag and schedules further in advance.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Context\n\t\t * @name lag\n\t\t * @static\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Context.prototype, 'lag', {\n\t get: function () {\n\t var diff = this._computedUpdateInterval - this._updateInterval;\n\t diff = Math.max(diff, 0);\n\t return diff;\n\t }\n\t });\n\t /**\n\t\t * The amount of time in advance that events are scheduled.\n\t\t * The lookAhead will adjust slightly in response to the \n\t\t * measured update time to try to avoid clicks.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Context\n\t\t * @name lookAhead\n\t\t * @static\n\t\t */\n\t Object.defineProperty(Tone.Context.prototype, 'lookAhead', {\n\t get: function () {\n\t return this._lookAhead;\n\t },\n\t set: function (lA) {\n\t this._lookAhead = lA;\n\t }\n\t });\n\t /**\n\t\t * How often the Web Worker callback is invoked.\n\t\t * This number corresponds to how responsive the scheduling\n\t\t * can be. Context.updateInterval + Context.lookAhead gives you the\n\t\t * total latency between scheduling an event and hearing it.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Context\n\t\t * @name updateInterval\n\t\t * @static\n\t\t */\n\t Object.defineProperty(Tone.Context.prototype, 'updateInterval', {\n\t get: function () {\n\t return this._updateInterval;\n\t },\n\t set: function (interval) {\n\t this._updateInterval = Math.max(interval, Tone.prototype.blockTime);\n\t this._worker.postMessage(Math.max(interval * 1000, 1));\n\t }\n\t });\n\t /**\n\t\t * The type of playback, which affects tradeoffs between audio \n\t\t * output latency and responsiveness. \n\t\t * \n\t\t * In addition to setting the value in seconds, the latencyHint also\n\t\t * accepts the strings \"interactive\" (prioritizes low latency), \n\t\t * \"playback\" (prioritizes sustained playback), \"balanced\" (balances\n\t\t * latency and performance), and \"fastest\" (lowest latency, might glitch more often). \n\t\t * @type {String|Seconds}\n\t\t * @memberOf Tone.Context#\n\t\t * @name latencyHint\n\t\t * @static\n\t\t * @example\n\t\t * //set the lookAhead to 0.3 seconds\n\t\t * Tone.context.latencyHint = 0.3;\n\t\t */\n\t Object.defineProperty(Tone.Context.prototype, 'latencyHint', {\n\t get: function () {\n\t return this._latencyHint;\n\t },\n\t set: function (hint) {\n\t var lookAhead = hint;\n\t this._latencyHint = hint;\n\t if (this.isString(hint)) {\n\t switch (hint) {\n\t case 'interactive':\n\t lookAhead = 0.1;\n\t this._context.latencyHint = hint;\n\t break;\n\t case 'playback':\n\t lookAhead = 0.8;\n\t this._context.latencyHint = hint;\n\t break;\n\t case 'balanced':\n\t lookAhead = 0.25;\n\t this._context.latencyHint = hint;\n\t break;\n\t case 'fastest':\n\t lookAhead = 0.01;\n\t break;\n\t }\n\t }\n\t this.lookAhead = lookAhead;\n\t this.updateInterval = lookAhead / 3;\n\t }\n\t });\n\t /**\n\t\t * Shim all connect/disconnect and some deprecated methods which are still in\n\t\t * some older implementations.\n\t\t * @private\n\t\t */\n\t function shimConnect() {\n\t var nativeConnect = AudioNode.prototype.connect;\n\t var nativeDisconnect = AudioNode.prototype.disconnect;\n\t //replace the old connect method\n\t function toneConnect(B, outNum, inNum) {\n\t if (B.input) {\n\t if (Array.isArray(B.input)) {\n\t if (Tone.prototype.isUndef(inNum)) {\n\t inNum = 0;\n\t }\n\t this.connect(B.input[inNum]);\n\t } else {\n\t this.connect(B.input, outNum, inNum);\n\t }\n\t } else {\n\t try {\n\t if (B instanceof AudioNode) {\n\t nativeConnect.call(this, B, outNum, inNum);\n\t } else {\n\t nativeConnect.call(this, B, outNum);\n\t }\n\t } catch (e) {\n\t throw new Error('error connecting to node: ' + B + '\\n' + e);\n\t }\n\t }\n\t }\n\t //replace the old disconnect method\n\t function toneDisconnect(B, outNum, inNum) {\n\t if (B && B.input && Array.isArray(B.input)) {\n\t if (Tone.prototype.isUndef(inNum)) {\n\t inNum = 0;\n\t }\n\t this.disconnect(B.input[inNum], outNum, inNum);\n\t } else if (B && B.input) {\n\t this.disconnect(B.input, outNum, inNum);\n\t } else {\n\t try {\n\t nativeDisconnect.apply(this, arguments);\n\t } catch (e) {\n\t throw new Error('error disconnecting node: ' + B + '\\n' + e);\n\t }\n\t }\n\t }\n\t if (AudioNode.prototype.connect !== toneConnect) {\n\t AudioNode.prototype.connect = toneConnect;\n\t AudioNode.prototype.disconnect = toneDisconnect;\n\t }\n\t }\n\t // set the audio context initially\n\t if (Tone.supported) {\n\t shimConnect();\n\t Tone.context = new Tone.Context();\n\t } else {\n\t console.warn('This browser does not support Tone.js');\n\t }\n\t return Tone.Context;\n\t});\n\tModule(function (Tone) {\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tTYPES\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Units which a value can take on.\n\t\t * @enum {String}\n\t\t */\n\t Tone.Type = {\n\t /** \n\t\t\t * Default units\n\t\t\t * @typedef {Default}\n\t\t\t */\n\t Default: 'number',\n\t /**\n\t\t\t * Time can be described in a number of ways. Read more [Time](https://github.com/Tonejs/Tone.js/wiki/Time).\n\t\t\t *\n\t\t\t * <ul>\n\t\t\t * <li>Numbers, which will be taken literally as the time (in seconds).</li>\n\t\t\t * <li>Notation, (\"4n\", \"8t\") describes time in BPM and time signature relative values.</li>\n\t\t\t * <li>TransportTime, (\"4:3:2\") will also provide tempo and time signature relative times \n\t\t\t * in the form BARS:QUARTERS:SIXTEENTHS.</li>\n\t\t\t * <li>Frequency, (\"8hz\") is converted to the length of the cycle in seconds.</li>\n\t\t\t * <li>Now-Relative, (\"+1\") prefix any of the above with \"+\" and it will be interpreted as \n\t\t\t * \"the current time plus whatever expression follows\".</li>\n\t\t\t * <li>Expressions, (\"3:0 + 2 - (1m / 7)\") any of the above can also be combined \n\t\t\t * into a mathematical expression which will be evaluated to compute the desired time.</li>\n\t\t\t * <li>No Argument, for methods which accept time, no argument will be interpreted as \n\t\t\t * \"now\" (i.e. the currentTime).</li>\n\t\t\t * </ul>\n\t\t\t * \n\t\t\t * @typedef {Time}\n\t\t\t */\n\t Time: 'time',\n\t /**\n\t\t\t * Frequency can be described similar to time, except ultimately the\n\t\t\t * values are converted to frequency instead of seconds. A number\n\t\t\t * is taken literally as the value in hertz. Additionally any of the \n\t\t\t * Time encodings can be used. Note names in the form\n\t\t\t * of NOTE OCTAVE (i.e. C4) are also accepted and converted to their\n\t\t\t * frequency value. \n\t\t\t * @typedef {Frequency}\n\t\t\t */\n\t Frequency: 'frequency',\n\t /**\n\t\t\t * TransportTime describes a position along the Transport's timeline. It is\n\t\t\t * similar to Time in that it uses all the same encodings, but TransportTime specifically\n\t\t\t * pertains to the Transport's timeline, which is startable, stoppable, loopable, and seekable. \n\t\t\t * [Read more](https://github.com/Tonejs/Tone.js/wiki/TransportTime)\n\t\t\t * @typedef {TransportTime}\n\t\t\t */\n\t TransportTime: 'transportTime',\n\t /** \n\t\t\t * Ticks are the basic subunit of the Transport. They are\n\t\t\t * the smallest unit of time that the Transport supports.\n\t\t\t * @typedef {Ticks}\n\t\t\t */\n\t Ticks: 'ticks',\n\t /** \n\t\t\t * Normal values are within the range [0, 1].\n\t\t\t * @typedef {NormalRange}\n\t\t\t */\n\t NormalRange: 'normalRange',\n\t /** \n\t\t\t * AudioRange values are between [-1, 1].\n\t\t\t * @typedef {AudioRange}\n\t\t\t */\n\t AudioRange: 'audioRange',\n\t /** \n\t\t\t * Decibels are a logarithmic unit of measurement which is useful for volume\n\t\t\t * because of the logarithmic way that we perceive loudness. 0 decibels \n\t\t\t * means no change in volume. -10db is approximately half as loud and 10db \n\t\t\t * is twice is loud. \n\t\t\t * @typedef {Decibels}\n\t\t\t */\n\t Decibels: 'db',\n\t /** \n\t\t\t * Half-step note increments, i.e. 12 is an octave above the root. and 1 is a half-step up.\n\t\t\t * @typedef {Interval}\n\t\t\t */\n\t Interval: 'interval',\n\t /** \n\t\t\t * Beats per minute. \n\t\t\t * @typedef {BPM}\n\t\t\t */\n\t BPM: 'bpm',\n\t /** \n\t\t\t * The value must be greater than or equal to 0.\n\t\t\t * @typedef {Positive}\n\t\t\t */\n\t Positive: 'positive',\n\t /** \n\t\t\t * A cent is a hundredth of a semitone. \n\t\t\t * @typedef {Cents}\n\t\t\t */\n\t Cents: 'cents',\n\t /** \n\t\t\t * Angle between 0 and 360. \n\t\t\t * @typedef {Degrees}\n\t\t\t */\n\t Degrees: 'degrees',\n\t /** \n\t\t\t * A number representing a midi note.\n\t\t\t * @typedef {MIDI}\n\t\t\t */\n\t MIDI: 'midi',\n\t /** \n\t\t\t * A colon-separated representation of time in the form of\n\t\t\t * Bars:Beats:Sixteenths. \n\t\t\t * @typedef {BarsBeatsSixteenths}\n\t\t\t */\n\t BarsBeatsSixteenths: 'barsBeatsSixteenths',\n\t /** \n\t\t\t * Sampling is the reduction of a continuous signal to a discrete signal.\n\t\t\t * Audio is typically sampled 44100 times per second. \n\t\t\t * @typedef {Samples}\n\t\t\t */\n\t Samples: 'samples',\n\t /** \n\t\t\t * Hertz are a frequency representation defined as one cycle per second.\n\t\t\t * @typedef {Hertz}\n\t\t\t */\n\t Hertz: 'hertz',\n\t /** \n\t\t\t * A frequency represented by a letter name, \n\t\t\t * accidental and octave. This system is known as\n\t\t\t * [Scientific Pitch Notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation).\n\t\t\t * @typedef {Note}\n\t\t\t */\n\t Note: 'note',\n\t /** \n\t\t\t * One millisecond is a thousandth of a second. \n\t\t\t * @typedef {Milliseconds}\n\t\t\t */\n\t Milliseconds: 'milliseconds',\n\t /** \n\t\t\t * Seconds are the time unit of the AudioContext. In the end, \n\t\t\t * all values need to be evaluated to seconds. \n\t\t\t * @typedef {Seconds}\n\t\t\t */\n\t Seconds: 'seconds',\n\t /** \n\t\t\t * A string representing a duration relative to a measure. \n\t\t\t * <ul>\n\t\t\t * \t<li>\"4n\" = quarter note</li>\n\t\t\t * \t<li>\"2m\" = two measures</li>\n\t\t\t * \t<li>\"8t\" = eighth-note triplet</li>\n\t\t\t * </ul>\n\t\t\t * @typedef {Notation}\n\t\t\t */\n\t Notation: 'notation'\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t // AUGMENT TONE's PROTOTYPE\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Convert Time into seconds.\n\t\t * \n\t\t * Unlike the method which it overrides, this takes into account \n\t\t * transporttime and musical notation.\n\t\t *\n\t\t * Time : 1.40\n\t\t * Notation: 4n|1m|2t\n\t\t * Now Relative: +3n\n\t\t * Math: 3n+16n or even complicated expressions ((3n*2)/6 + 1)\n\t\t *\n\t\t * @param {Time} time \n\t\t * @return {Seconds} \n\t\t */\n\t Tone.prototype.toSeconds = function (time) {\n\t if (this.isNumber(time)) {\n\t return time;\n\t } else if (this.isUndef(time)) {\n\t return this.now();\n\t } else if (this.isString(time)) {\n\t return new Tone.Time(time).toSeconds();\n\t } else if (time instanceof Tone.TimeBase) {\n\t return time.toSeconds();\n\t }\n\t };\n\t /**\n\t\t * Convert a frequency representation into a number.\n\t\t * @param {Frequency} freq \n\t\t * @return {Hertz} the frequency in hertz\n\t\t */\n\t Tone.prototype.toFrequency = function (freq) {\n\t if (this.isNumber(freq)) {\n\t return freq;\n\t } else if (this.isString(freq) || this.isUndef(freq)) {\n\t return new Tone.Frequency(freq).valueOf();\n\t } else if (freq instanceof Tone.TimeBase) {\n\t return freq.toFrequency();\n\t }\n\t };\n\t /**\n\t\t * Convert a time representation into ticks.\n\t\t * @param {Time} time\n\t\t * @return {Ticks} the time in ticks\n\t\t */\n\t Tone.prototype.toTicks = function (time) {\n\t if (this.isNumber(time) || this.isString(time)) {\n\t return new Tone.TransportTime(time).toTicks();\n\t } else if (this.isUndef(time)) {\n\t return Tone.Transport.ticks;\n\t } else if (time instanceof Tone.TimeBase) {\n\t return time.toTicks();\n\t }\n\t };\n\t return Tone;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Param wraps the native Web Audio's AudioParam to provide\n\t\t * additional unit conversion functionality. It also\n\t\t * serves as a base-class for classes which have a single,\n\t\t * automatable parameter. \n\t\t * @extends {Tone}\n\t\t * @param {AudioParam} param The parameter to wrap.\n\t\t * @param {Tone.Type} units The units of the audio param.\n\t\t * @param {Boolean} convert If the param should be converted.\n\t\t */\n\t Tone.Param = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'param',\n\t 'units',\n\t 'convert'\n\t ], Tone.Param.defaults);\n\t /**\n\t\t\t * The native parameter to control\n\t\t\t * @type {AudioParam}\n\t\t\t * @private\n\t\t\t */\n\t this._param = this.input = options.param;\n\t /**\n\t\t\t * The units of the parameter\n\t\t\t * @type {Tone.Type}\n\t\t\t */\n\t this.units = options.units;\n\t /**\n\t\t\t * If the value should be converted or not\n\t\t\t * @type {Boolean}\n\t\t\t */\n\t this.convert = options.convert;\n\t /**\n\t\t\t * True if the signal value is being overridden by \n\t\t\t * a connected signal.\n\t\t\t * @readOnly\n\t\t\t * @type {boolean}\n\t\t\t * @private\n\t\t\t */\n\t this.overridden = false;\n\t /**\n\t\t\t * If there is an LFO, this is where it is held.\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfo = null;\n\t if (this.isObject(options.lfo)) {\n\t this.value = options.lfo;\n\t } else if (!this.isUndef(options.value)) {\n\t this.value = options.value;\n\t }\n\t };\n\t Tone.extend(Tone.Param);\n\t /**\n\t\t * Defaults\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.Param.defaults = {\n\t 'units': Tone.Type.Default,\n\t 'convert': true,\n\t 'param': undefined\n\t };\n\t /**\n\t\t * The current value of the parameter. \n\t\t * @memberOf Tone.Param#\n\t\t * @type {Number}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.Param.prototype, 'value', {\n\t get: function () {\n\t return this._toUnits(this._param.value);\n\t },\n\t set: function (value) {\n\t if (this.isObject(value)) {\n\t //throw an error if the LFO needs to be included\n\t if (this.isUndef(Tone.LFO)) {\n\t throw new Error('Include \\'Tone.LFO\\' to use an LFO as a Param value.');\n\t }\n\t //remove the old one\n\t if (this._lfo) {\n\t this._lfo.dispose();\n\t }\n\t this._lfo = new Tone.LFO(value).start();\n\t this._lfo.connect(this.input);\n\t } else {\n\t var convertedVal = this._fromUnits(value);\n\t this._param.cancelScheduledValues(0);\n\t this._param.value = convertedVal;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Convert the given value from the type specified by Tone.Param.units\n\t\t * into the destination value (such as Gain or Frequency).\n\t\t * @private\n\t\t * @param {*} val the value to convert\n\t\t * @return {number} the number which the value should be set to\n\t\t */\n\t Tone.Param.prototype._fromUnits = function (val) {\n\t if (this.convert || this.isUndef(this.convert)) {\n\t switch (this.units) {\n\t case Tone.Type.Time:\n\t return this.toSeconds(val);\n\t case Tone.Type.Frequency:\n\t return this.toFrequency(val);\n\t case Tone.Type.Decibels:\n\t return this.dbToGain(val);\n\t case Tone.Type.NormalRange:\n\t return Math.min(Math.max(val, 0), 1);\n\t case Tone.Type.AudioRange:\n\t return Math.min(Math.max(val, -1), 1);\n\t case Tone.Type.Positive:\n\t return Math.max(val, 0);\n\t default:\n\t return val;\n\t }\n\t } else {\n\t return val;\n\t }\n\t };\n\t /**\n\t\t * Convert the parameters value into the units specified by Tone.Param.units.\n\t\t * @private\n\t\t * @param {number} val the value to convert\n\t\t * @return {number}\n\t\t */\n\t Tone.Param.prototype._toUnits = function (val) {\n\t if (this.convert || this.isUndef(this.convert)) {\n\t switch (this.units) {\n\t case Tone.Type.Decibels:\n\t return this.gainToDb(val);\n\t default:\n\t return val;\n\t }\n\t } else {\n\t return val;\n\t }\n\t };\n\t /**\n\t\t * the minimum output value\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t Tone.Param.prototype._minOutput = 0.00001;\n\t /**\n\t\t * Schedules a parameter value change at the given time.\n\t\t * @param {*}\tvalue The value to set the signal.\n\t\t * @param {Time} time The time when the change should occur.\n\t\t * @returns {Tone.Param} this\n\t\t * @example\n\t\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t\t */\n\t Tone.Param.prototype.setValueAtTime = function (value, time) {\n\t value = this._fromUnits(value);\n\t time = this.toSeconds(time);\n\t if (time <= this.now() + this.blockTime) {\n\t this._param.value = value;\n\t } else {\n\t this._param.setValueAtTime(value, time);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Creates a schedule point with the current value at the current time.\n\t\t * This is useful for creating an automation anchor point in order to \n\t\t * schedule changes from the current value. \n\t\t *\n\t\t * @param {number=} now (Optionally) pass the now value in. \n\t\t * @returns {Tone.Param} this\n\t\t */\n\t Tone.Param.prototype.setRampPoint = function (now) {\n\t now = this.defaultArg(now, this.now());\n\t var currentVal = this._param.value;\n\t // exponentialRampToValueAt cannot ever ramp from or to 0\n\t // More info: https://bugzilla.mozilla.org/show_bug.cgi?id=1125600#c2\n\t if (currentVal === 0) {\n\t currentVal = this._minOutput;\n\t }\n\t this._param.setValueAtTime(currentVal, now);\n\t return this;\n\t };\n\t /**\n\t\t * Schedules a linear continuous change in parameter value from the \n\t\t * previous scheduled parameter value to the given value.\n\t\t * \n\t\t * @param {number} value \n\t\t * @param {Time} endTime \n\t\t * @returns {Tone.Param} this\n\t\t */\n\t Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) {\n\t value = this._fromUnits(value);\n\t this._param.linearRampToValueAtTime(value, this.toSeconds(endTime));\n\t return this;\n\t };\n\t /**\n\t\t * Schedules an exponential continuous change in parameter value from \n\t\t * the previous scheduled parameter value to the given value.\n\t\t * \n\t\t * @param {number} value \n\t\t * @param {Time} endTime \n\t\t * @returns {Tone.Param} this\n\t\t */\n\t Tone.Param.prototype.exponentialRampToValueAtTime = function (value, endTime) {\n\t value = this._fromUnits(value);\n\t value = Math.max(this._minOutput, value);\n\t this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));\n\t return this;\n\t };\n\t /**\n\t\t * Schedules an exponential continuous change in parameter value from \n\t\t * the current time and current value to the given value over the \n\t\t * duration of the rampTime.\n\t\t * \n\t\t * @param {number} value The value to ramp to.\n\t\t * @param {Time} rampTime the time that it takes the \n\t\t * value to ramp from it's current value\n\t\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t\t * @returns {Tone.Param} this\n\t\t * @example\n\t\t * //exponentially ramp to the value 2 over 4 seconds. \n\t\t * signal.exponentialRampToValue(2, 4);\n\t\t */\n\t Tone.Param.prototype.exponentialRampToValue = function (value, rampTime, startTime) {\n\t startTime = this.toSeconds(startTime);\n\t this.setRampPoint(startTime);\n\t this.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t return this;\n\t };\n\t /**\n\t\t * Schedules an linear continuous change in parameter value from \n\t\t * the current time and current value to the given value over the \n\t\t * duration of the rampTime.\n\t\t * \n\t\t * @param {number} value The value to ramp to.\n\t\t * @param {Time} rampTime the time that it takes the \n\t\t * value to ramp from it's current value\n\t\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t\t * @returns {Tone.Param} this\n\t\t * @example\n\t\t * //linearly ramp to the value 4 over 3 seconds. \n\t\t * signal.linearRampToValue(4, 3);\n\t\t */\n\t Tone.Param.prototype.linearRampToValue = function (value, rampTime, startTime) {\n\t startTime = this.toSeconds(startTime);\n\t this.setRampPoint(startTime);\n\t this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));\n\t return this;\n\t };\n\t /**\n\t\t * Start exponentially approaching the target value at the given time with\n\t\t * a rate having the given time constant.\n\t\t * @param {number} value \n\t\t * @param {Time} startTime \n\t\t * @param {number} timeConstant \n\t\t * @returns {Tone.Param} this \n\t\t */\n\t Tone.Param.prototype.setTargetAtTime = function (value, startTime, timeConstant) {\n\t value = this._fromUnits(value);\n\t // The value will never be able to approach without timeConstant > 0.\n\t // http://www.w3.org/TR/webaudio/#dfn-setTargetAtTime, where the equation\n\t // is described. 0 results in a division by 0.\n\t value = Math.max(this._minOutput, value);\n\t timeConstant = Math.max(this._minOutput, timeConstant);\n\t this._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);\n\t return this;\n\t };\n\t /**\n\t\t * Sets an array of arbitrary parameter values starting at the given time\n\t\t * for the given duration.\n\t\t * \t\n\t\t * @param {Array} values \n\t\t * @param {Time} startTime \n\t\t * @param {Time} duration \n\t\t * @returns {Tone.Param} this\n\t\t */\n\t Tone.Param.prototype.setValueCurveAtTime = function (values, startTime, duration) {\n\t for (var i = 0; i < values.length; i++) {\n\t values[i] = this._fromUnits(values[i]);\n\t }\n\t this._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));\n\t return this;\n\t };\n\t /**\n\t\t * Cancels all scheduled parameter changes with times greater than or \n\t\t * equal to startTime.\n\t\t * \n\t\t * @param {Time} startTime\n\t\t * @returns {Tone.Param} this\n\t\t */\n\t Tone.Param.prototype.cancelScheduledValues = function (startTime) {\n\t this._param.cancelScheduledValues(this.toSeconds(startTime));\n\t return this;\n\t };\n\t /**\n\t\t * Ramps to the given value over the duration of the rampTime. \n\t\t * Automatically selects the best ramp type (exponential or linear)\n\t\t * depending on the `units` of the signal\n\t\t * \n\t\t * @param {number} value \n\t\t * @param {Time} rampTime \tThe time that it takes the \n\t\t * value to ramp from it's current value\n\t\t * @param {Time}\t[startTime=now] \tWhen the ramp should start. \n\t\t * @returns {Tone.Param} this\n\t\t * @example\n\t\t * //ramp to the value either linearly or exponentially \n\t\t * //depending on the \"units\" value of the signal\n\t\t * signal.rampTo(0, 10);\n\t\t * @example\n\t\t * //schedule it to ramp starting at a specific time\n\t\t * signal.rampTo(0, 10, 5)\n\t\t */\n\t Tone.Param.prototype.rampTo = function (value, rampTime, startTime) {\n\t rampTime = this.defaultArg(rampTime, 0);\n\t if (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels) {\n\t this.exponentialRampToValue(value, rampTime, startTime);\n\t } else {\n\t this.linearRampToValue(value, rampTime, startTime);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * The LFO created by the signal instance. If none\n\t\t * was created, this is null.\n\t\t * @type {Tone.LFO}\n\t\t * @readOnly\n\t\t * @memberOf Tone.Param#\n\t\t * @name lfo\n\t\t */\n\t Object.defineProperty(Tone.Param.prototype, 'lfo', {\n\t get: function () {\n\t return this._lfo;\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @returns {Tone.Param} this\n\t\t */\n\t Tone.Param.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._param = null;\n\t if (this._lfo) {\n\t this._lfo.dispose();\n\t this._lfo = null;\n\t }\n\t return this;\n\t };\n\t return Tone.Param;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * createGain shim\n\t\t * @private\n\t\t */\n\t if (window.GainNode && !AudioContext.prototype.createGain) {\n\t AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;\n\t }\n\t /**\n\t\t * @class A thin wrapper around the Native Web Audio GainNode.\n\t\t * The GainNode is a basic building block of the Web Audio\n\t\t * API and is useful for routing audio and adjusting gains. \n\t\t * @extends {Tone}\n\t\t * @param {Number=} gain The initial gain of the GainNode\n\t\t * @param {Tone.Type=} units The units of the gain parameter. \n\t\t */\n\t Tone.Gain = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'gain',\n\t 'units'\n\t ], Tone.Gain.defaults);\n\t /**\n\t\t\t * The GainNode\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.input = this.output = this._gainNode = this.context.createGain();\n\t /**\n\t\t\t * The gain parameter of the gain node.\n\t\t\t * @type {Tone.Param}\n\t\t\t * @signal\n\t\t\t */\n\t this.gain = new Tone.Param({\n\t 'param': this._gainNode.gain,\n\t 'units': options.units,\n\t 'value': options.gain,\n\t 'convert': options.convert\n\t });\n\t this._readOnly('gain');\n\t };\n\t Tone.extend(Tone.Gain);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Gain.defaults = {\n\t 'gain': 1,\n\t 'convert': true\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.Gain} this\n\t\t */\n\t Tone.Gain.prototype.dispose = function () {\n\t Tone.Param.prototype.dispose.call(this);\n\t this._gainNode.disconnect();\n\t this._gainNode = null;\n\t this._writable('gain');\n\t this.gain.dispose();\n\t this.gain = null;\n\t };\n\t //STATIC///////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Create input and outputs for this object.\n\t\t * @param {Number} input The number of inputs\n\t\t * @param {Number=} outputs The number of outputs\n\t\t * @return {Tone} this\n\t\t * @internal\n\t\t */\n\t Tone.prototype.createInsOuts = function (inputs, outputs) {\n\t if (inputs === 1) {\n\t this.input = new Tone.Gain();\n\t } else if (inputs > 1) {\n\t this.input = new Array(inputs);\n\t }\n\t if (outputs === 1) {\n\t this.output = new Tone.Gain();\n\t } else if (outputs > 1) {\n\t this.output = new Array(inputs);\n\t }\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t return Tone.Gain;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A signal is an audio-rate value. Tone.Signal is a core component of the library.\n\t\t * Unlike a number, Signals can be scheduled with sample-level accuracy. Tone.Signal\n\t\t * has all of the methods available to native Web Audio \n\t\t * [AudioParam](http://webaudio.github.io/web-audio-api/#the-audioparam-interface)\n\t\t * as well as additional conveniences. Read more about working with signals \n\t\t * [here](https://github.com/Tonejs/Tone.js/wiki/Signals).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Param}\n\t\t * @param {Number|AudioParam} [value] Initial value of the signal. If an AudioParam\n\t\t * is passed in, that parameter will be wrapped\n\t\t * and controlled by the Signal. \n\t\t * @param {string} [units=Number] unit The units the signal is in. \n\t\t * @example\n\t\t * var signal = new Tone.Signal(10);\n\t\t */\n\t Tone.Signal = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'value',\n\t 'units'\n\t ], Tone.Signal.defaults);\n\t /**\n\t\t\t * The node where the constant signal value is scaled.\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.output = this._gain = this.context.createGain();\n\t options.param = this._gain.gain;\n\t Tone.Param.call(this, options);\n\t /**\n\t\t\t * The node where the value is set.\n\t\t\t * @type {Tone.Param}\n\t\t\t * @private\n\t\t\t */\n\t this.input = this._param = this._gain.gain;\n\t //connect the const output to the node output\n\t this.context.getConstant(1).chain(this._gain);\n\t };\n\t Tone.extend(Tone.Signal, Tone.Param);\n\t /**\n\t\t * The default values\n\t\t * @type {Object}\n\t\t * @static\n\t\t * @const\n\t\t */\n\t Tone.Signal.defaults = {\n\t 'value': 0,\n\t 'units': Tone.Type.Default,\n\t 'convert': true\n\t };\n\t /**\n\t\t * When signals connect to other signals or AudioParams, \n\t\t * they take over the output value of that signal or AudioParam. \n\t\t * For all other nodes, the behavior is the same as a default <code>connect</code>. \n\t\t *\n\t\t * @override\n\t\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t\t * @param {number} [outputNumber=0] The output number to connect from.\n\t\t * @param {number} [inputNumber=0] The input number to connect to.\n\t\t * @returns {Tone.SignalBase} this\n\t\t * @method\n\t\t */\n\t Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;\n\t /**\n\t\t * dispose and disconnect\n\t\t * @returns {Tone.Signal} this\n\t\t */\n\t Tone.Signal.prototype.dispose = function () {\n\t Tone.Param.prototype.dispose.call(this);\n\t this._param = null;\n\t this._gain.disconnect();\n\t this._gain = null;\n\t return this;\n\t };\n\t return Tone.Signal;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A Timeline class for scheduling and maintaining state\n\t\t * along a timeline. All events must have a \"time\" property. \n\t\t * Internally, events are stored in time order for fast \n\t\t * retrieval.\n\t\t * @extends {Tone}\n\t\t * @param {Positive} [memory=Infinity] The number of previous events that are retained.\n\t\t */\n\t Tone.Timeline = function () {\n\t var options = this.optionsObject(arguments, ['memory'], Tone.Timeline.defaults);\n\t /**\n\t\t\t * The array of scheduled timeline events\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._timeline = [];\n\t /**\n\t\t\t * An array of items to remove from the list. \n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._toRemove = [];\n\t /**\n\t\t\t * Flag if the tieline is mid iteration\n\t\t\t * @private\n\t\t\t * @type {Boolean}\n\t\t\t */\n\t this._iterating = false;\n\t /**\n\t\t\t * The memory of the timeline, i.e.\n\t\t\t * how many events in the past it will retain\n\t\t\t * @type {Positive}\n\t\t\t */\n\t this.memory = options.memory;\n\t };\n\t Tone.extend(Tone.Timeline);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t */\n\t Tone.Timeline.defaults = { 'memory': Infinity };\n\t /**\n\t\t * The number of items in the timeline.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Timeline#\n\t\t * @name length\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Timeline.prototype, 'length', {\n\t get: function () {\n\t return this._timeline.length;\n\t }\n\t });\n\t /**\n\t\t * Insert an event object onto the timeline. Events must have a \"time\" attribute.\n\t\t * @param {Object} event The event object to insert into the \n\t\t * timeline. \n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.add = function (event) {\n\t //the event needs to have a time attribute\n\t if (this.isUndef(event.time)) {\n\t throw new Error('Tone.Timeline: events must have a time attribute');\n\t }\n\t if (this._timeline.length) {\n\t var index = this._search(event.time);\n\t this._timeline.splice(index + 1, 0, event);\n\t } else {\n\t this._timeline.push(event);\n\t }\n\t //if the length is more than the memory, remove the previous ones\n\t if (this.length > this.memory) {\n\t var diff = this.length - this.memory;\n\t this._timeline.splice(0, diff);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Remove an event from the timeline.\n\t\t * @param {Object} event The event object to remove from the list.\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.remove = function (event) {\n\t if (this._iterating) {\n\t this._toRemove.push(event);\n\t } else {\n\t var index = this._timeline.indexOf(event);\n\t if (index !== -1) {\n\t this._timeline.splice(index, 1);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Get the nearest event whose time is less than or equal to the given time.\n\t\t * @param {Number} time The time to query.\n\t\t * @returns {Object} The event object set after that time.\n\t\t */\n\t Tone.Timeline.prototype.get = function (time) {\n\t var index = this._search(time);\n\t if (index !== -1) {\n\t return this._timeline[index];\n\t } else {\n\t return null;\n\t }\n\t };\n\t /**\n\t\t * Return the first event in the timeline without removing it\n\t\t * @returns {Object} The first event object\n\t\t */\n\t Tone.Timeline.prototype.peek = function () {\n\t return this._timeline[0];\n\t };\n\t /**\n\t\t * Return the first event in the timeline and remove it\n\t\t * @returns {Object} The first event object\n\t\t */\n\t Tone.Timeline.prototype.shift = function () {\n\t return this._timeline.shift();\n\t };\n\t /**\n\t\t * Get the event which is scheduled after the given time.\n\t\t * @param {Number} time The time to query.\n\t\t * @returns {Object} The event object after the given time\n\t\t */\n\t Tone.Timeline.prototype.getAfter = function (time) {\n\t var index = this._search(time);\n\t if (index + 1 < this._timeline.length) {\n\t return this._timeline[index + 1];\n\t } else {\n\t return null;\n\t }\n\t };\n\t /**\n\t\t * Get the event before the event at the given time.\n\t\t * @param {Number} time The time to query.\n\t\t * @returns {Object} The event object before the given time\n\t\t */\n\t Tone.Timeline.prototype.getBefore = function (time) {\n\t var len = this._timeline.length;\n\t //if it's after the last item, return the last item\n\t if (len > 0 && this._timeline[len - 1].time < time) {\n\t return this._timeline[len - 1];\n\t }\n\t var index = this._search(time);\n\t if (index - 1 >= 0) {\n\t return this._timeline[index - 1];\n\t } else {\n\t return null;\n\t }\n\t };\n\t /**\n\t\t * Cancel events after the given time\n\t\t * @param {Number} time The time to query.\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.cancel = function (after) {\n\t if (this._timeline.length > 1) {\n\t var index = this._search(after);\n\t if (index >= 0) {\n\t if (this._timeline[index].time === after) {\n\t //get the first item with that time\n\t for (var i = index; i >= 0; i--) {\n\t if (this._timeline[i].time === after) {\n\t index = i;\n\t } else {\n\t break;\n\t }\n\t }\n\t this._timeline = this._timeline.slice(0, index);\n\t } else {\n\t this._timeline = this._timeline.slice(0, index + 1);\n\t }\n\t } else {\n\t this._timeline = [];\n\t }\n\t } else if (this._timeline.length === 1) {\n\t //the first item's time\n\t if (this._timeline[0].time >= after) {\n\t this._timeline = [];\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Cancel events before or equal to the given time.\n\t\t * @param {Number} time The time to cancel before.\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.cancelBefore = function (time) {\n\t if (this._timeline.length) {\n\t var index = this._search(time);\n\t if (index >= 0) {\n\t this._timeline = this._timeline.slice(index + 1);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Does a binary serach on the timeline array and returns the \n\t\t * nearest event index whose time is after or equal to the given time.\n\t\t * If a time is searched before the first index in the timeline, -1 is returned.\n\t\t * If the time is after the end, the index of the last item is returned.\n\t\t * @param {Number} time \n\t\t * @return {Number} the index in the timeline array \n\t\t * @private\n\t\t */\n\t Tone.Timeline.prototype._search = function (time) {\n\t var beginning = 0;\n\t var len = this._timeline.length;\n\t var end = len;\n\t if (len > 0 && this._timeline[len - 1].time <= time) {\n\t return len - 1;\n\t }\n\t while (beginning < end) {\n\t // calculate the midpoint for roughly equal partition\n\t var midPoint = Math.floor(beginning + (end - beginning) / 2);\n\t var event = this._timeline[midPoint];\n\t var nextEvent = this._timeline[midPoint + 1];\n\t if (event.time === time) {\n\t //choose the last one that has the same time\n\t for (var i = midPoint; i < this._timeline.length; i++) {\n\t var testEvent = this._timeline[i];\n\t if (testEvent.time === time) {\n\t midPoint = i;\n\t }\n\t }\n\t return midPoint;\n\t } else if (event.time < time && nextEvent.time > time) {\n\t return midPoint;\n\t } else if (event.time > time) {\n\t //search lower\n\t end = midPoint;\n\t } else if (event.time < time) {\n\t //search upper\n\t beginning = midPoint + 1;\n\t }\n\t }\n\t return -1;\n\t };\n\t /**\n\t\t * Internal iterator. Applies extra safety checks for \n\t\t * removing items from the array. \n\t\t * @param {Function} callback \n\t\t * @param {Number=} lowerBound \n\t\t * @param {Number=} upperBound \n\t\t * @private\n\t\t */\n\t Tone.Timeline.prototype._iterate = function (callback, lowerBound, upperBound) {\n\t this._iterating = true;\n\t lowerBound = this.defaultArg(lowerBound, 0);\n\t upperBound = this.defaultArg(upperBound, this._timeline.length - 1);\n\t for (var i = lowerBound; i <= upperBound; i++) {\n\t callback(this._timeline[i]);\n\t }\n\t this._iterating = false;\n\t if (this._toRemove.length > 0) {\n\t for (var j = 0; j < this._toRemove.length; j++) {\n\t var index = this._timeline.indexOf(this._toRemove[j]);\n\t if (index !== -1) {\n\t this._timeline.splice(index, 1);\n\t }\n\t }\n\t this._toRemove = [];\n\t }\n\t };\n\t /**\n\t\t * Iterate over everything in the array\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.forEach = function (callback) {\n\t this._iterate(callback);\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over everything in the array at or before the given time.\n\t\t * @param {Number} time The time to check if items are before\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.forEachBefore = function (time, callback) {\n\t //iterate over the items in reverse so that removing an item doesn't break things\n\t var upperBound = this._search(time);\n\t if (upperBound !== -1) {\n\t this._iterate(callback, 0, upperBound);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over everything in the array after the given time.\n\t\t * @param {Number} time The time to check if items are before\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.forEachAfter = function (time, callback) {\n\t //iterate over the items in reverse so that removing an item doesn't break things\n\t var lowerBound = this._search(time);\n\t this._iterate(callback, lowerBound + 1);\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over everything in the array at or after the given time. Similar to \n\t\t * forEachAfter, but includes the item(s) at the given time.\n\t\t * @param {Number} time The time to check if items are before\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.forEachFrom = function (time, callback) {\n\t //iterate over the items in reverse so that removing an item doesn't break things\n\t var lowerBound = this._search(time);\n\t //work backwards until the event time is less than time\n\t while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) {\n\t lowerBound--;\n\t }\n\t this._iterate(callback, lowerBound + 1);\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over everything in the array at the given time\n\t\t * @param {Number} time The time to check if items are before\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.forEachAtTime = function (time, callback) {\n\t //iterate over the items in reverse so that removing an item doesn't break things\n\t var upperBound = this._search(time);\n\t if (upperBound !== -1) {\n\t this._iterate(function (event) {\n\t if (event.time === time) {\n\t callback(event);\n\t }\n\t }, 0, upperBound);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.Timeline} this\n\t\t */\n\t Tone.Timeline.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._timeline = null;\n\t this._toRemove = null;\n\t };\n\t return Tone.Timeline;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A signal which adds the method getValueAtTime. \n\t\t * Code and inspiration from https://github.com/jsantell/web-audio-automation-timeline\n\t\t * @extends {Tone.Param}\n\t\t * @param {Number=} value The initial value of the signal\n\t\t * @param {String=} units The conversion units of the signal.\n\t\t */\n\t Tone.TimelineSignal = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'value',\n\t 'units'\n\t ], Tone.Signal.defaults);\n\t /**\n\t\t\t * The scheduled events\n\t\t\t * @type {Tone.Timeline}\n\t\t\t * @private\n\t\t\t */\n\t this._events = new Tone.Timeline(10);\n\t //constructors\n\t Tone.Signal.apply(this, options);\n\t options.param = this._param;\n\t Tone.Param.call(this, options);\n\t /**\n\t\t\t * The initial scheduled value\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._initial = this._fromUnits(this._param.value);\n\t };\n\t Tone.extend(Tone.TimelineSignal, Tone.Param);\n\t /**\n\t\t * The event types of a schedulable signal.\n\t\t * @enum {String}\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.Type = {\n\t Linear: 'linear',\n\t Exponential: 'exponential',\n\t Target: 'target',\n\t Curve: 'curve',\n\t Set: 'set'\n\t };\n\t /**\n\t\t * The current value of the signal. \n\t\t * @memberOf Tone.TimelineSignal#\n\t\t * @type {Number}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.TimelineSignal.prototype, 'value', {\n\t get: function () {\n\t var now = this.now();\n\t var val = this.getValueAtTime(now);\n\t return this._toUnits(val);\n\t },\n\t set: function (value) {\n\t var convertedVal = this._fromUnits(value);\n\t this._initial = convertedVal;\n\t this.cancelScheduledValues();\n\t this._param.value = convertedVal;\n\t }\n\t });\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tSCHEDULING\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Schedules a parameter value change at the given time.\n\t\t * @param {*}\tvalue The value to set the signal.\n\t\t * @param {Time} time The time when the change should occur.\n\t\t * @returns {Tone.TimelineSignal} this\n\t\t * @example\n\t\t * //set the frequency to \"G4\" in exactly 1 second from now. \n\t\t * freq.setValueAtTime(\"G4\", \"+1\");\n\t\t */\n\t Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {\n\t value = this._fromUnits(value);\n\t startTime = this.toSeconds(startTime);\n\t this._events.add({\n\t 'type': Tone.TimelineSignal.Type.Set,\n\t 'value': value,\n\t 'time': startTime\n\t });\n\t //invoke the original event\n\t this._param.setValueAtTime(value, startTime);\n\t return this;\n\t };\n\t /**\n\t\t * Schedules a linear continuous change in parameter value from the \n\t\t * previous scheduled parameter value to the given value.\n\t\t * \n\t\t * @param {number} value \n\t\t * @param {Time} endTime \n\t\t * @returns {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {\n\t value = this._fromUnits(value);\n\t endTime = this.toSeconds(endTime);\n\t this._events.add({\n\t 'type': Tone.TimelineSignal.Type.Linear,\n\t 'value': value,\n\t 'time': endTime\n\t });\n\t this._param.linearRampToValueAtTime(value, endTime);\n\t return this;\n\t };\n\t /**\n\t\t * Schedules an exponential continuous change in parameter value from \n\t\t * the previous scheduled parameter value to the given value.\n\t\t * \n\t\t * @param {number} value \n\t\t * @param {Time} endTime \n\t\t * @returns {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {\n\t //get the previous event and make sure it's not starting from 0\n\t endTime = this.toSeconds(endTime);\n\t var beforeEvent = this._searchBefore(endTime);\n\t if (beforeEvent && beforeEvent.value === 0) {\n\t //reschedule that event\n\t this.setValueAtTime(this._minOutput, beforeEvent.time);\n\t }\n\t value = this._fromUnits(value);\n\t var setValue = Math.max(value, this._minOutput);\n\t this._events.add({\n\t 'type': Tone.TimelineSignal.Type.Exponential,\n\t 'value': setValue,\n\t 'time': endTime\n\t });\n\t //if the ramped to value is 0, make it go to the min output, and then set to 0.\n\t if (value < this._minOutput) {\n\t this._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);\n\t this.setValueAtTime(0, endTime);\n\t } else {\n\t this._param.exponentialRampToValueAtTime(value, endTime);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Start exponentially approaching the target value at the given time with\n\t\t * a rate having the given time constant.\n\t\t * @param {number} value \n\t\t * @param {Time} startTime \n\t\t * @param {number} timeConstant \n\t\t * @returns {Tone.TimelineSignal} this \n\t\t */\n\t Tone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {\n\t value = this._fromUnits(value);\n\t value = Math.max(this._minOutput, value);\n\t timeConstant = Math.max(this._minOutput, timeConstant);\n\t startTime = this.toSeconds(startTime);\n\t this._events.add({\n\t 'type': Tone.TimelineSignal.Type.Target,\n\t 'value': value,\n\t 'time': startTime,\n\t 'constant': timeConstant\n\t });\n\t this._param.setTargetAtTime(value, startTime, timeConstant);\n\t return this;\n\t };\n\t /**\n\t\t * Set an array of arbitrary values starting at the given time for the given duration.\n\t\t * @param {Float32Array} values \n\t\t * @param {Time} startTime \n\t\t * @param {Time} duration\n\t\t * @param {NormalRange} [scaling=1] If the values in the curve should be scaled by some value\n\t\t * @returns {Tone.TimelineSignal} this \n\t\t */\n\t Tone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {\n\t scaling = this.defaultArg(scaling, 1);\n\t //copy the array\n\t var floats = new Array(values.length);\n\t for (var i = 0; i < floats.length; i++) {\n\t floats[i] = this._fromUnits(values[i]) * scaling;\n\t }\n\t startTime = this.toSeconds(startTime);\n\t duration = this.toSeconds(duration);\n\t this._events.add({\n\t 'type': Tone.TimelineSignal.Type.Curve,\n\t 'value': floats,\n\t 'time': startTime,\n\t 'duration': duration\n\t });\n\t //set the first value\n\t this._param.setValueAtTime(floats[0], startTime);\n\t //schedule a lienar ramp for each of the segments\n\t for (var j = 1; j < floats.length; j++) {\n\t var segmentTime = startTime + j / (floats.length - 1) * duration;\n\t this._param.linearRampToValueAtTime(floats[j], segmentTime);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Cancels all scheduled parameter changes with times greater than or \n\t\t * equal to startTime.\n\t\t * \n\t\t * @param {Time} startTime\n\t\t * @returns {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) {\n\t after = this.toSeconds(after);\n\t this._events.cancel(after);\n\t this._param.cancelScheduledValues(after);\n\t return this;\n\t };\n\t /**\n\t\t * Sets the computed value at the given time. This provides\n\t\t * a point from which a linear or exponential curve\n\t\t * can be scheduled after. Will cancel events after \n\t\t * the given time and shorten the currently scheduled\n\t\t * linear or exponential ramp so that it ends at `time` .\n\t\t * This is to avoid discontinuities and clicks in envelopes. \n\t\t * @param {Time} time When to set the ramp point\n\t\t * @returns {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.setRampPoint = function (time) {\n\t time = this.toSeconds(time);\n\t //get the value at the given time\n\t var val = this._toUnits(this.getValueAtTime(time));\n\t //if there is an event at the given time\n\t //and that even is not a \"set\"\n\t var before = this._searchBefore(time);\n\t if (before && before.time === time) {\n\t //remove everything after\n\t this.cancelScheduledValues(time + this.sampleTime);\n\t } else if (before && before.type === Tone.TimelineSignal.Type.Curve && before.time + before.duration > time) {\n\t //if the curve is still playing\n\t //cancel the curve\n\t this.cancelScheduledValues(time);\n\t this.linearRampToValueAtTime(val, time);\n\t } else {\n\t //reschedule the next event to end at the given time\n\t var after = this._searchAfter(time);\n\t if (after) {\n\t //cancel the next event(s)\n\t this.cancelScheduledValues(time);\n\t if (after.type === Tone.TimelineSignal.Type.Linear) {\n\t this.linearRampToValueAtTime(val, time);\n\t } else if (after.type === Tone.TimelineSignal.Type.Exponential) {\n\t this.exponentialRampToValueAtTime(val, time);\n\t }\n\t }\n\t this.setValueAtTime(val, time);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Do a linear ramp to the given value between the start and finish times.\n\t\t * @param {Number} value The value to ramp to.\n\t\t * @param {Time} start The beginning anchor point to do the linear ramp\n\t\t * @param {Time} finish The ending anchor point by which the value of\n\t\t * the signal will equal the given value.\n\t\t * @returns {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {\n\t this.setRampPoint(start);\n\t this.linearRampToValueAtTime(value, finish);\n\t return this;\n\t };\n\t /**\n\t\t * Do a exponential ramp to the given value between the start and finish times.\n\t\t * @param {Number} value The value to ramp to.\n\t\t * @param {Time} start The beginning anchor point to do the exponential ramp\n\t\t * @param {Time} finish The ending anchor point by which the value of\n\t\t * the signal will equal the given value.\n\t\t * @returns {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {\n\t this.setRampPoint(start);\n\t this.exponentialRampToValueAtTime(value, finish);\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tGETTING SCHEDULED VALUES\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Returns the value before or equal to the given time\n\t\t * @param {Number} time The time to query\n\t\t * @return {Object} The event at or before the given time.\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.prototype._searchBefore = function (time) {\n\t return this._events.get(time);\n\t };\n\t /**\n\t\t * The event after the given time\n\t\t * @param {Number} time The time to query.\n\t\t * @return {Object} The next event after the given time\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.prototype._searchAfter = function (time) {\n\t return this._events.getAfter(time);\n\t };\n\t /**\n\t\t * Get the scheduled value at the given time. This will\n\t\t * return the unconverted (raw) value.\n\t\t * @param {Number} time The time in seconds.\n\t\t * @return {Number} The scheduled value at the given time.\n\t\t */\n\t Tone.TimelineSignal.prototype.getValueAtTime = function (time) {\n\t time = this.toSeconds(time);\n\t var after = this._searchAfter(time);\n\t var before = this._searchBefore(time);\n\t var value = this._initial;\n\t //if it was set by\n\t if (before === null) {\n\t value = this._initial;\n\t } else if (before.type === Tone.TimelineSignal.Type.Target) {\n\t var previous = this._events.getBefore(before.time);\n\t var previouVal;\n\t if (previous === null) {\n\t previouVal = this._initial;\n\t } else {\n\t previouVal = previous.value;\n\t }\n\t value = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);\n\t } else if (before.type === Tone.TimelineSignal.Type.Curve) {\n\t value = this._curveInterpolate(before.time, before.value, before.duration, time);\n\t } else if (after === null) {\n\t value = before.value;\n\t } else if (after.type === Tone.TimelineSignal.Type.Linear) {\n\t value = this._linearInterpolate(before.time, before.value, after.time, after.value, time);\n\t } else if (after.type === Tone.TimelineSignal.Type.Exponential) {\n\t value = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);\n\t } else {\n\t value = before.value;\n\t }\n\t return value;\n\t };\n\t /**\n\t\t * When signals connect to other signals or AudioParams, \n\t\t * they take over the output value of that signal or AudioParam. \n\t\t * For all other nodes, the behavior is the same as a default <code>connect</code>. \n\t\t *\n\t\t * @override\n\t\t * @param {AudioParam|AudioNode|Tone.Signal|Tone} node \n\t\t * @param {number} [outputNumber=0] The output number to connect from.\n\t\t * @param {number} [inputNumber=0] The input number to connect to.\n\t\t * @returns {Tone.TimelineSignal} this\n\t\t * @method\n\t\t */\n\t Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tAUTOMATION CURVE CALCULATIONS\n\t //\tMIT License, copyright (c) 2014 Jordan Santell\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Calculates the the value along the curve produced by setTargetAtTime\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {\n\t return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);\n\t };\n\t /**\n\t\t * Calculates the the value along the curve produced by linearRampToValueAtTime\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {\n\t return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));\n\t };\n\t /**\n\t\t * Calculates the the value along the curve produced by exponentialRampToValueAtTime\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {\n\t v0 = Math.max(this._minOutput, v0);\n\t return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));\n\t };\n\t /**\n\t\t * Calculates the the value along the curve produced by setValueCurveAtTime\n\t\t * @private\n\t\t */\n\t Tone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {\n\t var len = curve.length;\n\t // If time is after duration, return the last curve value\n\t if (time >= start + duration) {\n\t return curve[len - 1];\n\t } else if (time <= start) {\n\t return curve[0];\n\t } else {\n\t var progress = (time - start) / duration;\n\t var lowerIndex = Math.floor((len - 1) * progress);\n\t var upperIndex = Math.ceil((len - 1) * progress);\n\t var lowerVal = curve[lowerIndex];\n\t var upperVal = curve[upperIndex];\n\t if (upperIndex === lowerIndex) {\n\t return lowerVal;\n\t } else {\n\t return this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));\n\t }\n\t }\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.TimelineSignal} this\n\t\t */\n\t Tone.TimelineSignal.prototype.dispose = function () {\n\t Tone.Signal.prototype.dispose.call(this);\n\t Tone.Param.prototype.dispose.call(this);\n\t this._events.dispose();\n\t this._events = null;\n\t };\n\t return Tone.TimelineSignal;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Pow applies an exponent to the incoming signal. The incoming signal\n\t\t * must be AudioRange.\n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @param {Positive} exp The exponent to apply to the incoming signal, must be at least 2. \n\t\t * @example\n\t\t * var pow = new Tone.Pow(2);\n\t\t * var sig = new Tone.Signal(0.5).connect(pow);\n\t\t * //output of pow is 0.25. \n\t\t */\n\t Tone.Pow = function (exp) {\n\t /**\n\t\t\t * the exponent\n\t\t\t * @private\n\t\t\t * @type {number}\n\t\t\t */\n\t this._exp = this.defaultArg(exp, 1);\n\t /**\n\t\t\t * @type {WaveShaperNode}\n\t\t\t * @private\n\t\t\t */\n\t this._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);\n\t };\n\t Tone.extend(Tone.Pow, Tone.SignalBase);\n\t /**\n\t\t * The value of the exponent.\n\t\t * @memberOf Tone.Pow#\n\t\t * @type {number}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.Pow.prototype, 'value', {\n\t get: function () {\n\t return this._exp;\n\t },\n\t set: function (exp) {\n\t this._exp = exp;\n\t this._expScaler.setMap(this._expFunc(this._exp));\n\t }\n\t });\n\t /**\n\t\t * the function which maps the waveshaper\n\t\t * @param {number} exp\n\t\t * @return {function}\n\t\t * @private\n\t\t */\n\t Tone.Pow.prototype._expFunc = function (exp) {\n\t return function (val) {\n\t return Math.pow(Math.abs(val), exp);\n\t };\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Pow} this\n\t\t */\n\t Tone.Pow.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._expScaler.dispose();\n\t this._expScaler = null;\n\t return this;\n\t };\n\t return Tone.Pow;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Envelope is an [ADSR](https://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope)\n\t\t * envelope generator. Tone.Envelope outputs a signal which \n\t\t * can be connected to an AudioParam or Tone.Signal. \n\t\t * <img src=\"https://upload.wikimedia.org/wikipedia/commons/e/ea/ADSR_parameter.svg\">\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {Time} [attack] The amount of time it takes for the envelope to go from \n\t\t * 0 to it's maximum value. \n\t\t * @param {Time} [decay]\tThe period of time after the attack that it takes for the envelope\n\t\t * \tto fall to the sustain value. \n\t\t * @param {NormalRange} [sustain]\tThe percent of the maximum value that the envelope rests at until\n\t\t * \tthe release is triggered. \n\t\t * @param {Time} [release]\tThe amount of time after the release is triggered it takes to reach 0. \n\t\t * @example\n\t\t * //an amplitude envelope\n\t\t * var gainNode = Tone.context.createGain();\n\t\t * var env = new Tone.Envelope({\n\t\t * \t\"attack\" : 0.1,\n\t\t * \t\"decay\" : 0.2,\n\t\t * \t\"sustain\" : 1,\n\t\t * \t\"release\" : 0.8,\n\t\t * });\n\t\t * env.connect(gainNode.gain);\n\t\t */\n\t Tone.Envelope = function () {\n\t //get all of the defaults\n\t var options = this.optionsObject(arguments, [\n\t 'attack',\n\t 'decay',\n\t 'sustain',\n\t 'release'\n\t ], Tone.Envelope.defaults);\n\t /** \n\t\t\t * When triggerAttack is called, the attack time is the amount of\n\t\t\t * time it takes for the envelope to reach it's maximum value. \n\t\t\t * @type {Time}\n\t\t\t */\n\t this.attack = options.attack;\n\t /**\n\t\t\t * After the attack portion of the envelope, the value will fall\n\t\t\t * over the duration of the decay time to it's sustain value. \n\t\t\t * @type {Time}\n\t\t\t */\n\t this.decay = options.decay;\n\t /**\n\t\t\t * \tThe sustain value is the value \n\t\t\t * \twhich the envelope rests at after triggerAttack is\n\t\t\t * \tcalled, but before triggerRelease is invoked. \n\t\t\t * @type {NormalRange}\n\t\t\t */\n\t this.sustain = options.sustain;\n\t /**\n\t\t\t * After triggerRelease is called, the envelope's\n\t\t\t * value will fall to it's miminum value over the\n\t\t\t * duration of the release time. \n\t\t\t * @type {Time}\n\t\t\t */\n\t this.release = options.release;\n\t /**\n\t\t\t * the next time the envelope is at standby\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._attackCurve = 'linear';\n\t /**\n\t\t\t * the next time the envelope is at standby\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._releaseCurve = 'exponential';\n\t /**\n\t\t\t * the signal\n\t\t\t * @type {Tone.TimelineSignal}\n\t\t\t * @private\n\t\t\t */\n\t this._sig = this.output = new Tone.TimelineSignal();\n\t this._sig.setValueAtTime(0, 0);\n\t //set the attackCurve initially\n\t this.attackCurve = options.attackCurve;\n\t this.releaseCurve = options.releaseCurve;\n\t };\n\t Tone.extend(Tone.Envelope);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t */\n\t Tone.Envelope.defaults = {\n\t 'attack': 0.01,\n\t 'decay': 0.1,\n\t 'sustain': 0.5,\n\t 'release': 1,\n\t 'attackCurve': 'linear',\n\t 'releaseCurve': 'exponential'\n\t };\n\t /**\n\t\t * Read the current value of the envelope. Useful for \n\t\t * syncronizing visual output to the envelope. \n\t\t * @memberOf Tone.Envelope#\n\t\t * @type {Number}\n\t\t * @name value\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Envelope.prototype, 'value', {\n\t get: function () {\n\t return this.getValueAtTime(this.now());\n\t }\n\t });\n\t /**\n\t\t * The shape of the attack. \n\t\t * Can be any of these strings:\n\t\t * <ul>\n\t\t * <li>linear</li>\n\t\t * <li>exponential</li>\n\t\t * <li>sine</li>\n\t\t * <li>cosine</li>\n\t\t * <li>bounce</li>\n\t\t * <li>ripple</li>\n\t\t * <li>step</li>\n\t\t * </ul>\n\t\t * Can also be an array which describes the curve. Values\n\t\t * in the array are evenly subdivided and linearly\n\t\t * interpolated over the duration of the attack. \n\t\t * @memberOf Tone.Envelope#\n\t\t * @type {String|Array}\n\t\t * @name attackCurve\n\t\t * @example\n\t\t * env.attackCurve = \"linear\";\n\t\t * @example\n\t\t * //can also be an array\n\t\t * env.attackCurve = [0, 0.2, 0.3, 0.4, 1]\n\t\t */\n\t Object.defineProperty(Tone.Envelope.prototype, 'attackCurve', {\n\t get: function () {\n\t if (this.isString(this._attackCurve)) {\n\t return this._attackCurve;\n\t } else if (this.isArray(this._attackCurve)) {\n\t //look up the name in the curves array\n\t for (var type in Tone.Envelope.Type) {\n\t if (Tone.Envelope.Type[type].In === this._attackCurve) {\n\t return type;\n\t }\n\t }\n\t //otherwise just return the array\n\t return this._attackCurve;\n\t }\n\t },\n\t set: function (curve) {\n\t //check if it's a valid type\n\t if (Tone.Envelope.Type.hasOwnProperty(curve)) {\n\t var curveDef = Tone.Envelope.Type[curve];\n\t if (this.isObject(curveDef)) {\n\t this._attackCurve = curveDef.In;\n\t } else {\n\t this._attackCurve = curveDef;\n\t }\n\t } else if (this.isArray(curve)) {\n\t this._attackCurve = curve;\n\t } else {\n\t throw new Error('Tone.Envelope: invalid curve: ' + curve);\n\t }\n\t }\n\t });\n\t /**\n\t\t * The shape of the release. See the attack curve types. \n\t\t * @memberOf Tone.Envelope#\n\t\t * @type {String|Array}\n\t\t * @name releaseCurve\n\t\t * @example\n\t\t * env.releaseCurve = \"linear\";\n\t\t */\n\t Object.defineProperty(Tone.Envelope.prototype, 'releaseCurve', {\n\t get: function () {\n\t if (this.isString(this._releaseCurve)) {\n\t return this._releaseCurve;\n\t } else if (this.isArray(this._releaseCurve)) {\n\t //look up the name in the curves array\n\t for (var type in Tone.Envelope.Type) {\n\t if (Tone.Envelope.Type[type].Out === this._releaseCurve) {\n\t return type;\n\t }\n\t }\n\t //otherwise just return the array\n\t return this._releaseCurve;\n\t }\n\t },\n\t set: function (curve) {\n\t //check if it's a valid type\n\t if (Tone.Envelope.Type.hasOwnProperty(curve)) {\n\t var curveDef = Tone.Envelope.Type[curve];\n\t if (this.isObject(curveDef)) {\n\t this._releaseCurve = curveDef.Out;\n\t } else {\n\t this._releaseCurve = curveDef;\n\t }\n\t } else if (this.isArray(curve)) {\n\t this._releaseCurve = curve;\n\t } else {\n\t throw new Error('Tone.Envelope: invalid curve: ' + curve);\n\t }\n\t }\n\t });\n\t /**\n\t\t * Trigger the attack/decay portion of the ADSR envelope. \n\t\t * @param {Time} [time=now] When the attack should start.\n\t\t * @param {NormalRange} [velocity=1] The velocity of the envelope scales the vales.\n\t\t * number between 0-1\n\t\t * @returns {Tone.Envelope} this\n\t\t * @example\n\t\t * //trigger the attack 0.5 seconds from now with a velocity of 0.2\n\t\t * env.triggerAttack(\"+0.5\", 0.2);\n\t\t */\n\t Tone.Envelope.prototype.triggerAttack = function (time, velocity) {\n\t time = this.toSeconds(time);\n\t var originalAttack = this.toSeconds(this.attack);\n\t var attack = originalAttack;\n\t var decay = this.toSeconds(this.decay);\n\t velocity = this.defaultArg(velocity, 1);\n\t //check if it's not a complete attack\n\t var currentValue = this.getValueAtTime(time);\n\t if (currentValue > 0) {\n\t //subtract the current value from the attack time\n\t var attackRate = 1 / attack;\n\t var remainingDistance = 1 - currentValue;\n\t //the attack is now the remaining time\n\t attack = remainingDistance / attackRate;\n\t }\n\t //attack\n\t if (this._attackCurve === 'linear') {\n\t this._sig.linearRampToValue(velocity, attack, time);\n\t } else if (this._attackCurve === 'exponential') {\n\t this._sig.exponentialRampToValue(velocity, attack, time);\n\t } else if (attack > 0) {\n\t this._sig.setRampPoint(time);\n\t var curve = this._attackCurve;\n\t //take only a portion of the curve\n\t if (attack < originalAttack) {\n\t var percentComplete = 1 - attack / originalAttack;\n\t var sliceIndex = Math.floor(percentComplete * this._attackCurve.length);\n\t curve = this._attackCurve.slice(sliceIndex);\n\t //the first index is the current value\n\t curve[0] = currentValue;\n\t }\n\t this._sig.setValueCurveAtTime(curve, time, attack, velocity);\n\t }\n\t //decay\n\t this._sig.exponentialRampToValue(velocity * this.sustain, decay, attack + time);\n\t return this;\n\t };\n\t /**\n\t\t * Triggers the release of the envelope.\n\t\t * @param {Time} [time=now] When the release portion of the envelope should start. \n\t\t * @returns {Tone.Envelope} this\n\t\t * @example\n\t\t * //trigger release immediately\n\t\t * env.triggerRelease();\n\t\t */\n\t Tone.Envelope.prototype.triggerRelease = function (time) {\n\t time = this.toSeconds(time);\n\t var currentValue = this.getValueAtTime(time);\n\t if (currentValue > 0) {\n\t var release = this.toSeconds(this.release);\n\t if (this._releaseCurve === 'linear') {\n\t this._sig.linearRampToValue(0, release, time);\n\t } else if (this._releaseCurve === 'exponential') {\n\t this._sig.exponentialRampToValue(0, release, time);\n\t } else {\n\t var curve = this._releaseCurve;\n\t if (this.isArray(curve)) {\n\t this._sig.setRampPoint(time);\n\t this._sig.setValueCurveAtTime(curve, time, release, currentValue);\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Get the scheduled value at the given time. This will\n\t\t * return the unconverted (raw) value.\n\t\t * @param {Number} time The time in seconds.\n\t\t * @return {Number} The scheduled value at the given time.\n\t\t */\n\t Tone.Envelope.prototype.getValueAtTime = function (time) {\n\t return this._sig.getValueAtTime(time);\n\t };\n\t /**\n\t\t * triggerAttackRelease is shorthand for triggerAttack, then waiting\n\t\t * some duration, then triggerRelease. \n\t\t * @param {Time} duration The duration of the sustain.\n\t\t * @param {Time} [time=now] When the attack should be triggered.\n\t\t * @param {number} [velocity=1] The velocity of the envelope. \n\t\t * @returns {Tone.Envelope} this\n\t\t * @example\n\t\t * //trigger the attack and then the release after 0.6 seconds.\n\t\t * env.triggerAttackRelease(0.6);\n\t\t */\n\t Tone.Envelope.prototype.triggerAttackRelease = function (duration, time, velocity) {\n\t time = this.toSeconds(time);\n\t this.triggerAttack(time, velocity);\n\t this.triggerRelease(time + this.toSeconds(duration));\n\t return this;\n\t };\n\t /**\n\t\t * Cancels all scheduled envelope changes after the given time.\n\t\t * @param {Time} after\n\t\t * @returns {Tone.Envelope} this\n\t\t */\n\t Tone.Envelope.prototype.cancel = function (after) {\n\t this._sig.cancelScheduledValues(after);\n\t return this;\n\t };\n\t /**\n\t\t * Borrows the connect method from Tone.Signal. \n\t\t * @function\n\t\t * @private\n\t\t */\n\t Tone.Envelope.prototype.connect = Tone.Signal.prototype.connect;\n\t /**\n\t \t * Generate some complex envelope curves. \n\t \t */\n\t (function _createCurves() {\n\t var curveLen = 128;\n\t var i, k;\n\t //cosine curve\n\t var cosineCurve = [];\n\t for (i = 0; i < curveLen; i++) {\n\t cosineCurve[i] = Math.sin(i / (curveLen - 1) * (Math.PI / 2));\n\t }\n\t //ripple curve\n\t var rippleCurve = [];\n\t var rippleCurveFreq = 6.4;\n\t for (i = 0; i < curveLen - 1; i++) {\n\t k = i / (curveLen - 1);\n\t var sineWave = Math.sin(k * (Math.PI * 2) * rippleCurveFreq - Math.PI / 2) + 1;\n\t rippleCurve[i] = sineWave / 10 + k * 0.83;\n\t }\n\t rippleCurve[curveLen - 1] = 1;\n\t //stairs curve\n\t var stairsCurve = [];\n\t var steps = 5;\n\t for (i = 0; i < curveLen; i++) {\n\t stairsCurve[i] = Math.ceil(i / (curveLen - 1) * steps) / steps;\n\t }\n\t //in-out easing curve\n\t var sineCurve = [];\n\t for (i = 0; i < curveLen; i++) {\n\t k = i / (curveLen - 1);\n\t sineCurve[i] = 0.5 * (1 - Math.cos(Math.PI * k));\n\t }\n\t //a bounce curve\n\t var bounceCurve = [];\n\t for (i = 0; i < curveLen; i++) {\n\t k = i / (curveLen - 1);\n\t var freq = Math.pow(k, 3) * 4 + 0.2;\n\t var val = Math.cos(freq * Math.PI * 2 * k);\n\t bounceCurve[i] = Math.abs(val * (1 - k));\n\t }\n\t /**\n\t\t\t * Invert a value curve to make it work for the release\n\t\t\t * @private\n\t\t\t */\n\t function invertCurve(curve) {\n\t var out = new Array(curve.length);\n\t for (var j = 0; j < curve.length; j++) {\n\t out[j] = 1 - curve[j];\n\t }\n\t return out;\n\t }\n\t /**\n\t\t\t * reverse the curve\n\t\t\t * @private\n\t\t\t */\n\t function reverseCurve(curve) {\n\t return curve.slice(0).reverse();\n\t }\n\t /**\n\t\t\t * attack and release curve arrays\n\t\t\t * @type {Object}\n\t\t\t * @private\n\t\t\t */\n\t Tone.Envelope.Type = {\n\t 'linear': 'linear',\n\t 'exponential': 'exponential',\n\t 'bounce': {\n\t In: invertCurve(bounceCurve),\n\t Out: bounceCurve\n\t },\n\t 'cosine': {\n\t In: cosineCurve,\n\t Out: reverseCurve(cosineCurve)\n\t },\n\t 'step': {\n\t In: stairsCurve,\n\t Out: invertCurve(stairsCurve)\n\t },\n\t 'ripple': {\n\t In: rippleCurve,\n\t Out: invertCurve(rippleCurve)\n\t },\n\t 'sine': {\n\t In: sineCurve,\n\t Out: invertCurve(sineCurve)\n\t }\n\t };\n\t }());\n\t /**\n\t\t * Disconnect and dispose.\n\t\t * @returns {Tone.Envelope} this\n\t\t */\n\t Tone.Envelope.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._sig.dispose();\n\t this._sig = null;\n\t this._attackCurve = null;\n\t this._releaseCurve = null;\n\t return this;\n\t };\n\t return Tone.Envelope;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.AmplitudeEnvelope is a Tone.Envelope connected to a gain node. \n\t\t * Unlike Tone.Envelope, which outputs the envelope's value, Tone.AmplitudeEnvelope accepts\n\t\t * an audio signal as the input and will apply the envelope to the amplitude\n\t\t * of the signal. Read more about ADSR Envelopes on [Wikipedia](https://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope).\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Envelope}\n\t\t * @param {Time|Object} [attack] The amount of time it takes for the envelope to go from \n\t\t * 0 to it's maximum value. \n\t\t * @param {Time} [decay]\tThe period of time after the attack that it takes for the envelope\n\t\t * \tto fall to the sustain value. \n\t\t * @param {NormalRange} [sustain]\tThe percent of the maximum value that the envelope rests at until\n\t\t * \tthe release is triggered. \n\t\t * @param {Time} [release]\tThe amount of time after the release is triggered it takes to reach 0. \n\t\t * @example\n\t\t * var ampEnv = new Tone.AmplitudeEnvelope({\n\t\t * \t\"attack\": 0.1,\n\t\t * \t\"decay\": 0.2,\n\t\t * \t\"sustain\": 1.0,\n\t\t * \t\"release\": 0.8\n\t\t * }).toMaster();\n\t\t * //create an oscillator and connect it\n\t\t * var osc = new Tone.Oscillator().connect(ampEnv).start();\n\t\t * //trigger the envelopes attack and release \"8t\" apart\n\t\t * ampEnv.triggerAttackRelease(\"8t\");\n\t\t */\n\t Tone.AmplitudeEnvelope = function () {\n\t Tone.Envelope.apply(this, arguments);\n\t /**\n\t\t\t * the input node\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.input = this.output = new Tone.Gain();\n\t this._sig.connect(this.output.gain);\n\t };\n\t Tone.extend(Tone.AmplitudeEnvelope, Tone.Envelope);\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.AmplitudeEnvelope} this\n\t\t */\n\t Tone.AmplitudeEnvelope.prototype.dispose = function () {\n\t this.input.dispose();\n\t this.input = null;\n\t Tone.Envelope.prototype.dispose.call(this);\n\t return this;\n\t };\n\t return Tone.AmplitudeEnvelope;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * AnalyserNode.getFloatTimeDomainData polyfill\n\t\t * @private\n\t\t */\n\t if (window.AnalyserNode && !AnalyserNode.prototype.getFloatTimeDomainData) {\n\t //referenced https://github.com/mohayonao/get-float-time-domain-data \n\t AnalyserNode.prototype.getFloatTimeDomainData = function (array) {\n\t var uint8 = new Uint8Array(array.length);\n\t this.getByteTimeDomainData(uint8);\n\t for (var i = 0; i < uint8.length; i++) {\n\t array[i] = (uint8[i] - 128) / 128;\n\t }\n\t };\n\t }\n\t /**\n\t\t * @class Wrapper around the native Web Audio's \n\t\t * [AnalyserNode](http://webaudio.github.io/web-audio-api/#idl-def-AnalyserNode).\n\t\t * Extracts FFT or Waveform data from the incoming signal.\n\t\t * @extends {Tone}\n\t\t * @param {String=} type The return type of the analysis, either \"fft\", or \"waveform\". \n\t\t * @param {Number=} size The size of the FFT. Value must be a power of \n\t\t * two in the range 32 to 32768.\n\t\t */\n\t Tone.Analyser = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'type',\n\t 'size'\n\t ], Tone.Analyser.defaults);\n\t /**\n\t\t\t * The analyser node.\n\t\t\t * @private\n\t\t\t * @type {AnalyserNode}\n\t\t\t */\n\t this._analyser = this.input = this.output = this.context.createAnalyser();\n\t /**\n\t\t\t * The analysis type\n\t\t\t * @type {String}\n\t\t\t * @private\n\t\t\t */\n\t this._type = options.type;\n\t /**\n\t\t\t * The return type of the analysis\n\t\t\t * @type {String}\n\t\t\t * @private\n\t\t\t */\n\t this._returnType = options.returnType;\n\t /**\n\t\t\t * The buffer that the FFT data is written to\n\t\t\t * @type {TypedArray}\n\t\t\t * @private\n\t\t\t */\n\t this._buffer = null;\n\t //set the values initially\n\t this.size = options.size;\n\t this.type = options.type;\n\t this.returnType = options.returnType;\n\t this.minDecibels = options.minDecibels;\n\t this.maxDecibels = options.maxDecibels;\n\t };\n\t Tone.extend(Tone.Analyser);\n\t /**\n\t\t * The default values.\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.Analyser.defaults = {\n\t 'size': 1024,\n\t 'returnType': 'byte',\n\t 'type': 'fft',\n\t 'smoothing': 0.8,\n\t 'maxDecibels': -30,\n\t 'minDecibels': -100\n\t };\n\t /**\n\t\t * Possible return types of Tone.Analyser.analyse()\n\t\t * @enum {String}\n\t\t */\n\t Tone.Analyser.Type = {\n\t Waveform: 'waveform',\n\t FFT: 'fft'\n\t };\n\t /**\n\t\t * Possible return types of Tone.Analyser.analyse(). \n\t\t * byte values are between [0,255]. float values are between \n\t\t * [-1, 1] when the type is set to \"waveform\" and between \n\t\t * [minDecibels,maxDecibels] when the type is \"fft\".\n\t\t * @enum {String}\n\t\t */\n\t Tone.Analyser.ReturnType = {\n\t Byte: 'byte',\n\t Float: 'float'\n\t };\n\t /**\n\t\t * Run the analysis given the current settings and return the \n\t\t * result as a TypedArray. \n\t\t * @returns {TypedArray}\n\t\t */\n\t Tone.Analyser.prototype.analyse = function () {\n\t if (this._type === Tone.Analyser.Type.FFT) {\n\t if (this._returnType === Tone.Analyser.ReturnType.Byte) {\n\t this._analyser.getByteFrequencyData(this._buffer);\n\t } else {\n\t this._analyser.getFloatFrequencyData(this._buffer);\n\t }\n\t } else if (this._type === Tone.Analyser.Type.Waveform) {\n\t if (this._returnType === Tone.Analyser.ReturnType.Byte) {\n\t this._analyser.getByteTimeDomainData(this._buffer);\n\t } else {\n\t this._analyser.getFloatTimeDomainData(this._buffer);\n\t }\n\t }\n\t return this._buffer;\n\t };\n\t /**\n\t\t * The size of analysis. This must be a power of two in the range 32 to 32768.\n\t\t * @memberOf Tone.Analyser#\n\t\t * @type {Number}\n\t\t * @name size\n\t\t */\n\t Object.defineProperty(Tone.Analyser.prototype, 'size', {\n\t get: function () {\n\t return this._analyser.frequencyBinCount;\n\t },\n\t set: function (size) {\n\t this._analyser.fftSize = size * 2;\n\t this.type = this._type;\n\t }\n\t });\n\t /**\n\t\t * The return type of Tone.Analyser.analyse(), either \"byte\" or \"float\". \n\t\t * When the type is set to \"byte\" the range of values returned in the array\n\t\t * are between 0-255. \"float\" values are between \n\t\t * [-1, 1] when the type is set to \"waveform\" and between \n\t\t * [minDecibels,maxDecibels] when the type is \"fft\".\n\t\t * @memberOf Tone.Analyser#\n\t\t * @type {String}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.Analyser.prototype, 'returnType', {\n\t get: function () {\n\t return this._returnType;\n\t },\n\t set: function (type) {\n\t if (type === Tone.Analyser.ReturnType.Byte) {\n\t this._buffer = new Uint8Array(this._analyser.frequencyBinCount);\n\t } else if (type === Tone.Analyser.ReturnType.Float) {\n\t this._buffer = new Float32Array(this._analyser.frequencyBinCount);\n\t } else {\n\t throw new TypeError('Tone.Analayser: invalid return type: ' + type);\n\t }\n\t this._returnType = type;\n\t }\n\t });\n\t /**\n\t\t * The analysis function returned by Tone.Analyser.analyse(), either \"fft\" or \"waveform\". \n\t\t * @memberOf Tone.Analyser#\n\t\t * @type {String}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.Analyser.prototype, 'type', {\n\t get: function () {\n\t return this._type;\n\t },\n\t set: function (type) {\n\t if (type !== Tone.Analyser.Type.Waveform && type !== Tone.Analyser.Type.FFT) {\n\t throw new TypeError('Tone.Analyser: invalid type: ' + type);\n\t }\n\t this._type = type;\n\t }\n\t });\n\t /**\n\t\t * 0 represents no time averaging with the last analysis frame.\n\t\t * @memberOf Tone.Analyser#\n\t\t * @type {NormalRange}\n\t\t * @name smoothing\n\t\t */\n\t Object.defineProperty(Tone.Analyser.prototype, 'smoothing', {\n\t get: function () {\n\t return this._analyser.smoothingTimeConstant;\n\t },\n\t set: function (val) {\n\t this._analyser.smoothingTimeConstant = val;\n\t }\n\t });\n\t /**\n\t\t * The smallest decibel value which is analysed by the FFT. \n\t\t * @memberOf Tone.Analyser#\n\t\t * @type {Decibels}\n\t\t * @name minDecibels\n\t\t */\n\t Object.defineProperty(Tone.Analyser.prototype, 'minDecibels', {\n\t get: function () {\n\t return this._analyser.minDecibels;\n\t },\n\t set: function (val) {\n\t this._analyser.minDecibels = val;\n\t }\n\t });\n\t /**\n\t\t * The largest decibel value which is analysed by the FFT. \n\t\t * @memberOf Tone.Analyser#\n\t\t * @type {Decibels}\n\t\t * @name maxDecibels\n\t\t */\n\t Object.defineProperty(Tone.Analyser.prototype, 'maxDecibels', {\n\t get: function () {\n\t return this._analyser.maxDecibels;\n\t },\n\t set: function (val) {\n\t this._analyser.maxDecibels = val;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.Analyser} this\n\t\t */\n\t Tone.Analyser.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._analyser.disconnect();\n\t this._analyser = null;\n\t this._buffer = null;\n\t };\n\t return Tone.Analyser;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Compressor is a thin wrapper around the Web Audio \n\t\t * [DynamicsCompressorNode](http://webaudio.github.io/web-audio-api/#the-dynamicscompressornode-interface).\n\t\t * Compression reduces the volume of loud sounds or amplifies quiet sounds \n\t\t * by narrowing or \"compressing\" an audio signal's dynamic range. \n\t\t * Read more on [Wikipedia](https://en.wikipedia.org/wiki/Dynamic_range_compression).\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {Decibels|Object} [threshold] The value above which the compression starts to be applied.\n\t\t * @param {Positive} [ratio] The gain reduction ratio.\n\t\t * @example\n\t\t * var comp = new Tone.Compressor(-30, 3);\n\t\t */\n\t Tone.Compressor = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'threshold',\n\t 'ratio'\n\t ], Tone.Compressor.defaults);\n\t /**\n\t\t\t * the compressor node\n\t\t\t * @type {DynamicsCompressorNode}\n\t\t\t * @private\n\t\t\t */\n\t this._compressor = this.input = this.output = this.context.createDynamicsCompressor();\n\t /**\n\t\t\t * the threshold vaue\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.threshold = new Tone.Param({\n\t 'param': this._compressor.threshold,\n\t 'units': Tone.Type.Decibels,\n\t 'convert': false\n\t });\n\t /**\n\t\t\t * The attack parameter\n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.attack = new Tone.Param(this._compressor.attack, Tone.Type.Time);\n\t /**\n\t\t\t * The release parameter\n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.release = new Tone.Param(this._compressor.release, Tone.Type.Time);\n\t /**\n\t\t\t * The knee parameter\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.knee = new Tone.Param({\n\t 'param': this._compressor.knee,\n\t 'units': Tone.Type.Decibels,\n\t 'convert': false\n\t });\n\t /**\n\t\t\t * The ratio value\n\t\t\t * @type {Number}\n\t\t\t * @signal\n\t\t\t */\n\t this.ratio = new Tone.Param({\n\t 'param': this._compressor.ratio,\n\t 'convert': false\n\t });\n\t //set the defaults\n\t this._readOnly([\n\t 'knee',\n\t 'release',\n\t 'attack',\n\t 'ratio',\n\t 'threshold'\n\t ]);\n\t this.set(options);\n\t };\n\t Tone.extend(Tone.Compressor);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Compressor.defaults = {\n\t 'ratio': 12,\n\t 'threshold': -24,\n\t 'release': 0.25,\n\t 'attack': 0.003,\n\t 'knee': 30\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Compressor} this\n\t\t */\n\t Tone.Compressor.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'knee',\n\t 'release',\n\t 'attack',\n\t 'ratio',\n\t 'threshold'\n\t ]);\n\t this._compressor.disconnect();\n\t this._compressor = null;\n\t this.attack.dispose();\n\t this.attack = null;\n\t this.release.dispose();\n\t this.release = null;\n\t this.threshold.dispose();\n\t this.threshold = null;\n\t this.ratio.dispose();\n\t this.ratio = null;\n\t this.knee.dispose();\n\t this.knee = null;\n\t return this;\n\t };\n\t return Tone.Compressor;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Add a signal and a number or two signals. When no value is\n\t\t * passed into the constructor, Tone.Add will sum <code>input[0]</code>\n\t\t * and <code>input[1]</code>. If a value is passed into the constructor, \n\t\t * the it will be added to the input.\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Signal}\n\t\t * @param {number=} value If no value is provided, Tone.Add will sum the first\n\t\t * and second inputs. \n\t\t * @example\n\t\t * var signal = new Tone.Signal(2);\n\t\t * var add = new Tone.Add(2);\n\t\t * signal.connect(add);\n\t\t * //the output of add equals 4\n\t\t * @example\n\t\t * //if constructed with no arguments\n\t\t * //it will add the first and second inputs\n\t\t * var add = new Tone.Add();\n\t\t * var sig0 = new Tone.Signal(3).connect(add, 0, 0);\n\t\t * var sig1 = new Tone.Signal(4).connect(add, 0, 1);\n\t\t * //the output of add equals 7. \n\t\t */\n\t Tone.Add = function (value) {\n\t this.createInsOuts(2, 0);\n\t /**\n\t\t\t * the summing node\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();\n\t /**\n\t\t\t * @private\n\t\t\t * @type {Tone.Signal}\n\t\t\t */\n\t this._param = this.input[1] = new Tone.Signal(value);\n\t this._param.connect(this._sum);\n\t };\n\t Tone.extend(Tone.Add, Tone.Signal);\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Add} this\n\t\t */\n\t Tone.Add.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._sum.dispose();\n\t this._sum = null;\n\t this._param.dispose();\n\t this._param = null;\n\t return this;\n\t };\n\t return Tone.Add;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Multiply two incoming signals. Or, if a number is given in the constructor, \n\t\t * multiplies the incoming signal by that value. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Signal}\n\t\t * @param {number=} value Constant value to multiple. If no value is provided,\n\t\t * it will return the product of the first and second inputs\n\t\t * @example\n\t\t * var mult = new Tone.Multiply();\n\t\t * var sigA = new Tone.Signal(3);\n\t\t * var sigB = new Tone.Signal(4);\n\t\t * sigA.connect(mult, 0, 0);\n\t\t * sigB.connect(mult, 0, 1);\n\t\t * //output of mult is 12.\n\t\t * @example\n\t\t * var mult = new Tone.Multiply(10);\n\t\t * var sig = new Tone.Signal(2).connect(mult);\n\t\t * //the output of mult is 20. \n\t\t */\n\t Tone.Multiply = function (value) {\n\t this.createInsOuts(2, 0);\n\t /**\n\t\t\t * the input node is the same as the output node\n\t\t\t * it is also the GainNode which handles the scaling of incoming signal\n\t\t\t * \n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this._mult = this.input[0] = this.output = new Tone.Gain();\n\t /**\n\t\t\t * the scaling parameter\n\t\t\t * @type {AudioParam}\n\t\t\t * @private\n\t\t\t */\n\t this._param = this.input[1] = this.output.gain;\n\t this._param.value = this.defaultArg(value, 0);\n\t };\n\t Tone.extend(Tone.Multiply, Tone.Signal);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Multiply} this\n\t\t */\n\t Tone.Multiply.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._mult.dispose();\n\t this._mult = null;\n\t this._param = null;\n\t return this;\n\t };\n\t return Tone.Multiply;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Negate the incoming signal. i.e. an input signal of 10 will output -10\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.SignalBase}\n\t\t * @example\n\t\t * var neg = new Tone.Negate();\n\t\t * var sig = new Tone.Signal(-2).connect(neg);\n\t\t * //output of neg is positive 2. \n\t\t */\n\t Tone.Negate = function () {\n\t /**\n\t\t\t * negation is done by multiplying by -1\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._multiply = this.input = this.output = new Tone.Multiply(-1);\n\t };\n\t Tone.extend(Tone.Negate, Tone.SignalBase);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Negate} this\n\t\t */\n\t Tone.Negate.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._multiply.dispose();\n\t this._multiply = null;\n\t return this;\n\t };\n\t return Tone.Negate;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Subtract the signal connected to <code>input[1]</code> from the signal connected \n\t\t * to <code>input[0]</code>. If an argument is provided in the constructor, the \n\t\t * signals <code>.value</code> will be subtracted from the incoming signal.\n\t\t *\n\t\t * @extends {Tone.Signal}\n\t\t * @constructor\n\t\t * @param {number=} value The value to subtract from the incoming signal. If the value\n\t\t * is omitted, it will subtract the second signal from the first.\n\t\t * @example\n\t\t * var sub = new Tone.Subtract(1);\n\t\t * var sig = new Tone.Signal(4).connect(sub);\n\t\t * //the output of sub is 3. \n\t\t * @example\n\t\t * var sub = new Tone.Subtract();\n\t\t * var sigA = new Tone.Signal(10);\n\t\t * var sigB = new Tone.Signal(2.5);\n\t\t * sigA.connect(sub, 0, 0);\n\t\t * sigB.connect(sub, 0, 1);\n\t\t * //output of sub is 7.5\n\t\t */\n\t Tone.Subtract = function (value) {\n\t this.createInsOuts(2, 0);\n\t /**\n\t\t\t * the summing node\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this._sum = this.input[0] = this.output = new Tone.Gain();\n\t /**\n\t\t\t * negate the input of the second input before connecting it\n\t\t\t * to the summing node.\n\t\t\t * @type {Tone.Negate}\n\t\t\t * @private\n\t\t\t */\n\t this._neg = new Tone.Negate();\n\t /**\n\t\t\t * the node where the value is set\n\t\t\t * @private\n\t\t\t * @type {Tone.Signal}\n\t\t\t */\n\t this._param = this.input[1] = new Tone.Signal(value);\n\t this._param.chain(this._neg, this._sum);\n\t };\n\t Tone.extend(Tone.Subtract, Tone.Signal);\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.SignalBase} this\n\t\t */\n\t Tone.Subtract.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._neg.dispose();\n\t this._neg = null;\n\t this._sum.disconnect();\n\t this._sum = null;\n\t this._param.dispose();\n\t this._param = null;\n\t return this;\n\t };\n\t return Tone.Subtract;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class GreaterThanZero outputs 1 when the input is strictly greater than zero\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.SignalBase}\n\t\t * @example\n\t\t * var gt0 = new Tone.GreaterThanZero();\n\t\t * var sig = new Tone.Signal(0.01).connect(gt0);\n\t\t * //the output of gt0 is 1. \n\t\t * sig.value = 0;\n\t\t * //the output of gt0 is 0. \n\t\t */\n\t Tone.GreaterThanZero = function () {\n\t /**\n\t\t\t * @type {Tone.WaveShaper}\n\t\t\t * @private\n\t\t\t */\n\t this._thresh = this.output = new Tone.WaveShaper(function (val) {\n\t if (val <= 0) {\n\t return 0;\n\t } else {\n\t return 1;\n\t }\n\t }, 127);\n\t /**\n\t\t\t * scale the first thresholded signal by a large value.\n\t\t\t * this will help with values which are very close to 0\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._scale = this.input = new Tone.Multiply(10000);\n\t //connections\n\t this._scale.connect(this._thresh);\n\t };\n\t Tone.extend(Tone.GreaterThanZero, Tone.SignalBase);\n\t /**\n\t\t * dispose method\n\t\t * @returns {Tone.GreaterThanZero} this\n\t\t */\n\t Tone.GreaterThanZero.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._scale.dispose();\n\t this._scale = null;\n\t this._thresh.dispose();\n\t this._thresh = null;\n\t return this;\n\t };\n\t return Tone.GreaterThanZero;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Output 1 if the signal is greater than the value, otherwise outputs 0.\n\t\t * can compare two signals or a signal and a number. \n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Signal}\n\t\t * @param {number} [value=0] the value to compare to the incoming signal\n\t\t * @example\n\t\t * var gt = new Tone.GreaterThan(2);\n\t\t * var sig = new Tone.Signal(4).connect(gt);\n\t\t * //output of gt is equal 1. \n\t\t */\n\t Tone.GreaterThan = function (value) {\n\t this.createInsOuts(2, 0);\n\t /**\n\t\t\t * subtract the amount from the incoming signal\n\t\t\t * @type {Tone.Subtract}\n\t\t\t * @private\n\t\t\t */\n\t this._param = this.input[0] = new Tone.Subtract(value);\n\t this.input[1] = this._param.input[1];\n\t /**\n\t\t\t * compare that amount to zero\n\t\t\t * @type {Tone.GreaterThanZero}\n\t\t\t * @private\n\t\t\t */\n\t this._gtz = this.output = new Tone.GreaterThanZero();\n\t //connect\n\t this._param.connect(this._gtz);\n\t };\n\t Tone.extend(Tone.GreaterThan, Tone.Signal);\n\t /**\n\t\t * dispose method\n\t\t * @returns {Tone.GreaterThan} this\n\t\t */\n\t Tone.GreaterThan.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._param.dispose();\n\t this._param = null;\n\t this._gtz.dispose();\n\t this._gtz = null;\n\t return this;\n\t };\n\t return Tone.GreaterThan;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Return the absolute value of an incoming signal. \n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.SignalBase}\n\t\t * @example\n\t\t * var signal = new Tone.Signal(-1);\n\t\t * var abs = new Tone.Abs();\n\t\t * signal.connect(abs);\n\t\t * //the output of abs is 1. \n\t\t */\n\t Tone.Abs = function () {\n\t /**\n\t\t\t * @type {Tone.LessThan}\n\t\t\t * @private\n\t\t\t */\n\t this._abs = this.input = this.output = new Tone.WaveShaper(function (val) {\n\t if (val === 0) {\n\t return 0;\n\t } else {\n\t return Math.abs(val);\n\t }\n\t }, 127);\n\t };\n\t Tone.extend(Tone.Abs, Tone.SignalBase);\n\t /**\n\t\t * dispose method\n\t\t * @returns {Tone.Abs} this\n\t\t */\n\t Tone.Abs.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._abs.dispose();\n\t this._abs = null;\n\t return this;\n\t };\n\t return Tone.Abs;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Signal-rate modulo operator. Only works in AudioRange [-1, 1] and for modulus\n\t\t * values in the NormalRange. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.SignalBase}\n\t\t * @param {NormalRange} modulus The modulus to apply.\n\t\t * @example\n\t\t * var mod = new Tone.Modulo(0.2)\n\t\t * var sig = new Tone.Signal(0.5).connect(mod);\n\t\t * //mod outputs 0.1\n\t\t */\n\t Tone.Modulo = function (modulus) {\n\t this.createInsOuts(1, 0);\n\t /**\n\t\t\t * A waveshaper gets the integer multiple of \n\t\t\t * the input signal and the modulus.\n\t\t\t * @private\n\t\t\t * @type {Tone.WaveShaper}\n\t\t\t */\n\t this._shaper = new Tone.WaveShaper(Math.pow(2, 16));\n\t /**\n\t\t\t * the integer multiple is multiplied by the modulus\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._multiply = new Tone.Multiply();\n\t /**\n\t\t\t * and subtracted from the input signal\n\t\t\t * @type {Tone.Subtract}\n\t\t\t * @private\n\t\t\t */\n\t this._subtract = this.output = new Tone.Subtract();\n\t /**\n\t\t\t * the modulus signal\n\t\t\t * @type {Tone.Signal}\n\t\t\t * @private\n\t\t\t */\n\t this._modSignal = new Tone.Signal(modulus);\n\t //connections\n\t this.input.fan(this._shaper, this._subtract);\n\t this._modSignal.connect(this._multiply, 0, 0);\n\t this._shaper.connect(this._multiply, 0, 1);\n\t this._multiply.connect(this._subtract, 0, 1);\n\t this._setWaveShaper(modulus);\n\t };\n\t Tone.extend(Tone.Modulo, Tone.SignalBase);\n\t /**\n\t\t * @param {number} mod the modulus to apply\n\t\t * @private\n\t\t */\n\t Tone.Modulo.prototype._setWaveShaper = function (mod) {\n\t this._shaper.setMap(function (val) {\n\t var multiple = Math.floor((val + 0.0001) / mod);\n\t return multiple;\n\t });\n\t };\n\t /**\n\t\t * The modulus value.\n\t\t * @memberOf Tone.Modulo#\n\t\t * @type {NormalRange}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.Modulo.prototype, 'value', {\n\t get: function () {\n\t return this._modSignal.value;\n\t },\n\t set: function (mod) {\n\t this._modSignal.value = mod;\n\t this._setWaveShaper(mod);\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Modulo} this\n\t\t */\n\t Tone.Modulo.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._shaper.dispose();\n\t this._shaper = null;\n\t this._multiply.dispose();\n\t this._multiply = null;\n\t this._subtract.dispose();\n\t this._subtract = null;\n\t this._modSignal.dispose();\n\t this._modSignal = null;\n\t return this;\n\t };\n\t return Tone.Modulo;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class AudioToGain converts an input in AudioRange [-1,1] to NormalRange [0,1]. \n\t\t * See Tone.GainToAudio.\n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @example\n\t\t * var a2g = new Tone.AudioToGain();\n\t\t */\n\t Tone.AudioToGain = function () {\n\t /**\n\t\t\t * @type {WaveShaperNode}\n\t\t\t * @private\n\t\t\t */\n\t this._norm = this.input = this.output = new Tone.WaveShaper(function (x) {\n\t return (x + 1) / 2;\n\t });\n\t };\n\t Tone.extend(Tone.AudioToGain, Tone.SignalBase);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.AudioToGain} this\n\t\t */\n\t Tone.AudioToGain.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._norm.dispose();\n\t this._norm = null;\n\t return this;\n\t };\n\t return Tone.AudioToGain;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Evaluate an expression at audio rate. <br><br>\n\t\t * Parsing code modified from https://code.google.com/p/tapdigit/\n\t\t * Copyright 2011 2012 Ariya Hidayat, New BSD License\n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @param {string} expr the expression to generate\n\t\t * @example\n\t\t * //adds the signals from input[0] and input[1].\n\t\t * var expr = new Tone.Expr(\"$0 + $1\");\n\t\t */\n\t Tone.Expr = function () {\n\t var expr = this._replacements(Array.prototype.slice.call(arguments));\n\t var inputCount = this._parseInputs(expr);\n\t /**\n\t\t\t * hold onto all of the nodes for disposal\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._nodes = [];\n\t /**\n\t\t\t * The inputs. The length is determined by the expression. \n\t\t\t * @type {Array}\n\t\t\t */\n\t this.input = new Array(inputCount);\n\t //create a gain for each input\n\t for (var i = 0; i < inputCount; i++) {\n\t this.input[i] = this.context.createGain();\n\t }\n\t //parse the syntax tree\n\t var tree = this._parseTree(expr);\n\t //evaluate the results\n\t var result;\n\t try {\n\t result = this._eval(tree);\n\t } catch (e) {\n\t this._disposeNodes();\n\t throw new Error('Tone.Expr: Could evaluate expression: ' + expr);\n\t }\n\t /**\n\t\t\t * The output node is the result of the expression\n\t\t\t * @type {Tone}\n\t\t\t */\n\t this.output = result;\n\t };\n\t Tone.extend(Tone.Expr, Tone.SignalBase);\n\t //some helpers to cut down the amount of code\n\t function applyBinary(Constructor, args, self) {\n\t var op = new Constructor();\n\t self._eval(args[0]).connect(op, 0, 0);\n\t self._eval(args[1]).connect(op, 0, 1);\n\t return op;\n\t }\n\t function applyUnary(Constructor, args, self) {\n\t var op = new Constructor();\n\t self._eval(args[0]).connect(op, 0, 0);\n\t return op;\n\t }\n\t function getNumber(arg) {\n\t return arg ? parseFloat(arg) : undefined;\n\t }\n\t function literalNumber(arg) {\n\t return arg && arg.args ? parseFloat(arg.args) : undefined;\n\t }\n\t /*\n\t\t * the Expressions that Tone.Expr can parse.\n\t\t *\n\t\t * each expression belongs to a group and contains a regexp \n\t\t * for selecting the operator as well as that operators method\n\t\t * \n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t Tone.Expr._Expressions = {\n\t //values\n\t 'value': {\n\t 'signal': {\n\t regexp: /^\\d+\\.\\d+|^\\d+/,\n\t method: function (arg) {\n\t var sig = new Tone.Signal(getNumber(arg));\n\t return sig;\n\t }\n\t },\n\t 'input': {\n\t regexp: /^\\$\\d/,\n\t method: function (arg, self) {\n\t return self.input[getNumber(arg.substr(1))];\n\t }\n\t }\n\t },\n\t //syntactic glue\n\t 'glue': {\n\t '(': { regexp: /^\\(/ },\n\t ')': { regexp: /^\\)/ },\n\t ',': { regexp: /^,/ }\n\t },\n\t //functions\n\t 'func': {\n\t 'abs': {\n\t regexp: /^abs/,\n\t method: applyUnary.bind(this, Tone.Abs)\n\t },\n\t 'mod': {\n\t regexp: /^mod/,\n\t method: function (args, self) {\n\t var modulus = literalNumber(args[1]);\n\t var op = new Tone.Modulo(modulus);\n\t self._eval(args[0]).connect(op);\n\t return op;\n\t }\n\t },\n\t 'pow': {\n\t regexp: /^pow/,\n\t method: function (args, self) {\n\t var exp = literalNumber(args[1]);\n\t var op = new Tone.Pow(exp);\n\t self._eval(args[0]).connect(op);\n\t return op;\n\t }\n\t },\n\t 'a2g': {\n\t regexp: /^a2g/,\n\t method: function (args, self) {\n\t var op = new Tone.AudioToGain();\n\t self._eval(args[0]).connect(op);\n\t return op;\n\t }\n\t }\n\t },\n\t //binary expressions\n\t 'binary': {\n\t '+': {\n\t regexp: /^\\+/,\n\t precedence: 1,\n\t method: applyBinary.bind(this, Tone.Add)\n\t },\n\t '-': {\n\t regexp: /^\\-/,\n\t precedence: 1,\n\t method: function (args, self) {\n\t //both unary and binary op\n\t if (args.length === 1) {\n\t return applyUnary(Tone.Negate, args, self);\n\t } else {\n\t return applyBinary(Tone.Subtract, args, self);\n\t }\n\t }\n\t },\n\t '*': {\n\t regexp: /^\\*/,\n\t precedence: 0,\n\t method: applyBinary.bind(this, Tone.Multiply)\n\t }\n\t },\n\t //unary expressions\n\t 'unary': {\n\t '-': {\n\t regexp: /^\\-/,\n\t method: applyUnary.bind(this, Tone.Negate)\n\t },\n\t '!': {\n\t regexp: /^\\!/,\n\t method: applyUnary.bind(this, Tone.NOT)\n\t }\n\t }\n\t };\n\t /**\n\t\t * @param {string} expr the expression string\n\t\t * @return {number} the input count\n\t\t * @private\n\t\t */\n\t Tone.Expr.prototype._parseInputs = function (expr) {\n\t var inputArray = expr.match(/\\$\\d/g);\n\t var inputMax = 0;\n\t if (inputArray !== null) {\n\t for (var i = 0; i < inputArray.length; i++) {\n\t var inputNum = parseInt(inputArray[i].substr(1)) + 1;\n\t inputMax = Math.max(inputMax, inputNum);\n\t }\n\t }\n\t return inputMax;\n\t };\n\t /**\n\t\t * @param {Array} args \tan array of arguments\n\t\t * @return {string} the results of the replacements being replaced\n\t\t * @private\n\t\t */\n\t Tone.Expr.prototype._replacements = function (args) {\n\t var expr = args.shift();\n\t for (var i = 0; i < args.length; i++) {\n\t expr = expr.replace(/\\%/i, args[i]);\n\t }\n\t return expr;\n\t };\n\t /**\n\t\t * tokenize the expression based on the Expressions object\n\t\t * @param {string} expr \n\t\t * @return {Object} returns two methods on the tokenized list, next and peek\n\t\t * @private\n\t\t */\n\t Tone.Expr.prototype._tokenize = function (expr) {\n\t var position = -1;\n\t var tokens = [];\n\t while (expr.length > 0) {\n\t expr = expr.trim();\n\t var token = getNextToken(expr);\n\t tokens.push(token);\n\t expr = expr.substr(token.value.length);\n\t }\n\t function getNextToken(expr) {\n\t for (var type in Tone.Expr._Expressions) {\n\t var group = Tone.Expr._Expressions[type];\n\t for (var opName in group) {\n\t var op = group[opName];\n\t var reg = op.regexp;\n\t var match = expr.match(reg);\n\t if (match !== null) {\n\t return {\n\t type: type,\n\t value: match[0],\n\t method: op.method\n\t };\n\t }\n\t }\n\t }\n\t throw new SyntaxError('Tone.Expr: Unexpected token ' + expr);\n\t }\n\t return {\n\t next: function () {\n\t return tokens[++position];\n\t },\n\t peek: function () {\n\t return tokens[position + 1];\n\t }\n\t };\n\t };\n\t /**\n\t\t * recursively parse the string expression into a syntax tree\n\t\t * \n\t\t * @param {string} expr \n\t\t * @return {Object}\n\t\t * @private\n\t\t */\n\t Tone.Expr.prototype._parseTree = function (expr) {\n\t var lexer = this._tokenize(expr);\n\t var isUndef = this.isUndef.bind(this);\n\t function matchSyntax(token, syn) {\n\t return !isUndef(token) && token.type === 'glue' && token.value === syn;\n\t }\n\t function matchGroup(token, groupName, prec) {\n\t var ret = false;\n\t var group = Tone.Expr._Expressions[groupName];\n\t if (!isUndef(token)) {\n\t for (var opName in group) {\n\t var op = group[opName];\n\t if (op.regexp.test(token.value)) {\n\t if (!isUndef(prec)) {\n\t if (op.precedence === prec) {\n\t return true;\n\t }\n\t } else {\n\t return true;\n\t }\n\t }\n\t }\n\t }\n\t return ret;\n\t }\n\t function parseExpression(precedence) {\n\t if (isUndef(precedence)) {\n\t precedence = 5;\n\t }\n\t var expr;\n\t if (precedence < 0) {\n\t expr = parseUnary();\n\t } else {\n\t expr = parseExpression(precedence - 1);\n\t }\n\t var token = lexer.peek();\n\t while (matchGroup(token, 'binary', precedence)) {\n\t token = lexer.next();\n\t expr = {\n\t operator: token.value,\n\t method: token.method,\n\t args: [\n\t expr,\n\t parseExpression(precedence - 1)\n\t ]\n\t };\n\t token = lexer.peek();\n\t }\n\t return expr;\n\t }\n\t function parseUnary() {\n\t var token, expr;\n\t token = lexer.peek();\n\t if (matchGroup(token, 'unary')) {\n\t token = lexer.next();\n\t expr = parseUnary();\n\t return {\n\t operator: token.value,\n\t method: token.method,\n\t args: [expr]\n\t };\n\t }\n\t return parsePrimary();\n\t }\n\t function parsePrimary() {\n\t var token, expr;\n\t token = lexer.peek();\n\t if (isUndef(token)) {\n\t throw new SyntaxError('Tone.Expr: Unexpected termination of expression');\n\t }\n\t if (token.type === 'func') {\n\t token = lexer.next();\n\t return parseFunctionCall(token);\n\t }\n\t if (token.type === 'value') {\n\t token = lexer.next();\n\t return {\n\t method: token.method,\n\t args: token.value\n\t };\n\t }\n\t if (matchSyntax(token, '(')) {\n\t lexer.next();\n\t expr = parseExpression();\n\t token = lexer.next();\n\t if (!matchSyntax(token, ')')) {\n\t throw new SyntaxError('Expected )');\n\t }\n\t return expr;\n\t }\n\t throw new SyntaxError('Tone.Expr: Parse error, cannot process token ' + token.value);\n\t }\n\t function parseFunctionCall(func) {\n\t var token, args = [];\n\t token = lexer.next();\n\t if (!matchSyntax(token, '(')) {\n\t throw new SyntaxError('Tone.Expr: Expected ( in a function call \"' + func.value + '\"');\n\t }\n\t token = lexer.peek();\n\t if (!matchSyntax(token, ')')) {\n\t args = parseArgumentList();\n\t }\n\t token = lexer.next();\n\t if (!matchSyntax(token, ')')) {\n\t throw new SyntaxError('Tone.Expr: Expected ) in a function call \"' + func.value + '\"');\n\t }\n\t return {\n\t method: func.method,\n\t args: args,\n\t name: name\n\t };\n\t }\n\t function parseArgumentList() {\n\t var token, expr, args = [];\n\t while (true) {\n\t expr = parseExpression();\n\t if (isUndef(expr)) {\n\t // TODO maybe throw exception?\n\t break;\n\t }\n\t args.push(expr);\n\t token = lexer.peek();\n\t if (!matchSyntax(token, ',')) {\n\t break;\n\t }\n\t lexer.next();\n\t }\n\t return args;\n\t }\n\t return parseExpression();\n\t };\n\t /**\n\t\t * recursively evaluate the expression tree\n\t\t * @param {Object} tree \n\t\t * @return {AudioNode} the resulting audio node from the expression\n\t\t * @private\n\t\t */\n\t Tone.Expr.prototype._eval = function (tree) {\n\t if (!this.isUndef(tree)) {\n\t var node = tree.method(tree.args, this);\n\t this._nodes.push(node);\n\t return node;\n\t }\n\t };\n\t /**\n\t\t * dispose all the nodes\n\t\t * @private\n\t\t */\n\t Tone.Expr.prototype._disposeNodes = function () {\n\t for (var i = 0; i < this._nodes.length; i++) {\n\t var node = this._nodes[i];\n\t if (this.isFunction(node.dispose)) {\n\t node.dispose();\n\t } else if (this.isFunction(node.disconnect)) {\n\t node.disconnect();\n\t }\n\t node = null;\n\t this._nodes[i] = null;\n\t }\n\t this._nodes = null;\n\t };\n\t /**\n\t\t * clean up\n\t\t */\n\t Tone.Expr.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._disposeNodes();\n\t };\n\t return Tone.Expr;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Convert an incoming signal between 0, 1 to an equal power gain scale.\n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @example\n\t\t * var eqPowGain = new Tone.EqualPowerGain();\n\t\t */\n\t Tone.EqualPowerGain = function () {\n\t /**\n\t\t\t * @type {Tone.WaveShaper}\n\t\t\t * @private\n\t\t\t */\n\t this._eqPower = this.input = this.output = new Tone.WaveShaper(function (val) {\n\t if (Math.abs(val) < 0.001) {\n\t //should output 0 when input is 0\n\t return 0;\n\t } else {\n\t return this.equalPowerScale(val);\n\t }\n\t }.bind(this), 4096);\n\t };\n\t Tone.extend(Tone.EqualPowerGain, Tone.SignalBase);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.EqualPowerGain} this\n\t\t */\n\t Tone.EqualPowerGain.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._eqPower.dispose();\n\t this._eqPower = null;\n\t return this;\n\t };\n\t return Tone.EqualPowerGain;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Crossfade provides equal power fading between two inputs. \n\t\t * More on crossfading technique [here](https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Crossfading).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {NormalRange} [initialFade=0.5]\n\t\t * @example\n\t\t * var crossFade = new Tone.CrossFade(0.5);\n\t\t * //connect effect A to crossfade from\n\t\t * //effect output 0 to crossfade input 0\n\t\t * effectA.connect(crossFade, 0, 0);\n\t\t * //connect effect B to crossfade from\n\t\t * //effect output 0 to crossfade input 1\n\t\t * effectB.connect(crossFade, 0, 1);\n\t\t * crossFade.fade.value = 0;\n\t\t * // ^ only effectA is output\n\t\t * crossFade.fade.value = 1;\n\t\t * // ^ only effectB is output\n\t\t * crossFade.fade.value = 0.5;\n\t\t * // ^ the two signals are mixed equally. \n\t\t */\n\t Tone.CrossFade = function (initialFade) {\n\t this.createInsOuts(2, 1);\n\t /**\n\t\t\t * Alias for <code>input[0]</code>. \n\t\t\t * @type {Tone.Gain}\n\t\t\t */\n\t this.a = this.input[0] = new Tone.Gain();\n\t /**\n\t\t\t * Alias for <code>input[1]</code>. \n\t\t\t * @type {Tone.Gain}\n\t\t\t */\n\t this.b = this.input[1] = new Tone.Gain();\n\t /**\n\t\t\t * \tThe mix between the two inputs. A fade value of 0\n\t\t\t * \twill output 100% <code>input[0]</code> and \n\t\t\t * \ta value of 1 will output 100% <code>input[1]</code>. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);\n\t /**\n\t\t\t * equal power gain cross fade\n\t\t\t * @private\n\t\t\t * @type {Tone.EqualPowerGain}\n\t\t\t */\n\t this._equalPowerA = new Tone.EqualPowerGain();\n\t /**\n\t\t\t * equal power gain cross fade\n\t\t\t * @private\n\t\t\t * @type {Tone.EqualPowerGain}\n\t\t\t */\n\t this._equalPowerB = new Tone.EqualPowerGain();\n\t /**\n\t\t\t * invert the incoming signal\n\t\t\t * @private\n\t\t\t * @type {Tone}\n\t\t\t */\n\t this._invert = new Tone.Expr('1 - $0');\n\t //connections\n\t this.a.connect(this.output);\n\t this.b.connect(this.output);\n\t this.fade.chain(this._equalPowerB, this.b.gain);\n\t this.fade.chain(this._invert, this._equalPowerA, this.a.gain);\n\t this._readOnly('fade');\n\t };\n\t Tone.extend(Tone.CrossFade);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.CrossFade} this\n\t\t */\n\t Tone.CrossFade.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable('fade');\n\t this._equalPowerA.dispose();\n\t this._equalPowerA = null;\n\t this._equalPowerB.dispose();\n\t this._equalPowerB = null;\n\t this.fade.dispose();\n\t this.fade = null;\n\t this._invert.dispose();\n\t this._invert = null;\n\t this.a.dispose();\n\t this.a = null;\n\t this.b.dispose();\n\t this.b = null;\n\t return this;\n\t };\n\t return Tone.CrossFade;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Filter is a filter which allows for all of the same native methods\n\t\t * as the [BiquadFilterNode](http://webaudio.github.io/web-audio-api/#the-biquadfilternode-interface). \n\t\t * Tone.Filter has the added ability to set the filter rolloff at -12 \n\t\t * (default), -24 and -48. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {Frequency|Object} [frequency] The cutoff frequency of the filter.\n\t\t * @param {string=} type The type of filter.\n\t\t * @param {number=} rolloff The drop in decibels per octave after the cutoff frequency.\n\t\t * 3 choices: -12, -24, and -48\n\t\t * @example\n\t\t * var filter = new Tone.Filter(200, \"highpass\");\n\t\t */\n\t Tone.Filter = function () {\n\t this.createInsOuts(1, 1);\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'type',\n\t 'rolloff'\n\t ], Tone.Filter.defaults);\n\t /**\n\t\t\t * the filter(s)\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._filters = [];\n\t /**\n\t\t\t * The cutoff frequency of the filter. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune parameter\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(0, Tone.Type.Cents);\n\t /**\n\t\t\t * The gain of the filter, only used in certain filter types\n\t\t\t * @type {Number}\n\t\t\t * @signal\n\t\t\t */\n\t this.gain = new Tone.Signal({\n\t 'value': options.gain,\n\t 'convert': false\n\t });\n\t /**\n\t\t\t * The Q or Quality of the filter\n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this.Q = new Tone.Signal(options.Q);\n\t /**\n\t\t\t * the type of the filter\n\t\t\t * @type {string}\n\t\t\t * @private\n\t\t\t */\n\t this._type = options.type;\n\t /**\n\t\t\t * the rolloff value of the filter\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._rolloff = options.rolloff;\n\t //set the rolloff;\n\t this.rolloff = options.rolloff;\n\t this._readOnly([\n\t 'detune',\n\t 'frequency',\n\t 'gain',\n\t 'Q'\n\t ]);\n\t };\n\t Tone.extend(Tone.Filter);\n\t /**\n\t\t * the default parameters\n\t\t *\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Filter.defaults = {\n\t 'type': 'lowpass',\n\t 'frequency': 350,\n\t 'rolloff': -12,\n\t 'Q': 1,\n\t 'gain': 0\n\t };\n\t /**\n\t\t * The type of the filter. Types: \"lowpass\", \"highpass\", \n\t\t * \"bandpass\", \"lowshelf\", \"highshelf\", \"notch\", \"allpass\", or \"peaking\". \n\t\t * @memberOf Tone.Filter#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.Filter.prototype, 'type', {\n\t get: function () {\n\t return this._type;\n\t },\n\t set: function (type) {\n\t var types = [\n\t 'lowpass',\n\t 'highpass',\n\t 'bandpass',\n\t 'lowshelf',\n\t 'highshelf',\n\t 'notch',\n\t 'allpass',\n\t 'peaking'\n\t ];\n\t if (types.indexOf(type) === -1) {\n\t throw new TypeError('Tone.Filter: invalid type ' + type);\n\t }\n\t this._type = type;\n\t for (var i = 0; i < this._filters.length; i++) {\n\t this._filters[i].type = type;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The rolloff of the filter which is the drop in db\n\t\t * per octave. Implemented internally by cascading filters.\n\t\t * Only accepts the values -12, -24, -48 and -96.\n\t\t * @memberOf Tone.Filter#\n\t\t * @type {number}\n\t\t * @name rolloff\n\t\t */\n\t Object.defineProperty(Tone.Filter.prototype, 'rolloff', {\n\t get: function () {\n\t return this._rolloff;\n\t },\n\t set: function (rolloff) {\n\t rolloff = parseInt(rolloff, 10);\n\t var possibilities = [\n\t -12,\n\t -24,\n\t -48,\n\t -96\n\t ];\n\t var cascadingCount = possibilities.indexOf(rolloff);\n\t //check the rolloff is valid\n\t if (cascadingCount === -1) {\n\t throw new RangeError('Tone.Filter: rolloff can only be -12, -24, -48 or -96');\n\t }\n\t cascadingCount += 1;\n\t this._rolloff = rolloff;\n\t //first disconnect the filters and throw them away\n\t this.input.disconnect();\n\t for (var i = 0; i < this._filters.length; i++) {\n\t this._filters[i].disconnect();\n\t this._filters[i] = null;\n\t }\n\t this._filters = new Array(cascadingCount);\n\t for (var count = 0; count < cascadingCount; count++) {\n\t var filter = this.context.createBiquadFilter();\n\t filter.type = this._type;\n\t this.frequency.connect(filter.frequency);\n\t this.detune.connect(filter.detune);\n\t this.Q.connect(filter.Q);\n\t this.gain.connect(filter.gain);\n\t this._filters[count] = filter;\n\t }\n\t //connect them up\n\t var connectionChain = [this.input].concat(this._filters).concat([this.output]);\n\t this.connectSeries.apply(this, connectionChain);\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @return {Tone.Filter} this\n\t\t */\n\t Tone.Filter.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t for (var i = 0; i < this._filters.length; i++) {\n\t this._filters[i].disconnect();\n\t this._filters[i] = null;\n\t }\n\t this._filters = null;\n\t this._writable([\n\t 'detune',\n\t 'frequency',\n\t 'gain',\n\t 'Q'\n\t ]);\n\t this.frequency.dispose();\n\t this.Q.dispose();\n\t this.frequency = null;\n\t this.Q = null;\n\t this.detune.dispose();\n\t this.detune = null;\n\t this.gain.dispose();\n\t this.gain = null;\n\t return this;\n\t };\n\t return Tone.Filter;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Split the incoming signal into three bands (low, mid, high)\n\t\t * with two crossover frequency controls. \n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {Frequency|Object} [lowFrequency] the low/mid crossover frequency\n\t\t * @param {Frequency} [highFrequency] the mid/high crossover frequency\n\t\t */\n\t Tone.MultibandSplit = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'lowFrequency',\n\t 'highFrequency'\n\t ], Tone.MultibandSplit.defaults);\n\t /**\n\t\t\t * the input\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this.input = new Tone.Gain();\n\t /**\n\t\t\t * the outputs\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this.output = new Array(3);\n\t /**\n\t\t\t * The low band. Alias for <code>output[0]</code>\n\t\t\t * @type {Tone.Filter}\n\t\t\t */\n\t this.low = this.output[0] = new Tone.Filter(0, 'lowpass');\n\t /**\n\t\t\t * the lower filter of the mid band\n\t\t\t * @type {Tone.Filter}\n\t\t\t * @private\n\t\t\t */\n\t this._lowMidFilter = new Tone.Filter(0, 'highpass');\n\t /**\n\t\t\t * The mid band output. Alias for <code>output[1]</code>\n\t\t\t * @type {Tone.Filter}\n\t\t\t */\n\t this.mid = this.output[1] = new Tone.Filter(0, 'lowpass');\n\t /**\n\t\t\t * The high band output. Alias for <code>output[2]</code>\n\t\t\t * @type {Tone.Filter}\n\t\t\t */\n\t this.high = this.output[2] = new Tone.Filter(0, 'highpass');\n\t /**\n\t\t\t * The low/mid crossover frequency.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.lowFrequency = new Tone.Signal(options.lowFrequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The mid/high crossover frequency.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.highFrequency = new Tone.Signal(options.highFrequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The quality of all the filters\n\t\t\t * @type {Number}\n\t\t\t * @signal\n\t\t\t */\n\t this.Q = new Tone.Signal(options.Q);\n\t this.input.fan(this.low, this.high);\n\t this.input.chain(this._lowMidFilter, this.mid);\n\t //the frequency control signal\n\t this.lowFrequency.connect(this.low.frequency);\n\t this.lowFrequency.connect(this._lowMidFilter.frequency);\n\t this.highFrequency.connect(this.mid.frequency);\n\t this.highFrequency.connect(this.high.frequency);\n\t //the Q value\n\t this.Q.connect(this.low.Q);\n\t this.Q.connect(this._lowMidFilter.Q);\n\t this.Q.connect(this.mid.Q);\n\t this.Q.connect(this.high.Q);\n\t this._readOnly([\n\t 'high',\n\t 'mid',\n\t 'low',\n\t 'highFrequency',\n\t 'lowFrequency'\n\t ]);\n\t };\n\t Tone.extend(Tone.MultibandSplit);\n\t /**\n\t\t * @private\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.MultibandSplit.defaults = {\n\t 'lowFrequency': 400,\n\t 'highFrequency': 2500,\n\t 'Q': 1\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.MultibandSplit} this\n\t\t */\n\t Tone.MultibandSplit.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'high',\n\t 'mid',\n\t 'low',\n\t 'highFrequency',\n\t 'lowFrequency'\n\t ]);\n\t this.low.dispose();\n\t this.low = null;\n\t this._lowMidFilter.dispose();\n\t this._lowMidFilter = null;\n\t this.mid.dispose();\n\t this.mid = null;\n\t this.high.dispose();\n\t this.high = null;\n\t this.lowFrequency.dispose();\n\t this.lowFrequency = null;\n\t this.highFrequency.dispose();\n\t this.highFrequency = null;\n\t this.Q.dispose();\n\t this.Q = null;\n\t return this;\n\t };\n\t return Tone.MultibandSplit;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.EQ3 is a three band EQ with control over low, mid, and high gain as\n\t\t * well as the low and high crossover frequencies.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * \n\t\t * @param {Decibels|Object} [lowLevel] The gain applied to the lows.\n\t\t * @param {Decibels} [midLevel] The gain applied to the mid.\n\t\t * @param {Decibels} [highLevel] The gain applied to the high.\n\t\t * @example\n\t\t * var eq = new Tone.EQ3(-10, 3, -20);\n\t\t */\n\t Tone.EQ3 = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'low',\n\t 'mid',\n\t 'high'\n\t ], Tone.EQ3.defaults);\n\t /**\n\t\t\t * the output node\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.output = new Tone.Gain();\n\t /**\n\t\t\t * the multiband split\n\t\t\t * @type {Tone.MultibandSplit}\n\t\t\t * @private\n\t\t\t */\n\t this._multibandSplit = this.input = new Tone.MultibandSplit({\n\t 'lowFrequency': options.lowFrequency,\n\t 'highFrequency': options.highFrequency\n\t });\n\t /**\n\t\t\t * The gain for the lower signals\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._lowGain = new Tone.Gain(options.low, Tone.Type.Decibels);\n\t /**\n\t\t\t * The gain for the mid signals\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._midGain = new Tone.Gain(options.mid, Tone.Type.Decibels);\n\t /**\n\t\t\t * The gain in decibels of the high part\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._highGain = new Tone.Gain(options.high, Tone.Type.Decibels);\n\t /**\n\t\t\t * The gain in decibels of the low part\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.low = this._lowGain.gain;\n\t /**\n\t\t\t * The gain in decibels of the mid part\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.mid = this._midGain.gain;\n\t /**\n\t\t\t * The gain in decibels of the high part\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.high = this._highGain.gain;\n\t /**\n\t\t\t * The Q value for all of the filters. \n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this.Q = this._multibandSplit.Q;\n\t /**\n\t\t\t * The low/mid crossover frequency. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.lowFrequency = this._multibandSplit.lowFrequency;\n\t /**\n\t\t\t * The mid/high crossover frequency. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.highFrequency = this._multibandSplit.highFrequency;\n\t //the frequency bands\n\t this._multibandSplit.low.chain(this._lowGain, this.output);\n\t this._multibandSplit.mid.chain(this._midGain, this.output);\n\t this._multibandSplit.high.chain(this._highGain, this.output);\n\t this._readOnly([\n\t 'low',\n\t 'mid',\n\t 'high',\n\t 'lowFrequency',\n\t 'highFrequency'\n\t ]);\n\t };\n\t Tone.extend(Tone.EQ3);\n\t /**\n\t\t * the default values\n\t\t */\n\t Tone.EQ3.defaults = {\n\t 'low': 0,\n\t 'mid': 0,\n\t 'high': 0,\n\t 'lowFrequency': 400,\n\t 'highFrequency': 2500\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.EQ3} this\n\t\t */\n\t Tone.EQ3.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'low',\n\t 'mid',\n\t 'high',\n\t 'lowFrequency',\n\t 'highFrequency'\n\t ]);\n\t this._multibandSplit.dispose();\n\t this._multibandSplit = null;\n\t this.lowFrequency = null;\n\t this.highFrequency = null;\n\t this._lowGain.dispose();\n\t this._lowGain = null;\n\t this._midGain.dispose();\n\t this._midGain = null;\n\t this._highGain.dispose();\n\t this._highGain = null;\n\t this.low = null;\n\t this.mid = null;\n\t this.high = null;\n\t this.Q = null;\n\t return this;\n\t };\n\t return Tone.EQ3;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Performs a linear scaling on an input signal.\n\t\t * Scales a NormalRange input to between\n\t\t * outputMin and outputMax.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.SignalBase}\n\t\t * @param {number} [outputMin=0] The output value when the input is 0. \n\t\t * @param {number} [outputMax=1]\tThe output value when the input is 1. \n\t\t * @example\n\t\t * var scale = new Tone.Scale(50, 100);\n\t\t * var signal = new Tone.Signal(0.5).connect(scale);\n\t\t * //the output of scale equals 75\n\t\t */\n\t Tone.Scale = function (outputMin, outputMax) {\n\t /** \n\t\t\t * @private\n\t\t\t * @type {number}\n\t\t\t */\n\t this._outputMin = this.defaultArg(outputMin, 0);\n\t /** \n\t\t\t * @private\n\t\t\t * @type {number}\n\t\t\t */\n\t this._outputMax = this.defaultArg(outputMax, 1);\n\t /** \n\t\t\t * @private\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._scale = this.input = new Tone.Multiply(1);\n\t /** \n\t\t\t * @private\n\t\t\t * @type {Tone.Add}\n\t\t\t * @private\n\t\t\t */\n\t this._add = this.output = new Tone.Add(0);\n\t this._scale.connect(this._add);\n\t this._setRange();\n\t };\n\t Tone.extend(Tone.Scale, Tone.SignalBase);\n\t /**\n\t\t * The minimum output value. This number is output when \n\t\t * the value input value is 0. \n\t\t * @memberOf Tone.Scale#\n\t\t * @type {number}\n\t\t * @name min\n\t\t */\n\t Object.defineProperty(Tone.Scale.prototype, 'min', {\n\t get: function () {\n\t return this._outputMin;\n\t },\n\t set: function (min) {\n\t this._outputMin = min;\n\t this._setRange();\n\t }\n\t });\n\t /**\n\t\t * The maximum output value. This number is output when \n\t\t * the value input value is 1. \n\t\t * @memberOf Tone.Scale#\n\t\t * @type {number}\n\t\t * @name max\n\t\t */\n\t Object.defineProperty(Tone.Scale.prototype, 'max', {\n\t get: function () {\n\t return this._outputMax;\n\t },\n\t set: function (max) {\n\t this._outputMax = max;\n\t this._setRange();\n\t }\n\t });\n\t /**\n\t\t * set the values\n\t\t * @private\n\t\t */\n\t Tone.Scale.prototype._setRange = function () {\n\t this._add.value = this._outputMin;\n\t this._scale.value = this._outputMax - this._outputMin;\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Scale} this\n\t\t */\n\t Tone.Scale.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._add.dispose();\n\t this._add = null;\n\t this._scale.dispose();\n\t this._scale = null;\n\t return this;\n\t };\n\t return Tone.Scale;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Performs an exponential scaling on an input signal.\n\t\t * Scales a NormalRange value [0,1] exponentially\n\t\t * to the output range of outputMin to outputMax.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.SignalBase}\n\t\t * @param {number} [outputMin=0] The output value when the input is 0. \n\t\t * @param {number} [outputMax=1]\tThe output value when the input is 1. \n\t\t * @param {number} [exponent=2] The exponent which scales the incoming signal.\n\t\t * @example\n\t\t * var scaleExp = new Tone.ScaleExp(0, 100, 2);\n\t\t * var signal = new Tone.Signal(0.5).connect(scaleExp);\n\t\t */\n\t Tone.ScaleExp = function (outputMin, outputMax, exponent) {\n\t /**\n\t\t\t * scale the input to the output range\n\t\t\t * @type {Tone.Scale}\n\t\t\t * @private\n\t\t\t */\n\t this._scale = this.output = new Tone.Scale(outputMin, outputMax);\n\t /**\n\t\t\t * @private\n\t\t\t * @type {Tone.Pow}\n\t\t\t * @private\n\t\t\t */\n\t this._exp = this.input = new Tone.Pow(this.defaultArg(exponent, 2));\n\t this._exp.connect(this._scale);\n\t };\n\t Tone.extend(Tone.ScaleExp, Tone.SignalBase);\n\t /**\n\t\t * Instead of interpolating linearly between the <code>min</code> and \n\t\t * <code>max</code> values, setting the exponent will interpolate between\n\t\t * the two values with an exponential curve. \n\t\t * @memberOf Tone.ScaleExp#\n\t\t * @type {number}\n\t\t * @name exponent\n\t\t */\n\t Object.defineProperty(Tone.ScaleExp.prototype, 'exponent', {\n\t get: function () {\n\t return this._exp.value;\n\t },\n\t set: function (exp) {\n\t this._exp.value = exp;\n\t }\n\t });\n\t /**\n\t\t * The minimum output value. This number is output when \n\t\t * the value input value is 0. \n\t\t * @memberOf Tone.ScaleExp#\n\t\t * @type {number}\n\t\t * @name min\n\t\t */\n\t Object.defineProperty(Tone.ScaleExp.prototype, 'min', {\n\t get: function () {\n\t return this._scale.min;\n\t },\n\t set: function (min) {\n\t this._scale.min = min;\n\t }\n\t });\n\t /**\n\t\t * The maximum output value. This number is output when \n\t\t * the value input value is 1. \n\t\t * @memberOf Tone.ScaleExp#\n\t\t * @type {number}\n\t\t * @name max\n\t\t */\n\t Object.defineProperty(Tone.ScaleExp.prototype, 'max', {\n\t get: function () {\n\t return this._scale.max;\n\t },\n\t set: function (max) {\n\t this._scale.max = max;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.ScaleExp} this\n\t\t */\n\t Tone.ScaleExp.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._scale.dispose();\n\t this._scale = null;\n\t this._exp.dispose();\n\t this._exp = null;\n\t return this;\n\t };\n\t return Tone.ScaleExp;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * createDelay shim\n\t\t * @private\n\t\t */\n\t if (window.DelayNode && !AudioContext.prototype.createDelay) {\n\t AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode;\n\t }\n\t /**\n\t\t * @class Wrapper around Web Audio's native [DelayNode](http://webaudio.github.io/web-audio-api/#the-delaynode-interface). \n\t\t * @extends {Tone}\n\t\t * @param {Time=} delayTime The delay applied to the incoming signal.\n\t\t * @param {Time=} maxDelay The maximum delay time. \n\t\t */\n\t Tone.Delay = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'delayTime',\n\t 'maxDelay'\n\t ], Tone.Delay.defaults);\n\t /**\n\t\t\t * The native delay node\n\t\t\t * @type {DelayNode}\n\t\t\t * @private\n\t\t\t */\n\t this._delayNode = this.input = this.output = this.context.createDelay(this.toSeconds(options.maxDelay));\n\t /**\n\t\t\t * The amount of time the incoming signal is\n\t\t\t * delayed. \n\t\t\t * @type {Tone.Param}\n\t\t\t * @signal\n\t\t\t */\n\t this.delayTime = new Tone.Param({\n\t 'param': this._delayNode.delayTime,\n\t 'units': Tone.Type.Time,\n\t 'value': options.delayTime\n\t });\n\t this._readOnly('delayTime');\n\t };\n\t Tone.extend(Tone.Delay);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Delay.defaults = {\n\t 'maxDelay': 1,\n\t 'delayTime': 0\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.Delay} this\n\t\t */\n\t Tone.Delay.prototype.dispose = function () {\n\t Tone.Param.prototype.dispose.call(this);\n\t this._delayNode.disconnect();\n\t this._delayNode = null;\n\t this._writable('delayTime');\n\t this.delayTime = null;\n\t return this;\n\t };\n\t return Tone.Delay;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Comb filters are basic building blocks for physical modeling. Read more\n\t\t * about comb filters on [CCRMA's website](https://ccrma.stanford.edu/~jos/pasp/Feedback_Comb_Filters.html).\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {Time|Object} [delayTime] The delay time of the filter. \n\t\t * @param {NormalRange=} resonance The amount of feedback the filter has. \n\t\t */\n\t Tone.FeedbackCombFilter = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'delayTime',\n\t 'resonance'\n\t ], Tone.FeedbackCombFilter.defaults);\n\t /**\n\t\t\t * the delay node\n\t\t\t * @type {DelayNode}\n\t\t\t * @private\n\t\t\t */\n\t this._delay = this.input = this.output = new Tone.Delay(options.delayTime);\n\t /**\n\t\t\t * The amount of delay of the comb filter. \n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.delayTime = this._delay.delayTime;\n\t /**\n\t\t\t * the feedback node\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this._feedback = new Tone.Gain(options.resonance, Tone.Type.NormalRange);\n\t /**\n\t\t\t * The amount of feedback of the delayed signal. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.resonance = this._feedback.gain;\n\t this._delay.chain(this._feedback, this._delay);\n\t this._readOnly([\n\t 'resonance',\n\t 'delayTime'\n\t ]);\n\t };\n\t Tone.extend(Tone.FeedbackCombFilter);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.FeedbackCombFilter.defaults = {\n\t 'delayTime': 0.1,\n\t 'resonance': 0.5\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.FeedbackCombFilter} this\n\t\t */\n\t Tone.FeedbackCombFilter.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'resonance',\n\t 'delayTime'\n\t ]);\n\t this._delay.dispose();\n\t this._delay = null;\n\t this.delayTime = null;\n\t this._feedback.dispose();\n\t this._feedback = null;\n\t this.resonance = null;\n\t return this;\n\t };\n\t return Tone.FeedbackCombFilter;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Follower is a crude envelope follower which will follow \n\t\t * the amplitude of an incoming signal. \n\t\t * Take care with small (< 0.02) attack or decay values \n\t\t * as follower has some ripple which is exaggerated\n\t\t * at these values. Read more about envelope followers (also known \n\t\t * as envelope detectors) on [Wikipedia](https://en.wikipedia.org/wiki/Envelope_detector).\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {Time|Object} [attack] The rate at which the follower rises.\n\t\t * @param {Time=} release The rate at which the folower falls. \n\t\t * @example\n\t\t * var follower = new Tone.Follower(0.2, 0.4);\n\t\t */\n\t Tone.Follower = function () {\n\t this.createInsOuts(1, 1);\n\t var options = this.optionsObject(arguments, [\n\t 'attack',\n\t 'release'\n\t ], Tone.Follower.defaults);\n\t /**\n\t\t\t * @type {Tone.Abs}\n\t\t\t * @private\n\t\t\t */\n\t this._abs = new Tone.Abs();\n\t /**\n\t\t\t * the lowpass filter which smooths the input\n\t\t\t * @type {BiquadFilterNode}\n\t\t\t * @private\n\t\t\t */\n\t this._filter = this.context.createBiquadFilter();\n\t this._filter.type = 'lowpass';\n\t this._filter.frequency.value = 0;\n\t this._filter.Q.value = -100;\n\t /**\n\t\t\t * @type {WaveShaperNode}\n\t\t\t * @private\n\t\t\t */\n\t this._frequencyValues = new Tone.WaveShaper();\n\t /**\n\t\t\t * @type {Tone.Subtract}\n\t\t\t * @private\n\t\t\t */\n\t this._sub = new Tone.Subtract();\n\t /**\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._delay = new Tone.Delay(this.blockTime);\n\t /**\n\t\t\t * this keeps it far from 0, even for very small differences\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._mult = new Tone.Multiply(10000);\n\t /**\n\t\t\t * @private\n\t\t\t * @type {number}\n\t\t\t */\n\t this._attack = options.attack;\n\t /**\n\t\t\t * @private\n\t\t\t * @type {number}\n\t\t\t */\n\t this._release = options.release;\n\t //the smoothed signal to get the values\n\t this.input.chain(this._abs, this._filter, this.output);\n\t //the difference path\n\t this._abs.connect(this._sub, 0, 1);\n\t this._filter.chain(this._delay, this._sub);\n\t //threshold the difference and use the thresh to set the frequency\n\t this._sub.chain(this._mult, this._frequencyValues, this._filter.frequency);\n\t //set the attack and release values in the table\n\t this._setAttackRelease(this._attack, this._release);\n\t };\n\t Tone.extend(Tone.Follower);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Follower.defaults = {\n\t 'attack': 0.05,\n\t 'release': 0.5\n\t };\n\t /**\n\t\t * sets the attack and release times in the wave shaper\n\t\t * @param {Time} attack \n\t\t * @param {Time} release \n\t\t * @private\n\t\t */\n\t Tone.Follower.prototype._setAttackRelease = function (attack, release) {\n\t var minTime = this.blockTime;\n\t attack = Tone.Time(attack).toFrequency();\n\t release = Tone.Time(release).toFrequency();\n\t attack = Math.max(attack, minTime);\n\t release = Math.max(release, minTime);\n\t this._frequencyValues.setMap(function (val) {\n\t if (val <= 0) {\n\t return attack;\n\t } else {\n\t return release;\n\t }\n\t });\n\t };\n\t /**\n\t\t * The attack time.\n\t\t * @memberOf Tone.Follower#\n\t\t * @type {Time}\n\t\t * @name attack\n\t\t */\n\t Object.defineProperty(Tone.Follower.prototype, 'attack', {\n\t get: function () {\n\t return this._attack;\n\t },\n\t set: function (attack) {\n\t this._attack = attack;\n\t this._setAttackRelease(this._attack, this._release);\n\t }\n\t });\n\t /**\n\t\t * The release time.\n\t\t * @memberOf Tone.Follower#\n\t\t * @type {Time}\n\t\t * @name release\n\t\t */\n\t Object.defineProperty(Tone.Follower.prototype, 'release', {\n\t get: function () {\n\t return this._release;\n\t },\n\t set: function (release) {\n\t this._release = release;\n\t this._setAttackRelease(this._attack, this._release);\n\t }\n\t });\n\t /**\n\t\t * Borrows the connect method from Signal so that the output can be used\n\t\t * as a Tone.Signal control signal.\n\t\t * @function\n\t\t */\n\t Tone.Follower.prototype.connect = Tone.Signal.prototype.connect;\n\t /**\n\t\t * dispose\n\t\t * @returns {Tone.Follower} this\n\t\t */\n\t Tone.Follower.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._filter.disconnect();\n\t this._filter = null;\n\t this._frequencyValues.disconnect();\n\t this._frequencyValues = null;\n\t this._delay.dispose();\n\t this._delay = null;\n\t this._sub.disconnect();\n\t this._sub = null;\n\t this._abs.dispose();\n\t this._abs = null;\n\t this._mult.dispose();\n\t this._mult = null;\n\t this._curve = null;\n\t return this;\n\t };\n\t return Tone.Follower;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.ScaledEnvelop is an envelope which can be scaled \n\t\t * to any range. It's useful for applying an envelope \n\t\t * to a frequency or any other non-NormalRange signal \n\t\t * parameter. \n\t\t *\n\t\t * @extends {Tone.Envelope}\n\t\t * @constructor\n\t\t * @param {Time|Object} [attack]\tthe attack time in seconds\n\t\t * @param {Time} [decay]\tthe decay time in seconds\n\t\t * @param {number} [sustain] \ta percentage (0-1) of the full amplitude\n\t\t * @param {Time} [release]\tthe release time in seconds\n\t\t * @example\n\t\t * var scaledEnv = new Tone.ScaledEnvelope({\n\t\t * \t\"attack\" : 0.2,\n\t\t * \t\"min\" : 200,\n\t\t * \t\"max\" : 2000\n\t\t * });\n\t\t * scaledEnv.connect(oscillator.frequency);\n\t\t */\n\t Tone.ScaledEnvelope = function () {\n\t //get all of the defaults\n\t var options = this.optionsObject(arguments, [\n\t 'attack',\n\t 'decay',\n\t 'sustain',\n\t 'release'\n\t ], Tone.Envelope.defaults);\n\t Tone.Envelope.call(this, options);\n\t options = this.defaultArg(options, Tone.ScaledEnvelope.defaults);\n\t /** \n\t\t\t * scale the incoming signal by an exponent\n\t\t\t * @type {Tone.Pow}\n\t\t\t * @private\n\t\t\t */\n\t this._exp = this.output = new Tone.Pow(options.exponent);\n\t /**\n\t\t\t * scale the signal to the desired range\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._scale = this.output = new Tone.Scale(options.min, options.max);\n\t this._sig.chain(this._exp, this._scale);\n\t };\n\t Tone.extend(Tone.ScaledEnvelope, Tone.Envelope);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t */\n\t Tone.ScaledEnvelope.defaults = {\n\t 'min': 0,\n\t 'max': 1,\n\t 'exponent': 1\n\t };\n\t /**\n\t\t * The envelope's min output value. This is the value which it\n\t\t * starts at. \n\t\t * @memberOf Tone.ScaledEnvelope#\n\t\t * @type {number}\n\t\t * @name min\n\t\t */\n\t Object.defineProperty(Tone.ScaledEnvelope.prototype, 'min', {\n\t get: function () {\n\t return this._scale.min;\n\t },\n\t set: function (min) {\n\t this._scale.min = min;\n\t }\n\t });\n\t /**\n\t\t * The envelope's max output value. In other words, the value\n\t\t * at the peak of the attack portion of the envelope. \n\t\t * @memberOf Tone.ScaledEnvelope#\n\t\t * @type {number}\n\t\t * @name max\n\t\t */\n\t Object.defineProperty(Tone.ScaledEnvelope.prototype, 'max', {\n\t get: function () {\n\t return this._scale.max;\n\t },\n\t set: function (max) {\n\t this._scale.max = max;\n\t }\n\t });\n\t /**\n\t\t * The envelope's exponent value. \n\t\t * @memberOf Tone.ScaledEnvelope#\n\t\t * @type {number}\n\t\t * @name exponent\n\t\t */\n\t Object.defineProperty(Tone.ScaledEnvelope.prototype, 'exponent', {\n\t get: function () {\n\t return this._exp.value;\n\t },\n\t set: function (exp) {\n\t this._exp.value = exp;\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.ScaledEnvelope} this\n\t\t */\n\t Tone.ScaledEnvelope.prototype.dispose = function () {\n\t Tone.Envelope.prototype.dispose.call(this);\n\t this._scale.dispose();\n\t this._scale = null;\n\t this._exp.dispose();\n\t this._exp = null;\n\t return this;\n\t };\n\t return Tone.ScaledEnvelope;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.FrequencyEnvelope is a Tone.ScaledEnvelope, but instead of `min` and `max`\n\t\t * it's got a `baseFrequency` and `octaves` parameter. \n\t\t *\n\t\t * @extends {Tone.Envelope}\n\t\t * @constructor\n\t\t * @param {Time|Object} [attack]\tthe attack time in seconds\n\t\t * @param {Time} [decay]\tthe decay time in seconds\n\t\t * @param {number} [sustain] \ta percentage (0-1) of the full amplitude\n\t\t * @param {Time} [release]\tthe release time in seconds\n\t\t * @example\n\t\t * var env = new Tone.FrequencyEnvelope({\n\t\t * \t\"attack\" : 0.2,\n\t\t * \t\"baseFrequency\" : \"C2\",\n\t\t * \t\"octaves\" : 4\n\t\t * });\n\t\t * scaledEnv.connect(oscillator.frequency);\n\t\t */\n\t Tone.FrequencyEnvelope = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'attack',\n\t 'decay',\n\t 'sustain',\n\t 'release'\n\t ], Tone.Envelope.defaults);\n\t Tone.ScaledEnvelope.call(this, options);\n\t options = this.defaultArg(options, Tone.FrequencyEnvelope.defaults);\n\t /**\n\t\t\t * Stores the octave value\n\t\t\t * @type {Positive}\n\t\t\t * @private\n\t\t\t */\n\t this._octaves = options.octaves;\n\t //setup\n\t this.baseFrequency = options.baseFrequency;\n\t this.octaves = options.octaves;\n\t };\n\t Tone.extend(Tone.FrequencyEnvelope, Tone.Envelope);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t */\n\t Tone.FrequencyEnvelope.defaults = {\n\t 'baseFrequency': 200,\n\t 'octaves': 4,\n\t 'exponent': 2\n\t };\n\t /**\n\t\t * The envelope's mininum output value. This is the value which it\n\t\t * starts at. \n\t\t * @memberOf Tone.FrequencyEnvelope#\n\t\t * @type {Frequency}\n\t\t * @name baseFrequency\n\t\t */\n\t Object.defineProperty(Tone.FrequencyEnvelope.prototype, 'baseFrequency', {\n\t get: function () {\n\t return this._scale.min;\n\t },\n\t set: function (min) {\n\t this._scale.min = this.toFrequency(min);\n\t //also update the octaves\n\t this.octaves = this._octaves;\n\t }\n\t });\n\t /**\n\t\t * The number of octaves above the baseFrequency that the\n\t\t * envelope will scale to.\n\t\t * @memberOf Tone.FrequencyEnvelope#\n\t\t * @type {Positive}\n\t\t * @name octaves\n\t\t */\n\t Object.defineProperty(Tone.FrequencyEnvelope.prototype, 'octaves', {\n\t get: function () {\n\t return this._octaves;\n\t },\n\t set: function (octaves) {\n\t this._octaves = octaves;\n\t this._scale.max = this.baseFrequency * Math.pow(2, octaves);\n\t }\n\t });\n\t /**\n\t\t * The envelope's exponent value. \n\t\t * @memberOf Tone.FrequencyEnvelope#\n\t\t * @type {number}\n\t\t * @name exponent\n\t\t */\n\t Object.defineProperty(Tone.FrequencyEnvelope.prototype, 'exponent', {\n\t get: function () {\n\t return this._exp.value;\n\t },\n\t set: function (exp) {\n\t this._exp.value = exp;\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.FrequencyEnvelope} this\n\t\t */\n\t Tone.FrequencyEnvelope.prototype.dispose = function () {\n\t Tone.ScaledEnvelope.prototype.dispose.call(this);\n\t return this;\n\t };\n\t return Tone.FrequencyEnvelope;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Gate only passes a signal through when the incoming \n\t\t * signal exceeds a specified threshold. To do this, Gate uses \n\t\t * a Tone.Follower to follow the amplitude of the incoming signal. \n\t\t * A common implementation of this class is a [Noise Gate](https://en.wikipedia.org/wiki/Noise_gate).\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {Decibels|Object} [threshold] The threshold above which the gate will open. \n\t\t * @param {Time=} attack The follower's attack time\n\t\t * @param {Time=} release The follower's release time\n\t\t * @example\n\t\t * var gate = new Tone.Gate(-30, 0.2, 0.3).toMaster();\n\t\t * var mic = new Tone.UserMedia().connect(gate);\n\t\t * //the gate will only pass through the incoming \n\t\t * //signal when it's louder than -30db\n\t\t */\n\t Tone.Gate = function () {\n\t this.createInsOuts(1, 1);\n\t var options = this.optionsObject(arguments, [\n\t 'threshold',\n\t 'attack',\n\t 'release'\n\t ], Tone.Gate.defaults);\n\t /**\n\t\t\t * @type {Tone.Follower}\n\t\t\t * @private\n\t\t\t */\n\t this._follower = new Tone.Follower(options.attack, options.release);\n\t /**\n\t\t\t * @type {Tone.GreaterThan}\n\t\t\t * @private\n\t\t\t */\n\t this._gt = new Tone.GreaterThan(this.dbToGain(options.threshold));\n\t //the connections\n\t this.input.connect(this.output);\n\t //the control signal\n\t this.input.chain(this._gt, this._follower, this.output.gain);\n\t };\n\t Tone.extend(Tone.Gate);\n\t /**\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Gate.defaults = {\n\t 'attack': 0.1,\n\t 'release': 0.1,\n\t 'threshold': -40\n\t };\n\t /**\n\t\t * The threshold of the gate in decibels\n\t\t * @memberOf Tone.Gate#\n\t\t * @type {Decibels}\n\t\t * @name threshold\n\t\t */\n\t Object.defineProperty(Tone.Gate.prototype, 'threshold', {\n\t get: function () {\n\t return this.gainToDb(this._gt.value);\n\t },\n\t set: function (thresh) {\n\t this._gt.value = this.dbToGain(thresh);\n\t }\n\t });\n\t /**\n\t\t * The attack speed of the gate\n\t\t * @memberOf Tone.Gate#\n\t\t * @type {Time}\n\t\t * @name attack\n\t\t */\n\t Object.defineProperty(Tone.Gate.prototype, 'attack', {\n\t get: function () {\n\t return this._follower.attack;\n\t },\n\t set: function (attackTime) {\n\t this._follower.attack = attackTime;\n\t }\n\t });\n\t /**\n\t\t * The release speed of the gate\n\t\t * @memberOf Tone.Gate#\n\t\t * @type {Time}\n\t\t * @name release\n\t\t */\n\t Object.defineProperty(Tone.Gate.prototype, 'release', {\n\t get: function () {\n\t return this._follower.release;\n\t },\n\t set: function (releaseTime) {\n\t this._follower.release = releaseTime;\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Gate} this\n\t\t */\n\t Tone.Gate.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._follower.dispose();\n\t this._gt.dispose();\n\t this._follower = null;\n\t this._gt = null;\n\t return this;\n\t };\n\t return Tone.Gate;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A Timeline State. Provides the methods: <code>setStateAtTime(\"state\", time)</code>\n\t\t * and <code>getValueAtTime(time)</code>.\n\t\t *\n\t\t * @extends {Tone.Timeline}\n\t\t * @param {String} initial The initial state of the TimelineState. \n\t\t * Defaults to <code>undefined</code>\n\t\t */\n\t Tone.TimelineState = function (initial) {\n\t Tone.Timeline.call(this);\n\t /**\n\t\t\t * The initial state\n\t\t\t * @private\n\t\t\t * @type {String}\n\t\t\t */\n\t this._initial = initial;\n\t };\n\t Tone.extend(Tone.TimelineState, Tone.Timeline);\n\t /**\n\t\t * Returns the scheduled state scheduled before or at\n\t\t * the given time.\n\t\t * @param {Number} time The time to query.\n\t\t * @return {String} The name of the state input in setStateAtTime.\n\t\t */\n\t Tone.TimelineState.prototype.getValueAtTime = function (time) {\n\t var event = this.get(time);\n\t if (event !== null) {\n\t return event.state;\n\t } else {\n\t return this._initial;\n\t }\n\t };\n\t /**\n\t\t * Returns the scheduled state scheduled before or at\n\t\t * the given time.\n\t\t * @param {String} state The name of the state to set.\n\t\t * @param {Number} time The time to query.\n\t\t */\n\t Tone.TimelineState.prototype.setStateAtTime = function (state, time) {\n\t this.add({\n\t 'state': state,\n\t 'time': time\n\t });\n\t };\n\t return Tone.TimelineState;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A sample accurate clock which provides a callback at the given rate. \n\t\t * While the callback is not sample-accurate (it is still susceptible to\n\t\t * loose JS timing), the time passed in as the argument to the callback\n\t\t * is precise. For most applications, it is better to use Tone.Transport\n\t\t * instead of the Clock by itself since you can synchronize multiple callbacks.\n\t\t *\n\t\t * \t@constructor\n\t\t * @extends {Tone.Emitter}\n\t\t * \t@param {function} callback The callback to be invoked with the time of the audio event\n\t\t * \t@param {Frequency} frequency The rate of the callback\n\t\t * \t@example\n\t\t * //the callback will be invoked approximately once a second\n\t\t * //and will print the time exactly once a second apart.\n\t\t * var clock = new Tone.Clock(function(time){\n\t\t * \tconsole.log(time);\n\t\t * }, 1);\n\t\t */\n\t Tone.Clock = function () {\n\t Tone.Emitter.call(this);\n\t var options = this.optionsObject(arguments, [\n\t 'callback',\n\t 'frequency'\n\t ], Tone.Clock.defaults);\n\t /**\n\t\t\t * The callback function to invoke at the scheduled tick.\n\t\t\t * @type {Function}\n\t\t\t */\n\t this.callback = options.callback;\n\t /**\n\t\t\t * The next time the callback is scheduled.\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._nextTick = 0;\n\t /**\n\t\t\t * The last state of the clock.\n\t\t\t * @type {State}\n\t\t\t * @private\n\t\t\t */\n\t this._lastState = Tone.State.Stopped;\n\t /**\n\t\t\t * The rate the callback function should be invoked. \n\t\t\t * @type {BPM}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);\n\t this._readOnly('frequency');\n\t /**\n\t\t\t * The number of times the callback was invoked. Starts counting at 0\n\t\t\t * and increments after the callback was invoked. \n\t\t\t * @type {Ticks}\n\t\t\t * @readOnly\n\t\t\t */\n\t this.ticks = 0;\n\t /**\n\t\t\t * The state timeline\n\t\t\t * @type {Tone.TimelineState}\n\t\t\t * @private\n\t\t\t */\n\t this._state = new Tone.TimelineState(Tone.State.Stopped);\n\t /**\n\t\t\t * The loop function bound to its context. \n\t\t\t * This is necessary to remove the event in the end.\n\t\t\t * @type {Function}\n\t\t\t * @private\n\t\t\t */\n\t this._boundLoop = this._loop.bind(this);\n\t //bind a callback to the worker thread\n\t this.context.on('tick', this._boundLoop);\n\t };\n\t Tone.extend(Tone.Clock, Tone.Emitter);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Clock.defaults = {\n\t 'callback': Tone.noOp,\n\t 'frequency': 1,\n\t 'lookAhead': 'auto'\n\t };\n\t /**\n\t\t * Returns the playback state of the source, either \"started\", \"stopped\" or \"paused\".\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.Clock#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.Clock.prototype, 'state', {\n\t get: function () {\n\t return this._state.getValueAtTime(this.now());\n\t }\n\t });\n\t /**\n\t\t * Start the clock at the given time. Optionally pass in an offset\n\t\t * of where to start the tick counter from.\n\t\t * @param {Time} time The time the clock should start\n\t\t * @param {Ticks=} offset Where the tick counter starts counting from.\n\t\t * @return {Tone.Clock} this\n\t\t */\n\t Tone.Clock.prototype.start = function (time, offset) {\n\t time = this.toSeconds(time);\n\t if (this._state.getValueAtTime(time) !== Tone.State.Started) {\n\t this._state.add({\n\t 'state': Tone.State.Started,\n\t 'time': time,\n\t 'offset': offset\n\t });\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Stop the clock. Stopping the clock resets the tick counter to 0.\n\t\t * @param {Time} [time=now] The time when the clock should stop.\n\t\t * @returns {Tone.Clock} this\n\t\t * @example\n\t\t * clock.stop();\n\t\t */\n\t Tone.Clock.prototype.stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._state.cancel(time);\n\t this._state.setStateAtTime(Tone.State.Stopped, time);\n\t return this;\n\t };\n\t /**\n\t\t * Pause the clock. Pausing does not reset the tick counter.\n\t\t * @param {Time} [time=now] The time when the clock should stop.\n\t\t * @returns {Tone.Clock} this\n\t\t */\n\t Tone.Clock.prototype.pause = function (time) {\n\t time = this.toSeconds(time);\n\t if (this._state.getValueAtTime(time) === Tone.State.Started) {\n\t this._state.setStateAtTime(Tone.State.Paused, time);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * The scheduling loop.\n\t\t * @param {Number} time The current page time starting from 0\n\t\t * when the page was loaded.\n\t\t * @private\n\t\t */\n\t Tone.Clock.prototype._loop = function () {\n\t //get the frequency value to compute the value of the next loop\n\t var now = this.now();\n\t //if it's started\n\t var lookAhead = this.context.lookAhead;\n\t var updateInterval = this.context.updateInterval;\n\t var lagCompensation = this.context.lag * 2;\n\t var loopInterval = now + lookAhead + updateInterval + lagCompensation;\n\t while (loopInterval > this._nextTick && this._state) {\n\t var currentState = this._state.getValueAtTime(this._nextTick);\n\t if (currentState !== this._lastState) {\n\t this._lastState = currentState;\n\t var event = this._state.get(this._nextTick);\n\t // emit an event\n\t if (currentState === Tone.State.Started) {\n\t //correct the time\n\t this._nextTick = event.time;\n\t if (!this.isUndef(event.offset)) {\n\t this.ticks = event.offset;\n\t }\n\t this.emit('start', event.time, this.ticks);\n\t } else if (currentState === Tone.State.Stopped) {\n\t this.ticks = 0;\n\t this.emit('stop', event.time);\n\t } else if (currentState === Tone.State.Paused) {\n\t this.emit('pause', event.time);\n\t }\n\t }\n\t var tickTime = this._nextTick;\n\t if (this.frequency) {\n\t this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);\n\t if (currentState === Tone.State.Started) {\n\t this.callback(tickTime);\n\t this.ticks++;\n\t }\n\t }\n\t }\n\t };\n\t /**\n\t\t * Returns the scheduled state at the given time.\n\t\t * @param {Time} time The time to query.\n\t\t * @return {String} The name of the state input in setStateAtTime.\n\t\t * @example\n\t\t * clock.start(\"+0.1\");\n\t\t * clock.getStateAtTime(\"+0.1\"); //returns \"started\"\n\t\t */\n\t Tone.Clock.prototype.getStateAtTime = function (time) {\n\t time = this.toSeconds(time);\n\t return this._state.getValueAtTime(time);\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @returns {Tone.Clock} this\n\t\t */\n\t Tone.Clock.prototype.dispose = function () {\n\t Tone.Emitter.prototype.dispose.call(this);\n\t this.context.off('tick', this._boundLoop);\n\t this._writable('frequency');\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this._boundLoop = null;\n\t this._nextTick = Infinity;\n\t this.callback = null;\n\t this._state.dispose();\n\t this._state = null;\n\t };\n\t return Tone.Clock;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Similar to Tone.Timeline, but all events represent\n\t\t * intervals with both \"time\" and \"duration\" times. The \n\t\t * events are placed in a tree structure optimized\n\t\t * for querying an intersection point with the timeline\n\t\t * events. Internally uses an [Interval Tree](https://en.wikipedia.org/wiki/Interval_tree)\n\t\t * to represent the data.\n\t\t * @extends {Tone}\n\t\t */\n\t Tone.IntervalTimeline = function () {\n\t /**\n\t\t\t * The root node of the inteval tree\n\t\t\t * @type {IntervalNode}\n\t\t\t * @private\n\t\t\t */\n\t this._root = null;\n\t /**\n\t\t\t * Keep track of the length of the timeline.\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._length = 0;\n\t };\n\t Tone.extend(Tone.IntervalTimeline);\n\t /**\n\t\t * The event to add to the timeline. All events must \n\t\t * have a time and duration value\n\t\t * @param {Object} event The event to add to the timeline\n\t\t * @return {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.add = function (event) {\n\t if (this.isUndef(event.time) || this.isUndef(event.duration)) {\n\t throw new Error('Tone.IntervalTimeline: events must have time and duration parameters');\n\t }\n\t var node = new IntervalNode(event.time, event.time + event.duration, event);\n\t if (this._root === null) {\n\t this._root = node;\n\t } else {\n\t this._root.insert(node);\n\t }\n\t this._length++;\n\t // Restructure tree to be balanced\n\t while (node !== null) {\n\t node.updateHeight();\n\t node.updateMax();\n\t this._rebalance(node);\n\t node = node.parent;\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Remove an event from the timeline.\n\t\t * @param {Object} event The event to remove from the timeline\n\t\t * @return {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.remove = function (event) {\n\t if (this._root !== null) {\n\t var results = [];\n\t this._root.search(event.time, results);\n\t for (var i = 0; i < results.length; i++) {\n\t var node = results[i];\n\t if (node.event === event) {\n\t this._removeNode(node);\n\t this._length--;\n\t break;\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * The number of items in the timeline.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.IntervalTimeline#\n\t\t * @name length\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.IntervalTimeline.prototype, 'length', {\n\t get: function () {\n\t return this._length;\n\t }\n\t });\n\t /**\n\t\t * Remove events whose time time is after the given time\n\t\t * @param {Number} time The time to query.\n\t\t * @returns {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.cancel = function (after) {\n\t this.forEachAfter(after, function (event) {\n\t this.remove(event);\n\t }.bind(this));\n\t return this;\n\t };\n\t /**\n\t\t * Set the root node as the given node\n\t\t * @param {IntervalNode} node\n\t\t * @private\n\t\t */\n\t Tone.IntervalTimeline.prototype._setRoot = function (node) {\n\t this._root = node;\n\t if (this._root !== null) {\n\t this._root.parent = null;\n\t }\n\t };\n\t /**\n\t\t * Replace the references to the node in the node's parent\n\t\t * with the replacement node.\n\t\t * @param {IntervalNode} node \n\t\t * @param {IntervalNode} replacement \n\t\t * @private\n\t\t */\n\t Tone.IntervalTimeline.prototype._replaceNodeInParent = function (node, replacement) {\n\t if (node.parent !== null) {\n\t if (node.isLeftChild()) {\n\t node.parent.left = replacement;\n\t } else {\n\t node.parent.right = replacement;\n\t }\n\t this._rebalance(node.parent);\n\t } else {\n\t this._setRoot(replacement);\n\t }\n\t };\n\t /**\n\t\t * Remove the node from the tree and replace it with \n\t\t * a successor which follows the schema.\n\t\t * @param {IntervalNode} node\n\t\t * @private\n\t\t */\n\t Tone.IntervalTimeline.prototype._removeNode = function (node) {\n\t if (node.left === null && node.right === null) {\n\t this._replaceNodeInParent(node, null);\n\t } else if (node.right === null) {\n\t this._replaceNodeInParent(node, node.left);\n\t } else if (node.left === null) {\n\t this._replaceNodeInParent(node, node.right);\n\t } else {\n\t var balance = node.getBalance();\n\t var replacement, temp;\n\t if (balance > 0) {\n\t if (node.left.right === null) {\n\t replacement = node.left;\n\t replacement.right = node.right;\n\t temp = replacement;\n\t } else {\n\t replacement = node.left.right;\n\t while (replacement.right !== null) {\n\t replacement = replacement.right;\n\t }\n\t replacement.parent.right = replacement.left;\n\t temp = replacement.parent;\n\t replacement.left = node.left;\n\t replacement.right = node.right;\n\t }\n\t } else {\n\t if (node.right.left === null) {\n\t replacement = node.right;\n\t replacement.left = node.left;\n\t temp = replacement;\n\t } else {\n\t replacement = node.right.left;\n\t while (replacement.left !== null) {\n\t replacement = replacement.left;\n\t }\n\t replacement.parent = replacement.parent;\n\t replacement.parent.left = replacement.right;\n\t temp = replacement.parent;\n\t replacement.left = node.left;\n\t replacement.right = node.right;\n\t }\n\t }\n\t if (node.parent !== null) {\n\t if (node.isLeftChild()) {\n\t node.parent.left = replacement;\n\t } else {\n\t node.parent.right = replacement;\n\t }\n\t } else {\n\t this._setRoot(replacement);\n\t }\n\t // this._replaceNodeInParent(node, replacement);\n\t this._rebalance(temp);\n\t }\n\t node.dispose();\n\t };\n\t /**\n\t\t * Rotate the tree to the left\n\t\t * @param {IntervalNode} node\n\t\t * @private\n\t\t */\n\t Tone.IntervalTimeline.prototype._rotateLeft = function (node) {\n\t var parent = node.parent;\n\t var isLeftChild = node.isLeftChild();\n\t // Make node.right the new root of this sub tree (instead of node)\n\t var pivotNode = node.right;\n\t node.right = pivotNode.left;\n\t pivotNode.left = node;\n\t if (parent !== null) {\n\t if (isLeftChild) {\n\t parent.left = pivotNode;\n\t } else {\n\t parent.right = pivotNode;\n\t }\n\t } else {\n\t this._setRoot(pivotNode);\n\t }\n\t };\n\t /**\n\t\t * Rotate the tree to the right\n\t\t * @param {IntervalNode} node\n\t\t * @private\n\t\t */\n\t Tone.IntervalTimeline.prototype._rotateRight = function (node) {\n\t var parent = node.parent;\n\t var isLeftChild = node.isLeftChild();\n\t // Make node.left the new root of this sub tree (instead of node)\n\t var pivotNode = node.left;\n\t node.left = pivotNode.right;\n\t pivotNode.right = node;\n\t if (parent !== null) {\n\t if (isLeftChild) {\n\t parent.left = pivotNode;\n\t } else {\n\t parent.right = pivotNode;\n\t }\n\t } else {\n\t this._setRoot(pivotNode);\n\t }\n\t };\n\t /**\n\t\t * Balance the BST\n\t\t * @param {IntervalNode} node\n\t\t * @private\n\t\t */\n\t Tone.IntervalTimeline.prototype._rebalance = function (node) {\n\t var balance = node.getBalance();\n\t if (balance > 1) {\n\t if (node.left.getBalance() < 0) {\n\t this._rotateLeft(node.left);\n\t } else {\n\t this._rotateRight(node);\n\t }\n\t } else if (balance < -1) {\n\t if (node.right.getBalance() > 0) {\n\t this._rotateRight(node.right);\n\t } else {\n\t this._rotateLeft(node);\n\t }\n\t }\n\t };\n\t /**\n\t\t * Get an event whose time and duration span the give time. Will\n\t\t * return the match whose \"time\" value is closest to the given time.\n\t\t * @param {Object} event The event to add to the timeline\n\t\t * @return {Object} The event which spans the desired time\n\t\t */\n\t Tone.IntervalTimeline.prototype.get = function (time) {\n\t if (this._root !== null) {\n\t var results = [];\n\t this._root.search(time, results);\n\t if (results.length > 0) {\n\t var max = results[0];\n\t for (var i = 1; i < results.length; i++) {\n\t if (results[i].low > max.low) {\n\t max = results[i];\n\t }\n\t }\n\t return max.event;\n\t }\n\t }\n\t return null;\n\t };\n\t /**\n\t\t * Iterate over everything in the timeline.\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.forEach = function (callback) {\n\t if (this._root !== null) {\n\t var allNodes = [];\n\t if (this._root !== null) {\n\t this._root.traverse(function (node) {\n\t allNodes.push(node);\n\t });\n\t }\n\t for (var i = 0; i < allNodes.length; i++) {\n\t var ev = allNodes[i].event;\n\t if (ev) {\n\t callback(ev);\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over everything in the array in which the given time\n\t\t * overlaps with the time and duration time of the event.\n\t\t * @param {Number} time The time to check if items are overlapping\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.forEachAtTime = function (time, callback) {\n\t if (this._root !== null) {\n\t var results = [];\n\t this._root.search(time, results);\n\t for (var i = results.length - 1; i >= 0; i--) {\n\t var ev = results[i].event;\n\t if (ev) {\n\t callback(ev);\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over everything in the array in which the time is greater\n\t\t * than the given time.\n\t\t * @param {Number} time The time to check if items are before\n\t\t * @param {Function} callback The callback to invoke with every item\n\t\t * @returns {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.forEachAfter = function (time, callback) {\n\t if (this._root !== null) {\n\t var results = [];\n\t this._root.searchAfter(time, results);\n\t for (var i = results.length - 1; i >= 0; i--) {\n\t var ev = results[i].event;\n\t if (ev) {\n\t callback(ev);\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.IntervalTimeline} this\n\t\t */\n\t Tone.IntervalTimeline.prototype.dispose = function () {\n\t var allNodes = [];\n\t if (this._root !== null) {\n\t this._root.traverse(function (node) {\n\t allNodes.push(node);\n\t });\n\t }\n\t for (var i = 0; i < allNodes.length; i++) {\n\t allNodes[i].dispose();\n\t }\n\t allNodes = null;\n\t this._root = null;\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tINTERVAL NODE HELPER\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Represents a node in the binary search tree, with the addition\n\t\t * of a \"high\" value which keeps track of the highest value of\n\t\t * its children. \n\t\t * References: \n\t\t * https://brooknovak.wordpress.com/2013/12/07/augmented-interval-tree-in-c/\n\t\t * http://www.mif.vu.lt/~valdas/ALGORITMAI/LITERATURA/Cormen/Cormen.pdf\n\t\t * @param {Number} low\n\t\t * @param {Number} high\n\t\t * @private\n\t\t */\n\t var IntervalNode = function (low, high, event) {\n\t //the event container\n\t this.event = event;\n\t //the low value\n\t this.low = low;\n\t //the high value\n\t this.high = high;\n\t //the high value for this and all child nodes\n\t this.max = this.high;\n\t //the nodes to the left\n\t this._left = null;\n\t //the nodes to the right\n\t this._right = null;\n\t //the parent node\n\t this.parent = null;\n\t //the number of child nodes\n\t this.height = 0;\n\t };\n\t /** \n\t\t * Insert a node into the correct spot in the tree\n\t\t * @param {IntervalNode} node\n\t\t */\n\t IntervalNode.prototype.insert = function (node) {\n\t if (node.low <= this.low) {\n\t if (this.left === null) {\n\t this.left = node;\n\t } else {\n\t this.left.insert(node);\n\t }\n\t } else {\n\t if (this.right === null) {\n\t this.right = node;\n\t } else {\n\t this.right.insert(node);\n\t }\n\t }\n\t };\n\t /**\n\t\t * Search the tree for nodes which overlap \n\t\t * with the given point\n\t\t * @param {Number} point The point to query\n\t\t * @param {Array} results The array to put the results\n\t\t */\n\t IntervalNode.prototype.search = function (point, results) {\n\t // If p is to the right of the rightmost point of any interval\n\t // in this node and all children, there won't be any matches.\n\t if (point > this.max) {\n\t return;\n\t }\n\t // Search left children\n\t if (this.left !== null) {\n\t this.left.search(point, results);\n\t }\n\t // Check this node\n\t if (this.low <= point && this.high > point) {\n\t results.push(this);\n\t }\n\t // If p is to the left of the time of this interval,\n\t // then it can't be in any child to the right.\n\t if (this.low > point) {\n\t return;\n\t }\n\t // Search right children\n\t if (this.right !== null) {\n\t this.right.search(point, results);\n\t }\n\t };\n\t /**\n\t\t * Search the tree for nodes which are less \n\t\t * than the given point\n\t\t * @param {Number} point The point to query\n\t\t * @param {Array} results The array to put the results\n\t\t */\n\t IntervalNode.prototype.searchAfter = function (point, results) {\n\t // Check this node\n\t if (this.low >= point) {\n\t results.push(this);\n\t if (this.left !== null) {\n\t this.left.searchAfter(point, results);\n\t }\n\t }\n\t // search the right side\n\t if (this.right !== null) {\n\t this.right.searchAfter(point, results);\n\t }\n\t };\n\t /**\n\t\t * Invoke the callback on this element and both it's branches\n\t\t * @param {Function} callback\n\t\t */\n\t IntervalNode.prototype.traverse = function (callback) {\n\t callback(this);\n\t if (this.left !== null) {\n\t this.left.traverse(callback);\n\t }\n\t if (this.right !== null) {\n\t this.right.traverse(callback);\n\t }\n\t };\n\t /**\n\t\t * Update the height of the node\n\t\t */\n\t IntervalNode.prototype.updateHeight = function () {\n\t if (this.left !== null && this.right !== null) {\n\t this.height = Math.max(this.left.height, this.right.height) + 1;\n\t } else if (this.right !== null) {\n\t this.height = this.right.height + 1;\n\t } else if (this.left !== null) {\n\t this.height = this.left.height + 1;\n\t } else {\n\t this.height = 0;\n\t }\n\t };\n\t /**\n\t\t * Update the height of the node\n\t\t */\n\t IntervalNode.prototype.updateMax = function () {\n\t this.max = this.high;\n\t if (this.left !== null) {\n\t this.max = Math.max(this.max, this.left.max);\n\t }\n\t if (this.right !== null) {\n\t this.max = Math.max(this.max, this.right.max);\n\t }\n\t };\n\t /**\n\t\t * The balance is how the leafs are distributed on the node\n\t\t * @return {Number} Negative numbers are balanced to the right\n\t\t */\n\t IntervalNode.prototype.getBalance = function () {\n\t var balance = 0;\n\t if (this.left !== null && this.right !== null) {\n\t balance = this.left.height - this.right.height;\n\t } else if (this.left !== null) {\n\t balance = this.left.height + 1;\n\t } else if (this.right !== null) {\n\t balance = -(this.right.height + 1);\n\t }\n\t return balance;\n\t };\n\t /**\n\t\t * @returns {Boolean} true if this node is the left child\n\t\t * of its parent\n\t\t */\n\t IntervalNode.prototype.isLeftChild = function () {\n\t return this.parent !== null && this.parent.left === this;\n\t };\n\t /**\n\t\t * get/set the left node\n\t\t * @type {IntervalNode}\n\t\t */\n\t Object.defineProperty(IntervalNode.prototype, 'left', {\n\t get: function () {\n\t return this._left;\n\t },\n\t set: function (node) {\n\t this._left = node;\n\t if (node !== null) {\n\t node.parent = this;\n\t }\n\t this.updateHeight();\n\t this.updateMax();\n\t }\n\t });\n\t /**\n\t\t * get/set the right node\n\t\t * @type {IntervalNode}\n\t\t */\n\t Object.defineProperty(IntervalNode.prototype, 'right', {\n\t get: function () {\n\t return this._right;\n\t },\n\t set: function (node) {\n\t this._right = node;\n\t if (node !== null) {\n\t node.parent = this;\n\t }\n\t this.updateHeight();\n\t this.updateMax();\n\t }\n\t });\n\t /**\n\t\t * null out references.\n\t\t */\n\t IntervalNode.prototype.dispose = function () {\n\t this.parent = null;\n\t this._left = null;\n\t this._right = null;\n\t this.event = null;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tEND INTERVAL NODE HELPER\n\t ///////////////////////////////////////////////////////////////////////////\n\t return Tone.IntervalTimeline;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Transport for timing musical events.\n\t\t * Supports tempo curves and time changes. Unlike browser-based timing (setInterval, requestAnimationFrame)\n\t\t * Tone.Transport timing events pass in the exact time of the scheduled event\n\t\t * in the argument of the callback function. Pass that time value to the object\n\t\t * you're scheduling. <br><br>\n\t\t * A single transport is created for you when the library is initialized. \n\t\t * <br><br>\n\t\t * The transport emits the events: \"start\", \"stop\", \"pause\", and \"loop\" which are\n\t\t * called with the time of that event as the argument. \n\t\t *\n\t\t * @extends {Tone.Emitter}\n\t\t * @singleton\n\t\t * @example\n\t\t * //repeated event every 8th note\n\t\t * Tone.Transport.scheduleRepeat(function(time){\n\t\t * \t//do something with the time\n\t\t * }, \"8n\");\n\t\t * @example\n\t\t * //schedule an event on the 16th measure\n\t\t * Tone.Transport.schedule(function(time){\n\t\t * \t//do something with the time\n\t\t * }, \"16:0:0\");\n\t\t */\n\t Tone.Transport = function () {\n\t Tone.Emitter.call(this);\n\t ///////////////////////////////////////////////////////////////////////\n\t //\tLOOPING\n\t //////////////////////////////////////////////////////////////////////\n\t /** \n\t\t\t * \tIf the transport loops or not.\n\t\t\t * @type {boolean}\n\t\t\t */\n\t this.loop = false;\n\t /** \n\t\t\t * \tThe loop start position in ticks\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._loopStart = 0;\n\t /** \n\t\t\t * \tThe loop end position in ticks\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._loopEnd = 0;\n\t ///////////////////////////////////////////////////////////////////////\n\t //\tCLOCK/TEMPO\n\t //////////////////////////////////////////////////////////////////////\n\t /**\n\t\t\t * Pulses per quarter is the number of ticks per quarter note.\n\t\t\t * @private\n\t\t\t * @type {Number}\n\t\t\t */\n\t this._ppq = TransportConstructor.defaults.PPQ;\n\t /**\n\t\t\t * watches the main oscillator for timing ticks\n\t\t\t * initially starts at 120bpm\n\t\t\t * @private\n\t\t\t * @type {Tone.Clock}\n\t\t\t */\n\t this._clock = new Tone.Clock({\n\t 'callback': this._processTick.bind(this),\n\t 'frequency': 0\n\t });\n\t this._bindClockEvents();\n\t /**\n\t\t\t * The Beats Per Minute of the Transport. \n\t\t\t * @type {BPM}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * Tone.Transport.bpm.value = 80;\n\t\t\t * //ramp the bpm to 120 over 10 seconds\n\t\t\t * Tone.Transport.bpm.rampTo(120, 10);\n\t\t\t */\n\t this.bpm = this._clock.frequency;\n\t this.bpm._toUnits = this._toUnits.bind(this);\n\t this.bpm._fromUnits = this._fromUnits.bind(this);\n\t this.bpm.units = Tone.Type.BPM;\n\t this.bpm.value = TransportConstructor.defaults.bpm;\n\t this._readOnly('bpm');\n\t /**\n\t\t\t * The time signature, or more accurately the numerator\n\t\t\t * of the time signature over a denominator of 4. \n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._timeSignature = TransportConstructor.defaults.timeSignature;\n\t ///////////////////////////////////////////////////////////////////////\n\t //\tTIMELINE EVENTS\n\t //////////////////////////////////////////////////////////////////////\n\t /**\n\t\t\t * All the events in an object to keep track by ID\n\t\t\t * @type {Object}\n\t\t\t * @private\n\t\t\t */\n\t this._scheduledEvents = {};\n\t /**\n\t\t\t * The event ID counter\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._eventID = 0;\n\t /**\n\t\t\t * \tThe scheduled events.\n\t\t\t * @type {Tone.Timeline}\n\t\t\t * @private\n\t\t\t */\n\t this._timeline = new Tone.Timeline();\n\t /**\n\t\t\t * Repeated events\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._repeatedEvents = new Tone.IntervalTimeline();\n\t /**\n\t\t\t * Events that occur once\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._onceEvents = new Tone.Timeline();\n\t /** \n\t\t\t * All of the synced Signals\n\t\t\t * @private \n\t\t\t * @type {Array}\n\t\t\t */\n\t this._syncedSignals = [];\n\t ///////////////////////////////////////////////////////////////////////\n\t //\tSWING\n\t //////////////////////////////////////////////////////////////////////\n\t /**\n\t\t\t * The subdivision of the swing\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._swingTicks = TransportConstructor.defaults.PPQ / 2;\n\t //8n\n\t /**\n\t\t\t * The swing amount\n\t\t\t * @type {NormalRange}\n\t\t\t * @private\n\t\t\t */\n\t this._swingAmount = 0;\n\t };\n\t Tone.extend(Tone.Transport, Tone.Emitter);\n\t /**\n\t\t * the defaults\n\t\t * @type {Object}\n\t\t * @const\n\t\t * @static\n\t\t */\n\t Tone.Transport.defaults = {\n\t 'bpm': 120,\n\t 'swing': 0,\n\t 'swingSubdivision': '8n',\n\t 'timeSignature': 4,\n\t 'loopStart': 0,\n\t 'loopEnd': '4m',\n\t 'PPQ': 192\n\t };\n\t ///////////////////////////////////////////////////////////////////////////////\n\t //\tTICKS\n\t ///////////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * called on every tick\n\t\t * @param {number} tickTime clock relative tick time\n\t\t * @private\n\t\t */\n\t Tone.Transport.prototype._processTick = function (tickTime) {\n\t var ticks = this._clock.ticks;\n\t //handle swing\n\t if (this._swingAmount > 0 && ticks % this._ppq !== 0 && //not on a downbeat\n\t ticks % (this._swingTicks * 2) !== 0) {\n\t //add some swing\n\t var progress = ticks % (this._swingTicks * 2) / (this._swingTicks * 2);\n\t var amount = Math.sin(progress * Math.PI) * this._swingAmount;\n\t tickTime += Tone.Time(this._swingTicks * 2 / 3, 'i') * amount;\n\t }\n\t //do the loop test\n\t if (this.loop) {\n\t if (ticks === this._loopEnd) {\n\t this.emit('loopEnd', tickTime);\n\t this._clock.ticks = this._loopStart;\n\t ticks = this._loopStart;\n\t this.emit('loopStart', tickTime, this.seconds);\n\t this.emit('loop', tickTime);\n\t }\n\t }\n\t //process the single occurrence events\n\t this._onceEvents.forEachBefore(ticks, function (event) {\n\t event.callback(tickTime);\n\t //remove the event\n\t delete this._scheduledEvents[event.id.toString()];\n\t }.bind(this));\n\t //and clear the single occurrence timeline\n\t this._onceEvents.cancelBefore(ticks);\n\t //fire the next tick events if their time has come\n\t this._timeline.forEachAtTime(ticks, function (event) {\n\t event.callback(tickTime);\n\t });\n\t //process the repeated events\n\t this._repeatedEvents.forEachAtTime(ticks, function (event) {\n\t if ((ticks - event.time) % event.interval === 0) {\n\t event.callback(tickTime);\n\t }\n\t });\n\t };\n\t ///////////////////////////////////////////////////////////////////////////////\n\t //\tSCHEDULABLE EVENTS\n\t ///////////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Schedule an event along the timeline.\n\t\t * @param {Function} callback The callback to be invoked at the time.\n\t\t * @param {TransportTime} time The time to invoke the callback at.\n\t\t * @return {Number} The id of the event which can be used for canceling the event. \n\t\t * @example\n\t\t * //trigger the callback when the Transport reaches the desired time\n\t\t * Tone.Transport.schedule(function(time){\n\t\t * \tenvelope.triggerAttack(time);\n\t\t * }, \"128i\");\n\t\t */\n\t Tone.Transport.prototype.schedule = function (callback, time) {\n\t var event = {\n\t 'time': this.toTicks(time),\n\t 'callback': callback\n\t };\n\t var id = this._eventID++;\n\t this._scheduledEvents[id.toString()] = {\n\t 'event': event,\n\t 'timeline': this._timeline\n\t };\n\t this._timeline.add(event);\n\t return id;\n\t };\n\t /**\n\t\t * Schedule a repeated event along the timeline. The event will fire\n\t\t * at the `interval` starting at the `startTime` and for the specified\n\t\t * `duration`. \n\t\t * @param {Function} callback The callback to invoke.\n\t\t * @param {Time} interval The duration between successive\n\t\t * callbacks.\n\t\t * @param {TimelinePosition=} startTime When along the timeline the events should\n\t\t * start being invoked.\n\t\t * @param {Time} [duration=Infinity] How long the event should repeat. \n\t\t * @return {Number} The ID of the scheduled event. Use this to cancel\n\t\t * the event. \n\t\t * @example\n\t\t * //a callback invoked every eighth note after the first measure\n\t\t * Tone.Transport.scheduleRepeat(callback, \"8n\", \"1m\");\n\t\t */\n\t Tone.Transport.prototype.scheduleRepeat = function (callback, interval, startTime, duration) {\n\t if (interval <= 0) {\n\t throw new Error('Tone.Transport: repeat events must have an interval larger than 0');\n\t }\n\t var event = {\n\t 'time': this.toTicks(startTime),\n\t 'duration': this.toTicks(this.defaultArg(duration, Infinity)),\n\t 'interval': this.toTicks(interval),\n\t 'callback': callback\n\t };\n\t var id = this._eventID++;\n\t this._scheduledEvents[id.toString()] = {\n\t 'event': event,\n\t 'timeline': this._repeatedEvents\n\t };\n\t this._repeatedEvents.add(event);\n\t return id;\n\t };\n\t /**\n\t\t * Schedule an event that will be removed after it is invoked. \n\t\t * Note that if the given time is less than the current transport time, \n\t\t * the event will be invoked immediately. \n\t\t * @param {Function} callback The callback to invoke once.\n\t\t * @param {TransportTime} time The time the callback should be invoked.\n\t\t * @returns {Number} The ID of the scheduled event. \n\t\t */\n\t Tone.Transport.prototype.scheduleOnce = function (callback, time) {\n\t var id = this._eventID++;\n\t var event = {\n\t 'time': this.toTicks(time),\n\t 'callback': callback,\n\t 'id': id\n\t };\n\t this._scheduledEvents[id.toString()] = {\n\t 'event': event,\n\t 'timeline': this._onceEvents\n\t };\n\t this._onceEvents.add(event);\n\t return id;\n\t };\n\t /**\n\t\t * Clear the passed in event id from the timeline\n\t\t * @param {Number} eventId The id of the event.\n\t\t * @returns {Tone.Transport} this\n\t\t */\n\t Tone.Transport.prototype.clear = function (eventId) {\n\t if (this._scheduledEvents.hasOwnProperty(eventId)) {\n\t var item = this._scheduledEvents[eventId.toString()];\n\t item.timeline.remove(item.event);\n\t delete this._scheduledEvents[eventId.toString()];\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Remove scheduled events from the timeline after\n\t\t * the given time. Repeated events will be removed\n\t\t * if their startTime is after the given time\n\t\t * @param {TransportTime} [after=0] Clear all events after\n\t\t * this time. \n\t\t * @returns {Tone.Transport} this\n\t\t */\n\t Tone.Transport.prototype.cancel = function (after) {\n\t after = this.defaultArg(after, 0);\n\t after = this.toTicks(after);\n\t this._timeline.cancel(after);\n\t this._onceEvents.cancel(after);\n\t this._repeatedEvents.cancel(after);\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////////\n\t //\tSTART/STOP/PAUSE\n\t ///////////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Bind start/stop/pause events from the clock and emit them.\n\t\t */\n\t Tone.Transport.prototype._bindClockEvents = function () {\n\t this._clock.on('start', function (time, offset) {\n\t offset = Tone.Time(this._clock.ticks, 'i').toSeconds();\n\t this.emit('start', time, offset);\n\t }.bind(this));\n\t this._clock.on('stop', function (time) {\n\t this.emit('stop', time);\n\t }.bind(this));\n\t this._clock.on('pause', function (time) {\n\t this.emit('pause', time);\n\t }.bind(this));\n\t };\n\t /**\n\t\t * Returns the playback state of the source, either \"started\", \"stopped\", or \"paused\"\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.Transport#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'state', {\n\t get: function () {\n\t return this._clock.getStateAtTime(this.now());\n\t }\n\t });\n\t /**\n\t\t * Start the transport and all sources synced to the transport.\n\t\t * @param {Time} [time=now] The time when the transport should start.\n\t\t * @param {TransportTime=} offset The timeline offset to start the transport.\n\t\t * @returns {Tone.Transport} this\n\t\t * @example\n\t\t * //start the transport in one second starting at beginning of the 5th measure. \n\t\t * Tone.Transport.start(\"+1\", \"4:0:0\");\n\t\t */\n\t Tone.Transport.prototype.start = function (time, offset) {\n\t //start the clock\n\t if (!this.isUndef(offset)) {\n\t offset = this.toTicks(offset);\n\t }\n\t this._clock.start(time, offset);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the transport and all sources synced to the transport.\n\t\t * @param {Time} [time=now] The time when the transport should stop. \n\t\t * @returns {Tone.Transport} this\n\t\t * @example\n\t\t * Tone.Transport.stop();\n\t\t */\n\t Tone.Transport.prototype.stop = function (time) {\n\t this._clock.stop(time);\n\t return this;\n\t };\n\t /**\n\t\t * Pause the transport and all sources synced to the transport.\n\t\t * @param {Time} [time=now]\n\t\t * @returns {Tone.Transport} this\n\t\t */\n\t Tone.Transport.prototype.pause = function (time) {\n\t this._clock.pause(time);\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////////\n\t //\tSETTERS/GETTERS\n\t ///////////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * The time signature as just the numerator over 4. \n\t\t * For example 4/4 would be just 4 and 6/8 would be 3.\n\t\t * @memberOf Tone.Transport#\n\t\t * @type {Number|Array}\n\t\t * @name timeSignature\n\t\t * @example\n\t\t * //common time\n\t\t * Tone.Transport.timeSignature = 4;\n\t\t * // 7/8\n\t\t * Tone.Transport.timeSignature = [7, 8];\n\t\t * //this will be reduced to a single number\n\t\t * Tone.Transport.timeSignature; //returns 3.5\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'timeSignature', {\n\t get: function () {\n\t return this._timeSignature;\n\t },\n\t set: function (timeSig) {\n\t if (this.isArray(timeSig)) {\n\t timeSig = timeSig[0] / timeSig[1] * 4;\n\t }\n\t this._timeSignature = timeSig;\n\t }\n\t });\n\t /**\n\t\t * When the Tone.Transport.loop = true, this is the starting position of the loop.\n\t\t * @memberOf Tone.Transport#\n\t\t * @type {TransportTime}\n\t\t * @name loopStart\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'loopStart', {\n\t get: function () {\n\t return Tone.TransportTime(this._loopStart, 'i').toSeconds();\n\t },\n\t set: function (startPosition) {\n\t this._loopStart = this.toTicks(startPosition);\n\t }\n\t });\n\t /**\n\t\t * When the Tone.Transport.loop = true, this is the ending position of the loop.\n\t\t * @memberOf Tone.Transport#\n\t\t * @type {TransportTime}\n\t\t * @name loopEnd\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'loopEnd', {\n\t get: function () {\n\t return Tone.TransportTime(this._loopEnd, 'i').toSeconds();\n\t },\n\t set: function (endPosition) {\n\t this._loopEnd = this.toTicks(endPosition);\n\t }\n\t });\n\t /**\n\t\t * Set the loop start and stop at the same time. \n\t\t * @param {TransportTime} startPosition \n\t\t * @param {TransportTime} endPosition \n\t\t * @returns {Tone.Transport} this\n\t\t * @example\n\t\t * //loop over the first measure\n\t\t * Tone.Transport.setLoopPoints(0, \"1m\");\n\t\t * Tone.Transport.loop = true;\n\t\t */\n\t Tone.Transport.prototype.setLoopPoints = function (startPosition, endPosition) {\n\t this.loopStart = startPosition;\n\t this.loopEnd = endPosition;\n\t return this;\n\t };\n\t /**\n\t\t * The swing value. Between 0-1 where 1 equal to \n\t\t * the note + half the subdivision.\n\t\t * @memberOf Tone.Transport#\n\t\t * @type {NormalRange}\n\t\t * @name swing\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'swing', {\n\t get: function () {\n\t return this._swingAmount;\n\t },\n\t set: function (amount) {\n\t //scale the values to a normal range\n\t this._swingAmount = amount;\n\t }\n\t });\n\t /**\n\t\t * Set the subdivision which the swing will be applied to. \n\t\t * The default value is an 8th note. Value must be less \n\t\t * than a quarter note.\n\t\t * \n\t\t * @memberOf Tone.Transport#\n\t\t * @type {Time}\n\t\t * @name swingSubdivision\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'swingSubdivision', {\n\t get: function () {\n\t return Tone.Time(this._swingTicks, 'i').toNotation();\n\t },\n\t set: function (subdivision) {\n\t this._swingTicks = this.toTicks(subdivision);\n\t }\n\t });\n\t /**\n\t\t * The Transport's position in Bars:Beats:Sixteenths.\n\t\t * Setting the value will jump to that position right away. \n\t\t * @memberOf Tone.Transport#\n\t\t * @type {BarsBeatsSixteenths}\n\t\t * @name position\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'position', {\n\t get: function () {\n\t return Tone.TransportTime(this.ticks, 'i').toBarsBeatsSixteenths();\n\t },\n\t set: function (progress) {\n\t var ticks = this.toTicks(progress);\n\t this.ticks = ticks;\n\t }\n\t });\n\t /**\n\t\t * The Transport's position in seconds\n\t\t * Setting the value will jump to that position right away. \n\t\t * @memberOf Tone.Transport#\n\t\t * @type {Seconds}\n\t\t * @name seconds\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'seconds', {\n\t get: function () {\n\t return Tone.TransportTime(this.ticks, 'i').toSeconds();\n\t },\n\t set: function (progress) {\n\t var ticks = this.toTicks(progress);\n\t this.ticks = ticks;\n\t }\n\t });\n\t /**\n\t\t * The Transport's loop position as a normalized value. Always\n\t\t * returns 0 if the transport if loop is not true. \n\t\t * @memberOf Tone.Transport#\n\t\t * @name progress\n\t\t * @type {NormalRange}\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'progress', {\n\t get: function () {\n\t if (this.loop) {\n\t return (this.ticks - this._loopStart) / (this._loopEnd - this._loopStart);\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The transports current tick position.\n\t\t * \n\t\t * @memberOf Tone.Transport#\n\t\t * @type {Ticks}\n\t\t * @name ticks\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'ticks', {\n\t get: function () {\n\t return this._clock.ticks;\n\t },\n\t set: function (t) {\n\t if (this._clock.ticks !== t) {\n\t var now = this.now();\n\t //stop everything synced to the transport\n\t if (this.state === Tone.State.Started) {\n\t this.emit('stop', now);\n\t this._clock.ticks = t;\n\t //restart it with the new time\n\t this.emit('start', now, this.seconds);\n\t } else {\n\t this._clock.ticks = t;\n\t }\n\t }\n\t }\n\t });\n\t /**\n\t\t * Pulses Per Quarter note. This is the smallest resolution\n\t\t * the Transport timing supports. This should be set once\n\t\t * on initialization and not set again. Changing this value \n\t\t * after other objects have been created can cause problems. \n\t\t * \n\t\t * @memberOf Tone.Transport#\n\t\t * @type {Number}\n\t\t * @name PPQ\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'PPQ', {\n\t get: function () {\n\t return this._ppq;\n\t },\n\t set: function (ppq) {\n\t var bpm = this.bpm.value;\n\t this._ppq = ppq;\n\t this.bpm.value = bpm;\n\t }\n\t });\n\t /**\n\t\t * The hint to the type of playback. Affects tradeoffs between audio \n\t\t * output latency and responsiveness. \n\t\t * \n\t\t * In addition to setting the value in seconds, the latencyHint also\n\t\t * accepts the strings \"interactive\" (prioritizes low latency), \n\t\t * \"playback\" (prioritizes sustained playback), \"balanced\" (balances\n\t\t * latency and performance), and \"fastest\" (lowest latency, might glitch more often). \n\t\t * @memberOf Tone.Transport#\n\t\t * @type {Seconds|String}\n\t\t * @name latencyHint\n\t\t */\n\t Object.defineProperty(Tone.Transport.prototype, 'latencyHint', {\n\t get: function () {\n\t return Tone.Clock.latencyHint;\n\t },\n\t set: function (hint) {\n\t Tone.Clock.latencyHint = hint;\n\t }\n\t });\n\t /**\n\t\t * Convert from BPM to frequency (factoring in PPQ)\n\t\t * @param {BPM} bpm The BPM value to convert to frequency\n\t\t * @return {Frequency} The BPM as a frequency with PPQ factored in.\n\t\t * @private\n\t\t */\n\t Tone.Transport.prototype._fromUnits = function (bpm) {\n\t return 1 / (60 / bpm / this.PPQ);\n\t };\n\t /**\n\t\t * Convert from frequency (with PPQ) into BPM\n\t\t * @param {Frequency} freq The clocks frequency to convert to BPM\n\t\t * @return {BPM} The frequency value as BPM.\n\t\t * @private\n\t\t */\n\t Tone.Transport.prototype._toUnits = function (freq) {\n\t return freq / this.PPQ * 60;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////////\n\t //\tSYNCING\n\t ///////////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Returns the time aligned to the next subdivision\n\t\t * of the Transport. If the Transport is not started,\n\t\t * it will return 0.\n\t\t * Note: this will not work precisely during tempo ramps.\n\t\t * @param {Time} subdivision The subdivision to quantize to\n\t\t * @return {Number} The context time of the next subdivision.\n\t\t * @example\n\t\t * Tone.Transport.start(); //the transport must be started\n\t\t * Tone.Transport.nextSubdivision(\"4n\");\n\t\t */\n\t Tone.Transport.prototype.nextSubdivision = function (subdivision) {\n\t subdivision = this.toSeconds(subdivision);\n\t //if the transport's not started, return 0\n\t var now;\n\t if (this.state === Tone.State.Started) {\n\t now = this._clock._nextTick;\n\t } else {\n\t return 0;\n\t }\n\t var transportPos = Tone.Time(this.ticks, 'i');\n\t var remainingTime = subdivision - transportPos % subdivision;\n\t if (remainingTime === 0) {\n\t remainingTime = subdivision;\n\t }\n\t return now + remainingTime;\n\t };\n\t /**\n\t\t * Attaches the signal to the tempo control signal so that \n\t\t * any changes in the tempo will change the signal in the same\n\t\t * ratio. \n\t\t * \n\t\t * @param {Tone.Signal} signal \n\t\t * @param {number=} ratio Optionally pass in the ratio between\n\t\t * the two signals. Otherwise it will be computed\n\t\t * based on their current values. \n\t\t * @returns {Tone.Transport} this\n\t\t */\n\t Tone.Transport.prototype.syncSignal = function (signal, ratio) {\n\t if (!ratio) {\n\t //get the sync ratio\n\t if (signal._param.value !== 0) {\n\t ratio = signal._param.value / this.bpm._param.value;\n\t } else {\n\t ratio = 0;\n\t }\n\t }\n\t var ratioSignal = new Tone.Gain(ratio);\n\t this.bpm.chain(ratioSignal, signal._param);\n\t this._syncedSignals.push({\n\t 'ratio': ratioSignal,\n\t 'signal': signal,\n\t 'initial': signal._param.value\n\t });\n\t signal._param.value = 0;\n\t return this;\n\t };\n\t /**\n\t\t * Unsyncs a previously synced signal from the transport's control. \n\t\t * See Tone.Transport.syncSignal.\n\t\t * @param {Tone.Signal} signal \n\t\t * @returns {Tone.Transport} this\n\t\t */\n\t Tone.Transport.prototype.unsyncSignal = function (signal) {\n\t for (var i = this._syncedSignals.length - 1; i >= 0; i--) {\n\t var syncedSignal = this._syncedSignals[i];\n\t if (syncedSignal.signal === signal) {\n\t syncedSignal.ratio.dispose();\n\t syncedSignal.signal._param.value = syncedSignal.initial;\n\t this._syncedSignals.splice(i, 1);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Transport} this\n\t\t * @private\n\t\t */\n\t Tone.Transport.prototype.dispose = function () {\n\t Tone.Emitter.prototype.dispose.call(this);\n\t this._clock.dispose();\n\t this._clock = null;\n\t this._writable('bpm');\n\t this.bpm = null;\n\t this._timeline.dispose();\n\t this._timeline = null;\n\t this._onceEvents.dispose();\n\t this._onceEvents = null;\n\t this._repeatedEvents.dispose();\n\t this._repeatedEvents = null;\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////////\n\t //\tINITIALIZATION\n\t ///////////////////////////////////////////////////////////////////////////////\n\t var TransportConstructor = Tone.Transport;\n\t Tone.Transport = new TransportConstructor();\n\t Tone.Context.on('init', function (context) {\n\t if (context.Transport instanceof TransportConstructor) {\n\t Tone.Transport = context.Transport;\n\t } else {\n\t Tone.Transport = new TransportConstructor();\n\t //store the Transport on the context so it can be retrieved later\n\t context.Transport = Tone.Transport;\n\t }\n\t });\n\t return Tone.Transport;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Volume is a simple volume node, useful for creating a volume fader. \n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {Decibels} [volume=0] the initial volume\n\t\t * @example\n\t\t * var vol = new Tone.Volume(-12);\n\t\t * instrument.chain(vol, Tone.Master);\n\t\t */\n\t Tone.Volume = function () {\n\t var options = this.optionsObject(arguments, ['volume'], Tone.Volume.defaults);\n\t /**\n\t\t\t * the output node\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.output = this.input = new Tone.Gain(options.volume, Tone.Type.Decibels);\n\t /**\n\t\t\t * The unmuted volume\n\t\t\t * @type {Decibels}\n\t\t\t * @private\n\t\t\t */\n\t this._unmutedVolume = options.volume;\n\t /**\n\t\t\t * The volume control in decibels. \n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.volume = this.output.gain;\n\t this._readOnly('volume');\n\t //set the mute initially\n\t this.mute = options.mute;\n\t };\n\t Tone.extend(Tone.Volume);\n\t /**\n\t\t * Defaults\n\t\t * @type {Object}\n\t\t * @const\n\t\t * @static\n\t\t */\n\t Tone.Volume.defaults = {\n\t 'volume': 0,\n\t 'mute': false\n\t };\n\t /**\n\t\t * Mute the output. \n\t\t * @memberOf Tone.Volume#\n\t\t * @type {boolean}\n\t\t * @name mute\n\t\t * @example\n\t\t * //mute the output\n\t\t * volume.mute = true;\n\t\t */\n\t Object.defineProperty(Tone.Volume.prototype, 'mute', {\n\t get: function () {\n\t return this.volume.value === -Infinity;\n\t },\n\t set: function (mute) {\n\t if (!this.mute && mute) {\n\t this._unmutedVolume = this.volume.value;\n\t //maybe it should ramp here?\n\t this.volume.value = -Infinity;\n\t } else if (this.mute && !mute) {\n\t this.volume.value = this._unmutedVolume;\n\t }\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Volume} this\n\t\t */\n\t Tone.Volume.prototype.dispose = function () {\n\t this.input.dispose();\n\t Tone.prototype.dispose.call(this);\n\t this._writable('volume');\n\t this.volume.dispose();\n\t this.volume = null;\n\t return this;\n\t };\n\t return Tone.Volume;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A single master output which is connected to the\n\t\t * AudioDestinationNode (aka your speakers). \n\t\t * It provides useful conveniences such as the ability \n\t\t * to set the volume and mute the entire application. \n\t\t * It also gives you the ability to apply master effects to your application. \n\t\t * <br><br>\n\t\t * Like Tone.Transport, A single Tone.Master is created\n\t\t * on initialization and you do not need to explicitly construct one.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @singleton\n\t\t * @example\n\t\t * //the audio will go from the oscillator to the speakers\n\t\t * oscillator.connect(Tone.Master);\n\t\t * //a convenience for connecting to the master output is also provided:\n\t\t * oscillator.toMaster();\n\t\t * //the above two examples are equivalent.\n\t\t */\n\t Tone.Master = function () {\n\t this.createInsOuts(1, 1);\n\t /**\n\t\t\t * The private volume node\n\t\t\t * @type {Tone.Volume}\n\t\t\t * @private\n\t\t\t */\n\t this._volume = this.output = new Tone.Volume();\n\t /**\n\t\t\t * The volume of the master output.\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.volume = this._volume.volume;\n\t this._readOnly('volume');\n\t //connections\n\t this.input.chain(this.output, this.context.destination);\n\t };\n\t Tone.extend(Tone.Master);\n\t /**\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.Master.defaults = {\n\t 'volume': 0,\n\t 'mute': false\n\t };\n\t /**\n\t\t * Mute the output. \n\t\t * @memberOf Tone.Master#\n\t\t * @type {boolean}\n\t\t * @name mute\n\t\t * @example\n\t\t * //mute the output\n\t\t * Tone.Master.mute = true;\n\t\t */\n\t Object.defineProperty(Tone.Master.prototype, 'mute', {\n\t get: function () {\n\t return this._volume.mute;\n\t },\n\t set: function (mute) {\n\t this._volume.mute = mute;\n\t }\n\t });\n\t /**\n\t\t * Add a master effects chain. NOTE: this will disconnect any nodes which were previously \n\t\t * chained in the master effects chain. \n\t\t * @param {AudioNode|Tone...} args All arguments will be connected in a row\n\t\t * and the Master will be routed through it.\n\t\t * @return {Tone.Master} this\n\t\t * @example\n\t\t * //some overall compression to keep the levels in check\n\t\t * var masterCompressor = new Tone.Compressor({\n\t\t * \t\"threshold\" : -6,\n\t\t * \t\"ratio\" : 3,\n\t\t * \t\"attack\" : 0.5,\n\t\t * \t\"release\" : 0.1\n\t\t * });\n\t\t * //give a little boost to the lows\n\t\t * var lowBump = new Tone.Filter(200, \"lowshelf\");\n\t\t * //route everything through the filter \n\t\t * //and compressor before going to the speakers\n\t\t * Tone.Master.chain(lowBump, masterCompressor);\n\t\t */\n\t Tone.Master.prototype.chain = function () {\n\t this.input.disconnect();\n\t this.input.chain.apply(this.input, arguments);\n\t arguments[arguments.length - 1].connect(this.output);\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.Master} this\n\t\t */\n\t Tone.Master.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable('volume');\n\t this._volume.dispose();\n\t this._volume = null;\n\t this.volume = null;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t //\tAUGMENT TONE's PROTOTYPE\n\t ///////////////////////////////////////////////////////////////////////////\n\t /**\n\t\t * Connect 'this' to the master output. Shorthand for this.connect(Tone.Master)\n\t\t * @returns {Tone} this\n\t\t * @example\n\t\t * //connect an oscillator to the master output\n\t\t * var osc = new Tone.Oscillator().toMaster();\n\t\t */\n\t Tone.prototype.toMaster = function () {\n\t this.connect(Tone.Master);\n\t return this;\n\t };\n\t /**\n\t\t * Also augment AudioNode's prototype to include toMaster\n\t\t * as a convenience\n\t\t * @returns {AudioNode} this\n\t\t */\n\t AudioNode.prototype.toMaster = function () {\n\t this.connect(Tone.Master);\n\t return this;\n\t };\n\t /**\n\t\t * initialize the module and listen for new audio contexts\n\t\t */\n\t var MasterConstructor = Tone.Master;\n\t Tone.Master = new MasterConstructor();\n\t Tone.Context.on('init', function (context) {\n\t // if it already exists, just restore it\n\t if (context.Master instanceof MasterConstructor) {\n\t Tone.Master = context.Master;\n\t } else {\n\t Tone.Master = new MasterConstructor();\n\t }\n\t context.Master = Tone.Master;\n\t });\n\t return Tone.Master;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Base class for sources. Sources have start/stop methods\n\t\t * and the ability to be synced to the \n\t\t * start/stop of Tone.Transport. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * //Multiple state change events can be chained together,\n\t\t * //but must be set in the correct order and with ascending times\n\t\t * \n\t\t * // OK\n\t\t * state.start().stop(\"+0.2\");\n\t\t * // AND\n\t\t * state.start().stop(\"+0.2\").start(\"+0.4\").stop(\"+0.7\")\n\t\t *\n\t\t * // BAD\n\t\t * state.stop(\"+0.2\").start();\n\t\t * // OR\n\t\t * state.start(\"+0.3\").stop(\"+0.2\");\n\t\t * \n\t\t */\n\t Tone.Source = function (options) {\n\t // this.createInsOuts(0, 1);\n\t options = this.defaultArg(options, Tone.Source.defaults);\n\t /**\n\t\t\t * The output volume node\n\t\t\t * @type {Tone.Volume}\n\t\t\t * @private\n\t\t\t */\n\t this._volume = this.output = new Tone.Volume(options.volume);\n\t /**\n\t\t\t * The volume of the output in decibels.\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * source.volume.value = -6;\n\t\t\t */\n\t this.volume = this._volume.volume;\n\t this._readOnly('volume');\n\t /**\n\t\t\t * \tKeep track of the scheduled state.\n\t\t\t * @type {Tone.TimelineState}\n\t\t\t * @private\n\t\t\t */\n\t this._state = new Tone.TimelineState(Tone.State.Stopped);\n\t this._state.memory = 10;\n\t /**\n\t\t\t * The synced `start` callback function from the transport\n\t\t\t * @type {Function}\n\t\t\t * @private\n\t\t\t */\n\t this._synced = false;\n\t /**\n\t\t\t * Keep track of all of the scheduled event ids\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._scheduled = [];\n\t //make the output explicitly stereo\n\t this._volume.output.output.channelCount = 2;\n\t this._volume.output.output.channelCountMode = 'explicit';\n\t //mute initially\n\t this.mute = options.mute;\n\t };\n\t Tone.extend(Tone.Source);\n\t /**\n\t\t * The default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Source.defaults = {\n\t 'volume': 0,\n\t 'mute': false\n\t };\n\t /**\n\t\t * Returns the playback state of the source, either \"started\" or \"stopped\".\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.Source#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.Source.prototype, 'state', {\n\t get: function () {\n\t if (this._synced) {\n\t if (Tone.Transport.state === Tone.State.Started) {\n\t return this._state.getValueAtTime(Tone.Transport.seconds);\n\t } else {\n\t return Tone.State.Stopped;\n\t }\n\t } else {\n\t return this._state.getValueAtTime(this.now());\n\t }\n\t }\n\t });\n\t /**\n\t\t * Mute the output. \n\t\t * @memberOf Tone.Source#\n\t\t * @type {boolean}\n\t\t * @name mute\n\t\t * @example\n\t\t * //mute the output\n\t\t * source.mute = true;\n\t\t */\n\t Object.defineProperty(Tone.Source.prototype, 'mute', {\n\t get: function () {\n\t return this._volume.mute;\n\t },\n\t set: function (mute) {\n\t this._volume.mute = mute;\n\t }\n\t });\n\t //overwrite these functions\n\t Tone.Source.prototype._start = Tone.noOp;\n\t Tone.Source.prototype._stop = Tone.noOp;\n\t /**\n\t\t * Start the source at the specified time. If no time is given, \n\t\t * start the source now.\n\t\t * @param {Time} [time=now] When the source should be started.\n\t\t * @returns {Tone.Source} this\n\t\t * @example\n\t\t * source.start(\"+0.5\"); //starts the source 0.5 seconds from now\n\t\t */\n\t Tone.Source.prototype.start = function (time, offset, duration) {\n\t if (this.isUndef(time) && this._synced) {\n\t time = Tone.Transport.seconds;\n\t } else {\n\t time = this.toSeconds(time);\n\t }\n\t //if it's started, stop it and restart it\n\t if (!this.retrigger && this._state.getValueAtTime(time) === Tone.State.Started) {\n\t this.stop(time);\n\t }\n\t this._state.setStateAtTime(Tone.State.Started, time);\n\t if (this._synced) {\n\t // add the offset time to the event\n\t var event = this._state.get(time);\n\t event.offset = this.defaultArg(offset, 0);\n\t event.duration = duration;\n\t var sched = Tone.Transport.schedule(function (t) {\n\t this._start(t, offset, duration);\n\t }.bind(this), time);\n\t this._scheduled.push(sched);\n\t } else {\n\t this._start.apply(this, arguments);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Stop the source at the specified time. If no time is given, \n\t\t * stop the source now.\n\t\t * @param {Time} [time=now] When the source should be stopped. \n\t\t * @returns {Tone.Source} this\n\t\t * @example\n\t\t * source.stop(); // stops the source immediately\n\t\t */\n\t Tone.Source.prototype.stop = function (time) {\n\t if (this.isUndef(time) && this._synced) {\n\t time = Tone.Transport.seconds;\n\t } else {\n\t time = this.toSeconds(time);\n\t }\n\t this._state.cancel(time);\n\t this._state.setStateAtTime(Tone.State.Stopped, time);\n\t if (!this._synced) {\n\t this._stop.apply(this, arguments);\n\t } else {\n\t var sched = Tone.Transport.schedule(this._stop.bind(this), time);\n\t this._scheduled.push(sched);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Sync the source to the Transport so that all subsequent\n\t\t * calls to `start` and `stop` are synced to the TransportTime\n\t\t * instead of the AudioContext time. \n\t\t *\n\t\t * @returns {Tone.Source} this\n\t\t * @example\n\t\t * //sync the source so that it plays between 0 and 0.3 on the Transport's timeline\n\t\t * source.sync().start(0).stop(0.3);\n\t\t * //start the transport.\n\t\t * Tone.Transport.start();\n\t\t *\n\t\t * @example\n\t\t * //start the transport with an offset and the sync'ed sources\n\t\t * //will start in the correct position\n\t\t * source.sync().start(0.1);\n\t\t * //the source will be invoked with an offset of 0.4\n\t\t * Tone.Transport.start(\"+0.5\", 0.5);\n\t\t */\n\t Tone.Source.prototype.sync = function () {\n\t this._synced = true;\n\t Tone.Transport.on('start loopStart', function (time, offset) {\n\t if (offset > 0) {\n\t // get the playback state at that time\n\t var stateEvent = this._state.get(offset);\n\t // listen for start events which may occur in the middle of the sync'ed time\n\t if (stateEvent && stateEvent.state === Tone.State.Started && stateEvent.time !== offset) {\n\t // get the offset\n\t var startOffset = offset - this.toSeconds(stateEvent.time);\n\t var duration;\n\t if (stateEvent.duration) {\n\t duration = this.toSeconds(stateEvent.duration) - startOffset;\n\t }\n\t this._start(time, this.toSeconds(stateEvent.offset) + startOffset, duration);\n\t }\n\t }\n\t }.bind(this));\n\t Tone.Transport.on('stop pause loopEnd', function (time) {\n\t if (this._state.getValueAtTime(Tone.Transport.seconds) === Tone.State.Started) {\n\t this._stop(time);\n\t }\n\t }.bind(this));\n\t return this;\n\t };\n\t /**\n\t\t * Unsync the source to the Transport. See Tone.Source.sync\n\t\t * @returns {Tone.Source} this\n\t\t */\n\t Tone.Source.prototype.unsync = function () {\n\t this._synced = false;\n\t Tone.Transport.off('start stop pause loopEnd loopStart');\n\t // clear all of the scheduled ids\n\t for (var i = 0; i < this._scheduled.length; i++) {\n\t var id = this._scheduled[i];\n\t Tone.Transport.clear(id);\n\t }\n\t this._scheduled = [];\n\t this._state.cancel(0);\n\t return this;\n\t };\n\t /**\n\t\t *\tClean up.\n\t\t * @return {Tone.Source} this\n\t\t */\n\t Tone.Source.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this.unsync();\n\t this._scheduled = null;\n\t this._writable('volume');\n\t this._volume.dispose();\n\t this._volume = null;\n\t this.volume = null;\n\t this._state.dispose();\n\t this._state = null;\n\t };\n\t return Tone.Source;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * OscillatorNode shim\n\t\t * @private\n\t\t */\n\t if (window.OscillatorNode && !OscillatorNode.prototype.start) {\n\t OscillatorNode.prototype.start = OscillatorNode.prototype.noteOn;\n\t OscillatorNode.prototype.stop = OscillatorNode.prototype.noteOff;\n\t if (!OscillatorNode.prototype.setPeriodicWave) {\n\t OscillatorNode.prototype.setPeriodicWave = OscillatorNode.prototype.setWaveTable;\n\t }\n\t if (!AudioContext.prototype.createPeriodicWave) {\n\t AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable;\n\t }\n\t }\n\t /**\n\t\t * @class Tone.Oscillator supports a number of features including\n\t\t * phase rotation, multiple oscillator types (see Tone.Oscillator.type), \n\t\t * and Transport syncing (see Tone.Oscillator.syncFrequency).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Source}\n\t\t * @param {Frequency} [frequency] Starting frequency\n\t\t * @param {string} [type] The oscillator type. Read more about type below.\n\t\t * @example\n\t\t * //make and start a 440hz sine tone\n\t\t * var osc = new Tone.Oscillator(440, \"sine\").toMaster().start();\n\t\t */\n\t Tone.Oscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'type'\n\t ], Tone.Oscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * the main oscillator\n\t\t\t * @type {OscillatorNode}\n\t\t\t * @private\n\t\t\t */\n\t this._oscillator = null;\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune control signal.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);\n\t /**\n\t\t\t * the periodic wave\n\t\t\t * @type {PeriodicWave}\n\t\t\t * @private\n\t\t\t */\n\t this._wave = null;\n\t /**\n\t\t\t * The partials of the oscillator\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._partials = this.defaultArg(options.partials, [1]);\n\t /**\n\t\t\t * the phase of the oscillator\n\t\t\t * between 0 - 360\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._phase = options.phase;\n\t /**\n\t\t\t * the type of the oscillator\n\t\t\t * @type {string}\n\t\t\t * @private\n\t\t\t */\n\t this._type = null;\n\t //setup\n\t this.type = options.type;\n\t this.phase = this._phase;\n\t this._readOnly([\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t };\n\t Tone.extend(Tone.Oscillator, Tone.Source);\n\t /**\n\t\t * the default parameters\n\t\t * @type {Object}\n\t\t */\n\t Tone.Oscillator.defaults = {\n\t 'type': 'sine',\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'phase': 0,\n\t 'partials': []\n\t };\n\t /**\n\t\t * The Oscillator types\n\t\t * @enum {String}\n\t\t */\n\t Tone.Oscillator.Type = {\n\t Sine: 'sine',\n\t Triangle: 'triangle',\n\t Sawtooth: 'sawtooth',\n\t Square: 'square',\n\t Custom: 'custom'\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now] \n\t\t * @private\n\t\t */\n\t Tone.Oscillator.prototype._start = function (time) {\n\t //new oscillator with previous values\n\t this._oscillator = this.context.createOscillator();\n\t this._oscillator.setPeriodicWave(this._wave);\n\t //connect the control signal to the oscillator frequency & detune\n\t this._oscillator.connect(this.output);\n\t this.frequency.connect(this._oscillator.frequency);\n\t this.detune.connect(this._oscillator.detune);\n\t //start the oscillator\n\t this._oscillator.start(this.toSeconds(time));\n\t };\n\t /**\n\t\t * stop the oscillator\n\t\t * @private\n\t\t * @param {Time} [time=now] (optional) timing parameter\n\t\t * @returns {Tone.Oscillator} this\n\t\t */\n\t Tone.Oscillator.prototype._stop = function (time) {\n\t if (this._oscillator) {\n\t this._oscillator.stop(this.toSeconds(time));\n\t this._oscillator = null;\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Sync the signal to the Transport's bpm. Any changes to the transports bpm,\n\t\t * will also affect the oscillators frequency. \n\t\t * @returns {Tone.Oscillator} this\n\t\t * @example\n\t\t * Tone.Transport.bpm.value = 120;\n\t\t * osc.frequency.value = 440;\n\t\t * //the ration between the bpm and the frequency will be maintained\n\t\t * osc.syncFrequency();\n\t\t * Tone.Transport.bpm.value = 240; \n\t\t * // the frequency of the oscillator is doubled to 880\n\t\t */\n\t Tone.Oscillator.prototype.syncFrequency = function () {\n\t Tone.Transport.syncSignal(this.frequency);\n\t return this;\n\t };\n\t /**\n\t\t * Unsync the oscillator's frequency from the Transport. \n\t\t * See Tone.Oscillator.syncFrequency\n\t\t * @returns {Tone.Oscillator} this\n\t\t */\n\t Tone.Oscillator.prototype.unsyncFrequency = function () {\n\t Tone.Transport.unsyncSignal(this.frequency);\n\t return this;\n\t };\n\t /**\n\t\t * The type of the oscillator: either sine, square, triangle, or sawtooth. Also capable of\n\t\t * setting the first x number of partials of the oscillator. For example: \"sine4\" would\n\t\t * set be the first 4 partials of the sine wave and \"triangle8\" would set the first\n\t\t * 8 partials of the triangle wave.\n\t\t * <br><br> \n\t\t * Uses PeriodicWave internally even for native types so that it can set the phase. \n\t\t * PeriodicWave equations are from the \n\t\t * [Webkit Web Audio implementation](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp&sq=package:chromium).\n\t\t * \n\t\t * @memberOf Tone.Oscillator#\n\t\t * @type {string}\n\t\t * @name type\n\t\t * @example\n\t\t * //set it to a square wave\n\t\t * osc.type = \"square\";\n\t\t * @example\n\t\t * //set the first 6 partials of a sawtooth wave\n\t\t * osc.type = \"sawtooth6\";\n\t\t */\n\t Object.defineProperty(Tone.Oscillator.prototype, 'type', {\n\t get: function () {\n\t return this._type;\n\t },\n\t set: function (type) {\n\t var coefs = this._getRealImaginary(type, this._phase);\n\t var periodicWave = this.context.createPeriodicWave(coefs[0], coefs[1]);\n\t this._wave = periodicWave;\n\t if (this._oscillator !== null) {\n\t this._oscillator.setPeriodicWave(this._wave);\n\t }\n\t this._type = type;\n\t }\n\t });\n\t /**\n\t\t * Returns the real and imaginary components based \n\t\t * on the oscillator type.\n\t\t * @returns {Array} [real, imaginary]\n\t\t * @private\n\t\t */\n\t Tone.Oscillator.prototype._getRealImaginary = function (type, phase) {\n\t var fftSize = 4096;\n\t var periodicWaveSize = fftSize / 2;\n\t var real = new Float32Array(periodicWaveSize);\n\t var imag = new Float32Array(periodicWaveSize);\n\t var partialCount = 1;\n\t if (type === Tone.Oscillator.Type.Custom) {\n\t partialCount = this._partials.length + 1;\n\t periodicWaveSize = partialCount;\n\t } else {\n\t var partial = /^(sine|triangle|square|sawtooth)(\\d+)$/.exec(type);\n\t if (partial) {\n\t partialCount = parseInt(partial[2]) + 1;\n\t type = partial[1];\n\t partialCount = Math.max(partialCount, 2);\n\t periodicWaveSize = partialCount;\n\t }\n\t }\n\t for (var n = 1; n < periodicWaveSize; ++n) {\n\t var piFactor = 2 / (n * Math.PI);\n\t var b;\n\t switch (type) {\n\t case Tone.Oscillator.Type.Sine:\n\t b = n <= partialCount ? 1 : 0;\n\t break;\n\t case Tone.Oscillator.Type.Square:\n\t b = n & 1 ? 2 * piFactor : 0;\n\t break;\n\t case Tone.Oscillator.Type.Sawtooth:\n\t b = piFactor * (n & 1 ? 1 : -1);\n\t break;\n\t case Tone.Oscillator.Type.Triangle:\n\t if (n & 1) {\n\t b = 2 * (piFactor * piFactor) * (n - 1 >> 1 & 1 ? -1 : 1);\n\t } else {\n\t b = 0;\n\t }\n\t break;\n\t case Tone.Oscillator.Type.Custom:\n\t b = this._partials[n - 1];\n\t break;\n\t default:\n\t throw new TypeError('Tone.Oscillator: invalid type: ' + type);\n\t }\n\t if (b !== 0) {\n\t real[n] = -b * Math.sin(phase * n);\n\t imag[n] = b * Math.cos(phase * n);\n\t } else {\n\t real[n] = 0;\n\t imag[n] = 0;\n\t }\n\t }\n\t return [\n\t real,\n\t imag\n\t ];\n\t };\n\t /**\n\t\t * Compute the inverse FFT for a given phase.\t\n\t\t * @param {Float32Array} real\n\t\t * @param {Float32Array} imag \n\t\t * @param {NormalRange} phase \n\t\t * @return {AudioRange}\n\t\t * @private\n\t\t */\n\t Tone.Oscillator.prototype._inverseFFT = function (real, imag, phase) {\n\t var sum = 0;\n\t var len = real.length;\n\t for (var i = 0; i < len; i++) {\n\t sum += real[i] * Math.cos(i * phase) + imag[i] * Math.sin(i * phase);\n\t }\n\t return sum;\n\t };\n\t /**\n\t\t * Returns the initial value of the oscillator.\n\t\t * @return {AudioRange}\n\t\t * @private\n\t\t */\n\t Tone.Oscillator.prototype._getInitialValue = function () {\n\t var coefs = this._getRealImaginary(this._type, 0);\n\t var real = coefs[0];\n\t var imag = coefs[1];\n\t var maxValue = 0;\n\t var twoPi = Math.PI * 2;\n\t //check for peaks in 8 places\n\t for (var i = 0; i < 8; i++) {\n\t maxValue = Math.max(this._inverseFFT(real, imag, i / 8 * twoPi), maxValue);\n\t }\n\t return -this._inverseFFT(real, imag, this._phase) / maxValue;\n\t };\n\t /**\n\t\t * The partials of the waveform. A partial represents \n\t\t * the amplitude at a harmonic. The first harmonic is the \n\t\t * fundamental frequency, the second is the octave and so on\n\t\t * following the harmonic series. \n\t\t * Setting this value will automatically set the type to \"custom\". \n\t\t * The value is an empty array when the type is not \"custom\". \n\t\t * @memberOf Tone.Oscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @example\n\t\t * osc.partials = [1, 0.2, 0.01];\n\t\t */\n\t Object.defineProperty(Tone.Oscillator.prototype, 'partials', {\n\t get: function () {\n\t if (this._type !== Tone.Oscillator.Type.Custom) {\n\t return [];\n\t } else {\n\t return this._partials;\n\t }\n\t },\n\t set: function (partials) {\n\t this._partials = partials;\n\t this.type = Tone.Oscillator.Type.Custom;\n\t }\n\t });\n\t /**\n\t\t * The phase of the oscillator in degrees. \n\t\t * @memberOf Tone.Oscillator#\n\t\t * @type {Degrees}\n\t\t * @name phase\n\t\t * @example\n\t\t * osc.phase = 180; //flips the phase of the oscillator\n\t\t */\n\t Object.defineProperty(Tone.Oscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._phase * (180 / Math.PI);\n\t },\n\t set: function (phase) {\n\t this._phase = phase * Math.PI / 180;\n\t //reset the type\n\t this.type = this._type;\n\t }\n\t });\n\t /**\n\t\t * Dispose and disconnect.\n\t\t * @return {Tone.Oscillator} this\n\t\t */\n\t Tone.Oscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t if (this._oscillator !== null) {\n\t this._oscillator.disconnect();\n\t this._oscillator = null;\n\t }\n\t this._wave = null;\n\t this._writable([\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this.detune.dispose();\n\t this.detune = null;\n\t this._partials = null;\n\t return this;\n\t };\n\t return Tone.Oscillator;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.Zero outputs 0's at audio-rate. The reason this has to be\n\t\t * it's own class is that many browsers optimize out Tone.Signal\n\t\t * with a value of 0 and will not process nodes further down the graph. \n\t\t * @extends {Tone}\n\t\t */\n\t Tone.Zero = function () {\n\t /**\n\t\t\t * The gain node\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._gain = this.input = this.output = new Tone.Gain();\n\t this.context.getConstant(0).connect(this._gain);\n\t };\n\t Tone.extend(Tone.Zero);\n\t /**\n\t\t * clean up\n\t\t * @return {Tone.Zero} this\n\t\t */\n\t Tone.Zero.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._gain.dispose();\n\t this._gain = null;\n\t return this;\n\t };\n\t return Tone.Zero;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class LFO stands for low frequency oscillator. Tone.LFO produces an output signal \n\t\t * which can be attached to an AudioParam or Tone.Signal \n\t\t * in order to modulate that parameter with an oscillator. The LFO can \n\t\t * also be synced to the transport to start/stop and change when the tempo changes.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Oscillator}\n\t\t * @param {Frequency|Object} [frequency] The frequency of the oscillation. Typically, LFOs will be\n\t\t * in the frequency range of 0.1 to 10 hertz. \n\t\t * @param {number=} min The minimum output value of the LFO. \n\t\t * @param {number=} max The maximum value of the LFO. \n\t\t * @example\n\t\t * var lfo = new Tone.LFO(\"4n\", 400, 4000);\n\t\t * lfo.connect(filter.frequency);\n\t\t */\n\t Tone.LFO = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'min',\n\t 'max'\n\t ], Tone.LFO.defaults);\n\t /** \n\t\t\t * The oscillator. \n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._oscillator = new Tone.Oscillator({\n\t 'frequency': options.frequency,\n\t 'type': options.type\n\t });\n\t /**\n\t\t\t * the lfo's frequency\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._oscillator.frequency;\n\t /**\n\t\t\t * The amplitude of the LFO, which controls the output range between\n\t\t\t * the min and max output. For example if the min is -10 and the max \n\t\t\t * is 10, setting the amplitude to 0.5 would make the LFO modulate\n\t\t\t * between -5 and 5. \n\t\t\t * @type {Number}\n\t\t\t * @signal\n\t\t\t */\n\t this.amplitude = this._oscillator.volume;\n\t this.amplitude.units = Tone.Type.NormalRange;\n\t this.amplitude.value = options.amplitude;\n\t /**\n\t\t\t * The signal which is output when the LFO is stopped\n\t\t\t * @type {Tone.Signal}\n\t\t\t * @private\n\t\t\t */\n\t this._stoppedSignal = new Tone.Signal(0, Tone.Type.AudioRange);\n\t /**\n\t\t\t * Just outputs zeros.\n\t\t\t * @type {Tone.Zero}\n\t\t\t * @private\n\t\t\t */\n\t this._zeros = new Tone.Zero();\n\t /**\n\t\t\t * The value that the LFO outputs when it's stopped\n\t\t\t * @type {AudioRange}\n\t\t\t * @private\n\t\t\t */\n\t this._stoppedValue = 0;\n\t /**\n\t\t\t * @type {Tone.AudioToGain} \n\t\t\t * @private\n\t\t\t */\n\t this._a2g = new Tone.AudioToGain();\n\t /**\n\t\t\t * @type {Tone.Scale} \n\t\t\t * @private\n\t\t\t */\n\t this._scaler = this.output = new Tone.Scale(options.min, options.max);\n\t /**\n\t\t\t * the units of the LFO (used for converting)\n\t\t\t * @type {Tone.Type} \n\t\t\t * @private\n\t\t\t */\n\t this._units = Tone.Type.Default;\n\t this.units = options.units;\n\t //connect it up\n\t this._oscillator.chain(this._a2g, this._scaler);\n\t this._zeros.connect(this._a2g);\n\t this._stoppedSignal.connect(this._a2g);\n\t this._readOnly([\n\t 'amplitude',\n\t 'frequency'\n\t ]);\n\t this.phase = options.phase;\n\t };\n\t Tone.extend(Tone.LFO, Tone.Oscillator);\n\t /**\n\t\t * the default parameters\n\t\t *\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.LFO.defaults = {\n\t 'type': 'sine',\n\t 'min': 0,\n\t 'max': 1,\n\t 'phase': 0,\n\t 'frequency': '4n',\n\t 'amplitude': 1,\n\t 'units': Tone.Type.Default\n\t };\n\t /**\n\t\t * Start the LFO. \n\t\t * @param {Time} [time=now] the time the LFO will start\n\t\t * @returns {Tone.LFO} this\n\t\t */\n\t Tone.LFO.prototype.start = function (time) {\n\t time = this.toSeconds(time);\n\t this._stoppedSignal.setValueAtTime(0, time);\n\t this._oscillator.start(time);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the LFO. \n\t\t * @param {Time} [time=now] the time the LFO will stop\n\t\t * @returns {Tone.LFO} this\n\t\t */\n\t Tone.LFO.prototype.stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._stoppedSignal.setValueAtTime(this._stoppedValue, time);\n\t this._oscillator.stop(time);\n\t return this;\n\t };\n\t /**\n\t\t * Sync the start/stop/pause to the transport \n\t\t * and the frequency to the bpm of the transport\n\t\t * @returns {Tone.LFO} this\n\t\t * @example\n\t\t * lfo.frequency.value = \"8n\";\n\t\t * lfo.sync().start(0)\n\t\t * //the rate of the LFO will always be an eighth note, \n\t\t * //even as the tempo changes\n\t\t */\n\t Tone.LFO.prototype.sync = function () {\n\t this._oscillator.sync();\n\t this._oscillator.syncFrequency();\n\t return this;\n\t };\n\t /**\n\t\t * unsync the LFO from transport control\n\t\t * @returns {Tone.LFO} this\n\t\t */\n\t Tone.LFO.prototype.unsync = function () {\n\t this._oscillator.unsync();\n\t this._oscillator.unsyncFrequency();\n\t return this;\n\t };\n\t /**\n\t\t * The miniumum output of the LFO.\n\t\t * @memberOf Tone.LFO#\n\t\t * @type {number}\n\t\t * @name min\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'min', {\n\t get: function () {\n\t return this._toUnits(this._scaler.min);\n\t },\n\t set: function (min) {\n\t min = this._fromUnits(min);\n\t this._scaler.min = min;\n\t }\n\t });\n\t /**\n\t\t * The maximum output of the LFO.\n\t\t * @memberOf Tone.LFO#\n\t\t * @type {number}\n\t\t * @name max\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'max', {\n\t get: function () {\n\t return this._toUnits(this._scaler.max);\n\t },\n\t set: function (max) {\n\t max = this._fromUnits(max);\n\t this._scaler.max = max;\n\t }\n\t });\n\t /**\n\t\t * The type of the oscillator: sine, square, sawtooth, triangle. \n\t\t * @memberOf Tone.LFO#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'type', {\n\t get: function () {\n\t return this._oscillator.type;\n\t },\n\t set: function (type) {\n\t this._oscillator.type = type;\n\t this._stoppedValue = this._oscillator._getInitialValue();\n\t this._stoppedSignal.value = this._stoppedValue;\n\t }\n\t });\n\t /**\n\t\t * The phase of the LFO.\n\t\t * @memberOf Tone.LFO#\n\t\t * @type {number}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'phase', {\n\t get: function () {\n\t return this._oscillator.phase;\n\t },\n\t set: function (phase) {\n\t this._oscillator.phase = phase;\n\t this._stoppedValue = this._oscillator._getInitialValue();\n\t this._stoppedSignal.value = this._stoppedValue;\n\t }\n\t });\n\t /**\n\t\t * The output units of the LFO.\n\t\t * @memberOf Tone.LFO#\n\t\t * @type {Tone.Type}\n\t\t * @name units\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'units', {\n\t get: function () {\n\t return this._units;\n\t },\n\t set: function (val) {\n\t var currentMin = this.min;\n\t var currentMax = this.max;\n\t //convert the min and the max\n\t this._units = val;\n\t this.min = currentMin;\n\t this.max = currentMax;\n\t }\n\t });\n\t /**\n\t\t * Mute the output. \n\t\t * @memberOf Tone.LFO#\n\t\t * @type {Boolean}\n\t\t * @name mute\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'mute', {\n\t get: function () {\n\t return this._oscillator.mute;\n\t },\n\t set: function (mute) {\n\t this._oscillator.mute = mute;\n\t }\n\t });\n\t /**\n\t\t * Returns the playback state of the source, either \"started\" or \"stopped\".\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.LFO#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.LFO.prototype, 'state', {\n\t get: function () {\n\t return this._oscillator.state;\n\t }\n\t });\n\t /**\n\t\t * Connect the output of the LFO to an AudioParam, AudioNode, or Tone Node. \n\t\t * Tone.LFO will automatically convert to the destination units of the \n\t\t * will get the units from the connected node.\n\t\t * @param {Tone | AudioParam | AudioNode} node \n\t\t * @param {number} [outputNum=0] optionally which output to connect from\n\t\t * @param {number} [inputNum=0] optionally which input to connect to\n\t\t * @returns {Tone.LFO} this\n\t\t * @private\n\t\t */\n\t Tone.LFO.prototype.connect = function (node) {\n\t if (node.constructor === Tone.Signal || node.constructor === Tone.Param || node.constructor === Tone.TimelineSignal) {\n\t this.convert = node.convert;\n\t this.units = node.units;\n\t }\n\t Tone.Signal.prototype.connect.apply(this, arguments);\n\t return this;\n\t };\n\t /**\n\t\t * private method borrowed from Param converts \n\t\t * units from their destination value\n\t\t * @function\n\t\t * @private\n\t\t */\n\t Tone.LFO.prototype._fromUnits = Tone.Param.prototype._fromUnits;\n\t /**\n\t\t * private method borrowed from Param converts \n\t\t * units to their destination value\n\t\t * @function\n\t\t * @private\n\t\t */\n\t Tone.LFO.prototype._toUnits = Tone.Param.prototype._toUnits;\n\t /**\n\t\t * disconnect and dispose\n\t\t * @returns {Tone.LFO} this\n\t\t */\n\t Tone.LFO.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'amplitude',\n\t 'frequency'\n\t ]);\n\t this._oscillator.dispose();\n\t this._oscillator = null;\n\t this._stoppedSignal.dispose();\n\t this._stoppedSignal = null;\n\t this._zeros.dispose();\n\t this._zeros = null;\n\t this._scaler.dispose();\n\t this._scaler = null;\n\t this._a2g.dispose();\n\t this._a2g = null;\n\t this.frequency = null;\n\t this.amplitude = null;\n\t return this;\n\t };\n\t return Tone.LFO;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Limiter will limit the loudness of an incoming signal. \n\t\t * It is composed of a Tone.Compressor with a fast attack \n\t\t * and release. Limiters are commonly used to safeguard against \n\t\t * signal clipping. Unlike a compressor, limiters do not provide \n\t\t * smooth gain reduction and almost completely prevent \n\t\t * additional gain above the threshold.\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {number} threshold The theshold above which the limiting is applied. \n\t\t * @example\n\t\t * var limiter = new Tone.Limiter(-6);\n\t\t */\n\t Tone.Limiter = function () {\n\t var options = this.optionsObject(arguments, ['threshold'], Tone.Limiter.defaults);\n\t /**\n\t\t\t * the compressor\n\t\t\t * @private\n\t\t\t * @type {Tone.Compressor}\n\t\t\t */\n\t this._compressor = this.input = this.output = new Tone.Compressor({\n\t 'attack': 0.001,\n\t 'decay': 0.001,\n\t 'threshold': options.threshold\n\t });\n\t /**\n\t\t\t * The threshold of of the limiter\n\t\t\t * @type {Decibel}\n\t\t\t * @signal\n\t\t\t */\n\t this.threshold = this._compressor.threshold;\n\t this._readOnly('threshold');\n\t };\n\t Tone.extend(Tone.Limiter);\n\t /**\n\t\t * The default value\n\t\t * @type {Object}\n\t\t * @const\n\t\t * @static\n\t\t */\n\t Tone.Limiter.defaults = { 'threshold': -12 };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Limiter} this\n\t\t */\n\t Tone.Limiter.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._compressor.dispose();\n\t this._compressor = null;\n\t this._writable('threshold');\n\t this.threshold = null;\n\t return this;\n\t };\n\t return Tone.Limiter;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Lowpass is a lowpass feedback comb filter. It is similar to \n\t\t * Tone.FeedbackCombFilter, but includes a lowpass filter.\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {Time|Object} [delayTime] The delay time of the comb filter\n\t\t * @param {NormalRange=} resonance The resonance (feedback) of the comb filter\n\t\t * @param {Frequency=} dampening The cutoff of the lowpass filter dampens the\n\t\t * signal as it is fedback. \n\t\t */\n\t Tone.LowpassCombFilter = function () {\n\t this.createInsOuts(1, 1);\n\t var options = this.optionsObject(arguments, [\n\t 'delayTime',\n\t 'resonance',\n\t 'dampening'\n\t ], Tone.LowpassCombFilter.defaults);\n\t /**\n\t\t\t * the delay node\n\t\t\t * @type {DelayNode}\n\t\t\t * @private\n\t\t\t */\n\t this._delay = this.input = new Tone.Delay(options.delayTime);\n\t /**\n\t\t\t * The delayTime of the comb filter. \n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.delayTime = this._delay.delayTime;\n\t /**\n\t\t\t * the lowpass filter\n\t\t\t * @type {BiquadFilterNode}\n\t\t\t * @private\n\t\t\t */\n\t this._lowpass = this.output = this.context.createBiquadFilter();\n\t this._lowpass.Q.value = -3.0102999566398125;\n\t this._lowpass.type = 'lowpass';\n\t /**\n\t\t\t * The dampening control of the feedback\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.dampening = new Tone.Param({\n\t 'param': this._lowpass.frequency,\n\t 'units': Tone.Type.Frequency,\n\t 'value': options.dampening\n\t });\n\t /**\n\t\t\t * the feedback gain\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._feedback = new Tone.Gain(options.resonance, Tone.Type.NormalRange);\n\t /**\n\t\t\t * The amount of feedback of the delayed signal. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.resonance = this._feedback.gain;\n\t //connections\n\t this._delay.chain(this._lowpass, this._feedback, this._delay);\n\t this._readOnly([\n\t 'dampening',\n\t 'resonance',\n\t 'delayTime'\n\t ]);\n\t };\n\t Tone.extend(Tone.LowpassCombFilter);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.LowpassCombFilter.defaults = {\n\t 'delayTime': 0.1,\n\t 'resonance': 0.5,\n\t 'dampening': 3000\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.LowpassCombFilter} this\n\t\t */\n\t Tone.LowpassCombFilter.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'dampening',\n\t 'resonance',\n\t 'delayTime'\n\t ]);\n\t this.dampening.dispose();\n\t this.dampening = null;\n\t this.resonance.dispose();\n\t this.resonance = null;\n\t this._delay.dispose();\n\t this._delay = null;\n\t this.delayTime = null;\n\t this._lowpass.disconnect();\n\t this._lowpass = null;\n\t this._feedback.disconnect();\n\t this._feedback = null;\n\t return this;\n\t };\n\t return Tone.LowpassCombFilter;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Merge brings two signals into the left and right \n\t\t * channels of a single stereo channel.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * var merge = new Tone.Merge().toMaster();\n\t\t * //routing a sine tone in the left channel\n\t\t * //and noise in the right channel\n\t\t * var osc = new Tone.Oscillator().connect(merge.left);\n\t\t * var noise = new Tone.Noise().connect(merge.right);\n\t\t * //starting our oscillators\n\t\t * noise.start();\n\t\t * osc.start();\n\t\t */\n\t Tone.Merge = function () {\n\t this.createInsOuts(2, 0);\n\t /**\n\t\t\t * The left input channel.\n\t\t\t * Alias for <code>input[0]</code>\n\t\t\t * @type {GainNode}\n\t\t\t */\n\t this.left = this.input[0] = new Tone.Gain();\n\t /**\n\t\t\t * The right input channel.\n\t\t\t * Alias for <code>input[1]</code>.\n\t\t\t * @type {GainNode}\n\t\t\t */\n\t this.right = this.input[1] = new Tone.Gain();\n\t /**\n\t\t\t * the merger node for the two channels\n\t\t\t * @type {ChannelMergerNode}\n\t\t\t * @private\n\t\t\t */\n\t this._merger = this.output = this.context.createChannelMerger(2);\n\t //connections\n\t this.left.connect(this._merger, 0, 0);\n\t this.right.connect(this._merger, 0, 1);\n\t this.left.channelCount = 1;\n\t this.right.channelCount = 1;\n\t this.left.channelCountMode = 'explicit';\n\t this.right.channelCountMode = 'explicit';\n\t };\n\t Tone.extend(Tone.Merge);\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Merge} this\n\t\t */\n\t Tone.Merge.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this.left.dispose();\n\t this.left = null;\n\t this.right.dispose();\n\t this.right = null;\n\t this._merger.disconnect();\n\t this._merger = null;\n\t return this;\n\t };\n\t return Tone.Merge;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Meter gets the [RMS](https://en.wikipedia.org/wiki/Root_mean_square)\n\t\t * of an input signal with some averaging applied. It can also get the raw \n\t\t * value of the input signal.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {String} type Either \"level\" or \"signal\". \n\t\t * @param {Number} smoothing The amount of smoothing applied between frames.\n\t\t * @example\n\t\t * var meter = new Tone.Meter();\n\t\t * var mic = new Tone.UserMedia().start();\n\t\t * //connect mic to the meter\n\t\t * mic.connect(meter);\n\t\t * //the current level of the mic input\n\t\t * var level = meter.value;\n\t\t */\n\t Tone.Meter = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'type',\n\t 'smoothing'\n\t ], Tone.Meter.defaults);\n\t /**\n\t\t\t * The type of the meter, either \"level\" or \"signal\". \n\t\t\t * A \"level\" meter will return the volume level (rms) of the \n\t\t\t * input signal and a \"signal\" meter will return\n\t\t\t * the signal value of the input. \n\t\t\t * @type {String}\n\t\t\t */\n\t this.type = options.type;\n\t /**\n\t\t\t * The analyser node which computes the levels.\n\t\t\t * @private\n\t\t\t * @type {Tone.Analyser}\n\t\t\t */\n\t this.input = this.output = this._analyser = new Tone.Analyser('waveform', 512);\n\t this._analyser.returnType = 'float';\n\t /**\n\t\t\t * The amount of carryover between the current and last frame. \n\t\t\t * Only applied meter for \"level\" type.\n\t\t\t * @type {Number}\n\t\t\t */\n\t this.smoothing = options.smoothing;\n\t /**\n\t\t\t * The last computed value\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._lastValue = 0;\n\t };\n\t Tone.extend(Tone.Meter);\n\t /**\n\t\t * @private\n\t\t * @enum {String}\n\t\t */\n\t Tone.Meter.Type = {\n\t Level: 'level',\n\t Signal: 'signal'\n\t };\n\t /**\n\t\t * The defaults\n\t\t * @type {Object}\n\t\t * @static\n\t\t * @const\n\t\t */\n\t Tone.Meter.defaults = {\n\t 'smoothing': 0.8,\n\t 'type': Tone.Meter.Type.Level\n\t };\n\t /**\n\t\t * The current value of the meter. A value of 1 is\n\t\t * \"unity\".\n\t\t * @memberOf Tone.Meter#\n\t\t * @type {Number}\n\t\t * @name value\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Meter.prototype, 'value', {\n\t get: function () {\n\t var signal = this._analyser.analyse();\n\t if (this.type === Tone.Meter.Type.Level) {\n\t //rms\n\t var sum = 0;\n\t for (var i = 0; i < signal.length; i++) {\n\t sum += Math.pow(signal[i], 2);\n\t }\n\t var rms = Math.sqrt(sum / signal.length);\n\t //smooth it\n\t rms = Math.max(rms, this._lastValue * this.smoothing);\n\t this._lastValue = rms;\n\t //scale it\n\t var unity = 0.35;\n\t var val = rms / unity;\n\t //scale the output curve\n\t return Math.sqrt(val);\n\t } else {\n\t return signal[0];\n\t }\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Meter} this\n\t\t */\n\t Tone.Meter.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._analyser.dispose();\n\t this._analyser = null;\n\t return this;\n\t };\n\t return Tone.Meter;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t *\t@class Tone.Split splits an incoming signal into left and right channels.\n\t\t *\t\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * var split = new Tone.Split();\n\t\t * stereoSignal.connect(split);\n\t\t */\n\t Tone.Split = function () {\n\t this.createInsOuts(0, 2);\n\t /** \n\t\t\t * @type {ChannelSplitterNode}\n\t\t\t * @private\n\t\t\t */\n\t this._splitter = this.input = this.context.createChannelSplitter(2);\n\t /** \n\t\t\t * Left channel output. \n\t\t\t * Alias for <code>output[0]</code>\n\t\t\t * @type {Tone.Gain}\n\t\t\t */\n\t this.left = this.output[0] = new Tone.Gain();\n\t /**\n\t\t\t * Right channel output.\n\t\t\t * Alias for <code>output[1]</code>\n\t\t\t * @type {Tone.Gain}\n\t\t\t */\n\t this.right = this.output[1] = new Tone.Gain();\n\t //connections\n\t this._splitter.connect(this.left, 0, 0);\n\t this._splitter.connect(this.right, 1, 0);\n\t };\n\t Tone.extend(Tone.Split);\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Split} this\n\t\t */\n\t Tone.Split.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._splitter.disconnect();\n\t this.left.dispose();\n\t this.left = null;\n\t this.right.dispose();\n\t this.right = null;\n\t this._splitter = null;\n\t return this;\n\t };\n\t return Tone.Split;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Mid/Side processing separates the the 'mid' signal \n\t\t * (which comes out of both the left and the right channel) \n\t\t * and the 'side' (which only comes out of the the side channels). <br><br>\n\t\t * <code>\n\t\t * Mid = (Left+Right)/sqrt(2); // obtain mid-signal from left and right<br>\n\t\t * Side = (Left-Right)/sqrt(2); // obtain side-signal from left and righ<br>\n\t\t * </code>\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t */\n\t Tone.MidSideSplit = function () {\n\t this.createInsOuts(0, 2);\n\t /**\n\t\t\t * split the incoming signal into left and right channels\n\t\t\t * @type {Tone.Split}\n\t\t\t * @private\n\t\t\t */\n\t this._split = this.input = new Tone.Split();\n\t /**\n\t\t\t * The mid send. Connect to mid processing. Alias for\n\t\t\t * <code>output[0]</code>\n\t\t\t * @type {Tone.Expr}\n\t\t\t */\n\t this.mid = this.output[0] = new Tone.Expr('($0 + $1) * $2');\n\t /**\n\t\t\t * The side output. Connect to side processing. Alias for\n\t\t\t * <code>output[1]</code>\n\t\t\t * @type {Tone.Expr}\n\t\t\t */\n\t this.side = this.output[1] = new Tone.Expr('($0 - $1) * $2');\n\t this._split.connect(this.mid, 0, 0);\n\t this._split.connect(this.mid, 1, 1);\n\t this._split.connect(this.side, 0, 0);\n\t this._split.connect(this.side, 1, 1);\n\t this.context.getConstant(Math.SQRT1_2).connect(this.mid, 0, 2);\n\t this.context.getConstant(Math.SQRT1_2).connect(this.side, 0, 2);\n\t };\n\t Tone.extend(Tone.MidSideSplit);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.MidSideSplit} this\n\t\t */\n\t Tone.MidSideSplit.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this.mid.dispose();\n\t this.mid = null;\n\t this.side.dispose();\n\t this.side = null;\n\t this._split.dispose();\n\t this._split = null;\n\t return this;\n\t };\n\t return Tone.MidSideSplit;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Mid/Side processing separates the the 'mid' signal \n\t\t * (which comes out of both the left and the right channel) \n\t\t * and the 'side' (which only comes out of the the side channels). \n\t\t * MidSideMerge merges the mid and side signal after they've been seperated\n\t\t * by Tone.MidSideSplit.<br><br>\n\t\t * <code>\n\t\t * Left = (Mid+Side)/sqrt(2); // obtain left signal from mid and side<br>\n\t\t * Right = (Mid-Side)/sqrt(2); // obtain right signal from mid and side<br>\n\t\t * </code>\n\t\t *\n\t\t * @extends {Tone.StereoEffect}\n\t\t * @constructor\n\t\t */\n\t Tone.MidSideMerge = function () {\n\t this.createInsOuts(2, 0);\n\t /**\n\t\t\t * The mid signal input. Alias for\n\t\t\t * <code>input[0]</code>\n\t\t\t * @type {Tone.Gain}\n\t\t\t */\n\t this.mid = this.input[0] = new Tone.Gain();\n\t /**\n\t\t\t * recombine the mid/side into Left\n\t\t\t * @type {Tone.Expr}\n\t\t\t * @private\n\t\t\t */\n\t this._left = new Tone.Expr('($0 + $1) * $2');\n\t /**\n\t\t\t * The side signal input. Alias for\n\t\t\t * <code>input[1]</code>\n\t\t\t * @type {Tone.Gain}\n\t\t\t */\n\t this.side = this.input[1] = new Tone.Gain();\n\t /**\n\t\t\t * recombine the mid/side into Right\n\t\t\t * @type {Tone.Expr}\n\t\t\t * @private\n\t\t\t */\n\t this._right = new Tone.Expr('($0 - $1) * $2');\n\t /**\n\t\t\t * Merge the left/right signal back into a stereo signal.\n\t\t\t * @type {Tone.Merge}\n\t\t\t * @private\n\t\t\t */\n\t this._merge = this.output = new Tone.Merge();\n\t this.mid.connect(this._left, 0, 0);\n\t this.side.connect(this._left, 0, 1);\n\t this.mid.connect(this._right, 0, 0);\n\t this.side.connect(this._right, 0, 1);\n\t this._left.connect(this._merge, 0, 0);\n\t this._right.connect(this._merge, 0, 1);\n\t this.context.getConstant(Math.SQRT1_2).connect(this._left, 0, 2);\n\t this.context.getConstant(Math.SQRT1_2).connect(this._right, 0, 2);\n\t };\n\t Tone.extend(Tone.MidSideMerge);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.MidSideMerge} this\n\t\t */\n\t Tone.MidSideMerge.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this.mid.dispose();\n\t this.mid = null;\n\t this.side.dispose();\n\t this.side = null;\n\t this._left.dispose();\n\t this._left = null;\n\t this._right.dispose();\n\t this._right = null;\n\t this._merge.dispose();\n\t this._merge = null;\n\t return this;\n\t };\n\t return Tone.MidSideMerge;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.MidSideCompressor applies two different compressors to the mid\n\t\t * and side signal components. See Tone.MidSideSplit. \n\t\t *\n\t\t * @extends {Tone}\n\t\t * @param {Object} options The options that are passed to the mid and side\n\t\t * compressors. \n\t\t * @constructor\n\t\t */\n\t Tone.MidSideCompressor = function (options) {\n\t options = this.defaultArg(options, Tone.MidSideCompressor.defaults);\n\t /**\n\t\t\t * the mid/side split\n\t\t\t * @type {Tone.MidSideSplit}\n\t\t\t * @private\n\t\t\t */\n\t this._midSideSplit = this.input = new Tone.MidSideSplit();\n\t /**\n\t\t\t * the mid/side recombination\n\t\t\t * @type {Tone.MidSideMerge}\n\t\t\t * @private\n\t\t\t */\n\t this._midSideMerge = this.output = new Tone.MidSideMerge();\n\t /**\n\t\t\t * The compressor applied to the mid signal\n\t\t\t * @type {Tone.Compressor}\n\t\t\t */\n\t this.mid = new Tone.Compressor(options.mid);\n\t /**\n\t\t\t * The compressor applied to the side signal\n\t\t\t * @type {Tone.Compressor}\n\t\t\t */\n\t this.side = new Tone.Compressor(options.side);\n\t this._midSideSplit.mid.chain(this.mid, this._midSideMerge.mid);\n\t this._midSideSplit.side.chain(this.side, this._midSideMerge.side);\n\t this._readOnly([\n\t 'mid',\n\t 'side'\n\t ]);\n\t };\n\t Tone.extend(Tone.MidSideCompressor);\n\t /**\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.MidSideCompressor.defaults = {\n\t 'mid': {\n\t 'ratio': 3,\n\t 'threshold': -24,\n\t 'release': 0.03,\n\t 'attack': 0.02,\n\t 'knee': 16\n\t },\n\t 'side': {\n\t 'ratio': 6,\n\t 'threshold': -30,\n\t 'release': 0.25,\n\t 'attack': 0.03,\n\t 'knee': 10\n\t }\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.MidSideCompressor} this\n\t\t */\n\t Tone.MidSideCompressor.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'mid',\n\t 'side'\n\t ]);\n\t this.mid.dispose();\n\t this.mid = null;\n\t this.side.dispose();\n\t this.side = null;\n\t this._midSideSplit.dispose();\n\t this._midSideSplit = null;\n\t this._midSideMerge.dispose();\n\t this._midSideMerge = null;\n\t return this;\n\t };\n\t return Tone.MidSideCompressor;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Mono coerces the incoming mono or stereo signal into a mono signal\n\t\t * where both left and right channels have the same value. This can be useful \n\t\t * for [stereo imaging](https://en.wikipedia.org/wiki/Stereo_imaging).\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t */\n\t Tone.Mono = function () {\n\t this.createInsOuts(1, 0);\n\t /**\n\t\t\t * merge the signal\n\t\t\t * @type {Tone.Merge}\n\t\t\t * @private\n\t\t\t */\n\t this._merge = this.output = new Tone.Merge();\n\t this.input.connect(this._merge, 0, 0);\n\t this.input.connect(this._merge, 0, 1);\n\t this.input.gain.value = this.dbToGain(-10);\n\t };\n\t Tone.extend(Tone.Mono);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Mono} this\n\t\t */\n\t Tone.Mono.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._merge.dispose();\n\t this._merge = null;\n\t return this;\n\t };\n\t return Tone.Mono;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A compressor with seperate controls over low/mid/high dynamics\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {Object} options The low/mid/high compressor settings.\n\t\t * @example\n\t\t * var multiband = new Tone.MultibandCompressor({\n\t\t * \t\"lowFrequency\" : 200,\n\t\t * \t\"highFrequency\" : 1300\n\t\t * \t\"low\" : {\n\t\t * \t\t\"threshold\" : -12\n\t\t * \t}\n\t\t * })\n\t\t */\n\t Tone.MultibandCompressor = function (options) {\n\t options = this.defaultArg(arguments, Tone.MultibandCompressor.defaults);\n\t /**\n\t\t\t * split the incoming signal into high/mid/low\n\t\t\t * @type {Tone.MultibandSplit}\n\t\t\t * @private\n\t\t\t */\n\t this._splitter = this.input = new Tone.MultibandSplit({\n\t 'lowFrequency': options.lowFrequency,\n\t 'highFrequency': options.highFrequency\n\t });\n\t /**\n\t\t\t * low/mid crossover frequency.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.lowFrequency = this._splitter.lowFrequency;\n\t /**\n\t\t\t * mid/high crossover frequency.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.highFrequency = this._splitter.highFrequency;\n\t /**\n\t\t\t * the output\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this.output = new Tone.Gain();\n\t /**\n\t\t\t * The compressor applied to the low frequencies.\n\t\t\t * @type {Tone.Compressor}\n\t\t\t */\n\t this.low = new Tone.Compressor(options.low);\n\t /**\n\t\t\t * The compressor applied to the mid frequencies.\n\t\t\t * @type {Tone.Compressor}\n\t\t\t */\n\t this.mid = new Tone.Compressor(options.mid);\n\t /**\n\t\t\t * The compressor applied to the high frequencies.\n\t\t\t * @type {Tone.Compressor}\n\t\t\t */\n\t this.high = new Tone.Compressor(options.high);\n\t //connect the compressor\n\t this._splitter.low.chain(this.low, this.output);\n\t this._splitter.mid.chain(this.mid, this.output);\n\t this._splitter.high.chain(this.high, this.output);\n\t this._readOnly([\n\t 'high',\n\t 'mid',\n\t 'low',\n\t 'highFrequency',\n\t 'lowFrequency'\n\t ]);\n\t };\n\t Tone.extend(Tone.MultibandCompressor);\n\t /**\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.MultibandCompressor.defaults = {\n\t 'low': Tone.Compressor.defaults,\n\t 'mid': Tone.Compressor.defaults,\n\t 'high': Tone.Compressor.defaults,\n\t 'lowFrequency': 250,\n\t 'highFrequency': 2000\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.MultibandCompressor} this\n\t\t */\n\t Tone.MultibandCompressor.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._splitter.dispose();\n\t this._writable([\n\t 'high',\n\t 'mid',\n\t 'low',\n\t 'highFrequency',\n\t 'lowFrequency'\n\t ]);\n\t this.low.dispose();\n\t this.mid.dispose();\n\t this.high.dispose();\n\t this._splitter = null;\n\t this.low = null;\n\t this.mid = null;\n\t this.high = null;\n\t this.lowFrequency = null;\n\t this.highFrequency = null;\n\t return this;\n\t };\n\t return Tone.MultibandCompressor;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Panner is an equal power Left/Right Panner and does not\n\t\t * support 3D. Panner uses the StereoPannerNode when available. \n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {NormalRange} [initialPan=0] The initail panner value (defaults to 0 = center)\n\t\t * @example\n\t\t * //pan the input signal hard right. \n\t\t * var panner = new Tone.Panner(1);\n\t\t */\n\t Tone.Panner = function (initialPan) {\n\t if (this._hasStereoPanner) {\n\t /**\n\t\t\t\t * the panner node\n\t\t\t\t * @type {StereoPannerNode}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._panner = this.input = this.output = this.context.createStereoPanner();\n\t /**\n\t\t\t\t * The pan control. -1 = hard left, 1 = hard right. \n\t\t\t\t * @type {NormalRange}\n\t\t\t\t * @signal\n\t\t\t\t */\n\t this.pan = this._panner.pan;\n\t } else {\n\t /**\n\t\t\t\t * the dry/wet knob\n\t\t\t\t * @type {Tone.CrossFade}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._crossFade = new Tone.CrossFade();\n\t /**\n\t\t\t\t * @type {Tone.Merge}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._merger = this.output = new Tone.Merge();\n\t /**\n\t\t\t\t * @type {Tone.Split}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._splitter = this.input = new Tone.Split();\n\t /**\n\t\t\t\t * The pan control. -1 = hard left, 1 = hard right. \n\t\t\t\t * @type {AudioRange}\n\t\t\t\t * @signal\n\t\t\t\t */\n\t this.pan = new Tone.Signal(0, Tone.Type.AudioRange);\n\t /**\n\t\t\t\t * always sends 0\n\t\t\t\t * @type {Tone.Zero}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._zero = new Tone.Zero();\n\t /**\n\t\t\t\t * The analog to gain conversion\n\t\t\t\t * @type {Tone.AudioToGain}\n\t\t\t\t * @private\n\t\t\t\t */\n\t this._a2g = new Tone.AudioToGain();\n\t //CONNECTIONS:\n\t this._zero.connect(this._a2g);\n\t this.pan.chain(this._a2g, this._crossFade.fade);\n\t //left channel is a, right channel is b\n\t this._splitter.connect(this._crossFade, 0, 0);\n\t this._splitter.connect(this._crossFade, 1, 1);\n\t //merge it back together\n\t this._crossFade.a.connect(this._merger, 0, 0);\n\t this._crossFade.b.connect(this._merger, 0, 1);\n\t }\n\t //initial value\n\t this.pan.value = this.defaultArg(initialPan, 0);\n\t this._readOnly('pan');\n\t };\n\t Tone.extend(Tone.Panner);\n\t /**\n\t\t * indicates if the panner is using the new StereoPannerNode internally\n\t\t * @type {boolean}\n\t\t * @private\n\t\t */\n\t Tone.Panner.prototype._hasStereoPanner = Tone.prototype.isFunction(Tone.context.createStereoPanner);\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Panner} this\n\t\t */\n\t Tone.Panner.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable('pan');\n\t if (this._hasStereoPanner) {\n\t this._panner.disconnect();\n\t this._panner = null;\n\t this.pan = null;\n\t } else {\n\t this._zero.dispose();\n\t this._zero = null;\n\t this._crossFade.dispose();\n\t this._crossFade = null;\n\t this._splitter.dispose();\n\t this._splitter = null;\n\t this._merger.dispose();\n\t this._merger = null;\n\t this.pan.dispose();\n\t this.pan = null;\n\t this._a2g.dispose();\n\t this._a2g = null;\n\t }\n\t return this;\n\t };\n\t return Tone.Panner;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A spatialized panner node which supports equalpower or HRTF panning.\n\t\t * Tries to normalize the API across various browsers. See Tone.Listener\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {Number} positionX The initial x position.\n\t\t * @param {Number} positionY The initial y position.\n\t\t * @param {Number} positionZ The initial z position.\n\t\t */\n\t Tone.Panner3D = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'positionX',\n\t 'positionY',\n\t 'positionZ'\n\t ], Tone.Panner3D.defaults);\n\t /**\n\t\t\t * The panner node\n\t\t\t * @type {PannerNode}\n\t\t\t * @private\n\t\t\t */\n\t this._panner = this.input = this.output = this.context.createPanner();\n\t //set some values\n\t this._panner.panningModel = options.panningModel;\n\t this._panner.maxDistance = options.maxDistance;\n\t this._panner.distanceModel = options.distanceModel;\n\t this._panner.coneOuterGain = options.coneOuterGain;\n\t this._panner.coneOuterAngle = options.coneOuterAngle;\n\t this._panner.coneInnerAngle = options.coneInnerAngle;\n\t this._panner.refDistance = options.refDistance;\n\t this._panner.rolloffFactor = options.rolloffFactor;\n\t /**\n\t\t\t * Holds the current orientation\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._orientation = [\n\t options.orientationX,\n\t options.orientationY,\n\t options.orientationZ\n\t ];\n\t /**\n\t\t\t * Holds the current position\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._position = [\n\t options.positionX,\n\t options.positionY,\n\t options.positionZ\n\t ];\n\t // set the default position/orientation\n\t this.orientationX = options.orientationX;\n\t this.orientationY = options.orientationY;\n\t this.orientationZ = options.orientationZ;\n\t this.positionX = options.positionX;\n\t this.positionY = options.positionY;\n\t this.positionZ = options.positionZ;\n\t };\n\t Tone.extend(Tone.Panner3D);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t * Defaults according to the specification\n\t\t */\n\t Tone.Panner3D.defaults = {\n\t 'positionX': 0,\n\t 'positionY': 0,\n\t 'positionZ': 0,\n\t 'orientationX': 0,\n\t 'orientationY': 0,\n\t 'orientationZ': 0,\n\t 'panningModel': 'equalpower',\n\t 'maxDistance': 10000,\n\t 'distanceModel': 'inverse',\n\t 'coneOuterGain': 0,\n\t 'coneOuterAngle': 360,\n\t 'coneInnerAngle': 360,\n\t 'refDistance': 1,\n\t 'rolloffFactor': 1\n\t };\n\t /**\n\t\t * The ramp time which is applied to the setTargetAtTime\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t Tone.Panner3D.prototype._rampTimeConstant = 0.01;\n\t /**\n\t\t * Sets the position of the source in 3d space.\t\n\t\t * @param {Number} x\n\t\t * @param {Number} y\n\t\t * @param {Number} z\n\t\t * @return {Tone.Panner3D} this\n\t\t */\n\t Tone.Panner3D.prototype.setPosition = function (x, y, z) {\n\t if (this._panner.positionX) {\n\t var now = this.now();\n\t this._panner.positionX.setTargetAtTime(x, now, this._rampTimeConstant);\n\t this._panner.positionY.setTargetAtTime(y, now, this._rampTimeConstant);\n\t this._panner.positionZ.setTargetAtTime(z, now, this._rampTimeConstant);\n\t } else {\n\t this._panner.setPosition(x, y, z);\n\t }\n\t this._position = Array.prototype.slice.call(arguments);\n\t return this;\n\t };\n\t /**\n\t\t * Sets the orientation of the source in 3d space.\t\n\t\t * @param {Number} x\n\t\t * @param {Number} y\n\t\t * @param {Number} z\n\t\t * @return {Tone.Panner3D} this\n\t\t */\n\t Tone.Panner3D.prototype.setOrientation = function (x, y, z) {\n\t if (this._panner.orientationX) {\n\t var now = this.now();\n\t this._panner.orientationX.setTargetAtTime(x, now, this._rampTimeConstant);\n\t this._panner.orientationY.setTargetAtTime(y, now, this._rampTimeConstant);\n\t this._panner.orientationZ.setTargetAtTime(z, now, this._rampTimeConstant);\n\t } else {\n\t this._panner.setOrientation(x, y, z);\n\t }\n\t this._orientation = Array.prototype.slice.call(arguments);\n\t return this;\n\t };\n\t /**\n\t\t * The x position of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name positionX\n\t\t */\n\t Object.defineProperty(Tone.Panner3D.prototype, 'positionX', {\n\t set: function (pos) {\n\t this._position[0] = pos;\n\t this.setPosition.apply(this, this._position);\n\t },\n\t get: function () {\n\t return this._position[0];\n\t }\n\t });\n\t /**\n\t\t * The y position of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name positionY\n\t\t */\n\t Object.defineProperty(Tone.Panner3D.prototype, 'positionY', {\n\t set: function (pos) {\n\t this._position[1] = pos;\n\t this.setPosition.apply(this, this._position);\n\t },\n\t get: function () {\n\t return this._position[1];\n\t }\n\t });\n\t /**\n\t\t * The z position of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name positionZ\n\t\t */\n\t Object.defineProperty(Tone.Panner3D.prototype, 'positionZ', {\n\t set: function (pos) {\n\t this._position[2] = pos;\n\t this.setPosition.apply(this, this._position);\n\t },\n\t get: function () {\n\t return this._position[2];\n\t }\n\t });\n\t /**\n\t\t * The x orientation of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name orientationX\n\t\t */\n\t Object.defineProperty(Tone.Panner3D.prototype, 'orientationX', {\n\t set: function (pos) {\n\t this._orientation[0] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[0];\n\t }\n\t });\n\t /**\n\t\t * The y orientation of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name orientationY\n\t\t */\n\t Object.defineProperty(Tone.Panner3D.prototype, 'orientationY', {\n\t set: function (pos) {\n\t this._orientation[1] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[1];\n\t }\n\t });\n\t /**\n\t\t * The z orientation of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name orientationZ\n\t\t */\n\t Object.defineProperty(Tone.Panner3D.prototype, 'orientationZ', {\n\t set: function (pos) {\n\t this._orientation[2] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[2];\n\t }\n\t });\n\t /**\n\t\t * Proxy a property on the panner to an exposed public propery\n\t\t * @param {String} prop\n\t\t * @private\n\t\t */\n\t Tone.Panner3D._aliasProperty = function (prop) {\n\t Object.defineProperty(Tone.Panner3D.prototype, prop, {\n\t set: function (val) {\n\t this._panner[prop] = val;\n\t },\n\t get: function () {\n\t return this._panner[prop];\n\t }\n\t });\n\t };\n\t /**\n\t\t * The panning model. Either \"equalpower\" or \"HRTF\".\n\t\t * @type {String}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name panningModel\n\t\t */\n\t Tone.Panner3D._aliasProperty('panningModel');\n\t /**\n\t\t * A reference distance for reducing volume as source move further from the listener\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name refDistance\n\t\t */\n\t Tone.Panner3D._aliasProperty('refDistance');\n\t /**\n\t\t * Describes how quickly the volume is reduced as source moves away from listener.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name rolloffFactor\n\t\t */\n\t Tone.Panner3D._aliasProperty('rolloffFactor');\n\t /**\n\t\t * The distance model used by, \"linear\", \"inverse\", or \"exponential\".\n\t\t * @type {String}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name distanceModel\n\t\t */\n\t Tone.Panner3D._aliasProperty('distanceModel');\n\t /**\n\t\t * The angle, in degrees, inside of which there will be no volume reduction\n\t\t * @type {Degrees}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name coneInnerAngle\n\t\t */\n\t Tone.Panner3D._aliasProperty('coneInnerAngle');\n\t /**\n\t\t * The angle, in degrees, outside of which the volume will be reduced \n\t\t * to a constant value of coneOuterGain\n\t\t * @type {Degrees}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name coneOuterAngle\n\t\t */\n\t Tone.Panner3D._aliasProperty('coneOuterAngle');\n\t /**\n\t\t * The gain outside of the coneOuterAngle\n\t\t * @type {Gain}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name coneOuterGain\n\t\t */\n\t Tone.Panner3D._aliasProperty('coneOuterGain');\n\t /**\n\t\t * The maximum distance between source and listener, \n\t\t * after which the volume will not be reduced any further.\n\t\t * @type {Positive}\n\t\t * @memberOf Tone.Panner3D#\n\t\t * @name maxDistance\n\t\t */\n\t Tone.Panner3D._aliasProperty('maxDistance');\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Panner3D} this\n\t\t */\n\t Tone.Panner3D.prototype.dispose = function () {\n\t this._panner.disconnect();\n\t this._panner = null;\n\t this._orientation = null;\n\t this._position = null;\n\t return this;\n\t };\n\t return Tone.Panner3D;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.PanVol is a Tone.Panner and Tone.Volume in one.\n\t\t *\n\t\t * @extends {Tone}\n\t\t * @constructor\n\t\t * @param {AudioRange} pan the initial pan\n\t\t * @param {number} volume The output volume. \n\t\t * @example\n\t\t * //pan the incoming signal left and drop the volume\n\t\t * var panVol = new Tone.PanVol(0.25, -12);\n\t\t */\n\t Tone.PanVol = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'pan',\n\t 'volume'\n\t ], Tone.PanVol.defaults);\n\t /**\n\t\t\t * The panning node\n\t\t\t * @type {Tone.Panner}\n\t\t\t * @private\n\t\t\t */\n\t this._panner = this.input = new Tone.Panner(options.pan);\n\t /**\n\t\t\t * The L/R panning control.\n\t\t\t * @type {AudioRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.pan = this._panner.pan;\n\t /**\n\t\t\t * The volume node\n\t\t\t * @type {Tone.Volume}\n\t\t\t */\n\t this._volume = this.output = new Tone.Volume(options.volume);\n\t /**\n\t\t\t * The volume control in decibels. \n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t */\n\t this.volume = this._volume.volume;\n\t //connections\n\t this._panner.connect(this._volume);\n\t this._readOnly([\n\t 'pan',\n\t 'volume'\n\t ]);\n\t };\n\t Tone.extend(Tone.PanVol);\n\t /**\n\t\t * The defaults\n\t\t * @type {Object}\n\t\t * @const\n\t\t * @static\n\t\t */\n\t Tone.PanVol.defaults = {\n\t 'pan': 0.5,\n\t 'volume': 0\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.PanVol} this\n\t\t */\n\t Tone.PanVol.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._writable([\n\t 'pan',\n\t 'volume'\n\t ]);\n\t this._panner.dispose();\n\t this._panner = null;\n\t this.pan = null;\n\t this._volume.dispose();\n\t this._volume = null;\n\t this.volume = null;\n\t return this;\n\t };\n\t return Tone.PanVol;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.CtrlInterpolate will interpolate between given values based\n\t\t * on the \"index\" property. Passing in an array or object literal\n\t\t * will interpolate each of the parameters. Note (i.e. \"C3\")\n\t\t * and Time (i.e. \"4n + 2\") can be interpolated. All other values are\n\t\t * assumed to be numbers. \n\t\t * @example\n\t\t * var interp = new Tone.CtrlInterpolate([0, 2, 9, 4]);\n\t\t * interp.index = 0.75;\n\t\t * interp.value; //returns 1.5\n\t\t *\n\t\t * @example\n\t\t * var interp = new Tone.CtrlInterpolate([\n\t\t * \t[2, 4, 5],\n\t\t * \t[9, 3, 2],\n\t\t * ]);\n\t\t * @param {Array} values The array of values to interpolate over\n\t\t * @param {Positive} index The initial interpolation index.\n\t\t * @extends {Tone}\n\t\t */\n\t Tone.CtrlInterpolate = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'values',\n\t 'index'\n\t ], Tone.CtrlInterpolate.defaults);\n\t /**\n\t\t\t * The values to interpolate between\n\t\t\t * @type {Array}\n\t\t\t */\n\t this.values = options.values;\n\t /**\n\t\t\t * The interpolated index between values. For example: a value of 1.5\n\t\t\t * would interpolate equally between the value at index 1\n\t\t\t * and the value at index 2. \n\t\t\t * @example\n\t\t\t * interp.index = 0; \n\t\t\t * interp.value; //returns the value at 0\n\t\t\t * interp.index = 0.5;\n\t\t\t * interp.value; //returns the value between indices 0 and 1. \n\t\t\t * @type {Positive}\n\t\t\t */\n\t this.index = options.index;\n\t };\n\t Tone.extend(Tone.CtrlInterpolate);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.CtrlInterpolate.defaults = {\n\t 'index': 0,\n\t 'values': []\n\t };\n\t /**\n\t\t * The current interpolated value based on the index\n\t\t * @readOnly\n\t\t * @memberOf Tone.CtrlInterpolate#\n\t\t * @type {*}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.CtrlInterpolate.prototype, 'value', {\n\t get: function () {\n\t var index = this.index;\n\t index = Math.min(index, this.values.length - 1);\n\t var lowerPosition = Math.floor(index);\n\t var lower = this.values[lowerPosition];\n\t var upper = this.values[Math.ceil(index)];\n\t return this._interpolate(index - lowerPosition, lower, upper);\n\t }\n\t });\n\t /**\n\t\t * Internal interpolation routine\n\t\t * @param {NormalRange} index The index between the lower and upper\n\t\t * @param {*} lower \n\t\t * @param {*} upper \n\t\t * @return {*} The interpolated value\n\t\t * @private\n\t\t */\n\t Tone.CtrlInterpolate.prototype._interpolate = function (index, lower, upper) {\n\t if (this.isArray(lower)) {\n\t var retArray = [];\n\t for (var i = 0; i < lower.length; i++) {\n\t retArray[i] = this._interpolate(index, lower[i], upper[i]);\n\t }\n\t return retArray;\n\t } else if (this.isObject(lower)) {\n\t var retObj = {};\n\t for (var attr in lower) {\n\t retObj[attr] = this._interpolate(index, lower[attr], upper[attr]);\n\t }\n\t return retObj;\n\t } else {\n\t lower = this._toNumber(lower);\n\t upper = this._toNumber(upper);\n\t return (1 - index) * lower + index * upper;\n\t }\n\t };\n\t /**\n\t\t * Convert from the given type into a number\n\t\t * @param {Number|String} value\n\t\t * @return {Number}\n\t\t * @private\n\t\t */\n\t Tone.CtrlInterpolate.prototype._toNumber = function (val) {\n\t if (this.isNumber(val)) {\n\t return val;\n\t } else {\n\t //otherwise assume that it's Time...\n\t return this.toSeconds(val);\n\t }\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.CtrlInterpolate} this\n\t\t */\n\t Tone.CtrlInterpolate.prototype.dispose = function () {\n\t this.values = null;\n\t };\n\t return Tone.CtrlInterpolate;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.CtrlMarkov represents a Markov Chain where each call\n\t\t * to Tone.CtrlMarkov.next will move to the next state. If the next\n\t\t * state choice is an array, the next state is chosen randomly with\n\t\t * even probability for all of the choices. For a weighted probability\n\t\t * of the next choices, pass in an object with \"state\" and \"probability\" attributes. \n\t\t * The probabilities will be normalized and then chosen. If no next options\n\t\t * are given for the current state, the state will stay there. \n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * var chain = new Tone.CtrlMarkov({\n\t\t * \t\"beginning\" : [\"end\", \"middle\"],\n\t\t * \t\"middle\" : \"end\"\n\t\t * });\n\t\t * chain.value = \"beginning\";\n\t\t * chain.next(); //returns \"end\" or \"middle\" with 50% probability\n\t\t *\n\t\t * @example\n\t\t * var chain = new Tone.CtrlMarkov({\n\t\t * \t\"beginning\" : [{\"value\" : \"end\", \"probability\" : 0.8}, \n\t\t * \t\t\t\t\t{\"value\" : \"middle\", \"probability\" : 0.2}],\n\t\t * \t\"middle\" : \"end\"\n\t\t * });\n\t\t * chain.value = \"beginning\";\n\t\t * chain.next(); //returns \"end\" with 80% probability or \"middle\" with 20%.\n\t\t * @param {Object} values An object with the state names as the keys\n\t\t * and the next state(s) as the values. \n\t\t */\n\t Tone.CtrlMarkov = function (values, initial) {\n\t /**\n\t\t\t * The Markov values with states as the keys\n\t\t\t * and next state(s) as the values. \n\t\t\t * @type {Object}\n\t\t\t */\n\t this.values = this.defaultArg(values, {});\n\t /**\n\t\t\t * The current state of the Markov values. The next\n\t\t\t * state will be evaluated and returned when Tone.CtrlMarkov.next\n\t\t\t * is invoked.\n\t\t\t * @type {String}\n\t\t\t */\n\t this.value = this.defaultArg(initial, Object.keys(this.values)[0]);\n\t };\n\t Tone.extend(Tone.CtrlMarkov);\n\t /**\n\t\t * Returns the next state of the Markov values. \n\t\t * @return {String}\n\t\t */\n\t Tone.CtrlMarkov.prototype.next = function () {\n\t if (this.values.hasOwnProperty(this.value)) {\n\t var next = this.values[this.value];\n\t if (this.isArray(next)) {\n\t var distribution = this._getProbDistribution(next);\n\t var rand = Math.random();\n\t var total = 0;\n\t for (var i = 0; i < distribution.length; i++) {\n\t var dist = distribution[i];\n\t if (rand > total && rand < total + dist) {\n\t var chosen = next[i];\n\t if (this.isObject(chosen)) {\n\t this.value = chosen.value;\n\t } else {\n\t this.value = chosen;\n\t }\n\t }\n\t total += dist;\n\t }\n\t } else {\n\t this.value = next;\n\t }\n\t }\n\t return this.value;\n\t };\n\t /**\n\t\t * Choose randomly from an array weighted options in the form \n\t\t * {\"state\" : string, \"probability\" : number} or an array of values\n\t\t * @param {Array} options \n\t\t * @return {Array} The randomly selected choice\n\t\t * @private\n\t\t */\n\t Tone.CtrlMarkov.prototype._getProbDistribution = function (options) {\n\t var distribution = [];\n\t var total = 0;\n\t var needsNormalizing = false;\n\t for (var i = 0; i < options.length; i++) {\n\t var option = options[i];\n\t if (this.isObject(option)) {\n\t needsNormalizing = true;\n\t distribution[i] = option.probability;\n\t } else {\n\t distribution[i] = 1 / options.length;\n\t }\n\t total += distribution[i];\n\t }\n\t if (needsNormalizing) {\n\t //normalize the values\n\t for (var j = 0; j < distribution.length; j++) {\n\t distribution[j] = distribution[j] / total;\n\t }\n\t }\n\t return distribution;\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.CtrlMarkov} this\n\t\t */\n\t Tone.CtrlMarkov.prototype.dispose = function () {\n\t this.values = null;\n\t };\n\t return Tone.CtrlMarkov;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Generate patterns from an array of values.\n\t\t * Has a number of arpeggiation and randomized\n\t\t * selection patterns. \n\t\t * <ul>\n\t\t * \t <li>\"up\" - cycles upward</li>\n\t\t * \t\t\t<li>\"down\" - cycles downward</li>\n\t\t * \t\t\t<li>\"upDown\" - up then and down</li>\n\t\t * \t\t\t<li>\"downUp\" - cycles down then and up</li>\n\t\t * \t\t\t<li>\"alternateUp\" - jump up two and down one</li>\n\t\t * \t\t\t<li>\"alternateDown\" - jump down two and up one</li>\n\t\t * \t\t\t<li>\"random\" - randomly select an index</li>\n\t\t * \t\t\t<li>\"randomWalk\" - randomly moves one index away from the current position</li>\n\t\t * \t\t\t<li>\"randomOnce\" - randomly select an index without repeating until all values have been chosen.</li>\n\t\t * \t\t</ul>\n\t\t * @param {Array} values An array of options to choose from.\n\t\t * @param {Tone.CtrlPattern.Type=} type The name of the pattern.\n\t\t * @extends {Tone}\n\t\t */\n\t Tone.CtrlPattern = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'values',\n\t 'type'\n\t ], Tone.CtrlPattern.defaults);\n\t /**\n\t\t\t * The array of values to arpeggiate over\n\t\t\t * @type {Array}\n\t\t\t */\n\t this.values = options.values;\n\t /**\n\t\t\t * The current position in the values array\n\t\t\t * @type {Number}\n\t\t\t */\n\t this.index = 0;\n\t /**\n\t\t\t * The type placeholder\n\t\t\t * @type {Tone.CtrlPattern.Type}\n\t\t\t * @private\n\t\t\t */\n\t this._type = null;\n\t /**\n\t\t\t * Shuffled values for the RandomOnce type\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._shuffled = null;\n\t /**\n\t\t\t * The direction of the movement\n\t\t\t * @type {String}\n\t\t\t * @private\n\t\t\t */\n\t this._direction = null;\n\t this.type = options.type;\n\t };\n\t Tone.extend(Tone.CtrlPattern);\n\t /**\n\t\t * The Control Patterns\n\t\t * @type {Object}\n\t\t * @static\n\t\t */\n\t Tone.CtrlPattern.Type = {\n\t Up: 'up',\n\t Down: 'down',\n\t UpDown: 'upDown',\n\t DownUp: 'downUp',\n\t AlternateUp: 'alternateUp',\n\t AlternateDown: 'alternateDown',\n\t Random: 'random',\n\t RandomWalk: 'randomWalk',\n\t RandomOnce: 'randomOnce'\n\t };\n\t /**\n\t\t * The default values. \n\t\t * @type {Object}\n\t\t */\n\t Tone.CtrlPattern.defaults = {\n\t 'type': Tone.CtrlPattern.Type.Up,\n\t 'values': []\n\t };\n\t /**\n\t\t * The value at the current index of the pattern.\n\t\t * @readOnly\n\t\t * @memberOf Tone.CtrlPattern#\n\t\t * @type {*}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.CtrlPattern.prototype, 'value', {\n\t get: function () {\n\t //some safeguards\n\t if (this.values.length === 0) {\n\t return;\n\t } else if (this.values.length === 1) {\n\t return this.values[0];\n\t }\n\t this.index = Math.min(this.index, this.values.length - 1);\n\t var val = this.values[this.index];\n\t if (this.type === Tone.CtrlPattern.Type.RandomOnce) {\n\t if (this.values.length !== this._shuffled.length) {\n\t this._shuffleValues();\n\t }\n\t val = this.values[this._shuffled[this.index]];\n\t }\n\t return val;\n\t }\n\t });\n\t /**\n\t\t * The pattern used to select the next\n\t\t * item from the values array\n\t\t * @memberOf Tone.CtrlPattern#\n\t\t * @type {Tone.CtrlPattern.Type}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.CtrlPattern.prototype, 'type', {\n\t get: function () {\n\t return this._type;\n\t },\n\t set: function (type) {\n\t this._type = type;\n\t this._shuffled = null;\n\t //the first index\n\t if (this._type === Tone.CtrlPattern.Type.Up || this._type === Tone.CtrlPattern.Type.UpDown || this._type === Tone.CtrlPattern.Type.RandomOnce || this._type === Tone.CtrlPattern.Type.AlternateUp) {\n\t this.index = 0;\n\t } else if (this._type === Tone.CtrlPattern.Type.Down || this._type === Tone.CtrlPattern.Type.DownUp || this._type === Tone.CtrlPattern.Type.AlternateDown) {\n\t this.index = this.values.length - 1;\n\t }\n\t //the direction\n\t if (this._type === Tone.CtrlPattern.Type.UpDown || this._type === Tone.CtrlPattern.Type.AlternateUp) {\n\t this._direction = Tone.CtrlPattern.Type.Up;\n\t } else if (this._type === Tone.CtrlPattern.Type.DownUp || this._type === Tone.CtrlPattern.Type.AlternateDown) {\n\t this._direction = Tone.CtrlPattern.Type.Down;\n\t }\n\t //randoms\n\t if (this._type === Tone.CtrlPattern.Type.RandomOnce) {\n\t this._shuffleValues();\n\t } else if (this._type === Tone.CtrlPattern.Random) {\n\t this.index = Math.floor(Math.random() * this.values.length);\n\t }\n\t }\n\t });\n\t /**\n\t\t * Return the next value given the current position\n\t\t * and pattern.\n\t\t * @return {*} The next value\n\t\t */\n\t Tone.CtrlPattern.prototype.next = function () {\n\t var type = this.type;\n\t //choose the next index\n\t if (type === Tone.CtrlPattern.Type.Up) {\n\t this.index++;\n\t if (this.index >= this.values.length) {\n\t this.index = 0;\n\t }\n\t } else if (type === Tone.CtrlPattern.Type.Down) {\n\t this.index--;\n\t if (this.index < 0) {\n\t this.index = this.values.length - 1;\n\t }\n\t } else if (type === Tone.CtrlPattern.Type.UpDown || type === Tone.CtrlPattern.Type.DownUp) {\n\t if (this._direction === Tone.CtrlPattern.Type.Up) {\n\t this.index++;\n\t } else {\n\t this.index--;\n\t }\n\t if (this.index < 0) {\n\t this.index = 1;\n\t this._direction = Tone.CtrlPattern.Type.Up;\n\t } else if (this.index >= this.values.length) {\n\t this.index = this.values.length - 2;\n\t this._direction = Tone.CtrlPattern.Type.Down;\n\t }\n\t } else if (type === Tone.CtrlPattern.Type.Random) {\n\t this.index = Math.floor(Math.random() * this.values.length);\n\t } else if (type === Tone.CtrlPattern.Type.RandomWalk) {\n\t if (Math.random() < 0.5) {\n\t this.index--;\n\t this.index = Math.max(this.index, 0);\n\t } else {\n\t this.index++;\n\t this.index = Math.min(this.index, this.values.length - 1);\n\t }\n\t } else if (type === Tone.CtrlPattern.Type.RandomOnce) {\n\t this.index++;\n\t if (this.index >= this.values.length) {\n\t this.index = 0;\n\t //reshuffle the values for next time\n\t this._shuffleValues();\n\t }\n\t } else if (type === Tone.CtrlPattern.Type.AlternateUp) {\n\t if (this._direction === Tone.CtrlPattern.Type.Up) {\n\t this.index += 2;\n\t this._direction = Tone.CtrlPattern.Type.Down;\n\t } else {\n\t this.index -= 1;\n\t this._direction = Tone.CtrlPattern.Type.Up;\n\t }\n\t if (this.index >= this.values.length) {\n\t this.index = 0;\n\t this._direction = Tone.CtrlPattern.Type.Up;\n\t }\n\t } else if (type === Tone.CtrlPattern.Type.AlternateDown) {\n\t if (this._direction === Tone.CtrlPattern.Type.Up) {\n\t this.index += 1;\n\t this._direction = Tone.CtrlPattern.Type.Down;\n\t } else {\n\t this.index -= 2;\n\t this._direction = Tone.CtrlPattern.Type.Up;\n\t }\n\t if (this.index < 0) {\n\t this.index = this.values.length - 1;\n\t this._direction = Tone.CtrlPattern.Type.Down;\n\t }\n\t }\n\t return this.value;\n\t };\n\t /**\n\t\t * Shuffles the values and places the results into the _shuffled\n\t\t * @private\n\t\t */\n\t Tone.CtrlPattern.prototype._shuffleValues = function () {\n\t var copy = [];\n\t this._shuffled = [];\n\t for (var i = 0; i < this.values.length; i++) {\n\t copy[i] = i;\n\t }\n\t while (copy.length > 0) {\n\t var randVal = copy.splice(Math.floor(copy.length * Math.random()), 1);\n\t this._shuffled.push(randVal[0]);\n\t }\n\t };\n\t /**\n\t\t * Clean up\n\t\t * @returns {Tone.CtrlPattern} this\n\t\t */\n\t Tone.CtrlPattern.prototype.dispose = function () {\n\t this._shuffled = null;\n\t this.values = null;\n\t };\n\t return Tone.CtrlPattern;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Choose a random value.\n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * var randomWalk = new Tone.CtrlRandom({\n\t\t * \t\"min\" : 0,\n\t\t * \t\"max\" : 10,\n\t\t * \t\"integer\" : true\n\t\t * });\n\t\t * randomWalk.eval();\n\t\t *\n\t\t * @param {Number|Time=} min The minimum return value.\n\t\t * @param {Number|Time=} max The maximum return value.\n\t\t */\n\t Tone.CtrlRandom = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'min',\n\t 'max'\n\t ], Tone.CtrlRandom.defaults);\n\t /**\n\t\t\t * The minimum return value\n\t\t\t * @type {Number|Time}\n\t\t\t */\n\t this.min = options.min;\n\t /**\n\t\t\t * The maximum return value\n\t\t\t * @type {Number|Time}\n\t\t\t */\n\t this.max = options.max;\n\t /**\n\t\t\t * If the return value should be an integer\n\t\t\t * @type {Boolean}\n\t\t\t */\n\t this.integer = options.integer;\n\t };\n\t Tone.extend(Tone.CtrlRandom);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.CtrlRandom.defaults = {\n\t 'min': 0,\n\t 'max': 1,\n\t 'integer': false\n\t };\n\t /**\n\t\t * Return a random value between min and max. \n\t\t * @readOnly\n\t\t * @memberOf Tone.CtrlRandom#\n\t\t * @type {*}\n\t\t * @name value\n\t\t */\n\t Object.defineProperty(Tone.CtrlRandom.prototype, 'value', {\n\t get: function () {\n\t var min = this.toSeconds(this.min);\n\t var max = this.toSeconds(this.max);\n\t var rand = Math.random();\n\t var val = rand * min + (1 - rand) * max;\n\t if (this.integer) {\n\t val = Math.floor(val);\n\t }\n\t return val;\n\t }\n\t });\n\t return Tone.CtrlRandom;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * AudioBuffer.copyToChannel polyfill\n\t\t * @private\n\t\t */\n\t if (window.AudioBuffer && !AudioBuffer.prototype.copyToChannel) {\n\t AudioBuffer.prototype.copyToChannel = function (src, chanNum, start) {\n\t var channel = this.getChannelData(chanNum);\n\t start = start || 0;\n\t for (var i = 0; i < channel.length; i++) {\n\t channel[i + start] = src[i];\n\t }\n\t };\n\t AudioBuffer.prototype.copyFromChannel = function (dest, chanNum, start) {\n\t var channel = this.getChannelData(chanNum);\n\t start = start || 0;\n\t for (var i = 0; i < channel.length; i++) {\n\t dest[i] = channel[i + start];\n\t }\n\t };\n\t }\n\t /**\n\t\t * @class Buffer loading and storage. Tone.Buffer is used internally by all \n\t\t * classes that make requests for audio files such as Tone.Player,\n\t\t * Tone.Sampler and Tone.Convolver.\n\t\t * <br><br>\n\t\t * Aside from load callbacks from individual buffers, Tone.Buffer \n\t\t * \t\tprovides static methods which keep track of the loading progress \n\t\t * \t\tof all of the buffers. These methods are Tone.Buffer.on(\"load\" / \"progress\" / \"error\")\n\t\t *\n\t\t * @constructor \n\t\t * @extends {Tone}\n\t\t * @param {AudioBuffer|string} url The url to load, or the audio buffer to set. \n\t\t * @param {Function=} onload A callback which is invoked after the buffer is loaded. \n\t\t * It's recommended to use Tone.Buffer.onload instead \n\t\t * since it will give you a callback when ALL buffers are loaded.\n\t\t * @param {Function=} onerror The callback to invoke if there is an error\n\t\t * @example\n\t\t * var buffer = new Tone.Buffer(\"path/to/sound.mp3\", function(){\n\t\t * \t//the buffer is now available.\n\t\t * \tvar buff = buffer.get();\n\t\t * });\n\t\t */\n\t Tone.Buffer = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'url',\n\t 'onload',\n\t 'onerror'\n\t ], Tone.Buffer.defaults);\n\t /**\n\t\t\t * stores the loaded AudioBuffer\n\t\t\t * @type {AudioBuffer}\n\t\t\t * @private\n\t\t\t */\n\t this._buffer = null;\n\t /**\n\t\t\t * indicates if the buffer should be reversed or not\n\t\t\t * @type {Boolean}\n\t\t\t * @private\n\t\t\t */\n\t this._reversed = options.reverse;\n\t /**\n\t\t\t * The XHR\n\t\t\t * @type {XMLHttpRequest}\n\t\t\t * @private\n\t\t\t */\n\t this._xhr = null;\n\t if (options.url instanceof AudioBuffer || options.url instanceof Tone.Buffer) {\n\t this.set(options.url);\n\t // invoke the onload callback\n\t if (options.onload) {\n\t options.onload(this);\n\t }\n\t } else if (this.isString(options.url)) {\n\t this.load(options.url, options.onload, options.onerror);\n\t }\n\t };\n\t Tone.extend(Tone.Buffer);\n\t /**\n\t\t * the default parameters\n\t\t * @type {Object}\n\t\t */\n\t Tone.Buffer.defaults = {\n\t 'url': undefined,\n\t 'reverse': false\n\t };\n\t /**\n\t\t * Pass in an AudioBuffer or Tone.Buffer to set the value\n\t\t * of this buffer.\n\t\t * @param {AudioBuffer|Tone.Buffer} buffer the buffer\n\t\t * @returns {Tone.Buffer} this\n\t\t */\n\t Tone.Buffer.prototype.set = function (buffer) {\n\t if (buffer instanceof Tone.Buffer) {\n\t this._buffer = buffer.get();\n\t } else {\n\t this._buffer = buffer;\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * @return {AudioBuffer} The audio buffer stored in the object.\n\t\t */\n\t Tone.Buffer.prototype.get = function () {\n\t return this._buffer;\n\t };\n\t /**\n\t\t * Makes an xhr reqest for the selected url then decodes\n\t\t * the file as an audio buffer. Invokes\n\t\t * the callback once the audio buffer loads.\n\t\t * @param {String} url The url of the buffer to load.\n\t\t * filetype support depends on the\n\t\t * browser.\n\t\t * @returns {Promise} returns a Promise which resolves with the Tone.Buffer\n\t\t */\n\t Tone.Buffer.prototype.load = function (url, onload, onerror) {\n\t var promise = new Promise(function (load, error) {\n\t this._xhr = Tone.Buffer.load(url, //success\n\t function (buff) {\n\t this._xhr = null;\n\t this.set(buff);\n\t load(this);\n\t if (onload) {\n\t onload(this);\n\t }\n\t }.bind(this), //error\n\t function (err) {\n\t this._xhr = null;\n\t error(err);\n\t if (onerror) {\n\t onerror(err);\n\t }\n\t }.bind(this));\n\t }.bind(this));\n\t return promise;\n\t };\n\t /**\n\t\t * dispose and disconnect\n\t\t * @returns {Tone.Buffer} this\n\t\t */\n\t Tone.Buffer.prototype.dispose = function () {\n\t Tone.Emitter.prototype.dispose.call(this);\n\t this._buffer = null;\n\t if (this._xhr) {\n\t Tone.Buffer._currentDownloads--;\n\t this._xhr.abort();\n\t this._xhr = null;\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * If the buffer is loaded or not\n\t\t * @memberOf Tone.Buffer#\n\t\t * @type {Boolean}\n\t\t * @name loaded\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Buffer.prototype, 'loaded', {\n\t get: function () {\n\t return this.length > 0;\n\t }\n\t });\n\t /**\n\t\t * The duration of the buffer. \n\t\t * @memberOf Tone.Buffer#\n\t\t * @type {Number}\n\t\t * @name duration\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Buffer.prototype, 'duration', {\n\t get: function () {\n\t if (this._buffer) {\n\t return this._buffer.duration;\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The length of the buffer in samples\n\t\t * @memberOf Tone.Buffer#\n\t\t * @type {Number}\n\t\t * @name length\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Buffer.prototype, 'length', {\n\t get: function () {\n\t if (this._buffer) {\n\t return this._buffer.length;\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The number of discrete audio channels. Returns 0 if no buffer\n\t\t * is loaded.\n\t\t * @memberOf Tone.Buffer#\n\t\t * @type {Number}\n\t\t * @name numberOfChannels\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Buffer.prototype, 'numberOfChannels', {\n\t get: function () {\n\t if (this._buffer) {\n\t return this._buffer.numberOfChannels;\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Set the audio buffer from the array\n\t\t * @param {Float32Array} array The array to fill the audio buffer\n\t\t * @param {Number} [channels=1] The number of channels contained in the array. \n\t\t * If the channel is more than 1, the input array\n\t\t * is expected to be a multidimensional array\n\t\t * with dimensions equal to the number of channels.\n\t\t * @return {Tone.Buffer} this\n\t\t */\n\t Tone.Buffer.prototype.fromArray = function (array) {\n\t var isMultidimensional = array[0].length > 0;\n\t var channels = isMultidimensional ? array.length : 1;\n\t var len = isMultidimensional ? array[0].length : array.length;\n\t var buffer = this.context.createBuffer(channels, len, this.context.sampleRate);\n\t if (!isMultidimensional && channels === 1) {\n\t array = [array];\n\t }\n\t for (var c = 0; c < channels; c++) {\n\t buffer.copyToChannel(array[c], c);\n\t }\n\t this._buffer = buffer;\n\t return this;\n\t };\n\t /**\n\t\t * \tSums muliple channels into 1 channel\n\t\t * @param {Number=} channel Optionally only copy a single channel from the array.\n\t\t * @return {Array}\n\t\t */\n\t Tone.Buffer.prototype.toMono = function (chanNum) {\n\t if (this.isNumber(chanNum)) {\n\t this.fromArray(this.toArray(chanNum));\n\t } else {\n\t var outputArray = new Float32Array(this.length);\n\t var numChannels = this.numberOfChannels;\n\t for (var channel = 0; channel < numChannels; channel++) {\n\t var channelArray = this.toArray(channel);\n\t for (var i = 0; i < channelArray.length; i++) {\n\t outputArray[i] += channelArray[i];\n\t }\n\t }\n\t //divide by the number of channels\n\t outputArray = outputArray.map(function (sample) {\n\t return sample / numChannels;\n\t });\n\t this.fromArray(outputArray);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * \tGet the buffer as an array. Single channel buffers will return a 1-dimensional \n\t\t * \tFloat32Array, and multichannel buffers will return multidimensional arrays.\n\t\t * @param {Number=} channel Optionally only copy a single channel from the array.\n\t\t * @return {Array}\n\t\t */\n\t Tone.Buffer.prototype.toArray = function (channel) {\n\t if (this.isNumber(channel)) {\n\t return this.getChannelData(channel);\n\t } else if (this.numberOfChannels === 1) {\n\t return this.toArray(0);\n\t } else {\n\t var ret = [];\n\t for (var c = 0; c < this.numberOfChannels; c++) {\n\t ret[c] = this.getChannelData(c);\n\t }\n\t return ret;\n\t }\n\t };\n\t /**\n\t\t * Returns the Float32Array representing the PCM audio data for the specific channel.\n\t\t * @param {Number} channel The channel number to return\n\t\t * @return {Float32Array} The audio as a TypedArray\n\t\t */\n\t Tone.Buffer.prototype.getChannelData = function (channel) {\n\t return this._buffer.getChannelData(channel);\n\t };\n\t /**\n\t\t * Cut a subsection of the array and return a buffer of the\n\t\t * subsection. Does not modify the original buffer\n\t\t * @param {Time} start The time to start the slice\n\t\t * @param {Time=} end The end time to slice. If none is given\n\t\t * will default to the end of the buffer\n\t\t * @return {Tone.Buffer} this\n\t\t */\n\t Tone.Buffer.prototype.slice = function (start, end) {\n\t end = this.defaultArg(end, this.duration);\n\t var startSamples = Math.floor(this.context.sampleRate * this.toSeconds(start));\n\t var endSamples = Math.floor(this.context.sampleRate * this.toSeconds(end));\n\t var replacement = [];\n\t for (var i = 0; i < this.numberOfChannels; i++) {\n\t replacement[i] = this.toArray(i).slice(startSamples, endSamples);\n\t }\n\t var retBuffer = new Tone.Buffer().fromArray(replacement);\n\t return retBuffer;\n\t };\n\t /**\n\t\t * Reverse the buffer.\n\t\t * @private\n\t\t * @return {Tone.Buffer} this\n\t\t */\n\t Tone.Buffer.prototype._reverse = function () {\n\t if (this.loaded) {\n\t for (var i = 0; i < this.numberOfChannels; i++) {\n\t Array.prototype.reverse.call(this.getChannelData(i));\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Reverse the buffer.\n\t\t * @memberOf Tone.Buffer#\n\t\t * @type {Boolean}\n\t\t * @name reverse\n\t\t */\n\t Object.defineProperty(Tone.Buffer.prototype, 'reverse', {\n\t get: function () {\n\t return this._reversed;\n\t },\n\t set: function (rev) {\n\t if (this._reversed !== rev) {\n\t this._reversed = rev;\n\t this._reverse();\n\t }\n\t }\n\t });\n\t ///////////////////////////////////////////////////////////////////////////\n\t // STATIC METHODS\n\t ///////////////////////////////////////////////////////////////////////////\n\t //statically inherits Emitter methods\n\t Tone.Emitter.mixin(Tone.Buffer);\n\t /**\n\t\t * the static queue for all of the xhr requests\n\t\t * @type {Array}\n\t\t * @private\n\t\t */\n\t Tone.Buffer._downloadQueue = [];\n\t /**\n\t\t * the total number of downloads\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t Tone.Buffer._currentDownloads = 0;\n\t /**\n\t\t * A path which is prefixed before every url.\n\t\t * @type {String}\n\t\t * @static\n\t\t */\n\t Tone.Buffer.baseUrl = '';\n\t /**\n\t\t * Loads a url using XMLHttpRequest.\n\t\t * @param {String} url\n\t\t * @param {Function} onload\n\t\t * @param {Function} onerror\n\t\t * @param {Function} onprogress\n\t\t * @return {XMLHttpRequest}\n\t\t */\n\t Tone.Buffer.load = function (url, onload, onerror) {\n\t //default\n\t onload = onload || Tone.noOp;\n\t function onError(e) {\n\t if (onerror) {\n\t onerror(e);\n\t Tone.Buffer.emit('error', e);\n\t } else {\n\t throw new Error(e);\n\t }\n\t }\n\t function onProgress() {\n\t //calculate the progress\n\t var totalProgress = 0;\n\t for (var i = 0; i < Tone.Buffer._downloadQueue.length; i++) {\n\t totalProgress += Tone.Buffer._downloadQueue[i].progress;\n\t }\n\t Tone.Buffer.emit('progress', totalProgress / Tone.Buffer._downloadQueue.length);\n\t }\n\t var request = new XMLHttpRequest();\n\t request.open('GET', Tone.Buffer.baseUrl + url, true);\n\t request.responseType = 'arraybuffer';\n\t //start out as 0\n\t request.progress = 0;\n\t Tone.Buffer._currentDownloads++;\n\t Tone.Buffer._downloadQueue.push(request);\n\t request.addEventListener('load', function () {\n\t if (request.status === 200) {\n\t Tone.context.decodeAudioData(request.response, function (buff) {\n\t request.progress = 1;\n\t onProgress();\n\t onload(buff);\n\t Tone.Buffer._currentDownloads--;\n\t if (Tone.Buffer._currentDownloads === 0) {\n\t // clear the downloads\n\t Tone.Buffer._downloadQueue = [];\n\t //emit the event at the end\n\t Tone.Buffer.emit('load');\n\t }\n\t }, function () {\n\t onError('Tone.Buffer: could not decode audio data: ' + url);\n\t });\n\t } else {\n\t onError('Tone.Buffer: could not locate file: ' + url);\n\t }\n\t });\n\t request.addEventListener('error', onError);\n\t request.addEventListener('progress', function (event) {\n\t if (event.lengthComputable) {\n\t //only go to 95%, the last 5% is when the audio is decoded\n\t request.progress = event.loaded / event.total * 0.95;\n\t onProgress();\n\t }\n\t });\n\t request.send();\n\t return request;\n\t };\n\t /**\n\t\t * Stop all of the downloads in progress\n\t\t * @return {Tone.Buffer}\n\t\t * @static\n\t\t */\n\t Tone.Buffer.cancelDownloads = function () {\n\t Tone.Buffer._downloadQueue.forEach(function (request) {\n\t request.abort();\n\t });\n\t Tone.Buffer._currentDownloads = 0;\n\t return Tone.Buffer;\n\t };\n\t /**\n\t\t * Checks a url's extension to see if the current browser can play that file type.\n\t\t * @param {String} url The url/extension to test\n\t\t * @return {Boolean} If the file extension can be played\n\t\t * @static\n\t\t * @example\n\t\t * Tone.Buffer.supportsType(\"wav\"); //returns true\n\t\t * Tone.Buffer.supportsType(\"path/to/file.wav\"); //returns true\n\t\t */\n\t Tone.Buffer.supportsType = function (url) {\n\t var extension = url.split('.');\n\t extension = extension[extension.length - 1];\n\t var response = document.createElement('audio').canPlayType('audio/' + extension);\n\t return response !== '';\n\t };\n\t /**\n\t\t * Returns a Promise which resolves when all of the buffers have loaded\n\t\t * @return {Promise}\n\t\t */\n\t Tone.loaded = function () {\n\t var onload, onerror;\n\t function removeEvents() {\n\t //remove the events when it's resolved\n\t Tone.Buffer.off('load', onload);\n\t Tone.Buffer.off('error', onerror);\n\t }\n\t return new Promise(function (success, fail) {\n\t onload = function () {\n\t success();\n\t };\n\t onerror = function () {\n\t fail();\n\t };\n\t //add the event listeners\n\t Tone.Buffer.on('load', onload);\n\t Tone.Buffer.on('error', onerror);\n\t }).then(removeEvents).catch(function (e) {\n\t removeEvents();\n\t throw new Error(e);\n\t });\n\t };\n\t return Tone.Buffer;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class A data structure for holding multiple buffers.\n\t\t * \n\t\t * @param {Object|Array} urls An object literal or array\n\t\t * of urls to load.\n\t\t * @param {Function=} callback The callback to invoke when\n\t\t * the buffers are loaded. \n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * //load a whole bank of piano samples\n\t\t * var pianoSamples = new Tone.Buffers({\n\t\t * \t\"C4\" : \"path/to/C4.mp3\"\n\t\t * \t\"C#4\" : \"path/to/C#4.mp3\"\n\t\t * \t\"D4\" : \"path/to/D4.mp3\"\n\t\t * \t\"D#4\" : \"path/to/D#4.mp3\"\n\t\t * \t...\n\t\t * }, function(){\n\t\t * \t//play one of the samples when they all load\n\t\t * \tplayer.buffer = pianoSamples.get(\"C4\");\n\t\t * \tplayer.start();\n\t\t * });\n\t\t * \n\t\t */\n\t Tone.Buffers = function (urls, onload, baseUrl) {\n\t /**\n\t\t\t * All of the buffers\n\t\t\t * @type {Object}\n\t\t\t * @private\n\t\t\t */\n\t this._buffers = {};\n\t /**\n\t\t\t * A path which is prefixed before every url.\n\t\t\t * @type {String}\n\t\t\t */\n\t this.baseUrl = this.defaultArg(baseUrl, '');\n\t urls = this._flattenUrls(urls);\n\t this._loadingCount = 0;\n\t //add each one\n\t for (var key in urls) {\n\t this._loadingCount++;\n\t this.add(key, urls[key], this._bufferLoaded.bind(this, onload));\n\t }\n\t };\n\t Tone.extend(Tone.Buffers);\n\t /**\n\t\t * True if the buffers object has a buffer by that name.\n\t\t * @param {String|Number} name The key or index of the \n\t\t * buffer.\n\t\t * @return {Boolean}\n\t\t */\n\t Tone.Buffers.prototype.has = function (name) {\n\t return this._buffers.hasOwnProperty(name);\n\t };\n\t /**\n\t\t * Get a buffer by name. If an array was loaded, \n\t\t * then use the array index.\n\t\t * @param {String|Number} name The key or index of the \n\t\t * buffer.\n\t\t * @return {Tone.Buffer}\n\t\t */\n\t Tone.Buffers.prototype.get = function (name) {\n\t if (this.has(name)) {\n\t return this._buffers[name];\n\t } else {\n\t throw new Error('Tone.Buffers: no buffer named ' + name);\n\t }\n\t };\n\t /**\n\t\t * A buffer was loaded. decrement the counter.\n\t\t * @param {Function} callback \n\t\t * @private\n\t\t */\n\t Tone.Buffers.prototype._bufferLoaded = function (callback) {\n\t this._loadingCount--;\n\t if (this._loadingCount === 0 && callback) {\n\t callback(this);\n\t }\n\t };\n\t /**\n\t\t * If the buffers are loaded or not\n\t\t * @memberOf Tone.Buffers#\n\t\t * @type {Boolean}\n\t\t * @name loaded\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Buffers.prototype, 'loaded', {\n\t get: function () {\n\t var isLoaded = true;\n\t for (var buffName in this._buffers) {\n\t var buff = this.get(buffName);\n\t isLoaded = isLoaded && buff.loaded;\n\t }\n\t return isLoaded;\n\t }\n\t });\n\t /**\n\t\t * Add a buffer by name and url to the Buffers\n\t\t * @param {String} name A unique name to give\n\t\t * the buffer\n\t\t * @param {String|Tone.Buffer|Audiobuffer} url Either the url of the bufer, \n\t\t * or a buffer which will be added\n\t\t * with the given name.\n\t\t * @param {Function=} callback The callback to invoke \n\t\t * when the url is loaded.\n\t\t */\n\t Tone.Buffers.prototype.add = function (name, url, callback) {\n\t callback = this.defaultArg(callback, Tone.noOp);\n\t if (url instanceof Tone.Buffer) {\n\t this._buffers[name] = url;\n\t callback(this);\n\t } else if (url instanceof AudioBuffer) {\n\t this._buffers[name] = new Tone.Buffer(url);\n\t callback(this);\n\t } else if (this.isString(url)) {\n\t this._buffers[name] = new Tone.Buffer(this.baseUrl + url, callback);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Flatten an object into a single depth object. \n\t\t * thanks to https://gist.github.com/penguinboy/762197\n\t\t * @param {Object} ob \t\n\t\t * @return {Object} \n\t\t * @private\n\t\t */\n\t Tone.Buffers.prototype._flattenUrls = function (ob) {\n\t var toReturn = {};\n\t for (var i in ob) {\n\t if (!ob.hasOwnProperty(i))\n\t continue;\n\t if (this.isObject(ob[i])) {\n\t var flatObject = this._flattenUrls(ob[i]);\n\t for (var x in flatObject) {\n\t if (!flatObject.hasOwnProperty(x))\n\t continue;\n\t toReturn[i + '.' + x] = flatObject[x];\n\t }\n\t } else {\n\t toReturn[i] = ob[i];\n\t }\n\t }\n\t return toReturn;\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.Buffers} this\n\t\t */\n\t Tone.Buffers.prototype.dispose = function () {\n\t for (var name in this._buffers) {\n\t this._buffers[name].dispose();\n\t }\n\t this._buffers = null;\n\t return this;\n\t };\n\t return Tone.Buffers;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * buses are another way of routing audio\n\t\t *\n\t\t * augments Tone.prototype to include send and recieve\n\t\t */\n\t /**\n\t\t * All of the routes\n\t\t * \n\t\t * @type {Object}\n\t\t * @static\n\t\t * @private\n\t\t */\n\t var Buses = {};\n\t /**\n\t\t * Send this signal to the channel name. \n\t\t * @param {string} channelName A named channel to send the signal to.\n\t\t * @param {Decibels} amount The amount of the source to send to the bus. \n\t\t * @return {GainNode} The gain node which connects this node to the desired channel. \n\t\t * Can be used to adjust the levels of the send.\n\t\t * @example\n\t\t * source.send(\"reverb\", -12);\n\t\t */\n\t Tone.prototype.send = function (channelName, amount) {\n\t if (!Buses.hasOwnProperty(channelName)) {\n\t Buses[channelName] = this.context.createGain();\n\t }\n\t amount = this.defaultArg(amount, 0);\n\t var sendKnob = new Tone.Gain(amount, Tone.Type.Decibels);\n\t this.output.chain(sendKnob, Buses[channelName]);\n\t return sendKnob;\n\t };\n\t /**\n\t\t * Recieve the input from the desired channelName to the input\n\t\t *\n\t\t * @param {string} channelName A named channel to send the signal to.\n\t\t * @param {AudioNode} [input] If no input is selected, the\n\t\t * input of the current node is\n\t\t * chosen. \n\t\t * @returns {Tone} this\n\t\t * @example\n\t\t * reverbEffect.receive(\"reverb\");\n\t\t */\n\t Tone.prototype.receive = function (channelName, input) {\n\t if (!Buses.hasOwnProperty(channelName)) {\n\t Buses[channelName] = this.context.createGain();\n\t }\n\t if (this.isUndef(input)) {\n\t input = this.input;\n\t }\n\t Buses[channelName].connect(input);\n\t return this;\n\t };\n\t //remove all the send/receives when a new audio context is passed in\n\t Tone.Context.on('init', function (context) {\n\t if (context.Buses) {\n\t Buses = context.Buses;\n\t } else {\n\t Buses = {};\n\t context.Buses = Buses;\n\t }\n\t });\n\t return Tone;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Draw is useful for synchronizing visuals and audio events.\n\t\t * Callbacks from Tone.Transport or any of the Tone.Event classes\n\t\t * always happen _before_ the scheduled time and are not synchronized\n\t\t * to the animation frame so they are not good for triggering tightly\n\t\t * synchronized visuals and sound. Tone.Draw makes it easy to schedule\n\t\t * callbacks using the AudioContext time and uses requestAnimationFrame.\n\t\t * \n\t\t * @singleton\n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * Tone.Transport.schedule(function(time){\n\t\t * \t//use the time argument to schedule a callback with Tone.Draw\n\t\t * \tTone.Draw.schedule(function(){\n\t\t * \t\t//do drawing or DOM manipulation here\n\t\t * \t}, time)\n\t\t * }, \"+0.5\")\n\t\t */\n\t Tone.Draw = function () {\n\t /**\n\t\t\t * All of the events.\n\t\t\t * @type {Tone.Timeline}\n\t\t\t * @private\n\t\t\t */\n\t this._events = new Tone.Timeline();\n\t /**\n\t\t\t * The duration after which events are not invoked.\n\t\t\t * @type {Number}\n\t\t\t * @default 0.25\n\t\t\t */\n\t this.expiration = 0.25;\n\t /**\n\t\t\t * The amount of time before the scheduled time \n\t\t\t * that the callback can be invoked. Default is\n\t\t\t * half the time of an animation frame (0.008 seconds).\n\t\t\t * @type {Number}\n\t\t\t * @default 0.008\n\t\t\t */\n\t this.anticipation = 0.008;\n\t /**\n\t\t\t * The draw loop\n\t\t\t * @type {Function}\n\t\t\t * @private\n\t\t\t */\n\t this._boundDrawLoop = this._drawLoop.bind(this);\n\t };\n\t Tone.extend(Tone.Draw);\n\t /**\n\t\t * Schedule a function at the given time to be invoked\n\t\t * on the nearest animation frame.\n\t\t * @param {Function} callback Callback is invoked at the given time.\n\t\t * @param {Time} time The time relative to the AudioContext time\n\t\t * to invoke the callback.\n\t\t * @return {Tone.Draw} this\n\t\t */\n\t Tone.Draw.prototype.schedule = function (callback, time) {\n\t this._events.add({\n\t callback: callback,\n\t time: this.toSeconds(time)\n\t });\n\t //start the draw loop on the first event\n\t if (this._events.length === 1) {\n\t requestAnimationFrame(this._boundDrawLoop);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Cancel events scheduled after the given time\n\t\t * @param {Time=} after Time after which scheduled events will \n\t\t * be removed from the scheduling timeline.\n\t\t * @return {Tone.Draw} this\n\t\t */\n\t Tone.Draw.prototype.cancel = function (after) {\n\t this._events.cancel(this.toSeconds(after));\n\t return this;\n\t };\n\t /**\n\t\t * The draw loop\n\t\t * @private\n\t\t */\n\t Tone.Draw.prototype._drawLoop = function () {\n\t var now = Tone.now();\n\t while (this._events.length && this._events.peek().time - this.anticipation <= now) {\n\t var event = this._events.shift();\n\t if (now - event.time <= this.expiration) {\n\t event.callback();\n\t }\n\t }\n\t if (this._events.length > 0) {\n\t requestAnimationFrame(this._boundDrawLoop);\n\t }\n\t };\n\t //make a singleton\n\t Tone.Draw = new Tone.Draw();\n\t return Tone.Draw;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Both Tone.Panner3D and Tone.Listener have a position in 3D space \n\t\t * using a right-handed cartesian coordinate system. \n\t\t * The units used in the coordinate system are not defined; \n\t\t * these coordinates are independent/invariant of any particular \n\t\t * units such as meters or feet. Tone.Panner3D objects have an forward \n\t\t * vector representing the direction the sound is projecting. Additionally, \n\t\t * they have a sound cone representing how directional the sound is. \n\t\t * For example, the sound could be omnidirectional, in which case it would \n\t\t * be heard anywhere regardless of its forward, or it can be more directional \n\t\t * and heard only if it is facing the listener. Tone.Listener objects \n\t\t * (representing a person's ears) have an forward and up vector \n\t\t * representing in which direction the person is facing. Because both the \n\t\t * source stream and the listener can be moving, they both have a velocity \n\t\t * vector representing both the speed and direction of movement. Taken together, \n\t\t * these two velocities can be used to generate a doppler shift effect which changes the pitch.\n\t\t * <br><br>\n\t\t * Note: the position of the Listener will have no effect on nodes not connected to a Tone.Panner3D\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @singleton\n\t\t * @param {Number} positionX The initial x position.\n\t\t * @param {Number} positionY The initial y position.\n\t\t * @param {Number} positionZ The initial z position.\n\t\t */\n\t Tone.Listener = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'positionX',\n\t 'positionY',\n\t 'positionZ'\n\t ], ListenerConstructor.defaults);\n\t /**\n\t\t\t * Holds the current forward orientation\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._orientation = [\n\t options.forwardX,\n\t options.forwardY,\n\t options.forwardZ,\n\t options.upX,\n\t options.upY,\n\t options.upZ\n\t ];\n\t /**\n\t\t\t * Holds the current position\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._position = [\n\t options.positionX,\n\t options.positionY,\n\t options.positionZ\n\t ];\n\t // set the default position/forward\n\t this.forwardX = options.forwardX;\n\t this.forwardY = options.forwardY;\n\t this.forwardZ = options.forwardZ;\n\t this.upX = options.upX;\n\t this.upY = options.upY;\n\t this.upZ = options.upZ;\n\t this.positionX = options.positionX;\n\t this.positionY = options.positionY;\n\t this.positionZ = options.positionZ;\n\t };\n\t Tone.extend(Tone.Listener);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t * Defaults according to the specification\n\t\t */\n\t Tone.Listener.defaults = {\n\t 'positionX': 0,\n\t 'positionY': 0,\n\t 'positionZ': 0,\n\t 'forwardX': 0,\n\t 'forwardY': 0,\n\t 'forwardZ': 1,\n\t 'upX': 0,\n\t 'upY': 1,\n\t 'upZ': 0\n\t };\n\t /**\n\t\t * The ramp time which is applied to the setTargetAtTime\n\t\t * @type {Number}\n\t\t * @private\n\t\t */\n\t Tone.Listener.prototype._rampTimeConstant = 0.01;\n\t /**\n\t\t * Sets the position of the listener in 3d space.\t\n\t\t * @param {Number} x\n\t\t * @param {Number} y\n\t\t * @param {Number} z\n\t\t * @return {Tone.Listener} this\n\t\t */\n\t Tone.Listener.prototype.setPosition = function (x, y, z) {\n\t if (this.context.listener.positionX) {\n\t var now = this.now();\n\t this.context.listener.positionX.setTargetAtTime(x, now, this._rampTimeConstant);\n\t this.context.listener.positionY.setTargetAtTime(y, now, this._rampTimeConstant);\n\t this.context.listener.positionZ.setTargetAtTime(z, now, this._rampTimeConstant);\n\t } else {\n\t this.context.listener.setPosition(x, y, z);\n\t }\n\t this._position = Array.prototype.slice.call(arguments);\n\t return this;\n\t };\n\t /**\n\t\t * Sets the orientation of the listener using two vectors, the forward\n\t\t * vector (which direction the listener is facing) and the up vector \n\t\t * (which the up direction of the listener). An up vector\n\t\t * of 0, 0, 1 is equivalent to the listener standing up in the Z direction. \n\t\t * @param {Number} x\n\t\t * @param {Number} y\n\t\t * @param {Number} z\n\t\t * @param {Number} upX\n\t\t * @param {Number} upY\n\t\t * @param {Number} upZ\n\t\t * @return {Tone.Listener} this\n\t\t */\n\t Tone.Listener.prototype.setOrientation = function (x, y, z, upX, upY, upZ) {\n\t if (this.context.listener.forwardX) {\n\t var now = this.now();\n\t this.context.listener.forwardX.setTargetAtTime(x, now, this._rampTimeConstant);\n\t this.context.listener.forwardY.setTargetAtTime(y, now, this._rampTimeConstant);\n\t this.context.listener.forwardZ.setTargetAtTime(z, now, this._rampTimeConstant);\n\t this.context.listener.upX.setTargetAtTime(upX, now, this._rampTimeConstant);\n\t this.context.listener.upY.setTargetAtTime(upY, now, this._rampTimeConstant);\n\t this.context.listener.upZ.setTargetAtTime(upZ, now, this._rampTimeConstant);\n\t } else {\n\t this.context.listener.setOrientation(x, y, z, upX, upY, upZ);\n\t }\n\t this._orientation = Array.prototype.slice.call(arguments);\n\t return this;\n\t };\n\t /**\n\t\t * The x position of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name positionX\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'positionX', {\n\t set: function (pos) {\n\t this._position[0] = pos;\n\t this.setPosition.apply(this, this._position);\n\t },\n\t get: function () {\n\t return this._position[0];\n\t }\n\t });\n\t /**\n\t\t * The y position of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name positionY\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'positionY', {\n\t set: function (pos) {\n\t this._position[1] = pos;\n\t this.setPosition.apply(this, this._position);\n\t },\n\t get: function () {\n\t return this._position[1];\n\t }\n\t });\n\t /**\n\t\t * The z position of the panner object.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name positionZ\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'positionZ', {\n\t set: function (pos) {\n\t this._position[2] = pos;\n\t this.setPosition.apply(this, this._position);\n\t },\n\t get: function () {\n\t return this._position[2];\n\t }\n\t });\n\t /**\n\t\t * The x coordinate of the listeners front direction. i.e. \n\t\t * which way they are facing.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name forwardX\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'forwardX', {\n\t set: function (pos) {\n\t this._orientation[0] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[0];\n\t }\n\t });\n\t /**\n\t\t * The y coordinate of the listeners front direction. i.e. \n\t\t * which way they are facing.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name forwardY\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'forwardY', {\n\t set: function (pos) {\n\t this._orientation[1] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[1];\n\t }\n\t });\n\t /**\n\t\t * The z coordinate of the listeners front direction. i.e. \n\t\t * which way they are facing.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name forwardZ\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'forwardZ', {\n\t set: function (pos) {\n\t this._orientation[2] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[2];\n\t }\n\t });\n\t /**\n\t\t * The x coordinate of the listener's up direction. i.e.\n\t\t * the direction the listener is standing in.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name upX\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'upX', {\n\t set: function (pos) {\n\t this._orientation[3] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[3];\n\t }\n\t });\n\t /**\n\t\t * The y coordinate of the listener's up direction. i.e.\n\t\t * the direction the listener is standing in.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name upY\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'upY', {\n\t set: function (pos) {\n\t this._orientation[4] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[4];\n\t }\n\t });\n\t /**\n\t\t * The z coordinate of the listener's up direction. i.e.\n\t\t * the direction the listener is standing in.\n\t\t * @type {Number}\n\t\t * @memberOf Tone.Listener#\n\t\t * @name upZ\n\t\t */\n\t Object.defineProperty(Tone.Listener.prototype, 'upZ', {\n\t set: function (pos) {\n\t this._orientation[5] = pos;\n\t this.setOrientation.apply(this, this._orientation);\n\t },\n\t get: function () {\n\t return this._orientation[5];\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Listener} this\n\t\t */\n\t Tone.Listener.prototype.dispose = function () {\n\t this._orientation = null;\n\t this._position = null;\n\t return this;\n\t };\n\t //SINGLETON SETUP\n\t var ListenerConstructor = Tone.Listener;\n\t Tone.Listener = new ListenerConstructor();\n\t Tone.Context.on('init', function (context) {\n\t if (context.Listener instanceof ListenerConstructor) {\n\t //a single listener object\n\t Tone.Listener = context.Listener;\n\t } else {\n\t //make new Listener insides\n\t Tone.Listener = new ListenerConstructor();\n\t }\n\t context.Listener = Tone.Listener;\n\t });\n\t //END SINGLETON SETUP\n\t return Tone.Listener;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * shim\n\t\t * @private\n\t\t */\n\t if (!window.hasOwnProperty('OfflineAudioContext') && window.hasOwnProperty('webkitOfflineAudioContext')) {\n\t window.OfflineAudioContext = window.webkitOfflineAudioContext;\n\t }\n\t /**\n\t\t * @class Wrapper around the OfflineAudioContext\n\t\t * @extends {Tone.Context\n\t\t * @param {Number} channels The number of channels to render\n\t\t * @param {Number} duration The duration to render in samples\n\t\t * @param {Number} sampleRate the sample rate to render at\n\t\t */\n\t Tone.OfflineContext = function (channels, duration, sampleRate) {\n\t /**\n\t\t\t * The offline context\n\t\t\t * @private\n\t\t\t * @type {OfflineAudioContext}\n\t\t\t */\n\t var offlineContext = new OfflineAudioContext(channels, duration * sampleRate, sampleRate);\n\t //wrap the methods/members\n\t Tone.Context.call(this, offlineContext);\n\t /**\n\t\t\t * A private reference to the duration\n\t\t\t * @private\n\t\t\t * @type {Number}\n\t\t\t */\n\t this._duration = duration;\n\t /**\n\t\t\t * An artificial clock source\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._currentTime = 0;\n\t //modify the lookAhead and updateInterval to one block\n\t this.lookAhead = this.blockTime;\n\t this.updateInterval = this.blockTime;\n\t };\n\t Tone.extend(Tone.OfflineContext, Tone.Context);\n\t /**\n\t\t * Override the now method to point to the internal clock time\n\t\t * @return {Number}\n\t\t */\n\t Tone.OfflineContext.prototype.now = function () {\n\t return this._currentTime;\n\t };\n\t /**\n\t\t * Overwrite this method since the worker is not necessary for the offline context\n\t\t * @private\n\t\t */\n\t Tone.OfflineContext.prototype._createWorker = function () {\n\t //dummy worker that does nothing\n\t return {\n\t postMessage: function () {\n\t }\n\t };\n\t };\n\t /**\n\t\t * Render the output of the OfflineContext\n\t\t * @return {Promise}\n\t\t */\n\t Tone.OfflineContext.prototype.render = function () {\n\t while (this._duration - this._currentTime >= 0) {\n\t //invoke all the callbacks on that time\n\t this.emit('tick');\n\t //increment the clock\n\t this._currentTime += Tone.prototype.blockTime;\n\t }\n\t //promise returned is not yet implemented in all browsers\n\t return new Promise(function (done) {\n\t this._context.oncomplete = function (e) {\n\t done(e.renderedBuffer);\n\t };\n\t this._context.startRendering();\n\t }.bind(this));\n\t };\n\t return Tone.OfflineContext;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * Generate a buffer by rendering all of the Tone.js code within the callback using the OfflineAudioContext. \n\t\t * The OfflineAudioContext is capable of rendering much faster than real time in many cases. \n\t\t * The callback function also passes in an offline instance of Tone.Transport which can be used\n\t\t * to schedule events along the Transport. \n\t\t * @param {Function} callback All Tone.js nodes which are created and scheduled within this callback are recorded into the output Buffer.\n\t\t * @param {Time} duration the amount of time to record for.\n\t\t * @return {Promise} The promise which is invoked with the Tone.Buffer of the recorded output.\n\t\t * @example\n\t\t * //render 2 seconds of the oscillator\n\t\t * Tone.Offline(function(){\n\t\t * \t//only nodes created in this callback will be recorded\n\t\t * \tvar oscillator = new Tone.Oscillator().toMaster().start(0)\n\t\t * \t//schedule their events\n\t\t * }, 2).then(function(buffer){\n\t\t * \t//do something with the output buffer\n\t\t * })\n\t\t * @example\n\t\t * //can also schedule events along the Transport\n\t\t * //using the passed in Offline Transport\n\t\t * Tone.Offline(function(Transport){\n\t\t * \tvar osc = new Tone.Oscillator().toMaster()\n\t\t * \tTransport.schedule(function(time){\n\t\t * \t\tosc.start(time).stop(time + 0.1)\n\t\t * \t}, 1)\n\t\t * \tTransport.start(0.2)\n\t\t * }, 4).then(function(buffer){\n\t\t * \t//do something with the output buffer\n\t\t * })\n\t\t */\n\t Tone.Offline = function (callback, duration) {\n\t //set the OfflineAudioContext\n\t var sampleRate = Tone.context.sampleRate;\n\t var originalContext = Tone.context;\n\t var context = new Tone.OfflineContext(2, duration, sampleRate);\n\t Tone.context = context;\n\t //invoke the callback/scheduling\n\t callback(Tone.Transport);\n\t //process the audio\n\t var rendered = context.render();\n\t //return the original AudioContext\n\t Tone.context = originalContext;\n\t //return the audio\n\t return rendered.then(function (buffer) {\n\t //wrap it in a Tone.Buffer\n\t return new Tone.Buffer(buffer);\n\t });\n\t };\n\t return Tone.Offline;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * \t@class Tone.Effect is the base class for effects. Connect the effect between\n\t\t * \t the effectSend and effectReturn GainNodes, then control the amount of\n\t\t * \t effect which goes to the output using the wet control.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {NormalRange|Object} [wet] The starting wet value. \n\t\t */\n\t Tone.Effect = function () {\n\t this.createInsOuts(1, 1);\n\t //get all of the defaults\n\t var options = this.optionsObject(arguments, ['wet'], Tone.Effect.defaults);\n\t /**\n\t\t\t * the drywet knob to control the amount of effect\n\t\t\t * @type {Tone.CrossFade}\n\t\t\t * @private\n\t\t\t */\n\t this._dryWet = new Tone.CrossFade(options.wet);\n\t /**\n\t\t\t * The wet control is how much of the effected\n\t\t\t * will pass through to the output. 1 = 100% effected\n\t\t\t * signal, 0 = 100% dry signal. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.wet = this._dryWet.fade;\n\t /**\n\t\t\t * connect the effectSend to the input of hte effect\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this.effectSend = new Tone.Gain();\n\t /**\n\t\t\t * connect the output of the effect to the effectReturn\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this.effectReturn = new Tone.Gain();\n\t //connections\n\t this.input.connect(this._dryWet.a);\n\t this.input.connect(this.effectSend);\n\t this.effectReturn.connect(this._dryWet.b);\n\t this._dryWet.connect(this.output);\n\t this._readOnly(['wet']);\n\t };\n\t Tone.extend(Tone.Effect);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Effect.defaults = { 'wet': 1 };\n\t /**\n\t\t * chains the effect in between the effectSend and effectReturn\n\t\t * @param {Tone} effect\n\t\t * @private\n\t\t * @returns {Tone.Effect} this\n\t\t */\n\t Tone.Effect.prototype.connectEffect = function (effect) {\n\t this.effectSend.chain(effect, this.effectReturn);\n\t return this;\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Effect} this\n\t\t */\n\t Tone.Effect.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._dryWet.dispose();\n\t this._dryWet = null;\n\t this.effectSend.dispose();\n\t this.effectSend = null;\n\t this.effectReturn.dispose();\n\t this.effectReturn = null;\n\t this._writable(['wet']);\n\t this.wet = null;\n\t return this;\n\t };\n\t return Tone.Effect;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.AutoFilter is a Tone.Filter with a Tone.LFO connected to the filter cutoff frequency.\n\t\t * Setting the LFO rate and depth allows for control over the filter modulation rate \n\t\t * and depth.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Effect}\n\t\t * @param {Time|Object} [frequency] The rate of the LFO.\n\t\t * @param {Frequency=} baseFrequency The lower value of the LFOs oscillation\n\t \t * @param {Frequency=} octaves The number of octaves above the baseFrequency\n\t\t * @example\n\t\t * //create an autofilter and start it's LFO\n\t\t * var autoFilter = new Tone.AutoFilter(\"4n\").toMaster().start();\n\t\t * //route an oscillator through the filter and start it\n\t\t * var oscillator = new Tone.Oscillator().connect(autoFilter).start();\n\t\t */\n\t Tone.AutoFilter = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'baseFrequency',\n\t 'octaves'\n\t ], Tone.AutoFilter.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * the lfo which drives the filter cutoff\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfo = new Tone.LFO({\n\t 'frequency': options.frequency,\n\t 'amplitude': options.depth\n\t });\n\t /**\n\t\t\t * The range of the filter modulating between the min and max frequency. \n\t\t\t * 0 = no modulation. 1 = full modulation.\n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.depth = this._lfo.amplitude;\n\t /**\n\t\t\t * How fast the filter modulates between min and max. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._lfo.frequency;\n\t /**\n\t\t\t * The filter node\n\t\t\t * @type {Tone.Filter}\n\t\t\t */\n\t this.filter = new Tone.Filter(options.filter);\n\t /**\n\t\t\t * The octaves placeholder\n\t\t\t * @type {Positive}\n\t\t\t * @private\n\t\t\t */\n\t this._octaves = 0;\n\t //connections\n\t this.connectEffect(this.filter);\n\t this._lfo.connect(this.filter.frequency);\n\t this.type = options.type;\n\t this._readOnly([\n\t 'frequency',\n\t 'depth'\n\t ]);\n\t this.octaves = options.octaves;\n\t this.baseFrequency = options.baseFrequency;\n\t };\n\t //extend Effect\n\t Tone.extend(Tone.AutoFilter, Tone.Effect);\n\t /**\n\t\t * defaults\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.AutoFilter.defaults = {\n\t 'frequency': 1,\n\t 'type': 'sine',\n\t 'depth': 1,\n\t 'baseFrequency': 200,\n\t 'octaves': 2.6,\n\t 'filter': {\n\t 'type': 'lowpass',\n\t 'rolloff': -12,\n\t 'Q': 1\n\t }\n\t };\n\t /**\n\t\t * Start the effect.\n\t\t * @param {Time} [time=now] When the LFO will start. \n\t\t * @returns {Tone.AutoFilter} this\n\t\t */\n\t Tone.AutoFilter.prototype.start = function (time) {\n\t this._lfo.start(time);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the effect.\n\t\t * @param {Time} [time=now] When the LFO will stop. \n\t\t * @returns {Tone.AutoFilter} this\n\t\t */\n\t Tone.AutoFilter.prototype.stop = function (time) {\n\t this._lfo.stop(time);\n\t return this;\n\t };\n\t /**\n\t\t * Sync the filter to the transport.\n\t\t * @param {Time} [delay=0] Delay time before starting the effect after the\n\t\t * Transport has started. \n\t\t * @returns {Tone.AutoFilter} this\n\t\t */\n\t Tone.AutoFilter.prototype.sync = function (delay) {\n\t this._lfo.sync(delay);\n\t return this;\n\t };\n\t /**\n\t\t * Unsync the filter from the transport.\n\t\t * @returns {Tone.AutoFilter} this\n\t\t */\n\t Tone.AutoFilter.prototype.unsync = function () {\n\t this._lfo.unsync();\n\t return this;\n\t };\n\t /**\n\t\t * Type of oscillator attached to the AutoFilter. \n\t\t * Possible values: \"sine\", \"square\", \"triangle\", \"sawtooth\".\n\t\t * @memberOf Tone.AutoFilter#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.AutoFilter.prototype, 'type', {\n\t get: function () {\n\t return this._lfo.type;\n\t },\n\t set: function (type) {\n\t this._lfo.type = type;\n\t }\n\t });\n\t /**\n\t\t * The minimum value of the filter's cutoff frequency.\n\t\t * @memberOf Tone.AutoFilter#\n\t\t * @type {Frequency}\n\t\t * @name min\n\t\t */\n\t Object.defineProperty(Tone.AutoFilter.prototype, 'baseFrequency', {\n\t get: function () {\n\t return this._lfo.min;\n\t },\n\t set: function (freq) {\n\t this._lfo.min = this.toFrequency(freq);\n\t //and set the max\n\t this.octaves = this._octaves;\n\t }\n\t });\n\t /**\n\t\t * The maximum value of the filter's cutoff frequency. \n\t\t * @memberOf Tone.AutoFilter#\n\t\t * @type {Positive}\n\t\t * @name octaves\n\t\t */\n\t Object.defineProperty(Tone.AutoFilter.prototype, 'octaves', {\n\t get: function () {\n\t return this._octaves;\n\t },\n\t set: function (oct) {\n\t this._octaves = oct;\n\t this._lfo.max = this.baseFrequency * Math.pow(2, oct);\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.AutoFilter} this\n\t\t */\n\t Tone.AutoFilter.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._lfo.dispose();\n\t this._lfo = null;\n\t this.filter.dispose();\n\t this.filter = null;\n\t this._writable([\n\t 'frequency',\n\t 'depth'\n\t ]);\n\t this.frequency = null;\n\t this.depth = null;\n\t return this;\n\t };\n\t return Tone.AutoFilter;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.AutoPanner is a Tone.Panner with an LFO connected to the pan amount. \n\t\t * More on using autopanners [here](https://www.ableton.com/en/blog/autopan-chopper-effect-and-more-liveschool/).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Effect}\n\t\t * @param {Frequency|Object} [frequency] Rate of left-right oscillation. \n\t\t * @example\n\t\t * //create an autopanner and start it's LFO\n\t\t * var autoPanner = new Tone.AutoPanner(\"4n\").toMaster().start();\n\t\t * //route an oscillator through the panner and start it\n\t\t * var oscillator = new Tone.Oscillator().connect(autoPanner).start();\n\t\t */\n\t Tone.AutoPanner = function () {\n\t var options = this.optionsObject(arguments, ['frequency'], Tone.AutoPanner.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * the lfo which drives the panning\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfo = new Tone.LFO({\n\t 'frequency': options.frequency,\n\t 'amplitude': options.depth,\n\t 'min': -1,\n\t 'max': 1\n\t });\n\t /**\n\t\t\t * The amount of panning between left and right. \n\t\t\t * 0 = always center. 1 = full range between left and right. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.depth = this._lfo.amplitude;\n\t /**\n\t\t\t * the panner node which does the panning\n\t\t\t * @type {Tone.Panner}\n\t\t\t * @private\n\t\t\t */\n\t this._panner = new Tone.Panner();\n\t /**\n\t\t\t * How fast the panner modulates between left and right. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._lfo.frequency;\n\t //connections\n\t this.connectEffect(this._panner);\n\t this._lfo.connect(this._panner.pan);\n\t this.type = options.type;\n\t this._readOnly([\n\t 'depth',\n\t 'frequency'\n\t ]);\n\t };\n\t //extend Effect\n\t Tone.extend(Tone.AutoPanner, Tone.Effect);\n\t /**\n\t\t * defaults\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.AutoPanner.defaults = {\n\t 'frequency': 1,\n\t 'type': 'sine',\n\t 'depth': 1\n\t };\n\t /**\n\t\t * Start the effect.\n\t\t * @param {Time} [time=now] When the LFO will start. \n\t\t * @returns {Tone.AutoPanner} this\n\t\t */\n\t Tone.AutoPanner.prototype.start = function (time) {\n\t this._lfo.start(time);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the effect.\n\t\t * @param {Time} [time=now] When the LFO will stop. \n\t\t * @returns {Tone.AutoPanner} this\n\t\t */\n\t Tone.AutoPanner.prototype.stop = function (time) {\n\t this._lfo.stop(time);\n\t return this;\n\t };\n\t /**\n\t\t * Sync the panner to the transport.\n\t\t * @param {Time} [delay=0] Delay time before starting the effect after the\n\t\t * Transport has started. \n\t\t * @returns {Tone.AutoPanner} this\n\t\t */\n\t Tone.AutoPanner.prototype.sync = function (delay) {\n\t this._lfo.sync(delay);\n\t return this;\n\t };\n\t /**\n\t\t * Unsync the panner from the transport\n\t\t * @returns {Tone.AutoPanner} this\n\t\t */\n\t Tone.AutoPanner.prototype.unsync = function () {\n\t this._lfo.unsync();\n\t return this;\n\t };\n\t /**\n\t\t * Type of oscillator attached to the AutoFilter. \n\t\t * Possible values: \"sine\", \"square\", \"triangle\", \"sawtooth\".\n\t\t * @memberOf Tone.AutoFilter#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.AutoPanner.prototype, 'type', {\n\t get: function () {\n\t return this._lfo.type;\n\t },\n\t set: function (type) {\n\t this._lfo.type = type;\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.AutoPanner} this\n\t\t */\n\t Tone.AutoPanner.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._lfo.dispose();\n\t this._lfo = null;\n\t this._panner.dispose();\n\t this._panner = null;\n\t this._writable([\n\t 'depth',\n\t 'frequency'\n\t ]);\n\t this.frequency = null;\n\t this.depth = null;\n\t return this;\n\t };\n\t return Tone.AutoPanner;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.AutoWah connects a Tone.Follower to a bandpass filter (Tone.Filter).\n\t\t * The frequency of the filter is adjusted proportionally to the \n\t\t * incoming signal's amplitude. Inspiration from [Tuna.js](https://github.com/Dinahmoe/tuna).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Effect}\n\t\t * @param {Frequency|Object} [baseFrequency] The frequency the filter is set \n\t\t * to at the low point of the wah\n\t\t * @param {Positive} [octaves] The number of octaves above the baseFrequency\n\t\t * the filter will sweep to when fully open\n\t\t * @param {Decibels} [sensitivity] The decibel threshold sensitivity for \n\t\t * the incoming signal. Normal range of -40 to 0. \n\t\t * @example\n\t\t * var autoWah = new Tone.AutoWah(50, 6, -30).toMaster();\n\t\t * //initialize the synth and connect to autowah\n\t\t * var synth = new Synth.connect(autoWah);\n\t\t * //Q value influences the effect of the wah - default is 2\n\t\t * autoWah.Q.value = 6;\n\t\t * //more audible on higher notes\n\t\t * synth.triggerAttackRelease(\"C4\", \"8n\")\n\t\t */\n\t Tone.AutoWah = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'baseFrequency',\n\t 'octaves',\n\t 'sensitivity'\n\t ], Tone.AutoWah.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * The envelope follower. Set the attack/release\n\t\t\t * timing to adjust how the envelope is followed. \n\t\t\t * @type {Tone.Follower}\n\t\t\t * @private\n\t\t\t */\n\t this.follower = new Tone.Follower(options.follower);\n\t /**\n\t\t\t * scales the follower value to the frequency domain\n\t\t\t * @type {Tone}\n\t\t\t * @private\n\t\t\t */\n\t this._sweepRange = new Tone.ScaleExp(0, 1, 0.5);\n\t /**\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._baseFrequency = options.baseFrequency;\n\t /**\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._octaves = options.octaves;\n\t /**\n\t\t\t * the input gain to adjust the sensitivity\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._inputBoost = new Tone.Gain();\n\t /**\n\t\t\t * @type {BiquadFilterNode}\n\t\t\t * @private\n\t\t\t */\n\t this._bandpass = new Tone.Filter({\n\t 'rolloff': -48,\n\t 'frequency': 0,\n\t 'Q': options.Q\n\t });\n\t /**\n\t\t\t * @type {Tone.Filter}\n\t\t\t * @private\n\t\t\t */\n\t this._peaking = new Tone.Filter(0, 'peaking');\n\t this._peaking.gain.value = options.gain;\n\t /**\n\t\t\t * The gain of the filter.\n\t\t\t * @type {Number}\n\t\t\t * @signal\n\t\t\t */\n\t this.gain = this._peaking.gain;\n\t /**\n\t\t\t * The quality of the filter.\n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this.Q = this._bandpass.Q;\n\t //the control signal path\n\t this.effectSend.chain(this._inputBoost, this.follower, this._sweepRange);\n\t this._sweepRange.connect(this._bandpass.frequency);\n\t this._sweepRange.connect(this._peaking.frequency);\n\t //the filtered path\n\t this.effectSend.chain(this._bandpass, this._peaking, this.effectReturn);\n\t //set the initial value\n\t this._setSweepRange();\n\t this.sensitivity = options.sensitivity;\n\t this._readOnly([\n\t 'gain',\n\t 'Q'\n\t ]);\n\t };\n\t Tone.extend(Tone.AutoWah, Tone.Effect);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.AutoWah.defaults = {\n\t 'baseFrequency': 100,\n\t 'octaves': 6,\n\t 'sensitivity': 0,\n\t 'Q': 2,\n\t 'gain': 2,\n\t 'follower': {\n\t 'attack': 0.3,\n\t 'release': 0.5\n\t }\n\t };\n\t /**\n\t\t * The number of octaves that the filter will sweep above the \n\t\t * baseFrequency. \n\t\t * @memberOf Tone.AutoWah#\n\t\t * @type {Number}\n\t\t * @name octaves\n\t\t */\n\t Object.defineProperty(Tone.AutoWah.prototype, 'octaves', {\n\t get: function () {\n\t return this._octaves;\n\t },\n\t set: function (octaves) {\n\t this._octaves = octaves;\n\t this._setSweepRange();\n\t }\n\t });\n\t /**\n\t\t * The base frequency from which the sweep will start from.\n\t\t * @memberOf Tone.AutoWah#\n\t\t * @type {Frequency}\n\t\t * @name baseFrequency\n\t\t */\n\t Object.defineProperty(Tone.AutoWah.prototype, 'baseFrequency', {\n\t get: function () {\n\t return this._baseFrequency;\n\t },\n\t set: function (baseFreq) {\n\t this._baseFrequency = baseFreq;\n\t this._setSweepRange();\n\t }\n\t });\n\t /**\n\t\t * The sensitivity to control how responsive to the input signal the filter is. \n\t\t * @memberOf Tone.AutoWah#\n\t\t * @type {Decibels}\n\t\t * @name sensitivity\n\t\t */\n\t Object.defineProperty(Tone.AutoWah.prototype, 'sensitivity', {\n\t get: function () {\n\t return this.gainToDb(1 / this._inputBoost.gain.value);\n\t },\n\t set: function (sensitivy) {\n\t this._inputBoost.gain.value = 1 / this.dbToGain(sensitivy);\n\t }\n\t });\n\t /**\n\t\t * sets the sweep range of the scaler\n\t\t * @private\n\t\t */\n\t Tone.AutoWah.prototype._setSweepRange = function () {\n\t this._sweepRange.min = this._baseFrequency;\n\t this._sweepRange.max = Math.min(this._baseFrequency * Math.pow(2, this._octaves), this.context.sampleRate / 2);\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.AutoWah} this\n\t\t */\n\t Tone.AutoWah.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this.follower.dispose();\n\t this.follower = null;\n\t this._sweepRange.dispose();\n\t this._sweepRange = null;\n\t this._bandpass.dispose();\n\t this._bandpass = null;\n\t this._peaking.dispose();\n\t this._peaking = null;\n\t this._inputBoost.dispose();\n\t this._inputBoost = null;\n\t this._writable([\n\t 'gain',\n\t 'Q'\n\t ]);\n\t this.gain = null;\n\t this.Q = null;\n\t return this;\n\t };\n\t return Tone.AutoWah;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Bitcrusher downsamples the incoming signal to a different bitdepth. \n\t\t * Lowering the bitdepth of the signal creates distortion. Read more about Bitcrushing\n\t\t * on [Wikipedia](https://en.wikipedia.org/wiki/Bitcrusher).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Effect}\n\t\t * @param {Number} bits The number of bits to downsample the signal. Nominal range\n\t\t * of 1 to 8. \n\t\t * @example\n\t\t * //initialize crusher and route a synth through it\n\t\t * var crusher = new Tone.BitCrusher(4).toMaster();\n\t\t * var synth = new Tone.MonoSynth().connect(crusher);\n\t\t */\n\t Tone.BitCrusher = function () {\n\t var options = this.optionsObject(arguments, ['bits'], Tone.BitCrusher.defaults);\n\t Tone.Effect.call(this, options);\n\t var invStepSize = 1 / Math.pow(2, options.bits - 1);\n\t /**\n\t\t\t * Subtract the input signal and the modulus of the input signal\n\t\t\t * @type {Tone.Subtract}\n\t\t\t * @private\n\t\t\t */\n\t this._subtract = new Tone.Subtract();\n\t /**\n\t\t\t * The mod function\n\t\t\t * @type {Tone.Modulo}\n\t\t\t * @private\n\t\t\t */\n\t this._modulo = new Tone.Modulo(invStepSize);\n\t /**\n\t\t\t * keeps track of the bits\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._bits = options.bits;\n\t //connect it up\n\t this.effectSend.fan(this._subtract, this._modulo);\n\t this._modulo.connect(this._subtract, 0, 1);\n\t this._subtract.connect(this.effectReturn);\n\t };\n\t Tone.extend(Tone.BitCrusher, Tone.Effect);\n\t /**\n\t\t * the default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.BitCrusher.defaults = { 'bits': 4 };\n\t /**\n\t\t * The bit depth of the effect. Nominal range of 1-8. \n\t\t * @memberOf Tone.BitCrusher#\n\t\t * @type {number}\n\t\t * @name bits\n\t\t */\n\t Object.defineProperty(Tone.BitCrusher.prototype, 'bits', {\n\t get: function () {\n\t return this._bits;\n\t },\n\t set: function (bits) {\n\t this._bits = bits;\n\t var invStepSize = 1 / Math.pow(2, bits - 1);\n\t this._modulo.value = invStepSize;\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.BitCrusher} this\n\t\t */\n\t Tone.BitCrusher.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._subtract.dispose();\n\t this._subtract = null;\n\t this._modulo.dispose();\n\t this._modulo = null;\n\t return this;\n\t };\n\t return Tone.BitCrusher;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.ChebyShev is a Chebyshev waveshaper, an effect which is good \n\t\t * for making different types of distortion sounds.\n\t\t * Note that odd orders sound very different from even ones, \n\t\t * and order = 1 is no change. \n\t\t * Read more at [music.columbia.edu](http://music.columbia.edu/cmc/musicandcomputers/chapter4/04_06.php).\n\t\t *\n\t\t * @extends {Tone.Effect}\n\t\t * @constructor\n\t\t * @param {Positive|Object} [order] The order of the chebyshev polynomial. Normal range between 1-100. \n\t\t * @example\n\t\t * //create a new cheby\n\t\t * var cheby = new Tone.Chebyshev(50);\n\t\t * //create a monosynth connected to our cheby\n\t\t * synth = new Tone.MonoSynth().connect(cheby);\n\t\t */\n\t Tone.Chebyshev = function () {\n\t var options = this.optionsObject(arguments, ['order'], Tone.Chebyshev.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * @type {WaveShaperNode}\n\t\t\t * @private\n\t\t\t */\n\t this._shaper = new Tone.WaveShaper(4096);\n\t /**\n\t\t\t * holds onto the order of the filter\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._order = options.order;\n\t this.connectEffect(this._shaper);\n\t this.order = options.order;\n\t this.oversample = options.oversample;\n\t };\n\t Tone.extend(Tone.Chebyshev, Tone.Effect);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Chebyshev.defaults = {\n\t 'order': 1,\n\t 'oversample': 'none'\n\t };\n\t /**\n\t\t * get the coefficient for that degree\n\t\t * @param {number} x the x value\n\t\t * @param {number} degree \n\t\t * @param {Object} memo memoize the computed value. \n\t\t * this speeds up computation greatly. \n\t\t * @return {number} the coefficient \n\t\t * @private\n\t\t */\n\t Tone.Chebyshev.prototype._getCoefficient = function (x, degree, memo) {\n\t if (memo.hasOwnProperty(degree)) {\n\t return memo[degree];\n\t } else if (degree === 0) {\n\t memo[degree] = 0;\n\t } else if (degree === 1) {\n\t memo[degree] = x;\n\t } else {\n\t memo[degree] = 2 * x * this._getCoefficient(x, degree - 1, memo) - this._getCoefficient(x, degree - 2, memo);\n\t }\n\t return memo[degree];\n\t };\n\t /**\n\t\t * The order of the Chebyshev polynomial which creates\n\t\t * the equation which is applied to the incoming \n\t\t * signal through a Tone.WaveShaper. The equations\n\t\t * are in the form:<br>\n\t\t * order 2: 2x^2 + 1<br>\n\t\t * order 3: 4x^3 + 3x <br>\n\t\t * @memberOf Tone.Chebyshev#\n\t\t * @type {Positive}\n\t\t * @name order\n\t\t */\n\t Object.defineProperty(Tone.Chebyshev.prototype, 'order', {\n\t get: function () {\n\t return this._order;\n\t },\n\t set: function (order) {\n\t this._order = order;\n\t var curve = new Array(4096);\n\t var len = curve.length;\n\t for (var i = 0; i < len; ++i) {\n\t var x = i * 2 / len - 1;\n\t if (x === 0) {\n\t //should output 0 when input is 0\n\t curve[i] = 0;\n\t } else {\n\t curve[i] = this._getCoefficient(x, order, {});\n\t }\n\t }\n\t this._shaper.curve = curve;\n\t }\n\t });\n\t /**\n\t\t * The oversampling of the effect. Can either be \"none\", \"2x\" or \"4x\".\n\t\t * @memberOf Tone.Chebyshev#\n\t\t * @type {string}\n\t\t * @name oversample\n\t\t */\n\t Object.defineProperty(Tone.Chebyshev.prototype, 'oversample', {\n\t get: function () {\n\t return this._shaper.oversample;\n\t },\n\t set: function (oversampling) {\n\t this._shaper.oversample = oversampling;\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Chebyshev} this\n\t\t */\n\t Tone.Chebyshev.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._shaper.dispose();\n\t this._shaper = null;\n\t return this;\n\t };\n\t return Tone.Chebyshev;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Base class for Stereo effects. Provides effectSendL/R and effectReturnL/R. \n\t\t *\n\t\t *\t@constructor\n\t\t *\t@extends {Tone.Effect}\n\t\t */\n\t Tone.StereoEffect = function () {\n\t this.createInsOuts(1, 1);\n\t //get the defaults\n\t var options = this.optionsObject(arguments, ['wet'], Tone.Effect.defaults);\n\t /**\n\t\t\t * the drywet knob to control the amount of effect\n\t\t\t * @type {Tone.CrossFade}\n\t\t\t * @private\n\t\t\t */\n\t this._dryWet = new Tone.CrossFade(options.wet);\n\t /**\n\t\t\t * The wet control, i.e. how much of the effected\n\t\t\t * will pass through to the output. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.wet = this._dryWet.fade;\n\t /**\n\t\t\t * then split it\n\t\t\t * @type {Tone.Split}\n\t\t\t * @private\n\t\t\t */\n\t this._split = new Tone.Split();\n\t /**\n\t\t\t * the effects send LEFT\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.effectSendL = this._split.left;\n\t /**\n\t\t\t * the effects send RIGHT\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.effectSendR = this._split.right;\n\t /**\n\t\t\t * the stereo effect merger\n\t\t\t * @type {Tone.Merge}\n\t\t\t * @private\n\t\t\t */\n\t this._merge = new Tone.Merge();\n\t /**\n\t\t\t * the effect return LEFT\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.effectReturnL = this._merge.left;\n\t /**\n\t\t\t * the effect return RIGHT\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.effectReturnR = this._merge.right;\n\t //connections\n\t this.input.connect(this._split);\n\t //dry wet connections\n\t this.input.connect(this._dryWet, 0, 0);\n\t this._merge.connect(this._dryWet, 0, 1);\n\t this._dryWet.connect(this.output);\n\t this._readOnly(['wet']);\n\t };\n\t Tone.extend(Tone.StereoEffect, Tone.Effect);\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.StereoEffect} this\n\t\t */\n\t Tone.StereoEffect.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._dryWet.dispose();\n\t this._dryWet = null;\n\t this._split.dispose();\n\t this._split = null;\n\t this._merge.dispose();\n\t this._merge = null;\n\t this.effectSendL = null;\n\t this.effectSendR = null;\n\t this.effectReturnL = null;\n\t this.effectReturnR = null;\n\t this._writable(['wet']);\n\t this.wet = null;\n\t return this;\n\t };\n\t return Tone.StereoEffect;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * \t@class Tone.FeedbackEffect provides a loop between an \n\t\t * \t audio source and its own output. This is a base-class\n\t\t * \t for feedback effects. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Effect}\n\t\t * @param {NormalRange|Object} [feedback] The initial feedback value.\n\t\t */\n\t Tone.FeedbackEffect = function () {\n\t var options = this.optionsObject(arguments, ['feedback']);\n\t options = this.defaultArg(options, Tone.FeedbackEffect.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * the gain which controls the feedback\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackGain = new Tone.Gain(options.feedback, Tone.Type.NormalRange);\n\t /**\n\t\t\t * The amount of signal which is fed back into the effect input. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.feedback = this._feedbackGain.gain;\n\t //the feedback loop\n\t this.effectReturn.chain(this._feedbackGain, this.effectSend);\n\t this._readOnly(['feedback']);\n\t };\n\t Tone.extend(Tone.FeedbackEffect, Tone.Effect);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.FeedbackEffect.defaults = { 'feedback': 0.125 };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.FeedbackEffect} this\n\t\t */\n\t Tone.FeedbackEffect.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._writable(['feedback']);\n\t this._feedbackGain.dispose();\n\t this._feedbackGain = null;\n\t this.feedback = null;\n\t return this;\n\t };\n\t return Tone.FeedbackEffect;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Just like a stereo feedback effect, but the feedback is routed from left to right\n\t\t * and right to left instead of on the same channel.\n\t\t *\n\t\t *\t@constructor\n\t\t *\t@extends {Tone.FeedbackEffect}\n\t\t */\n\t Tone.StereoXFeedbackEffect = function () {\n\t var options = this.optionsObject(arguments, ['feedback'], Tone.FeedbackEffect.defaults);\n\t Tone.StereoEffect.call(this, options);\n\t /**\n\t\t\t * The amount of feedback from the output\n\t\t\t * back into the input of the effect (routed\n\t\t\t * across left and right channels).\n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.feedback = new Tone.Signal(options.feedback, Tone.Type.NormalRange);\n\t /**\n\t\t\t * the left side feeback\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackLR = new Tone.Gain();\n\t /**\n\t\t\t * the right side feeback\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackRL = new Tone.Gain();\n\t //connect it up\n\t this.effectReturnL.chain(this._feedbackLR, this.effectSendR);\n\t this.effectReturnR.chain(this._feedbackRL, this.effectSendL);\n\t this.feedback.fan(this._feedbackLR.gain, this._feedbackRL.gain);\n\t this._readOnly(['feedback']);\n\t };\n\t Tone.extend(Tone.StereoXFeedbackEffect, Tone.FeedbackEffect);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.StereoXFeedbackEffect} this\n\t\t */\n\t Tone.StereoXFeedbackEffect.prototype.dispose = function () {\n\t Tone.StereoEffect.prototype.dispose.call(this);\n\t this._writable(['feedback']);\n\t this.feedback.dispose();\n\t this.feedback = null;\n\t this._feedbackLR.dispose();\n\t this._feedbackLR = null;\n\t this._feedbackRL.dispose();\n\t this._feedbackRL = null;\n\t return this;\n\t };\n\t return Tone.StereoXFeedbackEffect;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Chorus is a stereo chorus effect with feedback composed of \n\t\t * a left and right delay with a Tone.LFO applied to the delayTime of each channel. \n\t\t * Inspiration from [Tuna.js](https://github.com/Dinahmoe/tuna/blob/master/tuna.js).\n\t\t * Read more on the chorus effect on [SoundOnSound](http://www.soundonsound.com/sos/jun04/articles/synthsecrets.htm).\n\t\t *\n\t\t *\t@constructor\n\t\t *\t@extends {Tone.StereoXFeedbackEffect}\n\t\t *\t@param {Frequency|Object} [frequency] The frequency of the LFO.\n\t\t *\t@param {Milliseconds} [delayTime] The delay of the chorus effect in ms. \n\t\t *\t@param {NormalRange} [depth] The depth of the chorus.\n\t\t *\t@example\n\t\t * var chorus = new Tone.Chorus(4, 2.5, 0.5);\n\t\t * var synth = new Tone.PolySynth(4, Tone.MonoSynth).connect(chorus);\n\t\t * synth.triggerAttackRelease([\"C3\",\"E3\",\"G3\"], \"8n\");\n\t\t */\n\t Tone.Chorus = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'delayTime',\n\t 'depth'\n\t ], Tone.Chorus.defaults);\n\t Tone.StereoXFeedbackEffect.call(this, options);\n\t /**\n\t\t\t * the depth of the chorus\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._depth = options.depth;\n\t /**\n\t\t\t * the delayTime\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._delayTime = options.delayTime / 1000;\n\t /**\n\t\t\t * the lfo which controls the delayTime\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoL = new Tone.LFO({\n\t 'frequency': options.frequency,\n\t 'min': 0,\n\t 'max': 1\n\t });\n\t /**\n\t\t\t * another LFO for the right side with a 180 degree phase diff\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoR = new Tone.LFO({\n\t 'frequency': options.frequency,\n\t 'min': 0,\n\t 'max': 1,\n\t 'phase': 180\n\t });\n\t /**\n\t\t\t * delay for left\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._delayNodeL = new Tone.Delay();\n\t /**\n\t\t\t * delay for right\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._delayNodeR = new Tone.Delay();\n\t /**\n\t\t\t * The frequency of the LFO which modulates the delayTime. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._lfoL.frequency;\n\t //connections\n\t this.effectSendL.chain(this._delayNodeL, this.effectReturnL);\n\t this.effectSendR.chain(this._delayNodeR, this.effectReturnR);\n\t //and pass through to make the detune apparent\n\t this.effectSendL.connect(this.effectReturnL);\n\t this.effectSendR.connect(this.effectReturnR);\n\t //lfo setup\n\t this._lfoL.connect(this._delayNodeL.delayTime);\n\t this._lfoR.connect(this._delayNodeR.delayTime);\n\t //start the lfo\n\t this._lfoL.start();\n\t this._lfoR.start();\n\t //have one LFO frequency control the other\n\t this._lfoL.frequency.connect(this._lfoR.frequency);\n\t //set the initial values\n\t this.depth = this._depth;\n\t this.frequency.value = options.frequency;\n\t this.type = options.type;\n\t this._readOnly(['frequency']);\n\t this.spread = options.spread;\n\t };\n\t Tone.extend(Tone.Chorus, Tone.StereoXFeedbackEffect);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Chorus.defaults = {\n\t 'frequency': 1.5,\n\t 'delayTime': 3.5,\n\t 'depth': 0.7,\n\t 'feedback': 0.1,\n\t 'type': 'sine',\n\t 'spread': 180\n\t };\n\t /**\n\t\t * The depth of the effect. A depth of 1 makes the delayTime\n\t\t * modulate between 0 and 2*delayTime (centered around the delayTime). \n\t\t * @memberOf Tone.Chorus#\n\t\t * @type {NormalRange}\n\t\t * @name depth\n\t\t */\n\t Object.defineProperty(Tone.Chorus.prototype, 'depth', {\n\t get: function () {\n\t return this._depth;\n\t },\n\t set: function (depth) {\n\t this._depth = depth;\n\t var deviation = this._delayTime * depth;\n\t this._lfoL.min = Math.max(this._delayTime - deviation, 0);\n\t this._lfoL.max = this._delayTime + deviation;\n\t this._lfoR.min = Math.max(this._delayTime - deviation, 0);\n\t this._lfoR.max = this._delayTime + deviation;\n\t }\n\t });\n\t /**\n\t\t * The delayTime in milliseconds of the chorus. A larger delayTime\n\t\t * will give a more pronounced effect. Nominal range a delayTime\n\t\t * is between 2 and 20ms. \n\t\t * @memberOf Tone.Chorus#\n\t\t * @type {Milliseconds}\n\t\t * @name delayTime\n\t\t */\n\t Object.defineProperty(Tone.Chorus.prototype, 'delayTime', {\n\t get: function () {\n\t return this._delayTime * 1000;\n\t },\n\t set: function (delayTime) {\n\t this._delayTime = delayTime / 1000;\n\t this.depth = this._depth;\n\t }\n\t });\n\t /**\n\t\t * The oscillator type of the LFO. \n\t\t * @memberOf Tone.Chorus#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.Chorus.prototype, 'type', {\n\t get: function () {\n\t return this._lfoL.type;\n\t },\n\t set: function (type) {\n\t this._lfoL.type = type;\n\t this._lfoR.type = type;\n\t }\n\t });\n\t /** \n\t\t * Amount of stereo spread. When set to 0, both LFO's will be panned centrally.\n\t\t * When set to 180, LFO's will be panned hard left and right respectively.\n\t\t * @memberOf Tone.Chorus#\n\t\t * @type {Degrees}\n\t\t * @name spread\n\t\t */\n\t Object.defineProperty(Tone.Chorus.prototype, 'spread', {\n\t get: function () {\n\t return this._lfoR.phase - this._lfoL.phase; //180\n\t },\n\t set: function (spread) {\n\t this._lfoL.phase = 90 - spread / 2;\n\t this._lfoR.phase = spread / 2 + 90;\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Chorus} this\n\t\t */\n\t Tone.Chorus.prototype.dispose = function () {\n\t Tone.StereoXFeedbackEffect.prototype.dispose.call(this);\n\t this._lfoL.dispose();\n\t this._lfoL = null;\n\t this._lfoR.dispose();\n\t this._lfoR = null;\n\t this._delayNodeL.dispose();\n\t this._delayNodeL = null;\n\t this._delayNodeR.dispose();\n\t this._delayNodeR = null;\n\t this._writable('frequency');\n\t this.frequency = null;\n\t return this;\n\t };\n\t return Tone.Chorus;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Convolver is a wrapper around the Native Web Audio \n\t\t * [ConvolverNode](http://webaudio.github.io/web-audio-api/#the-convolvernode-interface).\n\t\t * Convolution is useful for reverb and filter emulation. Read more about convolution reverb on\n\t\t * [Wikipedia](https://en.wikipedia.org/wiki/Convolution_reverb).\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Effect}\n\t\t * @param {string|Tone.Buffer|Object} [url] The URL of the impulse response or the Tone.Buffer\n\t\t * contianing the impulse response. \n\t\t * @param {Function} onload The callback to invoke when the url is loaded.\n\t\t * @example\n\t\t * //initializing the convolver with an impulse response\n\t\t * var convolver = new Tone.Convolver(\"./path/to/ir.wav\").toMaster();\n\t\t */\n\t Tone.Convolver = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'url',\n\t 'onload'\n\t ], Tone.Convolver.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * convolver node\n\t\t\t * @type {ConvolverNode}\n\t\t\t * @private\n\t\t\t */\n\t this._convolver = this.context.createConvolver();\n\t /**\n\t\t\t * the convolution buffer\n\t\t\t * @type {Tone.Buffer}\n\t\t\t * @private\n\t\t\t */\n\t this._buffer = new Tone.Buffer();\n\t if (this.isString(options.url)) {\n\t this._buffer.load(options.url, function (buffer) {\n\t this.buffer = buffer;\n\t options.onload();\n\t }.bind(this));\n\t } else if (options.url) {\n\t this.buffer = options.url;\n\t options.onload();\n\t }\n\t this.connectEffect(this._convolver);\n\t };\n\t Tone.extend(Tone.Convolver, Tone.Effect);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Convolver.defaults = { 'onload': Tone.noOp };\n\t /**\n\t\t * The convolver's buffer\n\t\t * @memberOf Tone.Convolver#\n\t\t * @type {AudioBuffer}\n\t\t * @name buffer\n\t\t */\n\t Object.defineProperty(Tone.Convolver.prototype, 'buffer', {\n\t get: function () {\n\t return this._buffer.get();\n\t },\n\t set: function (buffer) {\n\t this._buffer.set(buffer);\n\t this._convolver.buffer = this._buffer.get();\n\t }\n\t });\n\t /**\n\t\t * Load an impulse response url as an audio buffer.\n\t\t * Decodes the audio asynchronously and invokes\n\t\t * the callback once the audio buffer loads.\n\t\t * @param {string} url The url of the buffer to load.\n\t\t * filetype support depends on the\n\t\t * browser.\n\t\t * @param {function=} callback\n\t\t * @returns {Promise}\n\t\t */\n\t Tone.Convolver.prototype.load = function (url, callback) {\n\t return this._buffer.load(url, function (buff) {\n\t this.buffer = buff;\n\t if (callback) {\n\t callback();\n\t }\n\t }.bind(this));\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Convolver} this\n\t\t */\n\t Tone.Convolver.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._convolver.disconnect();\n\t this._convolver = null;\n\t this._buffer.dispose();\n\t this._buffer = null;\n\t return this;\n\t };\n\t return Tone.Convolver;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Distortion is a simple distortion effect using Tone.WaveShaper.\n\t\t * Algorithm from [a stackoverflow answer](http://stackoverflow.com/a/22313408).\n\t\t *\n\t\t * @extends {Tone.Effect}\n\t\t * @constructor\n\t\t * @param {Number|Object} [distortion] The amount of distortion (nominal range of 0-1)\n\t\t * @example\n\t\t * var dist = new Tone.Distortion(0.8).toMaster();\n\t\t * var fm = new Tone.SimpleFM().connect(dist);\n\t\t * //this sounds good on bass notes\n\t\t * fm.triggerAttackRelease(\"A1\", \"8n\");\n\t\t */\n\t Tone.Distortion = function () {\n\t var options = this.optionsObject(arguments, ['distortion'], Tone.Distortion.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * @type {Tone.WaveShaper}\n\t\t\t * @private\n\t\t\t */\n\t this._shaper = new Tone.WaveShaper(4096);\n\t /**\n\t\t\t * holds the distortion amount\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._distortion = options.distortion;\n\t this.connectEffect(this._shaper);\n\t this.distortion = options.distortion;\n\t this.oversample = options.oversample;\n\t };\n\t Tone.extend(Tone.Distortion, Tone.Effect);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Distortion.defaults = {\n\t 'distortion': 0.4,\n\t 'oversample': 'none'\n\t };\n\t /**\n\t\t * The amount of distortion.\n\t\t * @memberOf Tone.Distortion#\n\t\t * @type {NormalRange}\n\t\t * @name distortion\n\t\t */\n\t Object.defineProperty(Tone.Distortion.prototype, 'distortion', {\n\t get: function () {\n\t return this._distortion;\n\t },\n\t set: function (amount) {\n\t this._distortion = amount;\n\t var k = amount * 100;\n\t var deg = Math.PI / 180;\n\t this._shaper.setMap(function (x) {\n\t if (Math.abs(x) < 0.001) {\n\t //should output 0 when input is 0\n\t return 0;\n\t } else {\n\t return (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));\n\t }\n\t });\n\t }\n\t });\n\t /**\n\t\t * The oversampling of the effect. Can either be \"none\", \"2x\" or \"4x\".\n\t\t * @memberOf Tone.Distortion#\n\t\t * @type {string}\n\t\t * @name oversample\n\t\t */\n\t Object.defineProperty(Tone.Distortion.prototype, 'oversample', {\n\t get: function () {\n\t return this._shaper.oversample;\n\t },\n\t set: function (oversampling) {\n\t this._shaper.oversample = oversampling;\n\t }\n\t });\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Distortion} this\n\t\t */\n\t Tone.Distortion.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._shaper.dispose();\n\t this._shaper = null;\n\t return this;\n\t };\n\t return Tone.Distortion;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.FeedbackDelay is a DelayNode in which part of output\n\t\t * signal is fed back into the delay. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.FeedbackEffect}\n\t\t * @param {Time|Object} [delayTime] The delay applied to the incoming signal. \n\t\t * @param {NormalRange=} feedback The amount of the effected signal which \n\t\t * is fed back through the delay.\n\t\t * @example\n\t\t * var feedbackDelay = new Tone.FeedbackDelay(\"8n\", 0.5).toMaster();\n\t\t * var tom = new Tone.DrumSynth({\n\t\t * \t\"octaves\" : 4,\n\t\t * \t\"pitchDecay\" : 0.1\n\t\t * }).connect(feedbackDelay);\n\t\t * tom.triggerAttackRelease(\"A2\",\"32n\");\n\t\t */\n\t Tone.FeedbackDelay = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'delayTime',\n\t 'feedback'\n\t ], Tone.FeedbackDelay.defaults);\n\t Tone.FeedbackEffect.call(this, options);\n\t /**\n\t\t\t * the delay node\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._delayNode = new Tone.Delay(options.delayTime);\n\t /**\n\t\t\t * The delayTime of the DelayNode. \n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.delayTime = this._delayNode.delayTime;\n\t // connect it up\n\t this.connectEffect(this._delayNode);\n\t this._readOnly(['delayTime']);\n\t };\n\t Tone.extend(Tone.FeedbackDelay, Tone.FeedbackEffect);\n\t /**\n\t\t * The default values. \n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.FeedbackDelay.defaults = { 'delayTime': 0.25 };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.FeedbackDelay} this\n\t\t */\n\t Tone.FeedbackDelay.prototype.dispose = function () {\n\t Tone.FeedbackEffect.prototype.dispose.call(this);\n\t this._delayNode.dispose();\n\t this._delayNode = null;\n\t this._writable(['delayTime']);\n\t this.delayTime = null;\n\t return this;\n\t };\n\t return Tone.FeedbackDelay;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * an array of comb filter delay values from Freeverb implementation\n\t\t * @static\n\t\t * @private\n\t\t * @type {Array}\n\t\t */\n\t var combFilterTunings = [\n\t 1557 / 44100,\n\t 1617 / 44100,\n\t 1491 / 44100,\n\t 1422 / 44100,\n\t 1277 / 44100,\n\t 1356 / 44100,\n\t 1188 / 44100,\n\t 1116 / 44100\n\t ];\n\t /**\n\t\t * an array of allpass filter frequency values from Freeverb implementation\n\t\t * @private\n\t\t * @static\n\t\t * @type {Array}\n\t\t */\n\t var allpassFilterFrequencies = [\n\t 225,\n\t 556,\n\t 441,\n\t 341\n\t ];\n\t /**\n\t\t * @class Tone.Freeverb is a reverb based on [Freeverb](https://ccrma.stanford.edu/~jos/pasp/Freeverb.html).\n\t\t * Read more on reverb on [SoundOnSound](http://www.soundonsound.com/sos/may00/articles/reverb.htm).\n\t\t *\n\t\t * @extends {Tone.Effect}\n\t\t * @constructor\n\t\t * @param {NormalRange|Object} [roomSize] Correlated to the decay time. \n\t\t * @param {Frequency} [dampening] The cutoff frequency of a lowpass filter as part \n\t\t * of the reverb. \n\t\t * @example\n\t\t * var freeverb = new Tone.Freeverb().toMaster();\n\t\t * freeverb.dampening.value = 1000;\n\t\t * //routing synth through the reverb\n\t\t * var synth = new Tone.AMSynth().connect(freeverb);\n\t\t */\n\t Tone.Freeverb = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'roomSize',\n\t 'dampening'\n\t ], Tone.Freeverb.defaults);\n\t Tone.StereoEffect.call(this, options);\n\t /**\n\t\t\t * The roomSize value between. A larger roomSize\n\t\t\t * will result in a longer decay. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.roomSize = new Tone.Signal(options.roomSize, Tone.Type.NormalRange);\n\t /**\n\t\t\t * The amount of dampening of the reverberant signal. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.dampening = new Tone.Signal(options.dampening, Tone.Type.Frequency);\n\t /**\n\t\t\t * the comb filters\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._combFilters = [];\n\t /**\n\t\t\t * the allpass filters on the left\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._allpassFiltersL = [];\n\t /**\n\t\t\t * the allpass filters on the right\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._allpassFiltersR = [];\n\t //make the allpass filters on the right\n\t for (var l = 0; l < allpassFilterFrequencies.length; l++) {\n\t var allpassL = this.context.createBiquadFilter();\n\t allpassL.type = 'allpass';\n\t allpassL.frequency.value = allpassFilterFrequencies[l];\n\t this._allpassFiltersL.push(allpassL);\n\t }\n\t //make the allpass filters on the left\n\t for (var r = 0; r < allpassFilterFrequencies.length; r++) {\n\t var allpassR = this.context.createBiquadFilter();\n\t allpassR.type = 'allpass';\n\t allpassR.frequency.value = allpassFilterFrequencies[r];\n\t this._allpassFiltersR.push(allpassR);\n\t }\n\t //make the comb filters\n\t for (var c = 0; c < combFilterTunings.length; c++) {\n\t var lfpf = new Tone.LowpassCombFilter(combFilterTunings[c]);\n\t if (c < combFilterTunings.length / 2) {\n\t this.effectSendL.chain(lfpf, this._allpassFiltersL[0]);\n\t } else {\n\t this.effectSendR.chain(lfpf, this._allpassFiltersR[0]);\n\t }\n\t this.roomSize.connect(lfpf.resonance);\n\t this.dampening.connect(lfpf.dampening);\n\t this._combFilters.push(lfpf);\n\t }\n\t //chain the allpass filters togetehr\n\t this.connectSeries.apply(this, this._allpassFiltersL);\n\t this.connectSeries.apply(this, this._allpassFiltersR);\n\t this._allpassFiltersL[this._allpassFiltersL.length - 1].connect(this.effectReturnL);\n\t this._allpassFiltersR[this._allpassFiltersR.length - 1].connect(this.effectReturnR);\n\t this._readOnly([\n\t 'roomSize',\n\t 'dampening'\n\t ]);\n\t };\n\t Tone.extend(Tone.Freeverb, Tone.StereoEffect);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Freeverb.defaults = {\n\t 'roomSize': 0.7,\n\t 'dampening': 3000\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.Freeverb} this\n\t\t */\n\t Tone.Freeverb.prototype.dispose = function () {\n\t Tone.StereoEffect.prototype.dispose.call(this);\n\t for (var al = 0; al < this._allpassFiltersL.length; al++) {\n\t this._allpassFiltersL[al].disconnect();\n\t this._allpassFiltersL[al] = null;\n\t }\n\t this._allpassFiltersL = null;\n\t for (var ar = 0; ar < this._allpassFiltersR.length; ar++) {\n\t this._allpassFiltersR[ar].disconnect();\n\t this._allpassFiltersR[ar] = null;\n\t }\n\t this._allpassFiltersR = null;\n\t for (var cf = 0; cf < this._combFilters.length; cf++) {\n\t this._combFilters[cf].dispose();\n\t this._combFilters[cf] = null;\n\t }\n\t this._combFilters = null;\n\t this._writable([\n\t 'roomSize',\n\t 'dampening'\n\t ]);\n\t this.roomSize.dispose();\n\t this.roomSize = null;\n\t this.dampening.dispose();\n\t this.dampening = null;\n\t return this;\n\t };\n\t return Tone.Freeverb;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * an array of the comb filter delay time values\n\t\t * @private\n\t\t * @static\n\t\t * @type {Array}\n\t\t */\n\t var combFilterDelayTimes = [\n\t 1687 / 25000,\n\t 1601 / 25000,\n\t 2053 / 25000,\n\t 2251 / 25000\n\t ];\n\t /**\n\t\t * the resonances of each of the comb filters\n\t\t * @private\n\t\t * @static\n\t\t * @type {Array}\n\t\t */\n\t var combFilterResonances = [\n\t 0.773,\n\t 0.802,\n\t 0.753,\n\t 0.733\n\t ];\n\t /**\n\t\t * the allpass filter frequencies\n\t\t * @private\n\t\t * @static\n\t\t * @type {Array}\n\t\t */\n\t var allpassFilterFreqs = [\n\t 347,\n\t 113,\n\t 37\n\t ];\n\t /**\n\t\t * @class Tone.JCReverb is a simple [Schroeder Reverberator](https://ccrma.stanford.edu/~jos/pasp/Schroeder_Reverberators.html)\n\t\t * tuned by John Chowning in 1970.\n\t\t * It is made up of three allpass filters and four Tone.FeedbackCombFilter. \n\t\t * \n\t\t *\n\t\t * @extends {Tone.Effect}\n\t\t * @constructor\n\t\t * @param {NormalRange|Object} [roomSize] Coorelates to the decay time.\n\t\t * @example\n\t\t * var reverb = new Tone.JCReverb(0.4).connect(Tone.Master);\n\t\t * var delay = new Tone.FeedbackDelay(0.5); \n\t\t * //connecting the synth to reverb through delay\n\t\t * var synth = new Tone.DuoSynth().chain(delay, reverb);\n\t\t * synth.triggerAttackRelease(\"A4\",\"8n\");\n\t\t */\n\t Tone.JCReverb = function () {\n\t var options = this.optionsObject(arguments, ['roomSize'], Tone.JCReverb.defaults);\n\t Tone.StereoEffect.call(this, options);\n\t /**\n\t\t\t * room size control values between [0,1]\n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.roomSize = new Tone.Signal(options.roomSize, Tone.Type.NormalRange);\n\t /**\n\t\t\t * scale the room size\n\t\t\t * @type {Tone.Scale}\n\t\t\t * @private\n\t\t\t */\n\t this._scaleRoomSize = new Tone.Scale(-0.733, 0.197);\n\t /**\n\t\t\t * a series of allpass filters\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._allpassFilters = [];\n\t /**\n\t\t\t * parallel feedback comb filters\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackCombFilters = [];\n\t //make the allpass filters\n\t for (var af = 0; af < allpassFilterFreqs.length; af++) {\n\t var allpass = this.context.createBiquadFilter();\n\t allpass.type = 'allpass';\n\t allpass.frequency.value = allpassFilterFreqs[af];\n\t this._allpassFilters.push(allpass);\n\t }\n\t //and the comb filters\n\t for (var cf = 0; cf < combFilterDelayTimes.length; cf++) {\n\t var fbcf = new Tone.FeedbackCombFilter(combFilterDelayTimes[cf], 0.1);\n\t this._scaleRoomSize.connect(fbcf.resonance);\n\t fbcf.resonance.value = combFilterResonances[cf];\n\t this._allpassFilters[this._allpassFilters.length - 1].connect(fbcf);\n\t if (cf < combFilterDelayTimes.length / 2) {\n\t fbcf.connect(this.effectReturnL);\n\t } else {\n\t fbcf.connect(this.effectReturnR);\n\t }\n\t this._feedbackCombFilters.push(fbcf);\n\t }\n\t //chain the allpass filters together\n\t this.roomSize.connect(this._scaleRoomSize);\n\t this.connectSeries.apply(this, this._allpassFilters);\n\t this.effectSendL.connect(this._allpassFilters[0]);\n\t this.effectSendR.connect(this._allpassFilters[0]);\n\t this._readOnly(['roomSize']);\n\t };\n\t Tone.extend(Tone.JCReverb, Tone.StereoEffect);\n\t /**\n\t\t * the default values\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.JCReverb.defaults = { 'roomSize': 0.5 };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.JCReverb} this\n\t\t */\n\t Tone.JCReverb.prototype.dispose = function () {\n\t Tone.StereoEffect.prototype.dispose.call(this);\n\t for (var apf = 0; apf < this._allpassFilters.length; apf++) {\n\t this._allpassFilters[apf].disconnect();\n\t this._allpassFilters[apf] = null;\n\t }\n\t this._allpassFilters = null;\n\t for (var fbcf = 0; fbcf < this._feedbackCombFilters.length; fbcf++) {\n\t this._feedbackCombFilters[fbcf].dispose();\n\t this._feedbackCombFilters[fbcf] = null;\n\t }\n\t this._feedbackCombFilters = null;\n\t this._writable(['roomSize']);\n\t this.roomSize.dispose();\n\t this.roomSize = null;\n\t this._scaleRoomSize.dispose();\n\t this._scaleRoomSize = null;\n\t return this;\n\t };\n\t return Tone.JCReverb;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Mid/Side processing separates the the 'mid' signal \n\t\t * (which comes out of both the left and the right channel) \n\t\t * and the 'side' (which only comes out of the the side channels) \n\t\t * and effects them separately before being recombined.\n\t\t * Applies a Mid/Side seperation and recombination.\n\t\t * Algorithm found in [kvraudio forums](http://www.kvraudio.com/forum/viewtopic.php?t=212587).\n\t\t * <br><br>\n\t\t * This is a base-class for Mid/Side Effects. \n\t\t *\n\t\t * @extends {Tone.Effect}\n\t\t * @constructor\n\t\t */\n\t Tone.MidSideEffect = function () {\n\t Tone.Effect.apply(this, arguments);\n\t /**\n\t\t\t * The mid/side split\n\t\t\t * @type {Tone.MidSideSplit}\n\t\t\t * @private\n\t\t\t */\n\t this._midSideSplit = new Tone.MidSideSplit();\n\t /**\n\t\t\t * The mid/side merge\n\t\t\t * @type {Tone.MidSideMerge}\n\t\t\t * @private\n\t\t\t */\n\t this._midSideMerge = new Tone.MidSideMerge();\n\t /**\n\t\t\t * The mid send. Connect to mid processing\n\t\t\t * @type {Tone.Expr}\n\t\t\t * @private\n\t\t\t */\n\t this.midSend = this._midSideSplit.mid;\n\t /**\n\t\t\t * The side send. Connect to side processing\n\t\t\t * @type {Tone.Expr}\n\t\t\t * @private\n\t\t\t */\n\t this.sideSend = this._midSideSplit.side;\n\t /**\n\t\t\t * The mid return connection\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.midReturn = this._midSideMerge.mid;\n\t /**\n\t\t\t * The side return connection\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this.sideReturn = this._midSideMerge.side;\n\t //the connections\n\t this.effectSend.connect(this._midSideSplit);\n\t this._midSideMerge.connect(this.effectReturn);\n\t };\n\t Tone.extend(Tone.MidSideEffect, Tone.Effect);\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.MidSideEffect} this\n\t\t */\n\t Tone.MidSideEffect.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._midSideSplit.dispose();\n\t this._midSideSplit = null;\n\t this._midSideMerge.dispose();\n\t this._midSideMerge = null;\n\t this.midSend = null;\n\t this.sideSend = null;\n\t this.midReturn = null;\n\t this.sideReturn = null;\n\t return this;\n\t };\n\t return Tone.MidSideEffect;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Phaser is a phaser effect. Phasers work by changing the phase\n\t\t * of different frequency components of an incoming signal. Read more on \n\t\t * [Wikipedia](https://en.wikipedia.org/wiki/Phaser_(effect)). \n\t\t * Inspiration for this phaser comes from [Tuna.js](https://github.com/Dinahmoe/tuna/).\n\t\t *\n\t\t *\t@extends {Tone.StereoEffect}\n\t\t *\t@constructor\n\t\t *\t@param {Frequency|Object} [frequency] The speed of the phasing. \n\t\t *\t@param {number} [octaves] The octaves of the effect. \n\t\t *\t@param {Frequency} [baseFrequency] The base frequency of the filters. \n\t\t *\t@example\n\t\t * var phaser = new Tone.Phaser({\n\t\t * \t\"frequency\" : 15, \n\t\t * \t\"octaves\" : 5, \n\t\t * \t\"baseFrequency\" : 1000\n\t\t * }).toMaster();\n\t\t * var synth = new Tone.FMSynth().connect(phaser);\n\t\t * synth.triggerAttackRelease(\"E3\", \"2n\");\n\t\t */\n\t Tone.Phaser = function () {\n\t //set the defaults\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'octaves',\n\t 'baseFrequency'\n\t ], Tone.Phaser.defaults);\n\t Tone.StereoEffect.call(this, options);\n\t /**\n\t\t\t * the lfo which controls the frequency on the left side\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoL = new Tone.LFO(options.frequency, 0, 1);\n\t /**\n\t\t\t * the lfo which controls the frequency on the right side\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoR = new Tone.LFO(options.frequency, 0, 1);\n\t this._lfoR.phase = 180;\n\t /**\n\t\t\t * the base modulation frequency\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._baseFrequency = options.baseFrequency;\n\t /**\n\t\t\t * the octaves of the phasing\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._octaves = options.octaves;\n\t /**\n\t\t\t * The quality factor of the filters\n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this.Q = new Tone.Signal(options.Q, Tone.Type.Positive);\n\t /**\n\t\t\t * the array of filters for the left side\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._filtersL = this._makeFilters(options.stages, this._lfoL, this.Q);\n\t /**\n\t\t\t * the array of filters for the left side\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._filtersR = this._makeFilters(options.stages, this._lfoR, this.Q);\n\t /**\n\t\t\t * the frequency of the effect\n\t\t\t * @type {Tone.Signal}\n\t\t\t */\n\t this.frequency = this._lfoL.frequency;\n\t this.frequency.value = options.frequency;\n\t //connect them up\n\t this.effectSendL.connect(this._filtersL[0]);\n\t this.effectSendR.connect(this._filtersR[0]);\n\t this._filtersL[options.stages - 1].connect(this.effectReturnL);\n\t this._filtersR[options.stages - 1].connect(this.effectReturnR);\n\t //control the frequency with one LFO\n\t this._lfoL.frequency.connect(this._lfoR.frequency);\n\t //set the options\n\t this.baseFrequency = options.baseFrequency;\n\t this.octaves = options.octaves;\n\t //start the lfo\n\t this._lfoL.start();\n\t this._lfoR.start();\n\t this._readOnly([\n\t 'frequency',\n\t 'Q'\n\t ]);\n\t };\n\t Tone.extend(Tone.Phaser, Tone.StereoEffect);\n\t /**\n\t\t * defaults\n\t\t * @static\n\t\t * @type {object}\n\t\t */\n\t Tone.Phaser.defaults = {\n\t 'frequency': 0.5,\n\t 'octaves': 3,\n\t 'stages': 10,\n\t 'Q': 10,\n\t 'baseFrequency': 350\n\t };\n\t /**\n\t\t * @param {number} stages\n\t\t * @returns {Array} the number of filters all connected together\n\t\t * @private\n\t\t */\n\t Tone.Phaser.prototype._makeFilters = function (stages, connectToFreq, Q) {\n\t var filters = new Array(stages);\n\t //make all the filters\n\t for (var i = 0; i < stages; i++) {\n\t var filter = this.context.createBiquadFilter();\n\t filter.type = 'allpass';\n\t Q.connect(filter.Q);\n\t connectToFreq.connect(filter.frequency);\n\t filters[i] = filter;\n\t }\n\t this.connectSeries.apply(this, filters);\n\t return filters;\n\t };\n\t /**\n\t\t * The number of octaves the phase goes above\n\t\t * the baseFrequency\n\t\t * @memberOf Tone.Phaser#\n\t\t * @type {Positive}\n\t\t * @name octaves\n\t\t */\n\t Object.defineProperty(Tone.Phaser.prototype, 'octaves', {\n\t get: function () {\n\t return this._octaves;\n\t },\n\t set: function (octaves) {\n\t this._octaves = octaves;\n\t var max = this._baseFrequency * Math.pow(2, octaves);\n\t this._lfoL.max = max;\n\t this._lfoR.max = max;\n\t }\n\t });\n\t /**\n\t\t * The the base frequency of the filters. \n\t\t * @memberOf Tone.Phaser#\n\t\t * @type {number}\n\t\t * @name baseFrequency\n\t\t */\n\t Object.defineProperty(Tone.Phaser.prototype, 'baseFrequency', {\n\t get: function () {\n\t return this._baseFrequency;\n\t },\n\t set: function (freq) {\n\t this._baseFrequency = freq;\n\t this._lfoL.min = freq;\n\t this._lfoR.min = freq;\n\t this.octaves = this._octaves;\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Phaser} this\n\t\t */\n\t Tone.Phaser.prototype.dispose = function () {\n\t Tone.StereoEffect.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'Q'\n\t ]);\n\t this.Q.dispose();\n\t this.Q = null;\n\t this._lfoL.dispose();\n\t this._lfoL = null;\n\t this._lfoR.dispose();\n\t this._lfoR = null;\n\t for (var i = 0; i < this._filtersL.length; i++) {\n\t this._filtersL[i].disconnect();\n\t this._filtersL[i] = null;\n\t }\n\t this._filtersL = null;\n\t for (var j = 0; j < this._filtersR.length; j++) {\n\t this._filtersR[j].disconnect();\n\t this._filtersR[j] = null;\n\t }\n\t this._filtersR = null;\n\t this.frequency = null;\n\t return this;\n\t };\n\t return Tone.Phaser;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.PingPongDelay is a feedback delay effect where the echo is heard\n\t\t * first in one channel and next in the opposite channel. In a stereo\n\t\t * system these are the right and left channels.\n\t\t * PingPongDelay in more simplified terms is two Tone.FeedbackDelays \n\t\t * with independent delay values. Each delay is routed to one channel\n\t\t * (left or right), and the channel triggered second will always \n\t\t * trigger at the same interval after the first.\n\t\t *\n\t\t * \t@constructor\n\t\t * \t@extends {Tone.StereoXFeedbackEffect}\n\t\t * @param {Time|Object} [delayTime] The delayTime between consecutive echos.\n\t\t * @param {NormalRange=} feedback The amount of the effected signal which \n\t\t * is fed back through the delay.\n\t\t * @example\n\t\t * var pingPong = new Tone.PingPongDelay(\"4n\", 0.2).toMaster();\n\t\t * var drum = new Tone.DrumSynth().connect(pingPong);\n\t\t * drum.triggerAttackRelease(\"C4\", \"32n\");\n\t\t */\n\t Tone.PingPongDelay = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'delayTime',\n\t 'feedback'\n\t ], Tone.PingPongDelay.defaults);\n\t Tone.StereoXFeedbackEffect.call(this, options);\n\t /**\n\t\t\t * the delay node on the left side\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._leftDelay = new Tone.Delay(0, options.maxDelayTime);\n\t /**\n\t\t\t * the delay node on the right side\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._rightDelay = new Tone.Delay(0, options.maxDelayTime);\n\t /**\n\t\t\t * the predelay on the right side\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._rightPreDelay = new Tone.Delay(0, options.maxDelayTime);\n\t /**\n\t\t\t * the delay time signal\n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.delayTime = new Tone.Signal(options.delayTime, Tone.Type.Time);\n\t //connect it up\n\t this.effectSendL.chain(this._leftDelay, this.effectReturnL);\n\t this.effectSendR.chain(this._rightPreDelay, this._rightDelay, this.effectReturnR);\n\t this.delayTime.fan(this._leftDelay.delayTime, this._rightDelay.delayTime, this._rightPreDelay.delayTime);\n\t //rearranged the feedback to be after the rightPreDelay\n\t this._feedbackLR.disconnect();\n\t this._feedbackLR.connect(this._rightDelay);\n\t this._readOnly(['delayTime']);\n\t };\n\t Tone.extend(Tone.PingPongDelay, Tone.StereoXFeedbackEffect);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.PingPongDelay.defaults = {\n\t 'delayTime': 0.25,\n\t 'maxDelayTime': 1\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.PingPongDelay} this\n\t\t */\n\t Tone.PingPongDelay.prototype.dispose = function () {\n\t Tone.StereoXFeedbackEffect.prototype.dispose.call(this);\n\t this._leftDelay.dispose();\n\t this._leftDelay = null;\n\t this._rightDelay.dispose();\n\t this._rightDelay = null;\n\t this._rightPreDelay.dispose();\n\t this._rightPreDelay = null;\n\t this._writable(['delayTime']);\n\t this.delayTime.dispose();\n\t this.delayTime = null;\n\t return this;\n\t };\n\t return Tone.PingPongDelay;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.PitchShift does near-realtime pitch shifting to the incoming signal. \n\t\t * The effect is achieved by speeding up or slowing down the delayTime\n\t\t * of a DelayNode using a sawtooth wave. \n\t\t * Algorithm found in [this pdf](http://dsp-book.narod.ru/soundproc.pdf).\n\t\t * Additional reference by [Miller Pucket](http://msp.ucsd.edu/techniques/v0.11/book-html/node115.html).\n\t\t * \n\t\t * @extends {Tone.FeedbackEffect}\n\t\t * @param {Interval=} pitch The interval to transpose the incoming signal by. \n\t\t */\n\t Tone.PitchShift = function () {\n\t var options = this.optionsObject(arguments, ['pitch'], Tone.PitchShift.defaults);\n\t Tone.FeedbackEffect.call(this, options);\n\t /**\n\t\t\t * The pitch signal\n\t\t\t * @type {Tone.Signal}\n\t\t\t * @private\n\t\t\t */\n\t this._frequency = new Tone.Signal(0);\n\t /**\n\t\t\t * Uses two DelayNodes to cover up the jump in\n\t\t\t * the sawtooth wave. \n\t\t\t * @type {DelayNode}\n\t\t\t * @private\n\t\t\t */\n\t this._delayA = new Tone.Delay(0, 1);\n\t /**\n\t\t\t * The first LFO.\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoA = new Tone.LFO({\n\t 'min': 0,\n\t 'max': 0.1,\n\t 'type': 'sawtooth'\n\t }).connect(this._delayA.delayTime);\n\t /**\n\t\t\t * The second DelayNode\n\t\t\t * @type {DelayNode}\n\t\t\t * @private\n\t\t\t */\n\t this._delayB = new Tone.Delay(0, 1);\n\t /**\n\t\t\t * The first LFO.\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoB = new Tone.LFO({\n\t 'min': 0,\n\t 'max': 0.1,\n\t 'type': 'sawtooth',\n\t 'phase': 180\n\t }).connect(this._delayB.delayTime);\n\t /**\n\t\t\t * Crossfade quickly between the two delay lines\n\t\t\t * to cover up the jump in the sawtooth wave\n\t\t\t * @type {Tone.CrossFade}\n\t\t\t * @private\n\t\t\t */\n\t this._crossFade = new Tone.CrossFade();\n\t /**\n\t\t\t * LFO which alternates between the two\n\t\t\t * delay lines to cover up the disparity in the\n\t\t\t * sawtooth wave. \n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._crossFadeLFO = new Tone.LFO({\n\t 'min': 0,\n\t 'max': 1,\n\t 'type': 'triangle',\n\t 'phase': 90\n\t }).connect(this._crossFade.fade);\n\t /**\n\t\t\t * The delay node\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackDelay = new Tone.Delay(options.delayTime);\n\t /**\n\t\t\t * The amount of delay on the input signal\n\t\t\t * @type {Time}\n\t\t\t * @signal\n\t\t\t */\n\t this.delayTime = this._feedbackDelay.delayTime;\n\t this._readOnly('delayTime');\n\t /**\n\t\t\t * Hold the current pitch\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._pitch = options.pitch;\n\t /**\n\t\t\t * Hold the current windowSize\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._windowSize = options.windowSize;\n\t //connect the two delay lines up\n\t this._delayA.connect(this._crossFade.a);\n\t this._delayB.connect(this._crossFade.b);\n\t //connect the frequency\n\t this._frequency.fan(this._lfoA.frequency, this._lfoB.frequency, this._crossFadeLFO.frequency);\n\t //route the input\n\t this.effectSend.fan(this._delayA, this._delayB);\n\t this._crossFade.chain(this._feedbackDelay, this.effectReturn);\n\t //start the LFOs at the same time\n\t var now = this.now();\n\t this._lfoA.start(now);\n\t this._lfoB.start(now);\n\t this._crossFadeLFO.start(now);\n\t //set the initial value\n\t this.windowSize = this._windowSize;\n\t };\n\t Tone.extend(Tone.PitchShift, Tone.FeedbackEffect);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.PitchShift.defaults = {\n\t 'pitch': 0,\n\t 'windowSize': 0.1,\n\t 'delayTime': 0,\n\t 'feedback': 0\n\t };\n\t /**\n\t\t * Repitch the incoming signal by some interval (measured\n\t\t * in semi-tones). \n\t\t * @memberOf Tone.PitchShift#\n\t\t * @type {Interval}\n\t\t * @name pitch\n\t\t * @example\n\t\t * pitchShift.pitch = -12; //down one octave\n\t\t * pitchShift.pitch = 7; //up a fifth\n\t\t */\n\t Object.defineProperty(Tone.PitchShift.prototype, 'pitch', {\n\t get: function () {\n\t return this._pitch;\n\t },\n\t set: function (interval) {\n\t this._pitch = interval;\n\t var factor = 0;\n\t if (interval < 0) {\n\t this._lfoA.min = 0;\n\t this._lfoA.max = this._windowSize;\n\t this._lfoB.min = 0;\n\t this._lfoB.max = this._windowSize;\n\t factor = this.intervalToFrequencyRatio(interval - 1) + 1;\n\t } else {\n\t this._lfoA.min = this._windowSize;\n\t this._lfoA.max = 0;\n\t this._lfoB.min = this._windowSize;\n\t this._lfoB.max = 0;\n\t factor = this.intervalToFrequencyRatio(interval) - 1;\n\t }\n\t this._frequency.value = factor * (1.2 / this._windowSize);\n\t }\n\t });\n\t /**\n\t\t * The window size corresponds roughly to the sample length in a looping sampler. \n\t\t * Smaller values are desirable for a less noticeable delay time of the pitch shifted\n\t\t * signal, but larger values will result in smoother pitch shifting for larger intervals. \n\t\t * A nominal range of 0.03 to 0.1 is recommended. \n\t\t * @memberOf Tone.PitchShift#\n\t\t * @type {Time}\n\t\t * @name windowSize\n\t\t * @example\n\t\t * pitchShift.windowSize = 0.1;\n\t\t */\n\t Object.defineProperty(Tone.PitchShift.prototype, 'windowSize', {\n\t get: function () {\n\t return this._windowSize;\n\t },\n\t set: function (size) {\n\t this._windowSize = this.toSeconds(size);\n\t this.pitch = this._pitch;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.PitchShift} this\n\t\t */\n\t Tone.PitchShift.prototype.dispose = function () {\n\t Tone.FeedbackEffect.prototype.dispose.call(this);\n\t this._frequency.dispose();\n\t this._frequency = null;\n\t this._delayA.disconnect();\n\t this._delayA = null;\n\t this._delayB.disconnect();\n\t this._delayB = null;\n\t this._lfoA.dispose();\n\t this._lfoA = null;\n\t this._lfoB.dispose();\n\t this._lfoB = null;\n\t this._crossFade.dispose();\n\t this._crossFade = null;\n\t this._crossFadeLFO.dispose();\n\t this._crossFadeLFO = null;\n\t this._writable('delayTime');\n\t this._feedbackDelay.dispose();\n\t this._feedbackDelay = null;\n\t this.delayTime = null;\n\t return this;\n\t };\n\t return Tone.PitchShift;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Base class for stereo feedback effects where the effectReturn\n\t\t * is fed back into the same channel. \n\t\t *\n\t\t *\t@constructor\n\t\t *\t@extends {Tone.FeedbackEffect}\n\t\t */\n\t Tone.StereoFeedbackEffect = function () {\n\t var options = this.optionsObject(arguments, ['feedback'], Tone.FeedbackEffect.defaults);\n\t Tone.StereoEffect.call(this, options);\n\t /**\n\t\t\t * controls the amount of feedback\n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.feedback = new Tone.Signal(options.feedback, Tone.Type.NormalRange);\n\t /**\n\t\t\t * the left side feeback\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackL = new Tone.Gain();\n\t /**\n\t\t\t * the right side feeback\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._feedbackR = new Tone.Gain();\n\t //connect it up\n\t this.effectReturnL.chain(this._feedbackL, this.effectSendL);\n\t this.effectReturnR.chain(this._feedbackR, this.effectSendR);\n\t this.feedback.fan(this._feedbackL.gain, this._feedbackR.gain);\n\t this._readOnly(['feedback']);\n\t };\n\t Tone.extend(Tone.StereoFeedbackEffect, Tone.FeedbackEffect);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.StereoFeedbackEffect} this\n\t\t */\n\t Tone.StereoFeedbackEffect.prototype.dispose = function () {\n\t Tone.StereoEffect.prototype.dispose.call(this);\n\t this._writable(['feedback']);\n\t this.feedback.dispose();\n\t this.feedback = null;\n\t this._feedbackL.dispose();\n\t this._feedbackL = null;\n\t this._feedbackR.dispose();\n\t this._feedbackR = null;\n\t return this;\n\t };\n\t return Tone.StereoFeedbackEffect;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Applies a width factor to the mid/side seperation. \n\t\t * 0 is all mid and 1 is all side.\n\t\t * Algorithm found in [kvraudio forums](http://www.kvraudio.com/forum/viewtopic.php?t=212587).\n\t\t * <br><br>\n\t\t * <code>\n\t\t * Mid *= 2*(1-width)<br>\n\t\t * Side *= 2*width\n\t\t * </code>\n\t\t *\n\t\t * @extends {Tone.MidSideEffect}\n\t\t * @constructor\n\t\t * @param {NormalRange|Object} [width] The stereo width. A width of 0 is mono and 1 is stereo. 0.5 is no change.\n\t\t */\n\t Tone.StereoWidener = function () {\n\t var options = this.optionsObject(arguments, ['width'], Tone.StereoWidener.defaults);\n\t Tone.MidSideEffect.call(this, options);\n\t /**\n\t\t\t * The width control. 0 = 100% mid. 1 = 100% side. 0.5 = no change. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.width = new Tone.Signal(options.width, Tone.Type.NormalRange);\n\t /**\n\t\t\t * Mid multiplier\n\t\t\t * @type {Tone.Expr}\n\t\t\t * @private\n\t\t\t */\n\t this._midMult = new Tone.Expr('$0 * ($1 * (1 - $2))');\n\t /**\n\t\t\t * Side multiplier\n\t\t\t * @type {Tone.Expr}\n\t\t\t * @private\n\t\t\t */\n\t this._sideMult = new Tone.Expr('$0 * ($1 * $2)');\n\t /**\n\t\t\t * constant output of 2\n\t\t\t * @type {Tone}\n\t\t\t * @private\n\t\t\t */\n\t this._two = new Tone.Signal(2);\n\t //the mid chain\n\t this._two.connect(this._midMult, 0, 1);\n\t this.width.connect(this._midMult, 0, 2);\n\t //the side chain\n\t this._two.connect(this._sideMult, 0, 1);\n\t this.width.connect(this._sideMult, 0, 2);\n\t //connect it to the effect send/return\n\t this.midSend.chain(this._midMult, this.midReturn);\n\t this.sideSend.chain(this._sideMult, this.sideReturn);\n\t this._readOnly(['width']);\n\t };\n\t Tone.extend(Tone.StereoWidener, Tone.MidSideEffect);\n\t /**\n\t\t * the default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.StereoWidener.defaults = { 'width': 0.5 };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.StereoWidener} this\n\t\t */\n\t Tone.StereoWidener.prototype.dispose = function () {\n\t Tone.MidSideEffect.prototype.dispose.call(this);\n\t this._writable(['width']);\n\t this.width.dispose();\n\t this.width = null;\n\t this._midMult.dispose();\n\t this._midMult = null;\n\t this._sideMult.dispose();\n\t this._sideMult = null;\n\t this._two.dispose();\n\t this._two = null;\n\t return this;\n\t };\n\t return Tone.StereoWidener;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Tremolo modulates the amplitude of an incoming signal using a Tone.LFO.\n\t\t * The type, frequency, and depth of the LFO is controllable.\n\t\t *\n\t\t * @extends {Tone.StereoEffect}\n\t\t * @constructor\n\t\t * @param {Frequency} [frequency] The rate of the effect.\n\t\t * @param {NormalRange} [depth] The depth of the effect.\n\t\t * @example\n\t\t * //create a tremolo and start it's LFO\n\t\t * var tremolo = new Tone.Tremolo(9, 0.75).toMaster().start();\n\t\t * //route an oscillator through the tremolo and start it\n\t\t * var oscillator = new Tone.Oscillator().connect(tremolo).start();\n\t\t */\n\t Tone.Tremolo = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'depth'\n\t ], Tone.Tremolo.defaults);\n\t Tone.StereoEffect.call(this, options);\n\t /**\n\t\t\t * The tremelo LFO in the left channel\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoL = new Tone.LFO({\n\t 'phase': options.spread,\n\t 'min': 1,\n\t 'max': 0\n\t });\n\t /**\n\t\t\t * The tremelo LFO in the left channel\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfoR = new Tone.LFO({\n\t 'phase': options.spread,\n\t 'min': 1,\n\t 'max': 0\n\t });\n\t /**\n\t\t\t * Where the gain is multiplied\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._amplitudeL = new Tone.Gain();\n\t /**\n\t\t\t * Where the gain is multiplied\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._amplitudeR = new Tone.Gain();\n\t /**\n\t\t\t * The frequency of the tremolo.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The depth of the effect. A depth of 0, has no effect\n\t\t\t * on the amplitude, and a depth of 1 makes the amplitude\n\t\t\t * modulate fully between 0 and 1.\n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.depth = new Tone.Signal(options.depth, Tone.Type.NormalRange);\n\t this._readOnly([\n\t 'frequency',\n\t 'depth'\n\t ]);\n\t this.effectSendL.chain(this._amplitudeL, this.effectReturnL);\n\t this.effectSendR.chain(this._amplitudeR, this.effectReturnR);\n\t this._lfoL.connect(this._amplitudeL.gain);\n\t this._lfoR.connect(this._amplitudeR.gain);\n\t this.frequency.fan(this._lfoL.frequency, this._lfoR.frequency);\n\t this.depth.fan(this._lfoR.amplitude, this._lfoL.amplitude);\n\t this.type = options.type;\n\t this.spread = options.spread;\n\t };\n\t Tone.extend(Tone.Tremolo, Tone.StereoEffect);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Tremolo.defaults = {\n\t 'frequency': 10,\n\t 'type': 'sine',\n\t 'depth': 0.5,\n\t 'spread': 180\n\t };\n\t /**\n\t\t * Start the tremolo.\n\t\t * @param {Time} [time=now] When the tremolo begins.\n\t\t * @returns {Tone.Tremolo} this\n\t\t */\n\t Tone.Tremolo.prototype.start = function (time) {\n\t this._lfoL.start(time);\n\t this._lfoR.start(time);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the tremolo.\n\t\t * @param {Time} [time=now] When the tremolo stops.\n\t\t * @returns {Tone.Tremolo} this\n\t\t */\n\t Tone.Tremolo.prototype.stop = function (time) {\n\t this._lfoL.stop(time);\n\t this._lfoR.stop(time);\n\t return this;\n\t };\n\t /**\n\t\t * Sync the effect to the transport.\n\t\t * @param {Time} [delay=0] Delay time before starting the effect after the\n\t\t * Transport has started.\n\t\t * @returns {Tone.AutoFilter} this\n\t\t */\n\t Tone.Tremolo.prototype.sync = function (delay) {\n\t this._lfoL.sync(delay);\n\t this._lfoR.sync(delay);\n\t return this;\n\t };\n\t /**\n\t\t * Unsync the filter from the transport\n\t\t * @returns {Tone.Tremolo} this\n\t\t */\n\t Tone.Tremolo.prototype.unsync = function () {\n\t this._lfoL.unsync();\n\t this._lfoR.unsync();\n\t return this;\n\t };\n\t /**\n\t\t * The Tremolo's oscillator type.\n\t\t * @memberOf Tone.Tremolo#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.Tremolo.prototype, 'type', {\n\t get: function () {\n\t return this._lfoL.type;\n\t },\n\t set: function (type) {\n\t this._lfoL.type = type;\n\t this._lfoR.type = type;\n\t }\n\t });\n\t /** \n\t\t * Amount of stereo spread. When set to 0, both LFO's will be panned centrally.\n\t\t * When set to 180, LFO's will be panned hard left and right respectively.\n\t\t * @memberOf Tone.Tremolo#\n\t\t * @type {Degrees}\n\t\t * @name spread\n\t\t */\n\t Object.defineProperty(Tone.Tremolo.prototype, 'spread', {\n\t get: function () {\n\t return this._lfoR.phase - this._lfoL.phase; //180\n\t },\n\t set: function (spread) {\n\t this._lfoL.phase = 90 - spread / 2;\n\t this._lfoR.phase = spread / 2 + 90;\n\t }\n\t });\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Tremolo} this\n\t\t */\n\t Tone.Tremolo.prototype.dispose = function () {\n\t Tone.StereoEffect.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'depth'\n\t ]);\n\t this._lfoL.dispose();\n\t this._lfoL = null;\n\t this._lfoR.dispose();\n\t this._lfoR = null;\n\t this._amplitudeL.dispose();\n\t this._amplitudeL = null;\n\t this._amplitudeR.dispose();\n\t this._amplitudeR = null;\n\t this.frequency = null;\n\t this.depth = null;\n\t return this;\n\t };\n\t return Tone.Tremolo;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A Vibrato effect composed of a Tone.Delay and a Tone.LFO. The LFO\n\t\t * modulates the delayTime of the delay, causing the pitch to rise\n\t\t * and fall. \n\t\t * @extends {Tone.Effect}\n\t\t * @param {Frequency} frequency The frequency of the vibrato.\n\t\t * @param {NormalRange} depth The amount the pitch is modulated.\n\t\t */\n\t Tone.Vibrato = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'depth'\n\t ], Tone.Vibrato.defaults);\n\t Tone.Effect.call(this, options);\n\t /**\n\t\t\t * The delay node used for the vibrato effect\n\t\t\t * @type {Tone.Delay}\n\t\t\t * @private\n\t\t\t */\n\t this._delayNode = new Tone.Delay(0, options.maxDelay);\n\t /**\n\t\t\t * The LFO used to control the vibrato\n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._lfo = new Tone.LFO({\n\t 'type': options.type,\n\t 'min': 0,\n\t 'max': options.maxDelay,\n\t 'frequency': options.frequency,\n\t 'phase': -90 //offse the phase so the resting position is in the center\n\t }).start().connect(this._delayNode.delayTime);\n\t /**\n\t\t\t * The frequency of the vibrato\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._lfo.frequency;\n\t /**\n\t\t\t * The depth of the vibrato. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.depth = this._lfo.amplitude;\n\t this.depth.value = options.depth;\n\t this._readOnly([\n\t 'frequency',\n\t 'depth'\n\t ]);\n\t this.effectSend.chain(this._delayNode, this.effectReturn);\n\t };\n\t Tone.extend(Tone.Vibrato, Tone.Effect);\n\t /**\n\t\t * The defaults\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.Vibrato.defaults = {\n\t 'maxDelay': 0.005,\n\t 'frequency': 5,\n\t 'depth': 0.1,\n\t 'type': 'sine'\n\t };\n\t /**\n\t\t * Type of oscillator attached to the Vibrato.\n\t\t * @memberOf Tone.Vibrato#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.Vibrato.prototype, 'type', {\n\t get: function () {\n\t return this._lfo.type;\n\t },\n\t set: function (type) {\n\t this._lfo.type = type;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Vibrato} this\n\t\t */\n\t Tone.Vibrato.prototype.dispose = function () {\n\t Tone.Effect.prototype.dispose.call(this);\n\t this._delayNode.dispose();\n\t this._delayNode = null;\n\t this._lfo.dispose();\n\t this._lfo = null;\n\t this._writable([\n\t 'frequency',\n\t 'depth'\n\t ]);\n\t this.frequency = null;\n\t this.depth = null;\n\t };\n\t return Tone.Vibrato;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Event abstracts away Tone.Transport.schedule and provides a schedulable\n\t\t * callback for a single or repeatable events along the timeline. \n\t\t *\n\t\t * @extends {Tone}\n\t\t * @param {function} callback The callback to invoke at the time. \n\t\t * @param {*} value The value or values which should be passed to\n\t\t * the callback function on invocation. \n\t\t * @example\n\t\t * var chord = new Tone.Event(function(time, chord){\n\t\t * \t//the chord as well as the exact time of the event\n\t\t * \t//are passed in as arguments to the callback function\n\t\t * }, [\"D4\", \"E4\", \"F4\"]);\n\t\t * //start the chord at the beginning of the transport timeline\n\t\t * chord.start();\n\t\t * //loop it every measure for 8 measures\n\t\t * chord.loop = 8;\n\t\t * chord.loopEnd = \"1m\";\n\t\t */\n\t Tone.Event = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'callback',\n\t 'value'\n\t ], Tone.Event.defaults);\n\t /**\n\t\t\t * Loop value\n\t\t\t * @type {Boolean|Positive}\n\t\t\t * @private\n\t\t\t */\n\t this._loop = options.loop;\n\t /**\n\t\t\t * The callback to invoke. \n\t\t\t * @type {Function}\n\t\t\t */\n\t this.callback = options.callback;\n\t /**\n\t\t\t * The value which is passed to the\n\t\t\t * callback function.\n\t\t\t * @type {*}\n\t\t\t * @private\n\t\t\t */\n\t this.value = options.value;\n\t /**\n\t\t\t * When the note is scheduled to start.\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._loopStart = this.toTicks(options.loopStart);\n\t /**\n\t\t\t * When the note is scheduled to start.\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._loopEnd = this.toTicks(options.loopEnd);\n\t /**\n\t\t\t * Tracks the scheduled events\n\t\t\t * @type {Tone.TimelineState}\n\t\t\t * @private\n\t\t\t */\n\t this._state = new Tone.TimelineState(Tone.State.Stopped);\n\t /**\n\t\t\t * The playback speed of the note. A speed of 1\n\t\t\t * is no change. \n\t\t\t * @private\n\t\t\t * @type {Positive}\n\t\t\t */\n\t this._playbackRate = 1;\n\t /**\n\t\t\t * A delay time from when the event is scheduled to start\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._startOffset = 0;\n\t /**\n\t\t\t * The probability that the callback will be invoked\n\t\t\t * at the scheduled time. \n\t\t\t * @type {NormalRange}\n\t\t\t * @example\n\t\t\t * //the callback will be invoked 50% of the time\n\t\t\t * event.probability = 0.5;\n\t\t\t */\n\t this.probability = options.probability;\n\t /**\n\t\t\t * If set to true, will apply small (+/-0.02 seconds) random variation\n\t\t\t * to the callback time. If the value is given as a time, it will randomize\n\t\t\t * by that amount.\n\t\t\t * @example\n\t\t\t * event.humanize = true;\n\t\t\t * @type {Boolean|Time}\n\t\t\t */\n\t this.humanize = options.humanize;\n\t /**\n\t\t\t * If mute is true, the callback won't be\n\t\t\t * invoked.\n\t\t\t * @type {Boolean}\n\t\t\t */\n\t this.mute = options.mute;\n\t //set the initial values\n\t this.playbackRate = options.playbackRate;\n\t };\n\t Tone.extend(Tone.Event);\n\t /**\n\t\t * The default values\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.Event.defaults = {\n\t 'callback': Tone.noOp,\n\t 'loop': false,\n\t 'loopEnd': '1m',\n\t 'loopStart': 0,\n\t 'playbackRate': 1,\n\t 'value': null,\n\t 'probability': 1,\n\t 'mute': false,\n\t 'humanize': false\n\t };\n\t /**\n\t\t * Reschedule all of the events along the timeline\n\t\t * with the updated values.\n\t\t * @param {Time} after Only reschedules events after the given time.\n\t\t * @return {Tone.Event} this\n\t\t * @private\n\t\t */\n\t Tone.Event.prototype._rescheduleEvents = function (after) {\n\t //if no argument is given, schedules all of the events\n\t after = this.defaultArg(after, -1);\n\t this._state.forEachFrom(after, function (event) {\n\t var duration;\n\t if (event.state === Tone.State.Started) {\n\t if (!this.isUndef(event.id)) {\n\t Tone.Transport.clear(event.id);\n\t }\n\t var startTick = event.time + Math.round(this.startOffset / this._playbackRate);\n\t if (this._loop) {\n\t duration = Infinity;\n\t if (this.isNumber(this._loop)) {\n\t duration = this._loop * this._getLoopDuration();\n\t }\n\t var nextEvent = this._state.getAfter(startTick);\n\t if (nextEvent !== null) {\n\t duration = Math.min(duration, nextEvent.time - startTick);\n\t }\n\t if (duration !== Infinity) {\n\t //schedule a stop since it's finite duration\n\t this._state.setStateAtTime(Tone.State.Stopped, startTick + duration + 1);\n\t duration = Tone.Time(duration, 'i');\n\t }\n\t var interval = Tone.Time(this._getLoopDuration(), 'i');\n\t event.id = Tone.Transport.scheduleRepeat(this._tick.bind(this), interval, Tone.TransportTime(startTick, 'i'), duration);\n\t } else {\n\t event.id = Tone.Transport.schedule(this._tick.bind(this), startTick + 'i');\n\t }\n\t }\n\t }.bind(this));\n\t return this;\n\t };\n\t /**\n\t\t * Returns the playback state of the note, either \"started\" or \"stopped\".\n\t\t * @type {String}\n\t\t * @readOnly\n\t\t * @memberOf Tone.Event#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'state', {\n\t get: function () {\n\t return this._state.getValueAtTime(Tone.Transport.ticks);\n\t }\n\t });\n\t /**\n\t\t * The start from the scheduled start time\n\t\t * @type {Ticks}\n\t\t * @memberOf Tone.Event#\n\t\t * @name startOffset\n\t\t * @private\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'startOffset', {\n\t get: function () {\n\t return this._startOffset;\n\t },\n\t set: function (offset) {\n\t this._startOffset = offset;\n\t }\n\t });\n\t /**\n\t\t * Start the note at the given time. \n\t\t * @param {TimelinePosition} time When the note should start.\n\t\t * @return {Tone.Event} this\n\t\t */\n\t Tone.Event.prototype.start = function (time) {\n\t time = this.toTicks(time);\n\t if (this._state.getValueAtTime(time) === Tone.State.Stopped) {\n\t this._state.add({\n\t 'state': Tone.State.Started,\n\t 'time': time,\n\t 'id': undefined\n\t });\n\t this._rescheduleEvents(time);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Stop the Event at the given time.\n\t\t * @param {TimelinePosition} time When the note should stop.\n\t\t * @return {Tone.Event} this\n\t\t */\n\t Tone.Event.prototype.stop = function (time) {\n\t this.cancel(time);\n\t time = this.toTicks(time);\n\t if (this._state.getValueAtTime(time) === Tone.State.Started) {\n\t this._state.setStateAtTime(Tone.State.Stopped, time);\n\t var previousEvent = this._state.getBefore(time);\n\t var reschedulTime = time;\n\t if (previousEvent !== null) {\n\t reschedulTime = previousEvent.time;\n\t }\n\t this._rescheduleEvents(reschedulTime);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Cancel all scheduled events greater than or equal to the given time\n\t\t * @param {TimelinePosition} [time=0] The time after which events will be cancel.\n\t\t * @return {Tone.Event} this\n\t\t */\n\t Tone.Event.prototype.cancel = function (time) {\n\t time = this.defaultArg(time, -Infinity);\n\t time = this.toTicks(time);\n\t this._state.forEachFrom(time, function (event) {\n\t Tone.Transport.clear(event.id);\n\t });\n\t this._state.cancel(time);\n\t return this;\n\t };\n\t /**\n\t\t * The callback function invoker. Also \n\t\t * checks if the Event is done playing\n\t\t * @param {Number} time The time of the event in seconds\n\t\t * @private\n\t\t */\n\t Tone.Event.prototype._tick = function (time) {\n\t if (!this.mute && this._state.getValueAtTime(Tone.Transport.ticks) === Tone.State.Started) {\n\t if (this.probability < 1 && Math.random() > this.probability) {\n\t return;\n\t }\n\t if (this.humanize) {\n\t var variation = 0.02;\n\t if (!this.isBoolean(this.humanize)) {\n\t variation = this.toSeconds(this.humanize);\n\t }\n\t time += (Math.random() * 2 - 1) * variation;\n\t }\n\t this.callback(time, this.value);\n\t }\n\t };\n\t /**\n\t\t * Get the duration of the loop.\n\t\t * @return {Ticks}\n\t\t * @private\n\t\t */\n\t Tone.Event.prototype._getLoopDuration = function () {\n\t return Math.round((this._loopEnd - this._loopStart) / this._playbackRate);\n\t };\n\t /**\n\t\t * If the note should loop or not\n\t\t * between Tone.Event.loopStart and \n\t\t * Tone.Event.loopEnd. An integer\n\t\t * value corresponds to the number of\n\t\t * loops the Event does after it starts.\n\t\t * @memberOf Tone.Event#\n\t\t * @type {Boolean|Positive}\n\t\t * @name loop\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'loop', {\n\t get: function () {\n\t return this._loop;\n\t },\n\t set: function (loop) {\n\t this._loop = loop;\n\t this._rescheduleEvents();\n\t }\n\t });\n\t /**\n\t\t * \tThe playback rate of the note. Defaults to 1.\n\t\t * @memberOf Tone.Event#\n\t\t * @type {Positive}\n\t\t * @name playbackRate\n\t\t * @example\n\t\t * note.loop = true;\n\t\t * //repeat the note twice as fast\n\t\t * note.playbackRate = 2;\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'playbackRate', {\n\t get: function () {\n\t return this._playbackRate;\n\t },\n\t set: function (rate) {\n\t this._playbackRate = rate;\n\t this._rescheduleEvents();\n\t }\n\t });\n\t /**\n\t\t * The loopEnd point is the time the event will loop\n\t\t * if Tone.Event.loop is true.\n\t\t * @memberOf Tone.Event#\n\t\t * @type {TransportTime}\n\t\t * @name loopEnd\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'loopEnd', {\n\t get: function () {\n\t return Tone.TransportTime(this._loopEnd, 'i').toNotation();\n\t },\n\t set: function (loopEnd) {\n\t this._loopEnd = this.toTicks(loopEnd);\n\t if (this._loop) {\n\t this._rescheduleEvents();\n\t }\n\t }\n\t });\n\t /**\n\t\t * The time when the loop should start. \n\t\t * @memberOf Tone.Event#\n\t\t * @type {TransportTime}\n\t\t * @name loopStart\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'loopStart', {\n\t get: function () {\n\t return Tone.TransportTime(this._loopStart, 'i').toNotation();\n\t },\n\t set: function (loopStart) {\n\t this._loopStart = this.toTicks(loopStart);\n\t if (this._loop) {\n\t this._rescheduleEvents();\n\t }\n\t }\n\t });\n\t /**\n\t\t * The current progress of the loop interval.\n\t\t * Returns 0 if the event is not started yet or\n\t\t * it is not set to loop.\n\t\t * @memberOf Tone.Event#\n\t\t * @type {NormalRange}\n\t\t * @name progress\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Event.prototype, 'progress', {\n\t get: function () {\n\t if (this._loop) {\n\t var ticks = Tone.Transport.ticks;\n\t var lastEvent = this._state.get(ticks);\n\t if (lastEvent !== null && lastEvent.state === Tone.State.Started) {\n\t var loopDuration = this._getLoopDuration();\n\t var progress = (ticks - lastEvent.time) % loopDuration;\n\t return progress / loopDuration;\n\t } else {\n\t return 0;\n\t }\n\t } else {\n\t return 0;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.Event} this\n\t\t */\n\t Tone.Event.prototype.dispose = function () {\n\t this.cancel();\n\t this._state.dispose();\n\t this._state = null;\n\t this.callback = null;\n\t this.value = null;\n\t };\n\t return Tone.Event;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.Loop creates a looped callback at the \n\t\t * specified interval. The callback can be \n\t\t * started, stopped and scheduled along\n\t\t * the Transport's timeline. \n\t\t * @example\n\t\t * var loop = new Tone.Loop(function(time){\n\t\t * \t//triggered every eighth note. \n\t\t * \tconsole.log(time);\n\t\t * }, \"8n\").start(0);\n\t\t * Tone.Transport.start();\n\t\t * @extends {Tone}\n\t\t * @param {Function} callback The callback to invoke with the event.\n\t\t * @param {Time} interval The time between successive callback calls. \n\t\t */\n\t Tone.Loop = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'callback',\n\t 'interval'\n\t ], Tone.Loop.defaults);\n\t /**\n\t\t\t * The event which produces the callbacks\n\t\t\t */\n\t this._event = new Tone.Event({\n\t 'callback': this._tick.bind(this),\n\t 'loop': true,\n\t 'loopEnd': options.interval,\n\t 'playbackRate': options.playbackRate,\n\t 'probability': options.probability\n\t });\n\t /**\n\t\t\t * The callback to invoke with the next event in the pattern\n\t\t\t * @type {Function}\n\t\t\t */\n\t this.callback = options.callback;\n\t //set the iterations\n\t this.iterations = options.iterations;\n\t };\n\t Tone.extend(Tone.Loop);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Loop.defaults = {\n\t 'interval': '4n',\n\t 'callback': Tone.noOp,\n\t 'playbackRate': 1,\n\t 'iterations': Infinity,\n\t 'probability': true,\n\t 'mute': false\n\t };\n\t /**\n\t\t * Start the loop at the specified time along the Transport's\n\t\t * timeline.\n\t\t * @param {TimelinePosition=} time When to start the Loop.\n\t\t * @return {Tone.Loop} this\n\t\t */\n\t Tone.Loop.prototype.start = function (time) {\n\t this._event.start(time);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the loop at the given time.\n\t\t * @param {TimelinePosition=} time When to stop the Arpeggio\n\t\t * @return {Tone.Loop} this\n\t\t */\n\t Tone.Loop.prototype.stop = function (time) {\n\t this._event.stop(time);\n\t return this;\n\t };\n\t /**\n\t\t * Cancel all scheduled events greater than or equal to the given time\n\t\t * @param {TimelinePosition} [time=0] The time after which events will be cancel.\n\t\t * @return {Tone.Loop} this\n\t\t */\n\t Tone.Loop.prototype.cancel = function (time) {\n\t this._event.cancel(time);\n\t return this;\n\t };\n\t /**\n\t\t * Internal function called when the notes should be called\n\t\t * @param {Number} time The time the event occurs\n\t\t * @private\n\t\t */\n\t Tone.Loop.prototype._tick = function (time) {\n\t this.callback(time);\n\t };\n\t /**\n\t\t * The state of the Loop, either started or stopped.\n\t\t * @memberOf Tone.Loop#\n\t\t * @type {String}\n\t\t * @name state\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'state', {\n\t get: function () {\n\t return this._event.state;\n\t }\n\t });\n\t /**\n\t\t * The progress of the loop as a value between 0-1. 0, when\n\t\t * the loop is stopped or done iterating. \n\t\t * @memberOf Tone.Loop#\n\t\t * @type {NormalRange}\n\t\t * @name progress\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'progress', {\n\t get: function () {\n\t return this._event.progress;\n\t }\n\t });\n\t /**\n\t\t * The time between successive callbacks. \n\t\t * @example\n\t\t * loop.interval = \"8n\"; //loop every 8n\n\t\t * @memberOf Tone.Loop#\n\t\t * @type {Time}\n\t\t * @name interval\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'interval', {\n\t get: function () {\n\t return this._event.loopEnd;\n\t },\n\t set: function (interval) {\n\t this._event.loopEnd = interval;\n\t }\n\t });\n\t /**\n\t\t * The playback rate of the loop. The normal playback rate is 1 (no change). \n\t\t * A `playbackRate` of 2 would be twice as fast. \n\t\t * @memberOf Tone.Loop#\n\t\t * @type {Time}\n\t\t * @name playbackRate\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'playbackRate', {\n\t get: function () {\n\t return this._event.playbackRate;\n\t },\n\t set: function (rate) {\n\t this._event.playbackRate = rate;\n\t }\n\t });\n\t /**\n\t\t * Random variation +/-0.01s to the scheduled time. \n\t\t * Or give it a time value which it will randomize by.\n\t\t * @type {Boolean|Time}\n\t\t * @memberOf Tone.Loop#\n\t\t * @name humanize\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'humanize', {\n\t get: function () {\n\t return this._event.humanize;\n\t },\n\t set: function (variation) {\n\t this._event.humanize = variation;\n\t }\n\t });\n\t /**\n\t\t * The probably of the callback being invoked.\n\t\t * @memberOf Tone.Loop#\n\t\t * @type {NormalRange}\n\t\t * @name probability\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'probability', {\n\t get: function () {\n\t return this._event.probability;\n\t },\n\t set: function (prob) {\n\t this._event.probability = prob;\n\t }\n\t });\n\t /**\n\t\t * Muting the Loop means that no callbacks are invoked.\n\t\t * @memberOf Tone.Loop#\n\t\t * @type {Boolean}\n\t\t * @name mute\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'mute', {\n\t get: function () {\n\t return this._event.mute;\n\t },\n\t set: function (mute) {\n\t this._event.mute = mute;\n\t }\n\t });\n\t /**\n\t\t * The number of iterations of the loop. The default\n\t\t * value is Infinity (loop forever).\n\t\t * @memberOf Tone.Loop#\n\t\t * @type {Positive}\n\t\t * @name iterations\n\t\t */\n\t Object.defineProperty(Tone.Loop.prototype, 'iterations', {\n\t get: function () {\n\t if (this._event.loop === true) {\n\t return Infinity;\n\t } else {\n\t return this._event.loop;\n\t }\n\t return this._pattern.index;\n\t },\n\t set: function (iters) {\n\t if (iters === Infinity) {\n\t this._event.loop = true;\n\t } else {\n\t this._event.loop = iters;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.Loop} this\n\t\t */\n\t Tone.Loop.prototype.dispose = function () {\n\t this._event.dispose();\n\t this._event = null;\n\t this.callback = null;\n\t };\n\t return Tone.Loop;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Part is a collection Tone.Events which can be\n\t\t * started/stoped and looped as a single unit.\n\t\t *\n\t\t * @extends {Tone.Event}\n\t\t * @param {Function} callback The callback to invoke on each event\n\t\t * @param {Array} events the array of events\n\t\t * @example\n\t\t * var part = new Tone.Part(function(time, note){\n\t\t * \t//the notes given as the second element in the array\n\t\t * \t//will be passed in as the second argument\n\t\t * \tsynth.triggerAttackRelease(note, \"8n\", time);\n\t\t * }, [[0, \"C2\"], [\"0:2\", \"C3\"], [\"0:3:2\", \"G2\"]]);\n\t\t * @example\n\t\t * //use an array of objects as long as the object has a \"time\" attribute\n\t\t * var part = new Tone.Part(function(time, value){\n\t\t * \t//the value is an object which contains both the note and the velocity\n\t\t * \tsynth.triggerAttackRelease(value.note, \"8n\", time, value.velocity);\n\t\t * }, [{\"time\" : 0, \"note\" : \"C3\", \"velocity\": 0.9}, \n\t\t * \t {\"time\" : \"0:2\", \"note\" : \"C4\", \"velocity\": 0.5}\n\t\t * ]).start(0);\n\t\t */\n\t Tone.Part = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'callback',\n\t 'events'\n\t ], Tone.Part.defaults);\n\t /**\n\t\t\t * If the part is looping or not\n\t\t\t * @type {Boolean|Positive}\n\t\t\t * @private\n\t\t\t */\n\t this._loop = options.loop;\n\t /**\n\t\t\t * When the note is scheduled to start.\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._loopStart = this.toTicks(options.loopStart);\n\t /**\n\t\t\t * When the note is scheduled to start.\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._loopEnd = this.toTicks(options.loopEnd);\n\t /**\n\t\t\t * The playback rate of the part\n\t\t\t * @type {Positive}\n\t\t\t * @private\n\t\t\t */\n\t this._playbackRate = options.playbackRate;\n\t /**\n\t\t\t * private holder of probability value\n\t\t\t * @type {NormalRange}\n\t\t\t * @private\n\t\t\t */\n\t this._probability = options.probability;\n\t /**\n\t\t\t * the amount of variation from the\n\t\t\t * given time. \n\t\t\t * @type {Boolean|Time}\n\t\t\t * @private\n\t\t\t */\n\t this._humanize = options.humanize;\n\t /**\n\t\t\t * The start offset\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._startOffset = 0;\n\t /**\n\t\t\t * Keeps track of the current state\n\t\t\t * @type {Tone.TimelineState}\n\t\t\t * @private\n\t\t\t */\n\t this._state = new Tone.TimelineState(Tone.State.Stopped);\n\t /**\n\t\t\t * An array of Objects. \n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._events = [];\n\t /**\n\t\t\t * The callback to invoke at all the scheduled events.\n\t\t\t * @type {Function}\n\t\t\t */\n\t this.callback = options.callback;\n\t /**\n\t\t\t * If mute is true, the callback won't be\n\t\t\t * invoked.\n\t\t\t * @type {Boolean}\n\t\t\t */\n\t this.mute = options.mute;\n\t //add the events\n\t var events = this.defaultArg(options.events, []);\n\t if (!this.isUndef(options.events)) {\n\t for (var i = 0; i < events.length; i++) {\n\t if (Array.isArray(events[i])) {\n\t this.add(events[i][0], events[i][1]);\n\t } else {\n\t this.add(events[i]);\n\t }\n\t }\n\t }\n\t };\n\t Tone.extend(Tone.Part, Tone.Event);\n\t /**\n\t\t * The default values\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.Part.defaults = {\n\t 'callback': Tone.noOp,\n\t 'loop': false,\n\t 'loopEnd': '1m',\n\t 'loopStart': 0,\n\t 'playbackRate': 1,\n\t 'probability': 1,\n\t 'humanize': false,\n\t 'mute': false\n\t };\n\t /**\n\t\t * Start the part at the given time. \n\t\t * @param {TransportTime} time When to start the part.\n\t\t * @param {Time=} offset The offset from the start of the part\n\t\t * to begin playing at.\n\t\t * @return {Tone.Part} this\n\t\t */\n\t Tone.Part.prototype.start = function (time, offset) {\n\t var ticks = this.toTicks(time);\n\t if (this._state.getValueAtTime(ticks) !== Tone.State.Started) {\n\t if (this._loop) {\n\t offset = this.defaultArg(offset, this._loopStart);\n\t } else {\n\t offset = this.defaultArg(offset, 0);\n\t }\n\t offset = this.toTicks(offset);\n\t this._state.add({\n\t 'state': Tone.State.Started,\n\t 'time': ticks,\n\t 'offset': offset\n\t });\n\t this._forEach(function (event) {\n\t this._startNote(event, ticks, offset);\n\t });\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Start the event in the given event at the correct time given\n\t\t * the ticks and offset and looping.\n\t\t * @param {Tone.Event} event \n\t\t * @param {Ticks} ticks\n\t\t * @param {Ticks} offset\n\t\t * @private\n\t\t */\n\t Tone.Part.prototype._startNote = function (event, ticks, offset) {\n\t ticks -= offset;\n\t if (this._loop) {\n\t if (event.startOffset >= this._loopStart && event.startOffset < this._loopEnd) {\n\t if (event.startOffset < offset) {\n\t //start it on the next loop\n\t ticks += this._getLoopDuration();\n\t }\n\t event.start(Tone.TransportTime(ticks, 'i'));\n\t } else if (event.startOffset < this._loopStart && event.startOffset >= offset) {\n\t event.loop = false;\n\t event.start(Tone.TransportTime(ticks, 'i'));\n\t }\n\t } else {\n\t if (event.startOffset >= offset) {\n\t event.start(Tone.TransportTime(ticks, 'i'));\n\t }\n\t }\n\t };\n\t /**\n\t\t * The start from the scheduled start time\n\t\t * @type {Ticks}\n\t\t * @memberOf Tone.Part#\n\t\t * @name startOffset\n\t\t * @private\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'startOffset', {\n\t get: function () {\n\t return this._startOffset;\n\t },\n\t set: function (offset) {\n\t this._startOffset = offset;\n\t this._forEach(function (event) {\n\t event.startOffset += this._startOffset;\n\t });\n\t }\n\t });\n\t /**\n\t\t * Stop the part at the given time.\n\t\t * @param {TimelinePosition} time When to stop the part.\n\t\t * @return {Tone.Part} this\n\t\t */\n\t Tone.Part.prototype.stop = function (time) {\n\t var ticks = this.toTicks(time);\n\t this._state.cancel(ticks);\n\t this._state.setStateAtTime(Tone.State.Stopped, ticks);\n\t this._forEach(function (event) {\n\t event.stop(time);\n\t });\n\t return this;\n\t };\n\t /**\n\t\t * Get/Set an Event's value at the given time. \n\t\t * If a value is passed in and no event exists at\n\t\t * the given time, one will be created with that value. \n\t\t * If two events are at the same time, the first one will\n\t\t * be returned.\n\t\t * @example\n\t\t * part.at(\"1m\"); //returns the part at the first measure\n\t\t *\n\t\t * part.at(\"2m\", \"C2\"); //set the value at \"2m\" to C2. \n\t\t * //if an event didn't exist at that time, it will be created.\n\t\t * @param {TransportTime} time The time of the event to get or set.\n\t\t * @param {*=} value If a value is passed in, the value of the\n\t\t * event at the given time will be set to it.\n\t\t * @return {Tone.Event} the event at the time\n\t\t */\n\t Tone.Part.prototype.at = function (time, value) {\n\t time = Tone.TransportTime(time);\n\t var tickTime = Tone.Time(1, 'i').toSeconds();\n\t for (var i = 0; i < this._events.length; i++) {\n\t var event = this._events[i];\n\t if (Math.abs(time.toTicks() - event.startOffset) < tickTime) {\n\t if (!this.isUndef(value)) {\n\t event.value = value;\n\t }\n\t return event;\n\t }\n\t }\n\t //if there was no event at that time, create one\n\t if (!this.isUndef(value)) {\n\t this.add(time, value);\n\t //return the new event\n\t return this._events[this._events.length - 1];\n\t } else {\n\t return null;\n\t }\n\t };\n\t /**\n\t\t * Add a an event to the part. \n\t\t * @param {Time} time The time the note should start.\n\t\t * If an object is passed in, it should\n\t\t * have a 'time' attribute and the rest\n\t\t * of the object will be used as the 'value'.\n\t\t * @param {Tone.Event|*} value \n\t\t * @returns {Tone.Part} this\n\t\t * @example\n\t\t * part.add(\"1m\", \"C#+11\");\n\t\t */\n\t Tone.Part.prototype.add = function (time, value) {\n\t //extract the parameters\n\t if (time.hasOwnProperty('time')) {\n\t value = time;\n\t time = value.time;\n\t }\n\t time = this.toTicks(time);\n\t var event;\n\t if (value instanceof Tone.Event) {\n\t event = value;\n\t event.callback = this._tick.bind(this);\n\t } else {\n\t event = new Tone.Event({\n\t 'callback': this._tick.bind(this),\n\t 'value': value\n\t });\n\t }\n\t //the start offset\n\t event.startOffset = time;\n\t //initialize the values\n\t event.set({\n\t 'loopEnd': this.loopEnd,\n\t 'loopStart': this.loopStart,\n\t 'loop': this.loop,\n\t 'humanize': this.humanize,\n\t 'playbackRate': this.playbackRate,\n\t 'probability': this.probability\n\t });\n\t this._events.push(event);\n\t //start the note if it should be played right now\n\t this._restartEvent(event);\n\t return this;\n\t };\n\t /**\n\t\t * Restart the given event\n\t\t * @param {Tone.Event} event \n\t\t * @private\n\t\t */\n\t Tone.Part.prototype._restartEvent = function (event) {\n\t this._state.forEach(function (stateEvent) {\n\t if (stateEvent.state === Tone.State.Started) {\n\t this._startNote(event, stateEvent.time, stateEvent.offset);\n\t } else {\n\t //stop the note\n\t event.stop(Tone.TransportTime(stateEvent.time, 'i'));\n\t }\n\t }.bind(this));\n\t };\n\t /**\n\t\t * Remove an event from the part. Will recursively iterate\n\t\t * into nested parts to find the event.\n\t\t * @param {Time} time The time of the event\n\t\t * @param {*} value Optionally select only a specific event value\n\t\t * @return {Tone.Part} this\n\t\t */\n\t Tone.Part.prototype.remove = function (time, value) {\n\t //extract the parameters\n\t if (time.hasOwnProperty('time')) {\n\t value = time;\n\t time = value.time;\n\t }\n\t time = this.toTicks(time);\n\t for (var i = this._events.length - 1; i >= 0; i--) {\n\t var event = this._events[i];\n\t if (event instanceof Tone.Part) {\n\t event.remove(time, value);\n\t } else {\n\t if (event.startOffset === time) {\n\t if (this.isUndef(value) || !this.isUndef(value) && event.value === value) {\n\t this._events.splice(i, 1);\n\t event.dispose();\n\t }\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Remove all of the notes from the group. \n\t\t * @return {Tone.Part} this\n\t\t */\n\t Tone.Part.prototype.removeAll = function () {\n\t this._forEach(function (event) {\n\t event.dispose();\n\t });\n\t this._events = [];\n\t return this;\n\t };\n\t /**\n\t\t * Cancel scheduled state change events: i.e. \"start\" and \"stop\".\n\t\t * @param {TimelinePosition} after The time after which to cancel the scheduled events.\n\t\t * @return {Tone.Part} this\n\t\t */\n\t Tone.Part.prototype.cancel = function (after) {\n\t after = this.toTicks(after);\n\t this._forEach(function (event) {\n\t event.cancel(after);\n\t });\n\t this._state.cancel(after);\n\t return this;\n\t };\n\t /**\n\t\t * Iterate over all of the events\n\t\t * @param {Function} callback\n\t\t * @param {Object} ctx The context\n\t\t * @private\n\t\t */\n\t Tone.Part.prototype._forEach = function (callback, ctx) {\n\t ctx = this.defaultArg(ctx, this);\n\t for (var i = this._events.length - 1; i >= 0; i--) {\n\t var e = this._events[i];\n\t if (e instanceof Tone.Part) {\n\t e._forEach(callback, ctx);\n\t } else {\n\t callback.call(ctx, e);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Set the attribute of all of the events\n\t\t * @param {String} attr the attribute to set\n\t\t * @param {*} value The value to set it to\n\t\t * @private\n\t\t */\n\t Tone.Part.prototype._setAll = function (attr, value) {\n\t this._forEach(function (event) {\n\t event[attr] = value;\n\t });\n\t };\n\t /**\n\t\t * Internal tick method\n\t\t * @param {Number} time The time of the event in seconds\n\t\t * @private\n\t\t */\n\t Tone.Part.prototype._tick = function (time, value) {\n\t if (!this.mute) {\n\t this.callback(time, value);\n\t }\n\t };\n\t /**\n\t\t * Determine if the event should be currently looping\n\t\t * given the loop boundries of this Part.\n\t\t * @param {Tone.Event} event The event to test\n\t\t * @private\n\t\t */\n\t Tone.Part.prototype._testLoopBoundries = function (event) {\n\t if (event.startOffset < this._loopStart || event.startOffset >= this._loopEnd) {\n\t event.cancel(0);\n\t } else {\n\t //reschedule it if it's stopped\n\t if (event.state === Tone.State.Stopped) {\n\t this._restartEvent(event);\n\t }\n\t }\n\t };\n\t /**\n\t\t * The probability of the notes being triggered.\n\t\t * @memberOf Tone.Part#\n\t\t * @type {NormalRange}\n\t\t * @name probability\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'probability', {\n\t get: function () {\n\t return this._probability;\n\t },\n\t set: function (prob) {\n\t this._probability = prob;\n\t this._setAll('probability', prob);\n\t }\n\t });\n\t /**\n\t\t * If set to true, will apply small random variation\n\t\t * to the callback time. If the value is given as a time, it will randomize\n\t\t * by that amount.\n\t\t * @example\n\t\t * event.humanize = true;\n\t\t * @type {Boolean|Time}\n\t\t * @name humanize\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'humanize', {\n\t get: function () {\n\t return this._humanize;\n\t },\n\t set: function (variation) {\n\t this._humanize = variation;\n\t this._setAll('humanize', variation);\n\t }\n\t });\n\t /**\n\t\t * If the part should loop or not\n\t\t * between Tone.Part.loopStart and \n\t\t * Tone.Part.loopEnd. An integer\n\t\t * value corresponds to the number of\n\t\t * loops the Part does after it starts.\n\t\t * @memberOf Tone.Part#\n\t\t * @type {Boolean|Positive}\n\t\t * @name loop\n\t\t * @example\n\t\t * //loop the part 8 times\n\t\t * part.loop = 8;\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'loop', {\n\t get: function () {\n\t return this._loop;\n\t },\n\t set: function (loop) {\n\t this._loop = loop;\n\t this._forEach(function (event) {\n\t event._loopStart = this._loopStart;\n\t event._loopEnd = this._loopEnd;\n\t event.loop = loop;\n\t this._testLoopBoundries(event);\n\t });\n\t }\n\t });\n\t /**\n\t\t * The loopEnd point determines when it will \n\t\t * loop if Tone.Part.loop is true.\n\t\t * @memberOf Tone.Part#\n\t\t * @type {TransportTime}\n\t\t * @name loopEnd\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'loopEnd', {\n\t get: function () {\n\t return Tone.TransportTime(this._loopEnd, 'i').toNotation();\n\t },\n\t set: function (loopEnd) {\n\t this._loopEnd = this.toTicks(loopEnd);\n\t if (this._loop) {\n\t this._forEach(function (event) {\n\t event.loopEnd = loopEnd;\n\t this._testLoopBoundries(event);\n\t });\n\t }\n\t }\n\t });\n\t /**\n\t\t * The loopStart point determines when it will \n\t\t * loop if Tone.Part.loop is true.\n\t\t * @memberOf Tone.Part#\n\t\t * @type {TransportTime}\n\t\t * @name loopStart\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'loopStart', {\n\t get: function () {\n\t return Tone.TransportTime(this._loopStart, 'i').toNotation();\n\t },\n\t set: function (loopStart) {\n\t this._loopStart = this.toTicks(loopStart);\n\t if (this._loop) {\n\t this._forEach(function (event) {\n\t event.loopStart = this.loopStart;\n\t this._testLoopBoundries(event);\n\t });\n\t }\n\t }\n\t });\n\t /**\n\t\t * \tThe playback rate of the part\n\t\t * @memberOf Tone.Part#\n\t\t * @type {Positive}\n\t\t * @name playbackRate\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'playbackRate', {\n\t get: function () {\n\t return this._playbackRate;\n\t },\n\t set: function (rate) {\n\t this._playbackRate = rate;\n\t this._setAll('playbackRate', rate);\n\t }\n\t });\n\t /**\n\t\t * \tThe number of scheduled notes in the part. \n\t\t * @memberOf Tone.Part#\n\t\t * @type {Positive}\n\t\t * @name length\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Part.prototype, 'length', {\n\t get: function () {\n\t return this._events.length;\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.Part} this\n\t\t */\n\t Tone.Part.prototype.dispose = function () {\n\t this.removeAll();\n\t this._state.dispose();\n\t this._state = null;\n\t this.callback = null;\n\t this._events = null;\n\t return this;\n\t };\n\t return Tone.Part;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.Pattern arpeggiates between the given notes\n\t\t * in a number of patterns. See Tone.CtrlPattern for\n\t\t * a full list of patterns.\n\t\t * @example\n\t\t * var pattern = new Tone.Pattern(function(time, note){\n\t\t * //the order of the notes passed in depends on the pattern\n\t\t * }, [\"C2\", \"D4\", \"E5\", \"A6\"], \"upDown\");\n\t\t * @extends {Tone.Loop}\n\t\t * @param {Function} callback The callback to invoke with the\n\t\t * event.\n\t\t * @param {Array} values The values to arpeggiate over.\n\t\t */\n\t Tone.Pattern = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'callback',\n\t 'values',\n\t 'pattern'\n\t ], Tone.Pattern.defaults);\n\t Tone.Loop.call(this, options);\n\t /**\n\t\t\t * The pattern manager\n\t\t\t * @type {Tone.CtrlPattern}\n\t\t\t * @private\n\t\t\t */\n\t this._pattern = new Tone.CtrlPattern({\n\t 'values': options.values,\n\t 'type': options.pattern,\n\t 'index': options.index\n\t });\n\t };\n\t Tone.extend(Tone.Pattern, Tone.Loop);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Pattern.defaults = {\n\t 'pattern': Tone.CtrlPattern.Type.Up,\n\t 'values': []\n\t };\n\t /**\n\t\t * Internal function called when the notes should be called\n\t\t * @param {Number} time The time the event occurs\n\t\t * @private\n\t\t */\n\t Tone.Pattern.prototype._tick = function (time) {\n\t this.callback(time, this._pattern.value);\n\t this._pattern.next();\n\t };\n\t /**\n\t\t * The current index in the values array.\n\t\t * @memberOf Tone.Pattern#\n\t\t * @type {Positive}\n\t\t * @name index\n\t\t */\n\t Object.defineProperty(Tone.Pattern.prototype, 'index', {\n\t get: function () {\n\t return this._pattern.index;\n\t },\n\t set: function (i) {\n\t this._pattern.index = i;\n\t }\n\t });\n\t /**\n\t\t * The array of events.\n\t\t * @memberOf Tone.Pattern#\n\t\t * @type {Array}\n\t\t * @name values\n\t\t */\n\t Object.defineProperty(Tone.Pattern.prototype, 'values', {\n\t get: function () {\n\t return this._pattern.values;\n\t },\n\t set: function (vals) {\n\t this._pattern.values = vals;\n\t }\n\t });\n\t /**\n\t\t * The current value of the pattern.\n\t\t * @memberOf Tone.Pattern#\n\t\t * @type {*}\n\t\t * @name value\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Pattern.prototype, 'value', {\n\t get: function () {\n\t return this._pattern.value;\n\t }\n\t });\n\t /**\n\t\t * The pattern type. See Tone.CtrlPattern for the full list of patterns.\n\t\t * @memberOf Tone.Pattern#\n\t\t * @type {String}\n\t\t * @name pattern\n\t\t */\n\t Object.defineProperty(Tone.Pattern.prototype, 'pattern', {\n\t get: function () {\n\t return this._pattern.type;\n\t },\n\t set: function (pattern) {\n\t this._pattern.type = pattern;\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.Pattern} this\n\t\t */\n\t Tone.Pattern.prototype.dispose = function () {\n\t Tone.Loop.prototype.dispose.call(this);\n\t this._pattern.dispose();\n\t this._pattern = null;\n\t };\n\t return Tone.Pattern;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class A sequence is an alternate notation of a part. Instead\n\t\t * of passing in an array of [time, event] pairs, pass\n\t\t * in an array of events which will be spaced at the\n\t\t * given subdivision. Sub-arrays will subdivide that beat\n\t\t * by the number of items are in the array. \n\t\t * Sequence notation inspiration from [Tidal](http://yaxu.org/tidal/)\n\t\t * @param {Function} callback The callback to invoke with every note\n\t\t * @param {Array} events The sequence\n\t\t * @param {Time} subdivision The subdivision between which events are placed. \n\t\t * @extends {Tone.Part}\n\t\t * @example\n\t\t * var seq = new Tone.Sequence(function(time, note){\n\t\t * \tconsole.log(note);\n\t\t * //straight quater notes\n\t\t * }, [\"C4\", \"E4\", \"G4\", \"A4\"], \"4n\");\n\t\t * @example\n\t\t * var seq = new Tone.Sequence(function(time, note){\n\t\t * \tconsole.log(note);\n\t\t * //subdivisions are given as subarrays\n\t\t * }, [\"C4\", [\"E4\", \"D4\", \"E4\"], \"G4\", [\"A4\", \"G4\"]]);\n\t\t */\n\t Tone.Sequence = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'callback',\n\t 'events',\n\t 'subdivision'\n\t ], Tone.Sequence.defaults);\n\t //remove the events\n\t var events = options.events;\n\t delete options.events;\n\t Tone.Part.call(this, options);\n\t /**\n\t\t\t * The subdivison of each note\n\t\t\t * @type {Ticks}\n\t\t\t * @private\n\t\t\t */\n\t this._subdivision = this.toTicks(options.subdivision);\n\t //if no time was passed in, the loop end is the end of the cycle\n\t if (this.isUndef(options.loopEnd) && !this.isUndef(events)) {\n\t this._loopEnd = events.length * this._subdivision;\n\t }\n\t //defaults to looping\n\t this._loop = true;\n\t //add all of the events\n\t if (!this.isUndef(events)) {\n\t for (var i = 0; i < events.length; i++) {\n\t this.add(i, events[i]);\n\t }\n\t }\n\t };\n\t Tone.extend(Tone.Sequence, Tone.Part);\n\t /**\n\t\t * The default values.\n\t\t * @type {Object}\n\t\t */\n\t Tone.Sequence.defaults = { 'subdivision': '4n' };\n\t /**\n\t\t * The subdivision of the sequence. This can only be \n\t\t * set in the constructor. The subdivision is the \n\t\t * interval between successive steps. \n\t\t * @type {Time}\n\t\t * @memberOf Tone.Sequence#\n\t\t * @name subdivision\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.Sequence.prototype, 'subdivision', {\n\t get: function () {\n\t return Tone.Time(this._subdivision, 'i').toNotation();\n\t }\n\t });\n\t /**\n\t\t * Get/Set an index of the sequence. If the index contains a subarray, \n\t\t * a Tone.Sequence representing that sub-array will be returned. \n\t\t * @example\n\t\t * var sequence = new Tone.Sequence(playNote, [\"E4\", \"C4\", \"F#4\", [\"A4\", \"Bb3\"]])\n\t\t * sequence.at(0)// => returns \"E4\"\n\t\t * //set a value\n\t\t * sequence.at(0, \"G3\");\n\t\t * //get a nested sequence\n\t\t * sequence.at(3).at(1)// => returns \"Bb3\"\n\t\t * @param {Positive} index The index to get or set\n\t\t * @param {*} value Optionally pass in the value to set at the given index.\n\t\t */\n\t Tone.Sequence.prototype.at = function (index, value) {\n\t //if the value is an array, \n\t if (this.isArray(value)) {\n\t //remove the current event at that index\n\t this.remove(index);\n\t }\n\t //call the parent's method\n\t return Tone.Part.prototype.at.call(this, this._indexTime(index), value);\n\t };\n\t /**\n\t\t * Add an event at an index, if there's already something\n\t\t * at that index, overwrite it. If `value` is an array, \n\t\t * it will be parsed as a subsequence.\n\t\t * @param {Number} index The index to add the event to\n\t\t * @param {*} value The value to add at that index\n\t\t * @returns {Tone.Sequence} this\n\t\t */\n\t Tone.Sequence.prototype.add = function (index, value) {\n\t if (value === null) {\n\t return this;\n\t }\n\t if (this.isArray(value)) {\n\t //make a subsequence and add that to the sequence\n\t var subSubdivision = Math.round(this._subdivision / value.length);\n\t value = new Tone.Sequence(this._tick.bind(this), value, Tone.Time(subSubdivision, 'i'));\n\t }\n\t Tone.Part.prototype.add.call(this, this._indexTime(index), value);\n\t return this;\n\t };\n\t /**\n\t\t * Remove a value from the sequence by index\n\t\t * @param {Number} index The index of the event to remove\n\t\t * @returns {Tone.Sequence} this\n\t\t */\n\t Tone.Sequence.prototype.remove = function (index, value) {\n\t Tone.Part.prototype.remove.call(this, this._indexTime(index), value);\n\t return this;\n\t };\n\t /**\n\t\t * Get the time of the index given the Sequence's subdivision\n\t\t * @param {Number} index \n\t\t * @return {Time} The time of that index\n\t\t * @private\n\t\t */\n\t Tone.Sequence.prototype._indexTime = function (index) {\n\t if (index instanceof Tone.TransportTime) {\n\t return index;\n\t } else {\n\t return Tone.TransportTime(index * this._subdivision + this.startOffset, 'i');\n\t }\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.Sequence} this\n\t\t */\n\t Tone.Sequence.prototype.dispose = function () {\n\t Tone.Part.prototype.dispose.call(this);\n\t return this;\n\t };\n\t return Tone.Sequence;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.PulseOscillator is a pulse oscillator with control over pulse width,\n\t\t * also known as the duty cycle. At 50% duty cycle (width = 0.5) the wave is \n\t\t * a square and only odd-numbered harmonics are present. At all other widths \n\t\t * even-numbered harmonics are present. Read more \n\t\t * [here](https://wigglewave.wordpress.com/2014/08/16/pulse-waveforms-and-harmonics/).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Oscillator}\n\t\t * @param {Frequency} [frequency] The frequency of the oscillator\n\t\t * @param {NormalRange} [width] The width of the pulse\n\t\t * @example\n\t\t * var pulse = new Tone.PulseOscillator(\"E5\", 0.4).toMaster().start();\n\t\t */\n\t Tone.PulseOscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'width'\n\t ], Tone.Oscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * The width of the pulse. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.width = new Tone.Signal(options.width, Tone.Type.NormalRange);\n\t /**\n\t\t\t * gate the width amount\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._widthGate = new Tone.Gain();\n\t /**\n\t\t\t * the sawtooth oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._sawtooth = new Tone.Oscillator({\n\t frequency: options.frequency,\n\t detune: options.detune,\n\t type: 'sawtooth',\n\t phase: options.phase\n\t });\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._sawtooth.frequency;\n\t /**\n\t\t\t * The detune in cents. \n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = this._sawtooth.detune;\n\t /**\n\t\t\t * Threshold the signal to turn it into a square\n\t\t\t * @type {Tone.WaveShaper}\n\t\t\t * @private\n\t\t\t */\n\t this._thresh = new Tone.WaveShaper(function (val) {\n\t if (val < 0) {\n\t return -1;\n\t } else {\n\t return 1;\n\t }\n\t });\n\t //connections\n\t this._sawtooth.chain(this._thresh, this.output);\n\t this.width.chain(this._widthGate, this._thresh);\n\t this._readOnly([\n\t 'width',\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t };\n\t Tone.extend(Tone.PulseOscillator, Tone.Oscillator);\n\t /**\n\t\t * The default parameters.\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.PulseOscillator.defaults = {\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'phase': 0,\n\t 'width': 0.2\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} time \n\t\t * @private\n\t\t */\n\t Tone.PulseOscillator.prototype._start = function (time) {\n\t time = this.toSeconds(time);\n\t this._sawtooth.start(time);\n\t this._widthGate.gain.setValueAtTime(1, time);\n\t };\n\t /**\n\t\t * stop the oscillator\n\t\t * @param {Time} time \n\t\t * @private\n\t\t */\n\t Tone.PulseOscillator.prototype._stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._sawtooth.stop(time);\n\t //the width is still connected to the output. \n\t //that needs to be stopped also\n\t this._widthGate.gain.setValueAtTime(0, time);\n\t };\n\t /**\n\t\t * The phase of the oscillator in degrees.\n\t\t * @memberOf Tone.PulseOscillator#\n\t\t * @type {Degrees}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.PulseOscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._sawtooth.phase;\n\t },\n\t set: function (phase) {\n\t this._sawtooth.phase = phase;\n\t }\n\t });\n\t /**\n\t\t * The type of the oscillator. Always returns \"pulse\".\n\t\t * @readOnly\n\t\t * @memberOf Tone.PulseOscillator#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.PulseOscillator.prototype, 'type', {\n\t get: function () {\n\t return 'pulse';\n\t }\n\t });\n\t /**\n\t\t * The partials of the waveform. Cannot set partials for this waveform type\n\t\t * @memberOf Tone.PulseOscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @private\n\t\t */\n\t Object.defineProperty(Tone.PulseOscillator.prototype, 'partials', {\n\t get: function () {\n\t return [];\n\t }\n\t });\n\t /**\n\t\t * Clean up method.\n\t\t * @return {Tone.PulseOscillator} this\n\t\t */\n\t Tone.PulseOscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this._sawtooth.dispose();\n\t this._sawtooth = null;\n\t this._writable([\n\t 'width',\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t this.width.dispose();\n\t this.width = null;\n\t this._widthGate.dispose();\n\t this._widthGate = null;\n\t this._thresh.dispose();\n\t this._thresh = null;\n\t this.frequency = null;\n\t this.detune = null;\n\t return this;\n\t };\n\t return Tone.PulseOscillator;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.PWMOscillator modulates the width of a Tone.PulseOscillator \n\t\t * at the modulationFrequency. This has the effect of continuously\n\t\t * changing the timbre of the oscillator by altering the harmonics \n\t\t * generated.\n\t\t *\n\t\t * @extends {Tone.Oscillator}\n\t\t * @constructor\n\t\t * @param {Frequency} frequency The starting frequency of the oscillator. \n\t\t * @param {Frequency} modulationFrequency The modulation frequency of the width of the pulse. \n\t\t * @example\n\t\t * var pwm = new Tone.PWMOscillator(\"Ab3\", 0.3).toMaster().start();\n\t\t */\n\t Tone.PWMOscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'modulationFrequency'\n\t ], Tone.PWMOscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * the pulse oscillator\n\t\t\t * @type {Tone.PulseOscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._pulse = new Tone.PulseOscillator(options.modulationFrequency);\n\t //change the pulse oscillator type\n\t this._pulse._sawtooth.type = 'sine';\n\t /**\n\t\t\t * the modulator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._modulator = new Tone.Oscillator({\n\t 'frequency': options.frequency,\n\t 'detune': options.detune,\n\t 'phase': options.phase\n\t });\n\t /**\n\t\t\t * Scale the oscillator so it doesn't go silent \n\t\t\t * at the extreme values.\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._scale = new Tone.Multiply(2);\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._modulator.frequency;\n\t /**\n\t\t\t * The detune of the oscillator.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = this._modulator.detune;\n\t /**\n\t\t\t * The modulation rate of the oscillator. \n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.modulationFrequency = this._pulse.frequency;\n\t //connections\n\t this._modulator.chain(this._scale, this._pulse.width);\n\t this._pulse.connect(this.output);\n\t this._readOnly([\n\t 'modulationFrequency',\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t };\n\t Tone.extend(Tone.PWMOscillator, Tone.Oscillator);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.PWMOscillator.defaults = {\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'phase': 0,\n\t 'modulationFrequency': 0.4\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now]\n\t\t * @private\n\t\t */\n\t Tone.PWMOscillator.prototype._start = function (time) {\n\t time = this.toSeconds(time);\n\t this._modulator.start(time);\n\t this._pulse.start(time);\n\t };\n\t /**\n\t\t * stop the oscillator\n\t\t * @param {Time} time (optional) timing parameter\n\t\t * @private\n\t\t */\n\t Tone.PWMOscillator.prototype._stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._modulator.stop(time);\n\t this._pulse.stop(time);\n\t };\n\t /**\n\t\t * The type of the oscillator. Always returns \"pwm\".\n\t\t * @readOnly\n\t\t * @memberOf Tone.PWMOscillator#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.PWMOscillator.prototype, 'type', {\n\t get: function () {\n\t return 'pwm';\n\t }\n\t });\n\t /**\n\t\t * The partials of the waveform. Cannot set partials for this waveform type\n\t\t * @memberOf Tone.PWMOscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @private\n\t\t */\n\t Object.defineProperty(Tone.PWMOscillator.prototype, 'partials', {\n\t get: function () {\n\t return [];\n\t }\n\t });\n\t /**\n\t\t * The phase of the oscillator in degrees.\n\t\t * @memberOf Tone.PWMOscillator#\n\t\t * @type {number}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.PWMOscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._modulator.phase;\n\t },\n\t set: function (phase) {\n\t this._modulator.phase = phase;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.PWMOscillator} this\n\t\t */\n\t Tone.PWMOscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this._pulse.dispose();\n\t this._pulse = null;\n\t this._scale.dispose();\n\t this._scale = null;\n\t this._modulator.dispose();\n\t this._modulator = null;\n\t this._writable([\n\t 'modulationFrequency',\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t this.frequency = null;\n\t this.detune = null;\n\t this.modulationFrequency = null;\n\t return this;\n\t };\n\t return Tone.PWMOscillator;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.FMOscillator \n\t\t *\n\t\t * @extends {Tone.Oscillator}\n\t\t * @constructor\n\t\t * @param {Frequency} frequency The starting frequency of the oscillator. \n\t\t * @param {String} type The type of the carrier oscillator.\n\t\t * @param {String} modulationType The type of the modulator oscillator.\n\t\t * @example\n\t\t * //a sine oscillator frequency-modulated by a square wave\n\t\t * var fmOsc = new Tone.FMOscillator(\"Ab3\", \"sine\", \"square\").toMaster().start();\n\t\t */\n\t Tone.FMOscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'type',\n\t 'modulationType'\n\t ], Tone.FMOscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * The carrier oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._carrier = new Tone.Oscillator(options.frequency, options.type);\n\t /**\n\t\t\t * The oscillator's frequency\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune control signal.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = this._carrier.detune;\n\t this.detune.value = options.detune;\n\t /**\n\t\t\t * The modulation index which is in essence the depth or amount of the modulation. In other terms it is the \n\t\t\t * ratio of the frequency of the modulating signal (mf) to the amplitude of the \n\t\t\t * modulating signal (ma) -- as in ma/mf. \n\t\t\t *\t@type {Positive}\n\t\t\t *\t@signal\n\t\t\t */\n\t this.modulationIndex = new Tone.Multiply(options.modulationIndex);\n\t this.modulationIndex.units = Tone.Type.Positive;\n\t /**\n\t\t\t * The modulating oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._modulator = new Tone.Oscillator(options.frequency, options.modulationType);\n\t /**\n\t\t\t * Harmonicity is the frequency ratio between the carrier and the modulator oscillators. \n\t\t\t * A harmonicity of 1 gives both oscillators the same frequency. \n\t\t\t * Harmonicity = 2 means a change of an octave. \n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * //pitch the modulator an octave below carrier\n\t\t\t * synth.harmonicity.value = 0.5;\n\t\t\t */\n\t this.harmonicity = new Tone.Multiply(options.harmonicity);\n\t this.harmonicity.units = Tone.Type.Positive;\n\t /**\n\t\t\t * the node where the modulation happens\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._modulationNode = new Tone.Gain(0);\n\t //connections\n\t this.frequency.connect(this._carrier.frequency);\n\t this.frequency.chain(this.harmonicity, this._modulator.frequency);\n\t this.frequency.chain(this.modulationIndex, this._modulationNode);\n\t this._modulator.connect(this._modulationNode.gain);\n\t this._modulationNode.connect(this._carrier.frequency);\n\t this._carrier.connect(this.output);\n\t this.detune.connect(this._modulator.detune);\n\t this.phase = options.phase;\n\t this._readOnly([\n\t 'modulationIndex',\n\t 'frequency',\n\t 'detune',\n\t 'harmonicity'\n\t ]);\n\t };\n\t Tone.extend(Tone.FMOscillator, Tone.Oscillator);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.FMOscillator.defaults = {\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'phase': 0,\n\t 'modulationIndex': 2,\n\t 'modulationType': 'square',\n\t 'harmonicity': 1\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now]\n\t\t * @private\n\t\t */\n\t Tone.FMOscillator.prototype._start = function (time) {\n\t time = this.toSeconds(time);\n\t this._modulator.start(time);\n\t this._carrier.start(time);\n\t };\n\t /**\n\t\t * stop the oscillator\n\t\t * @param {Time} time (optional) timing parameter\n\t\t * @private\n\t\t */\n\t Tone.FMOscillator.prototype._stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._modulator.stop(time);\n\t this._carrier.stop(time);\n\t };\n\t /**\n\t\t * The type of the carrier oscillator\n\t\t * @memberOf Tone.FMOscillator#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.FMOscillator.prototype, 'type', {\n\t get: function () {\n\t return this._carrier.type;\n\t },\n\t set: function (type) {\n\t this._carrier.type = type;\n\t }\n\t });\n\t /**\n\t\t * The type of the modulator oscillator\n\t\t * @memberOf Tone.FMOscillator#\n\t\t * @type {String}\n\t\t * @name modulationType\n\t\t */\n\t Object.defineProperty(Tone.FMOscillator.prototype, 'modulationType', {\n\t get: function () {\n\t return this._modulator.type;\n\t },\n\t set: function (type) {\n\t this._modulator.type = type;\n\t }\n\t });\n\t /**\n\t\t * The phase of the oscillator in degrees.\n\t\t * @memberOf Tone.FMOscillator#\n\t\t * @type {number}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.FMOscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._carrier.phase;\n\t },\n\t set: function (phase) {\n\t this._carrier.phase = phase;\n\t this._modulator.phase = phase;\n\t }\n\t });\n\t /**\n\t\t * The partials of the carrier waveform. A partial represents \n\t\t * the amplitude at a harmonic. The first harmonic is the \n\t\t * fundamental frequency, the second is the octave and so on\n\t\t * following the harmonic series. \n\t\t * Setting this value will automatically set the type to \"custom\". \n\t\t * The value is an empty array when the type is not \"custom\". \n\t\t * @memberOf Tone.FMOscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @example\n\t\t * osc.partials = [1, 0.2, 0.01];\n\t\t */\n\t Object.defineProperty(Tone.FMOscillator.prototype, 'partials', {\n\t get: function () {\n\t return this._carrier.partials;\n\t },\n\t set: function (partials) {\n\t this._carrier.partials = partials;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.FMOscillator} this\n\t\t */\n\t Tone.FMOscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this._writable([\n\t 'modulationIndex',\n\t 'frequency',\n\t 'detune',\n\t 'harmonicity'\n\t ]);\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this.detune = null;\n\t this.harmonicity.dispose();\n\t this.harmonicity = null;\n\t this._carrier.dispose();\n\t this._carrier = null;\n\t this._modulator.dispose();\n\t this._modulator = null;\n\t this._modulationNode.dispose();\n\t this._modulationNode = null;\n\t this.modulationIndex.dispose();\n\t this.modulationIndex = null;\n\t return this;\n\t };\n\t return Tone.FMOscillator;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.AMOscillator \n\t\t *\n\t\t * @extends {Tone.Oscillator}\n\t\t * @constructor\n\t\t * @param {Frequency} frequency The starting frequency of the oscillator. \n\t\t * @param {String} type The type of the carrier oscillator.\n\t\t * @param {String} modulationType The type of the modulator oscillator.\n\t\t * @example\n\t\t * //a sine oscillator frequency-modulated by a square wave\n\t\t * var fmOsc = new Tone.AMOscillator(\"Ab3\", \"sine\", \"square\").toMaster().start();\n\t\t */\n\t Tone.AMOscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'type',\n\t 'modulationType'\n\t ], Tone.AMOscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * The carrier oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._carrier = new Tone.Oscillator(options.frequency, options.type);\n\t /**\n\t\t\t * The oscillator's frequency\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this._carrier.frequency;\n\t /**\n\t\t\t * The detune control signal.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = this._carrier.detune;\n\t this.detune.value = options.detune;\n\t /**\n\t\t\t * The modulating oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._modulator = new Tone.Oscillator(options.frequency, options.modulationType);\n\t /**\n\t\t\t * convert the -1,1 output to 0,1\n\t\t\t * @type {Tone.AudioToGain}\n\t\t\t * @private\n\t\t\t */\n\t this._modulationScale = new Tone.AudioToGain();\n\t /**\n\t\t\t * Harmonicity is the frequency ratio between the carrier and the modulator oscillators. \n\t\t\t * A harmonicity of 1 gives both oscillators the same frequency. \n\t\t\t * Harmonicity = 2 means a change of an octave. \n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * //pitch the modulator an octave below carrier\n\t\t\t * synth.harmonicity.value = 0.5;\n\t\t\t */\n\t this.harmonicity = new Tone.Multiply(options.harmonicity);\n\t this.harmonicity.units = Tone.Type.Positive;\n\t /**\n\t\t\t * the node where the modulation happens\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._modulationNode = new Tone.Gain(0);\n\t //connections\n\t this.frequency.chain(this.harmonicity, this._modulator.frequency);\n\t this.detune.connect(this._modulator.detune);\n\t this._modulator.chain(this._modulationScale, this._modulationNode.gain);\n\t this._carrier.chain(this._modulationNode, this.output);\n\t this.phase = options.phase;\n\t this._readOnly([\n\t 'frequency',\n\t 'detune',\n\t 'harmonicity'\n\t ]);\n\t };\n\t Tone.extend(Tone.AMOscillator, Tone.Oscillator);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.AMOscillator.defaults = {\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'phase': 0,\n\t 'modulationType': 'square',\n\t 'harmonicity': 1\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now]\n\t\t * @private\n\t\t */\n\t Tone.AMOscillator.prototype._start = function (time) {\n\t time = this.toSeconds(time);\n\t this._modulator.start(time);\n\t this._carrier.start(time);\n\t };\n\t /**\n\t\t * stop the oscillator\n\t\t * @param {Time} time (optional) timing parameter\n\t\t * @private\n\t\t */\n\t Tone.AMOscillator.prototype._stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._modulator.stop(time);\n\t this._carrier.stop(time);\n\t };\n\t /**\n\t\t * The type of the carrier oscillator\n\t\t * @memberOf Tone.AMOscillator#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.AMOscillator.prototype, 'type', {\n\t get: function () {\n\t return this._carrier.type;\n\t },\n\t set: function (type) {\n\t this._carrier.type = type;\n\t }\n\t });\n\t /**\n\t\t * The type of the modulator oscillator\n\t\t * @memberOf Tone.AMOscillator#\n\t\t * @type {string}\n\t\t * @name modulationType\n\t\t */\n\t Object.defineProperty(Tone.AMOscillator.prototype, 'modulationType', {\n\t get: function () {\n\t return this._modulator.type;\n\t },\n\t set: function (type) {\n\t this._modulator.type = type;\n\t }\n\t });\n\t /**\n\t\t * The phase of the oscillator in degrees.\n\t\t * @memberOf Tone.AMOscillator#\n\t\t * @type {number}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.AMOscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._carrier.phase;\n\t },\n\t set: function (phase) {\n\t this._carrier.phase = phase;\n\t this._modulator.phase = phase;\n\t }\n\t });\n\t /**\n\t\t * The partials of the carrier waveform. A partial represents \n\t\t * the amplitude at a harmonic. The first harmonic is the \n\t\t * fundamental frequency, the second is the octave and so on\n\t\t * following the harmonic series. \n\t\t * Setting this value will automatically set the type to \"custom\". \n\t\t * The value is an empty array when the type is not \"custom\". \n\t\t * @memberOf Tone.AMOscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @example\n\t\t * osc.partials = [1, 0.2, 0.01];\n\t\t */\n\t Object.defineProperty(Tone.AMOscillator.prototype, 'partials', {\n\t get: function () {\n\t return this._carrier.partials;\n\t },\n\t set: function (partials) {\n\t this._carrier.partials = partials;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.AMOscillator} this\n\t\t */\n\t Tone.AMOscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'detune',\n\t 'harmonicity'\n\t ]);\n\t this.frequency = null;\n\t this.detune = null;\n\t this.harmonicity.dispose();\n\t this.harmonicity = null;\n\t this._carrier.dispose();\n\t this._carrier = null;\n\t this._modulator.dispose();\n\t this._modulator = null;\n\t this._modulationNode.dispose();\n\t this._modulationNode = null;\n\t this._modulationScale.dispose();\n\t this._modulationScale = null;\n\t return this;\n\t };\n\t return Tone.AMOscillator;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.FatOscillator \n\t\t *\n\t\t * @extends {Tone.Oscillator}\n\t\t * @constructor\n\t\t * @param {Frequency} frequency The starting frequency of the oscillator. \n\t\t * @param {String} type The type of the carrier oscillator.\n\t\t * @param {String} modulationType The type of the modulator oscillator.\n\t\t * @example\n\t\t * //a sine oscillator frequency-modulated by a square wave\n\t\t * var fmOsc = new Tone.FatOscillator(\"Ab3\", \"sine\", \"square\").toMaster().start();\n\t\t */\n\t Tone.FatOscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'type',\n\t 'spread'\n\t ], Tone.FatOscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * The oscillator's frequency\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune control signal.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);\n\t /**\n\t\t\t * The array of oscillators\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._oscillators = [];\n\t /**\n\t\t\t * The total spread of the oscillators\n\t\t\t * @type {Cents}\n\t\t\t * @private\n\t\t\t */\n\t this._spread = options.spread;\n\t /**\n\t\t\t * The type of the oscillator\n\t\t\t * @type {String}\n\t\t\t * @private\n\t\t\t */\n\t this._type = options.type;\n\t /**\n\t\t\t * The phase of the oscillators\n\t\t\t * @type {Degrees}\n\t\t\t * @private\n\t\t\t */\n\t this._phase = options.phase;\n\t /**\n\t\t\t * The partials array\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._partials = this.defaultArg(options.partials, []);\n\t //set the count initially\n\t this.count = options.count;\n\t this._readOnly([\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t };\n\t Tone.extend(Tone.FatOscillator, Tone.Oscillator);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.FatOscillator.defaults = {\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'phase': 0,\n\t 'spread': 20,\n\t 'count': 3,\n\t 'type': 'sawtooth'\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now]\n\t\t * @private\n\t\t */\n\t Tone.FatOscillator.prototype._start = function (time) {\n\t time = this.toSeconds(time);\n\t this._forEach(function (osc) {\n\t osc.start(time);\n\t });\n\t };\n\t /**\n\t\t * stop the oscillator\n\t\t * @param {Time} time (optional) timing parameter\n\t\t * @private\n\t\t */\n\t Tone.FatOscillator.prototype._stop = function (time) {\n\t time = this.toSeconds(time);\n\t this._forEach(function (osc) {\n\t osc.stop(time);\n\t });\n\t };\n\t /**\n\t\t * Iterate over all of the oscillators\n\t\t * @param {Function} iterator The iterator function\n\t\t * @private\n\t\t */\n\t Tone.FatOscillator.prototype._forEach = function (iterator) {\n\t for (var i = 0; i < this._oscillators.length; i++) {\n\t iterator.call(this, this._oscillators[i], i);\n\t }\n\t };\n\t /**\n\t\t * The type of the carrier oscillator\n\t\t * @memberOf Tone.FatOscillator#\n\t\t * @type {string}\n\t\t * @name type\n\t\t */\n\t Object.defineProperty(Tone.FatOscillator.prototype, 'type', {\n\t get: function () {\n\t return this._type;\n\t },\n\t set: function (type) {\n\t this._type = type;\n\t this._forEach(function (osc) {\n\t osc.type = type;\n\t });\n\t }\n\t });\n\t /**\n\t\t * The detune spread between the oscillators. If \"count\" is\n\t\t * set to 3 oscillators and the \"spread\" is set to 40,\n\t\t * the three oscillators would be detuned like this: [-20, 0, 20]\n\t\t * for a total detune spread of 40 cents.\n\t\t * @memberOf Tone.FatOscillator#\n\t\t * @type {Cents}\n\t\t * @name spread\n\t\t */\n\t Object.defineProperty(Tone.FatOscillator.prototype, 'spread', {\n\t get: function () {\n\t return this._spread;\n\t },\n\t set: function (spread) {\n\t this._spread = spread;\n\t if (this._oscillators.length > 1) {\n\t var start = -spread / 2;\n\t var step = spread / (this._oscillators.length - 1);\n\t this._forEach(function (osc, i) {\n\t osc.detune.value = start + step * i;\n\t });\n\t }\n\t }\n\t });\n\t /**\n\t\t * The number of detuned oscillators\n\t\t * @memberOf Tone.FatOscillator#\n\t\t * @type {Number}\n\t\t * @name count\n\t\t */\n\t Object.defineProperty(Tone.FatOscillator.prototype, 'count', {\n\t get: function () {\n\t return this._oscillators.length;\n\t },\n\t set: function (count) {\n\t count = Math.max(count, 1);\n\t if (this._oscillators.length !== count) {\n\t // var partials = this.partials;\n\t // var type = this.type;\n\t //dispose the previous oscillators\n\t this._forEach(function (osc) {\n\t osc.dispose();\n\t });\n\t this._oscillators = [];\n\t for (var i = 0; i < count; i++) {\n\t var osc = new Tone.Oscillator();\n\t if (this.type === Tone.Oscillator.Type.Custom) {\n\t osc.partials = this._partials;\n\t } else {\n\t osc.type = this._type;\n\t }\n\t osc.phase = this._phase;\n\t osc.volume.value = -6 - count;\n\t this.frequency.connect(osc.frequency);\n\t this.detune.connect(osc.detune);\n\t osc.connect(this.output);\n\t this._oscillators[i] = osc;\n\t }\n\t //set the spread\n\t this.spread = this._spread;\n\t if (this.state === Tone.State.Started) {\n\t this._forEach(function (osc) {\n\t osc.start();\n\t });\n\t }\n\t }\n\t }\n\t });\n\t /**\n\t\t * The phase of the oscillator in degrees.\n\t\t * @memberOf Tone.FatOscillator#\n\t\t * @type {Number}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.FatOscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._phase;\n\t },\n\t set: function (phase) {\n\t this._phase = phase;\n\t this._forEach(function (osc) {\n\t osc.phase = phase;\n\t });\n\t }\n\t });\n\t /**\n\t\t * The partials of the carrier waveform. A partial represents \n\t\t * the amplitude at a harmonic. The first harmonic is the \n\t\t * fundamental frequency, the second is the octave and so on\n\t\t * following the harmonic series. \n\t\t * Setting this value will automatically set the type to \"custom\". \n\t\t * The value is an empty array when the type is not \"custom\". \n\t\t * @memberOf Tone.FatOscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @example\n\t\t * osc.partials = [1, 0.2, 0.01];\n\t\t */\n\t Object.defineProperty(Tone.FatOscillator.prototype, 'partials', {\n\t get: function () {\n\t return this._partials;\n\t },\n\t set: function (partials) {\n\t this._partials = partials;\n\t this._type = Tone.Oscillator.Type.Custom;\n\t this._forEach(function (osc) {\n\t osc.partials = partials;\n\t });\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.FatOscillator} this\n\t\t */\n\t Tone.FatOscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this.detune.dispose();\n\t this.detune = null;\n\t this._forEach(function (osc) {\n\t osc.dispose();\n\t });\n\t this._oscillators = null;\n\t this._partials = null;\n\t return this;\n\t };\n\t return Tone.FatOscillator;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.OmniOscillator aggregates Tone.Oscillator, Tone.PulseOscillator,\n\t\t * Tone.PWMOscillator, Tone.FMOscillator, Tone.AMOscillator, and Tone.FatOscillator\n\t\t * into one class. The oscillator class can be changed by setting the `type`. \n\t\t * `omniOsc.type = \"pwm\"` will set it to the Tone.PWMOscillator. Prefixing\n\t\t * any of the basic types (\"sine\", \"square4\", etc.) with \"fm\", \"am\", or \"fat\"\n\t\t * will use the FMOscillator, AMOscillator or FatOscillator respectively. \n\t\t * For example: `omniOsc.type = \"fatsawtooth\"` will create set the oscillator\n\t\t * to a FatOscillator of type \"sawtooth\". \n\t\t *\n\t\t * @extends {Tone.Oscillator}\n\t\t * @constructor\n\t\t * @param {Frequency} frequency The initial frequency of the oscillator.\n\t\t * @param {String} type The type of the oscillator.\n\t\t * @example\n\t\t * var omniOsc = new Tone.OmniOscillator(\"C#4\", \"pwm\");\n\t\t */\n\t Tone.OmniOscillator = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'frequency',\n\t 'type'\n\t ], Tone.OmniOscillator.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune control\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);\n\t /**\n\t\t\t * the type of the oscillator source\n\t\t\t * @type {String}\n\t\t\t * @private\n\t\t\t */\n\t this._sourceType = undefined;\n\t /**\n\t\t\t * the oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t * @private\n\t\t\t */\n\t this._oscillator = null;\n\t //set the oscillator\n\t this.type = options.type;\n\t this._readOnly([\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t //set the options\n\t this.set(options);\n\t };\n\t Tone.extend(Tone.OmniOscillator, Tone.Oscillator);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @type {Object}\n\t\t * @const\n\t\t */\n\t Tone.OmniOscillator.defaults = {\n\t 'frequency': 440,\n\t 'detune': 0,\n\t 'type': 'sine',\n\t 'phase': 0\n\t };\n\t /**\n\t\t * @enum {String}\n\t\t * @private\n\t\t */\n\t var OmniOscType = {\n\t Pulse: 'PulseOscillator',\n\t PWM: 'PWMOscillator',\n\t Osc: 'Oscillator',\n\t FM: 'FMOscillator',\n\t AM: 'AMOscillator',\n\t Fat: 'FatOscillator'\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now] the time to start the oscillator\n\t\t * @private\n\t\t */\n\t Tone.OmniOscillator.prototype._start = function (time) {\n\t this._oscillator.start(time);\n\t };\n\t /**\n\t\t * start the oscillator\n\t\t * @param {Time} [time=now] the time to start the oscillator\n\t\t * @private\n\t\t */\n\t Tone.OmniOscillator.prototype._stop = function (time) {\n\t this._oscillator.stop(time);\n\t };\n\t /**\n\t\t * The type of the oscillator. Can be any of the basic types: sine, square, triangle, sawtooth. Or\n\t\t * prefix the basic types with \"fm\", \"am\", or \"fat\" to use the FMOscillator, AMOscillator or FatOscillator\n\t\t * types. The oscillator could also be set to \"pwm\" or \"pulse\". All of the parameters of the\n\t\t * oscillator's class are accessible when the oscillator is set to that type, but throws an error \n\t\t * when it's not.\n\t\t * \n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {String}\n\t\t * @name type\n\t\t * @example\n\t\t * omniOsc.type = \"pwm\";\n\t\t * //modulationFrequency is parameter which is available\n\t\t * //only when the type is \"pwm\". \n\t\t * omniOsc.modulationFrequency.value = 0.5;\n\t\t * @example\n\t\t * //an square wave frequency modulated by a sawtooth\n\t\t * omniOsc.type = \"fmsquare\";\n\t\t * omniOsc.modulationType = \"sawtooth\";\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'type', {\n\t get: function () {\n\t var prefix = '';\n\t if (this._sourceType === OmniOscType.FM) {\n\t prefix = 'fm';\n\t } else if (this._sourceType === OmniOscType.AM) {\n\t prefix = 'am';\n\t } else if (this._sourceType === OmniOscType.Fat) {\n\t prefix = 'fat';\n\t }\n\t return prefix + this._oscillator.type;\n\t },\n\t set: function (type) {\n\t if (type.substr(0, 2) === 'fm') {\n\t this._createNewOscillator(OmniOscType.FM);\n\t this._oscillator.type = type.substr(2);\n\t } else if (type.substr(0, 2) === 'am') {\n\t this._createNewOscillator(OmniOscType.AM);\n\t this._oscillator.type = type.substr(2);\n\t } else if (type.substr(0, 3) === 'fat') {\n\t this._createNewOscillator(OmniOscType.Fat);\n\t this._oscillator.type = type.substr(3);\n\t } else if (type === 'pwm') {\n\t this._createNewOscillator(OmniOscType.PWM);\n\t } else if (type === 'pulse') {\n\t this._createNewOscillator(OmniOscType.Pulse);\n\t } else {\n\t this._createNewOscillator(OmniOscType.Osc);\n\t this._oscillator.type = type;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The partials of the waveform. A partial represents \n\t\t * the amplitude at a harmonic. The first harmonic is the \n\t\t * fundamental frequency, the second is the octave and so on\n\t\t * following the harmonic series. \n\t\t * Setting this value will automatically set the type to \"custom\". \n\t\t * The value is an empty array when the type is not \"custom\". \n\t\t * This is not available on \"pwm\" and \"pulse\" oscillator types.\n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {Array}\n\t\t * @name partials\n\t\t * @example\n\t\t * osc.partials = [1, 0.2, 0.01];\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'partials', {\n\t get: function () {\n\t return this._oscillator.partials;\n\t },\n\t set: function (partials) {\n\t this._oscillator.partials = partials;\n\t }\n\t });\n\t /**\n\t\t * Set a member/attribute of the oscillator. \n\t\t * @param {Object|String} params\n\t\t * @param {number=} value\n\t\t * @param {Time=} rampTime\n\t\t * @returns {Tone.OmniOscillator} this\n\t\t */\n\t Tone.OmniOscillator.prototype.set = function (params, value) {\n\t //make sure the type is set first\n\t if (params === 'type') {\n\t this.type = value;\n\t } else if (this.isObject(params) && params.hasOwnProperty('type')) {\n\t this.type = params.type;\n\t }\n\t //then set the rest\n\t Tone.prototype.set.apply(this, arguments);\n\t return this;\n\t };\n\t /**\n\t\t * connect the oscillator to the frequency and detune signals\n\t\t * @private\n\t\t */\n\t Tone.OmniOscillator.prototype._createNewOscillator = function (oscType) {\n\t if (oscType !== this._sourceType) {\n\t this._sourceType = oscType;\n\t var OscillatorConstructor = Tone[oscType];\n\t //short delay to avoid clicks on the change\n\t var now = this.now() + this.blockTime;\n\t if (this._oscillator !== null) {\n\t var oldOsc = this._oscillator;\n\t oldOsc.stop(now);\n\t //dispose the old one\n\t setTimeout(function () {\n\t oldOsc.dispose();\n\t oldOsc = null;\n\t }, this.blockTime * 1000);\n\t }\n\t this._oscillator = new OscillatorConstructor();\n\t this.frequency.connect(this._oscillator.frequency);\n\t this.detune.connect(this._oscillator.detune);\n\t this._oscillator.connect(this.output);\n\t if (this.state === Tone.State.Started) {\n\t this._oscillator.start(now);\n\t }\n\t }\n\t };\n\t /**\n\t\t * The phase of the oscillator in degrees. \n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {Degrees}\n\t\t * @name phase\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'phase', {\n\t get: function () {\n\t return this._oscillator.phase;\n\t },\n\t set: function (phase) {\n\t this._oscillator.phase = phase;\n\t }\n\t });\n\t /**\n\t\t * The width of the oscillator (only if the oscillator is set to \"pulse\")\n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {NormalRange}\n\t\t * @signal\n\t\t * @name width\n\t\t * @example\n\t\t * var omniOsc = new Tone.OmniOscillator(440, \"pulse\");\n\t\t * //can access the width attribute only if type === \"pulse\"\n\t\t * omniOsc.width.value = 0.2; \n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'width', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.Pulse) {\n\t return this._oscillator.width;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The number of detuned oscillators\n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {Number}\n\t\t * @name count\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'count', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.Fat) {\n\t return this._oscillator.count;\n\t }\n\t },\n\t set: function (count) {\n\t if (this._sourceType === OmniOscType.Fat) {\n\t this._oscillator.count = count;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The detune spread between the oscillators. If \"count\" is\n\t\t * set to 3 oscillators and the \"spread\" is set to 40,\n\t\t * the three oscillators would be detuned like this: [-20, 0, 20]\n\t\t * for a total detune spread of 40 cents. See Tone.FatOscillator\n\t\t * for more info.\n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {Cents}\n\t\t * @name spread\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'spread', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.Fat) {\n\t return this._oscillator.spread;\n\t }\n\t },\n\t set: function (spread) {\n\t if (this._sourceType === OmniOscType.Fat) {\n\t this._oscillator.spread = spread;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The type of the modulator oscillator. Only if the oscillator\n\t\t * is set to \"am\" or \"fm\" types. see. Tone.AMOscillator or Tone.FMOscillator\n\t\t * for more info. \n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {String}\n\t\t * @name modulationType\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'modulationType', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.FM || this._sourceType === OmniOscType.AM) {\n\t return this._oscillator.modulationType;\n\t }\n\t },\n\t set: function (mType) {\n\t if (this._sourceType === OmniOscType.FM || this._sourceType === OmniOscType.AM) {\n\t this._oscillator.modulationType = mType;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The modulation index which is in essence the depth or amount of the modulation. In other terms it is the \n\t\t * ratio of the frequency of the modulating signal (mf) to the amplitude of the \n\t\t * modulating signal (ma) -- as in ma/mf. \n\t\t * See Tone.FMOscillator for more info. \n\t\t * @type {Positive}\n\t\t * @signal\n\t\t * @name modulationIndex\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'modulationIndex', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.FM) {\n\t return this._oscillator.modulationIndex;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Harmonicity is the frequency ratio between the carrier and the modulator oscillators. \n\t\t * A harmonicity of 1 gives both oscillators the same frequency. \n\t\t * Harmonicity = 2 means a change of an octave. See Tone.AMOscillator or Tone.FMOscillator\n\t\t * for more info. \n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @signal\n\t\t * @type {Positive}\n\t\t * @name harmonicity\n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'harmonicity', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.FM || this._sourceType === OmniOscType.AM) {\n\t return this._oscillator.harmonicity;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The modulationFrequency Signal of the oscillator \n\t\t * (only if the oscillator type is set to pwm). See \n\t\t * Tone.PWMOscillator for more info. \n\t\t * @memberOf Tone.OmniOscillator#\n\t\t * @type {Frequency}\n\t\t * @signal\n\t\t * @name modulationFrequency\n\t\t * @example\n\t\t * var omniOsc = new Tone.OmniOscillator(440, \"pwm\");\n\t\t * //can access the modulationFrequency attribute only if type === \"pwm\"\n\t\t * omniOsc.modulationFrequency.value = 0.2; \n\t\t */\n\t Object.defineProperty(Tone.OmniOscillator.prototype, 'modulationFrequency', {\n\t get: function () {\n\t if (this._sourceType === OmniOscType.PWM) {\n\t return this._oscillator.modulationFrequency;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.OmniOscillator} this\n\t\t */\n\t Tone.OmniOscillator.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'detune'\n\t ]);\n\t this.detune.dispose();\n\t this.detune = null;\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this._oscillator.dispose();\n\t this._oscillator = null;\n\t this._sourceType = null;\n\t return this;\n\t };\n\t return Tone.OmniOscillator;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Base-class for all instruments\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t */\n\t Tone.Instrument = function (options) {\n\t //get the defaults\n\t options = this.defaultArg(options, Tone.Instrument.defaults);\n\t /**\n\t\t\t * The output and volume triming node\n\t\t\t * @type {Tone.Volume}\n\t\t\t * @private\n\t\t\t */\n\t this._volume = this.output = new Tone.Volume(options.volume);\n\t /**\n\t\t\t * The volume of the output in decibels.\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * source.volume.value = -6;\n\t\t\t */\n\t this.volume = this._volume.volume;\n\t this._readOnly('volume');\n\t };\n\t Tone.extend(Tone.Instrument);\n\t /**\n\t\t * the default attributes\n\t\t * @type {object}\n\t\t */\n\t Tone.Instrument.defaults = {\n\t /** the volume of the output in decibels */\n\t 'volume': 0\n\t };\n\t /**\n\t\t * @abstract\n\t\t * @param {string|number} note the note to trigger\n\t\t * @param {Time} [time=now] the time to trigger the ntoe\n\t\t * @param {number} [velocity=1] the velocity to trigger the note\n\t\t */\n\t Tone.Instrument.prototype.triggerAttack = Tone.noOp;\n\t /**\n\t\t * @abstract\n\t\t * @param {Time} [time=now] when to trigger the release\n\t\t */\n\t Tone.Instrument.prototype.triggerRelease = Tone.noOp;\n\t /**\n\t\t * Trigger the attack and then the release after the duration. \n\t\t * @param {Frequency} note The note to trigger.\n\t\t * @param {Time} duration How long the note should be held for before\n\t\t * triggering the release. This value must be greater than 0. \n\t\t * @param {Time} [time=now] When the note should be triggered.\n\t\t * @param {NormalRange} [velocity=1] The velocity the note should be triggered at.\n\t\t * @returns {Tone.Instrument} this\n\t\t * @example\n\t\t * //trigger \"C4\" for the duration of an 8th note\n\t\t * synth.triggerAttackRelease(\"C4\", \"8n\");\n\t\t */\n\t Tone.Instrument.prototype.triggerAttackRelease = function (note, duration, time, velocity) {\n\t if (this.isUndef(time)) {\n\t time = this.now() + this.blockTime;\n\t } else {\n\t time = this.toSeconds(time);\n\t }\n\t duration = this.toSeconds(duration);\n\t this.triggerAttack(note, time, velocity);\n\t this.triggerRelease(time + duration);\n\t return this;\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Instrument} this\n\t\t */\n\t Tone.Instrument.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._volume.dispose();\n\t this._volume = null;\n\t this._writable(['volume']);\n\t this.volume = null;\n\t return this;\n\t };\n\t return Tone.Instrument;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class This is an abstract base class for other monophonic instruments to \n\t\t * extend. IMPORTANT: It does not make any sound on its own and\n\t\t * shouldn't be directly instantiated.\n\t\t *\n\t\t * @constructor\n\t\t * @abstract\n\t\t * @extends {Tone.Instrument}\n\t\t */\n\t Tone.Monophonic = function (options) {\n\t //get the defaults\n\t options = this.defaultArg(options, Tone.Monophonic.defaults);\n\t Tone.Instrument.call(this, options);\n\t /**\n\t\t\t * The glide time between notes. \n\t\t\t * @type {Time}\n\t\t\t */\n\t this.portamento = options.portamento;\n\t };\n\t Tone.extend(Tone.Monophonic, Tone.Instrument);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Monophonic.defaults = { 'portamento': 0 };\n\t /**\n\t\t * Trigger the attack of the note optionally with a given velocity. \n\t\t * \n\t\t * \n\t\t * @param {Frequency} note The note to trigger.\n\t\t * @param {Time} [time=now] When the note should start.\n\t\t * @param {number} [velocity=1] velocity The velocity scaler \n\t\t * determines how \"loud\" the note \n\t\t * will be triggered.\n\t\t * @returns {Tone.Monophonic} this\n\t\t * @example\n\t\t * synth.triggerAttack(\"C4\");\n\t\t * @example\n\t\t * //trigger the note a half second from now at half velocity\n\t\t * synth.triggerAttack(\"C4\", \"+0.5\", 0.5);\n\t\t */\n\t Tone.Monophonic.prototype.triggerAttack = function (note, time, velocity) {\n\t if (this.isUndef(time)) {\n\t time = this.now() + this.blockTime;\n\t } else {\n\t time = this.toSeconds(time);\n\t }\n\t this._triggerEnvelopeAttack(time, velocity);\n\t this.setNote(note, time);\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the release portion of the envelope\n\t\t * @param {Time} [time=now] If no time is given, the release happens immediatly\n\t\t * @returns {Tone.Monophonic} this\n\t\t * @example\n\t\t * synth.triggerRelease();\n\t\t */\n\t Tone.Monophonic.prototype.triggerRelease = function (time) {\n\t if (this.isUndef(time)) {\n\t time = this.now() + this.blockTime;\n\t } else {\n\t time = this.toSeconds(time);\n\t }\n\t this._triggerEnvelopeRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * override this method with the actual method\n\t\t * @abstract\n\t\t * @private\n\t\t */\n\t Tone.Monophonic.prototype._triggerEnvelopeAttack = function () {\n\t };\n\t /**\n\t\t * override this method with the actual method\n\t\t * @abstract\n\t\t * @private\n\t\t */\n\t Tone.Monophonic.prototype._triggerEnvelopeRelease = function () {\n\t };\n\t /**\n\t\t * Set the note at the given time. If no time is given, the note\n\t\t * will set immediately. \n\t\t * @param {Frequency} note The note to change to.\n\t\t * @param {Time} [time=now] The time when the note should be set. \n\t\t * @returns {Tone.Monophonic} this\n\t\t * @example\n\t\t * //change to F#6 in one quarter note from now.\n\t\t * synth.setNote(\"F#6\", \"+4n\");\n\t\t * @example\n\t\t * //change to Bb4 right now\n\t\t * synth.setNote(\"Bb4\");\n\t\t */\n\t Tone.Monophonic.prototype.setNote = function (note, time) {\n\t time = this.toSeconds(time);\n\t if (this.portamento > 0) {\n\t var currentNote = this.frequency.value;\n\t this.frequency.setValueAtTime(currentNote, time);\n\t var portTime = this.toSeconds(this.portamento);\n\t this.frequency.exponentialRampToValueAtTime(note, time + portTime);\n\t } else {\n\t this.frequency.setValueAtTime(note, time);\n\t }\n\t return this;\n\t };\n\t return Tone.Monophonic;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Synth is composed simply of a Tone.OmniOscillator\n\t\t * routed through a Tone.AmplitudeEnvelope. \n\t\t * <img src=\"https://docs.google.com/drawings/d/1-1_0YW2Z1J2EPI36P8fNCMcZG7N1w1GZluPs4og4evo/pub?w=1163&h=231\">\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Monophonic}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var synth = new Tone.Synth().toMaster();\n\t\t * synth.triggerAttackRelease(\"C4\", \"8n\");\n\t\t */\n\t Tone.Synth = function (options) {\n\t //get the defaults\n\t options = this.defaultArg(options, Tone.Synth.defaults);\n\t Tone.Monophonic.call(this, options);\n\t /**\n\t\t\t * The oscillator.\n\t\t\t * @type {Tone.OmniOscillator}\n\t\t\t */\n\t this.oscillator = new Tone.OmniOscillator(options.oscillator);\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this.oscillator.frequency;\n\t /**\n\t\t\t * The detune control.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = this.oscillator.detune;\n\t /**\n\t\t\t * The amplitude envelope.\n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.envelope = new Tone.AmplitudeEnvelope(options.envelope);\n\t //connect the oscillators to the output\n\t this.oscillator.chain(this.envelope, this.output);\n\t //start the oscillators\n\t this.oscillator.start();\n\t this._readOnly([\n\t 'oscillator',\n\t 'frequency',\n\t 'detune',\n\t 'envelope'\n\t ]);\n\t };\n\t Tone.extend(Tone.Synth, Tone.Monophonic);\n\t /**\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.Synth.defaults = {\n\t 'oscillator': { 'type': 'triangle' },\n\t 'envelope': {\n\t 'attack': 0.005,\n\t 'decay': 0.1,\n\t 'sustain': 0.3,\n\t 'release': 1\n\t }\n\t };\n\t /**\n\t\t * start the attack portion of the envelope\n\t\t * @param {Time} [time=now] the time the attack should start\n\t\t * @param {number} [velocity=1] the velocity of the note (0-1)\n\t\t * @returns {Tone.Synth} this\n\t\t * @private\n\t\t */\n\t Tone.Synth.prototype._triggerEnvelopeAttack = function (time, velocity) {\n\t //the envelopes\n\t this.envelope.triggerAttack(time, velocity);\n\t return this;\n\t };\n\t /**\n\t\t * start the release portion of the envelope\n\t\t * @param {Time} [time=now] the time the release should start\n\t\t * @returns {Tone.Synth} this\n\t\t * @private\n\t\t */\n\t Tone.Synth.prototype._triggerEnvelopeRelease = function (time) {\n\t this.envelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Synth} this\n\t\t */\n\t Tone.Synth.prototype.dispose = function () {\n\t Tone.Monophonic.prototype.dispose.call(this);\n\t this._writable([\n\t 'oscillator',\n\t 'frequency',\n\t 'detune',\n\t 'envelope'\n\t ]);\n\t this.oscillator.dispose();\n\t this.oscillator = null;\n\t this.envelope.dispose();\n\t this.envelope = null;\n\t this.frequency = null;\n\t this.detune = null;\n\t return this;\n\t };\n\t return Tone.Synth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class AMSynth uses the output of one Tone.Synth to modulate the\n\t\t * amplitude of another Tone.Synth. The harmonicity (the ratio between\n\t\t * the two signals) affects the timbre of the output signal greatly.\n\t\t * Read more about Amplitude Modulation Synthesis on \n\t\t * [SoundOnSound](http://www.soundonsound.com/sos/mar00/articles/synthsecrets.htm).\n\t\t * <img src=\"https://docs.google.com/drawings/d/1TQu8Ed4iFr1YTLKpB3U1_hur-UwBrh5gdBXc8BxfGKw/pub?w=1009&h=457\">\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Monophonic}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var synth = new Tone.AMSynth().toMaster();\n\t\t * synth.triggerAttackRelease(\"C4\", \"4n\");\n\t\t */\n\t Tone.AMSynth = function (options) {\n\t options = this.defaultArg(options, Tone.AMSynth.defaults);\n\t Tone.Monophonic.call(this, options);\n\t /**\n\t\t\t * The carrier voice. \n\t\t\t * @type {Tone.Synth}\n\t\t\t * @private\n\t\t\t */\n\t this._carrier = new Tone.Synth();\n\t this._carrier.volume.value = -10;\n\t /**\n\t\t\t * The carrier's oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t */\n\t this.oscillator = this._carrier.oscillator;\n\t /**\n\t\t\t * The carrier's envelope\n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.envelope = this._carrier.envelope.set(options.envelope);\n\t /**\n\t\t\t * The modulator voice. \n\t\t\t * @type {Tone.Synth}\n\t\t\t * @private\n\t\t\t */\n\t this._modulator = new Tone.Synth();\n\t this._modulator.volume.value = -10;\n\t /**\n\t\t\t * The modulator's oscillator which is applied\n\t\t\t * to the amplitude of the oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t */\n\t this.modulation = this._modulator.oscillator.set(options.modulation);\n\t /**\n\t\t\t * The modulator's envelope\n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.modulationEnvelope = this._modulator.envelope.set(options.modulationEnvelope);\n\t /**\n\t\t\t * The frequency.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(440, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune in cents\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);\n\t /**\n\t\t\t * Harmonicity is the ratio between the two voices. A harmonicity of\n\t\t\t * 1 is no change. Harmonicity = 2 means a change of an octave. \n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * //pitch voice1 an octave below voice0\n\t\t\t * synth.harmonicity.value = 0.5;\n\t\t\t */\n\t this.harmonicity = new Tone.Multiply(options.harmonicity);\n\t this.harmonicity.units = Tone.Type.Positive;\n\t /**\n\t\t\t * convert the -1,1 output to 0,1\n\t\t\t * @type {Tone.AudioToGain}\n\t\t\t * @private\n\t\t\t */\n\t this._modulationScale = new Tone.AudioToGain();\n\t /**\n\t\t\t * the node where the modulation happens\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._modulationNode = new Tone.Gain();\n\t //control the two voices frequency\n\t this.frequency.connect(this._carrier.frequency);\n\t this.frequency.chain(this.harmonicity, this._modulator.frequency);\n\t this.detune.fan(this._carrier.detune, this._modulator.detune);\n\t this._modulator.chain(this._modulationScale, this._modulationNode.gain);\n\t this._carrier.chain(this._modulationNode, this.output);\n\t this._readOnly([\n\t 'frequency',\n\t 'harmonicity',\n\t 'oscillator',\n\t 'envelope',\n\t 'modulation',\n\t 'modulationEnvelope',\n\t 'detune'\n\t ]);\n\t };\n\t Tone.extend(Tone.AMSynth, Tone.Monophonic);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.AMSynth.defaults = {\n\t 'harmonicity': 3,\n\t 'detune': 0,\n\t 'oscillator': { 'type': 'sine' },\n\t 'envelope': {\n\t 'attack': 0.01,\n\t 'decay': 0.01,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t },\n\t 'modulation': { 'type': 'square' },\n\t 'modulationEnvelope': {\n\t 'attack': 0.5,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t }\n\t };\n\t /**\n\t\t * trigger the attack portion of the note\n\t\t * \n\t\t * @param {Time} [time=now] the time the note will occur\n\t\t * @param {NormalRange} [velocity=1] the velocity of the note\n\t\t * @private\n\t\t * @returns {Tone.AMSynth} this\n\t\t */\n\t Tone.AMSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {\n\t //the port glide\n\t time = this.toSeconds(time);\n\t //the envelopes\n\t this.envelope.triggerAttack(time, velocity);\n\t this.modulationEnvelope.triggerAttack(time, velocity);\n\t return this;\n\t };\n\t /**\n\t\t * trigger the release portion of the note\n\t\t * \n\t\t * @param {Time} [time=now] the time the note will release\n\t\t * @private\n\t\t * @returns {Tone.AMSynth} this\n\t\t */\n\t Tone.AMSynth.prototype._triggerEnvelopeRelease = function (time) {\n\t this.envelope.triggerRelease(time);\n\t this.modulationEnvelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.AMSynth} this\n\t\t */\n\t Tone.AMSynth.prototype.dispose = function () {\n\t Tone.Monophonic.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'harmonicity',\n\t 'oscillator',\n\t 'envelope',\n\t 'modulation',\n\t 'modulationEnvelope',\n\t 'detune'\n\t ]);\n\t this._carrier.dispose();\n\t this._carrier = null;\n\t this._modulator.dispose();\n\t this._modulator = null;\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this.detune.dispose();\n\t this.detune = null;\n\t this.harmonicity.dispose();\n\t this.harmonicity = null;\n\t this._modulationScale.dispose();\n\t this._modulationScale = null;\n\t this._modulationNode.dispose();\n\t this._modulationNode = null;\n\t this.oscillator = null;\n\t this.envelope = null;\n\t this.modulationEnvelope = null;\n\t this.modulation = null;\n\t return this;\n\t };\n\t return Tone.AMSynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.MonoSynth is composed of one oscillator, one filter, and two envelopes.\n\t\t * The amplitude of the Tone.Oscillator and the cutoff frequency of the \n\t\t * Tone.Filter are controlled by Tone.Envelopes. \n\t\t * <img src=\"https://docs.google.com/drawings/d/1gaY1DF9_Hzkodqf8JI1Cg2VZfwSElpFQfI94IQwad38/pub?w=924&h=240\">\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Monophonic}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var synth = new Tone.MonoSynth({\n\t\t * \t\"oscillator\" : {\n\t\t * \t\t\"type\" : \"square\"\n\t\t * },\n\t\t * \"envelope\" : {\n\t\t * \t\"attack\" : 0.1\n\t\t * }\n\t\t * }).toMaster();\n\t\t * synth.triggerAttackRelease(\"C4\", \"8n\");\n\t\t */\n\t Tone.MonoSynth = function (options) {\n\t //get the defaults\n\t options = this.defaultArg(options, Tone.MonoSynth.defaults);\n\t Tone.Monophonic.call(this, options);\n\t /**\n\t\t\t * The oscillator.\n\t\t\t * @type {Tone.OmniOscillator}\n\t\t\t */\n\t this.oscillator = new Tone.OmniOscillator(options.oscillator);\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = this.oscillator.frequency;\n\t /**\n\t\t\t * The detune control.\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = this.oscillator.detune;\n\t /**\n\t\t\t * The filter.\n\t\t\t * @type {Tone.Filter}\n\t\t\t */\n\t this.filter = new Tone.Filter(options.filter);\n\t /**\n\t\t\t * The filter envelope.\n\t\t\t * @type {Tone.FrequencyEnvelope}\n\t\t\t */\n\t this.filterEnvelope = new Tone.FrequencyEnvelope(options.filterEnvelope);\n\t /**\n\t\t\t * The amplitude envelope.\n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.envelope = new Tone.AmplitudeEnvelope(options.envelope);\n\t //connect the oscillators to the output\n\t this.oscillator.chain(this.filter, this.envelope, this.output);\n\t //start the oscillators\n\t this.oscillator.start();\n\t //connect the filter envelope\n\t this.filterEnvelope.connect(this.filter.frequency);\n\t this._readOnly([\n\t 'oscillator',\n\t 'frequency',\n\t 'detune',\n\t 'filter',\n\t 'filterEnvelope',\n\t 'envelope'\n\t ]);\n\t };\n\t Tone.extend(Tone.MonoSynth, Tone.Monophonic);\n\t /**\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.MonoSynth.defaults = {\n\t 'frequency': 'C4',\n\t 'detune': 0,\n\t 'oscillator': { 'type': 'square' },\n\t 'filter': {\n\t 'Q': 6,\n\t 'type': 'lowpass',\n\t 'rolloff': -24\n\t },\n\t 'envelope': {\n\t 'attack': 0.005,\n\t 'decay': 0.1,\n\t 'sustain': 0.9,\n\t 'release': 1\n\t },\n\t 'filterEnvelope': {\n\t 'attack': 0.06,\n\t 'decay': 0.2,\n\t 'sustain': 0.5,\n\t 'release': 2,\n\t 'baseFrequency': 200,\n\t 'octaves': 7,\n\t 'exponent': 2\n\t }\n\t };\n\t /**\n\t\t * start the attack portion of the envelope\n\t\t * @param {Time} [time=now] the time the attack should start\n\t\t * @param {NormalRange} [velocity=1] the velocity of the note (0-1)\n\t\t * @returns {Tone.MonoSynth} this\n\t\t * @private\n\t\t */\n\t Tone.MonoSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {\n\t //the envelopes\n\t this.envelope.triggerAttack(time, velocity);\n\t this.filterEnvelope.triggerAttack(time);\n\t return this;\n\t };\n\t /**\n\t\t * start the release portion of the envelope\n\t\t * @param {Time} [time=now] the time the release should start\n\t\t * @returns {Tone.MonoSynth} this\n\t\t * @private\n\t\t */\n\t Tone.MonoSynth.prototype._triggerEnvelopeRelease = function (time) {\n\t this.envelope.triggerRelease(time);\n\t this.filterEnvelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.MonoSynth} this\n\t\t */\n\t Tone.MonoSynth.prototype.dispose = function () {\n\t Tone.Monophonic.prototype.dispose.call(this);\n\t this._writable([\n\t 'oscillator',\n\t 'frequency',\n\t 'detune',\n\t 'filter',\n\t 'filterEnvelope',\n\t 'envelope'\n\t ]);\n\t this.oscillator.dispose();\n\t this.oscillator = null;\n\t this.envelope.dispose();\n\t this.envelope = null;\n\t this.filterEnvelope.dispose();\n\t this.filterEnvelope = null;\n\t this.filter.dispose();\n\t this.filter = null;\n\t this.frequency = null;\n\t this.detune = null;\n\t return this;\n\t };\n\t return Tone.MonoSynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.DuoSynth is a monophonic synth composed of two \n\t\t * MonoSynths run in parallel with control over the \n\t\t * frequency ratio between the two voices and vibrato effect.\n\t\t * <img src=\"https://docs.google.com/drawings/d/1bL4GXvfRMMlqS7XyBm9CjL9KJPSUKbcdBNpqOlkFLxk/pub?w=1012&h=448\">\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Monophonic}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var duoSynth = new Tone.DuoSynth().toMaster();\n\t\t * duoSynth.triggerAttackRelease(\"C4\", \"2n\");\n\t\t */\n\t Tone.DuoSynth = function (options) {\n\t options = this.defaultArg(options, Tone.DuoSynth.defaults);\n\t Tone.Monophonic.call(this, options);\n\t /**\n\t\t\t * the first voice\n\t\t\t * @type {Tone.MonoSynth}\n\t\t\t */\n\t this.voice0 = new Tone.MonoSynth(options.voice0);\n\t this.voice0.volume.value = -10;\n\t /**\n\t\t\t * the second voice\n\t\t\t * @type {Tone.MonoSynth}\n\t\t\t */\n\t this.voice1 = new Tone.MonoSynth(options.voice1);\n\t this.voice1.volume.value = -10;\n\t /**\n\t\t\t * The vibrato LFO. \n\t\t\t * @type {Tone.LFO}\n\t\t\t * @private\n\t\t\t */\n\t this._vibrato = new Tone.LFO(options.vibratoRate, -50, 50);\n\t this._vibrato.start();\n\t /**\n\t\t\t * the vibrato frequency\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.vibratoRate = this._vibrato.frequency;\n\t /**\n\t\t\t * the vibrato gain\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._vibratoGain = new Tone.Gain(options.vibratoAmount, Tone.Type.Positive);\n\t /**\n\t\t\t * The amount of vibrato\n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this.vibratoAmount = this._vibratoGain.gain;\n\t /**\n\t\t\t * the frequency control\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(440, Tone.Type.Frequency);\n\t /**\n\t\t\t * Harmonicity is the ratio between the two voices. A harmonicity of\n\t\t\t * 1 is no change. Harmonicity = 2 means a change of an octave. \n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * //pitch voice1 an octave below voice0\n\t\t\t * duoSynth.harmonicity.value = 0.5;\n\t\t\t */\n\t this.harmonicity = new Tone.Multiply(options.harmonicity);\n\t this.harmonicity.units = Tone.Type.Positive;\n\t //control the two voices frequency\n\t this.frequency.connect(this.voice0.frequency);\n\t this.frequency.chain(this.harmonicity, this.voice1.frequency);\n\t this._vibrato.connect(this._vibratoGain);\n\t this._vibratoGain.fan(this.voice0.detune, this.voice1.detune);\n\t this.voice0.connect(this.output);\n\t this.voice1.connect(this.output);\n\t this._readOnly([\n\t 'voice0',\n\t 'voice1',\n\t 'frequency',\n\t 'vibratoAmount',\n\t 'vibratoRate'\n\t ]);\n\t };\n\t Tone.extend(Tone.DuoSynth, Tone.Monophonic);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.DuoSynth.defaults = {\n\t 'vibratoAmount': 0.5,\n\t 'vibratoRate': 5,\n\t 'harmonicity': 1.5,\n\t 'voice0': {\n\t 'volume': -10,\n\t 'portamento': 0,\n\t 'oscillator': { 'type': 'sine' },\n\t 'filterEnvelope': {\n\t 'attack': 0.01,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t },\n\t 'envelope': {\n\t 'attack': 0.01,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t }\n\t },\n\t 'voice1': {\n\t 'volume': -10,\n\t 'portamento': 0,\n\t 'oscillator': { 'type': 'sine' },\n\t 'filterEnvelope': {\n\t 'attack': 0.01,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t },\n\t 'envelope': {\n\t 'attack': 0.01,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t }\n\t }\n\t };\n\t /**\n\t\t * start the attack portion of the envelopes\n\t\t * \n\t\t * @param {Time} [time=now] the time the attack should start\n\t\t * @param {NormalRange} [velocity=1] the velocity of the note (0-1)\n\t\t * @returns {Tone.DuoSynth} this\n\t\t * @private\n\t\t */\n\t Tone.DuoSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {\n\t time = this.toSeconds(time);\n\t this.voice0.envelope.triggerAttack(time, velocity);\n\t this.voice1.envelope.triggerAttack(time, velocity);\n\t this.voice0.filterEnvelope.triggerAttack(time);\n\t this.voice1.filterEnvelope.triggerAttack(time);\n\t return this;\n\t };\n\t /**\n\t\t * start the release portion of the envelopes\n\t\t * \n\t\t * @param {Time} [time=now] the time the release should start\n\t\t * @returns {Tone.DuoSynth} this\n\t\t * @private\n\t\t */\n\t Tone.DuoSynth.prototype._triggerEnvelopeRelease = function (time) {\n\t this.voice0.triggerRelease(time);\n\t this.voice1.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.DuoSynth} this\n\t\t */\n\t Tone.DuoSynth.prototype.dispose = function () {\n\t Tone.Monophonic.prototype.dispose.call(this);\n\t this._writable([\n\t 'voice0',\n\t 'voice1',\n\t 'frequency',\n\t 'vibratoAmount',\n\t 'vibratoRate'\n\t ]);\n\t this.voice0.dispose();\n\t this.voice0 = null;\n\t this.voice1.dispose();\n\t this.voice1 = null;\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this._vibratoGain.dispose();\n\t this._vibratoGain = null;\n\t this._vibrato = null;\n\t this.harmonicity.dispose();\n\t this.harmonicity = null;\n\t this.vibratoAmount.dispose();\n\t this.vibratoAmount = null;\n\t this.vibratoRate = null;\n\t return this;\n\t };\n\t return Tone.DuoSynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class FMSynth is composed of two Tone.Synths where one Tone.Synth modulates\n\t\t * the frequency of a second Tone.Synth. A lot of spectral content \n\t\t * can be explored using the modulationIndex parameter. Read more about\n\t\t * frequency modulation synthesis on [SoundOnSound](http://www.soundonsound.com/sos/apr00/articles/synthsecrets.htm).\n\t\t * <img src=\"https://docs.google.com/drawings/d/1h0PUDZXPgi4Ikx6bVT6oncrYPLluFKy7lj53puxj-DM/pub?w=902&h=462\">\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Monophonic}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var fmSynth = new Tone.FMSynth().toMaster();\n\t\t * fmSynth.triggerAttackRelease(\"C5\", \"4n\");\n\t\t */\n\t Tone.FMSynth = function (options) {\n\t options = this.defaultArg(options, Tone.FMSynth.defaults);\n\t Tone.Monophonic.call(this, options);\n\t /**\n\t\t\t * The carrier voice.\n\t\t\t * @type {Tone.Synth}\n\t\t\t * @private\n\t\t\t */\n\t this._carrier = new Tone.Synth(options.carrier);\n\t this._carrier.volume.value = -10;\n\t /**\n\t\t\t * The carrier's oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t */\n\t this.oscillator = this._carrier.oscillator;\n\t /**\n\t\t\t * The carrier's envelope\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t */\n\t this.envelope = this._carrier.envelope.set(options.envelope);\n\t /**\n\t\t\t * The modulator voice.\n\t\t\t * @type {Tone.Synth}\n\t\t\t * @private\n\t\t\t */\n\t this._modulator = new Tone.Synth(options.modulator);\n\t this._modulator.volume.value = -10;\n\t /**\n\t\t\t * The modulator's oscillator which is applied\n\t\t\t * to the amplitude of the oscillator\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t */\n\t this.modulation = this._modulator.oscillator.set(options.modulation);\n\t /**\n\t\t\t * The modulator's envelope\n\t\t\t * @type {Tone.Oscillator}\n\t\t\t */\n\t this.modulationEnvelope = this._modulator.envelope.set(options.modulationEnvelope);\n\t /**\n\t\t\t * The frequency control.\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(440, Tone.Type.Frequency);\n\t /**\n\t\t\t * The detune in cents\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);\n\t /**\n\t\t\t * Harmonicity is the ratio between the two voices. A harmonicity of\n\t\t\t * 1 is no change. Harmonicity = 2 means a change of an octave. \n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * //pitch voice1 an octave below voice0\n\t\t\t * synth.harmonicity.value = 0.5;\n\t\t\t */\n\t this.harmonicity = new Tone.Multiply(options.harmonicity);\n\t this.harmonicity.units = Tone.Type.Positive;\n\t /**\n\t\t\t * The modulation index which essentially the depth or amount of the modulation. It is the \n\t\t\t * ratio of the frequency of the modulating signal (mf) to the amplitude of the \n\t\t\t * modulating signal (ma) -- as in ma/mf. \n\t\t\t *\t@type {Positive}\n\t\t\t *\t@signal\n\t\t\t */\n\t this.modulationIndex = new Tone.Multiply(options.modulationIndex);\n\t this.modulationIndex.units = Tone.Type.Positive;\n\t /**\n\t\t\t * the node where the modulation happens\n\t\t\t * @type {GainNode}\n\t\t\t * @private\n\t\t\t */\n\t this._modulationNode = new Tone.Gain(0);\n\t //control the two voices frequency\n\t this.frequency.connect(this._carrier.frequency);\n\t this.frequency.chain(this.harmonicity, this._modulator.frequency);\n\t this.frequency.chain(this.modulationIndex, this._modulationNode);\n\t this.detune.fan(this._carrier.detune, this._modulator.detune);\n\t this._modulator.connect(this._modulationNode.gain);\n\t this._modulationNode.connect(this._carrier.frequency);\n\t this._carrier.connect(this.output);\n\t this._readOnly([\n\t 'frequency',\n\t 'harmonicity',\n\t 'modulationIndex',\n\t 'oscillator',\n\t 'envelope',\n\t 'modulation',\n\t 'modulationEnvelope',\n\t 'detune'\n\t ]);\n\t };\n\t Tone.extend(Tone.FMSynth, Tone.Monophonic);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.FMSynth.defaults = {\n\t 'harmonicity': 3,\n\t 'modulationIndex': 10,\n\t 'detune': 0,\n\t 'oscillator': { 'type': 'sine' },\n\t 'envelope': {\n\t 'attack': 0.01,\n\t 'decay': 0.01,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t },\n\t 'modulation': { 'type': 'square' },\n\t 'modulationEnvelope': {\n\t 'attack': 0.5,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.5\n\t }\n\t };\n\t /**\n\t\t * \ttrigger the attack portion of the note\n\t\t * \n\t\t * @param {Time} [time=now] the time the note will occur\n\t\t * @param {number} [velocity=1] the velocity of the note\n\t\t * @returns {Tone.FMSynth} this\n\t\t * @private\n\t\t */\n\t Tone.FMSynth.prototype._triggerEnvelopeAttack = function (time, velocity) {\n\t time = this.toSeconds(time);\n\t //the envelopes\n\t this.envelope.triggerAttack(time, velocity);\n\t this.modulationEnvelope.triggerAttack(time);\n\t return this;\n\t };\n\t /**\n\t\t * trigger the release portion of the note\n\t\t * \n\t\t * @param {Time} [time=now] the time the note will release\n\t\t * @returns {Tone.FMSynth} this\n\t\t * @private\n\t\t */\n\t Tone.FMSynth.prototype._triggerEnvelopeRelease = function (time) {\n\t time = this.toSeconds(time);\n\t this.envelope.triggerRelease(time);\n\t this.modulationEnvelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.FMSynth} this\n\t\t */\n\t Tone.FMSynth.prototype.dispose = function () {\n\t Tone.Monophonic.prototype.dispose.call(this);\n\t this._writable([\n\t 'frequency',\n\t 'harmonicity',\n\t 'modulationIndex',\n\t 'oscillator',\n\t 'envelope',\n\t 'modulation',\n\t 'modulationEnvelope',\n\t 'detune'\n\t ]);\n\t this._carrier.dispose();\n\t this._carrier = null;\n\t this._modulator.dispose();\n\t this._modulator = null;\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this.detune.dispose();\n\t this.detune = null;\n\t this.modulationIndex.dispose();\n\t this.modulationIndex = null;\n\t this.harmonicity.dispose();\n\t this.harmonicity = null;\n\t this._modulationNode.dispose();\n\t this._modulationNode = null;\n\t this.oscillator = null;\n\t this.envelope = null;\n\t this.modulationEnvelope = null;\n\t this.modulation = null;\n\t return this;\n\t };\n\t return Tone.FMSynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.MembraneSynth makes kick and tom sounds using a single oscillator\n\t\t * with an amplitude envelope and frequency ramp. A Tone.OmniOscillator\n\t\t * is routed through a Tone.AmplitudeEnvelope to the output. The drum\n\t\t * quality of the sound comes from the frequency envelope applied\n\t\t * during during Tone.MembraneSynth.triggerAttack(note). The frequency\n\t\t * envelope starts at <code>note * .octaves</code> and ramps to \n\t\t * <code>note</code> over the duration of <code>.pitchDecay</code>. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Instrument}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var synth = new Tone.MembraneSynth().toMaster();\n\t\t * synth.triggerAttackRelease(\"C2\", \"8n\");\n\t\t */\n\t Tone.MembraneSynth = function (options) {\n\t options = this.defaultArg(options, Tone.MembraneSynth.defaults);\n\t Tone.Instrument.call(this, options);\n\t /**\n\t\t\t * The oscillator.\n\t\t\t * @type {Tone.OmniOscillator}\n\t\t\t */\n\t this.oscillator = new Tone.OmniOscillator(options.oscillator).start();\n\t /**\n\t\t\t * The amplitude envelope.\n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.envelope = new Tone.AmplitudeEnvelope(options.envelope);\n\t /**\n\t\t\t * The number of octaves the pitch envelope ramps.\n\t\t\t * @type {Positive}\n\t\t\t */\n\t this.octaves = options.octaves;\n\t /**\n\t\t\t * The amount of time the frequency envelope takes. \n\t\t\t * @type {Time}\n\t\t\t */\n\t this.pitchDecay = options.pitchDecay;\n\t this.oscillator.chain(this.envelope, this.output);\n\t this._readOnly([\n\t 'oscillator',\n\t 'envelope'\n\t ]);\n\t };\n\t Tone.extend(Tone.MembraneSynth, Tone.Instrument);\n\t /**\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.MembraneSynth.defaults = {\n\t 'pitchDecay': 0.05,\n\t 'octaves': 10,\n\t 'oscillator': { 'type': 'sine' },\n\t 'envelope': {\n\t 'attack': 0.001,\n\t 'decay': 0.4,\n\t 'sustain': 0.01,\n\t 'release': 1.4,\n\t 'attackCurve': 'exponential'\n\t }\n\t };\n\t /**\n\t\t * Trigger the note at the given time with the given velocity. \n\t\t * \n\t\t * @param {Frequency} note the note\n\t\t * @param {Time} [time=now] the time, if not given is now\n\t\t * @param {number} [velocity=1] velocity defaults to 1\n\t\t * @returns {Tone.MembraneSynth} this\n\t\t * @example\n\t\t * kick.triggerAttack(60);\n\t\t */\n\t Tone.MembraneSynth.prototype.triggerAttack = function (note, time, velocity) {\n\t time = this.toSeconds(time);\n\t note = this.toFrequency(note);\n\t var maxNote = note * this.octaves;\n\t this.oscillator.frequency.setValueAtTime(maxNote, time);\n\t this.oscillator.frequency.exponentialRampToValueAtTime(note, time + this.toSeconds(this.pitchDecay));\n\t this.envelope.triggerAttack(time, velocity);\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the release portion of the note.\n\t\t * \n\t\t * @param {Time} [time=now] the time the note will release\n\t\t * @returns {Tone.MembraneSynth} this\n\t\t */\n\t Tone.MembraneSynth.prototype.triggerRelease = function (time) {\n\t this.envelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.MembraneSynth} this\n\t\t */\n\t Tone.MembraneSynth.prototype.dispose = function () {\n\t Tone.Instrument.prototype.dispose.call(this);\n\t this._writable([\n\t 'oscillator',\n\t 'envelope'\n\t ]);\n\t this.oscillator.dispose();\n\t this.oscillator = null;\n\t this.envelope.dispose();\n\t this.envelope = null;\n\t return this;\n\t };\n\t return Tone.MembraneSynth;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * Inharmonic ratio of frequencies based on the Roland TR-808\n\t\t * Taken from https://ccrma.stanford.edu/papers/tr-808-cymbal-physically-informed-circuit-bendable-digital-model\n\t\t * @private\n\t\t * @static\n\t\t * @type {Array}\n\t\t */\n\t var inharmRatios = [\n\t 1,\n\t 1.483,\n\t 1.932,\n\t 2.546,\n\t 2.63,\n\t 3.897\n\t ];\n\t /**\n\t\t * @class A highly inharmonic and spectrally complex source with a highpass filter\n\t\t * and amplitude envelope which is good for making metalophone sounds. Based\n\t\t * on CymbalSynth by [@polyrhythmatic](https://github.com/polyrhythmatic).\n\t\t * Inspiration from [Sound on Sound](http://www.soundonsound.com/sos/jul02/articles/synthsecrets0702.asp).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Instrument}\n\t\t * @param {Object} [options] The options availble for the synth\n\t\t * see defaults below\n\t\t */\n\t Tone.MetalSynth = function (options) {\n\t options = this.defaultArg(options, Tone.MetalSynth.defaults);\n\t Tone.Instrument.call(this, options);\n\t /**\n\t\t\t * The frequency of the cymbal\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);\n\t /**\n\t\t\t * The array of FMOscillators\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._oscillators = [];\n\t /**\n\t\t\t * The frequency multipliers\n\t\t\t * @type {Array}\n\t\t\t * @private\n\t\t\t */\n\t this._freqMultipliers = [];\n\t /**\n\t\t\t * The amplitude for the body\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._amplitue = new Tone.Gain(0).connect(this.output);\n\t /**\n\t\t\t * highpass the output\n\t\t\t * @type {Tone.Filter}\n\t\t\t * @private\n\t\t\t */\n\t this._highpass = new Tone.Filter({\n\t 'type': 'highpass',\n\t 'Q': -3.0102999566398125\n\t }).connect(this._amplitue);\n\t /**\n\t\t\t * The number of octaves the highpass\n\t\t\t * filter frequency ramps\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._octaves = options.octaves;\n\t /**\n\t\t\t * Scale the body envelope\n\t\t\t * for the bandpass\n\t\t\t * @type {Tone.Scale}\n\t\t\t * @private\n\t\t\t */\n\t this._filterFreqScaler = new Tone.Scale(options.resonance, 7000);\n\t /**\n\t\t\t * The envelope which is connected both to the \n\t\t\t * amplitude and highpass filter's cutoff frequency\n\t\t\t * @type {Tone.Envelope}\n\t\t\t */\n\t this.envelope = new Tone.Envelope({\n\t 'attack': options.envelope.attack,\n\t 'attackCurve': 'linear',\n\t 'decay': options.envelope.decay,\n\t 'sustain': 0,\n\t 'release': options.envelope.release\n\t }).chain(this._filterFreqScaler, this._highpass.frequency);\n\t this.envelope.connect(this._amplitue.gain);\n\t for (var i = 0; i < inharmRatios.length; i++) {\n\t var osc = new Tone.FMOscillator({\n\t 'type': 'square',\n\t 'modulationType': 'square',\n\t 'harmonicity': options.harmonicity,\n\t 'modulationIndex': options.modulationIndex\n\t });\n\t osc.connect(this._highpass).start(0);\n\t this._oscillators[i] = osc;\n\t var mult = new Tone.Multiply(inharmRatios[i]);\n\t this._freqMultipliers[i] = mult;\n\t this.frequency.chain(mult, osc.frequency);\n\t }\n\t //set the octaves\n\t this.octaves = options.octaves;\n\t };\n\t Tone.extend(Tone.MetalSynth, Tone.Instrument);\n\t /**\n\t\t * default values\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.MetalSynth.defaults = {\n\t 'frequency': 200,\n\t 'envelope': {\n\t 'attack': 0.001,\n\t 'decay': 1.4,\n\t 'release': 0.2\n\t },\n\t 'harmonicity': 5.1,\n\t 'modulationIndex': 32,\n\t 'resonance': 4000,\n\t 'octaves': 1.5\n\t };\n\t /**\n\t\t * Trigger the attack.\n\t\t * @param {Time} time When the attack should be triggered.\n\t\t * @param {NormalRange=1} velocity The velocity that the envelope should be triggered at.\n\t\t * @return {Tone.MetalSynth} this\n\t\t */\n\t Tone.MetalSynth.prototype.triggerAttack = function (time, vel) {\n\t time = this.toSeconds(time);\n\t vel = this.defaultArg(vel, 1);\n\t this.envelope.triggerAttack(time, vel);\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the release of the envelope.\n\t\t * @param {Time} time When the release should be triggered.\n\t\t * @return {Tone.MetalSynth} this\n\t\t */\n\t Tone.MetalSynth.prototype.triggerRelease = function (time) {\n\t time = this.toSeconds(time);\n\t this.envelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the attack and release of the envelope after the given \n\t\t * duration. \n\t\t * @param {Time} duration The duration before triggering the release\n\t\t * @param {Time} time When the attack should be triggered.\n\t\t * @param {NormalRange=1} velocity The velocity that the envelope should be triggered at.\n\t\t * @return {Tone.MetalSynth} this\n\t\t */\n\t Tone.MetalSynth.prototype.triggerAttackRelease = function (duration, time, velocity) {\n\t time = this.toSeconds(time);\n\t duration = this.toSeconds(duration);\n\t this.triggerAttack(time, velocity);\n\t this.triggerRelease(time + duration);\n\t return this;\n\t };\n\t /**\n\t\t * The modulationIndex of the oscillators which make up the source.\n\t\t * see Tone.FMOscillator.modulationIndex\n\t\t * @memberOf Tone.MetalSynth#\n\t\t * @type {Positive}\n\t\t * @name modulationIndex\n\t\t */\n\t Object.defineProperty(Tone.MetalSynth.prototype, 'modulationIndex', {\n\t get: function () {\n\t return this._oscillators[0].modulationIndex.value;\n\t },\n\t set: function (val) {\n\t for (var i = 0; i < this._oscillators.length; i++) {\n\t this._oscillators[i].modulationIndex.value = val;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The harmonicity of the oscillators which make up the source.\n\t\t * see Tone.FMOscillator.harmonicity\n\t\t * @memberOf Tone.MetalSynth#\n\t\t * @type {Positive}\n\t\t * @name harmonicity\n\t\t */\n\t Object.defineProperty(Tone.MetalSynth.prototype, 'harmonicity', {\n\t get: function () {\n\t return this._oscillators[0].harmonicity.value;\n\t },\n\t set: function (val) {\n\t for (var i = 0; i < this._oscillators.length; i++) {\n\t this._oscillators[i].harmonicity.value = val;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The frequency of the highpass filter attached to the envelope\n\t\t * @memberOf Tone.MetalSynth#\n\t\t * @type {Frequency}\n\t\t * @name resonance\n\t\t */\n\t Object.defineProperty(Tone.MetalSynth.prototype, 'resonance', {\n\t get: function () {\n\t return this._filterFreqScaler.min;\n\t },\n\t set: function (val) {\n\t this._filterFreqScaler.min = val;\n\t this.octaves = this._octaves;\n\t }\n\t });\n\t /**\n\t\t * The number of octaves above the \"resonance\" frequency\n\t\t * that the filter ramps during the attack/decay envelope\n\t\t * @memberOf Tone.MetalSynth#\n\t\t * @type {Number}\n\t\t * @name octaves\n\t\t */\n\t Object.defineProperty(Tone.MetalSynth.prototype, 'octaves', {\n\t get: function () {\n\t return this._octaves;\n\t },\n\t set: function (octs) {\n\t this._octaves = octs;\n\t this._filterFreqScaler.max = this._filterFreqScaler.min * Math.pow(2, octs);\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @returns {Tone.MetalSynth} this\n\t\t */\n\t Tone.MetalSynth.prototype.dispose = function () {\n\t Tone.Instrument.prototype.dispose.call(this);\n\t for (var i = 0; i < this._oscillators.length; i++) {\n\t this._oscillators[i].dispose();\n\t this._freqMultipliers[i].dispose();\n\t }\n\t this._oscillators = null;\n\t this._freqMultipliers = null;\n\t this.frequency.dispose();\n\t this.frequency = null;\n\t this._filterFreqScaler.dispose();\n\t this._filterFreqScaler = null;\n\t this._amplitue.dispose();\n\t this._amplitue = null;\n\t this.envelope.dispose();\n\t this.envelope = null;\n\t this._highpass.dispose();\n\t this._highpass = null;\n\t };\n\t return Tone.MetalSynth;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * BufferSource polyfill\n\t\t */\n\t if (window.AudioBufferSourceNode && !AudioBufferSourceNode.prototype.start) {\n\t AudioBufferSourceNode.prototype.start = AudioBufferSourceNode.prototype.noteGrainOn;\n\t AudioBufferSourceNode.prototype.stop = AudioBufferSourceNode.prototype.noteOff;\n\t }\n\t /**\n\t\t * @class Wrapper around the native BufferSourceNode.\n\t\t * @param {AudioBuffer|Tone.Buffer} buffer The buffer to play\n\t\t * @param {Function} onended The callback to invoke when the \n\t\t * buffer is done playing.\n\t\t */\n\t Tone.BufferSource = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'buffer',\n\t 'onended'\n\t ], Tone.BufferSource.defaults);\n\t /**\n\t\t\t * The callback to invoke after the \n\t\t\t * buffer source is done playing. \n\t\t\t * @type {Function}\n\t\t\t */\n\t this.onended = options.onended;\n\t /**\n\t\t\t * The time that the buffer was started.\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._startTime = -1;\n\t /**\n\t\t\t * The time that the buffer is scheduled to stop.\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._stopTime = -1;\n\t /**\n\t\t\t * The gain node which envelopes the BufferSource\n\t\t\t * @type {Tone.Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._gainNode = this.output = new Tone.Gain();\n\t /**\n\t\t\t * The buffer source\n\t\t\t * @type {AudioBufferSourceNode}\n\t\t\t * @private\n\t\t\t */\n\t this._source = this.context.createBufferSource();\n\t this._source.connect(this._gainNode);\n\t /**\n\t\t\t * The playbackRate of the buffer\n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this.playbackRate = new Tone.Param(this._source.playbackRate, Tone.Type.Positive);\n\t /**\n\t\t\t * The fadeIn time of the amplitude envelope.\n\t\t\t * @type {Time}\n\t\t\t */\n\t this.fadeIn = options.fadeIn;\n\t /**\n\t\t\t * The fadeOut time of the amplitude envelope.\n\t\t\t * @type {Time}\n\t\t\t */\n\t this.fadeOut = options.fadeOut;\n\t /**\n\t\t\t * The value that the buffer ramps to\n\t\t\t * @type {Gain}\n\t\t\t * @private\n\t\t\t */\n\t this._gain = 1;\n\t /**\n\t\t\t * The onended timeout\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._onendedTimeout = -1;\n\t //set the buffer initially\n\t if (!this.isUndef(options.buffer)) {\n\t this.buffer = options.buffer;\n\t }\n\t this.loop = options.loop;\n\t };\n\t Tone.extend(Tone.BufferSource);\n\t /**\n\t\t * The defaults\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.BufferSource.defaults = {\n\t 'onended': Tone.noOp,\n\t 'fadeIn': 0,\n\t 'fadeOut': 0\n\t };\n\t /**\n\t\t * Returns the playback state of the source, either \"started\" or \"stopped\".\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.BufferSource#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.BufferSource.prototype, 'state', {\n\t get: function () {\n\t var now = this.now();\n\t if (this._startTime !== -1 && now >= this._startTime && now < this._stopTime) {\n\t return Tone.State.Started;\n\t } else {\n\t return Tone.State.Stopped;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Start the buffer\n\t\t * @param {Time} [startTime=now] When the player should start.\n\t\t * @param {Time} [offset=0] The offset from the beginning of the sample\n\t\t * to start at. \n\t\t * @param {Time=} duration How long the sample should play. If no duration\n\t\t * is given, it will default to the full length \n\t\t * of the sample (minus any offset)\n\t\t * @param {Gain} [gain=1] The gain to play the buffer back at.\n\t\t * @param {Time=} fadeInTime The optional fadeIn ramp time.\n\t\t * @return {Tone.BufferSource} this\n\t\t */\n\t Tone.BufferSource.prototype.start = function (time, offset, duration, gain, fadeInTime) {\n\t if (this._startTime !== -1) {\n\t throw new Error('Tone.BufferSource: can only be started once.');\n\t }\n\t if (this.buffer) {\n\t time = this.toSeconds(time);\n\t //if it's a loop the default offset is the loopstart point\n\t if (this.loop) {\n\t offset = this.defaultArg(offset, this.loopStart);\n\t } else {\n\t //otherwise the default offset is 0\n\t offset = this.defaultArg(offset, 0);\n\t }\n\t offset = this.toSeconds(offset);\n\t //the values in seconds\n\t time = this.toSeconds(time);\n\t this._source.start(time, offset);\n\t gain = this.defaultArg(gain, 1);\n\t this._gain = gain;\n\t //the fadeIn time\n\t if (this.isUndef(fadeInTime)) {\n\t fadeInTime = this.toSeconds(this.fadeIn);\n\t } else {\n\t fadeInTime = this.toSeconds(fadeInTime);\n\t }\n\t if (fadeInTime > 0) {\n\t this._gainNode.gain.setValueAtTime(0, time);\n\t this._gainNode.gain.linearRampToValueAtTime(this._gain, time + fadeInTime);\n\t } else {\n\t this._gainNode.gain.setValueAtTime(gain, time);\n\t }\n\t this._startTime = time + fadeInTime;\n\t if (!this.isUndef(duration)) {\n\t duration = this.defaultArg(duration, this.buffer.duration - offset);\n\t duration = this.toSeconds(duration);\n\t this.stop(time + duration + fadeInTime, fadeInTime);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Stop the buffer. Optionally add a ramp time to fade the \n\t\t * buffer out. \n\t\t * @param {Time=} time The time the buffer should stop.\n\t\t * @param {Time=} fadeOutTime How long the gain should fade out for\n\t\t * @return {Tone.BufferSource} this\n\t\t */\n\t Tone.BufferSource.prototype.stop = function (time, fadeOutTime) {\n\t if (this.buffer) {\n\t time = this.toSeconds(time);\n\t //the fadeOut time\n\t if (this.isUndef(fadeOutTime)) {\n\t fadeOutTime = this.toSeconds(this.fadeOut);\n\t } else {\n\t fadeOutTime = this.toSeconds(fadeOutTime);\n\t }\n\t this._stopTime = time + fadeOutTime;\n\t //cancel the end curve\n\t this._gainNode.gain.cancelScheduledValues(this._startTime + this.sampleTime);\n\t //set a new one\n\t if (fadeOutTime > 0) {\n\t this._gainNode.gain.setValueAtTime(this._gain, time);\n\t this._gainNode.gain.linearRampToValueAtTime(0, time + fadeOutTime);\n\t time += fadeOutTime;\n\t } else {\n\t this._gainNode.gain.setValueAtTime(0, time);\n\t }\n\t // fix for safari bug and old FF\n\t if (!this.isNumber(this._source.playbackState) || this._source.playbackState === 2) {\n\t this._source.stop(time);\n\t }\n\t clearTimeout(this._onendedTimeout);\n\t this._onendedTimeout = setTimeout(this._onended.bind(this), (this._stopTime - this.now()) * 1000);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Internal callback when the buffer is ended. \n\t\t * Invokes `onended` and disposes the node.\n\t\t * @private\n\t\t */\n\t Tone.BufferSource.prototype._onended = function () {\n\t this.onended(this);\n\t this.dispose();\n\t };\n\t /**\n\t\t * If loop is true, the loop will start at this position. \n\t\t * @memberOf Tone.BufferSource#\n\t\t * @type {Time}\n\t\t * @name loopStart\n\t\t */\n\t Object.defineProperty(Tone.BufferSource.prototype, 'loopStart', {\n\t get: function () {\n\t return this._source.loopStart;\n\t },\n\t set: function (loopStart) {\n\t this._source.loopStart = this.toSeconds(loopStart);\n\t }\n\t });\n\t /**\n\t\t * If loop is true, the loop will end at this position.\n\t\t * @memberOf Tone.BufferSource#\n\t\t * @type {Time}\n\t\t * @name loopEnd\n\t\t */\n\t Object.defineProperty(Tone.BufferSource.prototype, 'loopEnd', {\n\t get: function () {\n\t return this._source.loopEnd;\n\t },\n\t set: function (loopEnd) {\n\t this._source.loopEnd = this.toSeconds(loopEnd);\n\t }\n\t });\n\t /**\n\t\t * The audio buffer belonging to the player. \n\t\t * @memberOf Tone.BufferSource#\n\t\t * @type {AudioBuffer}\n\t\t * @name buffer\n\t\t */\n\t Object.defineProperty(Tone.BufferSource.prototype, 'buffer', {\n\t get: function () {\n\t if (this._source) {\n\t return this._source.buffer;\n\t } else {\n\t return null;\n\t }\n\t },\n\t set: function (buffer) {\n\t if (buffer instanceof Tone.Buffer) {\n\t this._source.buffer = buffer.get();\n\t } else {\n\t this._source.buffer = buffer;\n\t }\n\t }\n\t });\n\t /**\n\t\t * If the buffer should loop once it's over. \n\t\t * @memberOf Tone.BufferSource#\n\t\t * @type {boolean}\n\t\t * @name loop\n\t\t */\n\t Object.defineProperty(Tone.BufferSource.prototype, 'loop', {\n\t get: function () {\n\t return this._source.loop;\n\t },\n\t set: function (loop) {\n\t this._source.loop = loop;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.BufferSource} this\n\t\t */\n\t Tone.BufferSource.prototype.dispose = function () {\n\t this.onended = null;\n\t if (this._source) {\n\t this._source.disconnect();\n\t this._source = null;\n\t }\n\t if (this._gainNode) {\n\t this._gainNode.dispose();\n\t this._gainNode = null;\n\t }\n\t this._startTime = -1;\n\t this.playbackRate = null;\n\t this.output = null;\n\t clearTimeout(this._onendedTimeout);\n\t return this;\n\t };\n\t return Tone.BufferSource;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Noise is a noise generator. It uses looped noise buffers to save on performance.\n\t\t * Tone.Noise supports the noise types: \"pink\", \"white\", and \"brown\". Read more about\n\t\t * colors of noise on [Wikipedia](https://en.wikipedia.org/wiki/Colors_of_noise).\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Source}\n\t\t * @param {string} type the noise type (white|pink|brown)\n\t\t * @example\n\t\t * //initialize the noise and start\n\t\t * var noise = new Tone.Noise(\"pink\").start();\n\t\t * \n\t\t * //make an autofilter to shape the noise\n\t\t * var autoFilter = new Tone.AutoFilter({\n\t\t * \t\"frequency\" : \"8m\", \n\t\t * \t\"min\" : 800, \n\t\t * \t\"max\" : 15000\n\t\t * }).connect(Tone.Master);\n\t\t * \n\t\t * //connect the noise\n\t\t * noise.connect(autoFilter);\n\t\t * //start the autofilter LFO\n\t\t * autoFilter.start()\n\t\t */\n\t Tone.Noise = function () {\n\t var options = this.optionsObject(arguments, ['type'], Tone.Noise.defaults);\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * @private\n\t\t\t * @type {AudioBufferSourceNode}\n\t\t\t */\n\t this._source = null;\n\t /**\n\t\t\t * the buffer\n\t\t\t * @private\n\t\t\t * @type {AudioBuffer}\n\t\t\t */\n\t this._type = options.type;\n\t /**\n\t\t\t * The playback rate of the noise. Affects\n\t\t\t * the \"frequency\" of the noise.\n\t\t\t * @type {Positive}\n\t\t\t * @signal\n\t\t\t */\n\t this._playbackRate = options.playbackRate;\n\t };\n\t Tone.extend(Tone.Noise, Tone.Source);\n\t /**\n\t\t * the default parameters\n\t\t *\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Noise.defaults = {\n\t 'type': 'white',\n\t 'playbackRate': 1\n\t };\n\t /**\n\t\t * The type of the noise. Can be \"white\", \"brown\", or \"pink\". \n\t\t * @memberOf Tone.Noise#\n\t\t * @type {string}\n\t\t * @name type\n\t\t * @example\n\t\t * noise.type = \"white\";\n\t\t */\n\t Object.defineProperty(Tone.Noise.prototype, 'type', {\n\t get: function () {\n\t return this._type;\n\t },\n\t set: function (type) {\n\t if (this._type !== type) {\n\t if (type in _noiseBuffers) {\n\t this._type = type;\n\t //if it's playing, stop and restart it\n\t if (this.state === Tone.State.Started) {\n\t var now = this.now() + this.blockTime;\n\t this._stop(now);\n\t this._start(now);\n\t }\n\t } else {\n\t throw new TypeError('Tone.Noise: invalid type: ' + type);\n\t }\n\t }\n\t }\n\t });\n\t /**\n\t\t * The playback rate of the noise. Affects\n\t\t * the \"frequency\" of the noise.\n\t\t * @type {Positive}\n\t\t * @signal\n\t\t */\n\t Object.defineProperty(Tone.Noise.prototype, 'playbackRate', {\n\t get: function () {\n\t return this._playbackRate;\n\t },\n\t set: function (rate) {\n\t this._playbackRate = rate;\n\t if (this._source) {\n\t this._source.playbackRate.value = rate;\n\t }\n\t }\n\t });\n\t /**\n\t\t * internal start method\n\t\t *\n\t\t * @param {Time} time\n\t\t * @private\n\t\t */\n\t Tone.Noise.prototype._start = function (time) {\n\t var buffer = _noiseBuffers[this._type];\n\t this._source = new Tone.BufferSource(buffer).connect(this.output);\n\t this._source.loop = true;\n\t this._source.playbackRate.value = this._playbackRate;\n\t this._source.start(this.toSeconds(time), Math.random() * (buffer.duration - 0.001));\n\t };\n\t /**\n\t\t * internal stop method\n\t\t *\n\t\t * @param {Time} time\n\t\t * @private\n\t\t */\n\t Tone.Noise.prototype._stop = function (time) {\n\t if (this._source) {\n\t this._source.stop(this.toSeconds(time));\n\t this._source = null;\n\t }\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Noise} this\n\t\t */\n\t Tone.Noise.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t if (this._source !== null) {\n\t this._source.disconnect();\n\t this._source = null;\n\t }\n\t this._buffer = null;\n\t return this;\n\t };\n\t ///////////////////////////////////////////////////////////////////////////\n\t // THE BUFFERS\n\t ///////////////////////////////////////////////////////////////////////////\n\t //Noise buffer stats\n\t var bufferLength = 44100 * 5;\n\t var channels = 2;\n\t /**\n\t\t *\tthe noise arrays. only generated once on init\n\t\t * @static\n\t\t * @private\n\t\t * @type {Array}\n\t\t * borrowed heavily from https://github.com/zacharydenton/noise.js \n\t\t * (c) 2013 Zach Denton (MIT)\n\t\t */\n\t var _noiseArrays = {\n\t 'pink': function () {\n\t var buffer = [];\n\t for (var channelNum = 0; channelNum < channels; channelNum++) {\n\t var channel = new Float32Array(bufferLength);\n\t buffer[channelNum] = channel;\n\t var b0, b1, b2, b3, b4, b5, b6;\n\t b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0;\n\t for (var i = 0; i < bufferLength; i++) {\n\t var white = Math.random() * 2 - 1;\n\t b0 = 0.99886 * b0 + white * 0.0555179;\n\t b1 = 0.99332 * b1 + white * 0.0750759;\n\t b2 = 0.969 * b2 + white * 0.153852;\n\t b3 = 0.8665 * b3 + white * 0.3104856;\n\t b4 = 0.55 * b4 + white * 0.5329522;\n\t b5 = -0.7616 * b5 - white * 0.016898;\n\t channel[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;\n\t channel[i] *= 0.11;\n\t // (roughly) compensate for gain\n\t b6 = white * 0.115926;\n\t }\n\t }\n\t return buffer;\n\t }(),\n\t 'brown': function () {\n\t var buffer = [];\n\t for (var channelNum = 0; channelNum < channels; channelNum++) {\n\t var channel = new Float32Array(bufferLength);\n\t buffer[channelNum] = channel;\n\t var lastOut = 0;\n\t for (var i = 0; i < bufferLength; i++) {\n\t var white = Math.random() * 2 - 1;\n\t channel[i] = (lastOut + 0.02 * white) / 1.02;\n\t lastOut = channel[i];\n\t channel[i] *= 3.5; // (roughly) compensate for gain\n\t }\n\t }\n\t return buffer;\n\t }(),\n\t 'white': function () {\n\t var buffer = [];\n\t for (var channelNum = 0; channelNum < channels; channelNum++) {\n\t var channel = new Float32Array(bufferLength);\n\t buffer[channelNum] = channel;\n\t for (var i = 0; i < bufferLength; i++) {\n\t channel[i] = Math.random() * 2 - 1;\n\t }\n\t }\n\t return buffer;\n\t }()\n\t };\n\t /**\n\t\t *\tstatic noise buffers\n\t\t * @static\n\t\t * @private\n\t\t * @type {Tone.Buffer}\n\t\t */\n\t var _noiseBuffers = {};\n\t //create the Tone.Buffers\n\t function createBuffers() {\n\t for (var type in _noiseArrays) {\n\t _noiseBuffers[type] = new Tone.Buffer().fromArray(_noiseArrays[type]);\n\t }\n\t }\n\t createBuffers();\n\t Tone.Context.on('init', createBuffers);\n\t return Tone.Noise;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.NoiseSynth is composed of a noise generator (Tone.Noise), one filter (Tone.Filter), \n\t\t * and two envelopes (Tone.Envelop). One envelope controls the amplitude\n\t\t * of the noise and the other is controls the cutoff frequency of the filter. \n\t\t * <img src=\"https://docs.google.com/drawings/d/1rqzuX9rBlhT50MRvD2TKml9bnZhcZmzXF1rf_o7vdnE/pub?w=918&h=242\">\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Instrument}\n\t\t * @param {Object} [options] the options available for the synth \n\t\t * see defaults below\n\t\t * @example\n\t\t * var noiseSynth = new Tone.NoiseSynth().toMaster();\n\t\t * noiseSynth.triggerAttackRelease(\"8n\");\n\t\t */\n\t Tone.NoiseSynth = function (options) {\n\t //get the defaults\n\t options = this.defaultArg(options, Tone.NoiseSynth.defaults);\n\t Tone.Instrument.call(this, options);\n\t /**\n\t\t\t * The noise source.\n\t\t\t * @type {Tone.Noise}\n\t\t\t * @example\n\t\t\t * noiseSynth.set(\"noise.type\", \"brown\");\n\t\t\t */\n\t this.noise = new Tone.Noise();\n\t /**\n\t\t\t * The amplitude envelope. \n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.envelope = new Tone.AmplitudeEnvelope(options.envelope);\n\t //connect the noise to the output\n\t this.noise.chain(this.envelope, this.output);\n\t //start the noise\n\t this.noise.start();\n\t this._readOnly([\n\t 'noise',\n\t 'envelope'\n\t ]);\n\t };\n\t Tone.extend(Tone.NoiseSynth, Tone.Instrument);\n\t /**\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.NoiseSynth.defaults = {\n\t 'noise': { 'type': 'white' },\n\t 'envelope': {\n\t 'attack': 0.005,\n\t 'decay': 0.1,\n\t 'sustain': 0\n\t }\n\t };\n\t /**\n\t\t * Start the attack portion of the envelopes. Unlike other \n\t\t * instruments, Tone.NoiseSynth doesn't have a note. \n\t\t * @param {Time} [time=now] the time the attack should start\n\t\t * @param {number} [velocity=1] the velocity of the note (0-1)\n\t\t * @returns {Tone.NoiseSynth} this\n\t\t * @example\n\t\t * noiseSynth.triggerAttack();\n\t\t */\n\t Tone.NoiseSynth.prototype.triggerAttack = function (time, velocity) {\n\t //the envelopes\n\t this.envelope.triggerAttack(time, velocity);\n\t return this;\n\t };\n\t /**\n\t\t * Start the release portion of the envelopes.\n\t\t * @param {Time} [time=now] the time the release should start\n\t\t * @returns {Tone.NoiseSynth} this\n\t\t */\n\t Tone.NoiseSynth.prototype.triggerRelease = function (time) {\n\t this.envelope.triggerRelease(time);\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the attack and then the release. \n\t\t * @param {Time} duration the duration of the note\n\t\t * @param {Time} [time=now] the time of the attack\n\t\t * @param {number} [velocity=1] the velocity\n\t\t * @returns {Tone.NoiseSynth} this\n\t\t */\n\t Tone.NoiseSynth.prototype.triggerAttackRelease = function (duration, time, velocity) {\n\t time = this.toSeconds(time);\n\t duration = this.toSeconds(duration);\n\t this.triggerAttack(time, velocity);\n\t this.triggerRelease(time + duration);\n\t return this;\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.NoiseSynth} this\n\t\t */\n\t Tone.NoiseSynth.prototype.dispose = function () {\n\t Tone.Instrument.prototype.dispose.call(this);\n\t this._writable([\n\t 'noise',\n\t 'envelope'\n\t ]);\n\t this.noise.dispose();\n\t this.noise = null;\n\t this.envelope.dispose();\n\t this.envelope = null;\n\t return this;\n\t };\n\t return Tone.NoiseSynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Karplus-String string synthesis. Often out of tune. \n\t\t * Will change when the AudioWorkerNode is available across\n\t\t * browsers. \n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Instrument}\n\t\t * @param {Object} [options] see the defaults\n\t\t * @example\n\t\t * var plucky = new Tone.PluckSynth().toMaster();\n\t\t * plucky.triggerAttack(\"C4\");\n\t\t */\n\t Tone.PluckSynth = function (options) {\n\t options = this.defaultArg(options, Tone.PluckSynth.defaults);\n\t Tone.Instrument.call(this, options);\n\t /**\n\t\t\t * @type {Tone.Noise}\n\t\t\t * @private\n\t\t\t */\n\t this._noise = new Tone.Noise('pink');\n\t /**\n\t\t\t * The amount of noise at the attack. \n\t\t\t * Nominal range of [0.1, 20]\n\t\t\t * @type {number}\n\t\t\t */\n\t this.attackNoise = options.attackNoise;\n\t /**\n\t\t\t * the LFCF\n\t\t\t * @type {Tone.LowpassCombFilter}\n\t\t\t * @private\n\t\t\t */\n\t this._lfcf = new Tone.LowpassCombFilter({\n\t 'resonance': options.resonance,\n\t 'dampening': options.dampening\n\t });\n\t /**\n\t\t\t * The resonance control. \n\t\t\t * @type {NormalRange}\n\t\t\t * @signal\n\t\t\t */\n\t this.resonance = this._lfcf.resonance;\n\t /**\n\t\t\t * The dampening control. i.e. the lowpass filter frequency of the comb filter\n\t\t\t * @type {Frequency}\n\t\t\t * @signal\n\t\t\t */\n\t this.dampening = this._lfcf.dampening;\n\t //connections\n\t this._noise.connect(this._lfcf);\n\t this._lfcf.connect(this.output);\n\t this._readOnly([\n\t 'resonance',\n\t 'dampening'\n\t ]);\n\t };\n\t Tone.extend(Tone.PluckSynth, Tone.Instrument);\n\t /**\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.PluckSynth.defaults = {\n\t 'attackNoise': 1,\n\t 'dampening': 4000,\n\t 'resonance': 0.9\n\t };\n\t /**\n\t\t * Trigger the note. \n\t\t * @param {Frequency} note The note to trigger.\n\t\t * @param {Time} [time=now] When the note should be triggered.\n\t\t * @returns {Tone.PluckSynth} this\n\t\t */\n\t Tone.PluckSynth.prototype.triggerAttack = function (note, time) {\n\t note = this.toFrequency(note);\n\t time = this.toSeconds(time);\n\t var delayAmount = 1 / note;\n\t this._lfcf.delayTime.setValueAtTime(delayAmount, time);\n\t this._noise.start(time);\n\t this._noise.stop(time + delayAmount * this.attackNoise);\n\t return this;\n\t };\n\t /**\n\t\t * Clean up. \n\t\t * @returns {Tone.PluckSynth} this\n\t\t */\n\t Tone.PluckSynth.prototype.dispose = function () {\n\t Tone.Instrument.prototype.dispose.call(this);\n\t this._noise.dispose();\n\t this._lfcf.dispose();\n\t this._noise = null;\n\t this._lfcf = null;\n\t this._writable([\n\t 'resonance',\n\t 'dampening'\n\t ]);\n\t this.dampening = null;\n\t this.resonance = null;\n\t return this;\n\t };\n\t return Tone.PluckSynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.PolySynth handles voice creation and allocation for any\n\t\t * instruments passed in as the second paramter. PolySynth is \n\t\t * not a synthesizer by itself, it merely manages voices of \n\t\t * one of the other types of synths, allowing any of the \n\t\t * monophonic synthesizers to be polyphonic. \n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Instrument}\n\t\t * @param {number|Object} [polyphony=4] The number of voices to create\n\t\t * @param {function} [voice=Tone.Synth] The constructor of the voices\n\t\t * uses Tone.Synth by default. \n\t\t * @example\n\t\t * //a polysynth composed of 6 Voices of Synth\n\t\t * var synth = new Tone.PolySynth(6, Tone.Synth).toMaster();\n\t\t * //set the attributes using the set interface\n\t\t * synth.set(\"detune\", -1200);\n\t\t * //play a chord\n\t\t * synth.triggerAttackRelease([\"C4\", \"E4\", \"A4\"], \"4n\");\n\t\t */\n\t Tone.PolySynth = function () {\n\t Tone.Instrument.call(this);\n\t var options = this.optionsObject(arguments, [\n\t 'polyphony',\n\t 'voice'\n\t ], Tone.PolySynth.defaults);\n\t options = this.defaultArg(options, Tone.Instrument.defaults);\n\t //max polyphony\n\t options.polyphony = Math.min(Tone.PolySynth.MAX_POLYPHONY, options.polyphony);\n\t /**\n\t\t\t * the array of voices\n\t\t\t * @type {Array}\n\t\t\t */\n\t this.voices = new Array(options.polyphony);\n\t /**\n\t\t\t * The queue of voices with data about last trigger\n\t\t\t * and the triggered note\n\t\t\t * @private\n\t\t\t * @type {Array}\n\t\t\t */\n\t this._triggers = new Array(options.polyphony);\n\t /**\n\t\t\t * The detune in cents\n\t\t\t * @type {Cents}\n\t\t\t * @signal\n\t\t\t */\n\t this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);\n\t this._readOnly('detune');\n\t //create the voices\n\t for (var i = 0; i < options.polyphony; i++) {\n\t var v = new options.voice(arguments[2], arguments[3]);\n\t this.voices[i] = v;\n\t v.connect(this.output);\n\t if (v.hasOwnProperty('detune')) {\n\t this.detune.connect(v.detune);\n\t }\n\t this._triggers[i] = {\n\t release: -1,\n\t note: null,\n\t voice: v\n\t };\n\t }\n\t //set the volume initially\n\t this.volume.value = options.volume;\n\t };\n\t Tone.extend(Tone.PolySynth, Tone.Instrument);\n\t /**\n\t\t * the defaults\n\t\t * @const\n\t\t * @static\n\t\t * @type {Object}\n\t\t */\n\t Tone.PolySynth.defaults = {\n\t 'polyphony': 4,\n\t 'volume': 0,\n\t 'detune': 0,\n\t 'voice': Tone.Synth\n\t };\n\t /**\n\t\t * Trigger the attack portion of the note\n\t\t * @param {Frequency|Array} notes The notes to play. Accepts a single\n\t\t * Frequency or an array of frequencies.\n\t\t * @param {Time} [time=now] The start time of the note.\n\t\t * @param {number} [velocity=1] The velocity of the note.\n\t\t * @returns {Tone.PolySynth} this\n\t\t * @example\n\t\t * //trigger a chord immediately with a velocity of 0.2\n\t\t * poly.triggerAttack([\"Ab3\", \"C4\", \"F5\"], undefined, 0.2);\n\t\t */\n\t Tone.PolySynth.prototype.triggerAttack = function (notes, time, velocity) {\n\t if (!Array.isArray(notes)) {\n\t notes = [notes];\n\t }\n\t time = this.toSeconds(time);\n\t for (var i = 0; i < notes.length; i++) {\n\t var val = notes[i];\n\t //trigger the oldest voice\n\t var oldest = this._triggers[0];\n\t var oldestIndex = 0;\n\t for (var j = 1; j < this._triggers.length; j++) {\n\t if (this._triggers[j].release < oldest.release) {\n\t oldest = this._triggers[j];\n\t oldestIndex = j;\n\t }\n\t }\n\t oldest.release = Infinity;\n\t oldest.note = JSON.stringify(val);\n\t oldest.voice.triggerAttack(val, time, velocity);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the attack and release after the specified duration\n\t\t * \n\t\t * @param {Frequency|Array} notes The notes to play. Accepts a single\n\t\t * Frequency or an array of frequencies.\n\t\t * @param {Time} duration the duration of the note\n\t\t * @param {Time} [time=now] if no time is given, defaults to now\n\t\t * @param {number} [velocity=1] the velocity of the attack (0-1)\n\t\t * @returns {Tone.PolySynth} this\n\t\t * @example\n\t\t * //trigger a chord for a duration of a half note \n\t\t * poly.triggerAttackRelease([\"Eb3\", \"G4\", \"C5\"], \"2n\");\n\t\t * @example\n\t\t * //can pass in an array of durations as well\n\t\t * poly.triggerAttackRelease([\"Eb3\", \"G4\", \"C5\"], [\"2n\", \"4n\", \"4n\"]);\n\t\t */\n\t Tone.PolySynth.prototype.triggerAttackRelease = function (notes, duration, time, velocity) {\n\t time = this.toSeconds(time);\n\t this.triggerAttack(notes, time, velocity);\n\t if (this.isArray(duration) && this.isArray(notes)) {\n\t for (var i = 0; i < notes.length; i++) {\n\t var d = duration[Math.min(i, duration.length - 1)];\n\t this.triggerRelease(notes[i], time + this.toSeconds(d));\n\t }\n\t } else {\n\t this.triggerRelease(notes, time + this.toSeconds(duration));\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the release of the note. Unlike monophonic instruments, \n\t\t * a note (or array of notes) needs to be passed in as the first argument.\n\t\t * @param {Frequency|Array} notes The notes to play. Accepts a single\n\t\t * Frequency or an array of frequencies.\n\t\t * @param {Time} [time=now] When the release will be triggered. \n\t\t * @returns {Tone.PolySynth} this\n\t\t * @example\n\t\t * poly.triggerRelease([\"Ab3\", \"C4\", \"F5\"], \"+2n\");\n\t\t */\n\t Tone.PolySynth.prototype.triggerRelease = function (notes, time) {\n\t if (!Array.isArray(notes)) {\n\t notes = [notes];\n\t }\n\t time = this.toSeconds(time);\n\t for (var i = 0; i < notes.length; i++) {\n\t //get the voice\n\t var stringified = JSON.stringify(notes[i]);\n\t for (var v = 0; v < this._triggers.length; v++) {\n\t var desc = this._triggers[v];\n\t if (desc.note === stringified && desc.release > time) {\n\t desc.voice.triggerRelease(time);\n\t desc.release = time;\n\t }\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Set a member/attribute of the voices. \n\t\t * @param {Object|string} params\n\t\t * @param {number=} value\n\t\t * @param {Time=} rampTime\n\t\t * @returns {Tone.PolySynth} this\n\t\t * @example\n\t\t * poly.set({\n\t\t * \t\"filter\" : {\n\t\t * \t\t\"type\" : \"highpass\"\n\t\t * \t},\n\t\t * \t\"envelope\" : {\n\t\t * \t\t\"attack\" : 0.25\n\t\t * \t}\n\t\t * });\n\t\t */\n\t Tone.PolySynth.prototype.set = function (params, value, rampTime) {\n\t for (var i = 0; i < this.voices.length; i++) {\n\t this.voices[i].set(params, value, rampTime);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Get the synth's attributes. Given no arguments get\n\t\t * will return all available object properties and their corresponding\n\t\t * values. Pass in a single attribute to retrieve or an array\n\t\t * of attributes. The attribute strings can also include a \".\"\n\t\t * to access deeper properties.\n\t\t * @param {Array=} params the parameters to get, otherwise will return \n\t\t * \t\t\t\t\t all available.\n\t\t */\n\t Tone.PolySynth.prototype.get = function (params) {\n\t return this.voices[0].get(params);\n\t };\n\t /**\n\t\t * Trigger the release portion of all the currently active voices.\n\t\t * @param {Time} [time=now] When the notes should be released.\n\t\t * @return {Tone.PolySynth} this\n\t\t */\n\t Tone.PolySynth.prototype.releaseAll = function (time) {\n\t time = this.toSeconds(time);\n\t for (var i = 0; i < this._triggers.length; i++) {\n\t var desc = this._triggers[i];\n\t if (desc.release > time) {\n\t desc.release = time;\n\t desc.voice.triggerRelease(time);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.PolySynth} this\n\t\t */\n\t Tone.PolySynth.prototype.dispose = function () {\n\t Tone.Instrument.prototype.dispose.call(this);\n\t for (var i = 0; i < this.voices.length; i++) {\n\t this.voices[i].dispose();\n\t this.voices[i] = null;\n\t }\n\t this._writable('detune');\n\t this.detune.dispose();\n\t this.detune = null;\n\t this.voices = null;\n\t this._triggers = null;\n\t return this;\n\t };\n\t /**\n\t\t * The maximum number of notes that can be allocated \n\t\t * to a polysynth. \n\t\t * @type {Number}\n\t\t * @static\n\t\t */\n\t Tone.PolySynth.MAX_POLYPHONY = 20;\n\t return Tone.PolySynth;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.Player is an audio file player with start, loop, and stop functions.\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone.Source} \n\t\t * @param {string|AudioBuffer} url Either the AudioBuffer or the url from\n\t\t * which to load the AudioBuffer\n\t\t * @param {function=} onload The function to invoke when the buffer is loaded. \n\t\t * Recommended to use Tone.Buffer.on('load') instead.\n\t\t * @example\n\t\t * var player = new Tone.Player(\"./path/to/sample.mp3\").toMaster();\n\t\t * //play as soon as the buffer is loaded\n\t\t * player.autostart = true;\n\t\t */\n\t Tone.Player = function (url) {\n\t var options;\n\t if (url instanceof Tone.Buffer) {\n\t url = url.get();\n\t options = Tone.Player.defaults;\n\t } else {\n\t options = this.optionsObject(arguments, [\n\t 'url',\n\t 'onload'\n\t ], Tone.Player.defaults);\n\t }\n\t Tone.Source.call(this, options);\n\t /**\n\t\t\t * @private\n\t\t\t * @type {AudioBufferSourceNode}\n\t\t\t */\n\t this._source = null;\n\t /**\n\t\t\t * If the file should play as soon\n\t\t\t * as the buffer is loaded. \n\t\t\t * @type {boolean}\n\t\t\t * @example\n\t\t\t * //will play as soon as it's loaded\n\t\t\t * var player = new Tone.Player({\n\t\t\t * \t\"url\" : \"./path/to/sample.mp3\",\n\t\t\t * \t\"autostart\" : true,\n\t\t\t * }).toMaster();\n\t\t\t */\n\t this.autostart = options.autostart;\n\t /**\n\t\t\t * the buffer\n\t\t\t * @private\n\t\t\t * @type {Tone.Buffer}\n\t\t\t */\n\t this._buffer = new Tone.Buffer({\n\t 'url': options.url,\n\t 'onload': this._onload.bind(this, options.onload),\n\t 'reverse': options.reverse\n\t });\n\t if (url instanceof AudioBuffer) {\n\t this._buffer.set(url);\n\t }\n\t /**\n\t\t\t * if the buffer should loop once it's over\n\t\t\t * @type {boolean}\n\t\t\t * @private\n\t\t\t */\n\t this._loop = options.loop;\n\t /**\n\t\t\t * if 'loop' is true, the loop will start at this position\n\t\t\t * @type {Time}\n\t\t\t * @private\n\t\t\t */\n\t this._loopStart = options.loopStart;\n\t /**\n\t\t\t * if 'loop' is true, the loop will end at this position\n\t\t\t * @type {Time}\n\t\t\t * @private\n\t\t\t */\n\t this._loopEnd = options.loopEnd;\n\t /**\n\t\t\t * the playback rate\n\t\t\t * @private\n\t\t\t * @type {number}\n\t\t\t */\n\t this._playbackRate = options.playbackRate;\n\t /**\n\t\t\t * Enabling retrigger will allow a player to be restarted\n\t\t\t * before the the previous 'start' is done playing. Otherwise, \n\t\t\t * successive calls to Tone.Player.start will only start\n\t\t\t * the sample if it had played all the way through. \n\t\t\t * @type {boolean}\n\t\t\t */\n\t this.retrigger = options.retrigger;\n\t };\n\t Tone.extend(Tone.Player, Tone.Source);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.Player.defaults = {\n\t 'onload': Tone.noOp,\n\t 'playbackRate': 1,\n\t 'loop': false,\n\t 'autostart': false,\n\t 'loopStart': 0,\n\t 'loopEnd': 0,\n\t 'retrigger': false,\n\t 'reverse': false\n\t };\n\t /**\n\t\t * Load the audio file as an audio buffer.\n\t\t * Decodes the audio asynchronously and invokes\n\t\t * the callback once the audio buffer loads. \n\t\t * Note: this does not need to be called if a url\n\t\t * was passed in to the constructor. Only use this\n\t\t * if you want to manually load a new url. \n\t\t * @param {string} url The url of the buffer to load.\n\t\t * Filetype support depends on the\n\t\t * browser.\n\t\t * @param {function=} callback The function to invoke once\n\t\t * the sample is loaded.\n\t\t * @returns {Promise}\n\t\t */\n\t Tone.Player.prototype.load = function (url, callback) {\n\t return this._buffer.load(url, this._onload.bind(this, callback));\n\t };\n\t /**\n\t\t * Internal callback when the buffer is loaded.\n\t\t * @private\n\t\t */\n\t Tone.Player.prototype._onload = function (callback) {\n\t callback = this.defaultArg(callback, Tone.noOp);\n\t callback(this);\n\t if (this.autostart) {\n\t this.start();\n\t }\n\t };\n\t /**\n\t\t * Play the buffer at the given startTime. Optionally add an offset\n\t\t * and/or duration which will play the buffer from a position\n\t\t * within the buffer for the given duration. \n\t\t * \n\t\t * @param {Time} [startTime=now] When the player should start.\n\t\t * @param {Time} [offset=0] The offset from the beginning of the sample\n\t\t * to start at. \n\t\t * @param {Time=} duration How long the sample should play. If no duration\n\t\t * is given, it will default to the full length \n\t\t * of the sample (minus any offset)\n\t\t * @returns {Tone.Player} this\n\t\t * @memberOf Tone.Player#\n\t\t * @method start\n\t\t * @name start\n\t\t */\n\t /**\n\t\t * Internal start method\n\t\t * @private\n\t\t */\n\t Tone.Player.prototype._start = function (startTime, offset, duration) {\n\t if (this._buffer.loaded) {\n\t //if it's a loop the default offset is the loopstart point\n\t if (this._loop) {\n\t offset = this.defaultArg(offset, this._loopStart);\n\t } else {\n\t //otherwise the default offset is 0\n\t offset = this.defaultArg(offset, 0);\n\t }\n\t offset = this.toSeconds(offset);\n\t //make sure it has a positive duration\n\t duration = this.defaultArg(duration, Math.max(this._buffer.duration - offset, 0));\n\t duration = this.toSeconds(duration);\n\t //the values in seconds\n\t startTime = this.toSeconds(startTime);\n\t //make the source\n\t this._source = this.context.createBufferSource();\n\t this._source.buffer = this._buffer.get();\n\t //set the looping properties\n\t if (this._loop) {\n\t this._source.loop = this._loop;\n\t this._source.loopStart = this.toSeconds(this._loopStart);\n\t this._source.loopEnd = this.toSeconds(this._loopEnd);\n\t } else if (!this._synced) {\n\t //if it's not looping, set the state change at the end of the sample\n\t this._state.setStateAtTime(Tone.State.Stopped, startTime + duration);\n\t }\n\t //and other properties\n\t this._source.playbackRate.value = this._playbackRate;\n\t this._source.connect(this.output);\n\t //start it\n\t if (this._loop) {\n\t //modify the offset if it's greater than the loop time\n\t var loopEnd = this._source.loopEnd || this._buffer.duration;\n\t var loopStart = this._source.loopStart;\n\t var loopDuration = loopEnd - loopStart;\n\t if (offset > loopEnd) {\n\t //move the offset back\n\t while (offset > loopEnd) {\n\t offset -= loopDuration;\n\t }\n\t }\n\t this._source.start(startTime, offset);\n\t } else {\n\t this._source.start(startTime, offset, duration);\n\t }\n\t } else {\n\t throw Error('Tone.Player: tried to start Player before the buffer was loaded');\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Stop playback.\n\t\t * @private\n\t\t * @param {Time} [time=now]\n\t\t * @returns {Tone.Player} this\n\t\t */\n\t Tone.Player.prototype._stop = function (time) {\n\t if (this._source) {\n\t this._source.stop(this.toSeconds(time));\n\t this._source = null;\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Seek to a specific time in the player's buffer. If the \n\t\t * source is no longer playing at that time, it will stop.\n\t\t * If you seek to a time that \n\t\t * @param {Time} offset The time to seek to.\n\t\t * @param {Time=} time The time for the seek event to occur.\n\t\t * @return {Tone.Player} this\n\t\t * @example\n\t\t * source.start(0.2);\n\t\t * source.stop(0.4);\n\t\t */\n\t Tone.Player.prototype.seek = function (offset, time) {\n\t time = this.toSeconds(time);\n\t if (this._state.getValueAtTime(time) === Tone.State.Started) {\n\t offset = this.toSeconds(offset);\n\t // if it's currently playing, stop it\n\t this._stop(time);\n\t //restart it at the given time\n\t this._start(time, offset);\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Set the loop start and end. Will only loop if loop is \n\t\t * set to true. \n\t\t * @param {Time} loopStart The loop end time\n\t\t * @param {Time} loopEnd The loop end time\n\t\t * @returns {Tone.Player} this\n\t\t * @example\n\t\t * //loop 0.1 seconds of the file. \n\t\t * player.setLoopPoints(0.2, 0.3);\n\t\t * player.loop = true;\n\t\t */\n\t Tone.Player.prototype.setLoopPoints = function (loopStart, loopEnd) {\n\t this.loopStart = loopStart;\n\t this.loopEnd = loopEnd;\n\t return this;\n\t };\n\t /**\n\t\t * If loop is true, the loop will start at this position. \n\t\t * @memberOf Tone.Player#\n\t\t * @type {Time}\n\t\t * @name loopStart\n\t\t */\n\t Object.defineProperty(Tone.Player.prototype, 'loopStart', {\n\t get: function () {\n\t return this._loopStart;\n\t },\n\t set: function (loopStart) {\n\t this._loopStart = loopStart;\n\t if (this._source) {\n\t this._source.loopStart = this.toSeconds(loopStart);\n\t }\n\t }\n\t });\n\t /**\n\t\t * If loop is true, the loop will end at this position.\n\t\t * @memberOf Tone.Player#\n\t\t * @type {Time}\n\t\t * @name loopEnd\n\t\t */\n\t Object.defineProperty(Tone.Player.prototype, 'loopEnd', {\n\t get: function () {\n\t return this._loopEnd;\n\t },\n\t set: function (loopEnd) {\n\t this._loopEnd = loopEnd;\n\t if (this._source) {\n\t this._source.loopEnd = this.toSeconds(loopEnd);\n\t }\n\t }\n\t });\n\t /**\n\t\t * The audio buffer belonging to the player. \n\t\t * @memberOf Tone.Player#\n\t\t * @type {Tone.Buffer}\n\t\t * @name buffer\n\t\t */\n\t Object.defineProperty(Tone.Player.prototype, 'buffer', {\n\t get: function () {\n\t return this._buffer;\n\t },\n\t set: function (buffer) {\n\t this._buffer.set(buffer);\n\t }\n\t });\n\t /**\n\t\t * If the buffer should loop once it's over. \n\t\t * @memberOf Tone.Player#\n\t\t * @type {boolean}\n\t\t * @name loop\n\t\t */\n\t Object.defineProperty(Tone.Player.prototype, 'loop', {\n\t get: function () {\n\t return this._loop;\n\t },\n\t set: function (loop) {\n\t this._loop = loop;\n\t if (this._source) {\n\t this._source.loop = loop;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The playback speed. 1 is normal speed. This is not a signal because\n\t\t * Safari and iOS currently don't support playbackRate as a signal.\n\t\t * @memberOf Tone.Player#\n\t\t * @type {number}\n\t\t * @name playbackRate\n\t\t */\n\t Object.defineProperty(Tone.Player.prototype, 'playbackRate', {\n\t get: function () {\n\t return this._playbackRate;\n\t },\n\t set: function (rate) {\n\t this._playbackRate = rate;\n\t if (this._source) {\n\t this._source.playbackRate.value = rate;\n\t }\n\t }\n\t });\n\t /**\n\t\t * The direction the buffer should play in\n\t\t * @memberOf Tone.Player#\n\t\t * @type {boolean}\n\t\t * @name reverse\n\t\t */\n\t Object.defineProperty(Tone.Player.prototype, 'reverse', {\n\t get: function () {\n\t return this._buffer.reverse;\n\t },\n\t set: function (rev) {\n\t this._buffer.reverse = rev;\n\t }\n\t });\n\t /**\n\t\t * Dispose and disconnect.\n\t\t * @return {Tone.Player} this\n\t\t */\n\t Tone.Player.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t if (this._source !== null) {\n\t this._source.disconnect();\n\t this._source = null;\n\t }\n\t this._buffer.dispose();\n\t this._buffer = null;\n\t return this;\n\t };\n\t return Tone.Player;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Sampler wraps Tone.Player in an AmplitudeEnvelope.\n\t\t *\n\t\t * @constructor\n\t\t * @extends {Tone.Instrument}\n\t\t * @param {String} url the url of the audio file\n\t\t * @param {Function=} onload The callback to invoke when the sample is loaded.\n\t\t * @example\n\t\t * var sampler = new Sampler(\"./audio/casio/A1.mp3\", function(){\n\t\t * \t//repitch the sample down a half step\n\t\t * \tsampler.triggerAttack(-1);\n\t\t * }).toMaster();\n\t\t */\n\t Tone.Sampler = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'url',\n\t 'onload'\n\t ], Tone.Sampler.defaults);\n\t Tone.Instrument.call(this, options);\n\t /**\n\t\t\t * The sample player.\n\t\t\t * @type {Tone.Player}\n\t\t\t */\n\t this.player = new Tone.Player(options.url, options.onload);\n\t this.player.retrigger = true;\n\t /**\n\t\t\t * The amplitude envelope. \n\t\t\t * @type {Tone.AmplitudeEnvelope}\n\t\t\t */\n\t this.envelope = new Tone.AmplitudeEnvelope(options.envelope);\n\t this.player.chain(this.envelope, this.output);\n\t this._readOnly([\n\t 'player',\n\t 'envelope'\n\t ]);\n\t this.loop = options.loop;\n\t this.reverse = options.reverse;\n\t };\n\t Tone.extend(Tone.Sampler, Tone.Instrument);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t */\n\t Tone.Sampler.defaults = {\n\t 'onload': Tone.noOp,\n\t 'loop': false,\n\t 'reverse': false,\n\t 'envelope': {\n\t 'attack': 0.001,\n\t 'decay': 0,\n\t 'sustain': 1,\n\t 'release': 0.1\n\t }\n\t };\n\t /**\n\t\t * Trigger the start of the sample. \n\t\t * @param {Interval} [pitch=0] The amount the sample should\n\t\t * be repitched. \n\t\t * @param {Time} [time=now] The time when the sample should start\n\t\t * @param {NormalRange} [velocity=1] The velocity of the note\n\t\t * @returns {Tone.Sampler} this\n\t\t * @example\n\t\t * sampler.triggerAttack(0, \"+0.1\", 0.5);\n\t\t */\n\t Tone.Sampler.prototype.triggerAttack = function (pitch, time, velocity) {\n\t time = this.toSeconds(time);\n\t pitch = this.defaultArg(pitch, 0);\n\t this.player.playbackRate = this.intervalToFrequencyRatio(pitch);\n\t this.player.start(time);\n\t this.envelope.triggerAttack(time, velocity);\n\t return this;\n\t };\n\t /**\n\t\t * Start the release portion of the sample. Will stop the sample once the \n\t\t * envelope has fully released. \n\t\t * \n\t\t * @param {Time} [time=now] The time when the note should release\n\t\t * @returns {Tone.Sampler} this\n\t\t * @example\n\t\t * sampler.triggerRelease();\n\t\t */\n\t Tone.Sampler.prototype.triggerRelease = function (time) {\n\t time = this.toSeconds(time);\n\t this.envelope.triggerRelease(time);\n\t this.player.stop(this.toSeconds(this.envelope.release) + time);\n\t return this;\n\t };\n\t /**\n\t\t * Trigger the attack and then the release after the duration. \n\t\t * @param {Interval} interval The interval in half-steps that the\n\t\t * sample should be pitch shifted.\n\t\t * @param {Time} duration How long the note should be held for before\n\t\t * triggering the release.\n\t\t * @param {Time} [time=now] When the note should be triggered.\n\t\t * @param {NormalRange} [velocity=1] The velocity the note should be triggered at.\n\t\t * @returns {Tone.Sampler} this\n\t\t * @example\n\t\t * //trigger the unpitched note for the duration of an 8th note\n\t\t * synth.triggerAttackRelease(0, \"8n\");\n\t\t * @memberOf Tone.Sampler#\n\t\t * @name triggerAttackRelease\n\t\t * @method triggerAttackRelease\n\t\t */\n\t /**\n\t\t * If the output sample should loop or not.\n\t\t * @memberOf Tone.Sampler#\n\t\t * @type {number|string}\n\t\t * @name loop\n\t\t */\n\t Object.defineProperty(Tone.Sampler.prototype, 'loop', {\n\t get: function () {\n\t return this.player.loop;\n\t },\n\t set: function (loop) {\n\t this.player.loop = loop;\n\t }\n\t });\n\t /**\n\t\t * The direction the buffer should play in\n\t\t * @memberOf Tone.Sampler#\n\t\t * @type {boolean}\n\t\t * @name reverse\n\t\t */\n\t Object.defineProperty(Tone.Sampler.prototype, 'reverse', {\n\t get: function () {\n\t return this.player.reverse;\n\t },\n\t set: function (rev) {\n\t this.player.reverse = rev;\n\t }\n\t });\n\t /**\n\t\t * The buffer to play.\n\t\t * @memberOf Tone.Sampler#\n\t\t * @type {Tone.Buffer}\n\t\t * @name buffer\n\t\t */\n\t Object.defineProperty(Tone.Sampler.prototype, 'buffer', {\n\t get: function () {\n\t return this.player.buffer;\n\t },\n\t set: function (buff) {\n\t this.player.buffer = buff;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @returns {Tone.Sampler} this\n\t\t */\n\t Tone.Sampler.prototype.dispose = function () {\n\t Tone.Instrument.prototype.dispose.call(this);\n\t this._writable([\n\t 'player',\n\t 'envelope'\n\t ]);\n\t this.player.dispose();\n\t this.player = null;\n\t this.envelope.dispose();\n\t this.envelope = null;\n\t return this;\n\t };\n\t return Tone.Sampler;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Maps a NormalRange [0, 1] to an AudioRange [-1, 1]. \n\t\t * See also Tone.AudioToGain. \n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @example\n\t\t * var g2a = new Tone.GainToAudio();\n\t\t */\n\t Tone.GainToAudio = function () {\n\t /**\n\t\t\t * @type {WaveShaperNode}\n\t\t\t * @private\n\t\t\t */\n\t this._norm = this.input = this.output = new Tone.WaveShaper(function (x) {\n\t return Math.abs(x) * 2 - 1;\n\t });\n\t };\n\t Tone.extend(Tone.GainToAudio, Tone.SignalBase);\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.GainToAudio} this\n\t\t */\n\t Tone.GainToAudio.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._norm.dispose();\n\t this._norm = null;\n\t return this;\n\t };\n\t return Tone.GainToAudio;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Normalize takes an input min and max and maps it linearly to NormalRange [0,1]\n\t\t *\n\t\t * @extends {Tone.SignalBase}\n\t\t * @constructor\n\t\t * @param {number} inputMin the min input value\n\t\t * @param {number} inputMax the max input value\n\t\t * @example\n\t\t * var norm = new Tone.Normalize(2, 4);\n\t\t * var sig = new Tone.Signal(3).connect(norm);\n\t\t * //output of norm is 0.5. \n\t\t */\n\t Tone.Normalize = function (inputMin, inputMax) {\n\t /**\n\t\t\t * the min input value\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._inputMin = this.defaultArg(inputMin, 0);\n\t /**\n\t\t\t * the max input value\n\t\t\t * @type {number}\n\t\t\t * @private\n\t\t\t */\n\t this._inputMax = this.defaultArg(inputMax, 1);\n\t /**\n\t\t\t * subtract the min from the input\n\t\t\t * @type {Tone.Add}\n\t\t\t * @private\n\t\t\t */\n\t this._sub = this.input = new Tone.Add(0);\n\t /**\n\t\t\t * divide by the difference between the input and output\n\t\t\t * @type {Tone.Multiply}\n\t\t\t * @private\n\t\t\t */\n\t this._div = this.output = new Tone.Multiply(1);\n\t this._sub.connect(this._div);\n\t this._setRange();\n\t };\n\t Tone.extend(Tone.Normalize, Tone.SignalBase);\n\t /**\n\t\t * The minimum value the input signal will reach.\n\t\t * @memberOf Tone.Normalize#\n\t\t * @type {number}\n\t\t * @name min\n\t\t */\n\t Object.defineProperty(Tone.Normalize.prototype, 'min', {\n\t get: function () {\n\t return this._inputMin;\n\t },\n\t set: function (min) {\n\t this._inputMin = min;\n\t this._setRange();\n\t }\n\t });\n\t /**\n\t\t * The maximum value the input signal will reach.\n\t\t * @memberOf Tone.Normalize#\n\t\t * @type {number}\n\t\t * @name max\n\t\t */\n\t Object.defineProperty(Tone.Normalize.prototype, 'max', {\n\t get: function () {\n\t return this._inputMax;\n\t },\n\t set: function (max) {\n\t this._inputMax = max;\n\t this._setRange();\n\t }\n\t });\n\t /**\n\t\t * set the values\n\t\t * @private\n\t\t */\n\t Tone.Normalize.prototype._setRange = function () {\n\t this._sub.value = -this._inputMin;\n\t this._div.value = 1 / (this._inputMax - this._inputMin);\n\t };\n\t /**\n\t\t * clean up\n\t\t * @returns {Tone.Normalize} this\n\t\t */\n\t Tone.Normalize.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._sub.dispose();\n\t this._sub = null;\n\t this._div.dispose();\n\t this._div = null;\n\t return this;\n\t };\n\t return Tone.Normalize;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.MultiPlayer is well suited for one-shots, multi-sampled instruments\n\t\t * or any time you need to play a bunch of audio buffers. \n\t\t * @param {Object|Array|Tone.Buffers} buffers The buffers which are available\n\t\t * to the MultiPlayer\n\t\t * @param {Function} onload The callback to invoke when all of the buffers are loaded.\n\t\t * @extends {Tone}\n\t\t * @example\n\t\t * var multiPlayer = new MultiPlayer({\n\t\t * \t\"kick\" : \"path/to/kick.mp3\",\n\t\t * \t\"snare\" : \"path/to/snare.mp3\",\n\t\t * }, function(){\n\t\t * \tmultiPlayer.start(\"kick\");\n\t\t * });\n\t\t * @example\n\t\t * //can also store the values in an array\n\t\t * var multiPlayer = new MultiPlayer([\"path/to/kick.mp3\", \"path/to/snare.mp3\"], \n\t\t * function(){\n\t\t * \t//if an array is passed in, the samples are referenced to by index\n\t\t * \tmultiPlayer.start(1);\n\t\t * });\n\t\t */\n\t Tone.MultiPlayer = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'urls',\n\t 'onload'\n\t ], Tone.MultiPlayer.defaults);\n\t if (options.urls instanceof Tone.Buffers) {\n\t /**\n\t\t\t\t * All the buffers belonging to the player.\n\t\t\t\t * @type {Tone.Buffers}\n\t\t\t\t */\n\t this.buffers = options.urls;\n\t } else {\n\t this.buffers = new Tone.Buffers(options.urls, options.onload);\n\t }\n\t /**\n\t\t\t * Keeps track of the currently playing sources.\n\t\t\t * @type {Object}\n\t\t\t * @private\n\t\t\t */\n\t this._activeSources = {};\n\t /**\n\t\t\t * The fade in envelope which is applied\n\t\t\t * to the beginning of the BufferSource\n\t\t\t * @type {Time}\n\t\t\t */\n\t this.fadeIn = options.fadeIn;\n\t /**\n\t\t\t * The fade out envelope which is applied\n\t\t\t * to the end of the BufferSource\n\t\t\t * @type {Time}\n\t\t\t */\n\t this.fadeOut = options.fadeOut;\n\t /**\n\t\t\t * The output volume node\n\t\t\t * @type {Tone.Volume}\n\t\t\t * @private\n\t\t\t */\n\t this._volume = this.output = new Tone.Volume(options.volume);\n\t /**\n\t\t\t * The volume of the output in decibels.\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * source.volume.value = -6;\n\t\t\t */\n\t this.volume = this._volume.volume;\n\t this._readOnly('volume');\n\t //make the output explicitly stereo\n\t this._volume.output.output.channelCount = 2;\n\t this._volume.output.output.channelCountMode = 'explicit';\n\t //mute initially\n\t this.mute = options.mute;\n\t };\n\t Tone.extend(Tone.MultiPlayer, Tone.Source);\n\t /**\n\t\t * The defaults\n\t\t * @type {Object}\n\t\t */\n\t Tone.MultiPlayer.defaults = {\n\t 'onload': Tone.noOp,\n\t 'fadeIn': 0,\n\t 'fadeOut': 0\n\t };\n\t /**\n\t\t * Make the source from the buffername\n\t\t * @param {String} bufferName\n\t\t * @return {Tone.BufferSource}\n\t\t * @private\n\t\t */\n\t Tone.MultiPlayer.prototype._makeSource = function (bufferName) {\n\t var buffer;\n\t if (this.isString(bufferName) || this.isNumber(bufferName)) {\n\t buffer = this.buffers.get(bufferName).get();\n\t } else if (bufferName instanceof Tone.Buffer) {\n\t buffer = bufferName.get();\n\t } else if (bufferName instanceof AudioBuffer) {\n\t buffer = bufferName;\n\t }\n\t var source = new Tone.BufferSource(buffer).connect(this.output);\n\t if (!this._activeSources.hasOwnProperty(bufferName)) {\n\t this._activeSources[bufferName] = [];\n\t }\n\t this._activeSources[bufferName].push(source);\n\t return source;\n\t };\n\t /**\n\t\t * Start a buffer by name. The `start` method allows a number of options\n\t\t * to be passed in such as offset, interval, and gain. This is good for multi-sampled \n\t\t * instruments and sound sprites where samples are repitched played back at different velocities.\n\t\t * @param {String} bufferName The name of the buffer to start.\n\t\t * @param {Time} time When to start the buffer.\n\t\t * @param {Time} [offset=0] The offset into the buffer to play from.\n\t\t * @param {Time=} duration How long to play the buffer for.\n\t\t * @param {Interval} [pitch=0] The interval to repitch the buffer.\n\t\t * @param {Gain} [gain=1] The gain to play the sample at.\n\t\t * @return {Tone.MultiPlayer} this\n\t\t */\n\t Tone.MultiPlayer.prototype.start = function (bufferName, time, offset, duration, pitch, gain) {\n\t time = this.toSeconds(time);\n\t var source = this._makeSource(bufferName);\n\t source.start(time, offset, duration, this.defaultArg(gain, 1), this.fadeIn);\n\t if (duration) {\n\t source.stop(time + this.toSeconds(duration), this.fadeOut);\n\t }\n\t pitch = this.defaultArg(pitch, 0);\n\t source.playbackRate.value = this.intervalToFrequencyRatio(pitch);\n\t return this;\n\t };\n\t /**\n\t\t * Start a looping buffer by name. Similar to `start`, but the buffer\n\t\t * is looped instead of played straight through. Can still be stopped with `stop`. \n\t\t * @param {String} bufferName The name of the buffer to start.\n\t\t * @param {Time} time When to start the buffer.\n\t\t * @param {Time} [offset=0] The offset into the buffer to play from.\n\t\t * @param {Time=} loopStart The start of the loop.\n\t\t * @param {Time=} loopEnd\tThe end of the loop.\n\t\t * @param {Interval} [pitch=0] The interval to repitch the buffer.\n\t\t * @param {Gain} [gain=1] The gain to play the sample at.\n\t\t * @return {Tone.MultiPlayer} this\n\t\t */\n\t Tone.MultiPlayer.prototype.startLoop = function (bufferName, time, offset, loopStart, loopEnd, pitch, gain) {\n\t time = this.toSeconds(time);\n\t var source = this._makeSource(bufferName);\n\t source.loop = true;\n\t source.loopStart = this.toSeconds(this.defaultArg(loopStart, 0));\n\t source.loopEnd = this.toSeconds(this.defaultArg(loopEnd, 0));\n\t source.start(time, offset, undefined, this.defaultArg(gain, 1), this.fadeIn);\n\t pitch = this.defaultArg(pitch, 0);\n\t source.playbackRate.value = this.intervalToFrequencyRatio(pitch);\n\t return this;\n\t };\n\t /**\n\t\t * Stop the first played instance of the buffer name.\n\t\t * @param {String} bufferName The buffer to stop.\n\t\t * @param {Time=} time When to stop the buffer\n\t\t * @return {Tone.MultiPlayer} this\n\t\t */\n\t Tone.MultiPlayer.prototype.stop = function (bufferName, time) {\n\t if (this._activeSources[bufferName] && this._activeSources[bufferName].length) {\n\t time = this.toSeconds(time);\n\t this._activeSources[bufferName].shift().stop(time, this.fadeOut);\n\t } else {\n\t throw new Error('Tone.MultiPlayer: cannot stop a buffer that hasn\\'t been started or is already stopped');\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Stop all currently playing buffers at the given time.\n\t\t * @param {Time=} time When to stop the buffers.\n\t\t * @return {Tone.MultiPlayer} this\n\t\t */\n\t Tone.MultiPlayer.prototype.stopAll = function (time) {\n\t time = this.toSeconds(time);\n\t for (var bufferName in this._activeSources) {\n\t var sources = this._activeSources[bufferName];\n\t for (var i = 0; i < sources.length; i++) {\n\t sources[i].stop(time);\n\t }\n\t }\n\t return this;\n\t };\n\t /**\n\t\t * Add another buffer to the available buffers.\n\t\t * @param {String} name The name to that the buffer is refered\n\t\t * to in start/stop methods. \n\t\t * @param {String|Tone.Buffer} url The url of the buffer to load\n\t\t * or the buffer.\n\t\t * @param {Function} callback The function to invoke after the buffer is loaded.\n\t\t */\n\t Tone.MultiPlayer.prototype.add = function (name, url, callback) {\n\t this.buffers.add(name, url, callback);\n\t return this;\n\t };\n\t /**\n\t\t * Returns the playback state of the source. \"started\"\n\t\t * if there are any buffers playing. \"stopped\" otherwise.\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.MultiPlayer#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.MultiPlayer.prototype, 'state', {\n\t get: function () {\n\t return this._activeSources.length > 0 ? Tone.State.Started : Tone.State.Stopped;\n\t }\n\t });\n\t /**\n\t\t * Mute the output. \n\t\t * @memberOf Tone.MultiPlayer#\n\t\t * @type {boolean}\n\t\t * @name mute\n\t\t * @example\n\t\t * //mute the output\n\t\t * source.mute = true;\n\t\t */\n\t Object.defineProperty(Tone.MultiPlayer.prototype, 'mute', {\n\t get: function () {\n\t return this._volume.mute;\n\t },\n\t set: function (mute) {\n\t this._volume.mute = mute;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.MultiPlayer} this\n\t\t */\n\t Tone.MultiPlayer.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this._volume.dispose();\n\t this._volume = null;\n\t this._writable('volume');\n\t this.volume = null;\n\t for (var bufferName in this._activeSources) {\n\t this._activeSources[bufferName].forEach(function (source) {\n\t source.dispose();\n\t });\n\t }\n\t this.buffers.dispose();\n\t this.buffers = null;\n\t this._activeSources = null;\n\t return this;\n\t };\n\t return Tone.MultiPlayer;\n\t});\n\tModule(function (Tone) {\n\t /**\n\t\t * @class Tone.GrainPlayer implements [granular synthesis](https://en.wikipedia.org/wiki/Granular_synthesis).\n\t\t * Granular Synthesis enables you to adjust pitch and playback rate independently. The grainSize is the \n\t\t * amount of time each small chunk of audio is played for and the overlap is the \n\t\t * amount of crossfading transition time between successive grains.\n\t\t * @extends {Tone}\n\t\t * @param {String|Tone.Buffer} url\tThe url to load, or the Tone.Buffer to play.\n\t\t * @param {Function=} callback The callback to invoke after the url is loaded.\n\t\t */\n\t Tone.GrainPlayer = function () {\n\t var options = this.optionsObject(arguments, [\n\t 'url',\n\t 'onload'\n\t ], Tone.GrainPlayer.defaults);\n\t Tone.Source.call(this);\n\t /**\n\t\t\t * The audio buffer belonging to the player.\n\t\t\t * @type {Tone.Buffer}\n\t\t\t */\n\t this.buffer = new Tone.Buffer(options.url, options.onload);\n\t /**\n\t\t\t * Plays the buffer with a small envelope\n\t\t\t * @type {Tone.MultiPlayer}\n\t\t\t * @private\n\t\t\t */\n\t this._player = new Tone.MultiPlayer().connect(this.output);\n\t /**\n\t\t\t * Create a repeating tick to schedule\n\t\t\t * the grains.\n\t\t\t * @type {Tone.Clock}\n\t\t\t * @private\n\t\t\t */\n\t this._clock = new Tone.Clock(this._tick.bind(this), 1);\n\t /**\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._loopStart = 0;\n\t /**\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._loopEnd = 0;\n\t /**\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._playbackRate = options.playbackRate;\n\t /**\n\t\t\t * @type {Number}\n\t\t\t * @private\n\t\t\t */\n\t this._grainSize = options.grainSize;\n\t /**\n\t\t\t * @private\n\t\t\t * @type {Number}\n\t\t\t */\n\t this._overlap = options.overlap;\n\t /**\n\t\t\t * Adjust the pitch independently of the playbackRate.\n\t\t\t * @type {Cents}\n\t\t\t */\n\t this.detune = options.detune;\n\t /**\n\t\t\t * The amount of time randomly added\n\t\t\t * or subtracted from the grain's offset\n\t\t\t * @type {Time}\n\t\t\t */\n\t this.drift = options.drift;\n\t //setup\n\t this.overlap = options.overlap;\n\t this.loop = options.loop;\n\t this.playbackRate = options.playbackRate;\n\t this.grainSize = options.grainSize;\n\t this.loopStart = options.loopStart;\n\t this.loopEnd = options.loopEnd;\n\t this.reverse = options.reverse;\n\t };\n\t Tone.extend(Tone.GrainPlayer, Tone.Source);\n\t /**\n\t\t * the default parameters\n\t\t * @static\n\t\t * @const\n\t\t * @type {Object}\n\t\t */\n\t Tone.GrainPlayer.defaults = {\n\t 'onload': Tone.noOp,\n\t 'overlap': 0.1,\n\t 'grainSize': 0.2,\n\t 'drift': 0,\n\t 'playbackRate': 1,\n\t 'detune': 0,\n\t 'loop': false,\n\t 'loopStart': 0,\n\t 'loopEnd': 0,\n\t 'reverse': false\n\t };\n\t /**\n\t\t * Play the buffer at the given startTime. Optionally add an offset\n\t\t * and/or duration which will play the buffer from a position\n\t\t * within the buffer for the given duration. \n\t\t * \n\t\t * @param {Time} [startTime=now] When the player should start.\n\t\t * @param {Time} [offset=0] The offset from the beginning of the sample\n\t\t * to start at. \n\t\t * @param {Time=} duration How long the sample should play. If no duration\n\t\t * is given, it will default to the full length \n\t\t * of the sample (minus any offset)\n\t\t * @returns {Tone.GrainPlayer} this\n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @method start\n\t\t * @name start\n\t\t */\n\t /**\n\t\t * Internal start method\n\t\t * @param {Time} time\n\t\t * @param {Time} offset\n\t\t * @private\n\t\t */\n\t Tone.GrainPlayer.prototype._start = function (time, offset, duration) {\n\t offset = this.defaultArg(offset, 0);\n\t offset = this.toSeconds(offset);\n\t time = this.toSeconds(time);\n\t this._offset = offset;\n\t this._clock.start(time);\n\t //unmute the player\n\t this._player.volume.setValueAtTime(0, time);\n\t if (duration) {\n\t this._stop(time + this.toSeconds(duration));\n\t }\n\t };\n\t /**\n\t\t * Internal start method\n\t\t * @param {Time} time\n\t\t * @private\n\t\t */\n\t Tone.GrainPlayer.prototype._stop = function (time) {\n\t this._clock.stop(time);\n\t //mute the player\n\t this._player.volume.cancelScheduledValues(time);\n\t this._player.volume.setValueAtTime(-Infinity, time);\n\t };\n\t /**\n\t\t * Invoked on each clock tick. scheduled a new\n\t\t * grain at this time.\n\t\t * @param {Time} time \n\t\t * @private\n\t\t */\n\t Tone.GrainPlayer.prototype._tick = function (time) {\n\t var bufferDuration = this.buffer.duration;\n\t if (this.loop && this._loopEnd > 0) {\n\t bufferDuration = this._loopEnd;\n\t }\n\t var drift = (Math.random() * 2 - 1) * this.drift;\n\t var offset = this._offset - this._overlap + drift;\n\t var detune = this.detune / 100;\n\t //keep the offset within the limits of the buffer\n\t offset = Math.max(offset, 0);\n\t offset = Math.min(offset, bufferDuration);\n\t var originalFadeIn = this._player.fadeIn;\n\t if (this.loop && this._offset > bufferDuration) {\n\t //play the end\n\t var endSegmentDuration = this._offset - bufferDuration;\n\t this._player.start(this.buffer, time, offset, endSegmentDuration + this._overlap, detune);\n\t //and play the beginning \n\t offset = this._offset % bufferDuration;\n\t this._offset = this._loopStart;\n\t this._player.fadeIn = 0;\n\t this._player.start(this.buffer, time + endSegmentDuration, this._offset, offset + this._overlap, detune);\n\t } else if (this._offset > bufferDuration) {\n\t //set the state to stopped. \n\t this.stop(time);\n\t } else {\n\t if (offset === 0) {\n\t this._player.fadeIn = 0;\n\t }\n\t this._player.start(this.buffer, time, offset, this.grainSize + this._overlap, detune);\n\t }\n\t this._player.fadeIn = originalFadeIn;\n\t //increment the offset\n\t var duration = this._clock._nextTick - time;\n\t this._offset += duration * this._playbackRate;\n\t };\n\t /**\n\t\t * Jump to a specific time and play it.\n\t\t * @param {Time} offset The offset to jump to.\n\t\t * @param {Time=} time When to make the jump.\n\t\t * @return {[type]} [description]\n\t\t */\n\t Tone.GrainPlayer.prototype.scrub = function (offset, time) {\n\t this._offset = this.toSeconds(offset);\n\t this._tick(this.toSeconds(time));\n\t return this;\n\t };\n\t /**\n\t\t * The playback rate of the sample\n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @type {Positive}\n\t\t * @name playbackRate\n\t\t */\n\t Object.defineProperty(Tone.GrainPlayer.prototype, 'playbackRate', {\n\t get: function () {\n\t return this._playbackRate;\n\t },\n\t set: function (rate) {\n\t this._playbackRate = rate;\n\t this.grainSize = this._grainSize;\n\t }\n\t });\n\t /**\n\t\t * The loop start time. \n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @type {Time}\n\t\t * @name loopStart\n\t\t */\n\t Object.defineProperty(Tone.GrainPlayer.prototype, 'loopStart', {\n\t get: function () {\n\t return this._loopStart;\n\t },\n\t set: function (time) {\n\t this._loopStart = this.toSeconds(time);\n\t }\n\t });\n\t /**\n\t\t * The loop end time. \n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @type {Time}\n\t\t * @name loopEnd\n\t\t */\n\t Object.defineProperty(Tone.GrainPlayer.prototype, 'loopEnd', {\n\t get: function () {\n\t return this._loopEnd;\n\t },\n\t set: function (time) {\n\t this._loopEnd = this.toSeconds(time);\n\t }\n\t });\n\t /**\n\t\t * The direction the buffer should play in\n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @type {boolean}\n\t\t * @name reverse\n\t\t */\n\t Object.defineProperty(Tone.GrainPlayer.prototype, 'reverse', {\n\t get: function () {\n\t return this.buffer.reverse;\n\t },\n\t set: function (rev) {\n\t this.buffer.reverse = rev;\n\t }\n\t });\n\t /**\n\t\t * The size of each chunk of audio that the \n\t\t * buffer is chopped into and played back at.\n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @type {Time}\n\t\t * @name grainSize\n\t\t */\n\t Object.defineProperty(Tone.GrainPlayer.prototype, 'grainSize', {\n\t get: function () {\n\t return this._grainSize;\n\t },\n\t set: function (size) {\n\t this._grainSize = this.toSeconds(size);\n\t this._clock.frequency.value = this._playbackRate / this._grainSize;\n\t }\n\t });\n\t /**\n\t\t * This is the duration of the cross-fade between \n\t\t * sucessive grains.\n\t\t * @memberOf Tone.GrainPlayer#\n\t\t * @type {Time}\n\t\t * @name overlap\n\t\t */\n\t Object.defineProperty(Tone.GrainPlayer.prototype, 'overlap', {\n\t get: function () {\n\t return this._overlap;\n\t },\n\t set: function (time) {\n\t time = this.toSeconds(time);\n\t this._overlap = time;\n\t if (this._overlap < 0) {\n\t this._player.fadeIn = 0.01;\n\t this._player.fadeOut = 0.01;\n\t } else {\n\t this._player.fadeIn = time;\n\t this._player.fadeOut = time;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Clean up\n\t\t * @return {Tone.GrainPlayer} this\n\t\t */\n\t Tone.GrainPlayer.prototype.dispose = function () {\n\t Tone.Source.prototype.dispose.call(this);\n\t this.buffer.dispose();\n\t this.buffer = null;\n\t this._player.dispose();\n\t this._player = null;\n\t this._clock.dispose();\n\t this._clock = null;\n\t return this;\n\t };\n\t return Tone.GrainPlayer;\n\t});\n\tModule(function (Tone) {\n\t \n\t /**\n\t\t * @class Tone.UserMedia uses MediaDevices.getUserMedia to open up\n\t\t * and external microphone or audio input. Check \n\t\t * [MediaDevices API Support](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)\n\t\t * to see which browsers are supported. Access to an external input\n\t\t * is limited to secure (HTTPS) connections.\n\t\t * \n\t\t * @constructor\n\t\t * @extends {Tone}\n\t\t * @param {Decibels=} volume The level of the input\n\t\t * @example\n\t\t * //list the inputs and open the third one\n\t\t * var motu = new Tone.UserMedia();\n\t\t * \n\t\t * //opening the input asks the user to activate their mic\n\t\t * motu.open().then(function(){\n\t\t * \t//opening is activates the microphone\n\t\t * \t//starting lets audio through\n\t\t * \tmotu.start(10);\n\t\t * });\n\t\t */\n\t Tone.UserMedia = function () {\n\t var options = this.optionsObject(arguments, ['volume'], Tone.UserMedia.defaults);\n\t /**\n\t\t\t * The MediaStreamNode \n\t\t\t * @type {MediaStreamAudioSourceNode}\n\t\t\t * @private\n\t\t\t */\n\t this._mediaStream = null;\n\t /**\n\t\t\t * The media stream created by getUserMedia.\n\t\t\t * @type {LocalMediaStream}\n\t\t\t * @private\n\t\t\t */\n\t this._stream = null;\n\t /**\n\t\t\t * The open device\n\t\t\t * @type {MediaDeviceInfo}\n\t\t\t * @private\n\t\t\t */\n\t this._device = null;\n\t /**\n\t\t\t * The output volume node\n\t\t\t * @type {Tone.Volume}\n\t\t\t * @private\n\t\t\t */\n\t this._volume = this.output = new Tone.Volume(options.volume);\n\t /**\n\t\t\t * The volume of the output in decibels.\n\t\t\t * @type {Decibels}\n\t\t\t * @signal\n\t\t\t * @example\n\t\t\t * input.volume.value = -6;\n\t\t\t */\n\t this.volume = this._volume.volume;\n\t this._readOnly('volume');\n\t this.mute = options.mute;\n\t };\n\t Tone.extend(Tone.UserMedia);\n\t /**\n\t\t * the default parameters\n\t\t * @type {Object}\n\t\t */\n\t Tone.UserMedia.defaults = {\n\t 'volume': 0,\n\t 'mute': false\n\t };\n\t /**\n\t\t * Open the media stream. If a string is passed in, it is assumed\n\t\t * to be the label or id of the stream, if a number is passed in,\n\t\t * it is the input number of the stream.\n\t\t * @param {String|Number} [labelOrId=\"default\"] The label or id of the audio input media device. \n\t\t * With no argument, the default stream is opened.\n\t\t * @return {Promise} The promise is resolved when the stream is open.\n\t\t */\n\t Tone.UserMedia.prototype.open = function (labelOrId) {\n\t labelOrId = this.defaultArg(labelOrId, 'default');\n\t return this.enumerateDevices().then(function (devices) {\n\t var device;\n\t if (this.isNumber(labelOrId)) {\n\t device = devices[labelOrId];\n\t } else {\n\t device = devices.find(function (device) {\n\t return device.label === labelOrId || device.deviceId === labelOrId;\n\t });\n\t if (!device) {\n\t //otherwise just take the first one\n\t device = devices[0];\n\t }\n\t }\n\t //didn't find a matching device\n\t if (!device) {\n\t throw new Error('Tone.UserMedia: no matching audio inputs.');\n\t }\n\t this._device = device;\n\t //do getUserMedia\n\t var constraints = {\n\t audio: {\n\t 'deviceId': device.deviceId,\n\t 'echoCancellation': false,\n\t 'sampleRate': this.context.sampleRate\n\t }\n\t };\n\t return navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {\n\t //start a new source only if the previous one is closed\n\t if (!this._stream) {\n\t this._stream = stream;\n\t //Wrap a MediaStreamSourceNode around the live input stream.\n\t this._mediaStream = this.context.createMediaStreamSource(stream);\n\t //Connect the MediaStreamSourceNode to a gate gain node\n\t this._mediaStream.connect(this.output);\n\t }\n\t return this;\n\t }.bind(this));\n\t }.bind(this));\n\t };\n\t /**\n\t\t * Close the media stream\n\t\t * @return {Tone.UserMedia} this\n\t\t */\n\t Tone.UserMedia.prototype.close = function () {\n\t if (this._stream) {\n\t this._stream.getAudioTracks().forEach(function (track) {\n\t track.stop();\n\t });\n\t this._stream = null;\n\t //remove the old media stream\n\t this._mediaStream.disconnect();\n\t this._mediaStream = null;\n\t }\n\t this._device = null;\n\t return this;\n\t };\n\t /**\n\t\t * Returns a promise which resolves with the list of audio input devices available.\n\t\t * @return {Promise} The promise that is resolved with the devices\n\t\t * @example\n\t\t * extInput.enumerateDevices().then(function(devices){\n\t\t * \tconsole.log(devices)\n\t\t * })\n\t\t */\n\t Tone.UserMedia.prototype.enumerateDevices = function () {\n\t return navigator.mediaDevices.enumerateDevices().then(function (devices) {\n\t return devices.filter(function (device) {\n\t return device.kind === 'audioinput';\n\t });\n\t });\n\t };\n\t /**\n\t\t * Returns the playback state of the source, \"started\" when the microphone is open\n\t\t * and \"stopped\" when the mic is closed.\n\t\t * @type {Tone.State}\n\t\t * @readOnly\n\t\t * @memberOf Tone.UserMedia#\n\t\t * @name state\n\t\t */\n\t Object.defineProperty(Tone.UserMedia.prototype, 'state', {\n\t get: function () {\n\t return this._stream && this._stream.active ? Tone.State.Started : Tone.State.Stopped;\n\t }\n\t });\n\t /**\n\t\t * \tReturns an identifier for the represented device that is \n\t\t * \tpersisted across sessions. It is un-guessable by other applications and \n\t\t * \tunique to the origin of the calling application. It is reset when the \n\t\t * \tuser clears cookies (for Private Browsing, a different identifier is \n\t\t * \tused that is not persisted across sessions). Returns undefined when the \n\t\t * \tdevice is not open.\n\t\t * @type {String}\n\t\t * @readOnly\n\t\t * @memberOf Tone.UserMedia#\n\t\t * @name deviceId\n\t\t */\n\t Object.defineProperty(Tone.UserMedia.prototype, 'deviceId', {\n\t get: function () {\n\t if (this._device) {\n\t return this._device.deviceId;\n\t }\n\t }\n\t });\n\t /**\n\t\t * \tReturns a group identifier. Two devices have the \n\t\t * \tsame group identifier if they belong to the same physical device.\n\t\t * \tReturns undefined when the device is not open.\n\t\t * @type {String}\n\t\t * @readOnly\n\t\t * @memberOf Tone.UserMedia#\n\t\t * @name groupId\n\t\t */\n\t Object.defineProperty(Tone.UserMedia.prototype, 'groupId', {\n\t get: function () {\n\t if (this._device) {\n\t return this._device.groupId;\n\t }\n\t }\n\t });\n\t /**\n\t\t * \tReturns a label describing this device (for example \"Built-in Microphone\"). \n\t\t * \tReturns undefined when the device is not open or label is not available\n\t\t * \tbecause of permissions.\n\t\t * @type {String}\n\t\t * @readOnly\n\t\t * @memberOf Tone.UserMedia#\n\t\t * @name groupId\n\t\t */\n\t Object.defineProperty(Tone.UserMedia.prototype, 'label', {\n\t get: function () {\n\t if (this._device) {\n\t return this._device.label;\n\t }\n\t }\n\t });\n\t /**\n\t\t * Mute the output. \n\t\t * @memberOf Tone.UserMedia#\n\t\t * @type {boolean}\n\t\t * @name mute\n\t\t * @example\n\t\t * //mute the output\n\t\t * userMedia.mute = true;\n\t\t */\n\t Object.defineProperty(Tone.UserMedia.prototype, 'mute', {\n\t get: function () {\n\t return this._volume.mute;\n\t },\n\t set: function (mute) {\n\t this._volume.mute = mute;\n\t }\n\t });\n\t /**\n\t\t * Clean up.\n\t\t * @return {Tone.UserMedia} this\n\t\t */\n\t Tone.UserMedia.prototype.dispose = function () {\n\t Tone.prototype.dispose.call(this);\n\t this.close();\n\t this._writable('volume');\n\t this._volume.dispose();\n\t this._volume = null;\n\t this.volume = null;\n\t return this;\n\t };\n\t /**\n\t\t * If getUserMedia is supported by the browser.\n\t\t * @type {Boolean}\n\t\t * @memberOf Tone.UserMedia#\n\t\t * @name supported\n\t\t * @static\n\t\t * @readOnly\n\t\t */\n\t Object.defineProperty(Tone.UserMedia, 'supported', {\n\t get: function () {\n\t return !Tone.prototype.isUndef(navigator.mediaDevices) && Tone.prototype.isFunction(navigator.mediaDevices.getUserMedia);\n\t }\n\t });\n\t return Tone.UserMedia;\n\t});\n\t\n\treturn Tone;\n}));\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/tone/build/Tone.js\n// module id = 0\n// module chunks = 0","'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar palettes = [[[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.33, 0.67]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.10, 0.20]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.30, 0.20, 0.20]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.80, 0.90, 0.30]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.00, 0.15, 0.20]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.50, 0.20, 0.25]], [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.00, 0.25, 0.25]]];\n\nvar palette = palettes[0];\n\nfunction channel(t, a, b, c, d, add, mul) {\n return a + b * Math.cos(2 * Math.PI * (c * t + d)) * mul + add;\n}\n\nfunction color(t, add, mul) {\n var a = void 0,\n b = void 0,\n c = void 0,\n d = void 0;\n var rgb = [];\n for (var i = 0; i < 3; i++) {\n a = palette[0][i];\n b = palette[1][i];\n c = palette[2][i];\n d = palette[3][i];\n rgb[i] = Math.round(channel(t, a, b, c, d, add, mul) * 255);\n }\n return 'rgb(' + rgb + ')';\n}\n\nexports.default = color;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/color.js\n// module id = 1\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nvar keys = {};\nvar key_numbers = {};\nvar letters = \"zxcvbnmasdfghjklqwertyuiop\";\nvar numbers = \"1234567890\";\n\nvar callback = function callback() {};\n\nletters.toUpperCase().split(\"\").map(function (k, i) {\n keys[k.charCodeAt(0)] = i;\n});\n\nnumbers.split(\"\").map(function (k, i) {\n keys[k.charCodeAt(0)] = i + letters.length;\n key_numbers[k.charCodeAt(0)] = true;\n});\n\nwindow.addEventListener(\"keydown\", keydown, true);\nfunction keydown(e) {\n if (e.altKey || e.ctrlKey || e.metaKey) {\n e.stopPropagation();\n return;\n }\n if (document.activeElement instanceof HTMLInputElement && e.keyCode in key_numbers) {\n e.stopPropagation();\n return;\n }\n if (!(e.keyCode in keys)) return;\n var index = keys[e.keyCode];\n if (e.shiftKey) index += letters.length;\n index -= 7;\n callback(index);\n}\n\nfunction listen(fn) {\n callback = fn;\n}\n\nexports.default = { listen: listen };\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/keys.js\n// module id = 2\n// module chunks = 0","'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.requestAudioContext = exports.firstTouch = exports.browser = exports.clamp = exports.mod = exports.choice = undefined;\n\nvar _tone = require('tone');\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nvar _startAudioContext = require('./startAudioContext');\n\nvar _startAudioContext2 = _interopRequireDefault(_startAudioContext);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar isIphone = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i);\nvar isIpad = navigator.userAgent.match(/iPad/i);\nvar isAndroid = navigator.userAgent.match(/Android/i);\nvar isMobile = isIphone || isIpad || isAndroid;\nvar isDesktop = !isMobile;\n\ndocument.body.classList.add(isMobile ? 'mobile' : 'desktop');\n\nvar browser = { isIphone: isIphone, isIpad: isIpad, isMobile: isMobile, isDesktop: isDesktop };\n\nfunction clamp(n, a, b) {\n return n < a ? a : n < b ? n : b;\n}\nfunction choice(a) {\n return a[Math.floor(Math.random() * a.length)];\n}\nfunction mod(n, m) {\n return n - m * Math.floor(n / m);\n}\nfunction firstTouch(f) {\n return function (e) {\n return f(e.touches[0]);\n };\n}\n\nfunction requestAudioContext(fn) {\n if (isMobile) {\n var container = document.createElement('div');\n var button = document.createElement('div');\n button.innerHTML = 'Tap to start - please unmute your phone';\n Object.assign(container.style, {\n display: 'block',\n position: 'absolute',\n width: '100%',\n height: '100%',\n zIndex: '10000',\n top: '0px',\n left: '0px',\n backgroundColor: 'rgba(0, 0, 0, 0.8)'\n });\n Object.assign(button.style, {\n display: 'block',\n position: 'absolute',\n left: '50%',\n top: '50%',\n padding: '20px',\n backgroundColor: '#7F33ED',\n color: 'white',\n fontFamily: 'monospace',\n borderRadius: '3px',\n transform: 'translate3D(-50%,-50%,0)',\n textAlign: 'center',\n lineHeight: '1.5',\n width: '150px'\n });\n container.appendChild(button);\n document.body.appendChild(container);\n _startAudioContext2.default.setContext(_tone2.default.context);\n _startAudioContext2.default.on(button);\n _startAudioContext2.default.onStarted(function (_) {\n container.remove();\n fn();\n });\n } else {\n fn();\n }\n}\n\nexports.choice = choice;\nexports.mod = mod;\nexports.clamp = clamp;\nexports.browser = browser;\nexports.firstTouch = firstTouch;\nexports.requestAudioContext = requestAudioContext;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/util.js\n// module id = 3\n// module chunks = 0","'use strict';\n\nvar _tone = require('tone');\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nvar _keys = require('./lib/keys');\n\nvar _keys2 = _interopRequireDefault(_keys);\n\nvar _color = require('./lib/color');\n\nvar _color2 = _interopRequireDefault(_color);\n\nvar _util = require('./lib/util');\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar compressor = new _tone2.default.Compressor(-30, 3).toMaster();\n\nvar GRAIN_TIME = 1 / 20;\nvar SAMPLE_RATE = 44100;\nvar GRAIN_SIZE = GRAIN_TIME * SAMPLE_RATE;\n\n(0, _util.requestAudioContext)(function () {\n var clock = new _tone2.default.Clock(tick, 1 / GRAIN_TIME);\n clock.start();\n console.log('ready');\n});\n\nvar offsets = [];\n\nvar player = new _tone2.default.MultiPlayer({\n applause: 'applause.mp3'\n}, function () {\n var data = player.buffers.get('applause').get().getChannelData(0);\n var intensities = [];\n for (var i = 0, len = Math.floor(data.length / GRAIN_SIZE); i < len; i++) {\n var z = 0;\n for (var j = i * GRAIN_SIZE, max = (i + 1) * GRAIN_SIZE; j < max; j++) {\n z += Math.abs(data[j]);\n }\n intensities[i] = [z / GRAIN_SIZE, i];\n }\n offsets = intensities.sort(function (a, b) {\n return a[0] < b[0] ? -1 : a[0] == b[0] ? 0 : 1;\n }).map(function (a, i) {\n return a[1];\n });\n});\n\nplayer.fadeIn = 0.25;\nplayer.fadeOut = 0.25;\nplayer.connect(compressor);\n\nvar intensity = 0,\n inertialIntensity = 0,\n inertia = 16;\n\nfunction tick(time) {\n if (!offsets.length) return;\n // let offsetIndex = clamp( Math.floor(mouse.y * offsets.length + Math.cos(time/20)), 0, offsets.length-1 )\n inertialIntensity = Math.max(intensity, (intensity + inertialIntensity * (inertia - 1)) / inertia);\n console.log(inertialIntensity);\n var offsetIndex = Math.floor(inertialIntensity * offsets.length + Math.cos(time));\n var offset = Math.max((offsets[offsetIndex] || 0) * GRAIN_TIME + 0.25 * Math.sin(time * 17 / 7), 0);\n // console.log(offset, offsets[offsetIndex] * GRAIN_TIME, ( 0.25 * Math.cos(time*13/7)))\n player.start('applause', time, offset, GRAIN_TIME * 4);\n}\n\nvar mouse = { x: 0, y: 0 };\nvar drawing = false;\nvar canvas = document.createElement('canvas');\ncanvas.width = window.innerWidth;\ncanvas.height = window.innerHeight;\nvar ctx = canvas.getContext('2d');\ndocument.body.appendChild(canvas);\n\nfunction down(e) {\n drawing = true;\n mouse.x = e.pageX / window.innerWidth;\n mouse.y = e.pageY / window.innerHeight;\n}\nfunction move(e) {\n var x = e.pageX / window.innerWidth;\n var y = e.pageY / window.innerHeight;\n var dx = mouse.x - x;\n var dy = mouse.y - y;\n var v = Math.sqrt(dx * dx + dy * dy);\n if (drawing) {\n intensity = Math.min(0.999, intensity + v * 0.1);\n inertialIntensity = Math.min(0.999, intensity);\n if (intensity == 0.999) intensity -= Math.random() * 0.01;\n if (inertialIntensity == 0.999) inertialIntensity -= Math.random() * 0.01;\n var gray = Math.floor((0, _util.clamp)(1 - 10 * v, 0, 1) * 255);\n ctx.fillStyle = 'rgb(' + [gray, gray, gray] + ')';\n ctx.beginPath();\n ctx.arc(x * window.innerWidth, y * window.innerHeight, v * 500, 0, Math.PI * 2);\n ctx.fill();\n }\n mouse.x = x;\n mouse.y = y;\n}\nfunction up(e) {\n drawing = false;\n intensity = 0;\n}\nsetInterval(function () {\n inertialIntensity += 0.1;\n}, 2000);\n\nif (_util.browser.isMobile) {\n document.body.addEventListener('touchstart', (0, _util.firstTouch)(down));\n document.body.addEventListener('touchmove', (0, _util.firstTouch)(move));\n window.addEventListener('touchend', (0, _util.firstTouch)(up));\n} else {\n document.body.addEventListener('mousedown', down);\n document.body.addEventListener('mousemove', move);\n window.addEventListener('mouseup', up);\n}\n\nfunction animate() {\n requestAnimationFrame(animate);\n ctx.save();\n ctx.fillStyle = 'rgba(255,255,255,0.11)';\n ctx.globalAlpha = 0.1;\n ctx.fillRect(0, 0, window.innerWidth, window.innerHeight);\n ctx.restore();\n}\nanimate();\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/index.js\n// module id = 4\n// module chunks = 0","\"use strict\";\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/**\n * StartAudioContext.js\n * @author Yotam Mann\n * @license http://opensource.org/licenses/MIT MIT License\n * @copyright 2016 Yotam Mann\n */\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], factory);\n } else if ((typeof module === \"undefined\" ? \"undefined\" : _typeof(module)) === 'object' && module.exports) {\n module.exports = factory();\n } else {\n root.StartAudioContext = factory();\n }\n})(undefined, function () {\n\n /**\n * The StartAudioContext object\n */\n var StartAudioContext = {\n /**\n * The audio context passed in by the user\n * @type {AudioContext}\n */\n context: null,\n /**\n * The TapListeners bound to the elements\n * @type {Array}\n * @private\n */\n _tapListeners: [],\n /**\n * Callbacks to invoke when the audio context is started\n * @type {Array}\n * @private\n */\n _onStarted: []\n };\n\n /**\n * Set the context\n * @param {AudioContext} ctx\n * @returns {StartAudioContext}\n */\n StartAudioContext.setContext = function (ctx) {\n StartAudioContext.context = ctx;\n return StartAudioContext;\n };\n\n /**\n * Add a tap listener to the audio context\n * @param {Array|Element|String|jQuery} element\n * @returns {StartAudioContext}\n */\n StartAudioContext.on = function (element) {\n if (Array.isArray(element) || NodeList && element instanceof NodeList) {\n for (var i = 0; i < element.length; i++) {\n StartAudioContext.on(element[i]);\n }\n } else if (typeof element === \"string\") {\n StartAudioContext.on(document.querySelectorAll(element));\n } else if (element.jquery && typeof element.toArray === \"function\") {\n StartAudioContext.on(element.toArray());\n } else if (Element && element instanceof Element) {\n //if it's an element, create a TapListener\n var tap = new TapListener(element, onTap);\n StartAudioContext._tapListeners.push(tap);\n }\n return StartAudioContext;\n };\n\n /**\n * Bind a callback to when the audio context is started. \n * @param {Function} cb\n * @return {StartAudioContext}\n */\n StartAudioContext.onStarted = function (cb) {\n //if it's already started, invoke the callback\n if (StartAudioContext.isStarted()) {\n cb();\n } else {\n StartAudioContext._onStarted.push(cb);\n }\n return StartAudioContext;\n };\n\n /**\n * returns true if the context is started\n * @return {Boolean}\n */\n StartAudioContext.isStarted = function () {\n return StartAudioContext.context !== null && StartAudioContext.context.state === \"running\";\n };\n\n /**\n * @class Listens for non-dragging tap ends on the given element\n * @param {Element} element\n * @internal\n */\n var TapListener = function TapListener(element) {\n\n this._dragged = false;\n\n this._element = element;\n\n this._bindedMove = this._moved.bind(this);\n this._bindedEnd = this._ended.bind(this);\n\n element.addEventListener(\"touchmove\", this._bindedMove);\n element.addEventListener(\"touchend\", this._bindedEnd);\n element.addEventListener(\"mouseup\", this._bindedEnd);\n };\n\n /**\n * drag move event\n */\n TapListener.prototype._moved = function (e) {\n this._dragged = true;\n };\n\n /**\n * tap ended listener\n */\n TapListener.prototype._ended = function (e) {\n if (!this._dragged) {\n onTap();\n }\n this._dragged = false;\n };\n\n /**\n * remove all the bound events\n */\n TapListener.prototype.dispose = function () {\n this._element.removeEventListener(\"touchmove\", this._bindedMove);\n this._element.removeEventListener(\"touchend\", this._bindedEnd);\n this._element.removeEventListener(\"mouseup\", this._bindedEnd);\n this._bindedMove = null;\n this._bindedEnd = null;\n this._element = null;\n };\n\n /**\n * Invoked the first time of the elements is tapped.\n * Creates a silent oscillator when a non-dragging touchend \n * event has been triggered.\n */\n function onTap() {\n //start the audio context with a silent oscillator\n if (StartAudioContext.context && !StartAudioContext.isStarted()) {\n var osc = StartAudioContext.context.createOscillator();\n var silent = StartAudioContext.context.createGain();\n silent.gain.value = 0;\n osc.connect(silent);\n silent.connect(StartAudioContext.context.destination);\n var now = StartAudioContext.context.currentTime;\n osc.start(now);\n osc.stop(now + 0.5);\n }\n\n //dispose all the tap listeners\n if (StartAudioContext._tapListeners) {\n for (var i = 0; i < StartAudioContext._tapListeners.length; i++) {\n StartAudioContext._tapListeners[i].dispose();\n }\n StartAudioContext._tapListeners = null;\n }\n //the onstarted callbacks\n if (StartAudioContext._onStarted) {\n for (var j = 0; j < StartAudioContext._onStarted.length; j++) {\n StartAudioContext._onStarted[j]();\n }\n StartAudioContext._onStarted = null;\n }\n }\n\n return StartAudioContext;\n});\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/startAudioContext.js\n// module id = 5\n// module chunks = 0"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;A;;;;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACr6rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACjIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;A","sourceRoot":""} \ No newline at end of file
diff --git a/client/index.js b/client/index.js
new file mode 100644
index 0000000..12d466e
--- /dev/null
+++ b/client/index.js
@@ -0,0 +1,115 @@
+import Tone from 'tone'
+import keys from './lib/keys'
+import color from './lib/color'
+import { browser, requestAudioContext, clamp, firstTouch } from './lib/util'
+
+const compressor = new Tone.Compressor(-30, 3).toMaster()
+
+const GRAIN_TIME = 1/20
+const SAMPLE_RATE = 44100
+const GRAIN_SIZE = GRAIN_TIME * SAMPLE_RATE
+
+requestAudioContext( () => {
+ const clock = new Tone.Clock(tick, 1/GRAIN_TIME)
+ clock.start()
+ console.log('ready')
+})
+
+let offsets = []
+
+let player = new Tone.MultiPlayer({
+ applause: 'applause.mp3',
+}, () => {
+ let data = player.buffers.get('applause').get().getChannelData(0)
+ let intensities = []
+ for (let i = 0, len = Math.floor(data.length / GRAIN_SIZE); i < len; i++) {
+ let z = 0
+ for (let j = i * GRAIN_SIZE, max = (i+1) * GRAIN_SIZE; j < max; j++) {
+ z += Math.abs(data[j])
+ }
+ intensities[i] = [z / GRAIN_SIZE, i]
+ }
+ offsets = intensities.sort( (a,b) => a[0] < b[0] ? -1 : a[0] == b[0] ? 0 : 1 )
+ .map( (a,i) => {
+ return a[1]
+ })
+})
+
+player.fadeIn = 0.25
+player.fadeOut = 0.25
+player.connect(compressor)
+
+let intensity = 0, inertialIntensity = 0, inertia = 16
+
+function tick (time) {
+ if (! offsets.length) return
+ // let offsetIndex = clamp( Math.floor(mouse.y * offsets.length + Math.cos(time/20)), 0, offsets.length-1 )
+ inertialIntensity = Math.max(intensity, (intensity + inertialIntensity*(inertia-1))/inertia)
+ console.log(inertialIntensity)
+ let offsetIndex = Math.floor(inertialIntensity * offsets.length + Math.cos(time))
+ let offset = Math.max((offsets[offsetIndex] || 0) * GRAIN_TIME + ( 0.25 * Math.sin(time*17/7) ), 0)
+ // console.log(offset, offsets[offsetIndex] * GRAIN_TIME, ( 0.25 * Math.cos(time*13/7)))
+ player.start('applause', time, offset, GRAIN_TIME * 4)
+}
+
+let mouse = { x: 0, y: 0 }
+let drawing = false
+let canvas = document.createElement('canvas')
+canvas.width = window.innerWidth
+canvas.height = window.innerHeight
+let ctx = canvas.getContext('2d')
+document.body.appendChild(canvas)
+
+function down (e) {
+ drawing = true
+ mouse.x = e.pageX / window.innerWidth
+ mouse.y = e.pageY / window.innerHeight
+}
+function move (e){
+ const x = e.pageX / window.innerWidth
+ const y = e.pageY / window.innerHeight
+ const dx = (mouse.x - x)
+ const dy = (mouse.y - y)
+ const v = Math.sqrt(dx*dx+dy*dy)
+ if (drawing) {
+ intensity = Math.min(0.999, intensity + v*0.1)
+ inertialIntensity = Math.min(0.999, intensity)
+ if (intensity == 0.999) intensity -= (Math.random() * 0.01)
+ if (inertialIntensity == 0.999) inertialIntensity -= (Math.random() * 0.01)
+ const gray = Math.floor( clamp(1-(10*v),0,1)*255 )
+ ctx.fillStyle = 'rgb(' + [gray,gray,gray] + ')'
+ ctx.beginPath()
+ ctx.arc( x*window.innerWidth, y*window.innerHeight, v*500, 0, Math.PI*2 )
+ ctx.fill()
+ }
+ mouse.x = x
+ mouse.y = y
+}
+function up (e) {
+ drawing = false
+ intensity = 0
+}
+setInterval( () => {
+ inertialIntensity += 0.1
+}, 2000)
+
+if (browser.isMobile) {
+ document.body.addEventListener('touchstart', firstTouch(down))
+ document.body.addEventListener('touchmove', firstTouch(move))
+ window.addEventListener('touchend', firstTouch(up))
+}
+else {
+ document.body.addEventListener('mousedown', down)
+ document.body.addEventListener('mousemove', move)
+ window.addEventListener('mouseup', up)
+}
+
+function animate(){
+ requestAnimationFrame(animate)
+ ctx.save()
+ ctx.fillStyle='rgba(255,255,255,0.11)'
+ ctx.globalAlpha = 0.1
+ ctx.fillRect(0,0,window.innerWidth,window.innerHeight)
+ ctx.restore()
+}
+animate()
diff --git a/client/lib/color.js b/client/lib/color.js
new file mode 100644
index 0000000..bd5b7ce
--- /dev/null
+++ b/client/lib/color.js
@@ -0,0 +1,31 @@
+
+const palettes = [
+ [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.33, 0.67]],
+ [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.10, 0.20]],
+ [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.30, 0.20, 0.20]],
+ [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.80, 0.90, 0.30]],
+ [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.00, 0.15, 0.20]],
+ [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.50, 0.20, 0.25]],
+ [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.00, 0.25, 0.25]],
+]
+
+let palette = palettes[0]
+
+function channel (t, a, b, c, d, add, mul) {
+ return a + b * Math.cos(2 * Math.PI * (c * t + d)) * mul + add
+}
+
+function color (t, add, mul) {
+ let a, b, c, d
+ const rgb = []
+ for (var i = 0; i < 3; i++) {
+ a = palette[0][i]
+ b = palette[1][i]
+ c = palette[2][i]
+ d = palette[3][i]
+ rgb[i] = Math.round(channel(t, a, b, c, d, add, mul) * 255)
+ }
+ return 'rgb(' + rgb + ')'
+}
+
+export default color
diff --git a/client/lib/kalimba.js b/client/lib/kalimba.js
new file mode 100644
index 0000000..4663bdc
--- /dev/null
+++ b/client/lib/kalimba.js
@@ -0,0 +1,55 @@
+import Tone from 'tone'
+import { choice } from './util'
+
+const player_count = 4
+
+const compressor = new Tone.Compressor(-30, 3).toMaster()
+
+const samples = [
+ { root: 226, fn: 'samples/380737__cabled-mess__sansula-01-a-raw.wav', },
+ { root: 267, fn: 'samples/380736__cabled-mess__sansula-02-c-raw.wav', },
+ { root: 340, fn: 'samples/380735__cabled-mess__sansula-03-e-raw.wav', },
+ { root: 452, fn: 'samples/380733__cabled-mess__sansula-06-a-02-raw.wav', },
+// { root: 507, fn: 'samples/380734__cabled-mess__sansula-07-b-h-raw.wav', },
+// { root: 535, fn: 'samples/380731__cabled-mess__sansula-08-c-raw.wav', },
+// { root: 671, fn: 'samples/380732__cabled-mess__sansula-09-e-raw.wav', },
+]
+
+samples.forEach((sample) => {
+ sample.players = []
+ sample.index = -1
+ for (let i = 0; i < player_count; i++) {
+ let fn = sample.fn
+ if (window.location.href.match(/asdf.us/)) {
+ fn = 'http://asdf.us/kalimba/' + fn.replace('wav','mp3')
+ }
+ let player = new Tone.Player({
+ url: fn,
+ retrigger: true,
+ playbackRate: 1,
+ })
+ player.connect(compressor)
+ sample.players.push(player)
+ }
+})
+
+function play (freq) {
+/*
+ while (freq < 440) {
+ freq *= 2
+ }
+ while (freq > 880) {
+ freq /= 2
+ }
+ freq /= 2
+*/
+ const best = { sample: choice(samples) }
+ best.sample.index = (best.sample.index + 1) % player_count
+
+ const player = best.sample.players[ best.sample.index ]
+ player.playbackRate = freq / best.sample.root
+ player.start()
+}
+
+export default { play }
+
diff --git a/client/lib/keys.js b/client/lib/keys.js
new file mode 100644
index 0000000..c9e51ac
--- /dev/null
+++ b/client/lib/keys.js
@@ -0,0 +1,39 @@
+const keys = {}
+const key_numbers = {}
+const letters = "zxcvbnmasdfghjklqwertyuiop"
+const numbers = "1234567890"
+
+let callback = function(){}
+
+letters.toUpperCase().split("").map(function(k,i){
+ keys[k.charCodeAt(0)] = i
+})
+
+numbers.split("").map(function(k,i){
+ keys[k.charCodeAt(0)] = i+letters.length
+ key_numbers[k.charCodeAt(0)] = true
+})
+
+window.addEventListener("keydown", keydown, true)
+function keydown (e) {
+ if (e.altKey || e.ctrlKey || e.metaKey) {
+ e.stopPropagation()
+ return
+ }
+ if (document.activeElement instanceof HTMLInputElement &&
+ (e.keyCode in key_numbers)) {
+ e.stopPropagation()
+ return
+ }
+ if (! (e.keyCode in keys)) return
+ var index = keys[e.keyCode]
+ if (e.shiftKey) index += letters.length
+ index -= 7
+ callback(index)
+}
+
+function listen (fn) {
+ callback = fn
+}
+
+export default { listen } \ No newline at end of file
diff --git a/client/lib/startAudioContext.js b/client/lib/startAudioContext.js
new file mode 100644
index 0000000..f3a9793
--- /dev/null
+++ b/client/lib/startAudioContext.js
@@ -0,0 +1,181 @@
+/**
+ * StartAudioContext.js
+ * @author Yotam Mann
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @copyright 2016 Yotam Mann
+ */
+(function (root, factory) {
+ if (typeof define === "function" && define.amd) {
+ define([], factory);
+ } else if (typeof module === 'object' && module.exports) {
+ module.exports = factory();
+ } else {
+ root.StartAudioContext = factory();
+ }
+}(this, function () {
+
+ /**
+ * The StartAudioContext object
+ */
+ var StartAudioContext = {
+ /**
+ * The audio context passed in by the user
+ * @type {AudioContext}
+ */
+ context : null,
+ /**
+ * The TapListeners bound to the elements
+ * @type {Array}
+ * @private
+ */
+ _tapListeners : [],
+ /**
+ * Callbacks to invoke when the audio context is started
+ * @type {Array}
+ * @private
+ */
+ _onStarted : [],
+ };
+
+
+ /**
+ * Set the context
+ * @param {AudioContext} ctx
+ * @returns {StartAudioContext}
+ */
+ StartAudioContext.setContext = function(ctx){
+ StartAudioContext.context = ctx;
+ return StartAudioContext;
+ };
+
+ /**
+ * Add a tap listener to the audio context
+ * @param {Array|Element|String|jQuery} element
+ * @returns {StartAudioContext}
+ */
+ StartAudioContext.on = function(element){
+ if (Array.isArray(element) || (NodeList && element instanceof NodeList)){
+ for (var i = 0; i < element.length; i++){
+ StartAudioContext.on(element[i]);
+ }
+ } else if (typeof element === "string"){
+ StartAudioContext.on(document.querySelectorAll(element));
+ } else if (element.jquery && typeof element.toArray === "function"){
+ StartAudioContext.on(element.toArray());
+ } else if (Element && element instanceof Element){
+ //if it's an element, create a TapListener
+ var tap = new TapListener(element, onTap);
+ StartAudioContext._tapListeners.push(tap);
+ }
+ return StartAudioContext;
+ };
+
+ /**
+ * Bind a callback to when the audio context is started.
+ * @param {Function} cb
+ * @return {StartAudioContext}
+ */
+ StartAudioContext.onStarted = function(cb){
+ //if it's already started, invoke the callback
+ if (StartAudioContext.isStarted()){
+ cb();
+ } else {
+ StartAudioContext._onStarted.push(cb);
+ }
+ return StartAudioContext;
+ };
+
+ /**
+ * returns true if the context is started
+ * @return {Boolean}
+ */
+ StartAudioContext.isStarted = function(){
+ return (StartAudioContext.context !== null && StartAudioContext.context.state === "running");
+ };
+
+ /**
+ * @class Listens for non-dragging tap ends on the given element
+ * @param {Element} element
+ * @internal
+ */
+ var TapListener = function(element){
+
+ this._dragged = false;
+
+ this._element = element;
+
+ this._bindedMove = this._moved.bind(this);
+ this._bindedEnd = this._ended.bind(this);
+
+ element.addEventListener("touchmove", this._bindedMove);
+ element.addEventListener("touchend", this._bindedEnd);
+ element.addEventListener("mouseup", this._bindedEnd);
+ };
+
+ /**
+ * drag move event
+ */
+ TapListener.prototype._moved = function(e){
+ this._dragged = true;
+ };
+
+ /**
+ * tap ended listener
+ */
+ TapListener.prototype._ended = function(e){
+ if (!this._dragged){
+ onTap();
+ }
+ this._dragged = false;
+ };
+
+ /**
+ * remove all the bound events
+ */
+ TapListener.prototype.dispose = function(){
+ this._element.removeEventListener("touchmove", this._bindedMove);
+ this._element.removeEventListener("touchend", this._bindedEnd);
+ this._element.removeEventListener("mouseup", this._bindedEnd);
+ this._bindedMove = null;
+ this._bindedEnd = null;
+ this._element = null;
+ };
+
+ /**
+ * Invoked the first time of the elements is tapped.
+ * Creates a silent oscillator when a non-dragging touchend
+ * event has been triggered.
+ */
+ function onTap(){
+ //start the audio context with a silent oscillator
+ if (StartAudioContext.context && !StartAudioContext.isStarted()){
+ var osc = StartAudioContext.context.createOscillator();
+ var silent = StartAudioContext.context.createGain();
+ silent.gain.value = 0;
+ osc.connect(silent);
+ silent.connect(StartAudioContext.context.destination);
+ var now = StartAudioContext.context.currentTime;
+ osc.start(now);
+ osc.stop(now+0.5);
+ }
+
+ //dispose all the tap listeners
+ if (StartAudioContext._tapListeners){
+ for (var i = 0; i < StartAudioContext._tapListeners.length; i++){
+ StartAudioContext._tapListeners[i].dispose();
+ }
+ StartAudioContext._tapListeners = null;
+ }
+ //the onstarted callbacks
+ if (StartAudioContext._onStarted){
+ for (var j = 0; j < StartAudioContext._onStarted.length; j++){
+ StartAudioContext._onStarted[j]();
+ }
+ StartAudioContext._onStarted = null;
+ }
+ }
+
+ return StartAudioContext;
+}));
+
+
diff --git a/client/lib/util.js b/client/lib/util.js
new file mode 100644
index 0000000..e8065d5
--- /dev/null
+++ b/client/lib/util.js
@@ -0,0 +1,63 @@
+import Tone from 'tone'
+import StartAudioContext from './startAudioContext'
+
+const isIphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))
+const isIpad = (navigator.userAgent.match(/iPad/i))
+const isAndroid = (navigator.userAgent.match(/Android/i))
+const isMobile = isIphone || isIpad || isAndroid
+const isDesktop = ! isMobile
+
+document.body.classList.add(isMobile ? 'mobile' : 'desktop')
+
+const browser = { isIphone, isIpad, isMobile, isDesktop }
+
+function clamp(n,a,b){ return n<a?a:n<b?n:b }
+function choice (a){ return a[ Math.floor(Math.random() * a.length) ] }
+function mod(n,m){ return n-(m * Math.floor(n/m)) }
+function firstTouch(f){ return e => f(e.touches[0]) }
+
+function requestAudioContext (fn) {
+ if (isMobile) {
+ const container = document.createElement('div')
+ const button = document.createElement('div')
+ button.innerHTML = 'Tap to start - please unmute your phone'
+ Object.assign(container.style, {
+ display: 'block',
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
+ zIndex: '10000',
+ top: '0px',
+ left: '0px',
+ backgroundColor: 'rgba(0, 0, 0, 0.8)',
+ })
+ Object.assign(button.style, {
+ display: 'block',
+ position: 'absolute',
+ left: '50%',
+ top: '50%',
+ padding: '20px',
+ backgroundColor: '#7F33ED',
+ color: 'white',
+ fontFamily: 'monospace',
+ borderRadius: '3px',
+ transform: 'translate3D(-50%,-50%,0)',
+ textAlign: 'center',
+ lineHeight: '1.5',
+ width: '150px',
+ })
+ container.appendChild(button)
+ document.body.appendChild(container)
+ StartAudioContext.setContext(Tone.context)
+ StartAudioContext.on(button)
+ StartAudioContext.onStarted(_ => {
+ container.remove()
+ fn()
+ })
+ } else {
+ fn()
+ }
+}
+
+export { choice, mod, clamp, browser, firstTouch, requestAudioContext }
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..65d1a24
--- /dev/null
+++ b/index.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<title>applause!</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
+<style>
+html,body {
+ width: 100%;
+ height: 100%;
+ margin: 0; padding: 0;
+ overflow: hidden;
+}
+body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+ color: white;
+ text-shadow: 0 0 1px #000;
+ transition: background-color 100ms;
+ user-select: none;
+}
+</style>
+</head>
+<body>
+</body>
+<script src='bundle.js'></script>
+</html>
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..460cbf0
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2579 @@
+{
+ "name": "applause",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "dependencies": {
+ "acorn": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz",
+ "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=",
+ "dev": true
+ },
+ "acorn-dynamic-import": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz",
+ "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=",
+ "dev": true,
+ "dependencies": {
+ "acorn": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+ "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=",
+ "dev": true
+ }
+ }
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
+ "dev": true
+ },
+ "ajv-keywords": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz",
+ "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=",
+ "dev": true
+ },
+ "align-text": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz",
+ "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=",
+ "dev": true
+ },
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz",
+ "integrity": "sha1-onTthawIhJtr14R8RYB0XcUa37E=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asn1.js": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz",
+ "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=",
+ "dev": true
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "dev": true
+ },
+ "async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz",
+ "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz",
+ "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=",
+ "dev": true
+ },
+ "babel-core": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.25.0.tgz",
+ "integrity": "sha1-fdQrBGPHQunVKW3rPsZ6kyLa1yk=",
+ "dev": true
+ },
+ "babel-generator": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.25.0.tgz",
+ "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=",
+ "dev": true
+ },
+ "babel-helper-builder-binary-assignment-operator-visitor": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+ "dev": true
+ },
+ "babel-helper-call-delegate": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+ "dev": true
+ },
+ "babel-helper-define-map": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz",
+ "integrity": "sha1-epdH8ljYlH0y1RX2qhx70CIEoIA=",
+ "dev": true
+ },
+ "babel-helper-explode-assignable-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+ "dev": true
+ },
+ "babel-helper-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+ "dev": true
+ },
+ "babel-helper-get-function-arity": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+ "dev": true
+ },
+ "babel-helper-hoist-variables": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+ "dev": true
+ },
+ "babel-helper-optimise-call-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+ "dev": true
+ },
+ "babel-helper-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz",
+ "integrity": "sha1-024i+rEAjXnYhkjjIRaGgShFbOg=",
+ "dev": true
+ },
+ "babel-helper-remap-async-to-generator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
+ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
+ "dev": true
+ },
+ "babel-helper-replace-supers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+ "dev": true
+ },
+ "babel-helpers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+ "dev": true
+ },
+ "babel-loader": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.0.tgz",
+ "integrity": "sha1-P78lgfCFd0vZZC3KmZDm1sFJEUQ=",
+ "dev": true
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true
+ },
+ "babel-plugin-check-es2015-constants": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+ "dev": true
+ },
+ "babel-plugin-syntax-async-functions": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+ "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
+ "dev": true
+ },
+ "babel-plugin-syntax-exponentiation-operator": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+ "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
+ "dev": true
+ },
+ "babel-plugin-syntax-trailing-function-commas": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
+ "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
+ "dev": true
+ },
+ "babel-plugin-transform-async-to-generator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
+ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-arrow-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-block-scoped-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-block-scoping": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz",
+ "integrity": "sha1-dsKV3DpHQbFmWt/TFnIV3P8ypXY=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-classes": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-computed-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-destructuring": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-duplicate-keys": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-for-of": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-amd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-commonjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz",
+ "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-systemjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-umd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-object-super": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-parameters": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-shorthand-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-spread": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-sticky-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-template-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-typeof-symbol": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-unicode-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+ "dev": true
+ },
+ "babel-plugin-transform-exponentiation-operator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+ "dev": true
+ },
+ "babel-plugin-transform-regenerator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz",
+ "integrity": "sha1-uNowWtQ8PJm0hI5P5AN7dw0jxBg=",
+ "dev": true
+ },
+ "babel-plugin-transform-strict-mode": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+ "dev": true
+ },
+ "babel-preset-env": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.5.2.tgz",
+ "integrity": "sha1-zUrpCm6Utwn5c3SzPl+LmDVWre8=",
+ "dev": true
+ },
+ "babel-preset-es2015": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+ "dev": true
+ },
+ "babel-register": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz",
+ "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=",
+ "dev": true
+ },
+ "babel-runtime": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz",
+ "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=",
+ "dev": true
+ },
+ "babel-template": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz",
+ "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=",
+ "dev": true
+ },
+ "babel-traverse": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz",
+ "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=",
+ "dev": true
+ },
+ "babel-types": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz",
+ "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=",
+ "dev": true
+ },
+ "babylon": {
+ "version": "6.17.4",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz",
+ "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "base64-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==",
+ "dev": true
+ },
+ "big.js": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
+ "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz",
+ "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=",
+ "dev": true
+ },
+ "bn.js": {
+ "version": "4.11.7",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz",
+ "integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+ "dev": true
+ },
+ "browserify-aes": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz",
+ "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=",
+ "dev": true
+ },
+ "browserify-cipher": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+ "dev": true
+ },
+ "browserify-des": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+ "dev": true
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "dev": true
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "dev": true
+ },
+ "browserify-zlib": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+ "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+ "dev": true
+ },
+ "browserslist": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.1.5.tgz",
+ "integrity": "sha1-6IJVDfPRzW1IHBo+ADjyuvE6RxE=",
+ "dev": true
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000694",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000694.tgz",
+ "integrity": "sha1-FJLat8EMYIydN6cj5uPnhz4M6U8=",
+ "dev": true
+ },
+ "center-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.3.tgz",
+ "integrity": "sha1-7qvxlEGc6QDaMBjCB9IS8qbfCgc=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dev": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "dev": true
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz",
+ "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=",
+ "dev": true
+ },
+ "core-js": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
+ "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "create-ecdh": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+ "dev": true
+ },
+ "create-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+ "dev": true
+ },
+ "create-hmac": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+ "dev": true
+ },
+ "crypto-browserify": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.0.tgz",
+ "integrity": "sha1-NlKgkGq5sqfgw85mpAjpV6JIVSI=",
+ "dev": true
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "dev": true
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+ "dev": true
+ },
+ "domain-browser": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
+ "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.14",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz",
+ "integrity": "sha1-ZK8Pnv08PGrNV9cfg7Scp+6cS0M=",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "dev": true
+ },
+ "enhanced-resolve": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz",
+ "integrity": "sha1-n0tib1dyRe3PSyrYPYbhf09CHew=",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz",
+ "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+ "dev": true
+ },
+ "evp_bytestokey": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz",
+ "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "dev": true
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+ "dev": true
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "dev": true
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz",
+ "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true,
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "bundled": true,
+ "dev": true
+ },
+ "boom": {
+ "version": "2.10.1",
+ "bundled": true,
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "dev": true
+ },
+ "buffer-shims": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "extend": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "bundled": true,
+ "dev": true
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "bundled": true,
+ "dev": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "bundled": true,
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.27.0",
+ "bundled": true,
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.15",
+ "bundled": true,
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "node-pre-gyp": {
+ "version": "0.6.36",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npmlog": {
+ "version": "4.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "bundled": true,
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "6.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.2.9",
+ "bundled": true,
+ "dev": true
+ },
+ "request": {
+ "version": "2.81.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "bundled": true,
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sshpk": {
+ "version": "1.13.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "bundled": true,
+ "dev": true
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
+ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
+ "dev": true
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "dev": true
+ },
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "hash-base": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+ "dev": true
+ },
+ "hash.js": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.1.tgz",
+ "integrity": "sha512-I2TYCUjYQMmqmRMCp6jKMC5bvdXxGIZ/heITRR/0F1u0OP920ImEj/cXt3WgcTKBnNYGn7enxUzdai3db829JA==",
+ "dev": true
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "dev": true
+ },
+ "home-or-tmp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
+ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz",
+ "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=",
+ "dev": true
+ },
+ "https-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz",
+ "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=",
+ "dev": true
+ },
+ "ieee754": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=",
+ "dev": true
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "interpret": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz",
+ "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=",
+ "dev": true
+ },
+ "invariant": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
+ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
+ "dev": true
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+ "dev": true
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true
+ },
+ "is-buffer": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
+ "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true
+ },
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+ "dev": true
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "dev": true
+ },
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+ "dev": true
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+ "dev": true
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz",
+ "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+ "dev": true
+ },
+ "json-loader": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.4.tgz",
+ "integrity": "sha1-i6oTZaYy9Yo8RtIBdfxgAsluN94=",
+ "dev": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true
+ },
+ "lazy-cache": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+ "dev": true
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true
+ },
+ "loader-runner": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
+ "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ },
+ "longest": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz",
+ "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=",
+ "dev": true
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true
+ },
+ "miller-rabin": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz",
+ "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=",
+ "dev": true
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
+ "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=",
+ "dev": true,
+ "optional": true
+ },
+ "node-libs-browser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.0.0.tgz",
+ "integrity": "sha1-o6WeyXAkmFtG6Vg3lkb5bEthZkY=",
+ "dev": true,
+ "dependencies": {
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz",
+ "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "dev": true
+ },
+ "os-browserify": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz",
+ "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "dev": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz",
+ "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=",
+ "dev": true
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true
+ },
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+ "dev": true
+ },
+ "parse-asn1": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+ "dev": true
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true
+ },
+ "pbkdf2": {
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz",
+ "integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+ "dev": true
+ },
+ "private": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz",
+ "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "prr": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz",
+ "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+ "dev": true
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "randomatic": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+ "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+ "dev": true,
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true
+ }
+ }
+ },
+ "randombytes": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
+ "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz",
+ "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+ "dev": true
+ },
+ "regenerate": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
+ "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+ "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.9.11",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz",
+ "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=",
+ "dev": true
+ },
+ "regex-cache": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
+ "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+ "dev": true
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz",
+ "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
+ "right-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "dev": true
+ },
+ "ripemd160": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+ "dev": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+ "dev": true
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.8",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz",
+ "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "source-list-map": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-1.1.2.tgz",
+ "integrity": "sha1-mIkBnRAkzOVc3AaUmDN+9hhqEaE=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.4.15",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz",
+ "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
+ "dev": true
+ },
+ "spdx-license-ids": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "dev": true
+ },
+ "stream-http": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz",
+ "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "tapable": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.6.tgz",
+ "integrity": "sha1-IGvo4YiGC1FEJTdebxrom/sB/Y0=",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.2.tgz",
+ "integrity": "sha1-q0iDz1l9zVCvIRNJoA+8pWrIa4Y=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true
+ },
+ "tone": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/tone/-/tone-0.10.0.tgz",
+ "integrity": "sha1-yFWKKUWeISQiKifr8Xu9vus259Y="
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "2.8.29",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+ "dev": true,
+ "dependencies": {
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dev": true
+ }
+ }
+ },
+ "uglify-to-browserify": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+ "dev": true,
+ "optional": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "dev": true,
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+ "dev": true
+ }
+ }
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "dev": true,
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+ "dev": true
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "dev": true
+ },
+ "watchpack": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.3.1.tgz",
+ "integrity": "sha1-fYaTkHsozmAT5/NhCqKhrPB9rYc=",
+ "dev": true
+ },
+ "webpack": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-2.6.1.tgz",
+ "integrity": "sha1-LgRX8KuxrF3zqxBsacZy8jZ4Xwc=",
+ "dev": true,
+ "dependencies": {
+ "loader-utils": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
+ "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true
+ }
+ }
+ },
+ "webpack-sources": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.2.3.tgz",
+ "integrity": "sha1-F8Yr+vE8cH+dAsR54Nzd6DgGl/s=",
+ "dev": true
+ },
+ "which-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+ "dev": true
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
+ "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
+ "dev": true,
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "dev": true
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+ "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+ "dev": true,
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..59fd466
--- /dev/null
+++ b/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "applause",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "UNLICENSED",
+ "devDependencies": {
+ "babel-core": "^6.24.1",
+ "babel-loader": "^7.0.0",
+ "babel-preset-env": "^1.4.0",
+ "babel-preset-es2015": "^6.24.1",
+ "webpack": "^2.4.1"
+ },
+ "dependencies": {
+ "tone": "^0.10.0"
+ }
+}
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..3b2bf92
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,24 @@
+var webpack = require('webpack');
+
+module.exports = {
+ entry: './client/index.js',
+ watch: true,
+ devtool: 'cheap-source-map',
+ output: {
+ filename: './bundle.js'
+ },
+ module: {
+ rules: [
+ {
+ test: /\.jsx?$/,
+ exclude: /(node_modules|bower_components)/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ presets: ['env']
+ }
+ }
+ }
+ ]
+ },
+}